(git:374b731)
Loading...
Searching...
No Matches
qs_tddfpt_utils.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \par History
10!> 09-JUL-2002, TCH, development started
11! **************************************************************************************************
22 USE cp_fm_types, ONLY: cp_fm_create,&
31 USE dbcsr_api, ONLY: dbcsr_p_type
32 USE kinds, ONLY: dp
33 USE physcon, ONLY: evolt
36 USE qs_mo_types, ONLY: get_mo_set
39 USE qs_p_env_types, ONLY: p_env_release,&
44#include "./base/base_uses.f90"
45
46 IMPLICIT NONE
47
48 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_tddfpt_utils'
49 LOGICAL, PARAMETER :: debug_this_module = .true.
50
51! **************************************************************************************************
53 INTEGER :: orbit
54 INTEGER :: lumo
55 REAL(kind=dp) :: value
56 TYPE(simple_solution_sorter), POINTER :: next
58
59 PRIVATE
60
61 ! METHODS
62 PUBLIC :: tddfpt_cleanup, &
66 normalize, &
68
69CONTAINS
70
71! **************************************************************************************************
72!> \brief Initialize some necessary structures for a tddfpt calculation.
73!> \param p_env perturbation environment to be initialized
74!> \param t_env tddfpt environment to be initialized
75!> \param qs_env Quickstep environment with the results of a
76!> ground state calcualtion
77! **************************************************************************************************
78 SUBROUTINE tddfpt_init(p_env, t_env, qs_env)
79
80 TYPE(qs_p_env_type), INTENT(INOUT) :: p_env
81 TYPE(tddfpt_env_type), INTENT(out) :: t_env
82 TYPE(qs_environment_type), POINTER :: qs_env
83
84!------------------!
85! create the p_env !
86!------------------!
87
88 CALL p_env_create(p_env, qs_env, orthogonal_orbitals=.true.)
89 CALL p_env_psi0_changed(p_env, qs_env) ! update the m_epsilon matrix
90
91 !------------------!
92 ! create the t_env !
93 !------------------!
94 CALL tddfpt_env_allocate(t_env, p_env, qs_env)
95 CALL tddfpt_env_init(t_env, qs_env)
96
97 END SUBROUTINE tddfpt_init
98
99! **************************************************************************************************
100!> \brief Initialize t_env with meaningfull values.
101!> \param t_env ...
102!> \param qs_env ...
103! **************************************************************************************************
104 SUBROUTINE tddfpt_env_init(t_env, qs_env)
105
106 TYPE(tddfpt_env_type), INTENT(inout) :: t_env
107 TYPE(qs_environment_type), POINTER :: qs_env
108
109 INTEGER :: n_spins, spin
110 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
111 TYPE(dft_control_type), POINTER :: dft_control
112
113 NULLIFY (matrix_s, dft_control)
114
115 CALL get_qs_env(qs_env, matrix_s=matrix_s, dft_control=dft_control)
116 n_spins = dft_control%nspins
117 IF (dft_control%tddfpt_control%invert_S) THEN
118 DO spin = 1, n_spins
119 CALL copy_dbcsr_to_fm(matrix_s(1)%matrix, t_env%invS(spin))
120 CALL cp_fm_cholesky_decompose(t_env%invS(spin))
121 CALL cp_fm_cholesky_invert(t_env%invS(spin))
122 END DO
123 END IF
124
125 END SUBROUTINE tddfpt_env_init
126
127! **************************************************************************************************
128!> \brief ...
129!> \param t_env ...
130!> \param p_env ...
131! **************************************************************************************************
132 SUBROUTINE tddfpt_cleanup(t_env, p_env)
133
134 TYPE(tddfpt_env_type), INTENT(inout) :: t_env
135 TYPE(qs_p_env_type), INTENT(INOUT) :: p_env
136
137 CALL tddfpt_env_deallocate(t_env)
138 CALL p_env_release(p_env)
139
140 END SUBROUTINE tddfpt_cleanup
141
142! **************************************************************************************************
143!> \brief ...
144!> \param matrices ...
145!> \param energies ...
146!> \param n_v ...
147!> \param qs_env ...
148! **************************************************************************************************
149 SUBROUTINE co_initial_guess(matrices, energies, n_v, qs_env)
150
151 TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: matrices
152 REAL(kind=dp), DIMENSION(:), INTENT(OUT) :: energies
153 INTEGER, INTENT(IN) :: n_v
154 TYPE(qs_environment_type), POINTER :: qs_env
155
156 INTEGER :: i, n_cols, n_lumos, n_orbits, n_rows, &
157 n_spins, oo, spin, vo
158 REAL(kind=dp) :: evd
159 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: guess, lumos
160 REAL(kind=dp), DIMENSION(:), POINTER :: orbital_eigenvalues
161 TYPE(dft_control_type), POINTER :: dft_control
162 TYPE(simple_solution_sorter), POINTER :: sorter_iterator, sorter_pointer, &
163 sorter_start
164 TYPE(tddfpt_control_type), POINTER :: tddfpt_control
165
166! number of vectors to initialize
167
168 NULLIFY (dft_control)
169
170 CALL get_qs_env(qs_env, dft_control=dft_control)
171 tddfpt_control => dft_control%tddfpt_control
172 n_spins = dft_control%nspins
173 energies = 0.0_dp
174
175 IF (.NOT. ASSOCIATED(tddfpt_control%lumos)) THEN
176 cpabort("LUMOS missing")
177 END IF
178
179 DO spin = 1, n_spins
180
181 n_cols = matrices(1, spin)%matrix_struct%ncol_global
182 n_rows = matrices(1, spin)%matrix_struct%nrow_global
183
184 DO i = 1, n_v
185 CALL cp_fm_set_all(matrices(i, spin), 0.0_dp)
186 END DO
187
188 CALL get_mo_set(qs_env%mos(spin), eigenvalues=orbital_eigenvalues)
189
190 n_lumos = tddfpt_control%lumos(spin)%matrix_struct%ncol_global
191
192 n_orbits = SIZE(orbital_eigenvalues)
193
194 !-----------------------------------------!
195 ! create a SORTED list of initial guesses !
196 !-----------------------------------------!
197 ! first element
198 evd = tddfpt_control%lumos_eigenvalues(1, spin) - orbital_eigenvalues(n_orbits)
199 ALLOCATE (sorter_start)
200 sorter_start%orbit = n_orbits
201 sorter_start%lumo = 1
202 sorter_start%value = evd
203 NULLIFY (sorter_start%next)
204 ! rest of the elements
205 DO oo = n_orbits, 1, -1
206 DO vo = 1, n_lumos
207
208 IF (oo == n_orbits .AND. vo == 1) cycle ! already in list
209
210 evd = tddfpt_control%lumos_eigenvalues(vo, spin) - orbital_eigenvalues(oo)
211
212 sorter_iterator => sorter_start
213 NULLIFY (sorter_pointer)
214 DO WHILE (ASSOCIATED(sorter_iterator%next))
215 IF (sorter_iterator%next%value > evd) THEN
216 sorter_pointer => sorter_iterator%next
217 EXIT
218 END IF
219 sorter_iterator => sorter_iterator%next
220 END DO
221
222 ALLOCATE (sorter_iterator%next)
223 sorter_iterator%next%orbit = oo
224 sorter_iterator%next%lumo = vo
225 sorter_iterator%next%value = evd
226 sorter_iterator%next%next => sorter_pointer
227
228 END DO
229 END DO
230
231 ALLOCATE (lumos(n_rows, n_lumos), guess(n_rows, n_orbits))
232 CALL cp_fm_get_submatrix(tddfpt_control%lumos(spin), lumos, &
233 start_col=1, n_cols=n_lumos)
234
235 !-------------------!
236 ! fill the matrices !
237 !-------------------!
238 sorter_iterator => sorter_start
239 DO i = 1, min(n_v, n_orbits*n_lumos)
240 guess(:, :) = 0.0_dp
241 CALL dcopy(n_rows, lumos(:, sorter_iterator%lumo), 1, &
242 guess(:, sorter_iterator%orbit), 1)
243 CALL cp_fm_set_submatrix(matrices(i, spin), guess)
244 energies(i) = energies(i) + sorter_iterator%value/real(n_spins, dp)
245 sorter_iterator => sorter_iterator%next
246 END DO
247 IF (n_v > n_orbits*n_lumos) THEN
248 DO i = n_orbits*n_lumos + 1, n_v
249 CALL cp_fm_init_random(matrices(i, spin), n_orbits)
250 energies(i) = 1.0e38_dp
251 END DO
252 END IF
253
254 !--------------!
255 ! some cleanup !
256 !--------------!
257 DEALLOCATE (lumos, guess)
258 sorter_iterator => sorter_start
259 DO WHILE (ASSOCIATED(sorter_iterator))
260 sorter_pointer => sorter_iterator
261 sorter_iterator => sorter_iterator%next
262 DEALLOCATE (sorter_pointer)
263 END DO
264
265 END DO
266
267 END SUBROUTINE co_initial_guess
268
269! **************************************************************************************************
270!> \brief ...
271!> \param qs_env ...
272!> \param t_env ...
273! **************************************************************************************************
274 SUBROUTINE find_contributions(qs_env, t_env)
275
276 TYPE(qs_environment_type), POINTER :: qs_env
277 TYPE(tddfpt_env_type), INTENT(IN) :: t_env
278
279 INTEGER :: i, j, n_ev, n_spins, occ, output_unit, &
280 spin, virt
281 INTEGER, DIMENSION(2) :: nhomos, nlumos, nrows
282 REAL(kind=dp) :: contribution, summed_contributions
283 REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: homo_coeff_col, lumo_coeff_col
284 TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: s_lumos
285 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
286 TYPE(dft_control_type), POINTER :: dft_control
287 TYPE(tddfpt_control_type) :: t_control
288
289 NULLIFY (matrix_s, dft_control)
290 output_unit = cp_logger_get_default_io_unit()
291 CALL get_qs_env(qs_env, matrix_s=matrix_s, dft_control=dft_control)
292
293 IF (output_unit > 0) WRITE (output_unit, *)
294 IF (output_unit > 0) WRITE (output_unit, *)
295
296 t_control = dft_control%tddfpt_control
297 n_ev = t_control%n_ev
298 n_spins = dft_control%nspins
299
300 ALLOCATE (s_lumos(n_spins))
301
302 DO spin = 1, n_spins
303 nrows(spin) = t_control%lumos(spin)%matrix_struct%nrow_global
304 nhomos(spin) = t_env%evecs(1, spin)%matrix_struct%ncol_global
305 nlumos(spin) = t_control%lumos(spin)%matrix_struct%ncol_global
306 CALL cp_fm_create(s_lumos(spin), t_control%lumos(spin)%matrix_struct, &
307 "S times lumos")
308 CALL cp_dbcsr_sm_fm_multiply(matrix_s(1)%matrix, t_control%lumos(spin), &
309 s_lumos(spin), nlumos(spin), 1.0_dp, 0.0_dp)
310 END DO
311
312 ALLOCATE (homo_coeff_col(maxval(nrows(1:n_spins)), 1), &
313 lumo_coeff_col(maxval(nrows(1:n_spins)), 1))
314 DO i = 1, n_ev
315 IF (output_unit > 0) THEN
316 WRITE (output_unit, '(A,I3,5X,F15.6)') " excited state : ", i, t_env%evals(i)*evolt
317 WRITE (output_unit, *)
318 END IF
319 summed_contributions = 0.0_dp
320 DO spin = 1, n_spins
321 IF (n_spins == 2) THEN
322 IF (spin == 1) THEN
323 IF (output_unit > 0) WRITE (output_unit, *) 'alpha:'
324 ELSE
325 IF (output_unit > 0) WRITE (output_unit, *) 'beta:'
326 END IF
327 END IF
328 searchloop: DO occ = nhomos(spin), 1, -1
329 CALL cp_fm_get_submatrix(t_env%evecs(i, spin), homo_coeff_col, &
330 1, occ, nrows(spin), 1)
331 DO virt = 1, nlumos(spin)
332 CALL cp_fm_get_submatrix(s_lumos(spin), lumo_coeff_col, &
333 1, virt, nrows(spin), 1)
334 contribution = 0.0_dp
335 DO j = 1, nrows(spin)
336 contribution = contribution + homo_coeff_col(j, 1)*lumo_coeff_col(j, 1)
337 END DO
338 summed_contributions = summed_contributions + (contribution)**2
339 IF (abs(contribution) > 5.0e-2_dp) THEN
340 IF (output_unit > 0) WRITE (output_unit, '(14X,I5,A,I5,10X,F8.3,5X,F8.3)') &
341 occ, " ->", nhomos(spin) + virt, abs(contribution), summed_contributions
342 END IF
343 IF (abs(summed_contributions - 1.0_dp) < 1.0e-3_dp) cycle searchloop
344 END DO
345 END DO searchloop
346 END DO
347 IF (output_unit > 0) WRITE (output_unit, *)
348 END DO
349
350 !
351 ! punch a checksum for the regs
352 IF (output_unit > 0) THEN
353 WRITE (output_unit, '(T2,A,E14.6)') ' TDDFPT : CheckSum =', sqrt(sum(t_env%evals**2))
354 END IF
355
356 CALL cp_fm_release(s_lumos)
357
358 DEALLOCATE (homo_coeff_col, lumo_coeff_col)
359
360 END SUBROUTINE find_contributions
361
362! **************************************************************************************************
363!> \brief ...
364!> \param X ...
365!> \param tmp_vec ...
366!> \param metric ...
367! **************************************************************************************************
368 SUBROUTINE normalize(X, tmp_vec, metric)
369
370 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: x, tmp_vec
371 TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: metric
372
373 INTEGER :: n_spins, spin
374 REAL(kind=dp) :: norm, tmp
375
376 n_spins = SIZE(x)
377 norm = 0.0_dp
378
379 DO spin = 1, n_spins
380 tmp = 0.0_dp
381 CALL cp_dbcsr_sm_fm_multiply(metric(1)%matrix, x(spin), &
382 tmp_vec(spin), &
383 x(spin)%matrix_struct%ncol_global, &
384 1.0_dp, 0.0_dp)
385 CALL cp_fm_trace(x(spin), tmp_vec(spin), tmp)
386 norm = norm + tmp
387 END DO
388
389 norm = sqrt(norm)
390 DO spin = 1, n_spins
391 CALL cp_fm_scale((1.0_dp/norm), x(spin))
392 END DO
393
394 END SUBROUTINE normalize
395
396 !---------------------------------------!
397 ! x must not be changed in this routine !
398 ! tmp_vec may be changed !
399 !---------------------------------------!
400! **************************************************************************************************
401!> \brief ...
402!> \param X ...
403!> \param V_set ...
404!> \param SV_set ...
405!> \param work ...
406!> \param n ...
407! **************************************************************************************************
408 SUBROUTINE reorthogonalize(X, V_set, SV_set, work, n)
409
410 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: x
411 TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: v_set, sv_set
412 TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: work
413 INTEGER, INTENT(IN) :: n
414
415 CHARACTER(LEN=*), PARAMETER :: routinen = 'reorthogonalize'
416
417 INTEGER :: handle, i, n_spins, spin
418 REAL(dp) :: dot_product, tmp
419
420 CALL timeset(routinen, handle)
421
422 IF (n > 0) THEN
423
424 n_spins = SIZE(x)
425 DO spin = 1, n_spins
426 CALL cp_fm_to_fm(x(spin), work(spin))
427 END DO
428
429 DO i = 1, n
430 dot_product = 0.0_dp
431 DO spin = 1, n_spins
432 CALL cp_fm_trace(sv_set(i, spin), work(spin), tmp)
433 dot_product = dot_product + tmp
434 END DO
435 DO spin = 1, n_spins
436 CALL cp_fm_scale_and_add(1.0_dp, x(spin), &
437 -1.0_dp*dot_product, v_set(i, spin))
438 END DO
439 END DO
440
441 END IF
442
443 CALL timestop(handle)
444
445 END SUBROUTINE reorthogonalize
446
447! **************************************************************************************************
448
449END MODULE qs_tddfpt_utils
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
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.
basic linear algebra operations for full matrices
subroutine, public cp_fm_scale_and_add(alpha, matrix_a, beta, matrix_b)
calc A <- alpha*A + beta*B optimized for alpha == 1.0 (just add beta*B) and beta == 0....
subroutine, public cp_fm_scale(alpha, matrix_a)
scales a matrix matrix_a = alpha * matrix_b
various cholesky decomposition related routines
subroutine, public cp_fm_cholesky_invert(matrix, n, info_out)
used to replace the cholesky decomposition by the inverse
subroutine, public cp_fm_cholesky_decompose(matrix, n, info_out)
used to replace a symmetric positive def. matrix M with its cholesky decomposition U: M = U^T * U,...
represent a full matrix distributed on many processors
Definition cp_fm_types.F:15
subroutine, public cp_fm_set_submatrix(fm, new_values, start_row, start_col, n_rows, n_cols, alpha, beta, transpose)
sets a submatrix of a full matrix fm(start_row:start_row+n_rows,start_col:start_col+n_cols) = alpha*o...
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_init_random(matrix, ncol, start_col)
fills a matrix with random numbers
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...
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
Definition of physical constants:
Definition physcon.F:68
real(kind=dp), parameter, public evolt
Definition physcon.F:183
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_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, 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, rhs)
Get the QUICKSTEP environment.
Definition and initialisation of the mo data type.
Definition qs_mo_types.F:22
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.
Utility functions for the perturbation calculations.
subroutine, public p_env_psi0_changed(p_env, qs_env)
To be called after the value of psi0 has changed. Recalculates the quantities S_psi0 and m_epsilon.
subroutine, public p_env_create(p_env, qs_env, p1_option, p1_admm_option, orthogonal_orbitals, linres_control)
allocates and initializes the perturbation environment (no setup)
basis types for the calculation of the perturbation of density theory.
subroutine, public p_env_release(p_env)
relases the given p_env (see doc/ReferenceCounting.html)
subroutine, public tddfpt_env_deallocate(t_env)
...
subroutine, public tddfpt_env_allocate(t_env, p_env, qs_env)
...
subroutine, public reorthogonalize(x, v_set, sv_set, work, n)
...
subroutine, public find_contributions(qs_env, t_env)
...
subroutine, public normalize(x, tmp_vec, metric)
...
subroutine, public tddfpt_init(p_env, t_env, qs_env)
Initialize some necessary structures for a tddfpt calculation.
subroutine, public co_initial_guess(matrices, energies, n_v, qs_env)
...
subroutine, public tddfpt_cleanup(t_env, p_env)
...
represent a full matrix
Represent a qs system that is perturbed. Can calculate the linear operator and the rhs of the system ...