(git:97501a3)
Loading...
Searching...
No Matches
xas_tdp_methods.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
8! **************************************************************************************************
9!> \brief Methods for X-Ray absorption spectroscopy (XAS) using TDDFPT
10!> \author AB (11.2017)
11! **************************************************************************************************
12
14 USE admm_types, ONLY: admm_type
19 USE basis_set_types, ONLY: &
23 USE bibliography, ONLY: bussy2021a,&
24 cite_reference
25 USE cell_types, ONLY: cell_type,&
26 pbc
29 USE cp_dbcsr_api, ONLY: &
32 dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, &
33 dbcsr_type_symmetric
38 USE cp_files, ONLY: close_file,&
41 USE cp_fm_diag, ONLY: cp_fm_geeig,&
47 USE cp_fm_types, ONLY: &
55 USE cp_output_handling, ONLY: cp_p_file,&
61 USE input_constants, ONLY: &
75 USE kinds, ONLY: default_path_length,&
77 dp
79 USE machine, ONLY: m_flush
80 USE mathlib, ONLY: get_diag
82 USE message_passing, ONLY: mp_comm_type,&
85 USE parallel_rng_types, ONLY: uniform,&
89 USE periodic_table, ONLY: ptable
90 USE physcon, ONLY: a_fine,&
91 angstrom,&
92 evolt
96 USE qs_kind_types, ONLY: get_qs_kind,&
98 USE qs_loc_main, ONLY: qs_loc_driver
101 USE qs_loc_types, ONLY: get_qs_loc_env,&
110 USE qs_mo_io, ONLY: write_mo_set_low
112 USE qs_mo_types, ONLY: allocate_mo_set,&
115 get_mo_set,&
118 USE qs_operators_ao, ONLY: p_xyz_ao,&
121 USE qs_rho_types, ONLY: qs_rho_get,&
123 USE qs_scf_types, ONLY: ot_method_nr
124 USE rixs_types, ONLY: rixs_env_type
125 USE util, ONLY: get_limit,&
126 locate,&
132 USE xas_tdp_correction, ONLY: gw2x_shift,&
138 USE xas_tdp_types, ONLY: &
143 USE xas_tdp_utils, ONLY: include_os_soc,&
147 USE xc_write_output, ONLY: xc_write
148#include "./base/base_uses.f90"
149
150 IMPLICIT NONE
151 PRIVATE
152
153 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'xas_tdp_methods'
154
155 PUBLIC :: xas_tdp, xas_tdp_init
156
157CONTAINS
158
159! **************************************************************************************************
160!> \brief Driver for XAS TDDFT calculations.
161!> \param qs_env the inherited qs_environment
162!> \param rixs_env ...
163!> \author AB
164!> \note Empty for now...
165! **************************************************************************************************
166 SUBROUTINE xas_tdp(qs_env, rixs_env)
167
168 TYPE(qs_environment_type), POINTER :: qs_env
169 TYPE(rixs_env_type), OPTIONAL, POINTER :: rixs_env
170
171 CHARACTER(len=*), PARAMETER :: routinen = 'xas_tdp'
172
173 CHARACTER(default_string_length) :: rst_filename
174 INTEGER :: handle, n_rep, output_unit
175 LOGICAL :: do_restart, do_rixs
176 TYPE(section_vals_type), POINTER :: xas_tdp_section
177
178 CALL timeset(routinen, handle)
179
180! Logger initialization and XAS TDP banner printing
181 NULLIFY (xas_tdp_section)
182
183 ! check if subroutine is called as part of rixs calculation
184 CALL get_qs_env(qs_env, do_rixs=do_rixs)
185 IF (do_rixs) THEN
186 xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%RIXS%XAS_TDP")
187 ELSE
188 xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "DFT%XAS_TDP")
189 END IF
190 output_unit = cp_logger_get_default_io_unit()
191
192 IF (output_unit > 0) THEN
193 WRITE (unit=output_unit, fmt="(/,T3,A,/,T3,A,/,T3,A,/,T3,A,/)") &
194 "!===========================================================================!", &
195 "! XAS TDP !", &
196 "! Starting TDDFPT driven X-rays absorption spectroscopy calculations !", &
197 "!===========================================================================!"
198 END IF
199
200 CALL cite_reference(bussy2021a)
201
202! Check whether this is a restart calculation, i.e. is a restart file is provided
203 CALL section_vals_val_get(xas_tdp_section, "RESTART_FROM_FILE", n_rep_val=n_rep)
204
205 IF (n_rep < 1) THEN
206 do_restart = .false.
207 ELSE
208 CALL section_vals_val_get(xas_tdp_section, "RESTART_FROM_FILE", c_val=rst_filename)
209 do_restart = .true.
210 END IF
211
212! Restart the calculation if needed
213 IF (do_restart) THEN
214
215 IF (output_unit > 0) THEN
216 WRITE (unit=output_unit, fmt="(/,T3,A)") &
217 "# This is a RESTART calculation for PDOS and/or CUBE printing"
218 END IF
219
220 CALL restart_calculation(rst_filename, xas_tdp_section, qs_env)
221
222! or run the core XAS_TDP routine if not
223 ELSE
224 IF (PRESENT(rixs_env)) THEN
225 CALL xas_tdp_core(xas_tdp_section, qs_env, rixs_env)
226 ELSE
227 CALL xas_tdp_core(xas_tdp_section, qs_env)
228 END IF
229 END IF
230
231 IF (output_unit > 0) THEN
232 WRITE (unit=output_unit, fmt="(/,T3,A,/,T3,A,/,T3,A,/)") &
233 "!===========================================================================!", &
234 "! End of TDDFPT driven X-rays absorption spectroscopy calculations !", &
235 "!===========================================================================!"
236 END IF
237
238 CALL timestop(handle)
239
240 END SUBROUTINE xas_tdp
241
242! **************************************************************************************************
243!> \brief The core workflow of the XAS_TDP method
244!> \param xas_tdp_section the input values for XAS_TDP
245!> \param qs_env ...
246!> \param rixs_env ...
247! **************************************************************************************************
248 SUBROUTINE xas_tdp_core(xas_tdp_section, qs_env, rixs_env)
249
250 TYPE(section_vals_type), POINTER :: xas_tdp_section
251 TYPE(qs_environment_type), POINTER :: qs_env
252 TYPE(rixs_env_type), OPTIONAL, POINTER :: rixs_env
253
254 CHARACTER(LEN=default_string_length) :: kind_name
255 INTEGER :: batch_size, bo(2), current_state_index, iat, iatom, ibatch, ikind, ispin, istate, &
256 nbatch, nex_atom, output_unit, tmp_index
257 INTEGER, ALLOCATABLE, DIMENSION(:) :: batch_atoms, ex_atoms_of_kind
258 INTEGER, DIMENSION(:), POINTER :: atoms_of_kind
259 LOGICAL :: do_os, do_rixs, end_of_batch, unique
260 TYPE(admm_type), POINTER :: admm_env
261 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
262 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
263 TYPE(dft_control_type), POINTER :: dft_control
264 TYPE(donor_state_type), POINTER :: current_state
265 TYPE(gto_basis_set_type), POINTER :: tmp_basis
266 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
267 TYPE(xas_atom_env_type), POINTER :: xas_atom_env
268 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
269 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
270
271 NULLIFY (xas_tdp_env, xas_tdp_control, atomic_kind_set, atoms_of_kind, current_state)
272 NULLIFY (xas_atom_env, dft_control, matrix_ks, admm_env, qs_kind_set, tmp_basis)
273
274! Initialization
275 output_unit = cp_logger_get_default_io_unit()
276
277 IF (output_unit > 0) THEN
278 WRITE (unit=output_unit, fmt="(/,T3,A)") &
279 "# Create and initialize the XAS_TDP environment"
280 END IF
281 CALL get_qs_env(qs_env, dft_control=dft_control, do_rixs=do_rixs)
282 IF (PRESENT(rixs_env)) THEN
283 CALL xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env, rixs_env)
284 ELSE
285 CALL xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env)
286 END IF
287 CALL print_info(output_unit, xas_tdp_control, qs_env)
288
289 IF (output_unit > 0) THEN
290 IF (xas_tdp_control%check_only) THEN
291 cpwarn("This is a CHECK_ONLY run for donor MOs verification")
292 END IF
293 END IF
294
295! Localization of the core orbitals if requested (used for better identification of donor states)
296 IF (xas_tdp_control%do_loc) THEN
297 IF (output_unit > 0) THEN
298 WRITE (unit=output_unit, fmt="(/,T3,A,/)") &
299 "# Localizing core orbitals for better identification"
300 END IF
301! closed shell or ROKS => myspin=1
302 IF (xas_tdp_control%do_uks) THEN
303 DO ispin = 1, dft_control%nspins
304 CALL qs_loc_driver(qs_env, xas_tdp_env%qs_loc_env, &
305 xas_tdp_control%print_loc_subsection, myspin=ispin)
306 END DO
307 ELSE
308 CALL qs_loc_driver(qs_env, xas_tdp_env%qs_loc_env, &
309 xas_tdp_control%print_loc_subsection, myspin=1)
310 END IF
311 END IF
312
313! Find the MO centers
314 CALL find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
315
316! Assign lowest energy orbitals to excited atoms
317 CALL assign_mos_to_ex_atoms(xas_tdp_env, xas_tdp_control, qs_env)
318
319! Once assigned, diagonalize the MOs wrt the KS matrix in the subspace associated to each atom
320 IF (xas_tdp_control%do_loc) THEN
321 IF (output_unit > 0) THEN
322 WRITE (unit=output_unit, fmt="(/,T3,A,/,T5,A)") &
323 "# Diagonalize localized MOs wrt the KS matrix in the subspace of each excited", &
324 "atom for better donor state identification."
325 END IF
326 CALL diagonalize_assigned_mo_subset(xas_tdp_env, xas_tdp_control, qs_env)
327 ! update MO centers
328 CALL find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
329 END IF
330
331 IF (output_unit > 0) THEN
332 WRITE (unit=output_unit, fmt="(/,T3,A,I4,A,/)") &
333 "# Assign the relevant subset of the ", xas_tdp_control%n_search, &
334 " lowest energy MOs to excited atoms"
335 END IF
336 CALL write_mos_to_ex_atoms_association(xas_tdp_env, xas_tdp_control, qs_env)
337
338! If CHECK_ONLY run, check the donor MOs
339 IF (xas_tdp_control%check_only) CALL print_checks(xas_tdp_env, xas_tdp_control, qs_env)
340
341! If not simply exact exchange, setup a xas_atom_env and compute the xc integrals on the atomic grids
342! Also needed if SOC is included or XPS GW2X(). Done before looping on atoms as it's all done at once
343 IF ((xas_tdp_control%do_xc .OR. xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) &
344 .AND. .NOT. xas_tdp_control%check_only) THEN
345
346 IF (output_unit > 0 .AND. xas_tdp_control%do_xc) THEN
347 WRITE (unit=output_unit, fmt="(/,T3,A,I4,A)") &
348 "# Integrating the xc kernel on the atomic grids ..."
349 CALL m_flush(output_unit)
350 END IF
351
352 CALL xas_atom_env_create(xas_atom_env)
353 CALL init_xas_atom_env(xas_atom_env, xas_tdp_env, xas_tdp_control, qs_env)
354 do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
355
356 IF (xas_tdp_control%do_xc .AND. (.NOT. xas_tdp_control%xps_only)) THEN
357 CALL integrate_fxc_atoms(xas_tdp_env%ri_fxc, xas_atom_env, xas_tdp_control, qs_env)
358 END IF
359
360 IF (xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) THEN
361 CALL integrate_soc_atoms(xas_tdp_env%orb_soc, xas_atom_env=xas_atom_env, qs_env=qs_env)
362 END IF
363
364 CALL xas_atom_env_release(xas_atom_env)
365 END IF
366
367! Compute the 3-center Coulomb integrals for the whole system
368 IF ((.NOT. (xas_tdp_control%check_only .OR. xas_tdp_control%xps_only)) .AND. &
369 (xas_tdp_control%do_xc .OR. xas_tdp_control%do_coulomb)) THEN
370 IF (output_unit > 0) THEN
371 WRITE (unit=output_unit, fmt="(/,T3,A,I4,A)") &
372 "# Computing the RI 3-center Coulomb integrals ..."
373 CALL m_flush(output_unit)
374 END IF
375 CALL compute_ri_3c_coulomb(xas_tdp_env, qs_env)
376
377 END IF
378
379! Loop over donor states for calculation
380 CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
381 current_state_index = 1
382
383! Loop over atomic kinds
384 DO ikind = 1, SIZE(atomic_kind_set)
385
386 IF (xas_tdp_control%check_only) EXIT
387 IF (.NOT. any(xas_tdp_env%ex_kind_indices == ikind)) cycle
388
389 CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), name=kind_name, &
390 atom_list=atoms_of_kind)
391
392 ! compute the RI coulomb2 inverse for this kind, and RI exchange2 if needed
393 CALL compute_ri_coulomb2_int(ikind, xas_tdp_env, xas_tdp_control, qs_env)
394 IF (xas_tdp_control%do_hfx) THEN
395 CALL compute_ri_exchange2_int(ikind, xas_tdp_env, xas_tdp_control, qs_env)
396 END IF
397
398 !Randomly distribute excited atoms of current kinds into batches for optimal load balance
399 !of RI 3c exchange integrals. Take batch sizes of 2 to avoid taxing memory too much, while
400 !greatly improving load balance
401 batch_size = 2
402 CALL get_ri_3c_batches(ex_atoms_of_kind, nbatch, batch_size, atoms_of_kind, xas_tdp_env)
403 nex_atom = SIZE(ex_atoms_of_kind)
404
405 !Loop over batches
406 DO ibatch = 1, nbatch
407
408 bo = get_limit(nex_atom, nbatch, ibatch - 1)
409 batch_size = bo(2) - bo(1) + 1
410 ALLOCATE (batch_atoms(batch_size))
411 iatom = 0
412 DO iat = bo(1), bo(2)
413 iatom = iatom + 1
414 batch_atoms(iatom) = ex_atoms_of_kind(iat)
415 END DO
416 CALL sort_unique(batch_atoms, unique)
417
418 !compute RI 3c exchange integrals on batch, if so required
419 IF (xas_tdp_control%do_hfx) THEN
420 IF (output_unit > 0) THEN
421 WRITE (unit=output_unit, fmt="(/,T3,A,I4,A,I4,A,I1,A,A)") &
422 "# Computing the RI 3-center Exchange integrals for batch ", ibatch, "(/", nbatch, ") of ", &
423 batch_size, " atoms of kind: ", trim(kind_name)
424 CALL m_flush(output_unit)
425 END IF
426 CALL compute_ri_3c_exchange(batch_atoms, xas_tdp_env, xas_tdp_control, qs_env)
427 END IF
428
429! Loop over atoms of batch
430 DO iat = 1, batch_size
431 iatom = batch_atoms(iat)
432
433 tmp_index = locate(xas_tdp_env%ex_atom_indices, iatom)
434
435 !if dipole in length rep, compute the dipole in the AO basis for this atom
436 !if quadrupole is required, compute it there too (in length rep)
437 IF (xas_tdp_control%dipole_form == xas_dip_len .OR. xas_tdp_control%do_quad) THEN
438 CALL compute_lenrep_multipole(iatom, xas_tdp_env, xas_tdp_control, qs_env)
439 END IF
440
441! Loop over states of excited atom of kind
442 DO istate = 1, SIZE(xas_tdp_env%state_types, 1)
443
444 IF (xas_tdp_env%state_types(istate, tmp_index) == xas_not_excited) cycle
445
446 current_state => xas_tdp_env%donor_states(current_state_index)
447 CALL set_donor_state(current_state, at_index=iatom, &
448 at_symbol=kind_name, kind_index=ikind, &
449 state_type=xas_tdp_env%state_types(istate, tmp_index))
450
451! Initial write for the donor state of interest
452 IF (output_unit > 0) THEN
453 WRITE (unit=output_unit, fmt="(/,T3,A,A2,A,I4,A,A,/)") &
454 "# Start of calculations for donor state of type ", &
455 xas_tdp_env%state_type_char(current_state%state_type), " for atom", &
456 current_state%at_index, " of kind ", trim(current_state%at_symbol)
457 CALL m_flush(output_unit)
458 END IF
459
460! Assign best fitting MO(s) to current core donnor state
461 CALL assign_mos_to_donor_state(current_state, xas_tdp_env, xas_tdp_control, qs_env)
462
463! Perform MO restricted Mulliken pop analysis for verification
464 CALL perform_mulliken_on_donor_state(current_state, qs_env)
465
466! GW2X correction
467 IF (xas_tdp_control%do_gw2x) THEN
468 CALL gw2x_shift(current_state, xas_tdp_env, xas_tdp_control, qs_env)
469 END IF
470
471! Do main XAS calculations here
472 IF (.NOT. xas_tdp_control%xps_only) THEN
473 CALL setup_xas_tdp_prob(current_state, qs_env, xas_tdp_env, xas_tdp_control)
474
475 IF (xas_tdp_control%do_spin_cons) THEN
476 CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
477 ex_type=tddfpt_spin_cons)
478 CALL compute_dipole_fosc(current_state, xas_tdp_control, xas_tdp_env)
479 IF (xas_tdp_control%do_quad) CALL compute_quadrupole_fosc(current_state, &
480 xas_tdp_control, xas_tdp_env)
481 CALL xas_tdp_post(tddfpt_spin_cons, current_state, xas_tdp_env, &
482 xas_tdp_section, qs_env)
483 CALL write_donor_state_restart(tddfpt_spin_cons, current_state, xas_tdp_section, qs_env)
484 END IF
485
486 IF (xas_tdp_control%do_spin_flip) THEN
487 CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
488 ex_type=tddfpt_spin_flip)
489 !no dipole in spin-flip (spin-forbidden)
490 CALL xas_tdp_post(tddfpt_spin_flip, current_state, xas_tdp_env, &
491 xas_tdp_section, qs_env)
492 CALL write_donor_state_restart(tddfpt_spin_flip, current_state, xas_tdp_section, qs_env)
493 END IF
494
495 IF (xas_tdp_control%do_singlet) THEN
496 CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
497 ex_type=tddfpt_singlet)
498 CALL compute_dipole_fosc(current_state, xas_tdp_control, xas_tdp_env)
499 IF (xas_tdp_control%do_quad) CALL compute_quadrupole_fosc(current_state, &
500 xas_tdp_control, xas_tdp_env)
501 CALL xas_tdp_post(tddfpt_singlet, current_state, xas_tdp_env, &
502 xas_tdp_section, qs_env)
503 CALL write_donor_state_restart(tddfpt_singlet, current_state, xas_tdp_section, qs_env)
504 END IF
505
506 IF (xas_tdp_control%do_triplet) THEN
507 CALL solve_xas_tdp_prob(current_state, xas_tdp_control, xas_tdp_env, qs_env, &
508 ex_type=tddfpt_triplet)
509 !no dipole for triplets by construction
510 CALL xas_tdp_post(tddfpt_triplet, current_state, xas_tdp_env, &
511 xas_tdp_section, qs_env)
512 CALL write_donor_state_restart(tddfpt_triplet, current_state, xas_tdp_section, qs_env)
513 END IF
514
515! Include the SOC if required, only for 2p donor stataes
516 IF (xas_tdp_control%do_soc .AND. current_state%state_type == xas_2p_type) THEN
517 IF (xas_tdp_control%do_singlet .AND. xas_tdp_control%do_triplet) THEN
518 CALL include_rcs_soc(current_state, xas_tdp_env, xas_tdp_control, qs_env)
519 END IF
520 IF (xas_tdp_control%do_spin_cons .AND. xas_tdp_control%do_spin_flip) THEN
521 CALL include_os_soc(current_state, xas_tdp_env, xas_tdp_control, qs_env)
522 END IF
523 END IF
524
525! Print the requested properties
526 CALL print_xas_tdp_to_file(current_state, xas_tdp_env, xas_tdp_control, xas_tdp_section)
527 END IF !xps_only
528 IF (xas_tdp_control%do_gw2x) CALL print_xps(current_state, xas_tdp_env, xas_tdp_control, qs_env)
529
530! Free some unneeded attributes of current_state
531 IF (.NOT. do_rixs) CALL free_ds_memory(current_state) ! donor-state will be cleaned in rixs
532 current_state_index = current_state_index + 1
533 NULLIFY (current_state)
534
535 END DO ! state type
536
537 end_of_batch = .false.
538 IF (iat == batch_size) end_of_batch = .true.
539 CALL free_exat_memory(xas_tdp_env, iatom, end_of_batch)
540 END DO ! atom of batch
541 DEALLOCATE (batch_atoms)
542 END DO !ibatch
543 DEALLOCATE (ex_atoms_of_kind)
544 END DO ! kind
545
546! Return to ususal KS matrix
547 IF (dft_control%do_admm) THEN
548 CALL get_qs_env(qs_env, matrix_ks=matrix_ks, admm_env=admm_env)
549 DO ispin = 1, dft_control%nspins
550 CALL admm_uncorrect_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
551 END DO
552 END IF
553
554! Return to initial basis set radii
555 IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
556 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
557 DO ikind = 1, SIZE(atomic_kind_set)
558 CALL get_qs_kind(qs_kind_set(ikind), basis_set=tmp_basis, basis_type="ORB")
559 CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=dft_control%qs_control%eps_pgf_orb)
560 END DO
561 END IF
562
563! Clean-up
564 IF (.NOT. do_rixs) CALL xas_tdp_env_release(xas_tdp_env) ! is released at the end of rixs
565 CALL xas_tdp_control_release(xas_tdp_control)
566
567 END SUBROUTINE xas_tdp_core
568
569! **************************************************************************************************
570!> \brief Overall control and environment types initialization
571!> \param xas_tdp_env the environment type to initialize
572!> \param xas_tdp_control the control type to initialize
573!> \param qs_env the inherited qs environement type
574!> \param rixs_env ...
575! **************************************************************************************************
576 SUBROUTINE xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env, rixs_env)
577
578 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
579 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
580 TYPE(qs_environment_type), POINTER :: qs_env
581 TYPE(rixs_env_type), OPTIONAL, POINTER :: rixs_env
582
583 CHARACTER(LEN=default_string_length) :: kind_name
584 INTEGER :: at_ind, i, ispin, j, k, kind_ind, &
585 n_donor_states, n_kinds, nao, &
586 nat_of_kind, natom, nex_atoms, &
587 nex_kinds, nmatch, nspins
588 INTEGER, DIMENSION(2) :: homo, n_mo, n_moloc
589 INTEGER, DIMENSION(:), POINTER :: ind_of_kind
590 LOGICAL :: do_os, do_rixs, do_uks, unique
591 REAL(dp) :: fact
592 REAL(dp), DIMENSION(:), POINTER :: mo_evals
593 TYPE(admm_type), POINTER :: admm_env
594 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: at_kind_set
595 TYPE(cell_type), POINTER :: cell
596 TYPE(cp_fm_type), POINTER :: mo_coeff
597 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s, rho_ao
598 TYPE(dbcsr_type) :: matrix_tmp
599 TYPE(dft_control_type), POINTER :: dft_control
600 TYPE(gto_basis_set_type), POINTER :: tmp_basis
601 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
602 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
603 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
604 TYPE(qs_loc_env_type), POINTER :: qs_loc_env
605 TYPE(qs_rho_type), POINTER :: rho
606 TYPE(section_type), POINTER :: dummy_section
607 TYPE(section_vals_type), POINTER :: loc_section, xas_tdp_section
608
609 NULLIFY (xas_tdp_section, at_kind_set, ind_of_kind, dft_control, qs_kind_set, tmp_basis)
610 NULLIFY (qs_loc_env, loc_section, mos, particle_set, rho, rho_ao, mo_evals, cell)
611 NULLIFY (mo_coeff, matrix_ks, admm_env, dummy_section)
612
613! XAS TDP control type initialization
614 CALL get_qs_env(qs_env, dft_control=dft_control, do_rixs=do_rixs)
615
616 IF (do_rixs) THEN
617 xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%RIXS%XAS_TDP")
618 ELSE
619 xas_tdp_section => section_vals_get_subs_vals(qs_env%input, "DFT%XAS_TDP")
620 END IF
621
622 CALL xas_tdp_control_create(xas_tdp_control)
623 CALL read_xas_tdp_control(xas_tdp_control, xas_tdp_section)
624
625! Check the qs_env for a LSD/ROKS calculation
626 IF (dft_control%uks) xas_tdp_control%do_uks = .true.
627 IF (dft_control%roks) xas_tdp_control%do_roks = .true.
628 do_uks = xas_tdp_control%do_uks
629 do_os = do_uks .OR. xas_tdp_control%do_roks
630
631! XAS TDP environment type initialization
632 IF (PRESENT(rixs_env)) THEN
633 xas_tdp_env => rixs_env%core_state
634 ELSE
635 CALL xas_tdp_env_create(xas_tdp_env)
636 END IF
637
638! Retrieving the excited atoms indices and correspondig state types
639 IF (xas_tdp_control%define_excited == xas_tdp_by_index) THEN
640
641! simply copy indices from xas_tdp_control
642 nex_atoms = SIZE(xas_tdp_control%list_ex_atoms)
643 CALL set_xas_tdp_env(xas_tdp_env, nex_atoms=nex_atoms)
644 ALLOCATE (xas_tdp_env%ex_atom_indices(nex_atoms))
645 ALLOCATE (xas_tdp_env%state_types(SIZE(xas_tdp_control%state_types, 1), nex_atoms))
646 xas_tdp_env%ex_atom_indices = xas_tdp_control%list_ex_atoms
647 xas_tdp_env%state_types = xas_tdp_control%state_types
648
649! Test that these indices are within the range of available atoms
650 CALL get_qs_env(qs_env=qs_env, natom=natom)
651 IF (any(xas_tdp_env%ex_atom_indices > natom)) THEN
652 cpabort("Invalid index for the ATOM_LIST keyword.")
653 END IF
654
655! Check atom kinds and fill corresponding array
656 ALLOCATE (xas_tdp_env%ex_kind_indices(nex_atoms))
657 xas_tdp_env%ex_kind_indices = 0
658 k = 0
659 CALL get_qs_env(qs_env, particle_set=particle_set)
660 DO i = 1, nex_atoms
661 at_ind = xas_tdp_env%ex_atom_indices(i)
662 CALL get_atomic_kind(particle_set(at_ind)%atomic_kind, kind_number=j)
663 IF (all(abs(xas_tdp_env%ex_kind_indices - j) .NE. 0)) THEN
664 k = k + 1
665 xas_tdp_env%ex_kind_indices(k) = j
666 END IF
667 END DO
668 nex_kinds = k
669 CALL set_xas_tdp_env(xas_tdp_env, nex_kinds=nex_kinds)
670 CALL reallocate(xas_tdp_env%ex_kind_indices, 1, nex_kinds)
671
672 ELSE IF (xas_tdp_control%define_excited == xas_tdp_by_kind) THEN
673
674! need to find out which atom of which kind is excited
675 CALL get_qs_env(qs_env=qs_env, atomic_kind_set=at_kind_set)
676 n_kinds = SIZE(at_kind_set)
677 nex_atoms = 0
678
679 nex_kinds = SIZE(xas_tdp_control%list_ex_kinds)
680 ALLOCATE (xas_tdp_env%ex_kind_indices(nex_kinds))
681 k = 0
682
683 DO i = 1, n_kinds
684 CALL get_atomic_kind(atomic_kind=at_kind_set(i), name=kind_name, &
685 natom=nat_of_kind, kind_number=kind_ind)
686 IF (any(xas_tdp_control%list_ex_kinds == kind_name)) THEN
687 nex_atoms = nex_atoms + nat_of_kind
688 k = k + 1
689 xas_tdp_env%ex_kind_indices(k) = kind_ind
690 END IF
691 END DO
692
693 ALLOCATE (xas_tdp_env%ex_atom_indices(nex_atoms))
694 ALLOCATE (xas_tdp_env%state_types(SIZE(xas_tdp_control%state_types, 1), nex_atoms))
695 nex_atoms = 0
696 nmatch = 0
697
698 DO i = 1, n_kinds
699 CALL get_atomic_kind(atomic_kind=at_kind_set(i), name=kind_name, &
700 natom=nat_of_kind, atom_list=ind_of_kind)
701 DO j = 1, nex_kinds
702 IF (xas_tdp_control%list_ex_kinds(j) == kind_name) THEN
703 xas_tdp_env%ex_atom_indices(nex_atoms + 1:nex_atoms + nat_of_kind) = ind_of_kind
704 DO k = 1, SIZE(xas_tdp_control%state_types, 1)
705 xas_tdp_env%state_types(k, nex_atoms + 1:nex_atoms + nat_of_kind) = &
706 xas_tdp_control%state_types(k, j)
707 END DO
708 nex_atoms = nex_atoms + nat_of_kind
709 nmatch = nmatch + 1
710 END IF
711 END DO
712 END DO
713
714 CALL set_xas_tdp_env(xas_tdp_env, nex_atoms=nex_atoms, nex_kinds=nex_kinds)
715
716! Verifying that the input was valid
717 IF (nmatch .NE. SIZE(xas_tdp_control%list_ex_kinds)) THEN
718 cpabort("Invalid kind(s) for the KIND_LIST keyword.")
719 END IF
720
721 END IF
722
723! Sort the excited atoms indices (for convinience and use of locate function)
724 CALL sort_unique(xas_tdp_env%ex_atom_indices, unique)
725 IF (.NOT. unique) THEN
726 cpabort("Excited atoms not uniquely defined.")
727 END IF
728
729! Check for periodicity
730 CALL get_qs_env(qs_env, cell=cell)
731 IF (all(cell%perd == 0)) THEN
732 xas_tdp_control%is_periodic = .false.
733 ELSE IF (all(cell%perd == 1)) THEN
734 xas_tdp_control%is_periodic = .true.
735 ELSE
736 cpabort("XAS TDP only implemented for full PBCs or non-PBCs")
737 END IF
738
739! Allocating memory for the array of donor states
740 n_donor_states = count(xas_tdp_env%state_types /= xas_not_excited)
741 ALLOCATE (xas_tdp_env%donor_states(n_donor_states))
742 DO i = 1, n_donor_states
743 CALL donor_state_create(xas_tdp_env%donor_states(i))
744 END DO
745
746! In case of ADMM, for the whole duration of the XAS_TDP, we need the total KS matrix
747 IF (dft_control%do_admm) THEN
748 CALL get_qs_env(qs_env, admm_env=admm_env, matrix_ks=matrix_ks)
749
750 DO ispin = 1, dft_control%nspins
751 CALL admm_correct_for_eigenvalues(ispin, admm_env, matrix_ks(ispin)%matrix)
752 END DO
753 END IF
754
755! In case of externally imposed EPS_PGF_XAS, need to update ORB and RI_XAS interaction radii
756 IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
757 CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set)
758
759 DO i = 1, SIZE(qs_kind_set)
760 CALL get_qs_kind(qs_kind_set(i), basis_set=tmp_basis, basis_type="ORB")
761 CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=xas_tdp_control%eps_pgf)
762 CALL get_qs_kind(qs_kind_set(i), basis_set=tmp_basis, basis_type="RI_XAS")
763 CALL init_interaction_radii_orb_basis(tmp_basis, eps_pgf_orb=xas_tdp_control%eps_pgf)
764 END DO
765 END IF
766
767! In case of ground state OT optimization, compute the MO eigenvalues and get canonical MOs
768 IF (qs_env%scf_env%method == ot_method_nr) THEN
769
770 CALL get_qs_env(qs_env, mos=mos, matrix_ks=matrix_ks)
771 nspins = 1; IF (do_uks) nspins = 2
772
773 DO ispin = 1, nspins
774 CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, eigenvalues=mo_evals)
775 CALL calculate_subspace_eigenvalues(mo_coeff, matrix_ks(ispin)%matrix, evals_arg=mo_evals)
776 END DO
777 END IF
778
779! Initializing the qs_loc_env from the LOCALIZE subsection of XAS_TDP (largely inpired by MI's XAS)
780! We create the LOCALIZE subsection here, since it is completely overwritten anyways
781 CALL create_localize_section(dummy_section)
782 CALL section_vals_create(xas_tdp_control%loc_subsection, dummy_section)
783 CALL section_vals_val_set(xas_tdp_control%loc_subsection, "_SECTION_PARAMETERS_", &
784 l_val=xas_tdp_control%do_loc)
785 CALL section_release(dummy_section)
786 xas_tdp_control%print_loc_subsection => section_vals_get_subs_vals( &
787 xas_tdp_control%loc_subsection, "PRINT")
788
789 ALLOCATE (xas_tdp_env%qs_loc_env)
790 CALL qs_loc_env_create(xas_tdp_env%qs_loc_env)
791 qs_loc_env => xas_tdp_env%qs_loc_env
792 loc_section => xas_tdp_control%loc_subsection
793! getting the number of MOs
794 CALL get_qs_env(qs_env, mos=mos)
795 CALL get_mo_set(mos(1), nmo=n_mo(1), homo=homo(1), nao=nao)
796 n_mo(2) = n_mo(1)
797 homo(2) = homo(1)
798 nspins = 1
799 IF (do_os) CALL get_mo_set(mos(2), nmo=n_mo(2), homo=homo(2))
800 IF (do_uks) nspins = 2 !in roks, same MOs for both spins
801
802 ! by default, all (doubly occupied) homo are localized
803 IF (xas_tdp_control%n_search < 0 .OR. xas_tdp_control%n_search > minval(homo)) &
804 xas_tdp_control%n_search = minval(homo)
805 CALL qs_loc_control_init(qs_loc_env, loc_section, do_homo=.true., do_xas=.true., &
806 nloc_xas=xas_tdp_control%n_search, spin_xas=1)
807
808 ! do_xas argument above only prepares spin-alpha localization
809 IF (do_uks) THEN
810 qs_loc_env%localized_wfn_control%nloc_states(2) = xas_tdp_control%n_search
811 qs_loc_env%localized_wfn_control%lu_bound_states(1, 2) = 1
812 qs_loc_env%localized_wfn_control%lu_bound_states(2, 2) = xas_tdp_control%n_search
813 END IF
814
815! final qs_loc_env initialization. Impose Berry operator
816 qs_loc_env%localized_wfn_control%operator_type = op_loc_berry
817 qs_loc_env%localized_wfn_control%max_iter = 25000
818 IF (.NOT. xas_tdp_control%do_loc) THEN
819 qs_loc_env%localized_wfn_control%localization_method = do_loc_none
820 ELSE
821 n_moloc = qs_loc_env%localized_wfn_control%nloc_states
822 CALL set_loc_centers(qs_loc_env%localized_wfn_control, n_moloc, nspins)
823 IF (do_uks) THEN
824 CALL qs_loc_env_init(qs_loc_env, qs_loc_env%localized_wfn_control, &
825 qs_env, do_localize=.true.)
826 ELSE
827 CALL qs_loc_env_init(qs_loc_env, qs_loc_env%localized_wfn_control, &
828 qs_env, do_localize=.true., myspin=1)
829 END IF
830 END IF
831
832! Allocating memory for the array of excited atoms MOs. Worst case senario, all searched MOs are
833! associated to the same atom
834 ALLOCATE (xas_tdp_env%mos_of_ex_atoms(xas_tdp_control%n_search, nex_atoms, nspins))
835
836! Compute the projector on the unoccupied, unperturbed ground state: Q = 1 - SP, sor each spin
837 IF (do_os) nspins = 2
838 CALL get_qs_env(qs_env, rho=rho, matrix_s=matrix_s)
839 CALL qs_rho_get(rho, rho_ao=rho_ao)
840
841 ALLOCATE (xas_tdp_env%q_projector(nspins))
842 ALLOCATE (xas_tdp_env%q_projector(1)%matrix)
843 CALL dbcsr_create(xas_tdp_env%q_projector(1)%matrix, name="Q PROJECTOR ALPHA", &
844 template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
845 IF (do_os) THEN
846 ALLOCATE (xas_tdp_env%q_projector(2)%matrix)
847 CALL dbcsr_create(xas_tdp_env%q_projector(2)%matrix, name="Q PROJECTOR BETA", &
848 template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry)
849 END IF
850
851! In the case of spin-restricted calculations, rho_ao includes double occupency => 0.5 prefactor
852 fact = -0.5_dp; IF (do_os) fact = -1.0_dp
853 CALL dbcsr_multiply('N', 'N', fact, matrix_s(1)%matrix, rho_ao(1)%matrix, 0.0_dp, &
854 xas_tdp_env%q_projector(1)%matrix, filter_eps=xas_tdp_control%eps_filter)
855 CALL dbcsr_add_on_diag(xas_tdp_env%q_projector(1)%matrix, 1.0_dp)
856 CALL dbcsr_finalize(xas_tdp_env%q_projector(1)%matrix)
857
858 IF (do_os) THEN
859 CALL dbcsr_multiply('N', 'N', fact, matrix_s(1)%matrix, rho_ao(2)%matrix, 0.0_dp, &
860 xas_tdp_env%q_projector(2)%matrix, filter_eps=xas_tdp_control%eps_filter)
861 CALL dbcsr_add_on_diag(xas_tdp_env%q_projector(2)%matrix, 1.0_dp)
862 CALL dbcsr_finalize(xas_tdp_env%q_projector(2)%matrix)
863 END IF
864
865! Create the structure for the dipole in the AO basis
866 ALLOCATE (xas_tdp_env%dipmat(3))
867 DO i = 1, 3
868 ALLOCATE (xas_tdp_env%dipmat(i)%matrix)
869 CALL dbcsr_copy(matrix_tmp, matrix_s(1)%matrix, name="XAS TDP dipole matrix")
870 IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
871 CALL dbcsr_create(xas_tdp_env%dipmat(i)%matrix, template=matrix_s(1)%matrix, &
872 matrix_type=dbcsr_type_antisymmetric)
873 CALL dbcsr_complete_redistribute(matrix_tmp, xas_tdp_env%dipmat(i)%matrix)
874 ELSE
875 CALL dbcsr_create(xas_tdp_env%dipmat(i)%matrix, template=matrix_s(1)%matrix, &
876 matrix_type=dbcsr_type_symmetric)
877 CALL dbcsr_copy(xas_tdp_env%dipmat(i)%matrix, matrix_tmp)
878 END IF
879 CALL dbcsr_set(xas_tdp_env%dipmat(i)%matrix, 0.0_dp)
880 CALL dbcsr_release(matrix_tmp)
881 END DO
882
883! Create the structure for the electric quadrupole in the AO basis, if required
884 IF (xas_tdp_control%do_quad) THEN
885 ALLOCATE (xas_tdp_env%quadmat(6))
886 DO i = 1, 6
887 ALLOCATE (xas_tdp_env%quadmat(i)%matrix)
888 CALL dbcsr_copy(xas_tdp_env%quadmat(i)%matrix, matrix_s(1)%matrix, name="XAS TDP quadrupole matrix")
889 CALL dbcsr_set(xas_tdp_env%quadmat(i)%matrix, 0.0_dp)
890 END DO
891 END IF
892
893! Precompute it in the velocity representation, if so chosen
894 IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
895 !enforce minimum image to avoid any PBCs related issues. Ok because very localized densities
896 CALL p_xyz_ao(xas_tdp_env%dipmat, qs_env, minimum_image=.true.)
897 END IF
898
899! Allocate SOC in AO basis matrices
900 IF (xas_tdp_control%do_soc .OR. xas_tdp_control%do_gw2x) THEN
901 ALLOCATE (xas_tdp_env%orb_soc(3))
902 DO i = 1, 3
903 ALLOCATE (xas_tdp_env%orb_soc(i)%matrix)
904 END DO
905 END IF
906
907! Check that everything is allowed
908 CALL safety_check(xas_tdp_control, qs_env)
909
910! Initialize libint for the 3-center integrals
912
913! Compute LUMOs as guess for OT solver and/or for GW2X correction
914 IF (xas_tdp_control%do_ot .OR. xas_tdp_control%do_gw2x) THEN
915 CALL make_lumo_guess(xas_tdp_env, xas_tdp_control, qs_env)
916 END IF
917
918 END SUBROUTINE xas_tdp_init
919
920! **************************************************************************************************
921!> \brief splits the excited atoms of a kind into batches for RI 3c integrals load balance
922!> \param ex_atoms_of_kind the excited atoms for the current kind, randomly shuffled
923!> \param nbatch number of batches to loop over
924!> \param batch_size standard size of a batch
925!> \param atoms_of_kind number of atoms for the current kind (excited or not)
926!> \param xas_tdp_env ...
927! **************************************************************************************************
928 SUBROUTINE get_ri_3c_batches(ex_atoms_of_kind, nbatch, batch_size, atoms_of_kind, xas_tdp_env)
929
930 INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(INOUT) :: ex_atoms_of_kind
931 INTEGER, INTENT(OUT) :: nbatch
932 INTEGER, INTENT(IN) :: batch_size
933 INTEGER, DIMENSION(:), INTENT(IN) :: atoms_of_kind
934 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
935
936 INTEGER :: iat, iatom, nex_atom
937 TYPE(rng_stream_type), ALLOCATABLE :: rng_stream
938
939 !Get the atoms from atoms_of_kind that are excited
940 nex_atom = 0
941 DO iat = 1, SIZE(atoms_of_kind)
942 iatom = atoms_of_kind(iat)
943 IF (.NOT. any(xas_tdp_env%ex_atom_indices == iatom)) cycle
944 nex_atom = nex_atom + 1
945 END DO
946
947 ALLOCATE (ex_atoms_of_kind(nex_atom))
948 nex_atom = 0
949 DO iat = 1, SIZE(atoms_of_kind)
950 iatom = atoms_of_kind(iat)
951 IF (.NOT. any(xas_tdp_env%ex_atom_indices == iatom)) cycle
952 nex_atom = nex_atom + 1
953 ex_atoms_of_kind(nex_atom) = iatom
954 END DO
955
956 !We shuffle those atoms to spread them
957 rng_stream = rng_stream_type(name="uniform_rng", distribution_type=uniform)
958 CALL rng_stream%shuffle(ex_atoms_of_kind(1:nex_atom))
959
960 nbatch = nex_atom/batch_size
961 IF (nbatch*batch_size .NE. nex_atom) nbatch = nbatch + 1
962
963 END SUBROUTINE get_ri_3c_batches
964
965! **************************************************************************************************
966!> \brief Checks for forbidden keywords combinations
967!> \param xas_tdp_control ...
968!> \param qs_env ...
969! **************************************************************************************************
970 SUBROUTINE safety_check(xas_tdp_control, qs_env)
971
972 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
973 TYPE(qs_environment_type), POINTER :: qs_env
974
975 TYPE(dft_control_type), POINTER :: dft_control
976
977 !PB only available without exact exchange
978 IF (xas_tdp_control%is_periodic .AND. xas_tdp_control%do_hfx &
979 .AND. xas_tdp_control%x_potential%potential_type == do_potential_coulomb) THEN
980 cpabort("XAS TDP with Coulomb operator for exact exchange only supports non-periodic BCs")
981 END IF
982
983 !open-shell/closed-shell tests
984 IF (xas_tdp_control%do_roks .OR. xas_tdp_control%do_uks) THEN
985
986 IF (.NOT. (xas_tdp_control%do_spin_cons .OR. xas_tdp_control%do_spin_flip)) THEN
987 cpabort("Need spin-conserving and/or spin-flip excitations for open-shell systems")
988 END IF
989
990 IF (xas_tdp_control%do_singlet .OR. xas_tdp_control%do_triplet) THEN
991 cpabort("Singlet/triplet excitations only for restricted closed-shell systems")
992 END IF
993
994 IF (xas_tdp_control%do_soc .AND. .NOT. &
995 (xas_tdp_control%do_spin_flip .AND. xas_tdp_control%do_spin_cons)) THEN
996
997 cpabort("Both spin-conserving and spin-flip excitations are required for SOC")
998 END IF
999 ELSE
1000
1001 IF (.NOT. (xas_tdp_control%do_singlet .OR. xas_tdp_control%do_triplet)) THEN
1002 cpabort("Need singlet and/or triplet excitations for closed-shell systems")
1003 END IF
1004
1005 IF (xas_tdp_control%do_spin_cons .OR. xas_tdp_control%do_spin_flip) THEN
1006 cpabort("Spin-conserving/spin-flip excitations only for open-shell systems")
1007 END IF
1008
1009 IF (xas_tdp_control%do_soc .AND. .NOT. &
1010 (xas_tdp_control%do_singlet .AND. xas_tdp_control%do_triplet)) THEN
1011
1012 cpabort("Both singlet and triplet excitations are needed for SOC")
1013 END IF
1014 END IF
1015
1016 !Warn against using E_RANGE with SOC
1017 IF (xas_tdp_control%do_soc .AND. xas_tdp_control%e_range > 0.0_dp) THEN
1018 cpwarn("Using E_RANGE and SOC together may lead to crashes, use N_EXCITED for safety.")
1019 END IF
1020
1021 !TDA, full-TDDFT and diagonalization
1022 IF (.NOT. xas_tdp_control%tamm_dancoff) THEN
1023
1024 IF (xas_tdp_control%do_spin_flip) THEN
1025 cpabort("Spin-flip kernel only implemented for Tamm-Dancoff approximation")
1026 END IF
1027
1028 IF (xas_tdp_control%do_ot) THEN
1029 cpabort("OT diagonalization only available within the Tamm-Dancoff approximation")
1030 END IF
1031 END IF
1032
1033 !GW2X, need hfx kernel and LOCALIZE
1034 IF (xas_tdp_control%do_gw2x) THEN
1035 IF (.NOT. xas_tdp_control%do_hfx) THEN
1036 cpabort("GW2x requires the definition of the EXACT_EXCHANGE kernel")
1037 END IF
1038 IF (.NOT. xas_tdp_control%do_loc) THEN
1039 cpabort("GW2X requires the LOCALIZE keyword in DONOR_STATES")
1040 END IF
1041 END IF
1042
1043 !Only allow ADMM schemes that correct for eigenvalues
1044 CALL get_qs_env(qs_env, dft_control=dft_control)
1045 IF (dft_control%do_admm) THEN
1046 IF ((.NOT. qs_env%admm_env%purification_method == do_admm_purify_none) .AND. &
1047 (.NOT. qs_env%admm_env%purification_method == do_admm_purify_cauchy_subspace) .AND. &
1048 (.NOT. qs_env%admm_env%purification_method == do_admm_purify_mo_diag)) THEN
1049
1050 cpabort("XAS_TDP only compatible with ADMM purification NONE, CAUCHY_SUBSPACE and MO_DIAG")
1051
1052 END IF
1053 END IF
1054
1055 END SUBROUTINE safety_check
1056
1057! **************************************************************************************************
1058!> \brief Prints some basic info about the chosen parameters
1059!> \param ou the output unis
1060!> \param xas_tdp_control ...
1061!> \param qs_env ...
1062! **************************************************************************************************
1063 SUBROUTINE print_info(ou, xas_tdp_control, qs_env)
1064
1065 INTEGER, INTENT(IN) :: ou
1066 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1067 TYPE(qs_environment_type), POINTER :: qs_env
1068
1069 INTEGER :: i
1070 REAL(dp) :: occ
1071 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1072 TYPE(dft_control_type), POINTER :: dft_control
1073 TYPE(section_vals_type), POINTER :: input, kernel_section
1074
1075 NULLIFY (input, kernel_section, dft_control, matrix_s)
1076
1077 CALL get_qs_env(qs_env, input=input, dft_control=dft_control, matrix_s=matrix_s)
1078
1079 !Overlap matrix sparsity
1080 occ = dbcsr_get_occupation(matrix_s(1)%matrix)
1081
1082 IF (ou .LE. 0) RETURN
1083
1084 !Reference calculation
1085 IF (xas_tdp_control%do_uks) THEN
1086 WRITE (unit=ou, fmt="(/,T3,A)") &
1087 "XAS_TDP| Reference calculation: Unrestricted Kohn-Sham"
1088 ELSE IF (xas_tdp_control%do_roks) THEN
1089 WRITE (unit=ou, fmt="(/,T3,A)") &
1090 "XAS_TDP| Reference calculation: Restricted Open-Shell Kohn-Sham"
1091 ELSE
1092 WRITE (unit=ou, fmt="(/,T3,A)") &
1093 "XAS_TDP| Reference calculation: Restricted Closed-Shell Kohn-Sham"
1094 END IF
1095
1096 !TDA
1097 IF (xas_tdp_control%tamm_dancoff) THEN
1098 WRITE (unit=ou, fmt="(T3,A)") &
1099 "XAS_TDP| Tamm-Dancoff Approximation (TDA): On"
1100 ELSE
1101 WRITE (unit=ou, fmt="(T3,A)") &
1102 "XAS_TDP| Tamm-Dancoff Approximation (TDA): Off"
1103 END IF
1104
1105 !Dipole form
1106 IF (xas_tdp_control%dipole_form == xas_dip_vel) THEN
1107 WRITE (unit=ou, fmt="(T3,A)") &
1108 "XAS_TDP| Transition Dipole Representation: VELOCITY"
1109 ELSE
1110 WRITE (unit=ou, fmt="(T3,A)") &
1111 "XAS_TDP| Transition Dipole Representation: LENGTH"
1112 END IF
1113
1114 !Quadrupole
1115 IF (xas_tdp_control%do_quad) THEN
1116 WRITE (unit=ou, fmt="(T3,A)") &
1117 "XAS_TDP| Transition Quadrupole: On"
1118 END IF
1119
1120 !EPS_PGF
1121 IF (xas_tdp_control%eps_pgf > 0.0_dp) THEN
1122 WRITE (unit=ou, fmt="(T3,A,ES7.1)") &
1123 "XAS_TDP| EPS_PGF_XAS: ", xas_tdp_control%eps_pgf
1124 ELSE
1125 WRITE (unit=ou, fmt="(T3,A,ES7.1,A)") &
1126 "XAS_TDP| EPS_PGF_XAS: ", dft_control%qs_control%eps_pgf_orb, " (= EPS_PGF_ORB)"
1127 END IF
1128
1129 !EPS_FILTER
1130 WRITE (unit=ou, fmt="(T3,A,ES7.1)") &
1131 "XAS_TDP| EPS_FILTER: ", xas_tdp_control%eps_filter
1132
1133 !Grid info
1134 IF (xas_tdp_control%do_xc) THEN
1135 WRITE (unit=ou, fmt="(T3,A)") &
1136 "XAS_TDP| Radial Grid(s) Info: Kind, na, nr"
1137 DO i = 1, SIZE(xas_tdp_control%grid_info, 1)
1138 WRITE (unit=ou, fmt="(T3,A,A6,A,A,A,A)") &
1139 " ", trim(xas_tdp_control%grid_info(i, 1)), ", ", &
1140 trim(xas_tdp_control%grid_info(i, 2)), ", ", trim(xas_tdp_control%grid_info(i, 3))
1141 END DO
1142 END IF
1143
1144 !No kernel
1145 IF (.NOT. xas_tdp_control%do_coulomb) THEN
1146 WRITE (unit=ou, fmt="(/,T3,A)") &
1147 "XAS_TDP| No kernel (standard DFT)"
1148 END IF
1149
1150 !XC kernel
1151 IF (xas_tdp_control%do_xc) THEN
1152
1153 WRITE (unit=ou, fmt="(/,T3,A,F5.2,A)") &
1154 "XAS_TDP| RI Region's Radius: ", xas_tdp_control%ri_radius*angstrom, " Ang"
1155
1156 WRITE (unit=ou, fmt="(T3,A,/)") &
1157 "XAS_TDP| XC Kernel Functional(s) used for the kernel:"
1158
1159 kernel_section => section_vals_get_subs_vals(input, "DFT%XAS_TDP%KERNEL")
1160 CALL xc_write(ou, kernel_section, lsd=.true.)
1161 END IF
1162
1163 !HFX kernel
1164 IF (xas_tdp_control%do_hfx) THEN
1165 WRITE (unit=ou, fmt="(/,T3,A,/,/,T3,A,F5.3)") &
1166 "XAS_TDP| Exact Exchange Kernel: Yes ", &
1167 "EXACT_EXCHANGE| Scale: ", xas_tdp_control%sx
1168 IF (xas_tdp_control%x_potential%potential_type == do_potential_coulomb) THEN
1169 WRITE (unit=ou, fmt="(T3,A)") &
1170 "EXACT_EXCHANGE| Potential : Coulomb"
1171 ELSE IF (xas_tdp_control%x_potential%potential_type == do_potential_truncated) THEN
1172 WRITE (unit=ou, fmt="(T3,A,/,T3,A,F5.2,A,/,T3,A,A)") &
1173 "EXACT_EXCHANGE| Potential: Truncated Coulomb", &
1174 "EXACT_EXCHANGE| Range: ", xas_tdp_control%x_potential%cutoff_radius*angstrom, ", (Ang)", &
1175 "EXACT_EXCHANGE| T_C_G_DATA: ", trim(xas_tdp_control%x_potential%filename)
1176 ELSE IF (xas_tdp_control%x_potential%potential_type == do_potential_short) THEN
1177 WRITE (unit=ou, fmt="(T3,A,/,T3,A,F5.2,A,/,T3,A,F5.2,A,/,T3,A,ES7.1)") &
1178 "EXACT_EXCHANGE| Potential: Short Range", &
1179 "EXACT_EXCHANGE| Omega: ", xas_tdp_control%x_potential%omega, ", (1/a0)", &
1180 "EXACT_EXCHANGE| Effective Range: ", xas_tdp_control%x_potential%cutoff_radius*angstrom, ", (Ang)", &
1181 "EXACT_EXCHANGE| EPS_RANGE: ", xas_tdp_control%eps_range
1182 END IF
1183 IF (xas_tdp_control%eps_screen > 1.0e-16) THEN
1184 WRITE (unit=ou, fmt="(T3,A,ES7.1)") &
1185 "EXACT_EXCHANGE| EPS_SCREENING: ", xas_tdp_control%eps_screen
1186 END IF
1187
1188 !RI metric
1189 IF (xas_tdp_control%do_ri_metric) THEN
1190
1191 WRITE (unit=ou, fmt="(/,T3,A)") &
1192 "EXACT_EXCHANGE| Using a RI metric"
1193 IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_id) THEN
1194 WRITE (unit=ou, fmt="(T3,A)") &
1195 "EXACT_EXCHANGE RI_METRIC| Potential : Overlap"
1196 ELSE IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_truncated) THEN
1197 WRITE (unit=ou, fmt="(T3,A,/,T3,A,F5.2,A,/,T3,A,A)") &
1198 "EXACT_EXCHANGE RI_METRIC| Potential: Truncated Coulomb", &
1199 "EXACT_EXCHANGE RI_METRIC| Range: ", xas_tdp_control%ri_m_potential%cutoff_radius &
1200 *angstrom, ", (Ang)", &
1201 "EXACT_EXCHANGE RI_METRIC| T_C_G_DATA: ", trim(xas_tdp_control%ri_m_potential%filename)
1202 ELSE IF (xas_tdp_control%ri_m_potential%potential_type == do_potential_short) THEN
1203 WRITE (unit=ou, fmt="(T3,A,/,T3,A,F5.2,A,/,T3,A,F5.2,A,/,T3,A,ES7.1)") &
1204 "EXACT_EXCHANGE RI_METRIC| Potential: Short Range", &
1205 "EXACT_EXCHANGE RI_METRIC| Omega: ", xas_tdp_control%ri_m_potential%omega, ", (1/a0)", &
1206 "EXACT_EXCHANGE RI_METRIC| Effective Range: ", &
1207 xas_tdp_control%ri_m_potential%cutoff_radius*angstrom, ", (Ang)", &
1208 "EXACT_EXCHANGE RI_METRIC| EPS_RANGE: ", xas_tdp_control%eps_range
1209 END IF
1210 END IF
1211 ELSE
1212 WRITE (unit=ou, fmt="(/,T3,A,/)") &
1213 "XAS_TDP| Exact Exchange Kernel: No "
1214 END IF
1215
1216 !overlap mtrix occupation
1217 WRITE (unit=ou, fmt="(/,T3,A,F5.2)") &
1218 "XAS_TDP| Overlap matrix occupation: ", occ
1219
1220 !GW2X parameter
1221 IF (xas_tdp_control%do_gw2x) THEN
1222 WRITE (unit=ou, fmt="(T3,A,/)") &
1223 "XAS_TDP| GW2X correction enabled"
1224
1225 IF (xas_tdp_control%xps_only) THEN
1226 WRITE (unit=ou, fmt="(T3,A)") &
1227 "GW2X| Only computing ionizations potentials for XPS"
1228 END IF
1229
1230 IF (xas_tdp_control%pseudo_canonical) THEN
1231 WRITE (unit=ou, fmt="(T3,A)") &
1232 "GW2X| Using the pseudo-canonical scheme"
1233 ELSE
1234 WRITE (unit=ou, fmt="(T3,A)") &
1235 "GW2X| Using the GW2X* scheme"
1236 END IF
1237
1238 WRITE (unit=ou, fmt="(T3,A,ES7.1)") &
1239 "GW2X| EPS_GW2X: ", xas_tdp_control%gw2x_eps
1240
1241 WRITE (unit=ou, fmt="(T3,A,I5)") &
1242 "GW2X| contraction batch size: ", xas_tdp_control%batch_size
1243
1244 IF ((int(xas_tdp_control%c_os) .NE. 1) .OR. (int(xas_tdp_control%c_ss) .NE. 1)) THEN
1245 WRITE (unit=ou, fmt="(T3,A,F7.4,/,T3,A,F7.4)") &
1246 "GW2X| Same-spin scaling factor: ", xas_tdp_control%c_ss, &
1247 "GW2X| Opposite-spin scaling factor: ", xas_tdp_control%c_os
1248 END IF
1249
1250 END IF
1251
1252 END SUBROUTINE print_info
1253
1254! **************************************************************************************************
1255!> \brief Assosciate (possibly localized) lowest energy MOs to each excited atoms. The procedure
1256!> looks for MOs "centered" on the excited atoms by comparing distances. It
1257!> then fills the mos_of_ex_atoms arrays of the xas_tdp_env. Only the xas_tdp_control%n_search
1258!> lowest energy MOs are considered. Largely inspired by MI's implementation of XAS
1259!> It is assumed that the Berry phase is used to compute centers.
1260!> \param xas_tdp_env ...
1261!> \param xas_tdp_control ...
1262!> \param qs_env ...
1263!> \note Whether localization took place or not, the procedure is the same as centers are stored in
1264!> xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set
1265!> Assumes that find_mo_centers has been run previously
1266! **************************************************************************************************
1267 SUBROUTINE assign_mos_to_ex_atoms(xas_tdp_env, xas_tdp_control, qs_env)
1268
1269 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
1270 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1271 TYPE(qs_environment_type), POINTER :: qs_env
1272
1273 INTEGER :: at_index, iat, iat_memo, imo, ispin, &
1274 n_atoms, n_search, nex_atoms, nspins
1275 INTEGER, DIMENSION(3) :: perd_init
1276 INTEGER, DIMENSION(:, :, :), POINTER :: mos_of_ex_atoms
1277 REAL(dp) :: dist, dist_min
1278 REAL(dp), DIMENSION(3) :: at_pos, r_ac, wfn_center
1279 TYPE(cell_type), POINTER :: cell
1280 TYPE(localized_wfn_control_type), POINTER :: localized_wfn_control
1281 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1282
1283 NULLIFY (localized_wfn_control, mos_of_ex_atoms, cell, particle_set)
1284
1285! Initialization. mos_of_ex_atoms filled with -1, meaning no assigned state
1286 mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
1287 mos_of_ex_atoms(:, :, :) = -1
1288 n_search = xas_tdp_control%n_search
1289 nex_atoms = xas_tdp_env%nex_atoms
1290 localized_wfn_control => xas_tdp_env%qs_loc_env%localized_wfn_control
1291 CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell)
1292 n_atoms = SIZE(particle_set)
1293 nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
1294
1295! Temporarly impose periodic BCs because of Berry's phase operator used for localization
1296 perd_init = cell%perd
1297 cell%perd = 1
1298
1299! Loop over n_search lowest energy MOs and all atoms, for each spin
1300 DO ispin = 1, nspins
1301 DO imo = 1, n_search
1302! retrieve MO wave function center coordinates.
1303 wfn_center(1:3) = localized_wfn_control%centers_set(ispin)%array(1:3, imo)
1304 iat_memo = 0
1305
1306! a large enough value to avoid bad surprises
1307 dist_min = 10000.0_dp
1308 DO iat = 1, n_atoms
1309 at_pos = particle_set(iat)%r
1310 r_ac = pbc(at_pos, wfn_center, cell)
1311 dist = norm2(r_ac)
1312
1313! keep memory of which atom is the closest to the wave function center
1314 IF (dist < dist_min) THEN
1315 iat_memo = iat
1316 dist_min = dist
1317 END IF
1318 END DO
1319
1320! Verify that the closest atom is actually excited and assign the MO if so
1321 IF (any(xas_tdp_env%ex_atom_indices == iat_memo)) THEN
1322 at_index = locate(xas_tdp_env%ex_atom_indices, iat_memo)
1323 mos_of_ex_atoms(imo, at_index, ispin) = 1
1324 END IF
1325 END DO !imo
1326 END DO !ispin
1327
1328! Go back to initial BCs
1329 cell%perd = perd_init
1330
1331 END SUBROUTINE assign_mos_to_ex_atoms
1332
1333! **************************************************************************************************
1334!> \brief Re-initialize the qs_loc_env to the current MOs.
1335!> \param qs_loc_env the env to re-initialize
1336!> \param n_loc_states the number of states to include
1337!> \param do_uks in cas of spin unrestricted calculation, initialize for both spins
1338!> \param qs_env ...
1339!> \note Useful when one needs to make use of qs_loc features and it is either with canonical MOs
1340!> or the localized MOs have been modified. do_localize is overwritten.
1341!> Same loc range for both spins
1342! **************************************************************************************************
1343 SUBROUTINE reinit_qs_loc_env(qs_loc_env, n_loc_states, do_uks, qs_env)
1344
1345 TYPE(qs_loc_env_type), POINTER :: qs_loc_env
1346 INTEGER, INTENT(IN) :: n_loc_states
1347 LOGICAL, INTENT(IN) :: do_uks
1348 TYPE(qs_environment_type), POINTER :: qs_env
1349
1350 INTEGER :: i, nspins
1351 TYPE(localized_wfn_control_type), POINTER :: loc_wfn_control
1352
1353! First, release the old env
1354 CALL qs_loc_env_release(qs_loc_env)
1355
1356! Re-create it
1357 CALL qs_loc_env_create(qs_loc_env)
1358 CALL localized_wfn_control_create(qs_loc_env%localized_wfn_control)
1359 loc_wfn_control => qs_loc_env%localized_wfn_control
1360
1361! Initialize it
1362 loc_wfn_control%localization_method = do_loc_none
1363 loc_wfn_control%operator_type = op_loc_berry
1364 loc_wfn_control%nloc_states(:) = n_loc_states
1365 loc_wfn_control%eps_occ = 0.0_dp
1366 loc_wfn_control%lu_bound_states(1, :) = 1
1367 loc_wfn_control%lu_bound_states(2, :) = n_loc_states
1368 loc_wfn_control%set_of_states = state_loc_list
1369 loc_wfn_control%do_homo = .true.
1370 ALLOCATE (loc_wfn_control%loc_states(n_loc_states, 2))
1371 DO i = 1, n_loc_states
1372 loc_wfn_control%loc_states(i, :) = i
1373 END DO
1374
1375 nspins = 1; IF (do_uks) nspins = 2
1376 CALL set_loc_centers(loc_wfn_control, loc_wfn_control%nloc_states, nspins=nspins)
1377 ! need to set do_localize=.TRUE. because otherwise no routine works
1378 IF (do_uks) THEN
1379 CALL qs_loc_env_init(qs_loc_env, loc_wfn_control, qs_env, do_localize=.true.)
1380 ELSE
1381 CALL qs_loc_env_init(qs_loc_env, loc_wfn_control, qs_env, myspin=1, do_localize=.true.)
1382 END IF
1383
1384 END SUBROUTINE reinit_qs_loc_env
1385
1386! *************************************************************************************************
1387!> \brief Diagonalize the subset of previously localized MOs that are associated to each excited
1388!> atoms. Updates the MO coeffs accordingly.
1389!> \param xas_tdp_env ...
1390!> \param xas_tdp_control ...
1391!> \param qs_env ...
1392!> \note Needed because after localization, the MOs loose their identity (1s, 2s , 2p, etc)
1393! **************************************************************************************************
1394 SUBROUTINE diagonalize_assigned_mo_subset(xas_tdp_env, xas_tdp_control, qs_env)
1395
1396 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
1397 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1398 TYPE(qs_environment_type), POINTER :: qs_env
1399
1400 INTEGER :: i, iat, ilmo, ispin, nao, nlmo, nspins
1401 REAL(dp), ALLOCATABLE, DIMENSION(:) :: evals
1402 TYPE(cp_blacs_env_type), POINTER :: blacs_env
1403 TYPE(cp_fm_struct_type), POINTER :: ks_struct, lmo_struct
1404 TYPE(cp_fm_type) :: evecs, ks_fm, lmo_fm, work
1405 TYPE(cp_fm_type), POINTER :: mo_coeff
1406 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1407 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1408 TYPE(mp_para_env_type), POINTER :: para_env
1409
1410 NULLIFY (mos, mo_coeff, matrix_ks, para_env, blacs_env, lmo_struct, ks_struct)
1411
1412 ! Get what we need from qs_env
1413 CALL get_qs_env(qs_env, mos=mos, matrix_ks=matrix_ks, para_env=para_env, blacs_env=blacs_env)
1414
1415 nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
1416
1417 ! Loop over the excited atoms and spin
1418 DO ispin = 1, nspins
1419 DO iat = 1, xas_tdp_env%nex_atoms
1420
1421 ! get the MOs
1422 CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao)
1423
1424 ! count how many MOs are associated to this atom and create a fm/struct
1425 nlmo = count(xas_tdp_env%mos_of_ex_atoms(:, iat, ispin) == 1)
1426 CALL cp_fm_struct_create(lmo_struct, nrow_global=nao, ncol_global=nlmo, &
1427 para_env=para_env, context=blacs_env)
1428 CALL cp_fm_create(lmo_fm, lmo_struct)
1429 CALL cp_fm_create(work, lmo_struct)
1430
1431 CALL cp_fm_struct_create(ks_struct, nrow_global=nlmo, ncol_global=nlmo, &
1432 para_env=para_env, context=blacs_env)
1433 CALL cp_fm_create(ks_fm, ks_struct)
1434 CALL cp_fm_create(evecs, ks_struct)
1435
1436 ! Loop over the localized MOs associated to this atom
1437 i = 0
1438 DO ilmo = 1, xas_tdp_control%n_search
1439 IF (xas_tdp_env%mos_of_ex_atoms(ilmo, iat, ispin) == -1) cycle
1440
1441 i = i + 1
1442 ! put the coeff in our atom-restricted lmo_fm
1443 CALL cp_fm_to_fm_submat(mo_coeff, lmo_fm, nrow=nao, ncol=1, s_firstrow=1, &
1444 s_firstcol=ilmo, t_firstrow=1, t_firstcol=i)
1445
1446 END DO !ilmo
1447
1448 ! Computing the KS matrix in the subset of MOs
1449 CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, lmo_fm, work, ncol=nlmo)
1450 CALL parallel_gemm('T', 'N', nlmo, nlmo, nao, 1.0_dp, lmo_fm, work, 0.0_dp, ks_fm)
1451
1452 ! Diagonalizing the KS matrix in the subset of MOs
1453 ALLOCATE (evals(nlmo))
1454 CALL cp_fm_syevd(ks_fm, evecs, evals)
1455 DEALLOCATE (evals)
1456
1457 ! Express the MOs in the basis that diagonalizes KS
1458 CALL parallel_gemm('N', 'N', nao, nlmo, nlmo, 1.0_dp, lmo_fm, evecs, 0.0_dp, work)
1459
1460 ! Replacing the new MOs back in the MO coeffs
1461 i = 0
1462 DO ilmo = 1, xas_tdp_control%n_search
1463 IF (xas_tdp_env%mos_of_ex_atoms(ilmo, iat, ispin) == -1) cycle
1464
1465 i = i + 1
1466 CALL cp_fm_to_fm_submat(work, mo_coeff, nrow=nao, ncol=1, s_firstrow=1, &
1467 s_firstcol=i, t_firstrow=1, t_firstcol=ilmo)
1468
1469 END DO
1470
1471 ! Excited atom clean-up
1472 CALL cp_fm_release(lmo_fm)
1473 CALL cp_fm_release(work)
1474 CALL cp_fm_struct_release(lmo_struct)
1475 CALL cp_fm_release(ks_fm)
1476 CALL cp_fm_release(evecs)
1477 CALL cp_fm_struct_release(ks_struct)
1478 END DO !iat
1479 END DO !ispin
1480
1481 END SUBROUTINE diagonalize_assigned_mo_subset
1482
1483! **************************************************************************************************
1484!> \brief Assign core MO(s) to a given donor_state, taking the type (1S, 2S, etc) into account.
1485!> The projection on a representative Slater-type orbital basis is used as a indicator.
1486!> It is assumed that MOs are already assigned to excited atoms based on their center
1487!> \param donor_state the donor_state to which a MO must be assigned
1488!> \param xas_tdp_env ...
1489!> \param xas_tdp_control ...
1490!> \param qs_env ...
1491! **************************************************************************************************
1492 SUBROUTINE assign_mos_to_donor_state(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
1493
1494 TYPE(donor_state_type), POINTER :: donor_state
1495 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
1496 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1497 TYPE(qs_environment_type), POINTER :: qs_env
1498
1499 INTEGER :: at_index, i, iat, imo, ispin, l, my_mo, &
1500 n_search, n_states, nao, ndo_so, nj, &
1501 nsgf_kind, nsgf_sto, nspins, &
1502 output_unit, zval
1503 INTEGER, ALLOCATABLE, DIMENSION(:, :) :: my_mos
1504 INTEGER, DIMENSION(2) :: next_best_overlap_ind
1505 INTEGER, DIMENSION(4, 7) :: ne
1506 INTEGER, DIMENSION(:), POINTER :: first_sgf, lq, nq
1507 INTEGER, DIMENSION(:, :, :), POINTER :: mos_of_ex_atoms
1508 LOGICAL :: unique
1509 REAL(dp) :: zeff
1510 REAL(dp), ALLOCATABLE, DIMENSION(:) :: diag, overlap, sto_overlap
1511 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: max_overlap
1512 REAL(dp), DIMENSION(2) :: next_best_overlap
1513 REAL(dp), DIMENSION(:), POINTER :: mo_evals, zeta
1514 REAL(dp), DIMENSION(:, :), POINTER :: overlap_matrix, tmp_coeff
1515 TYPE(cp_blacs_env_type), POINTER :: blacs_env
1516 TYPE(cp_fm_struct_type), POINTER :: eval_mat_struct, gs_struct, matrix_struct
1517 TYPE(cp_fm_type) :: eval_mat, work_mat
1518 TYPE(cp_fm_type), POINTER :: gs_coeffs, mo_coeff
1519 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks
1520 TYPE(gto_basis_set_type), POINTER :: kind_basis_set, sto_to_gto_basis_set
1521 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1522 TYPE(mp_para_env_type), POINTER :: para_env
1523 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1524 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1525 TYPE(sto_basis_set_type), POINTER :: sto_basis_set
1526
1527 NULLIFY (sto_basis_set, sto_to_gto_basis_set, qs_kind_set, kind_basis_set, lq, nq, zeta)
1528 NULLIFY (overlap_matrix, mos, mo_coeff, mos_of_ex_atoms, tmp_coeff, first_sgf, particle_set)
1529 NULLIFY (mo_evals, matrix_ks, para_env, blacs_env)
1530 NULLIFY (eval_mat_struct, gs_struct, gs_coeffs)
1531
1532 output_unit = cp_logger_get_default_io_unit()
1533
1534 CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, mos=mos, particle_set=particle_set, &
1535 matrix_ks=matrix_ks, para_env=para_env, blacs_env=blacs_env)
1536
1537 nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
1538
1539! Construction of a STO that fits the type of orbital we look for
1540 ALLOCATE (zeta(1))
1541 ALLOCATE (lq(1))
1542 ALLOCATE (nq(1))
1543! Retrieving quantum numbers
1544 IF (donor_state%state_type == xas_1s_type) THEN
1545 nq(1) = 1
1546 lq(1) = 0
1547 n_states = 1
1548 ELSE IF (donor_state%state_type == xas_2s_type) THEN
1549 nq(1) = 2
1550 lq(1) = 0
1551 n_states = 1
1552 ELSE IF (donor_state%state_type == xas_2p_type) THEN
1553 nq(1) = 2
1554 lq(1) = 1
1555 n_states = 3
1556 ELSE
1557 cpabort("Procedure for required type not implemented")
1558 END IF
1559 ALLOCATE (my_mos(n_states, nspins))
1560 ALLOCATE (max_overlap(n_states, nspins))
1561
1562! Getting the atomic number
1563 CALL get_qs_kind(qs_kind_set(donor_state%kind_index), zeff=zeff)
1564 zval = int(zeff)
1565
1566! Electronic configuration (copied from MI's XAS)
1567 ne = 0
1568 DO l = 1, 4
1569 nj = 2*(l - 1) + 1
1570 DO i = l, 7
1571 ne(l, i) = ptable(zval)%e_conv(l - 1) - 2*nj*(i - l)
1572 ne(l, i) = max(ne(l, i), 0)
1573 ne(l, i) = min(ne(l, i), 2*nj)
1574 END DO
1575 END DO
1576
1577! computing zeta with the Slater sum rules
1578 zeta(1) = srules(zval, ne, nq(1), lq(1))
1579
1580! Allocating memory and initiate STO
1581 CALL allocate_sto_basis_set(sto_basis_set)
1582 CALL set_sto_basis_set(sto_basis_set, nshell=1, nq=nq, lq=lq, zet=zeta)
1583
1584! Some clean-up
1585 DEALLOCATE (nq, lq, zeta)
1586
1587! Expanding the STO into (normalized) GTOs for later calculations, use standard 3 gaussians
1588 CALL create_gto_from_sto_basis(sto_basis_set=sto_basis_set, &
1589 gto_basis_set=sto_to_gto_basis_set, &
1590 ngauss=3)
1591 sto_to_gto_basis_set%norm_type = 2
1592 CALL init_orb_basis_set(sto_to_gto_basis_set)
1593
1594! Retrieving the atomic kind related GTO in which MOs are expanded
1595 CALL get_qs_kind(qs_kind_set(donor_state%kind_index), basis_set=kind_basis_set)
1596
1597! Allocating and computing the overlap between the two basis (they share the same center)
1598 CALL get_gto_basis_set(gto_basis_set=kind_basis_set, nsgf=nsgf_kind)
1599 CALL get_gto_basis_set(gto_basis_set=sto_to_gto_basis_set, nsgf=nsgf_sto)
1600 ALLOCATE (overlap_matrix(nsgf_sto, nsgf_kind))
1601
1602! Making use of MI's subroutine
1603 CALL calc_stogto_overlap(sto_to_gto_basis_set, kind_basis_set, overlap_matrix)
1604
1605! Some clean-up
1606 CALL deallocate_sto_basis_set(sto_basis_set)
1607 CALL deallocate_gto_basis_set(sto_to_gto_basis_set)
1608
1609! Looping over the potential donor states to compute overlap with STO basis
1610 mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
1611 n_search = xas_tdp_control%n_search
1612 at_index = donor_state%at_index
1613 iat = locate(xas_tdp_env%ex_atom_indices, at_index)
1614 ALLOCATE (first_sgf(SIZE(particle_set))) !probably do not need that
1615 CALL get_particle_set(particle_set=particle_set, qs_kind_set=qs_kind_set, first_sgf=first_sgf)
1616 ALLOCATE (tmp_coeff(nsgf_kind, 1))
1617 ALLOCATE (sto_overlap(nsgf_kind))
1618 ALLOCATE (overlap(n_search))
1619
1620 next_best_overlap = 0.0_dp
1621 max_overlap = 0.0_dp
1622
1623 DO ispin = 1, nspins
1624
1625 CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao)
1626 overlap = 0.0_dp
1627
1628 my_mo = 0
1629 DO imo = 1, n_search
1630 IF (mos_of_ex_atoms(imo, iat, ispin) > 0) THEN
1631
1632 sto_overlap = 0.0_dp
1633 tmp_coeff = 0.0_dp
1634
1635! Getting the relevant coefficients for the candidate state
1636 CALL cp_fm_get_submatrix(fm=mo_coeff, target_m=tmp_coeff, start_row=first_sgf(at_index), &
1637 start_col=imo, n_rows=nsgf_kind, n_cols=1, transpose=.false.)
1638
1639! Computing the product overlap_matrix*coeffs
1640 CALL dgemm('N', 'N', nsgf_sto, 1, nsgf_kind, 1.0_dp, overlap_matrix, nsgf_sto, &
1641 tmp_coeff, nsgf_kind, 0.0_dp, sto_overlap, nsgf_sto)
1642
1643! Each element of column vector sto_overlap is the overlap of a basis element of the
1644! generated STO basis with the kind specific orbital basis. Take the sum of the absolute
1645! values so that rotation (of the px, py, pz for example) does not hinder our search
1646 overlap(imo) = sum(abs(sto_overlap))
1647
1648 END IF
1649 END DO
1650
1651! Finding the best overlap(s)
1652 DO i = 1, n_states
1653 my_mo = maxloc(overlap, 1)
1654 my_mos(i, ispin) = my_mo
1655 max_overlap(i, ispin) = maxval(overlap, 1)
1656 overlap(my_mo) = 0.0_dp
1657 END DO
1658! Getting the next best overlap (for validation purposes)
1659 next_best_overlap(ispin) = maxval(overlap, 1)
1660 next_best_overlap_ind(ispin) = maxloc(overlap, 1)
1661
1662! Sort MO indices
1663 CALL sort_unique(my_mos(:, ispin), unique)
1664
1665 END DO !ispin
1666
1667! Some clean-up
1668 DEALLOCATE (overlap_matrix, tmp_coeff)
1669
1670! Dealing with the result
1671 IF (all(my_mos > 0) .AND. all(my_mos <= n_search)) THEN
1672! Assigning the MO indices to the donor_state
1673 ALLOCATE (donor_state%mo_indices(n_states, nspins))
1674 donor_state%mo_indices = my_mos
1675 donor_state%ndo_mo = n_states
1676
1677! Storing the MOs in the donor_state, as vectors column: first columns alpha spin, then beta
1678 CALL cp_fm_struct_create(gs_struct, nrow_global=nao, ncol_global=n_states*nspins, &
1679 para_env=para_env, context=blacs_env)
1680 ALLOCATE (donor_state%gs_coeffs)
1681 CALL cp_fm_create(donor_state%gs_coeffs, gs_struct)
1682
1683 IF (.NOT. ASSOCIATED(xas_tdp_env%mo_coeff)) THEN
1684 ALLOCATE (xas_tdp_env%mo_coeff(nspins))
1685 END IF
1686
1687 DO ispin = 1, nspins
1688 CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
1689 ! check if mo_coeff is copied before for another donor_state
1690 IF (.NOT. ASSOCIATED(xas_tdp_env%mo_coeff(ispin)%local_data)) THEN
1691 ! copy mo_coeff
1692 CALL cp_fm_get_info(matrix=mo_coeff, &
1693 matrix_struct=matrix_struct)
1694 CALL cp_fm_create(xas_tdp_env%mo_coeff(ispin), matrix_struct)
1695 CALL cp_fm_to_fm(mo_coeff, xas_tdp_env%mo_coeff(ispin))
1696 END IF
1697
1698 DO i = 1, n_states
1699 CALL cp_fm_to_fm_submat(msource=mo_coeff, mtarget=donor_state%gs_coeffs, nrow=nao, &
1700 ncol=1, s_firstrow=1, s_firstcol=my_mos(i, ispin), &
1701 t_firstrow=1, t_firstcol=(ispin - 1)*n_states + i)
1702 END DO
1703 END DO
1704 gs_coeffs => donor_state%gs_coeffs
1705
1706 !Keep the subset of the coeffs centered on the excited atom as global array (used a lot)
1707 ALLOCATE (donor_state%contract_coeffs(nsgf_kind, n_states*nspins))
1708 CALL cp_fm_get_submatrix(gs_coeffs, donor_state%contract_coeffs, start_row=first_sgf(at_index), &
1709 start_col=1, n_rows=nsgf_kind, n_cols=n_states*nspins)
1710
1711! Assigning corresponding energy eigenvalues and writing some info in standard input file
1712
1713 !standard eigenvalues as gotten from the KS diagonalization in the ground state
1714 IF (.NOT. xas_tdp_control%do_loc .AND. .NOT. xas_tdp_control%do_roks) THEN
1715 IF (output_unit > 0) THEN
1716 WRITE (unit=output_unit, fmt="(T5,A,/,T5,A,/,T5,A)") &
1717 "The following canonical MO(s) have been associated with the donor state(s)", &
1718 "based on the overlap with the components of a minimal STO basis: ", &
1719 " Spin MO index overlap(sum)"
1720 END IF
1721
1722 ALLOCATE (donor_state%energy_evals(n_states, nspins))
1723 donor_state%energy_evals = 0.0_dp
1724
1725! Canonical MO, no change in eigenvalues, only diagonal elements
1726 DO ispin = 1, nspins
1727 CALL get_mo_set(mos(ispin), eigenvalues=mo_evals)
1728 DO i = 1, n_states
1729 donor_state%energy_evals(i, ispin) = mo_evals(my_mos(i, ispin))
1730
1731 IF (output_unit > 0) THEN
1732 WRITE (unit=output_unit, fmt="(T46,I4,I11,F17.5)") &
1733 ispin, my_mos(i, ispin), max_overlap(i, ispin)
1734 END IF
1735 END DO
1736 END DO
1737
1738 !either localization of MOs or ROKS, in both cases the MO eigenvalues from the KS
1739 !digonalization mat have changed
1740 ELSE
1741 IF (output_unit > 0) THEN
1742 WRITE (unit=output_unit, fmt="(T5,A,/,T5,A,/,T5,A)") &
1743 "The following localized MO(s) have been associated with the donor state(s)", &
1744 "based on the overlap with the components of a minimal STO basis: ", &
1745 " Spin MO index overlap(sum)"
1746 END IF
1747
1748! Loop over the donor states and print
1749 DO ispin = 1, nspins
1750 DO i = 1, n_states
1751
1752! Print info
1753 IF (output_unit > 0) THEN
1754 WRITE (unit=output_unit, fmt="(T46,I4,I11,F17.5)") &
1755 ispin, my_mos(i, ispin), max_overlap(i, ispin)
1756 END IF
1757 END DO
1758 END DO
1759
1760! MO have been rotated or non-physical ROKS MO eigrenvalues:
1761! => need epsilon_ij = <psi_i|F|psi_j> = sum_{pq} c_{qi}c_{pj} F_{pq}
1762! Note: only have digonal elements by construction
1763 ndo_so = nspins*n_states
1764 CALL cp_fm_create(work_mat, gs_struct)
1765 CALL cp_fm_struct_create(eval_mat_struct, nrow_global=ndo_so, ncol_global=ndo_so, &
1766 para_env=para_env, context=blacs_env)
1767 CALL cp_fm_create(eval_mat, eval_mat_struct)
1768 ALLOCATE (diag(ndo_so))
1769
1770 IF (.NOT. xas_tdp_control%do_roks) THEN
1771
1772 ALLOCATE (donor_state%energy_evals(n_states, nspins))
1773 donor_state%energy_evals = 0.0_dp
1774
1775! Compute gs_coeff^T * matrix_ks * gs_coeff to get the epsilon_ij matrix
1776 DO ispin = 1, nspins
1777 CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, gs_coeffs, work_mat, ncol=ndo_so)
1778 CALL parallel_gemm('T', 'N', ndo_so, ndo_so, nao, 1.0_dp, gs_coeffs, work_mat, 0.0_dp, eval_mat)
1779
1780! Put the epsilon_ii into the donor_state. No off-diagonal element because of subset diag
1781 CALL cp_fm_get_diag(eval_mat, diag)
1782 donor_state%energy_evals(:, ispin) = diag((ispin - 1)*n_states + 1:ispin*n_states)
1783
1784 END DO
1785
1786 ELSE
1787 ! If ROKS, slightly different procedure => 2 KS matrices but one type of MOs
1788 ALLOCATE (donor_state%energy_evals(n_states, 2))
1789 donor_state%energy_evals = 0.0_dp
1790
1791! Compute gs_coeff^T * matrix_ks * gs_coeff to get the epsilon_ij matrix
1792 DO ispin = 1, 2
1793 CALL cp_dbcsr_sm_fm_multiply(matrix_ks(ispin)%matrix, gs_coeffs, work_mat, ncol=ndo_so)
1794 CALL parallel_gemm('T', 'N', ndo_so, ndo_so, nao, 1.0_dp, gs_coeffs, work_mat, 0.0_dp, eval_mat)
1795
1796 CALL cp_fm_get_diag(eval_mat, diag)
1797 donor_state%energy_evals(:, ispin) = diag(:)
1798
1799 END DO
1800
1801 DEALLOCATE (diag)
1802 END IF
1803
1804! Clean-up
1805 CALL cp_fm_release(work_mat)
1806 CALL cp_fm_release(eval_mat)
1807 CALL cp_fm_struct_release(eval_mat_struct)
1808
1809 END IF ! do_localize and/or ROKS
1810
1811! Allocate and initialize GW2X corrected IPs as energy_evals
1812 ALLOCATE (donor_state%gw2x_evals(SIZE(donor_state%energy_evals, 1), SIZE(donor_state%energy_evals, 2)))
1813 donor_state%gw2x_evals(:, :) = donor_state%energy_evals(:, :)
1814
1815! Clean-up
1816 CALL cp_fm_struct_release(gs_struct)
1817 DEALLOCATE (first_sgf)
1818
1819 IF (output_unit > 0) WRITE (unit=output_unit, fmt="(T5,A)") " "
1820
1821 DO ispin = 1, nspins
1822 IF (output_unit > 0) THEN
1823 WRITE (unit=output_unit, fmt="(T5,A,I1,A,F7.5,A,I4)") &
1824 "The next best overlap for spin ", ispin, " is ", next_best_overlap(ispin), &
1825 " for MO with index ", next_best_overlap_ind(ispin)
1826 END IF
1827 END DO
1828 IF (output_unit > 0) WRITE (unit=output_unit, fmt="(T5,A)") " "
1829
1830 ELSE
1831 cpabort("A core donor state could not be assigned MO(s). Increasing NSEARCH might help.")
1832 END IF
1833
1834 END SUBROUTINE assign_mos_to_donor_state
1835
1836! **************************************************************************************************
1837!> \brief Compute the centers and spreads of (core) MOs using the Berry phase operator
1838!> \param xas_tdp_env ...
1839!> \param xas_tdp_control ...
1840!> \param qs_env ...
1841!> \note xas_tdp_env%qs_loc_env is used and modified. OK since no localization done after this
1842!> subroutine is used.
1843! **************************************************************************************************
1844 SUBROUTINE find_mo_centers(xas_tdp_env, xas_tdp_control, qs_env)
1845
1846 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
1847 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1848 TYPE(qs_environment_type), POINTER :: qs_env
1849
1850 INTEGER :: dim_op, i, ispin, j, n_centers, nao, &
1851 nspins
1852 REAL(dp), DIMENSION(6) :: weights
1853 TYPE(cell_type), POINTER :: cell
1854 TYPE(cp_blacs_env_type), POINTER :: blacs_env
1855 TYPE(cp_fm_struct_type), POINTER :: tmp_fm_struct
1856 TYPE(cp_fm_type) :: opvec
1857 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: zij_fm_set
1858 TYPE(cp_fm_type), DIMENSION(:), POINTER :: moloc_coeff
1859 TYPE(cp_fm_type), POINTER :: vectors
1860 TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: op_sm_set
1861 TYPE(mp_para_env_type), POINTER :: para_env
1862 TYPE(qs_loc_env_type), POINTER :: qs_loc_env
1863 TYPE(section_vals_type), POINTER :: print_loc_section, prog_run_info
1864
1865 NULLIFY (qs_loc_env, cell, print_loc_section, op_sm_set, moloc_coeff, vectors)
1866 NULLIFY (tmp_fm_struct, para_env, blacs_env, prog_run_info)
1867
1868! Initialization
1869 print_loc_section => xas_tdp_control%print_loc_subsection
1870 n_centers = xas_tdp_control%n_search
1871 CALL get_qs_env(qs_env=qs_env, para_env=para_env, blacs_env=blacs_env, cell=cell)
1872
1873! Set print option to debug to keep clean output file
1874 prog_run_info => section_vals_get_subs_vals(print_loc_section, "PROGRAM_RUN_INFO")
1875 CALL section_vals_val_set(prog_run_info, keyword_name="_SECTION_PARAMETERS_", &
1876 i_val=debug_print_level)
1877
1878! Re-initialize the qs_loc_env to get the current MOs. Use force_loc because needed for centers
1879 CALL reinit_qs_loc_env(xas_tdp_env%qs_loc_env, n_centers, xas_tdp_control%do_uks, qs_env)
1880 qs_loc_env => xas_tdp_env%qs_loc_env
1881
1882! Get what we need from the qs_lovc_env
1883 CALL get_qs_loc_env(qs_loc_env=qs_loc_env, weights=weights, op_sm_set=op_sm_set, &
1884 moloc_coeff=moloc_coeff)
1885
1886! Prepare for zij
1887 vectors => moloc_coeff(1)
1888 CALL cp_fm_get_info(vectors, nrow_global=nao)
1889 CALL cp_fm_create(opvec, vectors%matrix_struct)
1890
1891 CALL cp_fm_struct_create(tmp_fm_struct, para_env=para_env, context=blacs_env, &
1892 ncol_global=n_centers, nrow_global=n_centers)
1893
1894 IF (cell%orthorhombic) THEN
1895 dim_op = 3
1896 ELSE
1897 dim_op = 6
1898 END IF
1899 ALLOCATE (zij_fm_set(2, dim_op))
1900 DO i = 1, dim_op
1901 DO j = 1, 2
1902 CALL cp_fm_create(zij_fm_set(j, i), tmp_fm_struct)
1903 END DO
1904 END DO
1905
1906 ! If spin-unrestricted, need to go spin by spin
1907 nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
1908
1909 DO ispin = 1, nspins
1910! zij computation, copied from qs_loc_methods:optimize_loc_berry
1911 vectors => moloc_coeff(ispin)
1912 DO i = 1, dim_op
1913 DO j = 1, 2
1914 CALL cp_fm_set_all(zij_fm_set(j, i), 0.0_dp)
1915 CALL cp_dbcsr_sm_fm_multiply(op_sm_set(j, i)%matrix, vectors, opvec, ncol=n_centers)
1916 CALL parallel_gemm("T", "N", n_centers, n_centers, nao, 1.0_dp, vectors, opvec, 0.0_dp, &
1917 zij_fm_set(j, i))
1918 END DO
1919 END DO
1920
1921! Compute centers (and spread)
1922 CALL centers_spreads_berry(qs_loc_env=qs_loc_env, zij=zij_fm_set, nmoloc=n_centers, &
1923 cell=cell, weights=weights, ispin=ispin, &
1924 print_loc_section=print_loc_section, only_initial_out=.true.)
1925 END DO !ispins
1926
1927! Clean-up
1928 CALL cp_fm_release(opvec)
1929 CALL cp_fm_struct_release(tmp_fm_struct)
1930 CALL cp_fm_release(zij_fm_set)
1931
1932! Make sure we leave with the correct do_loc value
1933 qs_loc_env%do_localize = xas_tdp_control%do_loc
1934
1935 END SUBROUTINE find_mo_centers
1936
1937! **************************************************************************************************
1938!> \brief Prints the MO to donor_state assocaition with overlap and Mulliken population analysis
1939!> \param xas_tdp_env ...
1940!> \param xas_tdp_control ...
1941!> \param qs_env ...
1942!> \note Called only in case of CHECK_ONLY run
1943! **************************************************************************************************
1944 SUBROUTINE print_checks(xas_tdp_env, xas_tdp_control, qs_env)
1945
1946 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
1947 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
1948 TYPE(qs_environment_type), POINTER :: qs_env
1949
1950 CHARACTER(LEN=default_string_length) :: kind_name
1951 INTEGER :: current_state_index, iat, iatom, ikind, &
1952 istate, output_unit, tmp_index
1953 INTEGER, DIMENSION(:), POINTER :: atoms_of_kind
1954 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1955 TYPE(donor_state_type), POINTER :: current_state
1956
1957 NULLIFY (atomic_kind_set, atoms_of_kind, current_state)
1958
1959 output_unit = cp_logger_get_default_io_unit()
1960
1961 IF (output_unit > 0) THEN
1962 WRITE (output_unit, "(/,T3,A,/,T3,A,/,T3,A)") &
1963 "# Check the donor states for their quality. They need to have a well defined type ", &
1964 " (1s, 2s, etc) which is indicated by the overlap. They also need to be localized, ", &
1965 " for which the Mulliken population analysis is one indicator (must be close to 1.0)"
1966 END IF
1967
1968! Loop over the donor states (as in the main xas_tdp loop)
1969 CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set)
1970 current_state_index = 1
1971
1972 !loop over atomic kinds
1973 DO ikind = 1, SIZE(atomic_kind_set)
1974
1975 CALL get_atomic_kind(atomic_kind=atomic_kind_set(ikind), name=kind_name, &
1976 atom_list=atoms_of_kind)
1977
1978 IF (.NOT. any(xas_tdp_env%ex_kind_indices == ikind)) cycle
1979
1980 !loop over atoms of kind
1981 DO iat = 1, SIZE(atoms_of_kind)
1982 iatom = atoms_of_kind(iat)
1983
1984 IF (.NOT. any(xas_tdp_env%ex_atom_indices == iatom)) cycle
1985 tmp_index = locate(xas_tdp_env%ex_atom_indices, iatom)
1986
1987 !loop over states of excited atom
1988 DO istate = 1, SIZE(xas_tdp_env%state_types, 1)
1989
1990 IF (xas_tdp_env%state_types(istate, tmp_index) == xas_not_excited) cycle
1991
1992 current_state => xas_tdp_env%donor_states(current_state_index)
1993 CALL set_donor_state(current_state, at_index=iatom, &
1994 at_symbol=kind_name, kind_index=ikind, &
1995 state_type=xas_tdp_env%state_types(istate, tmp_index))
1996
1997 IF (output_unit > 0) THEN
1998 WRITE (output_unit, "(/,T4,A,A2,A,I4,A,A,A)") &
1999 "-Donor state of type ", xas_tdp_env%state_type_char(current_state%state_type), &
2000 " for atom", current_state%at_index, " of kind ", trim(current_state%at_symbol), ":"
2001 END IF
2002
2003 !Assign the MOs and perform Mulliken
2004 CALL assign_mos_to_donor_state(current_state, xas_tdp_env, xas_tdp_control, qs_env)
2005 CALL perform_mulliken_on_donor_state(current_state, qs_env)
2006
2007 current_state_index = current_state_index + 1
2008 NULLIFY (current_state)
2009
2010 END DO !istate
2011 END DO !iat
2012 END DO !ikind
2013
2014 IF (output_unit > 0) THEN
2015 WRITE (output_unit, "(/,T5,A)") &
2016 "Use LOCALIZE and/or increase N_SEARCH for better results, if so required."
2017 END IF
2018
2019 END SUBROUTINE print_checks
2020
2021! **************************************************************************************************
2022!> \brief Computes the required multipole moment in the length representation for a given atom
2023!> \param iatom index of the given atom
2024!> \param xas_tdp_env ...
2025!> \param xas_tdp_control ...
2026!> \param qs_env ...
2027!> \note Assumes that wither dipole or quadrupole in length rep is required
2028! **************************************************************************************************
2029 SUBROUTINE compute_lenrep_multipole(iatom, xas_tdp_env, xas_tdp_control, qs_env)
2030
2031 INTEGER, INTENT(IN) :: iatom
2032 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2033 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2034 TYPE(qs_environment_type), POINTER :: qs_env
2035
2036 INTEGER :: i, order
2037 REAL(dp), DIMENSION(3) :: rc
2038 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: work
2039 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2040
2041 NULLIFY (work, particle_set)
2042
2043 CALL get_qs_env(qs_env, particle_set=particle_set)
2044 rc = particle_set(iatom)%r
2045
2046 ALLOCATE (work(9))
2047 IF (xas_tdp_control%dipole_form == xas_dip_len) THEN
2048 DO i = 1, 3
2049 CALL dbcsr_set(xas_tdp_env%dipmat(i)%matrix, 0.0_dp)
2050 work(i)%matrix => xas_tdp_env%dipmat(i)%matrix
2051 END DO
2052 order = 1
2053 END IF
2054 IF (xas_tdp_control%do_quad) THEN
2055 DO i = 1, 6
2056 CALL dbcsr_set(xas_tdp_env%quadmat(i)%matrix, 0.0_dp)
2057 work(3 + i)%matrix => xas_tdp_env%quadmat(i)%matrix
2058 END DO
2059 order = 2
2060 IF (xas_tdp_control%dipole_form == xas_dip_vel) order = -2
2061 END IF
2062
2063 !enforce minimum image to avoid PBCs related issues, ok because localized densities
2064 CALL rrc_xyz_ao(work, qs_env, rc, order=order, minimum_image=.true.)
2065 DEALLOCATE (work)
2066
2067 END SUBROUTINE compute_lenrep_multipole
2068
2069! **************************************************************************************************
2070!> \brief Computes the oscillator strength based on the dipole moment (velocity or length rep) for
2071!> all available excitation energies and store the results in the donor_state. There is no
2072!> triplet dipole in the spin-restricted ground state.
2073!> \param donor_state the donor state which is excited
2074!> \param xas_tdp_control ...
2075!> \param xas_tdp_env ...
2076!> \note The oscillator strength is a scalar: osc_str = 2/(3*omega)*(dipole_v)^2 in the velocity rep
2077!> or : osc_str = 2/3*omega*(dipole_r)^2 in the length representation
2078!> The formulae for the dipoles come from the trace of the dipole operator with the transition
2079!> densities, i.e. what we get from solving the xas_tdp problem. Same procedure with or wo TDA
2080! **************************************************************************************************
2081 SUBROUTINE compute_dipole_fosc(donor_state, xas_tdp_control, xas_tdp_env)
2082
2083 TYPE(donor_state_type), POINTER :: donor_state
2084 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2085 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2086
2087 CHARACTER(len=*), PARAMETER :: routinen = 'compute_dipole_fosc'
2088
2089 INTEGER :: handle, iosc, j, nao, ndo_mo, ndo_so, &
2090 ngs, nosc, nspins
2091 LOGICAL :: do_sc, do_sg
2092 REAL(dp) :: alpha_xyz, beta_xyz, osc_xyz, pref
2093 REAL(dp), ALLOCATABLE, DIMENSION(:) :: alpha_contr, beta_contr, tot_contr
2094 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: dip_block
2095 REAL(dp), DIMENSION(:), POINTER :: lr_evals
2096 REAL(dp), DIMENSION(:, :), POINTER :: alpha_osc, beta_osc, osc_str
2097 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2098 TYPE(cp_fm_struct_type), POINTER :: col_struct, mat_struct
2099 TYPE(cp_fm_type) :: col_work, mat_work
2100 TYPE(cp_fm_type), POINTER :: lr_coeffs
2101 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: dipmat
2102 TYPE(mp_para_env_type), POINTER :: para_env
2103
2104 NULLIFY (dipmat, col_struct, mat_struct, para_env, blacs_env, lr_coeffs)
2105 NULLIFY (lr_evals, osc_str, alpha_osc, beta_osc)
2106
2107 CALL timeset(routinen, handle)
2108
2109! Initialization
2110 do_sc = xas_tdp_control%do_spin_cons
2111 do_sg = xas_tdp_control%do_singlet
2112 IF (do_sc) THEN
2113 nspins = 2
2114 lr_evals => donor_state%sc_evals
2115 lr_coeffs => donor_state%sc_coeffs
2116 ELSE IF (do_sg) THEN
2117 nspins = 1
2118 lr_evals => donor_state%sg_evals
2119 lr_coeffs => donor_state%sg_coeffs
2120 ELSE
2121 cpabort("Dipole oscilaltor strength only for singlets and spin-conserving excitations.")
2122 END IF
2123 ndo_mo = donor_state%ndo_mo
2124 ndo_so = ndo_mo*nspins
2125 ngs = ndo_so; IF (xas_tdp_control%do_roks) ngs = ndo_mo !in ROKS, same gs coeffs
2126 nosc = SIZE(lr_evals)
2127 ALLOCATE (donor_state%osc_str(nosc, 4), donor_state%alpha_osc(nosc, 4), donor_state%beta_osc(nosc, 4))
2128 osc_str => donor_state%osc_str
2129 alpha_osc => donor_state%alpha_osc
2130 beta_osc => donor_state%beta_osc
2131 osc_str = 0.0_dp
2132 alpha_osc = 0.0_dp
2133 beta_osc = 0.0_dp
2134 dipmat => xas_tdp_env%dipmat
2135
2136 ! do some work matrix initialization
2137 CALL cp_fm_get_info(donor_state%gs_coeffs, matrix_struct=col_struct, para_env=para_env, &
2138 context=blacs_env, nrow_global=nao)
2139 CALL cp_fm_struct_create(mat_struct, para_env=para_env, context=blacs_env, &
2140 nrow_global=ndo_so*nosc, ncol_global=ngs)
2141 CALL cp_fm_create(mat_work, mat_struct)
2142 CALL cp_fm_create(col_work, col_struct)
2143
2144 ALLOCATE (tot_contr(ndo_mo), dip_block(ndo_so, ngs), alpha_contr(ndo_mo), beta_contr(ndo_mo))
2145 pref = 2.0_dp; IF (do_sc) pref = 1.0_dp !because of singlet definition u = 1/sqrt(2)(c_a+c_b)
2146
2147! Looping over cartesian coord
2148 DO j = 1, 3
2149
2150 !Compute dip*gs_coeffs
2151 CALL cp_dbcsr_sm_fm_multiply(dipmat(j)%matrix, donor_state%gs_coeffs, col_work, ncol=ngs)
2152 !compute lr_coeffs*dip*gs_coeffs
2153 CALL parallel_gemm('T', 'N', ndo_so*nosc, ngs, nao, 1.0_dp, lr_coeffs, col_work, 0.0_dp, mat_work)
2154
2155 !Loop over the excited states
2156 DO iosc = 1, nosc
2157
2158 tot_contr = 0.0_dp
2159 CALL cp_fm_get_submatrix(fm=mat_work, target_m=dip_block, start_row=(iosc - 1)*ndo_so + 1, &
2160 start_col=1, n_rows=ndo_so, n_cols=ngs)
2161 IF (do_sg) THEN
2162 tot_contr(:) = get_diag(dip_block)
2163 ELSE IF (do_sc .AND. xas_tdp_control%do_uks) THEN
2164 alpha_contr(:) = get_diag(dip_block(1:ndo_mo, 1:ndo_mo))
2165 beta_contr(:) = get_diag(dip_block(ndo_mo + 1:ndo_so, ndo_mo + 1:ndo_so))
2166 tot_contr(:) = alpha_contr(:) + beta_contr(:)
2167 ELSE
2168 !roks
2169 alpha_contr(:) = get_diag(dip_block(1:ndo_mo, :))
2170 beta_contr(:) = get_diag(dip_block(ndo_mo + 1:ndo_so, :))
2171 tot_contr(:) = alpha_contr(:) + beta_contr(:)
2172 END IF
2173
2174 osc_xyz = sum(tot_contr)**2
2175 alpha_xyz = sum(alpha_contr)**2
2176 beta_xyz = sum(beta_contr)**2
2177
2178 alpha_osc(iosc, 4) = alpha_osc(iosc, 4) + alpha_xyz
2179 alpha_osc(iosc, j) = alpha_xyz
2180
2181 beta_osc(iosc, 4) = beta_osc(iosc, 4) + beta_xyz
2182 beta_osc(iosc, j) = beta_xyz
2183
2184 osc_str(iosc, 4) = osc_str(iosc, 4) + osc_xyz
2185 osc_str(iosc, j) = osc_xyz
2186
2187 END DO !iosc
2188 END DO !j
2189
2190 !compute the prefactor
2191 DO j = 1, 4
2192 IF (xas_tdp_control%dipole_form == xas_dip_len) THEN
2193 osc_str(:, j) = pref*2.0_dp/3.0_dp*lr_evals(:)*osc_str(:, j)
2194 alpha_osc(:, j) = pref*2.0_dp/3.0_dp*lr_evals(:)*alpha_osc(:, j)
2195 beta_osc(:, j) = pref*2.0_dp/3.0_dp*lr_evals(:)*beta_osc(:, j)
2196 ELSE
2197 osc_str(:, j) = pref*2.0_dp/3.0_dp/lr_evals(:)*osc_str(:, j)
2198 alpha_osc(:, j) = pref*2.0_dp/3.0_dp/lr_evals(:)*alpha_osc(:, j)
2199 beta_osc(:, j) = pref*2.0_dp/3.0_dp/lr_evals(:)*beta_osc(:, j)
2200 END IF
2201 END DO
2202
2203 !clean-up
2204 CALL cp_fm_release(mat_work)
2205 CALL cp_fm_release(col_work)
2206 CALL cp_fm_struct_release(mat_struct)
2207
2208 CALL timestop(handle)
2209
2210 END SUBROUTINE compute_dipole_fosc
2211
2212! **************************************************************************************************
2213!> \brief Computes the oscillator strength due to the electric quadrupole moment and store it in
2214!> the donor_state (for singlet or spin-conserving)
2215!> \param donor_state the donor state which is excited
2216!> \param xas_tdp_control ...
2217!> \param xas_tdp_env ...
2218!> \note Formula: 1/20*a_fine^2*omega^3 * sum_ab (sum_i r_ia*r_ib - 1/3*ri^2*delta_ab)
2219! **************************************************************************************************
2220 SUBROUTINE compute_quadrupole_fosc(donor_state, xas_tdp_control, xas_tdp_env)
2221
2222 TYPE(donor_state_type), POINTER :: donor_state
2223 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2224 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2225
2226 CHARACTER(len=*), PARAMETER :: routinen = 'compute_quadrupole_fosc'
2227
2228 INTEGER :: handle, iosc, j, nao, ndo_mo, ndo_so, &
2229 ngs, nosc, nspins
2230 LOGICAL :: do_sc, do_sg
2231 REAL(dp) :: pref
2232 REAL(dp), ALLOCATABLE, DIMENSION(:) :: tot_contr, trace
2233 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: quad_block
2234 REAL(dp), DIMENSION(:), POINTER :: lr_evals, osc_str
2235 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2236 TYPE(cp_fm_struct_type), POINTER :: col_struct, mat_struct
2237 TYPE(cp_fm_type) :: col_work, mat_work
2238 TYPE(cp_fm_type), POINTER :: lr_coeffs
2239 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: quadmat
2240 TYPE(mp_para_env_type), POINTER :: para_env
2241
2242 NULLIFY (lr_evals, osc_str, lr_coeffs, col_struct, mat_struct, para_env)
2243 NULLIFY (blacs_env)
2244
2245 CALL timeset(routinen, handle)
2246
2247 ! Initialization
2248 do_sc = xas_tdp_control%do_spin_cons
2249 do_sg = xas_tdp_control%do_singlet
2250 IF (do_sc) THEN
2251 nspins = 2
2252 lr_evals => donor_state%sc_evals
2253 lr_coeffs => donor_state%sc_coeffs
2254 ELSE IF (do_sg) THEN
2255 nspins = 1
2256 lr_evals => donor_state%sg_evals
2257 lr_coeffs => donor_state%sg_coeffs
2258 ELSE
2259 cpabort("Quadrupole oscillator strengths only for singlet and spin-conserving excitations")
2260 END IF
2261 ndo_mo = donor_state%ndo_mo
2262 ndo_so = ndo_mo*nspins
2263 ngs = ndo_so; IF (xas_tdp_control%do_roks) ngs = ndo_mo !only alpha do_mo in ROKS
2264 nosc = SIZE(lr_evals)
2265 ALLOCATE (donor_state%quad_osc_str(nosc))
2266 osc_str => donor_state%quad_osc_str
2267 osc_str = 0.0_dp
2268 quadmat => xas_tdp_env%quadmat
2269
2270 !work matrices init
2271 CALL cp_fm_get_info(donor_state%gs_coeffs, matrix_struct=col_struct, para_env=para_env, &
2272 context=blacs_env, nrow_global=nao)
2273 CALL cp_fm_struct_create(mat_struct, para_env=para_env, context=blacs_env, &
2274 nrow_global=ndo_so*nosc, ncol_global=ngs)
2275 CALL cp_fm_create(mat_work, mat_struct)
2276 CALL cp_fm_create(col_work, col_struct)
2277
2278 ALLOCATE (quad_block(ndo_so, ngs), tot_contr(ndo_mo))
2279 pref = 2.0_dp; IF (do_sc) pref = 1.0_dp !because of singlet definition u = 1/sqrt(2)*...
2280 ALLOCATE (trace(nosc))
2281 trace = 0.0_dp
2282
2283 !Loop over the cartesioan coord :x2, xy, xz, y2, yz, z2
2284 DO j = 1, 6
2285
2286 !Compute quad*gs_coeffs
2287 CALL cp_dbcsr_sm_fm_multiply(quadmat(j)%matrix, donor_state%gs_coeffs, col_work, ncol=ngs)
2288 !compute lr_coeffs*quadmat*gs_coeffs
2289 CALL parallel_gemm('T', 'N', ndo_so*nosc, ngs, nao, 1.0_dp, lr_coeffs, col_work, 0.0_dp, mat_work)
2290
2291 !Loop over the excited states
2292 DO iosc = 1, nosc
2293
2294 tot_contr = 0.0_dp
2295 CALL cp_fm_get_submatrix(fm=mat_work, target_m=quad_block, start_row=(iosc - 1)*ndo_so + 1, &
2296 start_col=1, n_rows=ndo_so, n_cols=ngs)
2297
2298 IF (do_sg) THEN
2299 tot_contr(:) = get_diag(quad_block)
2300 ELSE IF (do_sc .AND. xas_tdp_control%do_uks) THEN
2301 tot_contr(:) = get_diag(quad_block(1:ndo_mo, 1:ndo_mo)) !alpha
2302 tot_contr(:) = tot_contr(:) + get_diag(quad_block(ndo_mo + 1:ndo_so, ndo_mo + 1:ndo_so)) !beta
2303 ELSE
2304 !roks
2305 tot_contr(:) = get_diag(quad_block(1:ndo_mo, :)) !alpha
2306 tot_contr(:) = tot_contr(:) + get_diag(quad_block(ndo_mo + 1:ndo_so, :)) !beta
2307 END IF
2308
2309 !if x2, y2, or z2 direction, need to update the trace (for later)
2310 IF (j == 1 .OR. j == 4 .OR. j == 6) THEN
2311 osc_str(iosc) = osc_str(iosc) + sum(tot_contr)**2
2312 trace(iosc) = trace(iosc) + sum(tot_contr)
2313
2314 !if xy, xz or yz, need to count twice the contribution (for yx, zx and zy)
2315 ELSE
2316 osc_str(iosc) = osc_str(iosc) + 2.0_dp*sum(tot_contr)**2
2317 END IF
2318
2319 END DO !iosc
2320 END DO !j
2321
2322 !compute the prefactor, and remove 1/3*trace^2
2323 osc_str(:) = pref*1._dp/20._dp*a_fine**2*lr_evals(:)**3*(osc_str(:) - 1._dp/3._dp*trace(:)**2)
2324
2325 !clean-up
2326 CALL cp_fm_release(mat_work)
2327 CALL cp_fm_release(col_work)
2328 CALL cp_fm_struct_release(mat_struct)
2329
2330 CALL timestop(handle)
2331
2332 END SUBROUTINE compute_quadrupole_fosc
2333
2334! **************************************************************************************************
2335!> \brief Writes the core MOs to excited atoms associations in the main output file
2336!> \param xas_tdp_env ...
2337!> \param xas_tdp_control ...
2338!> \param qs_env ...
2339!> \note Look at alpha spin MOs, as we are dealing with core states and alpha/beta MOs are the same
2340! **************************************************************************************************
2341 SUBROUTINE write_mos_to_ex_atoms_association(xas_tdp_env, xas_tdp_control, qs_env)
2342
2343 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2344 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2345 TYPE(qs_environment_type), POINTER :: qs_env
2346
2347 CHARACTER(LEN=default_string_length) :: kind_name
2348 INTEGER :: at_index, imo, ispin, nmo, nspins, &
2349 output_unit, tmp_index
2350 INTEGER, DIMENSION(3) :: perd_init
2351 INTEGER, DIMENSION(:), POINTER :: ex_atom_indices
2352 INTEGER, DIMENSION(:, :, :), POINTER :: mos_of_ex_atoms
2353 REAL(dp) :: dist, mo_spread
2354 REAL(dp), DIMENSION(3) :: at_pos, r_ac, wfn_center
2355 TYPE(cell_type), POINTER :: cell
2356 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2357
2358 NULLIFY (cell, particle_set, mos_of_ex_atoms, ex_atom_indices)
2359
2360 output_unit = cp_logger_get_default_io_unit()
2361
2362 IF (output_unit > 0) THEN
2363 WRITE (unit=output_unit, fmt="(/,T3,A,/,T3,A,/,T3,A)") &
2364 " Associated Associated Distance to MO spread (Ang^2)", &
2365 "Spin MO index atom index atom kind MO center (Ang) -w_i ln(|z_ij|^2)", &
2366 "---------------------------------------------------------------------------------"
2367 END IF
2368
2369! Initialization
2370 nspins = 1; IF (xas_tdp_control%do_uks) nspins = 2
2371 mos_of_ex_atoms => xas_tdp_env%mos_of_ex_atoms
2372 ex_atom_indices => xas_tdp_env%ex_atom_indices
2373 nmo = xas_tdp_control%n_search
2374 CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell)
2375
2376! because the use of Berry's phase operator implies PBCs
2377 perd_init = cell%perd
2378 cell%perd = 1
2379
2380! Retrieving all the info for each MO and spin
2381 DO imo = 1, nmo
2382 DO ispin = 1, nspins
2383
2384! each Mo is associated to at most one atom (only 1 in array of -1)
2385 IF (any(mos_of_ex_atoms(imo, :, ispin) == 1)) THEN
2386 tmp_index = maxloc(mos_of_ex_atoms(imo, :, ispin), 1)
2387 at_index = ex_atom_indices(tmp_index)
2388 kind_name = particle_set(at_index)%atomic_kind%name
2389
2390 at_pos = particle_set(at_index)%r
2391 wfn_center = xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set(ispin)%array(1:3, imo)
2392 r_ac = pbc(at_pos, wfn_center, cell)
2393 dist = norm2(r_ac)
2394! convert distance from a.u. to Angstrom
2395 dist = dist*angstrom
2396
2397 mo_spread = xas_tdp_env%qs_loc_env%localized_wfn_control%centers_set(ispin)%array(4, imo)
2398 mo_spread = mo_spread*angstrom*angstrom
2399
2400 IF (output_unit > 0) THEN
2401 WRITE (unit=output_unit, fmt="(T3,I4,I10,I14,A14,ES19.3,ES20.3)") &
2402 ispin, imo, at_index, trim(kind_name), dist, mo_spread
2403 END IF
2404
2405 END IF
2406 END DO !ispin
2407 END DO !imo
2408
2409 IF (output_unit > 0) THEN
2410 WRITE (unit=output_unit, fmt="(T3,A,/)") &
2411 "---------------------------------------------------------------------------------"
2412 END IF
2413
2414! Go back to initial BCs
2415 cell%perd = perd_init
2416
2417 END SUBROUTINE write_mos_to_ex_atoms_association
2418
2419! **************************************************************************************************
2420!> \brief Performs Mulliken population analysis for the MO(s) of a donor_state_type so that user
2421!> can verify it is indeed a core state
2422!> \param donor_state ...
2423!> \param qs_env ...
2424!> \note This is a specific case of Mulliken analysis. In general one computes sum_i (SP)_ii, where
2425!> i labels the basis function centered on the atom of interest. For a specific MO with index
2426!> j, one need to compute sum_{ik} c_{ij} S_{ik} c_{kj}, k = 1,nao
2427! **************************************************************************************************
2428 SUBROUTINE perform_mulliken_on_donor_state(donor_state, qs_env)
2429 TYPE(donor_state_type), POINTER :: donor_state
2430 TYPE(qs_environment_type), POINTER :: qs_env
2431
2432 INTEGER :: at_index, i, ispin, nao, natom, ndo_mo, &
2433 ndo_so, nsgf, nspins, output_unit
2434 INTEGER, DIMENSION(:), POINTER :: first_sgf, last_sgf
2435 INTEGER, DIMENSION(:, :), POINTER :: mo_indices
2436 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: mul_pop, pop_mat
2437 REAL(dp), DIMENSION(:, :), POINTER :: work_array
2438 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2439 TYPE(cp_fm_struct_type), POINTER :: col_vect_struct
2440 TYPE(cp_fm_type) :: work_vect
2441 TYPE(cp_fm_type), POINTER :: gs_coeffs
2442 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
2443 TYPE(mp_para_env_type), POINTER :: para_env
2444 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2445 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2446
2447 NULLIFY (mo_indices, qs_kind_set, particle_set, first_sgf, work_array)
2448 NULLIFY (matrix_s, para_env, blacs_env, col_vect_struct, last_sgf)
2449
2450! Initialization
2451 at_index = donor_state%at_index
2452 mo_indices => donor_state%mo_indices
2453 ndo_mo = donor_state%ndo_mo
2454 gs_coeffs => donor_state%gs_coeffs
2455 output_unit = cp_logger_get_default_io_unit()
2456 nspins = 1; IF (SIZE(mo_indices, 2) == 2) nspins = 2
2457 ndo_so = ndo_mo*nspins
2458 ALLOCATE (mul_pop(ndo_mo, nspins))
2459 mul_pop = 0.0_dp
2460
2461 CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, qs_kind_set=qs_kind_set, &
2462 para_env=para_env, blacs_env=blacs_env, matrix_s=matrix_s)
2463 CALL cp_fm_get_info(gs_coeffs, nrow_global=nao, matrix_struct=col_vect_struct)
2464
2465 natom = SIZE(particle_set, 1)
2466 ALLOCATE (first_sgf(natom))
2467 ALLOCATE (last_sgf(natom))
2468
2469 CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf, last_sgf=last_sgf)
2470 nsgf = last_sgf(at_index) - first_sgf(at_index) + 1
2471
2472 CALL cp_fm_create(work_vect, col_vect_struct)
2473
2474! Take the product of S*coeffs
2475 CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, gs_coeffs, work_vect, ncol=ndo_so)
2476
2477! Only consider the product coeffs^T * S * coeffs on the atom of interest
2478 ALLOCATE (work_array(nsgf, ndo_so))
2479 ALLOCATE (pop_mat(ndo_so, ndo_so))
2480
2481 CALL cp_fm_get_submatrix(fm=work_vect, target_m=work_array, start_row=first_sgf(at_index), &
2482 start_col=1, n_rows=nsgf, n_cols=ndo_so, transpose=.false.)
2483
2484 CALL dgemm('T', 'N', ndo_so, ndo_so, nsgf, 1.0_dp, donor_state%contract_coeffs, nsgf, &
2485 work_array, nsgf, 0.0_dp, pop_mat, ndo_so)
2486
2487! The Mullikan population for the MOs in on the diagonal.
2488 DO ispin = 1, nspins
2489 DO i = 1, ndo_mo
2490 mul_pop(i, ispin) = pop_mat((ispin - 1)*ndo_mo + i, (ispin - 1)*ndo_mo + i)
2491 END DO
2492 END DO
2493
2494! Printing in main output file
2495 IF (output_unit > 0) THEN
2496 WRITE (unit=output_unit, fmt="(T5,A,/,T5,A)") &
2497 "Mulliken population analysis retricted to the associated MO(s) yields: ", &
2498 " Spin MO index charge"
2499 DO ispin = 1, nspins
2500 DO i = 1, ndo_mo
2501 WRITE (unit=output_unit, fmt="(T51,I4,I10,F11.3)") &
2502 ispin, mo_indices(i, ispin), mul_pop(i, ispin)
2503 END DO
2504 END DO
2505 END IF
2506
2507! Clean-up
2508 DEALLOCATE (first_sgf, last_sgf, work_array)
2509 CALL cp_fm_release(work_vect)
2510
2511 END SUBROUTINE perform_mulliken_on_donor_state
2512
2513! **************************************************************************************************
2514!> \brief write the PDOS wrt the LR-orbitals for the current donor_state and/or the CUBES files
2515!> \param ex_type the excitation type: singlet, triplet, spin-conserving, etc
2516!> \param donor_state ...
2517!> \param xas_tdp_env ...
2518!> \param xas_tdp_section ...
2519!> \param qs_env ...
2520! **************************************************************************************************
2521 SUBROUTINE xas_tdp_post(ex_type, donor_state, xas_tdp_env, xas_tdp_section, qs_env)
2522
2523 INTEGER, INTENT(IN) :: ex_type
2524 TYPE(donor_state_type), POINTER :: donor_state
2525 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2526 TYPE(section_vals_type), POINTER :: xas_tdp_section
2527 TYPE(qs_environment_type), POINTER :: qs_env
2528
2529 CHARACTER(len=*), PARAMETER :: routinen = 'xas_tdp_post'
2530
2531 CHARACTER(len=default_string_length) :: domo, domon, excite, pos, xas_mittle
2532 INTEGER :: ex_state_idx, handle, ic, ido_mo, imo, irep, ispin, n_dependent, n_rep, nao, &
2533 ncubes, ndo_mo, ndo_so, nlumo, nmo, nspins, output_unit
2534 INTEGER, DIMENSION(:), POINTER :: bounds, list, state_list
2535 LOGICAL :: append_cube, do_cubes, do_pdos, &
2536 do_wfn_restart
2537 REAL(dp), DIMENSION(:), POINTER :: lr_evals
2538 REAL(dp), DIMENSION(:, :), POINTER :: centers
2539 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2540 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2541 TYPE(cp_fm_struct_type), POINTER :: fm_struct, mo_struct
2542 TYPE(cp_fm_type) :: mo_coeff, work_fm
2543 TYPE(cp_fm_type), POINTER :: lr_coeffs
2544 TYPE(cp_logger_type), POINTER :: logger
2545 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
2546 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
2547 TYPE(mo_set_type), POINTER :: mo_set
2548 TYPE(mp_para_env_type), POINTER :: para_env
2549 TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2550 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2551 TYPE(section_vals_type), POINTER :: print_key
2552
2553 NULLIFY (atomic_kind_set, particle_set, qs_kind_set, mo_set, lr_evals, lr_coeffs)
2554 NULLIFY (mo_struct, para_env, blacs_env, fm_struct, matrix_s, print_key, logger)
2555 NULLIFY (bounds, state_list, list, mos)
2556
2557 !Tests on what to do
2558 logger => cp_get_default_logger()
2559 do_pdos = .false.; do_cubes = .false.; do_wfn_restart = .false.
2560
2561 IF (btest(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
2562 "PRINT%PDOS"), cp_p_file)) do_pdos = .true.
2563
2564 IF (btest(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
2565 "PRINT%CUBES"), cp_p_file)) do_cubes = .true.
2566
2567 IF (btest(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
2568 "PRINT%RESTART_WFN"), cp_p_file)) do_wfn_restart = .true.
2569
2570 IF (.NOT. (do_pdos .OR. do_cubes .OR. do_wfn_restart)) RETURN
2571
2572 CALL timeset(routinen, handle)
2573
2574 !Initialization
2575 CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set, particle_set=particle_set, &
2576 qs_kind_set=qs_kind_set, para_env=para_env, blacs_env=blacs_env, &
2577 matrix_s=matrix_s, mos=mos)
2578
2579 SELECT CASE (ex_type)
2580 CASE (tddfpt_spin_cons)
2581 lr_evals => donor_state%sc_evals
2582 lr_coeffs => donor_state%sc_coeffs
2583 nspins = 2
2584 excite = "spincons"
2585 CASE (tddfpt_spin_flip)
2586 lr_evals => donor_state%sf_evals
2587 lr_coeffs => donor_state%sf_coeffs
2588 nspins = 2
2589 excite = "spinflip"
2590 CASE (tddfpt_singlet)
2591 lr_evals => donor_state%sg_evals
2592 lr_coeffs => donor_state%sg_coeffs
2593 nspins = 1
2594 excite = "singlet"
2595 CASE (tddfpt_triplet)
2596 lr_evals => donor_state%tp_evals
2597 lr_coeffs => donor_state%tp_coeffs
2598 nspins = 1
2599 excite = "triplet"
2600 END SELECT
2601
2602 SELECT CASE (donor_state%state_type)
2603 CASE (xas_1s_type)
2604 domo = "1s"
2605 CASE (xas_2s_type)
2606 domo = "2s"
2607 CASE (xas_2p_type)
2608 domo = "2p"
2609 END SELECT
2610
2611 ndo_mo = donor_state%ndo_mo
2612 ndo_so = ndo_mo*nspins
2613 nmo = SIZE(lr_evals)
2614 CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
2615
2616 CALL cp_fm_struct_create(mo_struct, context=blacs_env, para_env=para_env, &
2617 nrow_global=nao, ncol_global=nmo)
2618 CALL cp_fm_create(mo_coeff, mo_struct)
2619
2620 !Dump the TDDFT excited state AMEW wavefunction into a file for restart in RTP
2621 IF (do_wfn_restart) THEN
2622 block
2623 TYPE(mo_set_type), DIMENSION(2) :: restart_mos
2624 IF (.NOT. (nspins == 1 .AND. donor_state%state_type == xas_1s_type)) THEN
2625 cpabort("RESTART.wfn file only available for RKS K-edge XAS spectroscopy")
2626 END IF
2627
2628 CALL section_vals_val_get(xas_tdp_section, "PRINT%RESTART_WFN%EXCITED_STATE_INDEX", n_rep_val=n_rep)
2629
2630 DO irep = 1, n_rep
2631 CALL section_vals_val_get(xas_tdp_section, "PRINT%RESTART_WFN%EXCITED_STATE_INDEX", &
2632 i_rep_val=irep, i_val=ex_state_idx)
2633 cpassert(ex_state_idx <= SIZE(lr_evals))
2634
2635 DO ispin = 1, 2
2636 CALL duplicate_mo_set(restart_mos(ispin), mos(1))
2637 ! Set the new occupation number in the case of spin-independent based calculaltion since the restart is spin-depedent
2638 IF (SIZE(mos) == 1) &
2639 restart_mos(ispin)%occupation_numbers = mos(1)%occupation_numbers/2
2640 END DO
2641
2642 CALL cp_fm_to_fm_submat(msource=lr_coeffs, mtarget=restart_mos(1)%mo_coeff, nrow=nao, &
2643 ncol=1, s_firstrow=1, s_firstcol=ex_state_idx, t_firstrow=1, &
2644 t_firstcol=donor_state%mo_indices(1, 1))
2645
2646 xas_mittle = 'xasat'//trim(adjustl(cp_to_string(donor_state%at_index)))//'_'//trim(domo)// &
2647 '_'//trim(excite)//'_idx'//trim(adjustl(cp_to_string(ex_state_idx)))
2648 output_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%RESTART_WFN", &
2649 extension=".wfn", file_status="REPLACE", &
2650 file_action="WRITE", file_form="UNFORMATTED", &
2651 middle_name=xas_mittle)
2652
2653 CALL write_mo_set_low(restart_mos, particle_set=particle_set, &
2654 qs_kind_set=qs_kind_set, ires=output_unit)
2655
2656 CALL cp_print_key_finished_output(output_unit, logger, xas_tdp_section, "PRINT%RESTART_WFN")
2657
2658 DO ispin = 1, 2
2659 CALL deallocate_mo_set(restart_mos(ispin))
2660 END DO
2661 END DO
2662 END block
2663 END IF
2664
2665 !PDOS related stuff
2666 IF (do_pdos) THEN
2667
2668 !If S^0.5 not yet stored, compute it once and for all
2669 IF (.NOT. ASSOCIATED(xas_tdp_env%matrix_shalf) .AND. do_pdos) THEN
2670 CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
2671 nrow_global=nao, ncol_global=nao)
2672 ALLOCATE (xas_tdp_env%matrix_shalf)
2673 CALL cp_fm_create(xas_tdp_env%matrix_shalf, fm_struct)
2674 CALL cp_fm_create(work_fm, fm_struct)
2675
2676 CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, xas_tdp_env%matrix_shalf)
2677 CALL cp_fm_power(xas_tdp_env%matrix_shalf, work_fm, 0.5_dp, epsilon(0.0_dp), n_dependent)
2678
2679 CALL cp_fm_release(work_fm)
2680 CALL cp_fm_struct_release(fm_struct)
2681 END IF
2682
2683 !Giving some PDOS info
2684 output_unit = cp_logger_get_default_io_unit()
2685 IF (output_unit > 0) THEN
2686 WRITE (unit=output_unit, fmt="(/,T5,A,/,T5,A,/,T5,A)") &
2687 "Computing the PDOS of linear-response orbitals for spectral features analysis", &
2688 "Note: using standard PDOS routines => ignore mentions of KS states and MO ", &
2689 " occupation numbers. Eigenvalues in *.pdos files are excitations energies."
2690 END IF
2691
2692 !Check on NLUMO
2693 CALL section_vals_val_get(xas_tdp_section, "PRINT%PDOS%NLUMO", i_val=nlumo)
2694 IF (nlumo .NE. 0) THEN
2695 cpwarn("NLUMO is irrelevant for XAS_TDP PDOS. It was overwritten to 0.")
2696 END IF
2697 CALL section_vals_val_set(xas_tdp_section, "PRINT%PDOS%NLUMO", i_val=0)
2698 END IF
2699
2700 !CUBES related stuff
2701 IF (do_cubes) THEN
2702
2703 print_key => section_vals_get_subs_vals(xas_tdp_section, "PRINT%CUBES")
2704
2705 CALL section_vals_val_get(print_key, "CUBES_LU_BOUNDS", i_vals=bounds)
2706 ncubes = bounds(2) - bounds(1) + 1
2707 IF (ncubes > 0) THEN
2708 ALLOCATE (state_list(ncubes))
2709 DO ic = 1, ncubes
2710 state_list(ic) = bounds(1) + ic - 1
2711 END DO
2712 END IF
2713
2714 IF (.NOT. ASSOCIATED(state_list)) THEN
2715 CALL section_vals_val_get(print_key, "CUBES_LIST", n_rep_val=n_rep)
2716
2717 ncubes = 0
2718 DO irep = 1, n_rep
2719 NULLIFY (list)
2720 CALL section_vals_val_get(print_key, "CUBES_LIST", i_rep_val=irep, i_vals=list)
2721 IF (ASSOCIATED(list)) THEN
2722 CALL reallocate(state_list, 1, ncubes + SIZE(list))
2723 DO ic = 1, SIZE(list)
2724 state_list(ncubes + ic) = list(ic)
2725 END DO
2726 ncubes = ncubes + SIZE(list)
2727 END IF
2728 END DO
2729 END IF
2730
2731 IF (.NOT. ASSOCIATED(state_list)) THEN
2732 ncubes = 1
2733 ALLOCATE (state_list(1))
2734 state_list(1) = 1
2735 END IF
2736
2737 CALL section_vals_val_get(print_key, "APPEND", l_val=append_cube)
2738 pos = "REWIND"
2739 IF (append_cube) pos = "APPEND"
2740
2741 ALLOCATE (centers(6, ncubes))
2742 centers = 0.0_dp
2743
2744 END IF
2745
2746 !Loop over MOs and spin, one PDOS/CUBE for each
2747 DO ido_mo = 1, ndo_mo
2748 DO ispin = 1, nspins
2749
2750 !need to create a mo set for the LR-orbitals
2751 ALLOCATE (mo_set)
2752 CALL allocate_mo_set(mo_set, nao=nao, nmo=nmo, nelectron=nmo, n_el_f=real(nmo, dp), &
2753 maxocc=1.0_dp, flexible_electron_count=0.0_dp)
2754 CALL init_mo_set(mo_set, fm_ref=mo_coeff, name="PDOS XAS_TDP MOs")
2755 mo_set%eigenvalues(:) = lr_evals(:)
2756
2757 !get the actual coeff => most common case: closed-shell K-edge, can directly take lr_coeffs
2758 IF (nspins == 1 .AND. ndo_mo == 1) THEN
2759 CALL cp_fm_to_fm(lr_coeffs, mo_set%mo_coeff)
2760 ELSE
2761 DO imo = 1, nmo
2762 CALL cp_fm_to_fm_submat(msource=lr_coeffs, mtarget=mo_set%mo_coeff, &
2763 nrow=nao, ncol=1, s_firstrow=1, &
2764 s_firstcol=(imo - 1)*ndo_so + (ispin - 1)*ndo_mo + ido_mo, &
2765 t_firstrow=1, t_firstcol=imo)
2766 END DO
2767 END IF
2768
2769 !naming the output
2770 domon = domo
2771 IF (donor_state%state_type == xas_2p_type) domon = trim(domo)//trim(adjustl(cp_to_string(ido_mo)))
2772 xas_mittle = 'xasat'//trim(adjustl(cp_to_string(donor_state%at_index)))//'_'// &
2773 trim(domon)//'_'//trim(excite)
2774
2775 IF (do_pdos) THEN
2776 CALL calculate_projected_dos(mo_set, atomic_kind_set, qs_kind_set, particle_set, &
2777 qs_env, xas_tdp_section, ispin, xas_mittle, &
2778 external_matrix_shalf=xas_tdp_env%matrix_shalf)
2779 END IF
2780
2781 IF (do_cubes) THEN
2782 CALL qs_print_cubes(qs_env, mo_set%mo_coeff, ncubes, state_list, centers, &
2783 print_key=print_key, root=xas_mittle, ispin=ispin, &
2784 file_position=pos)
2785 END IF
2786
2787 !clean-up
2788 CALL deallocate_mo_set(mo_set)
2789 DEALLOCATE (mo_set)
2790
2791 END DO
2792 END DO
2793
2794 !clean-up
2795 CALL cp_fm_release(mo_coeff)
2796 CALL cp_fm_struct_release(mo_struct)
2797 IF (do_cubes) DEALLOCATE (centers, state_list)
2798
2799 CALL timestop(handle)
2800
2801 END SUBROUTINE xas_tdp_post
2802
2803! **************************************************************************************************
2804!> \brief Computed the LUMOs for the OT eigensolver guesses
2805!> \param xas_tdp_env ...
2806!> \param xas_tdp_control ...
2807!> \param qs_env ...
2808!> \note Uses stendard diagonalization. Do not use the stendard make_lumo subroutine as it uses
2809!> the OT eigensolver and there is no guarantee that it will converge fast
2810! **************************************************************************************************
2811 SUBROUTINE make_lumo_guess(xas_tdp_env, xas_tdp_control, qs_env)
2812
2813 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2814 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2815 TYPE(qs_environment_type), POINTER :: qs_env
2816
2817 CHARACTER(len=*), PARAMETER :: routinen = 'make_lumo_guess'
2818
2819 INTEGER :: handle, ispin, nao, nelec_spin(2), &
2820 nlumo(2), nocc(2), nspins
2821 LOGICAL :: do_os
2822 REAL(dp), ALLOCATABLE, DIMENSION(:) :: evals
2823 TYPE(cp_blacs_env_type), POINTER :: blacs_env
2824 TYPE(cp_fm_struct_type), POINTER :: fm_struct, lumo_struct
2825 TYPE(cp_fm_type) :: amatrix, bmatrix, evecs, work_fm
2826 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s
2827 TYPE(mp_para_env_type), POINTER :: para_env
2828
2829 NULLIFY (matrix_ks, matrix_s, para_env, blacs_env)
2830 NULLIFY (lumo_struct, fm_struct)
2831
2832 CALL timeset(routinen, handle)
2833
2834 do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
2835 nspins = 1; IF (do_os) nspins = 2
2836 ALLOCATE (xas_tdp_env%lumo_evecs(nspins))
2837 ALLOCATE (xas_tdp_env%lumo_evals(nspins))
2838 CALL get_qs_env(qs_env, matrix_ks=matrix_ks, matrix_s=matrix_s, nelectron_spin=nelec_spin, &
2839 para_env=para_env, blacs_env=blacs_env)
2840 CALL dbcsr_get_info(matrix_s(1)%matrix, nfullrows_total=nao)
2841
2842 IF (do_os) THEN
2843 nlumo = nao - nelec_spin
2844 nocc = nelec_spin
2845 ELSE
2846 nlumo = nao - nelec_spin(1)/2
2847 nocc = nelec_spin(1)/2
2848 END IF
2849
2850 ALLOCATE (xas_tdp_env%ot_prec(nspins))
2851
2852 DO ispin = 1, nspins
2853
2854 !Going through fm to diagonalize
2855 CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
2856 nrow_global=nao, ncol_global=nao)
2857 CALL cp_fm_create(amatrix, fm_struct)
2858 CALL cp_fm_create(bmatrix, fm_struct)
2859 CALL cp_fm_create(evecs, fm_struct)
2860 CALL cp_fm_create(work_fm, fm_struct)
2861 ALLOCATE (evals(nao))
2862 ALLOCATE (xas_tdp_env%lumo_evals(ispin)%array(nlumo(ispin)))
2863
2864 CALL copy_dbcsr_to_fm(matrix_ks(ispin)%matrix, amatrix)
2865 CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, bmatrix)
2866
2867 !The actual diagonalization through Cholesky decomposition
2868 CALL cp_fm_geeig(amatrix, bmatrix, evecs, evals, work_fm)
2869
2870 !Storing results
2871 CALL cp_fm_struct_create(lumo_struct, para_env=para_env, context=blacs_env, &
2872 nrow_global=nao, ncol_global=nlumo(ispin))
2873 CALL cp_fm_create(xas_tdp_env%lumo_evecs(ispin), lumo_struct)
2874
2875 CALL cp_fm_to_fm_submat(evecs, xas_tdp_env%lumo_evecs(ispin), nrow=nao, &
2876 ncol=nlumo(ispin), s_firstrow=1, s_firstcol=nocc(ispin) + 1, &
2877 t_firstrow=1, t_firstcol=1)
2878
2879 xas_tdp_env%lumo_evals(ispin)%array(1:nlumo(ispin)) = evals(nocc(ispin) + 1:nao)
2880
2881 CALL build_ot_spin_prec(evecs, evals, ispin, xas_tdp_env, xas_tdp_control, qs_env)
2882
2883 !clean-up
2884 CALL cp_fm_release(amatrix)
2885 CALL cp_fm_release(bmatrix)
2886 CALL cp_fm_release(evecs)
2887 CALL cp_fm_release(work_fm)
2888 CALL cp_fm_struct_release(fm_struct)
2889 CALL cp_fm_struct_release(lumo_struct)
2890 DEALLOCATE (evals)
2891 END DO
2892
2893 CALL timestop(handle)
2894
2895 END SUBROUTINE make_lumo_guess
2896
2897! **************************************************************************************************
2898!> \brief Builds a preconditioner for the OT eigensolver, based on some heurstics that prioritize
2899!> LUMOs with lower eigenvalues
2900!> \param evecs all the ground state eigenvectors
2901!> \param evals all the ground state eigenvalues
2902!> \param ispin ...
2903!> \param xas_tdp_env ...
2904!> \param xas_tdp_control ...
2905!> \param qs_env ...
2906!> \note assumes that the preconditioner matrix array is allocated
2907! **************************************************************************************************
2908 SUBROUTINE build_ot_spin_prec(evecs, evals, ispin, xas_tdp_env, xas_tdp_control, qs_env)
2909
2910 TYPE(cp_fm_type), INTENT(IN) :: evecs
2911 REAL(dp), DIMENSION(:) :: evals
2912 INTEGER :: ispin
2913 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2914 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2915 TYPE(qs_environment_type), POINTER :: qs_env
2916
2917 CHARACTER(len=*), PARAMETER :: routinen = 'build_ot_spin_prec'
2918
2919 INTEGER :: handle, nao, nelec_spin(2), nguess, &
2920 nocc, nspins
2921 LOGICAL :: do_os
2922 REAL(dp) :: shift
2923 REAL(dp), ALLOCATABLE, DIMENSION(:) :: scaling
2924 TYPE(cp_fm_struct_type), POINTER :: fm_struct
2925 TYPE(cp_fm_type) :: fm_prec, work_fm
2926 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
2927 TYPE(mp_para_env_type), POINTER :: para_env
2928
2929 NULLIFY (fm_struct, para_env, matrix_s)
2930
2931 CALL timeset(routinen, handle)
2932
2933 do_os = xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks
2934 CALL get_qs_env(qs_env, para_env=para_env, nelectron_spin=nelec_spin, matrix_s=matrix_s)
2935 CALL cp_fm_get_info(evecs, nrow_global=nao, matrix_struct=fm_struct)
2936 CALL cp_fm_create(fm_prec, fm_struct)
2937 ALLOCATE (scaling(nao))
2938 nocc = nelec_spin(1)/2
2939 nspins = 1
2940 IF (do_os) THEN
2941 nocc = nelec_spin(ispin)
2942 nspins = 2
2943 END IF
2944
2945 !rough estimate of the number of required evals
2946 nguess = nao - nocc
2947 IF (xas_tdp_control%n_excited > 0 .AND. xas_tdp_control%n_excited < nguess) THEN
2948 nguess = xas_tdp_control%n_excited/nspins
2949 ELSE IF (xas_tdp_control%e_range > 0.0_dp) THEN
2950 nguess = count(evals(nocc + 1:nao) - evals(nocc + 1) .LE. xas_tdp_control%e_range)
2951 END IF
2952
2953 !Give max weight to the first LUMOs
2954 scaling(nocc + 1:nocc + nguess) = 100.0_dp
2955 !Then gradually decrease weight
2956 shift = evals(nocc + 1) - 0.01_dp
2957 scaling(nocc + nguess:nao) = 1.0_dp/(evals(nocc + nguess:nao) - shift)
2958 !HOMOs do not matter, but need well behaved matrix
2959 scaling(1:nocc) = 1.0_dp
2960
2961 !Building the precond as an fm
2962 CALL cp_fm_create(work_fm, fm_struct)
2963
2964 CALL cp_fm_copy_general(evecs, work_fm, para_env)
2965 CALL cp_fm_column_scale(work_fm, scaling)
2966
2967 CALL parallel_gemm('N', 'T', nao, nao, nao, 1.0_dp, work_fm, evecs, 0.0_dp, fm_prec)
2968
2969 !Copy into dbcsr format
2970 ALLOCATE (xas_tdp_env%ot_prec(ispin)%matrix)
2971 CALL dbcsr_create(xas_tdp_env%ot_prec(ispin)%matrix, template=matrix_s(1)%matrix, name="OT_PREC")
2972 CALL copy_fm_to_dbcsr(fm_prec, xas_tdp_env%ot_prec(ispin)%matrix)
2973 CALL dbcsr_filter(xas_tdp_env%ot_prec(ispin)%matrix, xas_tdp_control%eps_filter)
2974
2975 CALL cp_fm_release(work_fm)
2976 CALL cp_fm_release(fm_prec)
2977
2978 CALL timestop(handle)
2979
2980 END SUBROUTINE build_ot_spin_prec
2981
2982! **************************************************************************************************
2983!> \brief Prints GW2X corrected ionization potentials to main output file, including SOC splitting
2984!> \param donor_state ...
2985!> \param xas_tdp_env ...
2986!> \param xas_tdp_control ...
2987!> \param qs_env ...
2988! **************************************************************************************************
2989 SUBROUTINE print_xps(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
2990
2991 TYPE(donor_state_type), POINTER :: donor_state
2992 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
2993 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
2994 TYPE(qs_environment_type), POINTER :: qs_env
2995
2996 INTEGER :: ido_mo, ispin, nspins, output_unit
2997 REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: ips, soc_shifts
2998
2999 output_unit = cp_logger_get_default_io_unit()
3000
3001 nspins = 1; IF (xas_tdp_control%do_uks .OR. xas_tdp_control%do_roks) nspins = 2
3002
3003 ALLOCATE (ips(SIZE(donor_state%gw2x_evals, 1), SIZE(donor_state%gw2x_evals, 2)))
3004 ips(:, :) = donor_state%gw2x_evals(:, :)
3005
3006 !IPs in PBCs cannot be trusted because of a lack of a potential reference
3007 IF (.NOT. xas_tdp_control%is_periodic) THEN
3008
3009 !Apply SOC splitting
3010 IF (donor_state%ndo_mo > 1) THEN
3011 CALL get_soc_splitting(soc_shifts, donor_state, xas_tdp_env, xas_tdp_control, qs_env)
3012 ips(:, :) = ips(:, :) + soc_shifts
3013
3014 IF (output_unit > 0) THEN
3015 WRITE (output_unit, fmt="(/,T5,A,F23.6)") &
3016 "Ionization potentials for XPS (GW2X + SOC): ", -ips(1, 1)*evolt
3017
3018 DO ispin = 1, nspins
3019 DO ido_mo = 1, donor_state%ndo_mo
3020
3021 IF (ispin == 1 .AND. ido_mo == 1) cycle
3022
3023 WRITE (output_unit, fmt="(T5,A,F23.6)") &
3024 " ", -ips(ido_mo, ispin)*evolt
3025
3026 END DO
3027 END DO
3028 END IF
3029
3030 ELSE
3031
3032 ! No SOC, only 1 donor MO per spin
3033 IF (output_unit > 0) THEN
3034 WRITE (output_unit, fmt="(/,T5,A,F29.6)") &
3035 "Ionization potentials for XPS (GW2X): ", -ips(1, 1)*evolt
3036
3037 IF (nspins == 2) THEN
3038 WRITE (output_unit, fmt="(T5,A,F29.6)") &
3039 " ", -ips(1, 2)*evolt
3040 END IF
3041 END IF
3042
3043 END IF
3044 END IF
3045
3046 END SUBROUTINE print_xps
3047
3048! **************************************************************************************************
3049!> \brief Prints the excitation energies and the oscillator strengths for a given donor_state in a file
3050!> \param donor_state the donor_state to print
3051!> \param xas_tdp_env ...
3052!> \param xas_tdp_control ...
3053!> \param xas_tdp_section ...
3054! **************************************************************************************************
3055 SUBROUTINE print_xas_tdp_to_file(donor_state, xas_tdp_env, xas_tdp_control, xas_tdp_section)
3056
3057 TYPE(donor_state_type), POINTER :: donor_state
3058 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
3059 TYPE(xas_tdp_control_type), POINTER :: xas_tdp_control
3060 TYPE(section_vals_type), POINTER :: xas_tdp_section
3061
3062 INTEGER :: i, output_unit, xas_tdp_unit
3063 TYPE(cp_logger_type), POINTER :: logger
3064
3065 NULLIFY (logger)
3066 logger => cp_get_default_logger()
3067
3068 xas_tdp_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%SPECTRUM", &
3069 extension=".spectrum", file_position="APPEND", &
3070 file_action="WRITE", file_form="FORMATTED")
3071
3072 output_unit = cp_logger_get_default_io_unit()
3073
3074 IF (output_unit > 0) THEN
3075 WRITE (output_unit, fmt="(/,T5,A,/)") &
3076 "Calculations done: "
3077 END IF
3078
3079 IF (xas_tdp_control%do_spin_cons) THEN
3080 IF (xas_tdp_unit > 0) THEN
3081
3082! Printing the general donor state information
3083 WRITE (xas_tdp_unit, fmt="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
3084 "==================================================================================", &
3085 "XAS TDP open-shell spin-conserving (no SOC) excitations for DONOR STATE: ", &
3086 xas_tdp_env%state_type_char(donor_state%state_type), ",", &
3087 "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
3088 donor_state%kind_index, "/", trim(donor_state%at_symbol), &
3089 "=================================================================================="
3090
3091! Simply dump the excitation energies/ oscillator strength as they come
3092
3093 IF (xas_tdp_control%do_quad) THEN
3094 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3095 " Index Excitation energy (eV) fosc dipole (a.u.) fosc quadrupole (a.u.)"
3096 DO i = 1, SIZE(donor_state%sc_evals)
3097 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F25.6)") &
3098 i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4), &
3099 donor_state%quad_osc_str(i)
3100 END DO
3101 ELSE IF (xas_tdp_control%xyz_dip) THEN
3102 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3103 " Index Excitation energy (eV) fosc dipole (a.u.) x-component y-component z-component"
3104 DO i = 1, SIZE(donor_state%sc_evals)
3105 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
3106 i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4), &
3107 donor_state%osc_str(i, 1), donor_state%osc_str(i, 2), donor_state%osc_str(i, 3)
3108 END DO
3109 ELSE IF (xas_tdp_control%spin_dip) THEN
3110 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3111 " Index Excitation energy (eV) fosc dipole (a.u.) alpha-comp beta-comp"
3112 DO i = 1, SIZE(donor_state%sc_evals)
3113 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6)") &
3114 i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4), &
3115 donor_state%alpha_osc(i, 4), donor_state%beta_osc(i, 4)
3116 END DO
3117 ELSE
3118 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3119 " Index Excitation energy (eV) fosc dipole (a.u.)"
3120 DO i = 1, SIZE(donor_state%sc_evals)
3121 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6)") &
3122 i, donor_state%sc_evals(i)*evolt, donor_state%osc_str(i, 4)
3123 END DO
3124 END IF
3125
3126 WRITE (xas_tdp_unit, fmt="(A,/)") " "
3127 END IF !xas_tdp_unit > 0
3128
3129 IF (output_unit > 0) THEN
3130 WRITE (output_unit, fmt="(T5,A,F17.6)") &
3131 "First spin-conserving XAS excitation energy (eV): ", donor_state%sc_evals(1)*evolt
3132 END IF
3133
3134 END IF ! do_spin_cons
3135
3136 IF (xas_tdp_control%do_spin_flip) THEN
3137 IF (xas_tdp_unit > 0) THEN
3138
3139! Printing the general donor state information
3140 WRITE (xas_tdp_unit, fmt="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
3141 "==================================================================================", &
3142 "XAS TDP open-shell spin-flip (no SOC) excitations for DONOR STATE: ", &
3143 xas_tdp_env%state_type_char(donor_state%state_type), ",", &
3144 "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
3145 donor_state%kind_index, "/", trim(donor_state%at_symbol), &
3146 "=================================================================================="
3147
3148! Simply dump the excitation energies/ oscillator strength as they come
3149
3150 IF (xas_tdp_control%do_quad) THEN
3151 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3152 " Index Excitation energy (eV) fosc dipole (a.u.) fosc quadrupole (a.u.)"
3153 DO i = 1, SIZE(donor_state%sf_evals)
3154 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F25.6)") &
3155 i, donor_state%sf_evals(i)*evolt, 0.0_dp, 0.0_dp !spin-forbidden !
3156 END DO
3157 ELSE IF (xas_tdp_control%xyz_dip) THEN
3158 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3159 " Index Excitation energy (eV) fosc dipole (a.u.) x-component y-component z-component"
3160 DO i = 1, SIZE(donor_state%sf_evals)
3161 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
3162 i, donor_state%sf_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp
3163 END DO
3164 ELSE IF (xas_tdp_control%spin_dip) THEN
3165 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3166 " Index Excitation energy (eV) fosc dipole (a.u.) alpha-comp beta-comp"
3167 DO i = 1, SIZE(donor_state%sf_evals)
3168 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6)") &
3169 i, donor_state%sf_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp
3170 END DO
3171 ELSE
3172 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3173 " Index Excitation energy (eV) fosc dipole (a.u.)"
3174 DO i = 1, SIZE(donor_state%sf_evals)
3175 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6)") &
3176 i, donor_state%sf_evals(i)*evolt, 0.0_dp
3177 END DO
3178 END IF
3179
3180 WRITE (xas_tdp_unit, fmt="(A,/)") " "
3181 END IF !xas_tdp_unit
3182
3183 IF (output_unit > 0) THEN
3184 WRITE (output_unit, fmt="(T5,A,F23.6)") &
3185 "First spin-flip XAS excitation energy (eV): ", donor_state%sf_evals(1)*evolt
3186 END IF
3187 END IF ! do_spin_flip
3188
3189 IF (xas_tdp_control%do_singlet) THEN
3190 IF (xas_tdp_unit > 0) THEN
3191
3192! Printing the general donor state information
3193 WRITE (xas_tdp_unit, fmt="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
3194 "==================================================================================", &
3195 "XAS TDP singlet excitations (no SOC) for DONOR STATE: ", &
3196 xas_tdp_env%state_type_char(donor_state%state_type), ",", &
3197 "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
3198 donor_state%kind_index, "/", trim(donor_state%at_symbol), &
3199 "=================================================================================="
3200
3201! Simply dump the excitation energies/ oscillator strength as they come
3202
3203 IF (xas_tdp_control%do_quad) THEN
3204 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3205 " Index Excitation energy (eV) fosc dipole (a.u.) fosc quadrupole (a.u.)"
3206 DO i = 1, SIZE(donor_state%sg_evals)
3207 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F25.6)") &
3208 i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4), &
3209 donor_state%quad_osc_str(i)
3210 END DO
3211 ELSE IF (xas_tdp_control%xyz_dip) THEN
3212 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3213 " Index Excitation energy (eV) fosc dipole (a.u.) x-component y-component z-component"
3214 DO i = 1, SIZE(donor_state%sg_evals)
3215 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
3216 i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4), &
3217 donor_state%osc_str(i, 1), donor_state%osc_str(i, 2), donor_state%osc_str(i, 3)
3218 END DO
3219 ELSE
3220 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3221 " Index Excitation energy (eV) fosc dipole (a.u.)"
3222 DO i = 1, SIZE(donor_state%sg_evals)
3223 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6)") &
3224 i, donor_state%sg_evals(i)*evolt, donor_state%osc_str(i, 4)
3225 END DO
3226 END IF
3227
3228 WRITE (xas_tdp_unit, fmt="(A,/)") " "
3229 END IF !xas_tdp_unit
3230
3231 IF (output_unit > 0) THEN
3232 WRITE (output_unit, fmt="(T5,A,F25.6)") &
3233 "First singlet XAS excitation energy (eV): ", donor_state%sg_evals(1)*evolt
3234 END IF
3235 END IF ! do_singlet
3236
3237 IF (xas_tdp_control%do_triplet) THEN
3238 IF (xas_tdp_unit > 0) THEN
3239
3240! Printing the general donor state information
3241 WRITE (xas_tdp_unit, fmt="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
3242 "==================================================================================", &
3243 "XAS TDP triplet excitations (no SOC) for DONOR STATE: ", &
3244 xas_tdp_env%state_type_char(donor_state%state_type), ",", &
3245 "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
3246 donor_state%kind_index, "/", trim(donor_state%at_symbol), &
3247 "=================================================================================="
3248
3249! Simply dump the excitation energies/ oscillator strength as they come
3250
3251 IF (xas_tdp_control%do_quad) THEN
3252 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3253 " Index Excitation energy (eV) fosc dipole (a.u.) fosc quadrupole (a.u.)"
3254 DO i = 1, SIZE(donor_state%tp_evals)
3255 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F25.6)") &
3256 i, donor_state%tp_evals(i)*evolt, 0.0_dp, 0.0_dp !spin-forbidden !
3257 END DO
3258 ELSE IF (xas_tdp_control%xyz_dip) THEN
3259 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3260 " Index Excitation energy (eV) fosc dipole (a.u.) x-component y-component z-component"
3261 DO i = 1, SIZE(donor_state%tp_evals)
3262 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
3263 i, donor_state%tp_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp, 0.0_dp
3264 END DO
3265 ELSE IF (xas_tdp_control%spin_dip) THEN
3266 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3267 " Index Excitation energy (eV) fosc dipole (a.u.) alpha-comp beta-comp"
3268 DO i = 1, SIZE(donor_state%tp_evals)
3269 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6)") &
3270 i, donor_state%tp_evals(i)*evolt, 0.0_dp, 0.0_dp, 0.0_dp
3271 END DO
3272 ELSE
3273 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3274 " Index Excitation energy (eV) fosc dipole (a.u.)"
3275 DO i = 1, SIZE(donor_state%tp_evals)
3276 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6)") &
3277 i, donor_state%tp_evals(i)*evolt, 0.0_dp
3278 END DO
3279 END IF
3280
3281 WRITE (xas_tdp_unit, fmt="(A,/)") " "
3282 END IF !xas_tdp_unit
3283
3284 IF (output_unit > 0) THEN
3285 WRITE (output_unit, fmt="(T5,A,F25.6)") &
3286 "First triplet XAS excitation energy (eV): ", donor_state%tp_evals(1)*evolt
3287 END IF
3288 END IF ! do_triplet
3289
3290 IF (xas_tdp_control%do_soc .AND. donor_state%state_type == xas_2p_type) THEN
3291 IF (xas_tdp_unit > 0) THEN
3292
3293! Printing the general donor state information
3294 WRITE (xas_tdp_unit, fmt="(A,/,A,A,A/,A,I5,A,I5,A,A,/,A)") &
3295 "==================================================================================", &
3296 "XAS TDP excitations after spin-orbit coupling for DONOR STATE: ", &
3297 xas_tdp_env%state_type_char(donor_state%state_type), ",", &
3298 "from EXCITED ATOM: ", donor_state%at_index, ", of KIND (index/symbol): ", &
3299 donor_state%kind_index, "/", trim(donor_state%at_symbol), &
3300 "=================================================================================="
3301
3302! Simply dump the excitation energies/ oscillator strength as they come
3303 IF (xas_tdp_control%do_quad) THEN
3304 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3305 " Index Excitation energy (eV) fosc dipole (a.u.) fosc quadrupole (a.u.)"
3306 DO i = 1, SIZE(donor_state%soc_evals)
3307 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F25.6)") &
3308 i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4), &
3309 donor_state%soc_quad_osc_str(i)
3310 END DO
3311 ELSE IF (xas_tdp_control%xyz_dip) THEN
3312 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3313 " Index Excitation energy (eV) fosc dipole (a.u.) x-component y-component z-component"
3314 DO i = 1, SIZE(donor_state%soc_evals)
3315 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6,F14.6,F14.6,F14.6)") &
3316 i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4), &
3317 donor_state%soc_osc_str(i, 1), donor_state%soc_osc_str(i, 2), donor_state%soc_osc_str(i, 3)
3318 END DO
3319 ELSE
3320 WRITE (xas_tdp_unit, fmt="(T3,A)") &
3321 " Index Excitation energy (eV) fosc dipole (a.u.)"
3322 DO i = 1, SIZE(donor_state%soc_evals)
3323 WRITE (xas_tdp_unit, fmt="(T3,I6,F27.6,F22.6)") &
3324 i, donor_state%soc_evals(i)*evolt, donor_state%soc_osc_str(i, 4)
3325 END DO
3326 END IF
3327
3328 WRITE (xas_tdp_unit, fmt="(A,/)") " "
3329 END IF !xas_tdp_unit
3330
3331 IF (output_unit > 0) THEN
3332 WRITE (output_unit, fmt="(T5,A,F29.6)") &
3333 "First SOC XAS excitation energy (eV): ", donor_state%soc_evals(1)*evolt
3334 END IF
3335 END IF !do_soc
3336
3337 CALL cp_print_key_finished_output(xas_tdp_unit, logger, xas_tdp_section, "PRINT%SPECTRUM")
3338
3339 END SUBROUTINE print_xas_tdp_to_file
3340
3341! **************************************************************************************************
3342!> \brief Prints the donor_state and excitation_type info into a RESTART file for cheap PDOS and/or
3343!> CUBE printing without expensive computation
3344!> \param ex_type singlet, triplet, etc.
3345!> \param donor_state ...
3346!> \param xas_tdp_section ...
3347!> \param qs_env ...
3348! **************************************************************************************************
3349 SUBROUTINE write_donor_state_restart(ex_type, donor_state, xas_tdp_section, qs_env)
3350
3351 INTEGER, INTENT(IN) :: ex_type
3352 TYPE(donor_state_type), POINTER :: donor_state
3353 TYPE(section_vals_type), POINTER :: xas_tdp_section
3354 TYPE(qs_environment_type), POINTER :: qs_env
3355
3356 CHARACTER(len=*), PARAMETER :: routinen = 'write_donor_state_restart'
3357
3358 CHARACTER(len=default_path_length) :: filename
3359 CHARACTER(len=default_string_length) :: domo, excite, my_middle
3360 INTEGER :: ex_atom, handle, ispin, nao, ndo_mo, &
3361 nex, nspins, output_unit, rst_unit, &
3362 state_type
3363 INTEGER, DIMENSION(:, :), POINTER :: mo_indices
3364 LOGICAL :: do_print
3365 REAL(dp), DIMENSION(:), POINTER :: lr_evals
3366 TYPE(cp_fm_type), POINTER :: lr_coeffs
3367 TYPE(cp_logger_type), POINTER :: logger
3368 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
3369 TYPE(section_vals_type), POINTER :: print_key
3370
3371 NULLIFY (logger, lr_coeffs, lr_evals, print_key, mos)
3372
3373 !Initialization
3374 logger => cp_get_default_logger()
3375 do_print = .false.
3376 IF (btest(cp_print_key_should_output(logger%iter_info, xas_tdp_section, &
3377 "PRINT%RESTART", used_print_key=print_key), cp_p_file)) do_print = .true.
3378
3379 IF (.NOT. do_print) RETURN
3380
3381 CALL timeset(routinen, handle)
3382
3383 output_unit = cp_logger_get_default_io_unit()
3384
3385 !Get general info
3386 SELECT CASE (ex_type)
3387 CASE (tddfpt_spin_cons)
3388 lr_evals => donor_state%sc_evals
3389 lr_coeffs => donor_state%sc_coeffs
3390 excite = "spincons"
3391 nspins = 2
3392 CASE (tddfpt_spin_flip)
3393 lr_evals => donor_state%sf_evals
3394 lr_coeffs => donor_state%sf_coeffs
3395 excite = "spinflip"
3396 nspins = 2
3397 CASE (tddfpt_singlet)
3398 lr_evals => donor_state%sg_evals
3399 lr_coeffs => donor_state%sg_coeffs
3400 excite = "singlet"
3401 nspins = 1
3402 CASE (tddfpt_triplet)
3403 lr_evals => donor_state%tp_evals
3404 lr_coeffs => donor_state%tp_coeffs
3405 excite = "triplet"
3406 nspins = 1
3407 END SELECT
3408
3409 SELECT CASE (donor_state%state_type)
3410 CASE (xas_1s_type)
3411 domo = "1s"
3412 CASE (xas_2s_type)
3413 domo = "2s"
3414 CASE (xas_2p_type)
3415 domo = "2p"
3416 END SELECT
3417
3418 ndo_mo = donor_state%ndo_mo
3419 nex = SIZE(lr_evals)
3420 CALL cp_fm_get_info(lr_coeffs, nrow_global=nao)
3421 state_type = donor_state%state_type
3422 ex_atom = donor_state%at_index
3423 mo_indices => donor_state%mo_indices
3424
3425 !Opening restart file
3426 rst_unit = -1
3427 my_middle = 'xasat'//trim(adjustl(cp_to_string(ex_atom)))//'_'//trim(domo)//'_'//trim(excite)
3428 rst_unit = cp_print_key_unit_nr(logger, xas_tdp_section, "PRINT%RESTART", extension=".rst", &
3429 file_status="REPLACE", file_action="WRITE", &
3430 file_form="UNFORMATTED", middle_name=trim(my_middle))
3431
3432 filename = cp_print_key_generate_filename(logger, print_key, middle_name=trim(my_middle), &
3433 extension=".rst", my_local=.false.)
3434
3435 IF (output_unit > 0) THEN
3436 WRITE (unit=output_unit, fmt="(/,T5,A,/T5,A,A,A)") &
3437 "Linear-response orbitals and excitation energies are written in: ", &
3438 '"', trim(filename), '"'
3439 END IF
3440
3441 !Writing
3442 IF (rst_unit > 0) THEN
3443 WRITE (rst_unit) ex_atom, state_type, ndo_mo, ex_type
3444 WRITE (rst_unit) nao, nex, nspins
3445 WRITE (rst_unit) mo_indices(:, :)
3446 WRITE (rst_unit) lr_evals(:)
3447 END IF
3448 CALL cp_fm_write_unformatted(lr_coeffs, rst_unit)
3449
3450 !The MOs as well (because the may have been localized)
3451 CALL get_qs_env(qs_env, mos=mos)
3452 DO ispin = 1, nspins
3453 CALL cp_fm_write_unformatted(mos(ispin)%mo_coeff, rst_unit)
3454 END DO
3455
3456 !closing
3457 CALL cp_print_key_finished_output(rst_unit, logger, xas_tdp_section, "PRINT%RESTART")
3458
3459 CALL timestop(handle)
3460
3461 END SUBROUTINE write_donor_state_restart
3462
3463! **************************************************************************************************
3464!> \brief Reads donor_state info from a restart file
3465!> \param donor_state the pre-allocated donor_state
3466!> \param ex_type the excitations stored in this specific file
3467!> \param filename the restart file to read from
3468!> \param qs_env ...
3469! **************************************************************************************************
3470 SUBROUTINE read_donor_state_restart(donor_state, ex_type, filename, qs_env)
3471
3472 TYPE(donor_state_type), POINTER :: donor_state
3473 INTEGER, INTENT(OUT) :: ex_type
3474 CHARACTER(len=*), INTENT(IN) :: filename
3475 TYPE(qs_environment_type), POINTER :: qs_env
3476
3477 CHARACTER(len=*), PARAMETER :: routinen = 'read_donor_state_restart'
3478
3479 INTEGER :: handle, ispin, nao, nex, nspins, &
3480 output_unit, read_params(7), rst_unit
3481 INTEGER, DIMENSION(:, :), POINTER :: mo_indices
3482 LOGICAL :: file_exists
3483 REAL(dp), DIMENSION(:), POINTER :: lr_evals
3484 TYPE(cp_blacs_env_type), POINTER :: blacs_env
3485 TYPE(cp_fm_struct_type), POINTER :: fm_struct
3486 TYPE(cp_fm_type), POINTER :: lr_coeffs
3487 TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
3488 TYPE(mp_comm_type) :: group
3489 TYPE(mp_para_env_type), POINTER :: para_env
3490
3491 NULLIFY (lr_evals, lr_coeffs, para_env, fm_struct, blacs_env, mos)
3492
3493 CALL timeset(routinen, handle)
3494
3495 output_unit = cp_logger_get_default_io_unit()
3496 cpassert(ASSOCIATED(donor_state))
3497 CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
3498 group = para_env
3499
3500 file_exists = .false.
3501 rst_unit = -1
3502
3503 IF (para_env%is_source()) THEN
3504
3505 INQUIRE (file=filename, exist=file_exists)
3506 IF (.NOT. file_exists) cpabort("Trying to read non-existing XAS_TDP restart file")
3507
3508 CALL open_file(file_name=trim(filename), file_action="READ", file_form="UNFORMATTED", &
3509 file_position="REWIND", file_status="OLD", unit_number=rst_unit)
3510 END IF
3511
3512 IF (output_unit > 0) THEN
3513 WRITE (unit=output_unit, fmt="(/,T5,A,/,T5,A,A,A)") &
3514 "Reading linear-response orbitals and excitation energies from file: ", &
3515 '"', filename, '"'
3516 END IF
3517
3518 !read general params
3519 IF (rst_unit > 0) THEN
3520 READ (rst_unit) read_params(1:4)
3521 READ (rst_unit) read_params(5:7)
3522 END IF
3523 CALL group%bcast(read_params)
3524 donor_state%at_index = read_params(1)
3525 donor_state%state_type = read_params(2)
3526 donor_state%ndo_mo = read_params(3)
3527 ex_type = read_params(4)
3528 nao = read_params(5)
3529 nex = read_params(6)
3530 nspins = read_params(7)
3531
3532 ALLOCATE (mo_indices(donor_state%ndo_mo, nspins))
3533 IF (rst_unit > 0) THEN
3534 READ (rst_unit) mo_indices(1:donor_state%ndo_mo, 1:nspins)
3535 END IF
3536 CALL group%bcast(mo_indices)
3537 donor_state%mo_indices => mo_indices
3538
3539 !read evals
3540 ALLOCATE (lr_evals(nex))
3541 IF (rst_unit > 0) READ (rst_unit) lr_evals(1:nex)
3542 CALL group%bcast(lr_evals)
3543
3544 !read evecs
3545 CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
3546 nrow_global=nao, ncol_global=nex*donor_state%ndo_mo*nspins)
3547 ALLOCATE (lr_coeffs)
3548 CALL cp_fm_create(lr_coeffs, fm_struct)
3549 CALL cp_fm_read_unformatted(lr_coeffs, rst_unit)
3550 CALL cp_fm_struct_release(fm_struct)
3551
3552 !read MO coeffs and replace in qs_env
3553 CALL get_qs_env(qs_env, mos=mos)
3554 DO ispin = 1, nspins
3555 CALL cp_fm_read_unformatted(mos(ispin)%mo_coeff, rst_unit)
3556 END DO
3557
3558 !closing file
3559 IF (para_env%is_source()) THEN
3560 CALL close_file(unit_number=rst_unit)
3561 END IF
3562
3563 !case study on excitation type
3564 SELECT CASE (ex_type)
3565 CASE (tddfpt_spin_cons)
3566 donor_state%sc_evals => lr_evals
3567 donor_state%sc_coeffs => lr_coeffs
3568 CASE (tddfpt_spin_flip)
3569 donor_state%sf_evals => lr_evals
3570 donor_state%sf_coeffs => lr_coeffs
3571 CASE (tddfpt_singlet)
3572 donor_state%sg_evals => lr_evals
3573 donor_state%sg_coeffs => lr_coeffs
3574 CASE (tddfpt_triplet)
3575 donor_state%tp_evals => lr_evals
3576 donor_state%tp_coeffs => lr_coeffs
3577 END SELECT
3578
3579 CALL timestop(handle)
3580
3581 END SUBROUTINE read_donor_state_restart
3582
3583! **************************************************************************************************
3584!> \brief Checks whether this is a restart calculation and runs it if so
3585!> \param rst_filename the file to read for restart
3586!> \param xas_tdp_section ...
3587!> \param qs_env ...
3588! **************************************************************************************************
3589 SUBROUTINE restart_calculation(rst_filename, xas_tdp_section, qs_env)
3590
3591 CHARACTER(len=*), INTENT(IN) :: rst_filename
3592 TYPE(section_vals_type), POINTER :: xas_tdp_section
3593 TYPE(qs_environment_type), POINTER :: qs_env
3594
3595 INTEGER :: ex_type
3596 TYPE(donor_state_type), POINTER :: donor_state
3597 TYPE(xas_tdp_env_type), POINTER :: xas_tdp_env
3598
3599 NULLIFY (xas_tdp_env, donor_state)
3600
3601 !create a donor_state that we fill with the information we read
3602 ALLOCATE (donor_state)
3603 CALL donor_state_create(donor_state)
3604 CALL read_donor_state_restart(donor_state, ex_type, rst_filename, qs_env)
3605
3606 !create a dummy xas_tdp_env and compute the post XAS_TDP stuff
3607 CALL xas_tdp_env_create(xas_tdp_env)
3608 CALL xas_tdp_post(ex_type, donor_state, xas_tdp_env, xas_tdp_section, qs_env)
3609
3610 !clean-up
3611 CALL xas_tdp_env_release(xas_tdp_env)
3612 CALL free_ds_memory(donor_state)
3613 DEALLOCATE (donor_state%mo_indices)
3614 DEALLOCATE (donor_state)
3615
3616 END SUBROUTINE restart_calculation
3617
3618END MODULE xas_tdp_methods
static void dgemm(const char transa, const char transb, const int m, const int n, const int k, const double alpha, const double *a, const int lda, const double *b, const int ldb, const double beta, double *c, const int ldc)
Convenient wrapper to hide Fortran nature of dgemm_, swapping a and b.
Types and set/get functions for auxiliary density matrix methods.
Definition admm_types.F:15
Contains methods used in the context of density fitting.
Definition admm_utils.F:15
subroutine, public admm_uncorrect_for_eigenvalues(ispin, admm_env, ks_matrix)
...
Definition admm_utils.F:127
subroutine, public admm_correct_for_eigenvalues(ispin, admm_env, ks_matrix)
...
Definition admm_utils.F:53
Define the atomic kind types and their sub types.
subroutine, public get_atomic_kind(atomic_kind, fist_potential, element_symbol, name, mass, kind_number, natom, atom_list, rcov, rvdw, z, qeff, apol, cpol, mm_radius, shell, shell_active, damping)
Get attributes of an atomic kind.
subroutine, public get_gto_basis_set(gto_basis_set, name, aliases, norm_type, kind_radius, ncgf, nset, nsgf, cgf_symbol, sgf_symbol, norm_cgf, set_radius, lmax, lmin, lx, ly, lz, m, ncgf_set, npgf, nsgf_set, nshell, cphi, pgf_radius, sphi, scon, zet, first_cgf, first_sgf, l, last_cgf, last_sgf, n, gcc, maxco, maxl, maxpgf, maxsgf_set, maxshell, maxso, nco_sum, npgf_sum, nshell_sum, maxder, short_kind_radius, npgf_seg_sum)
...
subroutine, public deallocate_gto_basis_set(gto_basis_set)
...
pure real(dp) function, public srules(z, ne, n, l)
...
subroutine, public deallocate_sto_basis_set(sto_basis_set)
...
subroutine, public allocate_sto_basis_set(sto_basis_set)
...
subroutine, public create_gto_from_sto_basis(sto_basis_set, gto_basis_set, ngauss, ortho)
...
subroutine, public set_sto_basis_set(sto_basis_set, name, nshell, symbol, nq, lq, zet)
...
subroutine, public init_orb_basis_set(gto_basis_set)
Initialise a Gaussian-type orbital (GTO) basis set data set.
collects all references to literature in CP2K as new algorithms / method are included from literature...
integer, save, public bussy2021a
Handles all functions related to the CELL.
Definition cell_types.F:15
methods related to the blacs parallel environment
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
subroutine, public dbcsr_copy(matrix_b, matrix_a, name, keep_sparsity, keep_imaginary)
...
subroutine, public dbcsr_multiply(transa, transb, alpha, matrix_a, matrix_b, beta, matrix_c, first_row, last_row, first_column, last_column, first_k, last_k, retain_sparsity, filter_eps, flop)
...
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_filter(matrix, eps)
...
real(kind=dp) function, public dbcsr_get_occupation(matrix)
...
subroutine, public dbcsr_finalize(matrix)
...
subroutine, public dbcsr_set(matrix, alpha)
...
subroutine, public dbcsr_release(matrix)
...
subroutine, public dbcsr_complete_redistribute(matrix, redist)
...
subroutine, public dbcsr_add_on_diag(matrix, alpha)
Adds the given scalar to the diagonal of the matrix. Reserves any missing diagonal blocks.
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.
Utility routines to open and close files. Tracking of preconnections.
Definition cp_files.F:16
subroutine, public open_file(file_name, file_status, file_form, file_action, file_position, file_pad, unit_number, debug, skip_get_unit_number, file_access)
Opens the requested file using a free unit number.
Definition cp_files.F:308
subroutine, public close_file(unit_number, file_status, keep_preconnection)
Close an open file given by its logical unit number. Optionally, keep the file and unit preconnected.
Definition cp_files.F:119
Basic linear algebra operations for full matrices.
subroutine, public cp_fm_column_scale(matrixa, scaling)
scales column i of matrix a with scaling(i)
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_power(matrix, work, exponent, threshold, n_dependent, verbose, eigvals)
...
subroutine, public cp_fm_syevd(matrix, eigenvectors, eigenvalues, info)
Computes all eigenvalues and vectors of a real symmetric matrix significantly faster than syevx,...
Definition cp_fm_diag.F:412
subroutine, public cp_fm_geeig(amatrix, bmatrix, eigenvectors, eigenvalues, work)
General Eigenvalue Problem AX = BXE Single option version: Cholesky decomposition of B.
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_copy_general(source, destination, para_env)
General copy of a fm matrix to another fm matrix. Uses non-blocking MPI rather than ScaLAPACK.
subroutine, public cp_fm_get_diag(matrix, diag)
returns the diagonal elements of a fm
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_write_unformatted(fm, unit)
...
subroutine, public cp_fm_read_unformatted(fm, unit)
...
subroutine, public cp_fm_to_fm_submat(msource, mtarget, nrow, ncol, s_firstrow, s_firstcol, t_firstrow, t_firstcol)
copy just a part ot the matrix
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_get_submatrix(fm, target_m, start_row, start_col, n_rows, n_cols, transpose)
gets a submatrix of a full matrix op(target_m)(1:n_rows,1:n_cols) =fm(start_row:start_row+n_rows,...
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, parameter, public debug_print_level
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)
...
character(len=default_path_length) function, public cp_print_key_generate_filename(logger, print_key, middle_name, extension, my_local)
Utility function that returns a unit number to write the print key. Might open a file with a unique f...
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...
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public xas_1s_type
integer, parameter, public do_admm_purify_none
integer, parameter, public do_loc_none
integer, parameter, public op_loc_berry
integer, parameter, public xas_not_excited
integer, parameter, public tddfpt_singlet
integer, parameter, public xas_2p_type
integer, parameter, public xas_dip_len
integer, parameter, public xas_dip_vel
integer, parameter, public tddfpt_triplet
integer, parameter, public xas_2s_type
integer, parameter, public tddfpt_spin_flip
integer, parameter, public xas_tdp_by_kind
integer, parameter, public do_admm_purify_cauchy_subspace
integer, parameter, public state_loc_list
integer, parameter, public do_potential_truncated
integer, parameter, public do_potential_id
integer, parameter, public xas_tdp_by_index
integer, parameter, public do_potential_coulomb
integer, parameter, public do_admm_purify_mo_diag
integer, parameter, public do_potential_short
integer, parameter, public tddfpt_spin_cons
subroutine, public create_localize_section(section)
parameters fo the localization of wavefunctions
objects that represent the structure of input sections and the data contained in an input section
recursive subroutine, public section_vals_create(section_vals, section)
creates a object where to store the values of a section
subroutine, public section_vals_val_set(section_vals, keyword_name, i_rep_section, i_rep_val, val, l_val, i_val, r_val, c_val, l_vals_ptr, i_vals_ptr, r_vals_ptr, c_vals_ptr)
sets the requested value
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
recursive subroutine, public section_release(section)
releases the given keyword list (see doc/ReferenceCounting.html)
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
integer, parameter, public default_path_length
Definition kinds.F:58
Interface to the Libint-Library or a c++ wrapper.
subroutine, public cp_libint_static_init()
An array-based list which grows on demand. When the internal array is full, a new array of twice the ...
Definition list.F:24
Machine interface based on Fortran 2003 and POSIX.
Definition machine.F:17
subroutine, public m_flush(lunit)
flushes units if the &GLOBAL flag is set accordingly
Definition machine.F:131
Collection of simple mathematical functions and subroutines.
Definition mathlib.F:15
pure real(kind=dp) function, dimension(min(size(a, 1), size(a, 2))), public get_diag(a)
Return the diagonal elements of matrix a as a vector.
Definition mathlib.F:493
subroutine, public diag(n, a, d, v)
Diagonalize matrix a. The eigenvalues are returned in vector d and the eigenvectors are returned in m...
Definition mathlib.F:1496
Utility routines for the memory handling.
Interface to the message passing library MPI.
basic linear algebra operations for full matrixes
Parallel (pseudo)random number generator (RNG) for multiple streams and substreams of random numbers.
integer, parameter, public uniform
Define methods related to particle_type.
subroutine, public get_particle_set(particle_set, qs_kind_set, first_sgf, last_sgf, nsgf, nmao, basis)
Get the components of a particle set.
Define the data structure for the particle information.
Periodic Table related data definitions.
type(atom), dimension(0:nelem), public ptable
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public a_fine
Definition physcon.F:119
real(kind=dp), parameter, public evolt
Definition physcon.F:183
real(kind=dp), parameter, public angstrom
Definition physcon.F:144
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, 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, ecoul_1c, rho0_s_rs, rho0_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.
Calculate the interaction radii for the operator matrix calculation.
subroutine, public init_interaction_radii_orb_basis(orb_basis_set, eps_pgf_orb, eps_pgf_short)
...
Define the quickstep kind type and their sub types.
subroutine, public get_qs_kind(qs_kind, basis_set, basis_type, ncgf, nsgf, all_potential, tnadd_potential, gth_potential, sgp_potential, upf_potential, se_parameter, dftb_parameter, xtb_parameter, dftb3_param, zatom, zeff, elec_conf, mao, lmax_dftb, alpha_core_charge, ccore_charge, core_charge, core_charge_radius, paw_proj_set, paw_atom, hard_radius, hard0_radius, max_rad_local, covalent_radius, vdw_radius, gpw_type_forced, harmonics, max_iso_not0, max_s_harm, grid_atom, ngrid_ang, ngrid_rad, lmax_rho0, dft_plus_u_atom, l_of_dft_plus_u, n_of_dft_plus_u, u_minus_j, u_of_dft_plus_u, j_of_dft_plus_u, alpha_of_dft_plus_u, beta_of_dft_plus_u, j0_of_dft_plus_u, occupation_of_dft_plus_u, dispersion, bs_occupation, magnetization, no_optimize, addel, laddel, naddel, orbitals, max_scf, eps_scf, smear, u_ramping, u_minus_j_target, eps_u_ramping, init_u_ramping_each_scf, reltmat, ghost, floating, name, element_symbol, pao_basis_size, pao_model_file, pao_potentials, pao_descriptors, nelec)
Get attributes of an atomic kind.
Driver for the localization that should be general for all the methods available and all the definiti...
Definition qs_loc_main.F:22
subroutine, public qs_loc_driver(qs_env, qs_loc_env, print_loc_section, myspin, ext_mo_coeff)
set up the calculation of localized orbitals
Definition qs_loc_main.F:96
Driver for the localization that should be general for all the methods available and all the definiti...
subroutine, public centers_spreads_berry(qs_loc_env, zij, nmoloc, cell, weights, ispin, print_loc_section, only_initial_out)
...
subroutine, public qs_print_cubes(qs_env, mo_coeff, nstates, state_list, centers, print_key, root, ispin, idir, state0, file_position)
write the cube files for a set of selected states
New version of the module for the localization of the molecular orbitals This should be able to use d...
subroutine, public localized_wfn_control_create(localized_wfn_control)
create the localized_wfn_control_type
subroutine, public qs_loc_env_release(qs_loc_env)
...
subroutine, public get_qs_loc_env(qs_loc_env, cell, local_molecules, localized_wfn_control, moloc_coeff, op_sm_set, op_fm_set, para_env, particle_set, weights, dim_op)
...
subroutine, public qs_loc_env_create(qs_loc_env)
...
Some utilities for the construction of the localization environment.
subroutine, public qs_loc_env_init(qs_loc_env, localized_wfn_control, qs_env, myspin, do_localize, loc_coeff, mo_loc_history)
allocates the data, and initializes the operators
subroutine, public set_loc_centers(localized_wfn_control, nmoloc, nspins)
create the center and spread array and the file names for the output
subroutine, public qs_loc_control_init(qs_loc_env, loc_section, do_homo, do_mixed, do_xas, nloc_xas, spin_xas)
initializes everything needed for localization of the HOMOs
Definition and initialisation of the mo data type.
Definition qs_mo_io.F:21
subroutine, public write_mo_set_low(mo_array, qs_kind_set, particle_set, ires, rt_mos, matrix_ks)
...
Definition qs_mo_io.F:287
collects routines that perform operations directly related to MOs
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
subroutine, public duplicate_mo_set(mo_set_new, mo_set_old)
allocate a new mo_set, and copy the old data
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 ...
subroutine, public p_xyz_ao(op, qs_env, minimum_image)
Calculation of the components of the dipole operator in the velocity form The elements of the sparse ...
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 and writing of projected density of states The DOS is computed per angular momentum and p...
Definition qs_pdos.F:15
subroutine, public calculate_projected_dos(mo_set, atomic_kind_set, qs_kind_set, particle_set, qs_env, dft_section, ispin, xas_mittle, external_matrix_shalf)
Compute and write projected density of states.
Definition qs_pdos.F:139
superstucture that hold various representations of the density and keeps track of which ones are vali...
subroutine, public qs_rho_get(rho_struct, rho_ao, rho_ao_im, rho_ao_kp, rho_ao_im_kp, rho_r, drho_r, rho_g, drho_g, tau_r, tau_g, rho_r_valid, drho_r_valid, rho_g_valid, drho_g_valid, tau_r_valid, tau_g_valid, tot_rho_r, tot_rho_g, rho_r_sccs, soft_valid, complex_rho_ao)
returns info about the density described by this object. If some representation is not available an e...
module that contains the definitions of the scf types
integer, parameter, public ot_method_nr
Define Resonant Inelastic XRAY Scattering (RIXS) control type and associated create,...
Definition rixs_types.F:13
All kind of helpful little routines.
Definition util.F:14
pure integer function, public locate(array, x)
Purpose: Given an array array(1:n), and given a value x, a value x_index is returned which is the ind...
Definition util.F:61
pure integer function, dimension(2), public get_limit(m, n, me)
divide m entries into n parts, return size of part me
Definition util.F:333
driver for the xas calculation and xas_scf for the tp method
Definition xas_methods.F:15
subroutine, public calc_stogto_overlap(base_a, base_b, matrix)
...
This module deals with all the integrals done on local atomic grids in xas_tdp. This is mostly used t...
subroutine, public init_xas_atom_env(xas_atom_env, xas_tdp_env, xas_tdp_control, qs_env, ltddfpt)
Initializes a xas_atom_env type given the qs_enxas_atom_env, qs_envv.
subroutine, public integrate_soc_atoms(matrix_soc, xas_atom_env, qs_env, soc_atom_env)
Computes the SOC matrix elements with respect to the ORB basis set for each atomic kind and put them ...
subroutine, public integrate_fxc_atoms(int_fxc, xas_atom_env, xas_tdp_control, qs_env)
Integrate the xc kernel as a function of r on the atomic grids for the RI_XAS basis.
Second order perturbation correction to XAS_TDP spectra (i.e. shift)
subroutine, public gw2x_shift(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
Computes the ionization potential using the GW2X method of Shigeta et. al. The result cam be used for...
subroutine, public get_soc_splitting(soc_shifts, donor_state, xas_tdp_env, xas_tdp_control, qs_env)
We try to compute the spin-orbit splitting via perturbation theory. We keep it \ cheap by only inculd...
3-center integrals machinery for the XAS_TDP method
subroutine, public compute_ri_coulomb2_int(ex_kind, xas_tdp_env, xas_tdp_control, qs_env)
Computes the two-center Coulomb integral needed for the RI in kernel calculation. Stores the integral...
subroutine, public compute_ri_3c_coulomb(xas_tdp_env, qs_env)
Computes the RI Coulomb 3-center integrals (ab|c), where c is from the RI_XAS basis and centered on t...
subroutine, public compute_ri_exchange2_int(ex_kind, xas_tdp_env, xas_tdp_control, qs_env)
Computes the two-center Exchange integral needed for the RI in kernel calculation....
subroutine, public compute_ri_3c_exchange(ex_atoms, xas_tdp_env, xas_tdp_control, qs_env)
Computes the RI exchange 3-center integrals (ab|c), where c is from the RI_XAS basis and centered on ...
Methods for X-Ray absorption spectroscopy (XAS) using TDDFPT.
subroutine, public xas_tdp_init(xas_tdp_env, xas_tdp_control, qs_env, rixs_env)
Overall control and environment types initialization.
subroutine, public xas_tdp(qs_env, rixs_env)
Driver for XAS TDDFT calculations.
Define XAS TDP control type and associated create, release, etc subroutines, as well as XAS TDP envir...
subroutine, public xas_tdp_env_create(xas_tdp_env)
Creates a TDP XAS environment type.
subroutine, public xas_tdp_env_release(xas_tdp_env)
Releases the TDP XAS environment type.
subroutine, public donor_state_create(donor_state)
Creates a donor_state.
subroutine, public xas_tdp_control_release(xas_tdp_control)
Releases the xas_tdp_control_type.
subroutine, public xas_atom_env_create(xas_atom_env)
Creates a xas_atom_env type.
subroutine, public set_xas_tdp_env(xas_tdp_env, nex_atoms, nex_kinds)
Sets values of selected variables within the TDP XAS environment type.
subroutine, public free_ds_memory(donor_state)
Deallocate a donor_state's heavy attributes.
subroutine, public set_donor_state(donor_state, at_index, at_symbol, kind_index, state_type)
sets specified values of the donor state type
subroutine, public xas_tdp_control_create(xas_tdp_control)
Creates and initializes the xas_tdp_control_type.
subroutine, public free_exat_memory(xas_tdp_env, atom, end_of_batch)
Releases the memory heavy attribute of xas_tdp_env that are specific to the current excited atom.
subroutine, public xas_atom_env_release(xas_atom_env)
Releases the xas_atom_env type.
subroutine, public read_xas_tdp_control(xas_tdp_control, xas_tdp_section)
Reads the inputs and stores in xas_tdp_control_type.
Utilities for X-ray absorption spectroscopy using TDDFPT.
subroutine, public include_rcs_soc(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
Includes the SOC effects on the precomputed restricted closed-shell singlet and triplet excitations....
subroutine, public setup_xas_tdp_prob(donor_state, qs_env, xas_tdp_env, xas_tdp_control)
Builds the matrix that defines the XAS TDDFPT generalized eigenvalue problem to be solved for excitat...
subroutine, public solve_xas_tdp_prob(donor_state, xas_tdp_control, xas_tdp_env, qs_env, ex_type)
Solves the XAS TDP generalized eigenvalue problem omega*C = matrix_tdp*C using standard full diagonal...
subroutine, public include_os_soc(donor_state, xas_tdp_env, xas_tdp_control, qs_env)
Includes the SOC effects on the precomputed spin-conserving and spin-flip excitations from an open-sh...
Writes information on XC functionals to output.
subroutine, public xc_write(iounit, xc_section, lsd)
...
stores some data used in wavefunction fitting
Definition admm_types.F:120
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...
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...
represent a section of the input file
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.
A type that holds controlling information for the calculation of the spread of wfn and the optimizati...
contains all the info needed by quickstep to calculate the spread of a selected set of orbitals and i...
keeps the density in various representations, keeping track of which ones are valid.
Type containing informations about a single donor state.
a environment type that contains all the info needed for XAS_TDP atomic grid calculations
Type containing control information for TDP XAS calculations.
Type containing informations such as inputs and results for TDP XAS calculations.