Line data Source code
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 : MODULE qs_tddfpt2_soc
8 : USE basis_set_types, ONLY: get_gto_basis_set,&
9 : gto_basis_set_type
10 : USE cp_blacs_env, ONLY: cp_blacs_env_type
11 : USE cp_cfm_diag, ONLY: cp_cfm_heevd
12 : USE cp_cfm_types, ONLY: cp_cfm_create,&
13 : cp_cfm_get_info,&
14 : cp_cfm_get_submatrix,&
15 : cp_cfm_release,&
16 : cp_cfm_type,&
17 : cp_fm_to_cfm
18 : USE cp_control_types, ONLY: dft_control_type,&
19 : qs_control_type,&
20 : tddfpt2_control_type
21 : USE cp_dbcsr_api, ONLY: &
22 : dbcsr_copy, dbcsr_create, dbcsr_distribution_get, dbcsr_distribution_new, &
23 : dbcsr_distribution_release, dbcsr_distribution_type, dbcsr_get_info, dbcsr_multiply, &
24 : dbcsr_p_type, dbcsr_release, dbcsr_scale, dbcsr_type, dbcsr_type_no_symmetry
25 : USE cp_dbcsr_contrib, ONLY: dbcsr_print,&
26 : dbcsr_reserve_all_blocks
27 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
28 : copy_fm_to_dbcsr,&
29 : cp_dbcsr_sm_fm_multiply
30 : USE cp_fm_basic_linalg, ONLY: cp_fm_scale,&
31 : cp_fm_transpose,&
32 : cp_fm_uplo_to_full
33 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
34 : cp_fm_struct_release,&
35 : cp_fm_struct_type
36 : USE cp_fm_types, ONLY: &
37 : cp_fm_create, cp_fm_get_diag, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, &
38 : cp_fm_set_all, cp_fm_set_element, cp_fm_to_fm_submat, cp_fm_type
39 : USE cp_log_handling, ONLY: cp_get_default_logger,&
40 : cp_logger_get_default_unit_nr,&
41 : cp_logger_type
42 : USE cp_output_handling, ONLY: cp_print_key_unit_nr
43 : USE input_constants, ONLY: tddfpt_dipole_length
44 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
45 : section_vals_type,&
46 : section_vals_val_get
47 : USE kinds, ONLY: default_string_length,&
48 : dp
49 : USE lebedev, ONLY: deallocate_lebedev_grids,&
50 : get_number_of_lebedev_grid,&
51 : init_lebedev_grids,&
52 : lebedev_grid
53 : USE mathlib, ONLY: get_diag
54 : USE memory_utilities, ONLY: reallocate
55 : USE message_passing, ONLY: mp_para_env_type
56 : USE orbital_pointers, ONLY: indso,&
57 : nsoset
58 : USE parallel_gemm_api, ONLY: parallel_gemm
59 : USE particle_types, ONLY: particle_type
60 : USE physcon, ONLY: evolt,&
61 : wavenumbers
62 : USE qs_environment_types, ONLY: get_qs_env,&
63 : qs_environment_type
64 : USE qs_grid_atom, ONLY: allocate_grid_atom,&
65 : create_grid_atom,&
66 : grid_atom_type
67 : USE qs_harmonics_atom, ONLY: allocate_harmonics_atom,&
68 : create_harmonics_atom,&
69 : get_maxl_CG,&
70 : harmonics_atom_type
71 : USE qs_kind_types, ONLY: get_qs_kind,&
72 : get_qs_kind_set,&
73 : qs_kind_type
74 : USE qs_mo_types, ONLY: mo_set_type
75 : USE qs_tddfpt2_soc_types, ONLY: soc_atom_create,&
76 : soc_atom_env_type,&
77 : soc_atom_release,&
78 : soc_env_create,&
79 : soc_env_release,&
80 : soc_env_type
81 : USE qs_tddfpt2_soc_utils, ONLY: dip_vel_op,&
82 : resort_evects,&
83 : soc_contract_evect,&
84 : soc_dipole_operator
85 : USE qs_tddfpt2_types, ONLY: tddfpt_ground_state_mos
86 : USE soc_pseudopotential_methods, ONLY: V_SOC_xyz_from_pseudopotential
87 : USE spherical_harmonics, ONLY: clebsch_gordon,&
88 : clebsch_gordon_deallocate,&
89 : clebsch_gordon_init
90 : USE xas_tdp_atom, ONLY: compute_sphi_so,&
91 : integrate_soc_atoms,&
92 : truncate_radial_grid
93 : USE xas_tdp_utils, ONLY: rcs_amew_soc_elements
94 : #include "./base/base_uses.f90"
95 :
96 : IMPLICIT NONE
97 :
98 : PRIVATE
99 :
100 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt2_soc'
101 :
102 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
103 :
104 : INTEGER, PARAMETER, PRIVATE :: nderivs = 3
105 : INTEGER, PARAMETER, PRIVATE :: maxspins = 2
106 :
107 : !A helper type for SOC
108 : TYPE dbcsr_soc_package_type
109 : TYPE(dbcsr_type), POINTER :: dbcsr_sg => Null()
110 : TYPE(dbcsr_type), POINTER :: dbcsr_tp => Null()
111 : TYPE(dbcsr_type), POINTER :: dbcsr_sc => Null()
112 : TYPE(dbcsr_type), POINTER :: dbcsr_sf => Null()
113 : TYPE(dbcsr_type), POINTER :: dbcsr_prod => Null()
114 : TYPE(dbcsr_type), POINTER :: dbcsr_ovlp => Null()
115 : TYPE(dbcsr_type), POINTER :: dbcsr_tmp => Null()
116 : TYPE(dbcsr_type), POINTER :: dbcsr_work => Null()
117 : END TYPE dbcsr_soc_package_type
118 :
119 : PUBLIC :: tddfpt_soc
120 :
121 : ! **************************************************************************************************
122 :
123 : CONTAINS
124 :
125 : ! **************************************************************************************************
126 : !> \brief Perform TDDFPT-SOC calculation.
127 : !> \param qs_env Quickstep environment
128 : !> \param evals_a eigenvalues for the singlet states
129 : !> \param evals_b eigenvalues for the triplet states
130 : !> \param evects_a eigenvectors for the singlet states
131 : !> \param evects_b eigenvectors for the triplet states
132 : !> \param gs_mos ground state orbitlas from the TDDFPT calculation
133 : !> \par History
134 : !> * 02.2023 created [Jan-Robert Vogt]
135 : !> \note Based on tddfpt2_methods and xas_tdp_utils.
136 : !> \note Only rcs for now, but written with the addition of os in mind
137 : ! **************************************************************************************************
138 :
139 10 : SUBROUTINE tddfpt_soc(qs_env, evals_a, evals_b, evects_a, evects_b, gs_mos)
140 :
141 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
142 : REAL(kind=dp), DIMENSION(:), INTENT(IN) :: evals_a, evals_b
143 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects_a, evects_b
144 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
145 : POINTER :: gs_mos
146 :
147 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_soc'
148 :
149 : INTEGER :: handle, istate, log_unit
150 : LOGICAL :: do_os
151 : TYPE(cp_logger_type), POINTER :: logger
152 : TYPE(dft_control_type), POINTER :: dft_control
153 :
154 10 : CALL timeset(routineN, handle)
155 :
156 10 : logger => cp_get_default_logger()
157 10 : IF (logger%para_env%is_source()) THEN
158 5 : log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
159 : ELSE
160 5 : log_unit = -1
161 : END IF
162 :
163 10 : IF (log_unit > 0) THEN
164 5 : WRITE (log_unit, "(1X,A)") "", &
165 5 : "-------------------------------------------------------------------------------", &
166 5 : "- START SOC CALCULATIONS -", &
167 10 : "-------------------------------------------------------------------------------"
168 : END IF
169 :
170 10 : NULLIFY (dft_control)
171 10 : CALL get_qs_env(qs_env, dft_control=dft_control)
172 10 : do_os = dft_control%uks .OR. dft_control%roks
173 0 : IF (do_os) CPABORT("SOC only implemented for closed shell.")
174 :
175 10 : IF (log_unit > 0) THEN
176 5 : WRITE (log_unit, '(A)') " Starting from TDDFPT Excited States:"
177 5 : WRITE (log_unit, '(A)') " STATE SINGLET/eV TRIPLET/eV"
178 19 : DO istate = 1, SIZE(evals_a)
179 19 : WRITE (log_unit, '(6X,I3,11X,F10.5,6X,F10.5)') istate, evals_a(istate)*evolt, evals_b(istate)*evolt
180 : END DO
181 : END IF
182 :
183 10 : IF (log_unit > 0) WRITE (log_unit, '(A)') " Starting restricted closed shell:"
184 10 : CALL tddfpt_soc_rcs(qs_env, evals_a, evals_b, evects_a, evects_b, log_unit, gs_mos)
185 :
186 10 : IF (log_unit > 0) THEN
187 5 : WRITE (log_unit, '(A,/,A)') "SOC Calculation terminated", &
188 10 : "Returning to TDDFPT for Force calculation and deallocations"
189 : END IF
190 :
191 10 : CALL timestop(handle)
192 :
193 10 : END SUBROUTINE tddfpt_soc
194 :
195 : ! **************************************************************************************************
196 : !> \brief Will perform the soc-calculation for restricted-closed-shell systems
197 : !> \param qs_env Quickstep Enviroment
198 : !> \param evals_sing eigenvalues singlet states
199 : !> \param evals_trip eigenvalues triplet states
200 : !> \param evects_sing eigenvector singlet states
201 : !> \param evects_trip eigenvectors triplet states
202 : !> \param log_unit default log_unit for convinients
203 : !> \param gs_mos ground state MOs from TDDFPT
204 : !> \par History
205 : !> * created 02.2023 [Jan-Robert Vogt]
206 : !> \note Mostly copied and modified from xas_tdp_utils include_rcs_soc
207 : ! **************************************************************************************************
208 10 : SUBROUTINE tddfpt_soc_rcs(qs_env, evals_sing, evals_trip, evects_sing, evects_trip, log_unit, gs_mos)
209 :
210 : TYPE(qs_environment_type), POINTER :: qs_env
211 : REAL(kind=dp), DIMENSION(:), INTENT(IN), TARGET :: evals_sing, evals_trip
212 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects_sing, evects_trip
213 : INTEGER :: log_unit
214 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
215 : POINTER :: gs_mos
216 :
217 : CHARACTER(LEN=*), PARAMETER :: routineN = 'tddfpt_soc_rcs'
218 :
219 : CHARACTER(len=3) :: mult
220 : INTEGER :: dipole_form, group, handle, iex, ii, &
221 : isg, istate, itp, jj, nactive, nao, &
222 : nex, npcols, nprows, nsg, ntot, ntp
223 10 : INTEGER, ALLOCATABLE, DIMENSION(:) :: evects_sort
224 10 : INTEGER, DIMENSION(:), POINTER :: col_blk_size, col_dist, row_blk_size, &
225 10 : row_dist, row_dist_new
226 10 : INTEGER, DIMENSION(:, :), POINTER :: pgrid
227 : LOGICAL :: print_ev, print_some, print_splitting, &
228 : print_wn
229 : REAL(dp) :: eps_filter, soc_gst, sqrt2, unit_scale
230 10 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: diag, tmp_evals
231 10 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: img_tmp, real_tmp
232 10 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: gstp_block, mo_soc_x, mo_soc_y, mo_soc_z
233 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
234 : TYPE(cp_cfm_type) :: evecs_cfm, hami_cfm
235 : TYPE(cp_fm_struct_type), POINTER :: full_struct, gstp_struct, prod_struct, &
236 : vec_struct, work_struct
237 : TYPE(cp_fm_type) :: gstp_fm, img_fm, prod_fm, real_fm, &
238 : tmp_fm, vec_soc_x, vec_soc_y, &
239 : vec_soc_z, work_fm
240 : TYPE(cp_fm_type), POINTER :: gs_coeffs, tp_coeffs
241 : TYPE(cp_logger_type), POINTER :: logger
242 : TYPE(dbcsr_distribution_type), POINTER :: coeffs_dist, dbcsr_dist, prod_dist
243 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
244 : TYPE(dbcsr_soc_package_type) :: dbcsr_soc_package
245 : TYPE(dbcsr_type), POINTER :: dbcsr_dummy, dbcsr_ovlp, dbcsr_prod, &
246 : dbcsr_sg, dbcsr_tmp, dbcsr_tp, &
247 : dbcsr_work, orb_soc_x, orb_soc_y, &
248 : orb_soc_z
249 : TYPE(mp_para_env_type), POINTER :: para_env
250 : TYPE(section_vals_type), POINTER :: soc_print_section, soc_section, &
251 : tddfpt_print_section
252 : TYPE(soc_atom_env_type), POINTER :: soc_atom_env
253 10 : TYPE(soc_env_type), TARGET :: soc_env
254 :
255 10 : CALL timeset(routineN, handle)
256 :
257 10 : NULLIFY (logger, pgrid, row_dist, row_dist_new)
258 10 : NULLIFY (col_dist, col_blk_size, row_blk_size, matrix_s)
259 10 : NULLIFY (gstp_struct, tddfpt_print_section, soc_print_section, soc_section)
260 :
261 10 : logger => cp_get_default_logger()
262 10 : tddfpt_print_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%PRINT")
263 10 : soc_print_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%PRINT%SOC_PRINT")
264 10 : soc_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%SOC")
265 :
266 10 : CALL section_vals_val_get(soc_section, "EPS_FILTER", r_val=eps_filter)
267 :
268 10 : nsg = SIZE(evals_sing) ! Number of excited singlet states
269 10 : ntp = SIZE(evals_trip) ! Number of excited triplet states
270 10 : nex = nsg ! Number of excited states of each multiplicity
271 10 : ntot = 1 + nsg + 3*ntp ! Number of (GS + S + T^-1 + T^0 + T^1)
272 :
273 : ! Initzialize Working environment
274 : CALL inititialize_soc(qs_env, soc_atom_env, soc_env, &
275 10 : evects_sing, evects_trip, dipole_form, gs_mos)
276 :
277 10 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
278 10 : nactive = gs_mos(1)%nmo_active
279 10 : CALL cp_fm_get_info(gs_mos(1)%mos_active, nrow_global=nao)
280 :
281 : ! this will create the H^SOC in an atomic basis
282 10 : CALL integrate_soc_atoms(soc_env%orb_soc, qs_env=qs_env, soc_atom_env=soc_atom_env)
283 10 : CALL soc_atom_release(soc_atom_env)
284 :
285 : !! Point at H^SOC and MOs for better readablity
286 10 : NULLIFY (tp_coeffs, orb_soc_x, orb_soc_y, orb_soc_z)
287 10 : tp_coeffs => soc_env%b_coeff
288 10 : soc_env%evals_a => evals_sing
289 10 : soc_env%evals_b => evals_trip
290 10 : orb_soc_x => soc_env%orb_soc(1)%matrix
291 10 : orb_soc_y => soc_env%orb_soc(2)%matrix
292 10 : orb_soc_z => soc_env%orb_soc(3)%matrix
293 :
294 : !! Create a matrix-structure, which links all states in this calculation
295 10 : NULLIFY (full_struct)
296 10 : CALL cp_fm_struct_create(full_struct, context=blacs_env, para_env=para_env, nrow_global=ntot, ncol_global=ntot)
297 10 : CALL cp_fm_create(real_fm, full_struct)
298 10 : CALL cp_fm_create(img_fm, full_struct)
299 10 : CALL cp_fm_set_all(real_fm, 0.0_dp)
300 10 : CALL cp_fm_set_all(img_fm, 0.0_dp)
301 :
302 : ! Put the excitation energies on the diagonal of the real matrix
303 38 : DO isg = 1, nsg
304 38 : CALL cp_fm_set_element(real_fm, 1 + isg, 1 + isg, evals_sing(isg))
305 : END DO
306 38 : DO itp = 1, ntp
307 : ! first T^-1, then T^0, then T^+1
308 28 : CALL cp_fm_set_element(real_fm, 1 + itp + nsg, 1 + itp + nsg, evals_trip(itp))
309 28 : CALL cp_fm_set_element(real_fm, 1 + itp + ntp + nsg, 1 + itp + ntp + nsg, evals_trip(itp))
310 38 : CALL cp_fm_set_element(real_fm, 1 + itp + 2*ntp + nsg, 1 + itp + 2*ntp + nsg, evals_trip(itp))
311 : END DO
312 :
313 : !!Create the dbcsr structures for this calculations
314 10 : CALL get_qs_env(qs_env, dbcsr_dist=dbcsr_dist)
315 : CALL dbcsr_distribution_get(dbcsr_dist, group=group, row_dist=row_dist, pgrid=pgrid, &
316 10 : npcols=npcols, nprows=nprows)
317 40 : ALLOCATE (col_dist(nex), row_dist_new(nex)) ! Split for each excitation
318 38 : DO iex = 1, nex
319 28 : col_dist(iex) = MODULO(npcols - iex, npcols)
320 38 : row_dist_new(iex) = MODULO(nprows - iex, nprows)
321 : END DO
322 10 : ALLOCATE (coeffs_dist, prod_dist)
323 : CALL dbcsr_distribution_new(coeffs_dist, group=group, pgrid=pgrid, row_dist=row_dist, &
324 10 : col_dist=col_dist)
325 : CALL dbcsr_distribution_new(prod_dist, group=group, pgrid=pgrid, row_dist=row_dist_new, &
326 10 : col_dist=col_dist)
327 :
328 : !! Create the matrices
329 20 : ALLOCATE (col_blk_size(nex))
330 38 : col_blk_size = nactive
331 :
332 10 : CALL get_qs_env(qs_env, matrix_s=matrix_s)
333 10 : CALL dbcsr_get_info(matrix_s(1)%matrix, row_blk_size=row_blk_size)
334 :
335 : !! The Eigenvectors for Sg und Tp will be dived into their diffrent components again
336 10 : ALLOCATE (dbcsr_sg, dbcsr_tp, dbcsr_work, dbcsr_ovlp, dbcsr_tmp, dbcsr_prod)
337 : CALL dbcsr_create(matrix=dbcsr_sg, name="SINGLETS", matrix_type=dbcsr_type_no_symmetry, &
338 10 : dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
339 : CALL dbcsr_create(matrix=dbcsr_tp, name="TRIPLETS", matrix_type=dbcsr_type_no_symmetry, &
340 10 : dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
341 : CALL dbcsr_create(matrix=dbcsr_work, name="WORK", matrix_type=dbcsr_type_no_symmetry, &
342 10 : dist=coeffs_dist, row_blk_size=row_blk_size, col_blk_size=col_blk_size)
343 : CALL dbcsr_create(matrix=dbcsr_prod, name="PROD", matrix_type=dbcsr_type_no_symmetry, &
344 10 : dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
345 : CALL dbcsr_create(matrix=dbcsr_ovlp, name="OVLP", matrix_type=dbcsr_type_no_symmetry, &
346 10 : dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
347 :
348 38 : col_blk_size = 1
349 : CALL dbcsr_create(matrix=dbcsr_tmp, name="TMP", matrix_type=dbcsr_type_no_symmetry, &
350 10 : dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
351 10 : CALL dbcsr_reserve_all_blocks(dbcsr_tmp)
352 :
353 : IF (debug_this_module) THEN
354 : ALLOCATE (dbcsr_dummy)
355 : CALL dbcsr_create(matrix=dbcsr_dummy, name="DUMMY", matrix_type=dbcsr_type_no_symmetry, &
356 : dist=prod_dist, row_blk_size=col_blk_size, col_blk_size=col_blk_size)
357 : CALL dbcsr_reserve_all_blocks(dbcsr_dummy)
358 : END IF
359 :
360 : !! This work dbcsr matrix will be packed together for easy transfer to other subroutines
361 10 : dbcsr_soc_package%dbcsr_sg => dbcsr_sg
362 10 : dbcsr_soc_package%dbcsr_tp => dbcsr_tp
363 10 : dbcsr_soc_package%dbcsr_work => dbcsr_work
364 10 : dbcsr_soc_package%dbcsr_ovlp => dbcsr_ovlp
365 10 : dbcsr_soc_package%dbcsr_prod => dbcsr_prod
366 10 : dbcsr_soc_package%dbcsr_tmp => dbcsr_tmp
367 :
368 : !Filling the coeffs matrices by copying from the stored fms
369 10 : CALL copy_fm_to_dbcsr(soc_env%a_coeff, dbcsr_sg)
370 10 : CALL copy_fm_to_dbcsr(soc_env%b_coeff, dbcsr_tp)
371 :
372 : !Create the work and helper fms
373 10 : gs_coeffs => gs_mos(1)%mos_active
374 10 : CALL cp_fm_get_info(gs_coeffs, matrix_struct=vec_struct)
375 10 : CALL cp_fm_create(vec_soc_x, vec_struct)
376 10 : CALL cp_fm_create(vec_soc_y, vec_struct)
377 10 : CALL cp_fm_create(vec_soc_z, vec_struct)
378 :
379 : CALL cp_fm_struct_create(prod_struct, context=blacs_env, para_env=para_env, &
380 10 : nrow_global=nactive, ncol_global=nactive)
381 10 : CALL cp_fm_create(prod_fm, prod_struct)
382 :
383 : CALL cp_fm_struct_create(work_struct, context=blacs_env, para_env=para_env, &
384 10 : nrow_global=nex, ncol_global=nex)
385 10 : CALL cp_fm_create(work_fm, work_struct)
386 10 : CALL cp_fm_create(tmp_fm, work_struct)
387 :
388 : IF (log_unit > 0 .AND. debug_this_module) THEN
389 : WRITE (log_unit, '(A)') "Starting Precomputations"
390 : END IF
391 :
392 : !! Begin with the precomputation
393 : !! Prefactor due to rcs.
394 : !! The excitation is presented as a linear combination of
395 : !! alpha and beta, where dalpha=-dbeta for triplet exc.
396 : !! and dalpha=dbeta for the singlet case
397 10 : sqrt2 = SQRT(2.0_dp)
398 :
399 : !! Precompute the <phi_i^0|H^SOC|phi_j^0> matrix elements
400 30 : ALLOCATE (diag(nactive))
401 80 : ALLOCATE (mo_soc_x(nactive, nactive), mo_soc_y(nactive, nactive), mo_soc_z(nactive, nactive))
402 :
403 : !! This will be the GS|H|GS contribution needed for all couplings
404 10 : CALL cp_dbcsr_sm_fm_multiply(orb_soc_x, gs_coeffs, vec_soc_x, ncol=nactive)
405 : CALL parallel_gemm('T', 'N', nactive, &
406 : nactive, nao, 1.0_dp, &
407 : gs_coeffs, vec_soc_x, &
408 10 : 0.0_dp, prod_fm)
409 10 : CALL cp_fm_get_submatrix(prod_fm, mo_soc_x)
410 :
411 10 : CALL cp_dbcsr_sm_fm_multiply(orb_soc_y, gs_coeffs, vec_soc_y, ncol=nactive)
412 : CALL parallel_gemm('T', 'N', nactive, &
413 : nactive, nao, 1.0_dp, &
414 : gs_coeffs, vec_soc_y, &
415 10 : 0.0_dp, prod_fm)
416 10 : CALL cp_fm_get_submatrix(prod_fm, mo_soc_y)
417 :
418 10 : CALL cp_dbcsr_sm_fm_multiply(orb_soc_z, gs_coeffs, vec_soc_z, ncol=nactive)
419 : CALL parallel_gemm('T', 'N', nactive, &
420 : nactive, nao, 1.0_dp, &
421 : gs_coeffs, vec_soc_z, &
422 10 : 0.0_dp, prod_fm)
423 10 : CALL cp_fm_get_submatrix(prod_fm, mo_soc_z)
424 :
425 : ! Only have SOC between singlet-triplet triplet-triplet and ground_state-triplet, the resulting
426 : ! matrix is Hermitian i.e. the real part is symmetric and the imaginary part is anti-symmetric.
427 : ! Can only fill upper half
428 : IF (log_unit > 0 .AND. debug_this_module) THEN
429 : WRITE (log_unit, '(A)') "Starting Ground-State contributions..."
430 : END IF
431 : !Start with the ground state/triplet SOC, SOC*gs_coeffs already computed above
432 : !note: we are computing <0|H|T>, but have SOC*gs_coeffs instead of gs_coeffs*SOC in store.
433 : !Since the SOC Hamiltonian is anti-symmetric, a - signs pops up in the gemms below
434 : CALL cp_fm_struct_create(gstp_struct, context=blacs_env, para_env=para_env, &
435 10 : nrow_global=ntp*nactive, ncol_global=nactive)
436 10 : CALL cp_fm_create(gstp_fm, gstp_struct)
437 30 : ALLOCATE (gstp_block(nactive, nactive))
438 :
439 : !gs-triplet with Ms=+-1, imaginary part
440 : ! <T+-1|H_x|GS>
441 : ! -1 to change to <GS|H|T+-1>
442 : CALL parallel_gemm('T', 'N', nactive*ntp, &
443 : nactive, nao, -1.0_dp, &
444 : tp_coeffs, vec_soc_x, &
445 10 : 0.0_dp, gstp_fm)
446 :
447 : !! Seperate them into the different states again (nactive x nactive)
448 38 : DO itp = 1, ntp
449 : CALL cp_fm_get_submatrix(fm=gstp_fm, target_m=gstp_block, &
450 : start_row=(itp - 1)*nactive + 1, start_col=1, &
451 28 : n_rows=nactive, n_cols=nactive)
452 28 : diag(:) = get_diag(gstp_block)
453 200 : soc_gst = SUM(diag)
454 : !! <0|H_x|T^-1>
455 28 : CALL cp_fm_set_element(img_fm, 1, 1 + nsg + itp, -1_dp*soc_gst)
456 : !! <0|H_x|T^+1>
457 38 : CALL cp_fm_set_element(img_fm, 1, 1 + nsg + 2*ntp + itp, soc_gst)
458 : END DO
459 :
460 : IF (debug_this_module .AND. (log_unit > 0)) THEN
461 : WRITE (log_unit, "(A,2F18.6)") "<0|H_x|T^-1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
462 : WRITE (log_unit, "(A,2F18.6)") "<0|H_x|T^+1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
463 : END IF
464 :
465 : !gs-triplet with Ms=+-1, real part
466 : ! <T+-1|H_y|GS>
467 : CALL parallel_gemm('T', 'N', nactive*ntp, &
468 : nactive, nao, -1.0_dp, &
469 : tp_coeffs, vec_soc_y, &
470 10 : 0.0_dp, gstp_fm)
471 :
472 38 : DO itp = 1, ntp
473 : CALL cp_fm_get_submatrix(fm=gstp_fm, target_m=gstp_block, start_row=(itp - 1)*nactive + 1, &
474 28 : start_col=1, n_rows=nactive, n_cols=nactive)
475 28 : diag(:) = get_diag(gstp_block)
476 200 : soc_gst = SUM(diag)
477 : ! <0|H_y|T^-1>
478 28 : CALL cp_fm_set_element(real_fm, 1, 1 + nsg + itp, -1.0_dp*soc_gst)
479 : ! <0|H_y|T^+1>
480 38 : CALL cp_fm_set_element(real_fm, 1, 1 + nsg + 2*ntp + itp, -1.0_dp*soc_gst)
481 : END DO
482 :
483 : IF (debug_this_module .AND. (log_unit > 0)) THEN
484 : WRITE (log_unit, "(A,2F18.6)") "<0|H_y|T^-1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
485 : WRITE (log_unit, "(A,2F18.6)") "<0|H_y|T^+1> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
486 : END IF
487 :
488 : !gs-triplet with Ms=0, purely imaginary
489 : !< T0|H_z|GS>
490 : CALL parallel_gemm('T', 'N', nactive*ntp, &
491 : nactive, nao, -1.0_dp, &
492 : tp_coeffs, vec_soc_z, &
493 10 : 0.0_dp, gstp_fm)
494 :
495 38 : DO itp = 1, ntp
496 : CALL cp_fm_get_submatrix(fm=gstp_fm, &
497 : target_m=gstp_block, &
498 : start_row=(itp - 1)*nactive + 1, &
499 : start_col=1, &
500 : n_rows=nactive, &
501 28 : n_cols=nactive)
502 28 : diag(:) = get_diag(gstp_block)
503 200 : soc_gst = sqrt2*SUM(diag)
504 38 : CALL cp_fm_set_element(img_fm, 1, 1 + nsg + ntp + itp, soc_gst)
505 : END DO
506 :
507 : IF (debug_this_module .AND. (log_unit > 0)) THEN
508 : WRITE (log_unit, "(A,2F18.6)") "<0|H_z|T> in Hartree / cm^-1", soc_gst, soc_gst*wavenumbers
509 : END IF
510 :
511 : !! After all::
512 : !! T-1 :: -<0|H_x|T^-1> - <0|H_y|T^-1> at 1+nsg+itp
513 : !! T+1 :: <0|H_x|T^-1> - <0|H_y|T^-1> at 1+nsp+2tnp+itp
514 : !! T0 :: < T0|H_z|GS> at 1+nsg+ntp+itp
515 :
516 : !gs clean-up
517 10 : CALL cp_fm_release(prod_fm)
518 10 : CALL cp_fm_release(vec_soc_x)
519 10 : CALL cp_fm_release(vec_soc_y)
520 10 : CALL cp_fm_release(vec_soc_z)
521 10 : CALL cp_fm_release(gstp_fm)
522 10 : CALL cp_fm_struct_release(gstp_struct)
523 10 : CALL cp_fm_struct_release(prod_struct)
524 10 : DEALLOCATE (gstp_block)
525 :
526 : IF (log_unit > 0 .AND. debug_this_module) THEN
527 : WRITE (log_unit, '(A)') "Starting Singlet-Triplet contributions..."
528 : END IF
529 :
530 : !Now do the singlet-triplet SOC
531 : !start by computing the singlet-triplet overlap
532 : ! <S|T>
533 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
534 : matrix_s(1)%matrix, &
535 : dbcsr_tp, 0.0_dp, &
536 : dbcsr_work, &
537 10 : filter_eps=eps_filter)
538 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
539 : dbcsr_sg, &
540 : dbcsr_work, &
541 : 0.0_dp, dbcsr_ovlp, &
542 10 : filter_eps=eps_filter)
543 :
544 : !singlet-triplet with Ms=+-1, imaginary part
545 : ! First precalculate <S|H_x|T+-1>
546 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
547 : orb_soc_x, &
548 : dbcsr_tp, 0.0_dp, &
549 : dbcsr_work, &
550 10 : filter_eps=eps_filter)
551 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
552 : dbcsr_sg, &
553 : dbcsr_work, 0.0_dp, &
554 : dbcsr_prod, &
555 10 : filter_eps=eps_filter)
556 :
557 : !! This will lead to:
558 : !! -1/sqrt(2)(<S|H_x|T> - <S|T> <GS|H_x|GS>)
559 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
560 : dbcsr_prod, &
561 : dbcsr_ovlp, &
562 : mo_soc_x, &
563 : pref_trace=-1.0_dp, &
564 10 : pref_overall=-0.5_dp*sqrt2)
565 :
566 : !<S|H_x|T^-1>
567 : !! Convert to fm for transfer to img_fm
568 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
569 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
570 : mtarget=img_fm, &
571 : nrow=nex, &
572 : ncol=nex, &
573 : s_firstrow=1, &
574 : s_firstcol=1, &
575 : t_firstrow=2, &
576 10 : t_firstcol=1 + nsg + 1)
577 :
578 : IF (debug_this_module) THEN
579 : WRITE (log_unit, "(/,A)") "<S|H_x|T^-1> in Hartree / cm^-1"
580 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
581 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
582 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
583 : END IF
584 :
585 : !<S|H_x|T^+1> takes a minus sign
586 10 : CALL cp_fm_scale(-1.0_dp, tmp_fm)
587 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
588 : mtarget=img_fm, &
589 : nrow=nex, &
590 : ncol=nex, &
591 : s_firstrow=1, &
592 : s_firstcol=1, &
593 : t_firstrow=2, &
594 10 : t_firstcol=1 + nsg + 2*ntp + 1)
595 :
596 : IF (debug_this_module) THEN
597 : WRITE (log_unit, "(/,A)") "<S|H_x|T^+1> in Hartree / cm^-1"
598 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
599 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
600 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
601 : END IF
602 :
603 : !!singlet-triplet with Ms=+-1, real part
604 : !! Precompute <S|H_y|T>
605 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
606 : orb_soc_y, dbcsr_tp, &
607 : 0.0_dp, dbcsr_work, &
608 10 : filter_eps=eps_filter)
609 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
610 : dbcsr_sg, dbcsr_work, &
611 : 0.0_dp, dbcsr_prod, &
612 10 : filter_eps=eps_filter)
613 :
614 : !! This will lead to -1/sqrt(2)(<S|H_y|T> - <S|T> <GS|H_y|GS>)
615 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
616 : dbcsr_prod, &
617 : dbcsr_ovlp, &
618 : mo_soc_y, &
619 : pref_trace=-1.0_dp, &
620 10 : pref_overall=-0.5_dp*sqrt2)
621 :
622 : !<S|H_y|T^-1>
623 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
624 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
625 : mtarget=real_fm, &
626 : nrow=nex, &
627 : ncol=nex, &
628 : s_firstrow=1, &
629 : s_firstcol=1, &
630 : t_firstrow=2, &
631 10 : t_firstcol=1 + nsg + 1)
632 :
633 : IF (debug_this_module) THEN
634 : WRITE (log_unit, "(/,A)") "<S|H_y|T^-1> in Hartree / cm^-1"
635 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
636 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
637 : CALL dbcsr_print(dbcsr_tmp, unit_nr=log_unit)
638 : END IF
639 :
640 : !<S|H_y|T^+1>
641 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
642 : mtarget=real_fm, &
643 : nrow=nex, &
644 : ncol=nex, &
645 : s_firstrow=1, &
646 : s_firstcol=1, &
647 : t_firstrow=2, &
648 10 : t_firstcol=1 + nsg + 2*ntp + 1)
649 :
650 : IF (debug_this_module) THEN
651 : WRITE (log_unit, "(/,A)") "<S|H_y|T^+1> in Hartree / cm^-1"
652 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
653 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
654 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
655 : END IF
656 :
657 : !singlet-triplet with Ms=0, purely imaginary
658 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
659 : orb_soc_z, dbcsr_tp, &
660 : 0.0_dp, dbcsr_work, &
661 10 : filter_eps=eps_filter)
662 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
663 : dbcsr_sg, dbcsr_work, &
664 : 0.0_dp, dbcsr_prod, &
665 10 : filter_eps=eps_filter)
666 :
667 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
668 : dbcsr_prod, &
669 : dbcsr_ovlp, &
670 : mo_soc_z, &
671 : pref_trace=-1.0_dp, &
672 10 : pref_overall=1.0_dp)
673 :
674 : !<S|H_z|T^0>
675 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
676 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
677 : mtarget=img_fm, &
678 : nrow=nex, &
679 : ncol=nex, &
680 : s_firstrow=1, &
681 : s_firstcol=1, &
682 : t_firstrow=2, &
683 10 : t_firstcol=1 + nsg + ntp + 1)
684 :
685 : IF (debug_this_module) THEN
686 : WRITE (log_unit, "(/,A)") "<S|H_z|T^0> in Hartree / cm^-1"
687 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
688 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
689 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
690 : END IF
691 :
692 : IF (log_unit > 0 .AND. debug_this_module) THEN
693 : WRITE (log_unit, '(A)') "Starting Triplet-Triplet contributions..."
694 : END IF
695 :
696 : !Now the triplet-triplet SOC
697 : !start by computing the overlap
698 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
699 : matrix_s(1)%matrix, &
700 : dbcsr_tp, 0.0_dp, &
701 : dbcsr_work, &
702 10 : filter_eps=eps_filter)
703 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
704 : dbcsr_tp, dbcsr_work, &
705 : 0.0_dp, dbcsr_ovlp, &
706 10 : filter_eps=eps_filter)
707 :
708 : !Ms=0 to Ms=+-1 SOC, imaginary part
709 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
710 : orb_soc_x, dbcsr_tp, &
711 : 0.0_dp, dbcsr_work, &
712 10 : filter_eps=eps_filter)
713 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
714 : dbcsr_tp, dbcsr_work, &
715 : 0.0_dp, dbcsr_prod, &
716 10 : filter_eps=eps_filter)
717 :
718 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
719 : dbcsr_prod, &
720 : dbcsr_ovlp, &
721 : mo_soc_x, &
722 : pref_trace=1.0_dp, &
723 10 : pref_overall=-0.5_dp*sqrt2)
724 :
725 : !<T^0|H_x|T^+1>
726 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
727 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
728 : mtarget=img_fm, &
729 : nrow=nex, &
730 : ncol=nex, &
731 : s_firstrow=1, &
732 : s_firstcol=1, &
733 : t_firstrow=1 + nsg + ntp + 1, &
734 10 : t_firstcol=1 + nsg + 2*ntp + 1)
735 :
736 : IF (debug_this_module) THEN
737 : WRITE (log_unit, "(/,A)") "<T^0|H_x|T^+1> in Hartree / cm^-1"
738 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
739 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
740 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
741 : END IF
742 :
743 : !<T^-1|H_x|T^0>, takes a minus sign and a transpose (because computed <T^0|H_x|T^-1>)
744 10 : CALL cp_fm_transpose(tmp_fm, work_fm)
745 10 : CALL cp_fm_scale(-1.0_dp, work_fm)
746 : CALL cp_fm_to_fm_submat(msource=work_fm, &
747 : mtarget=img_fm, &
748 : nrow=nex, &
749 : ncol=nex, &
750 : s_firstrow=1, &
751 : s_firstcol=1, &
752 : t_firstrow=1 + nsg + 1, &
753 10 : t_firstcol=1 + nsg + ntp + 1)
754 :
755 : IF (debug_this_module) THEN
756 : WRITE (log_unit, "(/,A)") "<T^-1|H_x|T^0> in Hartree / cm^-1"
757 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
758 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
759 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
760 : END IF
761 :
762 : !Ms=0 to Ms=+-1 SOC, real part
763 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
764 : orb_soc_y, dbcsr_tp, &
765 : 0.0_dp, dbcsr_work, &
766 10 : filter_eps=eps_filter)
767 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
768 : dbcsr_tp, dbcsr_work, &
769 : 0.0_dp, dbcsr_prod, &
770 10 : filter_eps=eps_filter)
771 :
772 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
773 : dbcsr_prod, &
774 : dbcsr_ovlp, &
775 : mo_soc_y, &
776 : pref_trace=1.0_dp, &
777 10 : pref_overall=0.5_dp*sqrt2)
778 :
779 : !<T^0|H_y|T^+1>
780 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
781 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
782 : mtarget=real_fm, &
783 : nrow=nex, &
784 : ncol=nex, &
785 : s_firstrow=1, &
786 : s_firstcol=1, t_firstrow=1 + nsg + ntp + 1, &
787 10 : t_firstcol=1 + nsg + 2*ntp + 1)
788 :
789 : IF (debug_this_module) THEN
790 : WRITE (log_unit, "(/,A)") "<T^0|H_y|T^+1> in Hartree / cm^-1"
791 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
792 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
793 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
794 : END IF
795 :
796 : !<T^-1|H_y|T^0>, takes a minus sign and a transpose
797 10 : CALL cp_fm_transpose(tmp_fm, work_fm)
798 10 : CALL cp_fm_scale(-1.0_dp, work_fm)
799 : CALL cp_fm_to_fm_submat(msource=work_fm, &
800 : mtarget=real_fm, &
801 : nrow=nex, &
802 : ncol=nex, &
803 : s_firstrow=1, &
804 : s_firstcol=1, t_firstrow=1 + nsg + 1, &
805 10 : t_firstcol=1 + nsg + ntp + 1)
806 :
807 : IF (debug_this_module) THEN
808 : WRITE (log_unit, "(/,A)") "<T^0|H_y|T^+1> in Hartree / cm^-1"
809 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
810 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
811 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
812 : END IF
813 :
814 : !Ms=1 to Ms=1 and Ms=-1 to Ms=-1 SOC, purely imaginary
815 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
816 : orb_soc_z, dbcsr_tp, &
817 : 0.0_dp, dbcsr_work, &
818 10 : filter_eps=eps_filter)
819 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
820 : dbcsr_tp, dbcsr_work, &
821 : 0.0_dp, dbcsr_prod, &
822 10 : filter_eps=eps_filter)
823 :
824 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
825 : dbcsr_prod, &
826 : dbcsr_ovlp, &
827 : mo_soc_z, &
828 : pref_trace=1.0_dp, &
829 10 : pref_overall=1.0_dp)
830 :
831 : !<T^+1|H_z|T^+1>
832 10 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
833 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
834 : mtarget=img_fm, &
835 : nrow=nex, &
836 : ncol=nex, &
837 : s_firstrow=1, &
838 : s_firstcol=1, &
839 : t_firstrow=1 + nsg + 2*ntp + 1, &
840 10 : t_firstcol=1 + nsg + 2*ntp + 1)
841 :
842 : IF (debug_this_module) THEN
843 : WRITE (log_unit, "(/,A)") "<T^+1|H_z|T^+1> in Hartree / cm^-1"
844 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
845 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
846 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
847 : END IF
848 :
849 : !<T^-1|H_z|T^-1>, takes a minus sign
850 10 : CALL cp_fm_scale(-1.0_dp, tmp_fm)
851 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
852 : mtarget=img_fm, &
853 : nrow=nex, &
854 : ncol=nex, &
855 : s_firstrow=1, &
856 : s_firstcol=1, &
857 : t_firstrow=1 + nsg + 1, &
858 10 : t_firstcol=1 + nsg + 1)
859 :
860 : IF (debug_this_module) THEN
861 : WRITE (log_unit, "(/,A)") "<T^-1|H_z|T^-1> in Hartree / cm^-1"
862 : CALL dbcsr_copy(dbcsr_dummy, dbcsr_tmp)
863 : CALL dbcsr_scale(dbcsr_dummy, wavenumbers)
864 : CALL dbcsr_print(dbcsr_dummy, unit_nr=log_unit)
865 : END IF
866 :
867 : !Intermediate clean-up
868 10 : CALL cp_fm_struct_release(work_struct)
869 10 : CALL cp_fm_release(work_fm)
870 10 : CALL cp_fm_release(tmp_fm)
871 10 : DEALLOCATE (diag, mo_soc_x, mo_soc_y, mo_soc_z)
872 :
873 10 : IF (log_unit > 0) THEN
874 5 : WRITE (log_unit, '(A)') "Diagonlzing SOC-Matrix"
875 : END IF
876 :
877 : !Set-up the complex hermitian perturbation matrix
878 10 : CALL cp_cfm_create(hami_cfm, full_struct)
879 10 : CALL cp_fm_to_cfm(real_fm, img_fm, hami_cfm)
880 :
881 : !!Optinal Output: SOC-Matrix
882 10 : IF (logger%para_env%is_source()) THEN
883 : log_unit = cp_print_key_unit_nr(logger, &
884 : tddfpt_print_section, &
885 : "SOC_PRINT", &
886 : extension=".socme", &
887 : file_form="FORMATTED", &
888 : file_action="WRITE", &
889 5 : file_status="UNKNOWN")
890 : ELSE
891 5 : log_unit = -1
892 : END IF
893 :
894 : !! Get the requested energy unit and optional outputs
895 10 : CALL section_vals_val_get(soc_print_section, "UNIT_eV", l_val=print_ev)
896 10 : CALL section_vals_val_get(soc_print_section, "UNIT_wn", l_val=print_wn)
897 10 : CALL section_vals_val_get(soc_print_section, "SPLITTING", l_val=print_splitting)
898 10 : CALL section_vals_val_get(soc_print_section, "SOME", l_val=print_some)
899 :
900 : !! save convertion unit into different varible for cleaner code
901 10 : IF (print_wn) THEN
902 2 : print_ev = .FALSE.
903 2 : unit_scale = wavenumbers
904 8 : ELSE IF (print_ev) THEN
905 : unit_scale = evolt
906 : ELSE
907 0 : CPWARN("No output unit was selected, printout will be in Hartree!")
908 0 : unit_scale = 1
909 : END IF
910 :
911 : !! This needs something to deal with a parallel run
912 : !! This output will be needed for NEWTONX for ISC!!
913 10 : IF (print_some) THEN
914 2 : IF (log_unit > 0) THEN
915 1 : WRITE (log_unit, '(A)') "____________________________________________________"
916 1 : WRITE (log_unit, '(A)') " FULL SOC-Matrix "
917 1 : IF (print_ev) THEN
918 0 : WRITE (log_unit, '(A)') "STATE STATE REAL-PART[eV] IMG-PART[eV] "
919 1 : ELSE IF (print_wn) THEN
920 1 : WRITE (log_unit, '(A)') "STATE STATE REAL-PART[cm-1] IMG-PART[cm-1]"
921 : ELSE
922 0 : WRITE (log_unit, '(A)') "STATE STATE REAL-PART[Hartree] IMG-PART[Hartree]"
923 : END IF
924 1 : WRITE (log_unit, '(A)') "____________________________________________________"
925 : END IF
926 12 : ALLOCATE (real_tmp(ntot, ntot), img_tmp(ntot, ntot))
927 182 : real_tmp = 0_dp
928 182 : img_tmp = 0_dp
929 :
930 2 : CALL cp_fm_get_submatrix(real_fm, real_tmp, 1, 1, ntot, ntot)
931 2 : CALL cp_fm_get_submatrix(img_fm, img_tmp, 1, 1, ntot, ntot)
932 :
933 2 : IF (log_unit > 0) THEN
934 10 : DO jj = 1, ntot
935 91 : DO ii = 1, ntot
936 81 : WRITE (unit=log_unit, fmt="(I3,5X,I3,5X,f16.8,5X,f16.8)") ii, jj, &
937 81 : real_tmp(ii, jj)*unit_scale, &
938 171 : img_tmp(ii, jj)*unit_scale
939 : END DO !! jj
940 : END DO !! ii
941 1 : WRITE (log_unit, '(A)') " END SOC-MATRIX "
942 1 : WRITE (log_unit, '(A)') "____________________________________________________"
943 1 : WRITE (log_unit, '(A)') "____________________________________________________"
944 : END IF !(log_unit)
945 2 : DEALLOCATE (real_tmp, img_tmp)
946 : END IF !print_some
947 :
948 10 : CALL cp_fm_release(real_fm)
949 10 : CALL cp_fm_release(img_fm)
950 :
951 : ! Diagonalize the Hamiltonian
952 30 : ALLOCATE (tmp_evals(ntot))
953 10 : CALL cp_cfm_create(evecs_cfm, full_struct)
954 10 : CALL cp_cfm_heevd(hami_cfm, evecs_cfm, tmp_evals)
955 :
956 : ! Adjust the energies so the GS has zero, and store in the donor_state (without the GS)
957 30 : ALLOCATE (soc_env%soc_evals(ntot - 1))
958 122 : soc_env%soc_evals(:) = tmp_evals(2:ntot) - tmp_evals(1)
959 :
960 : !! We may be interested in the ground state stabilisation energy
961 10 : IF (logger%para_env%is_source()) THEN
962 5 : log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
963 : ELSE
964 5 : log_unit = -1
965 : END IF
966 :
967 10 : IF (log_unit > 0) THEN
968 5 : WRITE (log_unit, '(A27,6X,F18.10)') "Ground state stabilisation:", (soc_env%soc_evals(1)*unit_scale)
969 : IF (debug_this_module) THEN
970 : WRITE (log_unit, '(A)') "Calculation Dipole Moments"
971 : END IF
972 : END IF
973 :
974 : !Compute the dipole oscillator strengths
975 10 : soc_env%evals_a => evals_sing
976 10 : soc_env%evals_b => evals_trip
977 : CALL soc_dipol(qs_env, dbcsr_soc_package, soc_env, &
978 : evecs_cfm, eps_filter, dipole_form, gs_mos, &
979 10 : evects_sing, evects_trip)
980 :
981 : !Create final output
982 : !! Output unit is choosen by the keyword "UNIT_eV" and "UNIT_wn" in "SOC_PRINT" section
983 10 : IF (logger%para_env%is_source()) THEN
984 5 : log_unit = cp_logger_get_default_unit_nr(logger, local=.TRUE.)
985 : ELSE
986 5 : log_unit = -1
987 : END IF
988 :
989 10 : IF (log_unit > 0) THEN
990 5 : WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
991 5 : WRITE (log_unit, '(A)') "- SOC CORRECTED SPECTRUM -"
992 5 : WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
993 5 : IF (print_ev) THEN
994 4 : WRITE (log_unit, '(A)') "- STATE SOC-corrected exc. energies [eV] Oscillator strengths [a.u.] -"
995 1 : ELSE IF (print_wn) THEN
996 1 : WRITE (log_unit, '(A)') "- STATE SOC-corrected exc. energies [cm-1] Oscillator strengths [a.u.]-"
997 : ELSE
998 0 : WRITE (log_unit, '(A)') "- STATE SOC-corrected exc.energies [Hartree] Oscillator strengths [a.u.]-"
999 : END IF
1000 5 : WRITE (log_unit, '(A)') "------------------------------------------------------------------------------"
1001 61 : DO istate = 1, SIZE(soc_env%soc_evals)
1002 56 : WRITE (log_unit, '(6X,I5,11X,2F16.5)') istate, soc_env%soc_evals(istate)*unit_scale, &
1003 117 : soc_env%soc_osc(istate)
1004 : END DO
1005 : !! This is used for regtesting
1006 61 : WRITE (log_unit, '(A,F18.8)') "TDDFT+SOC : CheckSum (eV) ", SUM(soc_env%soc_evals)*evolt
1007 : END IF
1008 :
1009 : !! We may be interested in the differenz between the SOC and
1010 : !! TDDFPT Eigenvalues
1011 : !! Activated with the "SPLITTING" keyword in "SOC_PRINT" section
1012 18 : IF (print_splitting .OR. debug_this_module) THEN
1013 8 : CALL resort_evects(evecs_cfm, evects_sort)
1014 8 : IF (log_unit > 0) THEN
1015 4 : WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
1016 4 : WRITE (log_unit, '(A)') "- Splittings -"
1017 4 : WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
1018 4 : IF (print_ev) THEN
1019 3 : WRITE (log_unit, '(A)') "- STATE exc.energies[eV] splittings[eV] -"
1020 1 : ELSE IF (print_wn) THEN
1021 1 : WRITE (log_unit, '(A)') "- STATE exc.energies[cm-1] splittings[cm-1] -"
1022 : ELSE
1023 0 : WRITE (log_unit, '(A)') "- STATE exc.energies[Hartree] splittings[Hartree] -"
1024 : END IF
1025 4 : WRITE (log_unit, '(A)') "-----------------------------------------------------------------------------"
1026 4 : mult = " "
1027 48 : DO iex = 1, SIZE(soc_env%soc_evals)
1028 44 : IF (evects_sort(iex + 1) > nsg + ntp*2 + 1) THEN
1029 11 : mult = "T+1"
1030 33 : ELSE IF (evects_sort(iex + 1) > nsg + ntp + 1) THEN
1031 11 : mult = "T0"
1032 22 : ELSE IF (evects_sort(iex + 1) > nsg + 1) THEN
1033 11 : mult = "T-1"
1034 : ELSE
1035 11 : mult = "S "
1036 : END IF
1037 48 : IF (mult == "T-1") THEN
1038 11 : WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
1039 11 : evects_sort(iex + 1) - (1 + nsg), soc_env%soc_evals(iex)*unit_scale, &
1040 22 : (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg)))*unit_scale
1041 33 : ELSE IF (mult == "T0") THEN
1042 11 : WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
1043 11 : evects_sort(iex + 1) - (1 + nsg + ntp), soc_env%soc_evals(iex)*unit_scale, &
1044 22 : (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg + ntp)))*unit_scale
1045 22 : ELSE IF (mult == "T+1") THEN
1046 11 : WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
1047 11 : evects_sort(iex + 1) - (1 + nsg + ntp*2), soc_env%soc_evals(iex)*unit_scale, &
1048 22 : (soc_env%soc_evals(iex) - evals_trip(evects_sort(iex + 1) - (1 + nsg + ntp*2)))*unit_scale
1049 11 : ELSE IF (mult == "S ") THEN
1050 11 : WRITE (log_unit, "(5X,A,I5,6X,F18.10,6X,F18.10)") mult, &
1051 11 : evects_sort(iex + 1), soc_env%soc_evals(iex)*unit_scale, &
1052 22 : (soc_env%soc_evals(iex) - evals_sing(evects_sort(iex + 1) - 1))*unit_scale
1053 : END IF
1054 : END DO
1055 4 : WRITE (log_unit, '(A)') "----------------------------------------------------------------------------"
1056 4 : DEALLOCATE (evects_sort)
1057 : END IF
1058 : END IF
1059 :
1060 : !! clean up
1061 10 : CALL soc_env_release(soc_env)
1062 10 : CALL cp_fm_struct_release(full_struct)
1063 10 : CALL cp_cfm_release(hami_cfm)
1064 10 : CALL cp_cfm_release(evecs_cfm)
1065 10 : CALL dbcsr_distribution_release(coeffs_dist)
1066 10 : CALL dbcsr_distribution_release(prod_dist)
1067 10 : CALL dbcsr_release(dbcsr_sg)
1068 10 : CALL dbcsr_release(dbcsr_tp)
1069 10 : CALL dbcsr_release(dbcsr_prod)
1070 10 : CALL dbcsr_release(dbcsr_ovlp)
1071 10 : CALL dbcsr_release(dbcsr_tmp)
1072 10 : CALL dbcsr_release(dbcsr_work)
1073 : IF (debug_this_module) THEN
1074 : CALL dbcsr_release(dbcsr_dummy)
1075 : DEALLOCATE (dbcsr_dummy)
1076 : END IF
1077 :
1078 10 : DEALLOCATE (dbcsr_work, dbcsr_prod, dbcsr_ovlp, dbcsr_tmp)
1079 10 : DEALLOCATE (coeffs_dist, prod_dist, col_dist, col_blk_size, row_dist_new)
1080 10 : DEALLOCATE (dbcsr_sg, dbcsr_tp, tmp_evals)
1081 :
1082 10 : CALL timestop(handle)
1083 :
1084 140 : END SUBROUTINE tddfpt_soc_rcs
1085 :
1086 : ! **************************************************************************************************
1087 : !> \brief Some additional initalizations
1088 : !> \param qs_env Quickstep environment
1089 : !> \param soc_atom_env contains information to build the ZORA-Hamiltionian
1090 : !> \param soc_env contails details and outputs for SOC Correction
1091 : !> \param evects_a singlet Eigenvectors
1092 : !> \param evects_b triplet eigenvectors
1093 : !> \param dipole_form choosen dipole-form from TDDFPT-Section
1094 : !> \param gs_mos ...
1095 : ! **************************************************************************************************
1096 10 : SUBROUTINE inititialize_soc(qs_env, soc_atom_env, soc_env, &
1097 10 : evects_a, evects_b, &
1098 10 : dipole_form, gs_mos)
1099 : !! Different Types
1100 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
1101 : TYPE(soc_atom_env_type), INTENT(OUT), POINTER :: soc_atom_env
1102 : TYPE(soc_env_type), INTENT(OUT), TARGET :: soc_env
1103 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects_a, evects_b
1104 : INTEGER :: dipole_form
1105 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1106 : INTENT(in) :: gs_mos
1107 :
1108 : CHARACTER(LEN=*), PARAMETER :: routineN = 'inititialize_soc'
1109 :
1110 : CHARACTER(len=default_string_length), &
1111 : ALLOCATABLE, DIMENSION(:, :) :: grid_info
1112 : CHARACTER(len=default_string_length), &
1113 10 : DIMENSION(:), POINTER :: k_list
1114 : INTEGER :: handle, i, ikind, irep, ispin, nactive, &
1115 : nao, natom, nkind, nrep, nspins, &
1116 : nstates
1117 : LOGICAL :: all_potential_present, do_os
1118 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1119 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1120 : TYPE(cp_fm_type), POINTER :: a_coeff, b_coeff
1121 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1122 : TYPE(dft_control_type), POINTER :: dft_control
1123 10 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1124 : TYPE(mp_para_env_type), POINTER :: para_env
1125 10 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1126 10 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1127 : TYPE(section_vals_type), POINTER :: soc_section
1128 : TYPE(tddfpt2_control_type), POINTER :: tddfpt_control
1129 :
1130 10 : CALL timeset(routineN, handle)
1131 :
1132 10 : NULLIFY (qs_kind_set, particle_set, blacs_env, para_env, &
1133 10 : a_coeff, b_coeff, tddfpt_control, soc_section)
1134 :
1135 : !! Open_shell is not implemented yet
1136 10 : do_os = .FALSE.
1137 :
1138 : !! soc_env will pass most of the larger matrices to the different modules
1139 10 : CALL soc_env_create(soc_env)
1140 : CALL get_qs_env(qs_env, qs_kind_set=qs_kind_set, &
1141 : mos=mos, natom=natom, &
1142 : particle_set=particle_set, blacs_env=blacs_env, &
1143 : para_env=para_env, matrix_s=matrix_s, &
1144 10 : dft_control=dft_control)
1145 :
1146 : !! The Dipole form shall be consistent with the tddfpt-module!
1147 10 : tddfpt_control => dft_control%tddfpt2_control
1148 10 : dipole_form = tddfpt_control%dipole_form
1149 :
1150 10 : soc_section => section_vals_get_subs_vals(qs_env%input, "PROPERTIES%TDDFPT%SOC")
1151 :
1152 : !! We may want to use a bigger grid then default
1153 10 : CALL section_vals_val_get(soc_section, "GRID", n_rep_val=nrep)
1154 20 : ALLOCATE (grid_info(nrep, 3))
1155 10 : DO irep = 1, nrep
1156 : CALL section_vals_val_get(soc_section, &
1157 : "GRID", &
1158 : i_rep_val=irep, &
1159 0 : c_vals=k_list)
1160 10 : grid_info(irep, :) = k_list
1161 : END DO
1162 :
1163 10 : CALL soc_dipole_operator(soc_env, tddfpt_control, qs_env, gs_mos)
1164 :
1165 10 : nspins = SIZE(evects_a, 1)
1166 20 : DO ispin = 1, nspins
1167 20 : CALL cp_fm_get_info(evects_a(ispin, 1), nrow_global=nao, ncol_global=nactive)
1168 : END DO
1169 :
1170 : !! We need to change and create structures for the exitation vectors.
1171 : !! All excited states shall be written in one matrix, oneafter the other
1172 10 : nstates = SIZE(evects_a, 2)
1173 :
1174 10 : a_coeff => soc_env%a_coeff
1175 10 : b_coeff => soc_env%b_coeff
1176 :
1177 10 : NULLIFY (fm_struct)
1178 : CALL cp_fm_struct_create(fm_struct, context=blacs_env, para_env=para_env, &
1179 10 : nrow_global=nao, ncol_global=nspins*nactive*nstates)
1180 10 : CALL cp_fm_create(a_coeff, fm_struct)
1181 10 : CALL cp_fm_create(b_coeff, fm_struct)
1182 10 : CALL cp_fm_struct_release(fm_struct)
1183 :
1184 10 : CALL soc_contract_evect(evects_a, a_coeff)
1185 10 : CALL soc_contract_evect(evects_b, b_coeff)
1186 :
1187 40 : ALLOCATE (soc_env%orb_soc(3))
1188 40 : DO i = 1, 3
1189 40 : ALLOCATE (soc_env%orb_soc(i)%matrix)
1190 : END DO
1191 :
1192 : ! Make soc_atom_env for H^SOC calculations
1193 : ! Compute the contraction coefficients for spherical orbitals
1194 10 : CALL soc_atom_create(soc_atom_env)
1195 : IF (do_os) THEN
1196 : soc_atom_env%nspins = 2
1197 : ELSE
1198 10 : soc_atom_env%nspins = 1
1199 : END IF
1200 :
1201 10 : nkind = SIZE(qs_kind_set)
1202 40 : ALLOCATE (soc_atom_env%grid_atom_set(nkind))
1203 40 : ALLOCATE (soc_atom_env%harmonics_atom_set(nkind))
1204 40 : ALLOCATE (soc_atom_env%orb_sphi_so(nkind))
1205 :
1206 10 : CALL get_qs_kind_set(qs_kind_set, all_potential_present=all_potential_present)
1207 10 : IF (.NOT. all_potential_present) THEN
1208 2 : CALL V_SOC_xyz_from_pseudopotential(qs_env, soc_atom_env%soc_pp)
1209 : END IF
1210 :
1211 : !! Prepare the atomic grid we need to calculate the SOC Operator in an Atomic basis
1212 : !! copied from init_xas_atom_grid_harmo for convenience
1213 10 : CALL init_atom_grid(soc_atom_env, grid_info, qs_env)
1214 :
1215 20 : DO ikind = 1, nkind
1216 10 : NULLIFY (soc_atom_env%orb_sphi_so(ikind)%array)
1217 20 : CALL compute_sphi_so(ikind, "ORB", soc_atom_env%orb_sphi_so(ikind)%array, qs_env)
1218 : END DO !ikind
1219 :
1220 10 : DEALLOCATE (grid_info)
1221 :
1222 10 : CALL timestop(handle)
1223 :
1224 50 : END SUBROUTINE inititialize_soc
1225 :
1226 : ! **************************************************************************************************
1227 : !> \brief Initializes the atomic grids and harmonics for the atomic calculations
1228 : !> \param soc_atom_env ...
1229 : !> \param grid_info ...
1230 : !> \param qs_env ...
1231 : !> \note Copied and modified from init_xas_atom_grid_harmo
1232 : ! **************************************************************************************************
1233 10 : SUBROUTINE init_atom_grid(soc_atom_env, grid_info, qs_env)
1234 :
1235 : TYPE(soc_atom_env_type) :: soc_atom_env
1236 : CHARACTER(len=default_string_length), &
1237 : ALLOCATABLE, DIMENSION(:, :) :: grid_info
1238 : TYPE(qs_environment_type) :: qs_env
1239 :
1240 : CHARACTER(LEN=*), PARAMETER :: routineN = 'init_atom_grid'
1241 :
1242 : CHARACTER(LEN=default_string_length) :: kind_name
1243 : INTEGER :: handle, igrid, ikind, il, iso, iso1, iso2, l1, l1l2, l2, la, lc1, lc2, lcleb, ll, &
1244 : llmax, lp, m1, m2, max_s_harm, max_s_set, maxl, maxlgto, maxs, mm, mp, na, nr, &
1245 : quadrature, stat
1246 : REAL(dp) :: kind_radius
1247 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: rga
1248 10 : REAL(dp), DIMENSION(:, :, :), POINTER :: my_CG
1249 : TYPE(dft_control_type), POINTER :: dft_control
1250 : TYPE(grid_atom_type), POINTER :: grid_atom
1251 : TYPE(gto_basis_set_type), POINTER :: tmp_basis
1252 : TYPE(harmonics_atom_type), POINTER :: harmonics
1253 : TYPE(qs_control_type), POINTER :: qs_control
1254 10 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1255 :
1256 10 : CALL timeset(routineN, handle)
1257 :
1258 10 : NULLIFY (my_CG, qs_kind_set, dft_control, qs_control)
1259 10 : NULLIFY (grid_atom, harmonics, tmp_basis)
1260 :
1261 : !! Initialization of some integer for the CG coeff generation
1262 : CALL get_qs_env(qs_env, &
1263 : qs_kind_set=qs_kind_set, &
1264 10 : dft_control=dft_control)
1265 :
1266 10 : CALL get_qs_kind_set(qs_kind_set, maxlgto=maxlgto, basis_type="ORB")
1267 10 : qs_control => dft_control%qs_control
1268 :
1269 : !!To be sure:: Is the basis grid present?
1270 10 : IF (maxlgto < 0) THEN
1271 0 : CPABORT("tmp_basis is not Present!")
1272 : END IF
1273 :
1274 : !maximum expansion
1275 10 : llmax = 2*maxlgto
1276 10 : max_s_harm = nsoset(llmax)
1277 10 : max_s_set = nsoset(maxlgto)
1278 10 : lcleb = llmax
1279 :
1280 : ! Allocate and compute the CG coeffs (copied from init_rho_atom)
1281 10 : CALL clebsch_gordon_init(lcleb)
1282 10 : CALL reallocate(my_CG, 1, max_s_set, 1, max_s_set, 1, max_s_harm)
1283 :
1284 30 : ALLOCATE (rga(lcleb, 2))
1285 40 : DO lc1 = 0, maxlgto
1286 130 : DO iso1 = nsoset(lc1 - 1) + 1, nsoset(lc1)
1287 90 : l1 = indso(1, iso1)
1288 90 : m1 = indso(2, iso1)
1289 390 : DO lc2 = 0, maxlgto
1290 1170 : DO iso2 = nsoset(lc2 - 1) + 1, nsoset(lc2)
1291 810 : l2 = indso(1, iso2)
1292 810 : m2 = indso(2, iso2)
1293 810 : CALL clebsch_gordon(l1, m1, l2, m2, rga)
1294 810 : IF (l1 + l2 > llmax) THEN
1295 : l1l2 = llmax
1296 : ELSE
1297 : l1l2 = l1 + l2
1298 : END IF
1299 810 : mp = m1 + m2
1300 810 : mm = m1 - m2
1301 810 : IF (m1*m2 < 0 .OR. (m1*m2 == 0 .AND. (m1 < 0 .OR. m2 < 0))) THEN
1302 360 : mp = -ABS(mp)
1303 360 : mm = -ABS(mm)
1304 : ELSE
1305 450 : mp = ABS(mp)
1306 450 : mm = ABS(mm)
1307 : END IF
1308 2880 : DO lp = MOD(l1 + l2, 2), l1l2, 2
1309 1800 : il = lp/2 + 1
1310 1800 : IF (ABS(mp) <= lp) THEN
1311 1280 : IF (mp >= 0) THEN
1312 860 : iso = nsoset(lp - 1) + lp + 1 + mp
1313 : ELSE
1314 420 : iso = nsoset(lp - 1) + lp + 1 - ABS(mp)
1315 : END IF
1316 1280 : my_CG(iso1, iso2, iso) = rga(il, 1)
1317 : END IF
1318 2610 : IF (mp /= mm .AND. ABS(mm) <= lp) THEN
1319 600 : IF (mm >= 0) THEN
1320 400 : iso = nsoset(lp - 1) + lp + 1 + mm
1321 : ELSE
1322 200 : iso = nsoset(lp - 1) + lp + 1 - ABS(mm)
1323 : END IF
1324 600 : my_CG(iso1, iso2, iso) = rga(il, 2)
1325 : END IF
1326 : END DO
1327 : END DO ! iso2
1328 : END DO ! lc2
1329 : END DO ! iso1
1330 : END DO ! lc1
1331 10 : DEALLOCATE (rga)
1332 10 : CALL clebsch_gordon_deallocate()
1333 :
1334 : ! Create the Lebedev grids and compute the spherical harmonics
1335 10 : CALL init_lebedev_grids()
1336 10 : quadrature = qs_control%gapw_control%quadrature
1337 :
1338 20 : DO ikind = 1, SIZE(soc_atom_env%grid_atom_set)
1339 :
1340 : ! Allocate the grid and the harmonics for this kind
1341 10 : NULLIFY (soc_atom_env%grid_atom_set(ikind)%grid_atom)
1342 10 : NULLIFY (soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom)
1343 10 : CALL allocate_grid_atom(soc_atom_env%grid_atom_set(ikind)%grid_atom)
1344 : CALL allocate_harmonics_atom( &
1345 10 : soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom)
1346 :
1347 : NULLIFY (grid_atom, harmonics)
1348 10 : grid_atom => soc_atom_env%grid_atom_set(ikind)%grid_atom
1349 10 : harmonics => soc_atom_env%harmonics_atom_set(ikind)%harmonics_atom
1350 :
1351 : ! Initialize some integers
1352 : CALL get_qs_kind(qs_kind_set(ikind), &
1353 : ngrid_rad=nr, &
1354 : ngrid_ang=na, &
1355 10 : name=kind_name)
1356 :
1357 : ! take the grid dimension given as input, if none, take the GAPW ones above
1358 10 : DO igrid = 1, SIZE(grid_info, 1)
1359 10 : IF (grid_info(igrid, 1) == kind_name) THEN
1360 0 : READ (grid_info(igrid, 2), *, iostat=stat) na
1361 0 : IF (stat /= 0) CPABORT("The 'na' value for the GRID keyword must be an integer")
1362 0 : READ (grid_info(igrid, 3), *, iostat=stat) nr
1363 0 : IF (stat /= 0) CPABORT("The 'nr' value for the GRID keyword must be an integer")
1364 : EXIT
1365 : END IF
1366 : END DO !igrid
1367 :
1368 10 : ll = get_number_of_lebedev_grid(n=na)
1369 10 : na = lebedev_grid(ll)%n
1370 10 : la = lebedev_grid(ll)%l
1371 10 : grid_atom%ng_sphere = na
1372 10 : grid_atom%nr = nr
1373 :
1374 : !Create the harmonics with the ORB-Basis
1375 : CALL get_qs_kind(qs_kind_set(ikind), &
1376 : basis_set=tmp_basis, &
1377 10 : basis_type="ORB")
1378 : CALL get_gto_basis_set(gto_basis_set=tmp_basis, &
1379 : maxl=maxl, &
1380 10 : kind_radius=kind_radius)
1381 :
1382 10 : CALL create_grid_atom(grid_atom, nr, na, llmax, ll, quadrature)
1383 10 : CALL truncate_radial_grid(grid_atom, kind_radius)
1384 :
1385 10 : maxs = nsoset(maxl)
1386 : CALL create_harmonics_atom(harmonics, &
1387 : my_CG, na, &
1388 : llmax, maxs, &
1389 : max_s_harm, ll, &
1390 : grid_atom%wa, &
1391 : grid_atom%azi, &
1392 10 : grid_atom%pol)
1393 40 : CALL get_maxl_CG(harmonics, tmp_basis, llmax, max_s_harm)
1394 : END DO !ikind
1395 :
1396 10 : CALL deallocate_lebedev_grids()
1397 10 : DEALLOCATE (my_CG)
1398 :
1399 10 : CALL timestop(handle)
1400 :
1401 20 : END SUBROUTINE init_atom_grid
1402 :
1403 : ! **************************************************************************************************
1404 : !> \brief ...
1405 : !> \param qs_env ...
1406 : !> \param dbcsr_soc_package ...
1407 : !> \param soc_env ...
1408 : !> \param soc_evecs_cfm ...
1409 : !> \param eps_filter ...
1410 : !> \param dipole_form ...
1411 : !> \param gs_mos ...
1412 : !> \param evects_sing ...
1413 : !> \param evects_trip ...
1414 : ! **************************************************************************************************
1415 10 : SUBROUTINE soc_dipol(qs_env, dbcsr_soc_package, soc_env, &
1416 : soc_evecs_cfm, eps_filter, dipole_form, gs_mos, &
1417 10 : evects_sing, evects_trip)
1418 : TYPE(qs_environment_type), POINTER :: qs_env
1419 : TYPE(dbcsr_soc_package_type) :: dbcsr_soc_package
1420 : TYPE(soc_env_type), TARGET :: soc_env
1421 : TYPE(cp_cfm_type), INTENT(in) :: soc_evecs_cfm
1422 : REAL(dp), INTENT(IN) :: eps_filter
1423 : INTEGER :: dipole_form
1424 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1425 : POINTER :: gs_mos
1426 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects_sing, evects_trip
1427 :
1428 : CHARACTER(len=*), PARAMETER :: routineN = 'soc_dipol'
1429 :
1430 : COMPLEX(dp), ALLOCATABLE, DIMENSION(:, :) :: transdip
1431 : INTEGER :: handle, i, nosc, ntot
1432 10 : REAL(dp), DIMENSION(:), POINTER :: osc_str, soc_evals
1433 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1434 : TYPE(cp_cfm_type) :: dip_cfm, work1_cfm, work2_cfm
1435 : TYPE(cp_fm_struct_type), POINTER :: dip_struct, full_struct
1436 10 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: amew_dip
1437 : TYPE(mp_para_env_type), POINTER :: para_env
1438 :
1439 10 : CALL timeset(routineN, handle)
1440 :
1441 10 : NULLIFY (para_env, blacs_env, dip_struct, full_struct, osc_str)
1442 10 : NULLIFY (soc_evals)
1443 :
1444 10 : CALL get_qs_env(qs_env, para_env=para_env, blacs_env=blacs_env)
1445 :
1446 10 : soc_evals => soc_env%soc_evals
1447 10 : nosc = SIZE(soc_evals)
1448 10 : ntot = nosc + 1
1449 30 : ALLOCATE (soc_env%soc_osc(nosc))
1450 10 : osc_str => soc_env%soc_osc
1451 122 : osc_str(:) = 0.0_dp
1452 :
1453 : !get some work arrays/matrix
1454 : CALL cp_fm_struct_create(dip_struct, &
1455 : context=blacs_env, para_env=para_env, &
1456 10 : nrow_global=ntot, ncol_global=1)
1457 :
1458 10 : CALL cp_cfm_get_info(soc_evecs_cfm, matrix_struct=full_struct)
1459 10 : CALL cp_cfm_create(dip_cfm, dip_struct, set_zero=.TRUE.)
1460 10 : CALL cp_cfm_create(work1_cfm, full_struct, set_zero=.TRUE.)
1461 10 : CALL cp_cfm_create(work2_cfm, full_struct, set_zero=.TRUE.)
1462 :
1463 30 : ALLOCATE (transdip(ntot, 1))
1464 :
1465 : CALL get_rcs_amew_op(amew_dip, soc_env, dbcsr_soc_package, &
1466 : eps_filter, qs_env, gs_mos, &
1467 10 : evects_sing, evects_trip)
1468 :
1469 40 : DO i = 1, 3 !cartesian coord x, y, z
1470 :
1471 : !Convert the real dipole into the cfm format for calculations
1472 30 : CALL cp_fm_to_cfm(msourcer=amew_dip(i), mtarget=work1_cfm)
1473 :
1474 : !compute amew_coeffs^dagger * amew_dip * amew_gs to get the transition moments
1475 : CALL parallel_gemm('C', 'N', ntot, &
1476 : ntot, ntot, &
1477 : (1.0_dp, 0.0_dp), &
1478 : soc_evecs_cfm, &
1479 : work1_cfm, &
1480 : (0.0_dp, 0.0_dp), &
1481 30 : work2_cfm)
1482 : CALL parallel_gemm('N', 'N', ntot, &
1483 : 1, ntot, &
1484 : (1.0_dp, 0.0_dp), &
1485 : work2_cfm, &
1486 : soc_evecs_cfm, &
1487 : (0.0_dp, 0.0_dp), &
1488 30 : dip_cfm)
1489 :
1490 30 : CALL cp_cfm_get_submatrix(dip_cfm, transdip)
1491 :
1492 : !transition dipoles are real numbers
1493 376 : osc_str(:) = osc_str(:) + REAL(transdip(2:ntot, 1))**2 + AIMAG(transdip(2:ntot, 1))**2
1494 :
1495 : END DO !i
1496 :
1497 : !multiply with appropriate prefac depending in the rep
1498 10 : IF (dipole_form == tddfpt_dipole_length) THEN
1499 208 : osc_str(:) = 2.0_dp/3.0_dp*soc_evals(:)*osc_str(:)
1500 : ELSE
1501 36 : osc_str(:) = 2.0_dp/3.0_dp*soc_evals(:)*osc_str(:)
1502 : END IF
1503 :
1504 : !clean-up
1505 10 : CALL cp_fm_struct_release(dip_struct)
1506 10 : CALL cp_cfm_release(work1_cfm)
1507 10 : CALL cp_cfm_release(work2_cfm)
1508 10 : CALL cp_cfm_release(dip_cfm)
1509 40 : DO i = 1, 3
1510 40 : CALL cp_fm_release(amew_dip(i))
1511 : END DO
1512 10 : DEALLOCATE (amew_dip, transdip)
1513 :
1514 10 : CALL timestop(handle)
1515 :
1516 10 : END SUBROUTINE soc_dipol
1517 :
1518 : !**********************************************************************************
1519 : !> \brief: This will create the Dipole operator within the amew basis
1520 : !> \param amew_op Output dipole operator
1521 : !> \param soc_env ...
1522 : !> \param dbcsr_soc_package Some work matrices
1523 : !> \param eps_filter ...
1524 : !> \param qs_env ...
1525 : !> \param gs_mos ...
1526 : !> \param evects_sing ...
1527 : !> \param evects_trip ...
1528 : ! **************************************************************************************************
1529 10 : SUBROUTINE get_rcs_amew_op(amew_op, soc_env, dbcsr_soc_package, eps_filter, qs_env, gs_mos, &
1530 10 : evects_sing, evects_trip)
1531 :
1532 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
1533 : INTENT(OUT) :: amew_op
1534 : TYPE(soc_env_type), TARGET :: soc_env
1535 : TYPE(dbcsr_soc_package_type) :: dbcsr_soc_package
1536 : REAL(dp), INTENT(IN) :: eps_filter
1537 : TYPE(qs_environment_type), POINTER :: qs_env
1538 : TYPE(tddfpt_ground_state_mos), DIMENSION(:), &
1539 : POINTER :: gs_mos
1540 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: evects_sing, evects_trip
1541 :
1542 : CHARACTER(len=*), PARAMETER :: routineN = 'get_rcs_amew_op'
1543 :
1544 : INTEGER :: dim_op, handle, i, isg, nactive, nao, &
1545 : nex, nsg, ntot, ntp
1546 : LOGICAL :: vel_rep
1547 : REAL(dp) :: op, sqrt2
1548 10 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: diag, gs_diag, gsgs_op
1549 10 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: mo_op, sggs_block
1550 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1551 : TYPE(cp_fm_struct_type), POINTER :: full_struct, gsgs_struct, sggs_struct, &
1552 : std_struct, tmp_struct
1553 : TYPE(cp_fm_type) :: gs_fm, sggs_fm, tmp_fm, vec_op, work_fm
1554 : TYPE(cp_fm_type), POINTER :: gs_coeffs
1555 10 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ao_op, matrix_s
1556 : TYPE(dbcsr_type), POINTER :: ao_op_i, dbcsr_ovlp, dbcsr_prod, &
1557 : dbcsr_sg, dbcsr_tmp, dbcsr_tp, &
1558 : dbcsr_work
1559 : TYPE(mp_para_env_type), POINTER :: para_env
1560 :
1561 10 : CALL timeset(routineN, handle)
1562 :
1563 10 : NULLIFY (gs_coeffs)
1564 10 : NULLIFY (matrix_s)
1565 10 : NULLIFY (para_env, blacs_env)
1566 10 : NULLIFY (full_struct, gsgs_struct, std_struct, tmp_struct, sggs_struct)
1567 10 : NULLIFY (ao_op_i, ao_op)
1568 10 : NULLIFY (dbcsr_tp, dbcsr_sg, dbcsr_ovlp, dbcsr_work, dbcsr_tmp, dbcsr_prod)
1569 :
1570 : ! Initialization
1571 : !! Fist case for length, secound for velocity-representation
1572 10 : IF (ASSOCIATED(soc_env%dipmat)) THEN
1573 8 : ao_op => soc_env%dipmat
1574 8 : vel_rep = .FALSE.
1575 : ELSE
1576 2 : ao_op => soc_env%dipmat_ao
1577 2 : vel_rep = .TRUE.
1578 : END IF
1579 10 : nsg = SIZE(soc_env%evals_a)
1580 10 : ntp = nsg; nex = nsg !all the same by construction, keep them separate for clarity
1581 10 : ntot = 1 + nsg + 3*ntp
1582 :
1583 10 : CALL get_qs_env(qs_env, matrix_s=matrix_s, para_env=para_env, blacs_env=blacs_env)
1584 10 : sqrt2 = SQRT(2.0_dp)
1585 10 : dim_op = SIZE(ao_op)
1586 :
1587 10 : dbcsr_sg => dbcsr_soc_package%dbcsr_sg
1588 10 : dbcsr_tp => dbcsr_soc_package%dbcsr_tp
1589 10 : dbcsr_work => dbcsr_soc_package%dbcsr_work
1590 10 : dbcsr_prod => dbcsr_soc_package%dbcsr_prod
1591 10 : dbcsr_ovlp => dbcsr_soc_package%dbcsr_ovlp
1592 10 : dbcsr_tmp => dbcsr_soc_package%dbcsr_tmp
1593 :
1594 : ! Create the amew_op matrix
1595 : CALL cp_fm_struct_create(full_struct, &
1596 : context=blacs_env, para_env=para_env, &
1597 10 : nrow_global=ntot, ncol_global=ntot)
1598 60 : ALLOCATE (amew_op(dim_op))
1599 40 : DO i = 1, dim_op
1600 40 : CALL cp_fm_create(amew_op(i), full_struct, set_zero=.TRUE.)
1601 : END DO !i
1602 :
1603 : ! Deal with the GS-GS contribution <0|0> = 2*sum_j <phi_j|op|phi_j>
1604 10 : nactive = gs_mos(1)%nmo_active
1605 10 : gs_coeffs => gs_mos(1)%mos_active
1606 10 : CALL cp_fm_get_info(gs_coeffs, matrix_struct=std_struct, nrow_global=nao)
1607 :
1608 : CALL cp_fm_struct_create(gsgs_struct, &
1609 : context=blacs_env, para_env=para_env, &
1610 10 : nrow_global=nactive, ncol_global=nactive)
1611 :
1612 10 : CALL cp_fm_create(gs_fm, gsgs_struct) !nactive nactive
1613 10 : CALL cp_fm_create(work_fm, std_struct) !nao nactive
1614 :
1615 30 : ALLOCATE (gsgs_op(dim_op))
1616 30 : ALLOCATE (gs_diag(nactive))
1617 :
1618 40 : DO i = 1, dim_op
1619 :
1620 30 : ao_op_i => ao_op(i)%matrix
1621 30 : CALL cp_dbcsr_sm_fm_multiply(ao_op_i, gs_coeffs, work_fm, ncol=nactive)
1622 : CALL parallel_gemm('T', 'N', nactive, nactive, nao, &
1623 30 : 1.0_dp, gs_coeffs, work_fm, 0.0_dp, gs_fm)
1624 30 : CALL cp_fm_get_diag(gs_fm, gs_diag)
1625 220 : gsgs_op(i) = 2.0_dp*SUM(gs_diag)
1626 :
1627 : END DO !i
1628 10 : DEALLOCATE (gs_diag)
1629 :
1630 10 : CALL cp_fm_release(work_fm)
1631 :
1632 : ! Create the work and helper fms
1633 10 : CALL cp_fm_create(vec_op, std_struct) !nao nactive
1634 10 : CALL cp_fm_struct_release(gsgs_struct)
1635 :
1636 : CALL cp_fm_struct_create(tmp_struct, &
1637 : context=blacs_env, para_env=para_env, &
1638 10 : nrow_global=nex, ncol_global=nex)
1639 : CALL cp_fm_struct_create(sggs_struct, &
1640 : context=blacs_env, para_env=para_env, &
1641 10 : nrow_global=nactive*nsg, ncol_global=nactive)
1642 :
1643 10 : CALL cp_fm_create(tmp_fm, tmp_struct)
1644 10 : CALL cp_fm_create(work_fm, full_struct)
1645 10 : CALL cp_fm_create(sggs_fm, sggs_struct)
1646 :
1647 20 : ALLOCATE (diag(nactive))
1648 40 : ALLOCATE (mo_op(nactive, nactive))
1649 30 : ALLOCATE (sggs_block(nactive, nactive))
1650 :
1651 : ! Iterate over the dimensions of the operator
1652 : ! Note: operator matrices are asusmed symmetric, can only do upper half
1653 40 : DO i = 1, dim_op
1654 :
1655 30 : ao_op_i => ao_op(i)%matrix
1656 :
1657 : ! The GS-GS contribution
1658 30 : CALL cp_fm_set_element(amew_op(i), 1, 1, gsgs_op(i))
1659 :
1660 : ! Compute the operator in the MO basis
1661 30 : CALL cp_dbcsr_sm_fm_multiply(ao_op_i, gs_coeffs, vec_op, ncol=nactive)
1662 30 : CALL cp_fm_get_submatrix(gs_fm, mo_op) ! instead of prod_fm
1663 :
1664 : ! Compute the ground-state/singlet components. ao_op*gs_coeffs already stored in vec_op
1665 30 : IF (vel_rep) THEN
1666 : CALL dip_vel_op(soc_env, qs_env, evects_sing, dbcsr_prod, i, .FALSE., &
1667 6 : gs_coeffs, sggs_fm)
1668 : ELSE
1669 : CALL parallel_gemm('T', 'N', nactive*nsg, nactive, nao, &
1670 24 : 1.0_dp, soc_env%a_coeff, vec_op, 0.0_dp, sggs_fm)
1671 : END IF
1672 :
1673 114 : DO isg = 1, nsg
1674 : CALL cp_fm_get_submatrix(fm=sggs_fm, &
1675 : target_m=sggs_block, &
1676 : start_row=(isg - 1)*nactive + 1, &
1677 : start_col=1, &
1678 : n_rows=nactive, &
1679 84 : n_cols=nactive)
1680 84 : diag(:) = get_diag(sggs_block)
1681 600 : op = sqrt2*SUM(diag)
1682 114 : CALL cp_fm_set_element(amew_op(i), 1, 1 + isg, op)
1683 : END DO !isg
1684 :
1685 : ! do the singlet-singlet components
1686 : !start with the overlap
1687 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
1688 : matrix_s(1)%matrix, dbcsr_sg, &
1689 : 0.0_dp, dbcsr_work, &
1690 30 : filter_eps=eps_filter)
1691 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
1692 : dbcsr_sg, dbcsr_work, &
1693 : 0.0_dp, dbcsr_ovlp, &
1694 30 : filter_eps=eps_filter)
1695 :
1696 30 : IF (vel_rep) THEN
1697 6 : CALL dip_vel_op(soc_env, qs_env, evects_sing, dbcsr_prod, i, .FALSE.)
1698 : ELSE
1699 : !then the operator in the LR orbital basis
1700 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
1701 : ao_op_i, dbcsr_sg, &
1702 : 0.0_dp, dbcsr_work, &
1703 24 : filter_eps=eps_filter)
1704 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
1705 : dbcsr_sg, dbcsr_work, &
1706 : 0.0_dp, dbcsr_prod, &
1707 24 : filter_eps=eps_filter)
1708 : END IF
1709 :
1710 : !use the soc routine, it is compatible
1711 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
1712 : dbcsr_prod, &
1713 : dbcsr_ovlp, &
1714 : mo_op, &
1715 : pref_trace=-1.0_dp, &
1716 : pref_overall=1.0_dp, &
1717 : pref_diags=gsgs_op(i), &
1718 30 : symmetric=.TRUE.)
1719 :
1720 30 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
1721 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
1722 : mtarget=amew_op(i), &
1723 : nrow=nex, &
1724 : ncol=nex, &
1725 : s_firstrow=1, &
1726 : s_firstcol=1, &
1727 : t_firstrow=2, &
1728 30 : t_firstcol=2)
1729 :
1730 : ! compute the triplet-triplet components
1731 : !the overlap
1732 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
1733 : matrix_s(1)%matrix, &
1734 : dbcsr_tp, 0.0_dp, &
1735 : dbcsr_work, &
1736 30 : filter_eps=eps_filter)
1737 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
1738 : dbcsr_tp, dbcsr_work, &
1739 : 0.0_dp, dbcsr_ovlp, &
1740 30 : filter_eps=eps_filter)
1741 :
1742 : !the operator in the LR orbital basis
1743 30 : IF (vel_rep) THEN
1744 6 : CALL dip_vel_op(soc_env, qs_env, evects_trip, dbcsr_prod, i, .TRUE.)
1745 : ELSE
1746 : CALL dbcsr_multiply('N', 'N', 1.0_dp, &
1747 : ao_op_i, dbcsr_tp, &
1748 : 0.0_dp, dbcsr_work, &
1749 24 : filter_eps=eps_filter)
1750 : CALL dbcsr_multiply('T', 'N', 1.0_dp, &
1751 : dbcsr_tp, dbcsr_work, &
1752 : 0.0_dp, dbcsr_prod, &
1753 24 : filter_eps=eps_filter)
1754 : END IF
1755 :
1756 : CALL rcs_amew_soc_elements(dbcsr_tmp, &
1757 : dbcsr_prod, &
1758 : dbcsr_ovlp, &
1759 : mo_op, &
1760 : pref_trace=-1.0_dp, &
1761 : pref_overall=1.0_dp, &
1762 : pref_diags=gsgs_op(i), &
1763 30 : symmetric=.TRUE.)
1764 :
1765 30 : CALL copy_dbcsr_to_fm(dbcsr_tmp, tmp_fm)
1766 : !<T^-1|op|T^-1>
1767 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
1768 : mtarget=amew_op(i), &
1769 : nrow=nex, &
1770 : ncol=nex, &
1771 : s_firstrow=1, &
1772 : s_firstcol=1, &
1773 : t_firstrow=1 + nsg + 1, &
1774 30 : t_firstcol=1 + nsg + 1)
1775 :
1776 : !<T^0|op|T^0>
1777 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
1778 : mtarget=amew_op(i), &
1779 : nrow=nex, &
1780 : ncol=nex, &
1781 : s_firstrow=1, &
1782 : s_firstcol=1, &
1783 : t_firstrow=1 + nsg + ntp + 1, &
1784 30 : t_firstcol=1 + nsg + ntp + 1)
1785 : !<T^+1|op|T^+1>
1786 : CALL cp_fm_to_fm_submat(msource=tmp_fm, &
1787 : mtarget=amew_op(i), &
1788 : nrow=nex, &
1789 : ncol=nex, &
1790 : s_firstrow=1, &
1791 : s_firstcol=1, &
1792 : t_firstrow=1 + nsg + 2*ntp + 1, &
1793 30 : t_firstcol=1 + nsg + 2*ntp + 1)
1794 :
1795 : ! Symmetrize the matrix (only upper triangle built)
1796 40 : CALL cp_fm_uplo_to_full(amew_op(i), work_fm)
1797 :
1798 : END DO !i
1799 :
1800 : ! Clean-up
1801 10 : CALL cp_fm_release(gs_fm)
1802 10 : CALL cp_fm_release(work_fm)
1803 10 : CALL cp_fm_release(tmp_fm)
1804 10 : CALL cp_fm_release(vec_op)
1805 10 : CALL cp_fm_release(sggs_fm)
1806 10 : CALL cp_fm_struct_release(full_struct)
1807 10 : CALL cp_fm_struct_release(tmp_struct)
1808 10 : CALL cp_fm_struct_release(sggs_struct)
1809 :
1810 10 : DEALLOCATE (sggs_block)
1811 10 : DEALLOCATE (diag, gsgs_op, mo_op)
1812 10 : CALL timestop(handle)
1813 :
1814 50 : END SUBROUTINE get_rcs_amew_op
1815 :
1816 0 : END MODULE qs_tddfpt2_soc
|