Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Calculates the moment integrals <a|r^m|b> and <a|r x d/dr|b>
10 : !> \par History
11 : !> added angular moments (JGH 11.2012)
12 : !> \author JGH (20.07.2006)
13 : ! **************************************************************************************************
14 : MODULE qs_moments
15 : USE ai_angmom, ONLY: angmom
16 : USE ai_moments, ONLY: contract_cossin, &
17 : cossin, &
18 : diff_momop, &
19 : diff_momop2, &
20 : diff_momop_velocity, &
21 : moment
22 : USE atomic_kind_types, ONLY: atomic_kind_type, &
23 : get_atomic_kind
24 : USE basis_set_types, ONLY: gto_basis_set_p_type, &
25 : gto_basis_set_type
26 : USE bibliography, ONLY: Mattiat2019, &
27 : cite_reference
28 : USE block_p_types, ONLY: block_p_type
29 : USE cell_types, ONLY: cell_type, &
30 : pbc, &
31 : get_cell
32 : USE commutator_rpnl, ONLY: build_com_mom_nl
33 : USE cp_blacs_env, ONLY: cp_blacs_env_type
34 : USE cp_cfm_basic_linalg, ONLY: cp_cfm_det
35 : USE cp_cfm_types, ONLY: cp_cfm_create, &
36 : cp_cfm_get_info, &
37 : cp_cfm_release, &
38 : cp_cfm_type
39 : USE cp_control_types, ONLY: dft_control_type
40 : USE cp_dbcsr_api, ONLY: &
41 : dbcsr_copy, dbcsr_create, dbcsr_deallocate_matrix, dbcsr_distribution_type, &
42 : dbcsr_get_block_p, dbcsr_get_info, dbcsr_init_p, dbcsr_multiply, dbcsr_p_type, &
43 : dbcsr_set, dbcsr_type, dbcsr_type_antisymmetric, dbcsr_type_no_symmetry, dbcsr_type_symmetric
44 : USE cp_dbcsr_contrib, ONLY: dbcsr_dot, &
45 : dbcsr_trace
46 : USE cp_dbcsr_cp2k_link, ONLY: cp_dbcsr_alloc_block_from_nbl
47 : USE cp_dbcsr_operations, ONLY: cp_dbcsr_sm_fm_multiply, &
48 : dbcsr_allocate_matrix_set, &
49 : dbcsr_deallocate_matrix_set
50 : USE cp_fm_struct, ONLY: cp_fm_struct_create, &
51 : cp_fm_struct_double, &
52 : cp_fm_struct_release, &
53 : cp_fm_struct_type
54 : USE cp_fm_types, ONLY: cp_fm_copy_general, &
55 : cp_fm_create, &
56 : cp_fm_get_element, &
57 : cp_fm_get_info, &
58 : cp_fm_release, &
59 : cp_fm_set_all, &
60 : cp_fm_type
61 : USE cp_result_methods, ONLY: cp_results_erase, &
62 : put_results
63 : USE cp_result_types, ONLY: cp_result_type
64 : USE distribution_1d_types, ONLY: distribution_1d_type
65 : USE kinds, ONLY: default_string_length, &
66 : dp, &
67 : max_line_length
68 : USE kpoint_k_r_trafo_simple, ONLY: replicate_rs_matrices, &
69 : rs_to_kp
70 : USE kpoint_methods, ONLY: kpoint_init_cell_index, &
71 : kpoint_initialize, &
72 : rskp_transform
73 : USE kpoint_types, ONLY: get_kpoint_info, &
74 : kpoint_env_p_type, &
75 : kpoint_env_type, &
76 : kpoint_type, &
77 : kpoint_create, &
78 : kpoint_release, &
79 : read_kpoint_section
80 : USE mathconstants, ONLY: pi, &
81 : twopi, &
82 : gaussi, &
83 : z_zero
84 : USE message_passing, ONLY: mp_para_env_type
85 : USE moments_utils, ONLY: get_reference_point
86 : USE orbital_pointers, ONLY: current_maxl, &
87 : indco, &
88 : ncoset
89 : USE parallel_gemm_api, ONLY: parallel_gemm
90 : USE particle_methods, ONLY: get_particle_set
91 : USE particle_types, ONLY: particle_type
92 : USE physcon, ONLY: bohr, &
93 : debye, &
94 : angstrom
95 : USE qs_environment_types, ONLY: get_qs_env, &
96 : qs_environment_type
97 : USE qs_kind_types, ONLY: get_qs_kind, &
98 : get_qs_kind_set, &
99 : qs_kind_type
100 : USE qs_ks_types, ONLY: get_ks_env, &
101 : qs_ks_env_type
102 : USE qs_mo_types, ONLY: get_mo_set, &
103 : mo_set_type
104 : USE qs_neighbor_list_types, ONLY: get_iterator_info, &
105 : neighbor_list_iterate, &
106 : neighbor_list_iterator_create, &
107 : neighbor_list_iterator_p_type, &
108 : neighbor_list_iterator_release, &
109 : neighbor_list_set_p_type
110 : USE qs_operators_ao, ONLY: build_lin_mom_matrix
111 : USE qs_overlap, ONLY: build_overlap_matrix
112 : USE qs_rho_types, ONLY: qs_rho_get, &
113 : qs_rho_type
114 : USE rt_propagation_types, ONLY: get_rtp, &
115 : rt_prop_type
116 : USE cp_parser_methods, ONLY: read_float_object
117 : USE input_section_types, ONLY: section_vals_get, &
118 : section_vals_get_subs_vals, &
119 : section_vals_type, &
120 : section_vals_val_get
121 : USE mathlib, ONLY: geeig_right, &
122 : gemm_square
123 : USE string_utilities, ONLY: uppercase
124 :
125 : #include "./base/base_uses.f90"
126 :
127 : IMPLICIT NONE
128 :
129 : PRIVATE
130 :
131 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_moments'
132 :
133 : ! Public subroutines
134 : PUBLIC :: build_berry_moment_matrix, build_local_moment_matrix
135 : PUBLIC :: build_berry_kpoint_matrix, build_local_magmom_matrix
136 : PUBLIC :: qs_moment_berry_phase, qs_moment_locop
137 : PUBLIC :: qs_moment_kpoints, build_local_moment_matrix_rs_img
138 : PUBLIC :: qs_moment_kpoints_deep
139 : PUBLIC :: qs_moment_kpoints_scf_mos
140 : PUBLIC :: dipole_deriv_ao
141 : PUBLIC :: build_local_moments_der_matrix
142 : PUBLIC :: build_dsdv_moments
143 : PUBLIC :: dipole_velocity_deriv
144 : PUBLIC :: calculate_commutator_nl_terms, op_orbbas, op_orbbas_rtp, &
145 : print_moments, print_moments_nl, set_label
146 :
147 : CONTAINS
148 :
149 : ! *****************************************************************************
150 : !> \brief This returns the derivative of the moment integrals [a|\mu|b], with respect
151 : !> to the basis function on the right
152 : !> difdip(beta, alpha) = < mu | r_beta | ∂_alpha nu > * (mu - nu)
153 : !> \param qs_env ...
154 : !> \param difdip ...
155 : !> \param order The order of the derivative (1 for dipole moment)
156 : !> \param lambda The atom on which we take the derivative
157 : !> \param rc ...
158 : !> \author Edward Ditler
159 : ! **************************************************************************************************
160 6 : SUBROUTINE dipole_velocity_deriv(qs_env, difdip, order, lambda, rc)
161 : TYPE(qs_environment_type), POINTER :: qs_env
162 : TYPE(dbcsr_p_type), DIMENSION(:, :), INTENT(INOUT) :: difdip
163 : INTEGER, INTENT(IN) :: order, lambda
164 : REAL(KIND=dp), DIMENSION(3) :: rc
165 :
166 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dipole_velocity_deriv'
167 :
168 : INTEGER :: handle, i, iatom, icol, idir, ikind, inode, irow, iset, j, jatom, jkind, jset, &
169 : last_jatom, lda, ldab, ldb, M_dim, maxsgf, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
170 : sgfb
171 : LOGICAL :: found
172 : REAL(dp) :: dab
173 : REAL(dp), DIMENSION(3) :: ra, rab, rac, rb, rbc
174 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
175 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mab
176 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: difmab, difmab2
177 6 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :) :: mint, mint2
178 : TYPE(cell_type), POINTER :: cell
179 6 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
180 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
181 : TYPE(neighbor_list_iterator_p_type), &
182 6 : DIMENSION(:), POINTER :: nl_iterator
183 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
184 6 : POINTER :: sab_all
185 6 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
186 6 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
187 : TYPE(qs_kind_type), POINTER :: qs_kind
188 :
189 6 : CALL timeset(routineN, handle)
190 :
191 6 : NULLIFY (cell, particle_set, qs_kind_set, sab_all)
192 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, &
193 6 : qs_kind_set=qs_kind_set, sab_all=sab_all)
194 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
195 6 : maxco=ldab, maxsgf=maxsgf)
196 :
197 6 : nkind = SIZE(qs_kind_set)
198 6 : natom = SIZE(particle_set)
199 :
200 6 : M_dim = ncoset(order) - 1
201 :
202 30 : ALLOCATE (basis_set_list(nkind))
203 :
204 30 : ALLOCATE (mab(ldab, ldab, M_dim))
205 36 : ALLOCATE (difmab2(ldab, ldab, M_dim, 3))
206 24 : ALLOCATE (work(ldab, maxsgf))
207 78 : ALLOCATE (mint(3, 3))
208 78 : ALLOCATE (mint2(3, 3))
209 :
210 4920 : mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
211 14766 : difmab2(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
212 414 : work(1:ldab, 1:maxsgf) = 0.0_dp
213 :
214 24 : DO i = 1, 3
215 78 : DO j = 1, 3
216 54 : NULLIFY (mint(i, j)%block)
217 72 : NULLIFY (mint2(i, j)%block)
218 : END DO
219 : END DO
220 :
221 : ! Set the basis_set_list(nkind) to point to the corresponding basis sets
222 18 : DO ikind = 1, nkind
223 12 : qs_kind => qs_kind_set(ikind)
224 12 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
225 18 : IF (ASSOCIATED(basis_set_a)) THEN
226 12 : basis_set_list(ikind)%gto_basis_set => basis_set_a
227 : ELSE
228 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
229 : END IF
230 : END DO
231 :
232 6 : CALL neighbor_list_iterator_create(nl_iterator, sab_all)
233 33 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
234 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
235 27 : iatom=iatom, jatom=jatom, r=rab)
236 :
237 27 : basis_set_a => basis_set_list(ikind)%gto_basis_set
238 27 : basis_set_b => basis_set_list(jkind)%gto_basis_set
239 27 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
240 27 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
241 :
242 : ASSOCIATE ( &
243 : ! basis ikind
244 : first_sgfa => basis_set_a%first_sgf, &
245 : la_max => basis_set_a%lmax, &
246 : la_min => basis_set_a%lmin, &
247 : npgfa => basis_set_a%npgf, &
248 : nsgfa => basis_set_a%nsgf_set, &
249 : rpgfa => basis_set_a%pgf_radius, &
250 : set_radius_a => basis_set_a%set_radius, &
251 : sphi_a => basis_set_a%sphi, &
252 : zeta => basis_set_a%zet, &
253 : ! basis jkind, &
254 : first_sgfb => basis_set_b%first_sgf, &
255 : lb_max => basis_set_b%lmax, &
256 : lb_min => basis_set_b%lmin, &
257 : npgfb => basis_set_b%npgf, &
258 : nsgfb => basis_set_b%nsgf_set, &
259 : rpgfb => basis_set_b%pgf_radius, &
260 : set_radius_b => basis_set_b%set_radius, &
261 : sphi_b => basis_set_b%sphi, &
262 : zetb => basis_set_b%zet)
263 :
264 27 : nseta = basis_set_a%nset
265 27 : nsetb = basis_set_b%nset
266 :
267 18 : IF (inode == 1) last_jatom = 0
268 :
269 : ! this guarantees minimum image convention
270 : ! anything else would not make sense
271 27 : IF (jatom == last_jatom) THEN
272 : CYCLE
273 : END IF
274 :
275 27 : last_jatom = jatom
276 :
277 27 : irow = iatom
278 27 : icol = jatom
279 :
280 108 : DO i = 1, 3
281 351 : DO j = 1, 3
282 243 : NULLIFY (mint(i, j)%block)
283 : CALL dbcsr_get_block_p(matrix=difdip(i, j)%matrix, &
284 : row=irow, col=icol, BLOCK=mint(i, j)%block, &
285 243 : found=found)
286 243 : CPASSERT(found)
287 2025 : mint(i, j)%block = 0._dp
288 : END DO
289 : END DO
290 :
291 : ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
292 27 : ra = pbc(particle_set(iatom)%r(:), cell)
293 108 : rb(:) = ra(:) + rab(:)
294 27 : rac = pbc(rc, ra, cell)
295 108 : rbc = rac + rab
296 108 : dab = norm2(rab)
297 :
298 81 : DO iset = 1, nseta
299 27 : ncoa = npgfa(iset)*ncoset(la_max(iset))
300 27 : sgfa = first_sgfa(1, iset)
301 81 : DO jset = 1, nsetb
302 27 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
303 27 : ncob = npgfb(jset)*ncoset(lb_max(jset))
304 27 : sgfb = first_sgfb(1, jset)
305 27 : ldab = MAX(ncoa, ncob)
306 27 : lda = ncoset(la_max(iset))*npgfa(iset)
307 27 : ldb = ncoset(lb_max(jset))*npgfb(jset)
308 162 : ALLOCATE (difmab(lda, ldb, M_dim, 3))
309 :
310 : ! Calculate integral difmab(beta, alpha) = (a|r_beta|db_alpha)
311 : ! difmab(beta, alpha) = < a | r_beta | ∂_alpha b >
312 : ! difmab(j, idir) = < a | r_j | ∂_idir b >
313 : CALL diff_momop_velocity(la_max(iset), npgfa(iset), zeta(:, iset), &
314 : rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
315 : zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
316 27 : difmab, lambda=lambda, iatom=iatom, jatom=jatom)
317 :
318 : ! *** Contraction step ***
319 :
320 108 : DO idir = 1, 3 ! derivative of AO function
321 351 : DO j = 1, 3 ! position operator r_j
322 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
323 : 1.0_dp, difmab(1, 1, j, idir), SIZE(difmab, 1), &
324 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
325 243 : 0.0_dp, work(1, 1), SIZE(work, 1))
326 :
327 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
328 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
329 : work(1, 1), SIZE(work, 1), &
330 : 1.0_dp, mint(j, idir)%block(sgfa, sgfb), &
331 324 : SIZE(mint(j, idir)%block, 1))
332 : END DO !j
333 : END DO !idir
334 54 : DEALLOCATE (difmab)
335 : END DO !jset
336 : END DO !iset
337 : END ASSOCIATE
338 : END DO!iterator
339 :
340 6 : CALL neighbor_list_iterator_release(nl_iterator)
341 :
342 24 : DO i = 1, 3
343 78 : DO j = 1, 3
344 72 : NULLIFY (mint(i, j)%block)
345 : END DO
346 : END DO
347 :
348 6 : DEALLOCATE (mab, difmab2, basis_set_list, work, mint, mint2)
349 :
350 6 : CALL timestop(handle)
351 18 : END SUBROUTINE dipole_velocity_deriv
352 :
353 : ! **************************************************************************************************
354 : !> \brief Builds the moments for the derivative of the overlap with respect to nuclear velocities
355 : !> \param qs_env ...
356 : !> \param moments ...
357 : !> \param nmoments ...
358 : !> \param ref_point ...
359 : !> \param ref_points ...
360 : !> \param basis_type ...
361 : !> \author Edward Ditler
362 : ! **************************************************************************************************
363 6 : SUBROUTINE build_dsdv_moments(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
364 :
365 : TYPE(qs_environment_type), POINTER :: qs_env
366 : TYPE(dbcsr_p_type), DIMENSION(:) :: moments
367 : INTEGER, INTENT(IN) :: nmoments
368 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: ref_point
369 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
370 : OPTIONAL :: ref_points
371 : CHARACTER(len=*), OPTIONAL :: basis_type
372 :
373 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_dsdv_moments'
374 :
375 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
376 : maxco, maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
377 : INTEGER, DIMENSION(3) :: image_cell
378 : LOGICAL :: found
379 : REAL(KIND=dp) :: dab
380 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
381 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mab
382 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
383 6 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: mint
384 : TYPE(cell_type), POINTER :: cell
385 6 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
386 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
387 : TYPE(neighbor_list_iterator_p_type), &
388 6 : DIMENSION(:), POINTER :: nl_iterator
389 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
390 6 : POINTER :: sab_orb
391 6 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
392 6 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
393 : TYPE(qs_kind_type), POINTER :: qs_kind
394 :
395 6 : IF (nmoments < 1) RETURN
396 :
397 6 : CALL timeset(routineN, handle)
398 :
399 6 : NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
400 :
401 6 : nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
402 6 : CPASSERT(SIZE(moments) >= nm)
403 :
404 6 : NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
405 : CALL get_qs_env(qs_env=qs_env, &
406 : qs_kind_set=qs_kind_set, &
407 : particle_set=particle_set, cell=cell, &
408 6 : sab_orb=sab_orb)
409 :
410 6 : nkind = SIZE(qs_kind_set)
411 6 : natom = SIZE(particle_set)
412 :
413 : ! Allocate work storage
414 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
415 : maxco=maxco, maxsgf=maxsgf, &
416 12 : basis_type=basis_type)
417 :
418 30 : ALLOCATE (mab(maxco, maxco, nm))
419 6 : mab(:, :, :) = 0.0_dp
420 :
421 24 : ALLOCATE (work(maxco, maxsgf))
422 6 : work(:, :) = 0.0_dp
423 :
424 36 : ALLOCATE (mint(nm))
425 24 : DO i = 1, nm
426 24 : NULLIFY (mint(i)%block)
427 : END DO
428 :
429 30 : ALLOCATE (basis_set_list(nkind))
430 18 : DO ikind = 1, nkind
431 12 : qs_kind => qs_kind_set(ikind)
432 12 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
433 18 : IF (ASSOCIATED(basis_set_a)) THEN
434 12 : basis_set_list(ikind)%gto_basis_set => basis_set_a
435 : ELSE
436 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
437 : END IF
438 : END DO
439 6 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
440 24 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
441 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
442 18 : iatom=iatom, jatom=jatom, r=rab, cell=image_cell)
443 18 : basis_set_a => basis_set_list(ikind)%gto_basis_set
444 18 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
445 18 : basis_set_b => basis_set_list(jkind)%gto_basis_set
446 18 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
447 : ! basis ikind
448 : ASSOCIATE ( &
449 : first_sgfa => basis_set_a%first_sgf, &
450 : la_max => basis_set_a%lmax, &
451 : la_min => basis_set_a%lmin, &
452 : npgfa => basis_set_a%npgf, &
453 : nsgfa => basis_set_a%nsgf_set, &
454 : rpgfa => basis_set_a%pgf_radius, &
455 : set_radius_a => basis_set_a%set_radius, &
456 : sphi_a => basis_set_a%sphi, &
457 : zeta => basis_set_a%zet, &
458 : ! basis jkind, &
459 : first_sgfb => basis_set_b%first_sgf, &
460 : lb_max => basis_set_b%lmax, &
461 : lb_min => basis_set_b%lmin, &
462 : npgfb => basis_set_b%npgf, &
463 : nsgfb => basis_set_b%nsgf_set, &
464 : rpgfb => basis_set_b%pgf_radius, &
465 : set_radius_b => basis_set_b%set_radius, &
466 : sphi_b => basis_set_b%sphi, &
467 : zetb => basis_set_b%zet)
468 :
469 18 : nseta = basis_set_a%nset
470 18 : nsetb = basis_set_b%nset
471 :
472 15 : IF (inode == 1) last_jatom = 0
473 :
474 : ! this guarantees minimum image convention
475 : ! anything else would not make sense
476 18 : IF (jatom == last_jatom) THEN
477 : CYCLE
478 : END IF
479 :
480 18 : last_jatom = jatom
481 :
482 18 : IF (iatom <= jatom) THEN
483 12 : irow = iatom
484 12 : icol = jatom
485 : ELSE
486 6 : irow = jatom
487 6 : icol = iatom
488 : END IF
489 :
490 72 : DO i = 1, nm
491 54 : NULLIFY (mint(i)%block)
492 : CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
493 54 : row=irow, col=icol, BLOCK=mint(i)%block, found=found)
494 396 : mint(i)%block = 0._dp
495 : END DO
496 :
497 : ! fold atomic position back into unit cell
498 18 : IF (PRESENT(ref_points)) THEN
499 0 : rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
500 18 : ELSE IF (PRESENT(ref_point)) THEN
501 72 : rc(:) = ref_point(:)
502 : ELSE
503 0 : rc(:) = 0._dp
504 : END IF
505 : ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
506 : ! by folding around the center, such screwing can be avoided for a proper choice of center.
507 : ! we dont use PBC at this point
508 :
509 : ! With and without MIC, rab(:) is the vector giving us the coordinates of rb.
510 72 : ra(:) = particle_set(iatom)%r(:)
511 72 : rb(:) = ra(:) + rab(:)
512 18 : rac = pbc(rc, ra, cell)
513 72 : rbc = rac + rab
514 :
515 72 : dab = NORM2(rab)
516 :
517 54 : DO iset = 1, nseta
518 :
519 18 : ncoa = npgfa(iset)*ncoset(la_max(iset))
520 18 : sgfa = first_sgfa(1, iset)
521 :
522 54 : DO jset = 1, nsetb
523 :
524 18 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
525 :
526 18 : ncob = npgfb(jset)*ncoset(lb_max(jset))
527 18 : sgfb = first_sgfb(1, jset)
528 :
529 : ! Calculate the primitive integrals
530 : CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
531 : rpgfa(:, iset), la_min(iset), &
532 : lb_max(jset), npgfb(jset), zetb(:, jset), &
533 18 : rpgfb(:, jset), nmoments, rac, rbc, mab)
534 :
535 : ! Contraction step
536 90 : DO i = 1, nm
537 :
538 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
539 : 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
540 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
541 54 : 0.0_dp, work(1, 1), SIZE(work, 1))
542 :
543 72 : IF (iatom <= jatom) THEN
544 :
545 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
546 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
547 : work(1, 1), SIZE(work, 1), &
548 : 1.0_dp, mint(i)%block(sgfa, sgfb), &
549 36 : SIZE(mint(i)%block, 1))
550 :
551 : ELSE
552 :
553 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
554 : 1.0_dp, work(1, 1), SIZE(work, 1), &
555 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
556 : 1.0_dp, mint(i)%block(sgfb, sgfa), &
557 18 : SIZE(mint(i)%block, 1))
558 :
559 : END IF
560 :
561 : END DO
562 :
563 : END DO
564 : END DO
565 : END ASSOCIATE
566 :
567 : END DO ! iterator
568 :
569 6 : CALL neighbor_list_iterator_release(nl_iterator)
570 :
571 : ! Release work storage
572 6 : DEALLOCATE (mab, basis_set_list)
573 6 : DEALLOCATE (work)
574 24 : DO i = 1, nm
575 24 : NULLIFY (mint(i)%block)
576 : END DO
577 6 : DEALLOCATE (mint)
578 :
579 6 : CALL timestop(handle)
580 :
581 12 : END SUBROUTINE build_dsdv_moments
582 :
583 : ! **************************************************************************************************
584 : !> \brief ...
585 : !> \param qs_env ...
586 : !> \param moments ...
587 : !> \param nmoments ...
588 : !> \param ref_point ...
589 : !> \param ref_points ...
590 : !> \param basis_type ...
591 : ! **************************************************************************************************
592 2990 : SUBROUTINE build_local_moment_matrix(qs_env, moments, nmoments, ref_point, ref_points, basis_type)
593 :
594 : TYPE(qs_environment_type), POINTER :: qs_env
595 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: moments
596 : INTEGER, INTENT(IN) :: nmoments
597 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: ref_point
598 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
599 : OPTIONAL :: ref_points
600 : CHARACTER(len=*), OPTIONAL :: basis_type
601 :
602 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_moment_matrix'
603 :
604 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
605 : maxco, maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
606 : LOGICAL :: found
607 : REAL(KIND=dp) :: dab
608 2990 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
609 2990 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mab
610 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
611 2990 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: mint
612 : TYPE(cell_type), POINTER :: cell
613 2990 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
614 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
615 : TYPE(neighbor_list_iterator_p_type), &
616 2990 : DIMENSION(:), POINTER :: nl_iterator
617 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
618 2990 : POINTER :: sab_orb
619 2990 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
620 2990 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
621 : TYPE(qs_kind_type), POINTER :: qs_kind
622 :
623 2990 : IF (nmoments < 1) RETURN
624 :
625 2990 : CALL timeset(routineN, handle)
626 :
627 2990 : NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
628 :
629 2990 : nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
630 2990 : CPASSERT(SIZE(moments) >= nm)
631 :
632 2990 : NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
633 : CALL get_qs_env(qs_env=qs_env, &
634 : qs_kind_set=qs_kind_set, &
635 : particle_set=particle_set, cell=cell, &
636 2990 : sab_orb=sab_orb)
637 :
638 2990 : nkind = SIZE(qs_kind_set)
639 2990 : natom = SIZE(particle_set)
640 :
641 : ! Allocate work storage
642 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
643 : maxco=maxco, maxsgf=maxsgf, &
644 5874 : basis_type=basis_type)
645 :
646 14950 : ALLOCATE (mab(maxco, maxco, nm))
647 2990 : mab(:, :, :) = 0.0_dp
648 :
649 11960 : ALLOCATE (work(maxco, maxsgf))
650 2990 : work(:, :) = 0.0_dp
651 :
652 18110 : ALLOCATE (mint(nm))
653 12130 : DO i = 1, nm
654 12130 : NULLIFY (mint(i)%block)
655 : END DO
656 :
657 15126 : ALLOCATE (basis_set_list(nkind))
658 9146 : DO ikind = 1, nkind
659 6156 : qs_kind => qs_kind_set(ikind)
660 6156 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
661 9146 : IF (ASSOCIATED(basis_set_a)) THEN
662 6156 : basis_set_list(ikind)%gto_basis_set => basis_set_a
663 : ELSE
664 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
665 : END IF
666 : END DO
667 2990 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
668 37746 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
669 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
670 34756 : iatom=iatom, jatom=jatom, r=rab)
671 34756 : basis_set_a => basis_set_list(ikind)%gto_basis_set
672 34756 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
673 34756 : basis_set_b => basis_set_list(jkind)%gto_basis_set
674 34756 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
675 : ASSOCIATE ( &
676 : ! basis ikind
677 : first_sgfa => basis_set_a%first_sgf, &
678 : la_max => basis_set_a%lmax, &
679 : la_min => basis_set_a%lmin, &
680 : npgfa => basis_set_a%npgf, &
681 : nsgfa => basis_set_a%nsgf_set, &
682 : rpgfa => basis_set_a%pgf_radius, &
683 : set_radius_a => basis_set_a%set_radius, &
684 : sphi_a => basis_set_a%sphi, &
685 : zeta => basis_set_a%zet, &
686 : ! basis jkind, &
687 : first_sgfb => basis_set_b%first_sgf, &
688 : lb_max => basis_set_b%lmax, &
689 : lb_min => basis_set_b%lmin, &
690 : npgfb => basis_set_b%npgf, &
691 : nsgfb => basis_set_b%nsgf_set, &
692 : rpgfb => basis_set_b%pgf_radius, &
693 : set_radius_b => basis_set_b%set_radius, &
694 : sphi_b => basis_set_b%sphi, &
695 : zetb => basis_set_b%zet)
696 :
697 34756 : nseta = basis_set_a%nset
698 34756 : nsetb = basis_set_b%nset
699 :
700 8641 : IF (inode == 1) last_jatom = 0
701 :
702 : ! this guarantees minimum image convention
703 : ! anything else would not make sense
704 34756 : IF (jatom == last_jatom) THEN
705 : CYCLE
706 : END IF
707 :
708 12276 : last_jatom = jatom
709 :
710 12276 : IF (iatom <= jatom) THEN
711 7599 : irow = iatom
712 7599 : icol = jatom
713 : ELSE
714 4677 : irow = jatom
715 4677 : icol = iatom
716 : END IF
717 :
718 49974 : DO i = 1, nm
719 37698 : NULLIFY (mint(i)%block)
720 : CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
721 37698 : row=irow, col=icol, BLOCK=mint(i)%block, found=found)
722 1728241 : mint(i)%block = 0._dp
723 : END DO
724 :
725 : ! fold atomic position back into unit cell
726 12276 : IF (PRESENT(ref_points)) THEN
727 0 : rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
728 12276 : ELSE IF (PRESENT(ref_point)) THEN
729 46456 : rc(:) = ref_point(:)
730 : ELSE
731 662 : rc(:) = 0._dp
732 : END IF
733 : ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
734 : ! by folding around the center, such screwing can be avoided for a proper choice of center.
735 98208 : ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
736 98208 : rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
737 : ! we dont use PBC at this point
738 49104 : rab(:) = ra(:) - rb(:)
739 49104 : rac(:) = ra(:) - rc(:)
740 49104 : rbc(:) = rb(:) - rc(:)
741 49104 : dab = NORM2(rab)
742 :
743 64944 : DO iset = 1, nseta
744 :
745 17912 : ncoa = npgfa(iset)*ncoset(la_max(iset))
746 17912 : sgfa = first_sgfa(1, iset)
747 :
748 59682 : DO jset = 1, nsetb
749 :
750 29494 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
751 :
752 29197 : ncob = npgfb(jset)*ncoset(lb_max(jset))
753 29197 : sgfb = first_sgfb(1, jset)
754 :
755 : ! Calculate the primitive integrals
756 : CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), &
757 : rpgfa(:, iset), la_min(iset), &
758 : lb_max(jset), npgfb(jset), zetb(:, jset), &
759 29197 : rpgfb(:, jset), nmoments, rac, rbc, mab)
760 :
761 : ! Contraction step
762 140130 : DO i = 1, nm
763 :
764 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
765 : 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
766 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
767 93021 : 0.0_dp, work(1, 1), SIZE(work, 1))
768 :
769 122515 : IF (iatom <= jatom) THEN
770 :
771 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
772 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
773 : work(1, 1), SIZE(work, 1), &
774 : 1.0_dp, mint(i)%block(sgfa, sgfb), &
775 59755 : SIZE(mint(i)%block, 1))
776 :
777 : ELSE
778 :
779 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
780 : 1.0_dp, work(1, 1), SIZE(work, 1), &
781 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
782 : 1.0_dp, mint(i)%block(sgfb, sgfa), &
783 33266 : SIZE(mint(i)%block, 1))
784 :
785 : END IF
786 :
787 : END DO
788 :
789 : END DO
790 : END DO
791 : END ASSOCIATE
792 :
793 : END DO
794 2990 : CALL neighbor_list_iterator_release(nl_iterator)
795 :
796 : ! Release work storage
797 2990 : DEALLOCATE (mab, basis_set_list)
798 2990 : DEALLOCATE (work)
799 12130 : DO i = 1, nm
800 12130 : NULLIFY (mint(i)%block)
801 : END DO
802 2990 : DEALLOCATE (mint)
803 :
804 2990 : CALL timestop(handle)
805 :
806 5980 : END SUBROUTINE build_local_moment_matrix
807 :
808 : ! **************************************************************************************************
809 : !> \brief Calculate right-hand sided derivatives of multipole moments, e. g. < a | xy d/dz | b >
810 : !> Optionally stores the multipole moments themselves for free.
811 : !> Note that the multipole moments are symmetric while their derivatives are anti-symmetric
812 : !> Only first derivatives are performed, e. g. x d/dy
813 : !> \param qs_env ...
814 : !> \param moments_der will contain the derivatives of the multipole moments
815 : !> \param nmoments_der order of the moments with derivatives
816 : !> \param nmoments order of the multipole moments (no derivatives, same output as
817 : !> build_local_moment_matrix, needs moments as arguments to store results)
818 : !> \param ref_point ...
819 : !> \param moments contains the multipole moments, optionally for free, up to order nmoments
820 : !> \note
821 : !> Adapted from rRc_xyz_der_ao in qs_operators_ao
822 : ! **************************************************************************************************
823 42 : SUBROUTINE build_local_moments_der_matrix(qs_env, moments_der, nmoments_der, nmoments, &
824 42 : ref_point, moments)
825 : TYPE(qs_environment_type), POINTER :: qs_env
826 : TYPE(dbcsr_p_type), DIMENSION(:, :), &
827 : INTENT(INOUT), POINTER :: moments_der
828 : INTEGER, INTENT(IN) :: nmoments_der, nmoments
829 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: ref_point
830 : TYPE(dbcsr_p_type), DIMENSION(:), INTENT(INOUT), &
831 : OPTIONAL, POINTER :: moments
832 :
833 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_moments_der_matrix'
834 :
835 : INTEGER :: dimders, handle, i, iatom, icol, ider, ii, ikind, inode, ipgf, irow, iset, j, &
836 : jatom, jkind, jpgf, jset, last_jatom, M_dim, maxco, maxsgf, na, nb, ncoa, ncob, nda, ndb, &
837 : nders, nkind, nm, nmom_build, nseta, nsetb, sgfa, sgfb
838 : LOGICAL :: found
839 : REAL(KIND=dp) :: dab
840 42 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
841 42 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mab
842 42 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: difmab
843 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
844 42 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: mab_tmp
845 42 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: mom_block
846 42 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :) :: mom_block_der
847 : TYPE(cell_type), POINTER :: cell
848 42 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
849 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
850 : TYPE(neighbor_list_iterator_p_type), &
851 42 : DIMENSION(:), POINTER :: nl_iterator
852 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
853 42 : POINTER :: sab_orb
854 42 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
855 42 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
856 : TYPE(qs_kind_type), POINTER :: qs_kind
857 :
858 42 : nmom_build = MAX(nmoments, nmoments_der) ! build moments up to order nmom_buiod
859 42 : IF (nmom_build < 1) RETURN
860 :
861 42 : CALL timeset(routineN, handle)
862 :
863 42 : nders = 1 ! only first order derivatives
864 42 : dimders = ncoset(nders) - 1
865 :
866 42 : NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
867 : CALL get_qs_env(qs_env=qs_env, &
868 : qs_kind_set=qs_kind_set, &
869 : particle_set=particle_set, &
870 : cell=cell, &
871 42 : sab_orb=sab_orb)
872 :
873 42 : nkind = SIZE(qs_kind_set)
874 :
875 : ! Work storage
876 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
877 42 : maxco=maxco, maxsgf=maxsgf)
878 :
879 42 : IF (nmoments > 0) THEN
880 40 : CPASSERT(PRESENT(moments))
881 40 : nm = (6 + 11*nmoments + 6*nmoments**2 + nmoments**3)/6 - 1
882 40 : CPASSERT(SIZE(moments) == nm)
883 : ! storage for integrals
884 200 : ALLOCATE (mab(maxco, maxco, nm))
885 : ! blocks
886 40 : mab(:, :, :) = 0.0_dp
887 480 : ALLOCATE (mom_block(nm))
888 400 : DO i = 1, nm
889 400 : NULLIFY (mom_block(i)%block)
890 : END DO
891 : END IF
892 :
893 42 : IF (nmoments_der > 0) THEN
894 42 : M_dim = ncoset(nmoments_der) - 1
895 42 : CPASSERT(SIZE(moments_der, dim=1) == M_dim)
896 42 : CPASSERT(SIZE(moments_der, dim=2) == dimders)
897 : ! storage for integrals
898 252 : ALLOCATE (difmab(maxco, maxco, M_dim, dimders))
899 42 : difmab(:, :, :, :) = 0.0_dp
900 : ! blocks
901 708 : ALLOCATE (mom_block_der(M_dim, dimders))
902 180 : DO i = 1, M_dim
903 594 : DO ider = 1, dimders
904 552 : NULLIFY (mom_block_der(i, ider)%block)
905 : END DO
906 : END DO
907 : END IF
908 :
909 168 : ALLOCATE (work(maxco, maxsgf))
910 42 : work(:, :) = 0.0_dp
911 :
912 42 : NULLIFY (basis_set_a, basis_set_b, basis_set_list)
913 42 : NULLIFY (qs_kind)
914 200 : ALLOCATE (basis_set_list(nkind))
915 116 : DO ikind = 1, nkind
916 74 : qs_kind => qs_kind_set(ikind)
917 74 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
918 116 : IF (ASSOCIATED(basis_set_a)) THEN
919 74 : basis_set_list(ikind)%gto_basis_set => basis_set_a
920 : ELSE
921 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
922 : END IF
923 : END DO
924 :
925 : ! Calculate derivatives looping over neighbour list
926 42 : NULLIFY (nl_iterator)
927 42 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
928 2256 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
929 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
930 2214 : iatom=iatom, jatom=jatom, r=rab)
931 2214 : basis_set_a => basis_set_list(ikind)%gto_basis_set
932 2214 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
933 2214 : basis_set_b => basis_set_list(jkind)%gto_basis_set
934 2214 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
935 : ASSOCIATE ( &
936 : ! basis ikind
937 : first_sgfa => basis_set_a%first_sgf, &
938 : la_max => basis_set_a%lmax, &
939 : la_min => basis_set_a%lmin, &
940 : npgfa => basis_set_a%npgf, &
941 : nsgfa => basis_set_a%nsgf_set, &
942 : rpgfa => basis_set_a%pgf_radius, &
943 : set_radius_a => basis_set_a%set_radius, &
944 : sphi_a => basis_set_a%sphi, &
945 : zeta => basis_set_a%zet, &
946 : ! basis jkind, &
947 : first_sgfb => basis_set_b%first_sgf, &
948 : lb_max => basis_set_b%lmax, &
949 : lb_min => basis_set_b%lmin, &
950 : npgfb => basis_set_b%npgf, &
951 : nsgfb => basis_set_b%nsgf_set, &
952 : rpgfb => basis_set_b%pgf_radius, &
953 : set_radius_b => basis_set_b%set_radius, &
954 : sphi_b => basis_set_b%sphi, &
955 : zetb => basis_set_b%zet)
956 :
957 2214 : nseta = basis_set_a%nset
958 2214 : nsetb = basis_set_b%nset
959 :
960 : ! reference point
961 2214 : IF (PRESENT(ref_point)) THEN
962 8856 : rc(:) = ref_point(:)
963 : ELSE
964 0 : rc(:) = 0._dp
965 : END IF
966 : ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
967 : ! by folding around the center, such screwing can be avoided for a proper choice of center.
968 17712 : ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
969 17712 : rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
970 : ! we dont use PBC at this point
971 8856 : rab(:) = ra(:) - rb(:)
972 8856 : rac(:) = ra(:) - rc(:)
973 8856 : rbc(:) = rb(:) - rc(:)
974 8856 : dab = NORM2(rab)
975 :
976 : ! get blocks
977 2214 : IF (inode == 1) last_jatom = 0
978 :
979 2214 : IF (jatom == last_jatom) THEN
980 : CYCLE
981 : END IF
982 :
983 1344 : last_jatom = jatom
984 :
985 1344 : IF (iatom <= jatom) THEN
986 710 : irow = iatom
987 710 : icol = jatom
988 : ELSE
989 634 : irow = jatom
990 634 : icol = iatom
991 : END IF
992 :
993 1344 : IF (nmoments > 0) THEN
994 13380 : DO i = 1, nm
995 12042 : NULLIFY (mom_block(i)%block)
996 : ! get block from pre calculated overlap matrix
997 : CALL dbcsr_get_block_p(matrix=moments(i)%matrix, &
998 12042 : row=irow, col=icol, BLOCK=mom_block(i)%block, found=found)
999 12042 : CPASSERT(found .AND. ASSOCIATED(mom_block(i)%block))
1000 162420 : mom_block(i)%block = 0._dp
1001 : END DO
1002 : END IF
1003 1344 : IF (nmoments_der > 0) THEN
1004 5412 : DO i = 1, M_dim
1005 17616 : DO ider = 1, dimders
1006 12204 : NULLIFY (mom_block_der(i, ider)%block)
1007 : CALL dbcsr_get_block_p(matrix=moments_der(i, ider)%matrix, &
1008 : row=irow, col=icol, &
1009 : block=mom_block_der(i, ider)%block, &
1010 12204 : found=found)
1011 12204 : CPASSERT(found .AND. ASSOCIATED(mom_block_der(i, ider)%block))
1012 166446 : mom_block_der(i, ider)%block = 0._dp
1013 : END DO
1014 : END DO
1015 : END IF
1016 :
1017 4935 : DO iset = 1, nseta
1018 :
1019 1377 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1020 1377 : sgfa = first_sgfa(1, iset)
1021 :
1022 4164 : DO jset = 1, nsetb
1023 :
1024 1443 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
1025 :
1026 954 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1027 954 : sgfb = first_sgfb(1, jset)
1028 :
1029 954 : NULLIFY (mab_tmp)
1030 : ALLOCATE (mab_tmp(npgfa(iset)*ncoset(la_max(iset) + 1), &
1031 4770 : npgfb(jset)*ncoset(lb_max(jset) + 1), ncoset(nmom_build) - 1))
1032 :
1033 : ! Calculate the primitive integrals (need l+1 for derivatives)
1034 : CALL moment(la_max(iset) + 1, npgfa(iset), zeta(:, iset), &
1035 : rpgfa(:, iset), la_min(iset), &
1036 : lb_max(jset) + 1, npgfb(jset), zetb(:, jset), &
1037 954 : rpgfb(:, jset), nmom_build, rac, rbc, mab_tmp)
1038 :
1039 954 : IF (nmoments_der > 0) THEN
1040 : CALL diff_momop(la_max(iset), npgfa(iset), zeta(:, iset), &
1041 : rpgfa(:, iset), la_min(iset), &
1042 : lb_max(jset), npgfb(jset), zetb(:, jset), &
1043 : rpgfb(:, jset), lb_min(jset), &
1044 954 : nmoments_der, rac, rbc, difmab, mab_ext=mab_tmp)
1045 : END IF
1046 :
1047 954 : IF (nmoments > 0) THEN
1048 : ! copy subset of mab_tmp (l+1) to mab (l)
1049 948 : mab = 0.0_dp
1050 9480 : DO ii = 1, nm
1051 8532 : na = 0
1052 8532 : nda = 0
1053 49494 : DO ipgf = 1, npgfa(iset)
1054 40014 : nb = 0
1055 40014 : ndb = 0
1056 234927 : DO jpgf = 1, npgfb(jset)
1057 727596 : DO j = 1, ncoset(lb_max(jset))
1058 2392173 : DO i = 1, ncoset(la_max(iset))
1059 2197260 : mab(i + na, j + nb, ii) = mab_tmp(i + nda, j + ndb, ii)
1060 : END DO ! i
1061 : END DO ! j
1062 194913 : nb = nb + ncoset(lb_max(jset))
1063 234927 : ndb = ndb + ncoset(lb_max(jset) + 1)
1064 : END DO ! jpgf
1065 40014 : na = na + ncoset(la_max(iset))
1066 48546 : nda = nda + ncoset(la_max(iset) + 1)
1067 : END DO ! ipgf
1068 : END DO
1069 : ! Contraction step
1070 9480 : DO i = 1, nm
1071 :
1072 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1073 : 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
1074 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
1075 8532 : 0.0_dp, work(1, 1), SIZE(work, 1))
1076 :
1077 9480 : IF (iatom <= jatom) THEN
1078 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1079 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1080 : work(1, 1), SIZE(work, 1), &
1081 : 1.0_dp, mom_block(i)%block(sgfa, sgfb), &
1082 4815 : SIZE(mom_block(i)%block, 1))
1083 : ELSE
1084 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1085 : 1.0_dp, work(1, 1), SIZE(work, 1), &
1086 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1087 : 1.0_dp, mom_block(i)%block(sgfb, sgfa), &
1088 3717 : SIZE(mom_block(i)%block, 1))
1089 : END IF
1090 : END DO
1091 : END IF
1092 :
1093 954 : IF (nmoments_der > 0) THEN
1094 3852 : DO i = 1, M_dim
1095 12546 : DO ider = 1, dimders
1096 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1097 : 1.0_dp, difmab(1, 1, i, ider), SIZE(difmab, 1), &
1098 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
1099 8694 : 0._dp, work(1, 1), SIZE(work, 1))
1100 :
1101 11592 : IF (iatom <= jatom) THEN
1102 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1103 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1104 : work(1, 1), SIZE(work, 1), &
1105 : 1._dp, mom_block_der(i, ider)%block(sgfa, sgfb), &
1106 4923 : SIZE(mom_block_der(i, ider)%block, 1))
1107 : ELSE
1108 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1109 : -1.0_dp, work(1, 1), SIZE(work, 1), &
1110 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1111 : 1.0_dp, mom_block_der(i, ider)%block(sgfb, sgfa), &
1112 3771 : SIZE(mom_block_der(i, ider)%block, 1))
1113 : END IF
1114 : END DO
1115 : END DO
1116 : END IF
1117 2820 : DEALLOCATE (mab_tmp)
1118 : END DO
1119 : END DO
1120 : END ASSOCIATE
1121 : END DO
1122 42 : CALL neighbor_list_iterator_release(nl_iterator)
1123 :
1124 : ! deallocations
1125 42 : DEALLOCATE (basis_set_list)
1126 42 : DEALLOCATE (work)
1127 42 : IF (nmoments > 0) THEN
1128 40 : DEALLOCATE (mab)
1129 400 : DO i = 1, nm
1130 400 : NULLIFY (mom_block(i)%block)
1131 : END DO
1132 40 : DEALLOCATE (mom_block)
1133 : END IF
1134 42 : IF (nmoments_der > 0) THEN
1135 42 : DEALLOCATE (difmab)
1136 180 : DO i = 1, M_dim
1137 594 : DO ider = 1, dimders
1138 552 : NULLIFY (mom_block_der(i, ider)%block)
1139 : END DO
1140 : END DO
1141 42 : DEALLOCATE (mom_block_der)
1142 : END IF
1143 :
1144 42 : CALL timestop(handle)
1145 :
1146 126 : END SUBROUTINE build_local_moments_der_matrix
1147 :
1148 : ! **************************************************************************************************
1149 : !> \brief ...
1150 : !> \param qs_env ...
1151 : !> \param magmom ...
1152 : !> \param nmoments ...
1153 : !> \param ref_point ...
1154 : !> \param ref_points ...
1155 : !> \param basis_type ...
1156 : ! **************************************************************************************************
1157 64 : SUBROUTINE build_local_magmom_matrix(qs_env, magmom, nmoments, ref_point, ref_points, basis_type)
1158 :
1159 : TYPE(qs_environment_type), POINTER :: qs_env
1160 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: magmom
1161 : INTEGER, INTENT(IN) :: nmoments
1162 : REAL(KIND=dp), DIMENSION(:), INTENT(IN), OPTIONAL :: ref_point
1163 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
1164 : OPTIONAL :: ref_points
1165 : CHARACTER(len=*), OPTIONAL :: basis_type
1166 :
1167 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_magmom_matrix'
1168 :
1169 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, maxco, &
1170 : maxsgf, natom, ncoa, ncob, nkind, nm, nseta, nsetb, sgfa, sgfb
1171 : LOGICAL :: found
1172 : REAL(KIND=dp) :: dab
1173 64 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
1174 64 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: mab
1175 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
1176 64 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:) :: mint
1177 : TYPE(cell_type), POINTER :: cell
1178 64 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1179 64 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1180 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
1181 : TYPE(neighbor_list_iterator_p_type), &
1182 64 : DIMENSION(:), POINTER :: nl_iterator
1183 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1184 64 : POINTER :: sab_orb
1185 64 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1186 64 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1187 : TYPE(qs_kind_type), POINTER :: qs_kind
1188 :
1189 64 : IF (nmoments < 1) RETURN
1190 :
1191 64 : CALL timeset(routineN, handle)
1192 :
1193 64 : NULLIFY (qs_kind_set, cell, particle_set, sab_orb)
1194 64 : NULLIFY (matrix_s)
1195 :
1196 64 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s)
1197 :
1198 : ! magnetic dipoles/angular moments only
1199 64 : nm = 3
1200 :
1201 64 : NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
1202 : CALL get_qs_env(qs_env=qs_env, &
1203 : qs_kind_set=qs_kind_set, &
1204 : particle_set=particle_set, cell=cell, &
1205 64 : sab_orb=sab_orb)
1206 :
1207 64 : nkind = SIZE(qs_kind_set)
1208 64 : natom = SIZE(particle_set)
1209 :
1210 : ! Allocate work storage
1211 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
1212 64 : maxco=maxco, maxsgf=maxsgf)
1213 :
1214 320 : ALLOCATE (mab(maxco, maxco, nm))
1215 64 : mab(:, :, :) = 0.0_dp
1216 :
1217 256 : ALLOCATE (work(maxco, maxsgf))
1218 64 : work(:, :) = 0.0_dp
1219 :
1220 256 : ALLOCATE (mint(nm))
1221 256 : DO i = 1, nm
1222 256 : NULLIFY (mint(i)%block)
1223 : END DO
1224 :
1225 356 : ALLOCATE (basis_set_list(nkind))
1226 228 : DO ikind = 1, nkind
1227 164 : qs_kind => qs_kind_set(ikind)
1228 328 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
1229 228 : IF (ASSOCIATED(basis_set_a)) THEN
1230 164 : basis_set_list(ikind)%gto_basis_set => basis_set_a
1231 : ELSE
1232 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
1233 : END IF
1234 : END DO
1235 64 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
1236 7696 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1237 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
1238 7632 : iatom=iatom, jatom=jatom, r=rab)
1239 7632 : basis_set_a => basis_set_list(ikind)%gto_basis_set
1240 7632 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
1241 7632 : basis_set_b => basis_set_list(jkind)%gto_basis_set
1242 7632 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
1243 : ASSOCIATE ( &
1244 : ! basis ikind
1245 : first_sgfa => basis_set_a%first_sgf, &
1246 : la_max => basis_set_a%lmax, &
1247 : la_min => basis_set_a%lmin, &
1248 : npgfa => basis_set_a%npgf, &
1249 : nsgfa => basis_set_a%nsgf_set, &
1250 : rpgfa => basis_set_a%pgf_radius, &
1251 : set_radius_a => basis_set_a%set_radius, &
1252 : sphi_a => basis_set_a%sphi, &
1253 : zeta => basis_set_a%zet, &
1254 : ! basis jkind, &
1255 : first_sgfb => basis_set_b%first_sgf, &
1256 : lb_max => basis_set_b%lmax, &
1257 : lb_min => basis_set_b%lmin, &
1258 : npgfb => basis_set_b%npgf, &
1259 : nsgfb => basis_set_b%nsgf_set, &
1260 : rpgfb => basis_set_b%pgf_radius, &
1261 : set_radius_b => basis_set_b%set_radius, &
1262 : sphi_b => basis_set_b%sphi, &
1263 : zetb => basis_set_b%zet)
1264 :
1265 7632 : nseta = basis_set_a%nset
1266 7632 : nsetb = basis_set_b%nset
1267 :
1268 7632 : IF (iatom <= jatom) THEN
1269 4216 : irow = iatom
1270 4216 : icol = jatom
1271 : ELSE
1272 3416 : irow = jatom
1273 3416 : icol = iatom
1274 : END IF
1275 :
1276 30528 : DO i = 1, nm
1277 22896 : NULLIFY (mint(i)%block)
1278 : CALL dbcsr_get_block_p(matrix=magmom(i)%matrix, &
1279 22896 : row=irow, col=icol, BLOCK=mint(i)%block, found=found)
1280 354234 : mint(i)%block = 0._dp
1281 53424 : CPASSERT(ASSOCIATED(mint(i)%block))
1282 : END DO
1283 :
1284 : ! fold atomic position back into unit cell
1285 7632 : IF (PRESENT(ref_points)) THEN
1286 0 : rc(:) = 0.5_dp*(ref_points(:, iatom) + ref_points(:, jatom))
1287 7632 : ELSE IF (PRESENT(ref_point)) THEN
1288 30528 : rc(:) = ref_point(:)
1289 : ELSE
1290 0 : rc(:) = 0._dp
1291 : END IF
1292 : ! using PBC here might screw a molecule that fits the box (but e.g. hasn't been shifted by center_molecule)
1293 : ! by folding around the center, such screwing can be avoided for a proper choice of center.
1294 61056 : ra(:) = pbc(particle_set(iatom)%r(:) - rc, cell) + rc
1295 61056 : rb(:) = pbc(particle_set(jatom)%r(:) - rc, cell) + rc
1296 : ! we dont use PBC at this point
1297 30528 : rab(:) = ra(:) - rb(:)
1298 30528 : rac(:) = ra(:) - rc(:)
1299 30528 : rbc(:) = rb(:) - rc(:)
1300 30528 : dab = NORM2(rab)
1301 :
1302 23013 : DO iset = 1, nseta
1303 :
1304 7749 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1305 7749 : sgfa = first_sgfa(1, iset)
1306 :
1307 23364 : DO jset = 1, nsetb
1308 :
1309 7983 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
1310 :
1311 6990 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1312 6990 : sgfb = first_sgfb(1, jset)
1313 :
1314 : ! Calculate the primitive integrals
1315 : CALL angmom(la_max(iset), npgfa(iset), zeta(:, iset), &
1316 : rpgfa(:, iset), la_min(iset), &
1317 : lb_max(jset), npgfb(jset), zetb(:, jset), &
1318 6990 : rpgfb(:, jset), rac, rbc, mab)
1319 :
1320 : ! Contraction step
1321 35709 : DO i = 1, nm
1322 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
1323 : 1.0_dp, mab(1, 1, i), SIZE(mab, 1), &
1324 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
1325 20970 : 0.0_dp, work(1, 1), SIZE(work, 1))
1326 :
1327 28953 : IF (iatom <= jatom) THEN
1328 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
1329 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1330 : work(1, 1), SIZE(work, 1), &
1331 : 1.0_dp, mint(i)%block(sgfa, sgfb), &
1332 11901 : SIZE(mint(i)%block, 1))
1333 : ELSE
1334 : CALL dgemm("T", "N", nsgfb(jset), nsgfa(iset), ncoa, &
1335 : -1.0_dp, work(1, 1), SIZE(work, 1), &
1336 : sphi_a(1, sgfa), SIZE(sphi_a, 1), &
1337 : 1.0_dp, mint(i)%block(sgfb, sgfa), &
1338 9069 : SIZE(mint(i)%block, 1))
1339 : END IF
1340 :
1341 : END DO
1342 :
1343 : END DO
1344 : END DO
1345 : END ASSOCIATE
1346 : END DO
1347 64 : CALL neighbor_list_iterator_release(nl_iterator)
1348 :
1349 : ! Release work storage
1350 64 : DEALLOCATE (mab, basis_set_list)
1351 64 : DEALLOCATE (work)
1352 256 : DO i = 1, nm
1353 256 : NULLIFY (mint(i)%block)
1354 : END DO
1355 64 : DEALLOCATE (mint)
1356 :
1357 64 : CALL timestop(handle)
1358 :
1359 192 : END SUBROUTINE build_local_magmom_matrix
1360 :
1361 : ! **************************************************************************************************
1362 : !> \brief ...
1363 : !> \param qs_env ...
1364 : !> \param cosmat ...
1365 : !> \param sinmat ...
1366 : !> \param kvec ...
1367 : !> \param sab_orb_external ...
1368 : !> \param basis_type ...
1369 : ! **************************************************************************************************
1370 13400 : SUBROUTINE build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec, sab_orb_external, basis_type)
1371 :
1372 : TYPE(qs_environment_type), POINTER :: qs_env
1373 : TYPE(dbcsr_type), POINTER :: cosmat, sinmat
1374 : REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: kvec
1375 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1376 : OPTIONAL, POINTER :: sab_orb_external
1377 : CHARACTER(len=*), OPTIONAL :: basis_type
1378 :
1379 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_berry_moment_matrix'
1380 :
1381 : INTEGER :: handle, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, ldab, ldsa, &
1382 : ldsb, ldwork, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, sgfb
1383 : LOGICAL :: found
1384 13400 : REAL(dp), DIMENSION(:, :), POINTER :: cblock, cosab, sblock, sinab, work
1385 : REAL(KIND=dp) :: dab
1386 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rb
1387 : TYPE(cell_type), POINTER :: cell
1388 13400 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1389 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
1390 : TYPE(neighbor_list_iterator_p_type), &
1391 13400 : DIMENSION(:), POINTER :: nl_iterator
1392 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1393 13400 : POINTER :: sab_orb
1394 13400 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1395 13400 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1396 : TYPE(qs_kind_type), POINTER :: qs_kind
1397 :
1398 13400 : CALL timeset(routineN, handle)
1399 :
1400 13400 : NULLIFY (qs_kind_set, particle_set, sab_orb, cell)
1401 : CALL get_qs_env(qs_env=qs_env, &
1402 : qs_kind_set=qs_kind_set, &
1403 : particle_set=particle_set, cell=cell, &
1404 13400 : sab_orb=sab_orb)
1405 :
1406 13400 : IF (PRESENT(sab_orb_external)) sab_orb => sab_orb_external
1407 :
1408 13400 : CALL dbcsr_set(sinmat, 0.0_dp)
1409 13400 : CALL dbcsr_set(cosmat, 0.0_dp)
1410 :
1411 15640 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxco=ldwork, basis_type=basis_type)
1412 13400 : ldab = ldwork
1413 53600 : ALLOCATE (cosab(ldab, ldab))
1414 40200 : ALLOCATE (sinab(ldab, ldab))
1415 40200 : ALLOCATE (work(ldwork, ldwork))
1416 :
1417 13400 : nkind = SIZE(qs_kind_set)
1418 13400 : natom = SIZE(particle_set)
1419 :
1420 66958 : ALLOCATE (basis_set_list(nkind))
1421 40158 : DO ikind = 1, nkind
1422 26758 : qs_kind => qs_kind_set(ikind)
1423 26758 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a, basis_type=basis_type)
1424 40158 : IF (ASSOCIATED(basis_set_a)) THEN
1425 26758 : basis_set_list(ikind)%gto_basis_set => basis_set_a
1426 : ELSE
1427 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
1428 : END IF
1429 : END DO
1430 13400 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
1431 239079 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1432 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
1433 225679 : iatom=iatom, jatom=jatom, r=rab)
1434 225679 : basis_set_a => basis_set_list(ikind)%gto_basis_set
1435 225679 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
1436 225679 : basis_set_b => basis_set_list(jkind)%gto_basis_set
1437 225679 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
1438 : ASSOCIATE ( &
1439 : ! basis ikind
1440 : first_sgfa => basis_set_a%first_sgf, &
1441 : la_max => basis_set_a%lmax, &
1442 : la_min => basis_set_a%lmin, &
1443 : npgfa => basis_set_a%npgf, &
1444 : nsgfa => basis_set_a%nsgf_set, &
1445 : rpgfa => basis_set_a%pgf_radius, &
1446 : set_radius_a => basis_set_a%set_radius, &
1447 : sphi_a => basis_set_a%sphi, &
1448 : zeta => basis_set_a%zet, &
1449 : ! basis jkind, &
1450 : first_sgfb => basis_set_b%first_sgf, &
1451 : lb_max => basis_set_b%lmax, &
1452 : lb_min => basis_set_b%lmin, &
1453 : npgfb => basis_set_b%npgf, &
1454 : nsgfb => basis_set_b%nsgf_set, &
1455 : rpgfb => basis_set_b%pgf_radius, &
1456 : set_radius_b => basis_set_b%set_radius, &
1457 : sphi_b => basis_set_b%sphi, &
1458 : zetb => basis_set_b%zet)
1459 :
1460 225679 : nseta = basis_set_a%nset
1461 225679 : nsetb = basis_set_b%nset
1462 :
1463 225679 : ldsa = SIZE(sphi_a, 1)
1464 225679 : ldsb = SIZE(sphi_b, 1)
1465 :
1466 225679 : IF (iatom <= jatom) THEN
1467 144914 : irow = iatom
1468 144914 : icol = jatom
1469 : ELSE
1470 80765 : irow = jatom
1471 80765 : icol = iatom
1472 : END IF
1473 :
1474 225679 : NULLIFY (cblock)
1475 : CALL dbcsr_get_block_p(matrix=cosmat, &
1476 225679 : row=irow, col=icol, BLOCK=cblock, found=found)
1477 225679 : NULLIFY (sblock)
1478 : CALL dbcsr_get_block_p(matrix=sinmat, &
1479 225679 : row=irow, col=icol, BLOCK=sblock, found=found)
1480 225679 : IF (ASSOCIATED(cblock) .AND. .NOT. ASSOCIATED(sblock) .OR. &
1481 225679 : .NOT. ASSOCIATED(cblock) .AND. ASSOCIATED(sblock)) THEN
1482 0 : CPABORT("")
1483 : END IF
1484 :
1485 677037 : IF (ASSOCIATED(cblock) .AND. ASSOCIATED(sblock)) THEN
1486 :
1487 225679 : ra(:) = pbc(particle_set(iatom)%r(:), cell)
1488 902716 : rb(:) = ra + rab
1489 225679 : dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
1490 :
1491 878135 : DO iset = 1, nseta
1492 :
1493 652456 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1494 652456 : sgfa = first_sgfa(1, iset)
1495 :
1496 3611418 : DO jset = 1, nsetb
1497 :
1498 2733283 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
1499 :
1500 946051 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1501 946051 : sgfb = first_sgfb(1, jset)
1502 :
1503 : ! Calculate the primitive integrals
1504 : CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
1505 : lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
1506 946051 : ra, rb, kvec, cosab, sinab)
1507 : CALL contract_cossin(cblock, sblock, &
1508 : iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
1509 : jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
1510 3385739 : cosab, sinab, ldab, work, ldwork)
1511 :
1512 : END DO
1513 : END DO
1514 :
1515 : END IF
1516 : END ASSOCIATE
1517 : END DO
1518 13400 : CALL neighbor_list_iterator_release(nl_iterator)
1519 :
1520 13400 : DEALLOCATE (cosab)
1521 13400 : DEALLOCATE (sinab)
1522 13400 : DEALLOCATE (work)
1523 13400 : DEALLOCATE (basis_set_list)
1524 :
1525 13400 : CALL timestop(handle)
1526 :
1527 13400 : END SUBROUTINE build_berry_moment_matrix
1528 :
1529 : ! **************************************************************************************************
1530 : !> \brief ...
1531 : !> \param qs_env ...
1532 : !> \param cosmat ...
1533 : !> \param sinmat ...
1534 : !> \param kvec ...
1535 : !> \param basis_type ...
1536 : ! **************************************************************************************************
1537 96 : SUBROUTINE build_berry_kpoint_matrix(qs_env, cosmat, sinmat, kvec, basis_type)
1538 :
1539 : TYPE(qs_environment_type), POINTER :: qs_env
1540 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: cosmat, sinmat
1541 : REAL(KIND=dp), DIMENSION(3), INTENT(IN) :: kvec
1542 : CHARACTER(len=*), OPTIONAL :: basis_type
1543 :
1544 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_berry_kpoint_matrix'
1545 :
1546 : INTEGER :: handle, i, iatom, ic, icol, ikind, inode, irow, iset, jatom, jkind, jset, ldab, &
1547 : ldsa, ldsb, ldwork, natom, ncoa, ncob, nimg, nkind, nseta, nsetb, sgfa, sgfb
1548 : INTEGER, DIMENSION(3) :: icell
1549 96 : INTEGER, DIMENSION(:), POINTER :: row_blk_sizes
1550 96 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
1551 : LOGICAL :: found, use_cell_mapping
1552 96 : REAL(dp), DIMENSION(:, :), POINTER :: cblock, cosab, sblock, sinab, work
1553 : REAL(KIND=dp) :: dab
1554 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rb
1555 : TYPE(cell_type), POINTER :: cell
1556 : TYPE(dbcsr_distribution_type), POINTER :: dbcsr_dist
1557 : TYPE(dft_control_type), POINTER :: dft_control
1558 96 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1559 : TYPE(gto_basis_set_type), POINTER :: basis_set, basis_set_a, basis_set_b
1560 : TYPE(kpoint_type), POINTER :: kpoints
1561 : TYPE(neighbor_list_iterator_p_type), &
1562 96 : DIMENSION(:), POINTER :: nl_iterator
1563 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1564 96 : POINTER :: sab_orb
1565 96 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1566 96 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1567 : TYPE(qs_kind_type), POINTER :: qs_kind
1568 : TYPE(qs_ks_env_type), POINTER :: ks_env
1569 :
1570 96 : CALL timeset(routineN, handle)
1571 :
1572 : CALL get_qs_env(qs_env, &
1573 : ks_env=ks_env, &
1574 96 : dft_control=dft_control)
1575 96 : nimg = dft_control%nimages
1576 96 : IF (nimg > 1) THEN
1577 96 : CALL get_ks_env(ks_env=ks_env, kpoints=kpoints)
1578 96 : CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index)
1579 96 : use_cell_mapping = .TRUE.
1580 : ELSE
1581 : use_cell_mapping = .FALSE.
1582 : END IF
1583 :
1584 : CALL get_qs_env(qs_env=qs_env, &
1585 : qs_kind_set=qs_kind_set, &
1586 : particle_set=particle_set, cell=cell, &
1587 96 : sab_orb=sab_orb)
1588 :
1589 96 : nkind = SIZE(qs_kind_set)
1590 96 : natom = SIZE(particle_set)
1591 384 : ALLOCATE (basis_set_list(nkind))
1592 192 : DO ikind = 1, nkind
1593 96 : qs_kind => qs_kind_set(ikind)
1594 192 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set, basis_type=basis_type)
1595 192 : IF (ASSOCIATED(basis_set)) THEN
1596 96 : basis_set_list(ikind)%gto_basis_set => basis_set
1597 : ELSE
1598 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
1599 : END IF
1600 : END DO
1601 :
1602 288 : ALLOCATE (row_blk_sizes(natom))
1603 : CALL get_particle_set(particle_set, qs_kind_set, nsgf=row_blk_sizes, &
1604 96 : basis=basis_set_list)
1605 96 : CALL get_ks_env(ks_env, dbcsr_dist=dbcsr_dist)
1606 : ! (re)allocate matrix sets
1607 96 : CALL dbcsr_allocate_matrix_set(sinmat, 1, nimg)
1608 96 : CALL dbcsr_allocate_matrix_set(cosmat, 1, nimg)
1609 13206 : DO i = 1, nimg
1610 : ! sin
1611 13110 : ALLOCATE (sinmat(1, i)%matrix)
1612 : CALL dbcsr_create(matrix=sinmat(1, i)%matrix, &
1613 : name="SINMAT", &
1614 : dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
1615 13110 : row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes)
1616 13110 : CALL cp_dbcsr_alloc_block_from_nbl(sinmat(1, i)%matrix, sab_orb)
1617 13110 : CALL dbcsr_set(sinmat(1, i)%matrix, 0.0_dp)
1618 : ! cos
1619 13110 : ALLOCATE (cosmat(1, i)%matrix)
1620 : CALL dbcsr_create(matrix=cosmat(1, i)%matrix, &
1621 : name="COSMAT", &
1622 : dist=dbcsr_dist, matrix_type=dbcsr_type_symmetric, &
1623 13110 : row_blk_size=row_blk_sizes, col_blk_size=row_blk_sizes)
1624 13110 : CALL cp_dbcsr_alloc_block_from_nbl(cosmat(1, i)%matrix, sab_orb)
1625 13206 : CALL dbcsr_set(cosmat(1, i)%matrix, 0.0_dp)
1626 : END DO
1627 :
1628 96 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxco=ldwork)
1629 96 : ldab = ldwork
1630 384 : ALLOCATE (cosab(ldab, ldab))
1631 288 : ALLOCATE (sinab(ldab, ldab))
1632 288 : ALLOCATE (work(ldwork, ldwork))
1633 :
1634 96 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
1635 95877 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
1636 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
1637 95781 : iatom=iatom, jatom=jatom, r=rab, cell=icell)
1638 95781 : basis_set_a => basis_set_list(ikind)%gto_basis_set
1639 95781 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
1640 95781 : basis_set_b => basis_set_list(jkind)%gto_basis_set
1641 95781 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
1642 : ASSOCIATE ( &
1643 : ! basis ikind
1644 : first_sgfa => basis_set_a%first_sgf, &
1645 : la_max => basis_set_a%lmax, &
1646 : la_min => basis_set_a%lmin, &
1647 : npgfa => basis_set_a%npgf, &
1648 : nsgfa => basis_set_a%nsgf_set, &
1649 : rpgfa => basis_set_a%pgf_radius, &
1650 : set_radius_a => basis_set_a%set_radius, &
1651 : sphi_a => basis_set_a%sphi, &
1652 : zeta => basis_set_a%zet, &
1653 : ! basis jkind, &
1654 : first_sgfb => basis_set_b%first_sgf, &
1655 : lb_max => basis_set_b%lmax, &
1656 : lb_min => basis_set_b%lmin, &
1657 : npgfb => basis_set_b%npgf, &
1658 : nsgfb => basis_set_b%nsgf_set, &
1659 : rpgfb => basis_set_b%pgf_radius, &
1660 : set_radius_b => basis_set_b%set_radius, &
1661 : sphi_b => basis_set_b%sphi, &
1662 191562 : zetb => basis_set_b%zet)
1663 :
1664 95781 : nseta = basis_set_a%nset
1665 95781 : nsetb = basis_set_b%nset
1666 :
1667 95781 : ldsa = SIZE(sphi_a, 1)
1668 95781 : ldsb = SIZE(sphi_b, 1)
1669 :
1670 95781 : IF (iatom <= jatom) THEN
1671 53733 : irow = iatom
1672 53733 : icol = jatom
1673 : ELSE
1674 42048 : irow = jatom
1675 42048 : icol = iatom
1676 : END IF
1677 :
1678 95781 : IF (use_cell_mapping) THEN
1679 95781 : ic = cell_to_index(icell(1), icell(2), icell(3))
1680 95781 : CPASSERT(ic > 0)
1681 : ELSE
1682 : ic = 1
1683 : END IF
1684 :
1685 95781 : NULLIFY (sblock)
1686 : CALL dbcsr_get_block_p(matrix=sinmat(1, ic)%matrix, &
1687 95781 : row=irow, col=icol, BLOCK=sblock, found=found)
1688 95781 : CPASSERT(found)
1689 95781 : NULLIFY (cblock)
1690 : CALL dbcsr_get_block_p(matrix=cosmat(1, ic)%matrix, &
1691 95781 : row=irow, col=icol, BLOCK=cblock, found=found)
1692 95781 : CPASSERT(found)
1693 :
1694 95781 : ra(:) = pbc(particle_set(iatom)%r(:), cell)
1695 383124 : rb(:) = ra + rab
1696 95781 : dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
1697 :
1698 287343 : DO iset = 1, nseta
1699 :
1700 95781 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1701 95781 : sgfa = first_sgfa(1, iset)
1702 :
1703 287343 : DO jset = 1, nsetb
1704 :
1705 95781 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
1706 :
1707 95781 : ncob = npgfb(jset)*ncoset(lb_max(jset))
1708 95781 : sgfb = first_sgfb(1, jset)
1709 :
1710 : ! Calculate the primitive integrals
1711 : CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
1712 : lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), lb_min(jset), &
1713 95781 : ra, rb, kvec, cosab, sinab)
1714 : CALL contract_cossin(cblock, sblock, &
1715 : iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
1716 : jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
1717 191562 : cosab, sinab, ldab, work, ldwork)
1718 :
1719 : END DO
1720 : END DO
1721 : END ASSOCIATE
1722 : END DO
1723 96 : CALL neighbor_list_iterator_release(nl_iterator)
1724 :
1725 96 : DEALLOCATE (cosab)
1726 96 : DEALLOCATE (sinab)
1727 96 : DEALLOCATE (work)
1728 96 : DEALLOCATE (basis_set_list)
1729 96 : DEALLOCATE (row_blk_sizes)
1730 :
1731 96 : CALL timestop(handle)
1732 :
1733 192 : END SUBROUTINE build_berry_kpoint_matrix
1734 :
1735 : ! **************************************************************************************************
1736 : !> \brief ...
1737 : !> \param qs_env ...
1738 : !> \param magnetic ...
1739 : !> \param nmoments ...
1740 : !> \param reference ...
1741 : !> \param ref_point ...
1742 : !> \param unit_number ...
1743 : ! **************************************************************************************************
1744 472 : SUBROUTINE qs_moment_berry_phase(qs_env, magnetic, nmoments, reference, ref_point, unit_number)
1745 :
1746 : TYPE(qs_environment_type), POINTER :: qs_env
1747 : LOGICAL, INTENT(IN) :: magnetic
1748 : INTEGER, INTENT(IN) :: nmoments, reference
1749 : REAL(dp), DIMENSION(:), POINTER :: ref_point
1750 : INTEGER, INTENT(IN) :: unit_number
1751 :
1752 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_berry_phase'
1753 :
1754 472 : CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:) :: rlab
1755 : CHARACTER(LEN=default_string_length) :: description
1756 : COMPLEX(dp) :: xphase(3), zdet, zdeta, zi(3), &
1757 : zij(3, 3), zijk(3, 3, 3), &
1758 : zijkl(3, 3, 3, 3), zphase(3), zz
1759 : INTEGER :: handle, i, ia, idim, ikind, ispin, ix, &
1760 : iy, iz, j, k, l, nao, nm, nmo, nmom, &
1761 : nmotot, tmp_dim
1762 : LOGICAL :: floating, ghost, uniform
1763 : REAL(dp) :: charge, ci(3), cij(3, 3), dd, occ, trace
1764 472 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: mmom
1765 472 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: rmom
1766 : REAL(dp), DIMENSION(3) :: kvec, qq, rcc, ria
1767 : TYPE(atomic_kind_type), POINTER :: atomic_kind
1768 : TYPE(cell_type), POINTER :: cell
1769 472 : TYPE(cp_cfm_type), ALLOCATABLE, DIMENSION(:) :: eigrmat
1770 : TYPE(cp_fm_struct_type), POINTER :: tmp_fm_struct
1771 472 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: opvec
1772 472 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: op_fm_set
1773 472 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: mos_new
1774 : TYPE(cp_fm_type), POINTER :: mo_coeff
1775 : TYPE(cp_result_type), POINTER :: results
1776 472 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s, rho_ao
1777 : TYPE(dbcsr_type), POINTER :: cosmat, sinmat
1778 : TYPE(dft_control_type), POINTER :: dft_control
1779 : TYPE(distribution_1d_type), POINTER :: local_particles
1780 472 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1781 : TYPE(mp_para_env_type), POINTER :: para_env
1782 472 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1783 472 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1784 : TYPE(qs_rho_type), POINTER :: rho
1785 : TYPE(rt_prop_type), POINTER :: rtp
1786 :
1787 0 : CPASSERT(ASSOCIATED(qs_env))
1788 :
1789 472 : IF (ASSOCIATED(qs_env%ls_scf_env)) THEN
1790 0 : IF (unit_number > 0) WRITE (unit_number, *) "Periodic moment calculation not implemented in linear scaling code"
1791 0 : RETURN
1792 : END IF
1793 :
1794 472 : CALL timeset(routineN, handle)
1795 :
1796 : ! restrict maximum moment available
1797 472 : nmom = MIN(nmoments, 2)
1798 :
1799 472 : nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
1800 : ! rmom(:,1)=electronic
1801 : ! rmom(:,2)=nuclear
1802 : ! rmom(:,1)=total
1803 2360 : ALLOCATE (rmom(nm + 1, 3))
1804 1416 : ALLOCATE (rlab(nm + 1))
1805 472 : rmom = 0.0_dp
1806 2360 : rlab = ""
1807 472 : IF (magnetic) THEN
1808 0 : nm = 3
1809 0 : ALLOCATE (mmom(nm))
1810 0 : mmom = 0._dp
1811 : END IF
1812 :
1813 472 : NULLIFY (dft_control, rho, cell, particle_set, results, para_env, &
1814 472 : local_particles, matrix_s, mos, rho_ao)
1815 :
1816 : CALL get_qs_env(qs_env, &
1817 : dft_control=dft_control, &
1818 : rho=rho, &
1819 : cell=cell, &
1820 : results=results, &
1821 : particle_set=particle_set, &
1822 : qs_kind_set=qs_kind_set, &
1823 : para_env=para_env, &
1824 : local_particles=local_particles, &
1825 : matrix_s=matrix_s, &
1826 472 : mos=mos)
1827 :
1828 472 : CALL qs_rho_get(rho, rho_ao=rho_ao)
1829 :
1830 472 : NULLIFY (cosmat, sinmat)
1831 472 : ALLOCATE (cosmat, sinmat)
1832 472 : CALL dbcsr_copy(cosmat, matrix_s(1)%matrix, 'COS MOM')
1833 472 : CALL dbcsr_copy(sinmat, matrix_s(1)%matrix, 'SIN MOM')
1834 472 : CALL dbcsr_set(cosmat, 0.0_dp)
1835 472 : CALL dbcsr_set(sinmat, 0.0_dp)
1836 :
1837 2898 : ALLOCATE (op_fm_set(2, dft_control%nspins))
1838 1910 : ALLOCATE (opvec(dft_control%nspins))
1839 1910 : ALLOCATE (eigrmat(dft_control%nspins))
1840 472 : nmotot = 0
1841 966 : DO ispin = 1, dft_control%nspins
1842 494 : NULLIFY (tmp_fm_struct, mo_coeff)
1843 494 : CALL get_mo_set(mo_set=mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
1844 494 : nmotot = nmotot + nmo
1845 494 : CALL cp_fm_create(opvec(ispin), mo_coeff%matrix_struct)
1846 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmo, &
1847 494 : ncol_global=nmo, para_env=para_env, context=mo_coeff%matrix_struct%context)
1848 1482 : DO i = 1, SIZE(op_fm_set, 1)
1849 1482 : CALL cp_fm_create(op_fm_set(i, ispin), tmp_fm_struct)
1850 : END DO
1851 494 : CALL cp_cfm_create(eigrmat(ispin), op_fm_set(1, ispin)%matrix_struct)
1852 1460 : CALL cp_fm_struct_release(tmp_fm_struct)
1853 : END DO
1854 :
1855 : ! occupation
1856 966 : DO ispin = 1, dft_control%nspins
1857 494 : CALL get_mo_set(mo_set=mos(ispin), maxocc=occ, uniform_occupation=uniform)
1858 966 : IF (.NOT. uniform) THEN
1859 0 : CPWARN("Berry phase moments for non uniform MOs' occupation numbers not implemented")
1860 : END IF
1861 : END DO
1862 :
1863 : ! reference point
1864 472 : CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
1865 1888 : rcc = pbc(rcc, cell)
1866 :
1867 : ! label
1868 1888 : DO l = 1, nm
1869 1416 : ix = indco(1, l + 1)
1870 1416 : iy = indco(2, l + 1)
1871 1416 : iz = indco(3, l + 1)
1872 1888 : CALL set_label(rlab(l + 1), ix, iy, iz)
1873 : END DO
1874 :
1875 : ! nuclear contribution
1876 1908 : DO ia = 1, SIZE(particle_set)
1877 1436 : atomic_kind => particle_set(ia)%atomic_kind
1878 1436 : CALL get_atomic_kind(atomic_kind, kind_number=ikind)
1879 1436 : CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge, ghost=ghost, floating=floating)
1880 1908 : IF (.NOT. ghost .AND. .NOT. floating) THEN
1881 1436 : rmom(1, 2) = rmom(1, 2) - charge
1882 : END IF
1883 : END DO
1884 7552 : ria = twopi*MATMUL(cell%h_inv, rcc)
1885 1888 : zphase = CMPLX(COS(ria), SIN(ria), dp)**rmom(1, 2)
1886 :
1887 472 : zi = 0._dp
1888 472 : zij = 0._dp
1889 : zijk = 0._dp
1890 : zijkl = 0._dp
1891 :
1892 944 : DO l = 1, nmom
1893 472 : SELECT CASE (l)
1894 : CASE (1)
1895 : ! Dipole
1896 1888 : zi(:) = CMPLX(1._dp, 0._dp, dp)
1897 1908 : DO ia = 1, SIZE(particle_set)
1898 1436 : atomic_kind => particle_set(ia)%atomic_kind
1899 1436 : CALL get_atomic_kind(atomic_kind, kind_number=ikind)
1900 1436 : CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge, ghost=ghost, floating=floating)
1901 1908 : IF (.NOT. ghost .AND. .NOT. floating) THEN
1902 5744 : ria = particle_set(ia)%r
1903 5744 : ria = pbc(ria, cell)
1904 5744 : DO i = 1, 3
1905 17232 : kvec(:) = twopi*cell%h_inv(i, :)
1906 17232 : dd = SUM(kvec(:)*ria(:))
1907 4308 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
1908 5744 : zi(i) = zi(i)*zdeta
1909 : END DO
1910 : END IF
1911 : END DO
1912 1888 : zi = zi*zphase
1913 1888 : ci = AIMAG(LOG(zi))/twopi
1914 1888 : qq = AIMAG(LOG(zi))
1915 7552 : rmom(2:4, 2) = MATMUL(cell%hmat, ci)
1916 : CASE (2)
1917 : ! Quadrupole
1918 0 : CPABORT("Berry phase moments bigger than 1 not implemented")
1919 0 : zij(:, :) = CMPLX(1._dp, 0._dp, dp)
1920 0 : DO ia = 1, SIZE(particle_set)
1921 0 : atomic_kind => particle_set(ia)%atomic_kind
1922 0 : CALL get_atomic_kind(atomic_kind, kind_number=ikind)
1923 0 : CALL get_qs_kind(qs_kind_set(ikind), core_charge=charge)
1924 0 : ria = particle_set(ia)%r
1925 0 : ria = pbc(ria, cell)
1926 0 : DO i = 1, 3
1927 0 : DO j = i, 3
1928 0 : kvec(:) = twopi*(cell%h_inv(i, :) + cell%h_inv(j, :))
1929 0 : dd = SUM(kvec(:)*ria(:))
1930 0 : zdeta = CMPLX(COS(dd), SIN(dd), KIND=dp)**charge
1931 0 : zij(i, j) = zij(i, j)*zdeta
1932 0 : zij(j, i) = zij(i, j)
1933 : END DO
1934 : END DO
1935 : END DO
1936 0 : DO i = 1, 3
1937 0 : DO j = 1, 3
1938 0 : zij(i, j) = zij(i, j)*zphase(i)*zphase(j)
1939 0 : zz = zij(i, j)/zi(i)/zi(j)
1940 0 : cij(i, j) = AIMAG(LOG(zz))/twopi
1941 : END DO
1942 : END DO
1943 0 : cij = 0.5_dp*cij/twopi/twopi
1944 0 : cij = MATMUL(MATMUL(cell%hmat, cij), TRANSPOSE(cell%hmat))
1945 0 : DO k = 4, 9
1946 0 : ix = indco(1, k + 1)
1947 0 : iy = indco(2, k + 1)
1948 0 : iz = indco(3, k + 1)
1949 0 : IF (ix == 0) THEN
1950 0 : rmom(k + 1, 2) = cij(iy, iz)
1951 0 : ELSE IF (iy == 0) THEN
1952 0 : rmom(k + 1, 2) = cij(ix, iz)
1953 0 : ELSE IF (iz == 0) THEN
1954 0 : rmom(k + 1, 2) = cij(ix, iy)
1955 : END IF
1956 : END DO
1957 : CASE (3)
1958 : ! Octapole
1959 0 : CPABORT("Berry phase moments bigger than 2 not implemented")
1960 : CASE (4)
1961 : ! Hexadecapole
1962 0 : CPABORT("Berry phase moments bigger than 3 not implemented")
1963 : CASE DEFAULT
1964 472 : CPABORT("Berry phase moments bigger than 4 not implemented")
1965 : END SELECT
1966 : END DO
1967 :
1968 : ! electronic contribution
1969 :
1970 7552 : ria = twopi*REAL(nmotot, dp)*occ*MATMUL(cell%h_inv, rcc)
1971 1888 : xphase = CMPLX(COS(ria), SIN(ria), dp)
1972 :
1973 : ! charge
1974 472 : trace = 0.0_dp
1975 966 : DO ispin = 1, dft_control%nspins
1976 494 : CALL dbcsr_dot(rho_ao(ispin)%matrix, matrix_s(1)%matrix, trace)
1977 966 : rmom(1, 1) = rmom(1, 1) + trace
1978 : END DO
1979 :
1980 472 : zi = 0._dp
1981 472 : zij = 0._dp
1982 : zijk = 0._dp
1983 : zijkl = 0._dp
1984 :
1985 944 : DO l = 1, nmom
1986 472 : SELECT CASE (l)
1987 : CASE (1)
1988 : ! Dipole
1989 1888 : DO i = 1, 3
1990 5664 : kvec(:) = twopi*cell%h_inv(i, :)
1991 1416 : CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec)
1992 1416 : IF (qs_env%run_rtp) THEN
1993 48 : CALL get_qs_env(qs_env, rtp=rtp)
1994 48 : CALL get_rtp(rtp, mos_new=mos_new)
1995 48 : CALL op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
1996 : ELSE
1997 1368 : CALL op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
1998 : END IF
1999 1416 : zdet = CMPLX(1._dp, 0._dp, dp)
2000 2898 : DO ispin = 1, dft_control%nspins
2001 1482 : CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
2002 8232 : DO idim = 1, tmp_dim
2003 : eigrmat(ispin)%local_data(:, idim) = &
2004 : CMPLX(op_fm_set(1, ispin)%local_data(:, idim), &
2005 43734 : -op_fm_set(2, ispin)%local_data(:, idim), dp)
2006 : END DO
2007 : ! CALL cp_cfm_lu_decompose(eigrmat(ispin), zdeta)
2008 1482 : CALL cp_cfm_det(eigrmat(ispin), zdeta)
2009 1482 : zdet = zdet*zdeta
2010 4380 : IF (dft_control%nspins == 1) THEN
2011 1350 : zdet = zdet*zdeta
2012 : END IF
2013 : END DO
2014 1888 : zi(i) = zdet
2015 : END DO
2016 1888 : zi = zi*xphase
2017 : CASE (2)
2018 : ! Quadrupole
2019 0 : CPABORT("Berry phase moments bigger than 1 not implemented")
2020 0 : DO i = 1, 3
2021 0 : DO j = i, 3
2022 0 : kvec(:) = twopi*(cell%h_inv(i, :) + cell%h_inv(j, :))
2023 0 : CALL build_berry_moment_matrix(qs_env, cosmat, sinmat, kvec)
2024 0 : IF (qs_env%run_rtp) THEN
2025 0 : CALL get_qs_env(qs_env, rtp=rtp)
2026 0 : CALL get_rtp(rtp, mos_new=mos_new)
2027 0 : CALL op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
2028 : ELSE
2029 0 : CALL op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
2030 : END IF
2031 0 : zdet = CMPLX(1._dp, 0._dp, dp)
2032 0 : DO ispin = 1, dft_control%nspins
2033 0 : CALL cp_cfm_get_info(eigrmat(ispin), ncol_local=tmp_dim)
2034 0 : DO idim = 1, tmp_dim
2035 : eigrmat(ispin)%local_data(:, idim) = &
2036 : CMPLX(op_fm_set(1, ispin)%local_data(:, idim), &
2037 0 : -op_fm_set(2, ispin)%local_data(:, idim), dp)
2038 : END DO
2039 : ! CALL cp_cfm_lu_decompose(eigrmat(ispin), zdeta)
2040 0 : CALL cp_cfm_det(eigrmat(ispin), zdeta)
2041 0 : zdet = zdet*zdeta
2042 0 : IF (dft_control%nspins == 1) THEN
2043 0 : zdet = zdet*zdeta
2044 : END IF
2045 : END DO
2046 0 : zij(i, j) = zdet*xphase(i)*xphase(j)
2047 0 : zij(j, i) = zdet*xphase(i)*xphase(j)
2048 : END DO
2049 : END DO
2050 : CASE (3)
2051 : ! Octapole
2052 0 : CPABORT("Berry phase moments bigger than 2 not implemented")
2053 : CASE (4)
2054 : ! Hexadecapole
2055 0 : CPABORT("Berry phase moments bigger than 3 not implemented")
2056 : CASE DEFAULT
2057 472 : CPABORT("Berry phase moments bigger than 4 not implemented")
2058 : END SELECT
2059 : END DO
2060 944 : DO l = 1, nmom
2061 472 : SELECT CASE (l)
2062 : CASE (1)
2063 : ! Dipole (apply periodic (2 Pi) boundary conditions)
2064 1888 : ci = AIMAG(LOG(zi))
2065 1888 : DO i = 1, 3
2066 1416 : IF (qq(i) + ci(i) > pi) ci(i) = ci(i) - twopi
2067 1888 : IF (qq(i) + ci(i) < -pi) ci(i) = ci(i) + twopi
2068 : END DO
2069 8968 : rmom(2:4, 1) = MATMUL(cell%hmat, ci)/twopi
2070 : CASE (2)
2071 : ! Quadrupole
2072 0 : CPABORT("Berry phase moments bigger than 1 not implemented")
2073 0 : DO i = 1, 3
2074 0 : DO j = 1, 3
2075 0 : zz = zij(i, j)/zi(i)/zi(j)
2076 0 : cij(i, j) = AIMAG(LOG(zz))/twopi
2077 : END DO
2078 : END DO
2079 0 : cij = 0.5_dp*cij/twopi/twopi
2080 0 : cij = MATMUL(MATMUL(cell%hmat, cij), TRANSPOSE(cell%hmat))
2081 0 : DO k = 4, 9
2082 0 : ix = indco(1, k + 1)
2083 0 : iy = indco(2, k + 1)
2084 0 : iz = indco(3, k + 1)
2085 0 : IF (ix == 0) THEN
2086 0 : rmom(k + 1, 1) = cij(iy, iz)
2087 0 : ELSE IF (iy == 0) THEN
2088 0 : rmom(k + 1, 1) = cij(ix, iz)
2089 0 : ELSE IF (iz == 0) THEN
2090 0 : rmom(k + 1, 1) = cij(ix, iy)
2091 : END IF
2092 : END DO
2093 : CASE (3)
2094 : ! Octapole
2095 0 : CPABORT("Berry phase moments bigger than 2 not implemented")
2096 : CASE (4)
2097 : ! Hexadecapole
2098 0 : CPABORT("Berry phase moments bigger than 3 not implemented")
2099 : CASE DEFAULT
2100 472 : CPABORT("Berry phase moments bigger than 4 not implemented")
2101 : END SELECT
2102 : END DO
2103 :
2104 2360 : rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
2105 472 : description = "[DIPOLE]"
2106 472 : CALL cp_results_erase(results=results, description=description)
2107 : CALL put_results(results=results, description=description, &
2108 472 : values=rmom(2:4, 3))
2109 472 : IF (magnetic) THEN
2110 0 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.TRUE., mmom=mmom)
2111 : ELSE
2112 472 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.TRUE.)
2113 : END IF
2114 :
2115 472 : DEALLOCATE (rmom)
2116 472 : DEALLOCATE (rlab)
2117 472 : IF (magnetic) THEN
2118 0 : DEALLOCATE (mmom)
2119 : END IF
2120 :
2121 472 : CALL dbcsr_deallocate_matrix(cosmat)
2122 472 : CALL dbcsr_deallocate_matrix(sinmat)
2123 :
2124 472 : CALL cp_fm_release(opvec)
2125 472 : CALL cp_fm_release(op_fm_set)
2126 966 : DO ispin = 1, dft_control%nspins
2127 966 : CALL cp_cfm_release(eigrmat(ispin))
2128 : END DO
2129 472 : DEALLOCATE (eigrmat)
2130 :
2131 472 : CALL timestop(handle)
2132 :
2133 1416 : END SUBROUTINE qs_moment_berry_phase
2134 :
2135 : ! **************************************************************************************************
2136 : !> \brief ...
2137 : !> \param cosmat ...
2138 : !> \param sinmat ...
2139 : !> \param mos ...
2140 : !> \param op_fm_set ...
2141 : !> \param opvec ...
2142 : ! **************************************************************************************************
2143 1368 : SUBROUTINE op_orbbas(cosmat, sinmat, mos, op_fm_set, opvec)
2144 :
2145 : TYPE(dbcsr_type), POINTER :: cosmat, sinmat
2146 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
2147 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: op_fm_set
2148 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: opvec
2149 :
2150 : INTEGER :: i, nao, nmo
2151 : TYPE(cp_fm_type), POINTER :: mo_coeff
2152 :
2153 2778 : DO i = 1, SIZE(op_fm_set, 2) ! spin
2154 1410 : CALL get_mo_set(mo_set=mos(i), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
2155 1410 : CALL cp_dbcsr_sm_fm_multiply(cosmat, mo_coeff, opvec(i), ncol=nmo)
2156 : CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(i), 0.0_dp, &
2157 1410 : op_fm_set(1, i))
2158 1410 : CALL cp_dbcsr_sm_fm_multiply(sinmat, mo_coeff, opvec(i), ncol=nmo)
2159 : CALL parallel_gemm("T", "N", nmo, nmo, nao, 1.0_dp, mo_coeff, opvec(i), 0.0_dp, &
2160 4188 : op_fm_set(2, i))
2161 : END DO
2162 :
2163 1368 : END SUBROUTINE op_orbbas
2164 :
2165 : ! **************************************************************************************************
2166 : !> \brief ...
2167 : !> \param cosmat ...
2168 : !> \param sinmat ...
2169 : !> \param mos ...
2170 : !> \param op_fm_set ...
2171 : !> \param mos_new ...
2172 : ! **************************************************************************************************
2173 48 : SUBROUTINE op_orbbas_rtp(cosmat, sinmat, mos, op_fm_set, mos_new)
2174 :
2175 : TYPE(dbcsr_type), POINTER :: cosmat, sinmat
2176 : TYPE(mo_set_type), DIMENSION(:), INTENT(IN) :: mos
2177 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: op_fm_set
2178 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: mos_new
2179 :
2180 : INTEGER :: i, icol, lcol, nao, newdim, nmo
2181 : LOGICAL :: double_col, double_row
2182 : TYPE(cp_fm_struct_type), POINTER :: newstruct, newstruct1
2183 : TYPE(cp_fm_type) :: work, work1, work2
2184 : TYPE(cp_fm_type), POINTER :: mo_coeff
2185 :
2186 120 : DO i = 1, SIZE(op_fm_set, 2) ! spin
2187 72 : CALL get_mo_set(mo_set=mos(i), nao=nao, mo_coeff=mo_coeff, nmo=nmo)
2188 72 : CALL cp_fm_get_info(mos_new(2*i), ncol_local=lcol, ncol_global=nmo)
2189 72 : double_col = .TRUE.
2190 72 : double_row = .FALSE.
2191 : CALL cp_fm_struct_double(newstruct, &
2192 : mos_new(2*i)%matrix_struct, &
2193 : mos_new(2*i)%matrix_struct%context, &
2194 : double_col, &
2195 72 : double_row)
2196 :
2197 72 : CALL cp_fm_create(work, matrix_struct=newstruct)
2198 72 : CALL cp_fm_create(work1, matrix_struct=newstruct)
2199 72 : CALL cp_fm_create(work2, matrix_struct=newstruct)
2200 72 : CALL cp_fm_get_info(work, ncol_global=newdim)
2201 :
2202 72 : CALL cp_fm_set_all(work, 0.0_dp, 0.0_dp)
2203 336 : DO icol = 1, lcol
2204 3300 : work%local_data(:, icol) = mos_new(2*i - 1)%local_data(:, icol)
2205 3372 : work%local_data(:, icol + lcol) = mos_new(2*i)%local_data(:, icol)
2206 : END DO
2207 :
2208 72 : CALL cp_dbcsr_sm_fm_multiply(cosmat, work, work1, ncol=newdim)
2209 72 : CALL cp_dbcsr_sm_fm_multiply(sinmat, work, work2, ncol=newdim)
2210 :
2211 336 : DO icol = 1, lcol
2212 3300 : work%local_data(:, icol) = work1%local_data(:, icol) - work2%local_data(:, icol + lcol)
2213 3372 : work%local_data(:, icol + lcol) = work1%local_data(:, icol + lcol) + work2%local_data(:, icol)
2214 : END DO
2215 :
2216 72 : CALL cp_fm_release(work1)
2217 72 : CALL cp_fm_release(work2)
2218 :
2219 : CALL cp_fm_struct_double(newstruct1, &
2220 : op_fm_set(1, i)%matrix_struct, &
2221 : op_fm_set(1, i)%matrix_struct%context, &
2222 : double_col, &
2223 72 : double_row)
2224 :
2225 72 : CALL cp_fm_create(work1, matrix_struct=newstruct1)
2226 :
2227 : CALL parallel_gemm("T", "N", nmo, newdim, nao, 1.0_dp, mos_new(2*i - 1), &
2228 72 : work, 0.0_dp, work1)
2229 :
2230 336 : DO icol = 1, lcol
2231 756 : op_fm_set(1, i)%local_data(:, icol) = work1%local_data(:, icol)
2232 828 : op_fm_set(2, i)%local_data(:, icol) = work1%local_data(:, icol + lcol)
2233 : END DO
2234 :
2235 : CALL parallel_gemm("T", "N", nmo, newdim, nao, 1.0_dp, mos_new(2*i), &
2236 72 : work, 0.0_dp, work1)
2237 :
2238 336 : DO icol = 1, lcol
2239 : op_fm_set(1, i)%local_data(:, icol) = &
2240 756 : op_fm_set(1, i)%local_data(:, icol) + work1%local_data(:, icol + lcol)
2241 : op_fm_set(2, i)%local_data(:, icol) = &
2242 828 : op_fm_set(2, i)%local_data(:, icol) - work1%local_data(:, icol)
2243 : END DO
2244 :
2245 72 : CALL cp_fm_release(work)
2246 72 : CALL cp_fm_release(work1)
2247 72 : CALL cp_fm_struct_release(newstruct)
2248 336 : CALL cp_fm_struct_release(newstruct1)
2249 :
2250 : END DO
2251 :
2252 48 : END SUBROUTINE op_orbbas_rtp
2253 :
2254 : ! **************************************************************************************************
2255 : !> \brief ...
2256 : !> \param qs_env ...
2257 : !> \param magnetic ...
2258 : !> \param nmoments ...
2259 : !> \param reference ...
2260 : !> \param ref_point ...
2261 : !> \param unit_number ...
2262 : !> \param vel_reprs ...
2263 : !> \param com_nl ...
2264 : ! **************************************************************************************************
2265 970 : SUBROUTINE qs_moment_locop(qs_env, magnetic, nmoments, reference, ref_point, unit_number, vel_reprs, com_nl)
2266 :
2267 : TYPE(qs_environment_type), POINTER :: qs_env
2268 : LOGICAL, INTENT(IN) :: magnetic
2269 : INTEGER, INTENT(IN) :: nmoments, reference
2270 : REAL(dp), DIMENSION(:), INTENT(IN), POINTER :: ref_point
2271 : INTEGER, INTENT(IN) :: unit_number
2272 : LOGICAL, INTENT(IN), OPTIONAL :: vel_reprs, com_nl
2273 :
2274 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_locop'
2275 :
2276 970 : CHARACTER(LEN=8), ALLOCATABLE, DIMENSION(:) :: rlab
2277 : CHARACTER(LEN=default_string_length) :: description
2278 : INTEGER :: akind, handle, i, ia, iatom, idir, &
2279 : ikind, ispin, ix, iy, iz, l, nm, nmom, &
2280 : order
2281 : LOGICAL :: my_com_nl, my_velreprs
2282 : REAL(dp) :: charge, dd, strace, trace
2283 970 : REAL(dp), ALLOCATABLE, DIMENSION(:) :: mmom, nlcom_rrv, nlcom_rrv_vrr, &
2284 970 : nlcom_rv, nlcom_rvr, nlcom_rxrv, &
2285 970 : qupole_der, rmom_vel
2286 970 : REAL(dp), ALLOCATABLE, DIMENSION(:, :) :: rmom
2287 : REAL(dp), DIMENSION(3) :: rcc, ria
2288 : TYPE(atomic_kind_type), POINTER :: atomic_kind
2289 : TYPE(cell_type), POINTER :: cell
2290 : TYPE(cp_result_type), POINTER :: results
2291 970 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: magmom, matrix_s, moments, momentum, &
2292 970 : rho_ao
2293 970 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: moments_der
2294 : TYPE(dbcsr_type), POINTER :: tmp_ao
2295 : TYPE(dft_control_type), POINTER :: dft_control
2296 : TYPE(distribution_1d_type), POINTER :: local_particles
2297 : TYPE(mp_para_env_type), POINTER :: para_env
2298 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2299 970 : POINTER :: sab_all, sab_orb
2300 970 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2301 970 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2302 : TYPE(qs_rho_type), POINTER :: rho
2303 :
2304 0 : CPASSERT(ASSOCIATED(qs_env))
2305 :
2306 970 : CALL timeset(routineN, handle)
2307 :
2308 970 : my_velreprs = .FALSE.
2309 970 : IF (PRESENT(vel_reprs)) my_velreprs = vel_reprs
2310 970 : IF (PRESENT(com_nl)) my_com_nl = com_nl
2311 970 : IF (my_velreprs) CALL cite_reference(Mattiat2019)
2312 :
2313 : ! reference point
2314 970 : CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
2315 :
2316 : ! only allow for moments up to maxl set by basis
2317 970 : nmom = MIN(nmoments, current_maxl)
2318 : ! electronic contribution
2319 970 : NULLIFY (dft_control, rho, cell, particle_set, qs_kind_set, results, para_env, matrix_s, rho_ao, sab_all, sab_orb)
2320 : CALL get_qs_env(qs_env, &
2321 : dft_control=dft_control, &
2322 : rho=rho, &
2323 : cell=cell, &
2324 : results=results, &
2325 : particle_set=particle_set, &
2326 : qs_kind_set=qs_kind_set, &
2327 : para_env=para_env, &
2328 : matrix_s=matrix_s, &
2329 : sab_all=sab_all, &
2330 970 : sab_orb=sab_orb)
2331 :
2332 970 : IF (my_com_nl) THEN
2333 40 : IF ((nmom >= 1) .AND. my_velreprs) THEN
2334 40 : ALLOCATE (nlcom_rv(3))
2335 40 : nlcom_rv(:) = 0._dp
2336 : END IF
2337 40 : IF ((nmom >= 2) .AND. my_velreprs) THEN
2338 40 : ALLOCATE (nlcom_rrv(6))
2339 40 : nlcom_rrv(:) = 0._dp
2340 40 : ALLOCATE (nlcom_rvr(6))
2341 40 : nlcom_rvr(:) = 0._dp
2342 40 : ALLOCATE (nlcom_rrv_vrr(6))
2343 40 : nlcom_rrv_vrr(:) = 0._dp
2344 : END IF
2345 40 : IF (magnetic) THEN
2346 18 : ALLOCATE (nlcom_rxrv(3))
2347 18 : nlcom_rxrv = 0._dp
2348 : END IF
2349 : ! Calculate non local correction terms
2350 40 : CALL calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, nlcom_rvr, nlcom_rrv_vrr, rcc)
2351 : END IF
2352 :
2353 970 : NULLIFY (moments)
2354 970 : nm = (6 + 11*nmom + 6*nmom**2 + nmom**3)/6 - 1
2355 970 : CALL dbcsr_allocate_matrix_set(moments, nm)
2356 4182 : DO i = 1, nm
2357 3212 : ALLOCATE (moments(i)%matrix)
2358 3212 : IF (my_velreprs .AND. (nmom >= 2)) THEN
2359 : CALL dbcsr_create(moments(i)%matrix, template=matrix_s(1)%matrix, &
2360 360 : matrix_type=dbcsr_type_symmetric)
2361 360 : CALL cp_dbcsr_alloc_block_from_nbl(moments(i)%matrix, sab_orb)
2362 : ELSE
2363 2852 : CALL dbcsr_copy(moments(i)%matrix, matrix_s(1)%matrix, "Moments")
2364 : END IF
2365 4182 : CALL dbcsr_set(moments(i)%matrix, 0.0_dp)
2366 : END DO
2367 :
2368 : ! calculate derivatives if quadrupole in vel. reprs. is requested
2369 970 : IF (my_velreprs .AND. (nmom >= 2)) THEN
2370 40 : NULLIFY (moments_der)
2371 40 : CALL dbcsr_allocate_matrix_set(moments_der, 3, 3)
2372 160 : DO i = 1, 3 ! x, y, z
2373 520 : DO idir = 1, 3 ! d/dx, d/dy, d/dz
2374 360 : CALL dbcsr_init_p(moments_der(i, idir)%matrix)
2375 : CALL dbcsr_create(moments_der(i, idir)%matrix, template=matrix_s(1)%matrix, &
2376 360 : matrix_type=dbcsr_type_antisymmetric)
2377 360 : CALL cp_dbcsr_alloc_block_from_nbl(moments_der(i, idir)%matrix, sab_orb)
2378 480 : CALL dbcsr_set(moments_der(i, idir)%matrix, 0.0_dp)
2379 : END DO
2380 : END DO
2381 40 : CALL build_local_moments_der_matrix(qs_env, moments_der, 1, 2, ref_point=rcc, moments=moments)
2382 : ELSE
2383 930 : CALL build_local_moment_matrix(qs_env, moments, nmom, ref_point=rcc)
2384 : END IF
2385 :
2386 970 : CALL qs_rho_get(rho, rho_ao=rho_ao)
2387 :
2388 3880 : ALLOCATE (rmom(nm + 1, 3))
2389 2910 : ALLOCATE (rlab(nm + 1))
2390 970 : rmom = 0.0_dp
2391 5152 : rlab = ""
2392 :
2393 970 : IF ((my_velreprs .AND. (nmoments >= 1)) .OR. magnetic) THEN
2394 : ! Allocate matrix to store the matrix product to be traced (dbcsr_dot only works for products of
2395 : ! symmetric matrices)
2396 42 : NULLIFY (tmp_ao)
2397 42 : CALL dbcsr_init_p(tmp_ao)
2398 42 : CALL dbcsr_create(tmp_ao, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry, name="tmp")
2399 42 : CALL cp_dbcsr_alloc_block_from_nbl(tmp_ao, sab_all)
2400 42 : CALL dbcsr_set(tmp_ao, 0.0_dp)
2401 : END IF
2402 :
2403 970 : trace = 0.0_dp
2404 2012 : DO ispin = 1, dft_control%nspins
2405 1042 : CALL dbcsr_dot(rho_ao(ispin)%matrix, matrix_s(1)%matrix, trace)
2406 2012 : rmom(1, 1) = rmom(1, 1) + trace
2407 : END DO
2408 :
2409 4182 : DO i = 1, SIZE(moments)
2410 3212 : strace = 0._dp
2411 6640 : DO ispin = 1, dft_control%nspins
2412 3428 : IF (my_velreprs .AND. nmoments >= 2) THEN
2413 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, moments(i)%matrix, &
2414 360 : 0.0_dp, tmp_ao)
2415 360 : CALL dbcsr_trace(tmp_ao, trace)
2416 : ELSE
2417 3068 : CALL dbcsr_dot(rho_ao(ispin)%matrix, moments(i)%matrix, trace)
2418 : END IF
2419 6640 : strace = strace + trace
2420 : END DO
2421 4182 : rmom(i + 1, 1) = strace
2422 : END DO
2423 :
2424 970 : CALL dbcsr_deallocate_matrix_set(moments)
2425 :
2426 : ! nuclear contribution
2427 : CALL get_qs_env(qs_env=qs_env, &
2428 970 : local_particles=local_particles)
2429 3064 : DO ikind = 1, SIZE(local_particles%n_el)
2430 4674 : DO ia = 1, local_particles%n_el(ikind)
2431 1610 : iatom = local_particles%list(ikind)%array(ia)
2432 : ! fold atomic positions back into unit cell
2433 12880 : ria = pbc(particle_set(iatom)%r - rcc, cell) + rcc
2434 6440 : ria = ria - rcc
2435 1610 : atomic_kind => particle_set(iatom)%atomic_kind
2436 1610 : CALL get_atomic_kind(atomic_kind, kind_number=akind)
2437 1610 : CALL get_qs_kind(qs_kind_set(akind), core_charge=charge)
2438 1610 : rmom(1, 2) = rmom(1, 2) - charge
2439 9497 : DO l = 1, nm
2440 5793 : ix = indco(1, l + 1)
2441 5793 : iy = indco(2, l + 1)
2442 5793 : iz = indco(3, l + 1)
2443 5793 : dd = 1._dp
2444 5793 : IF (ix > 0) dd = dd*ria(1)**ix
2445 5793 : IF (iy > 0) dd = dd*ria(2)**iy
2446 5793 : IF (iz > 0) dd = dd*ria(3)**iz
2447 5793 : rmom(l + 1, 2) = rmom(l + 1, 2) - charge*dd
2448 7403 : CALL set_label(rlab(l + 1), ix, iy, iz)
2449 : END DO
2450 : END DO
2451 : END DO
2452 970 : CALL para_env%sum(rmom(:, 2))
2453 16426 : rmom(:, :) = -rmom(:, :)
2454 5152 : rmom(:, 3) = rmom(:, 1) + rmom(:, 2)
2455 :
2456 : ! magnetic moments
2457 970 : IF (magnetic) THEN
2458 20 : NULLIFY (magmom)
2459 20 : CALL dbcsr_allocate_matrix_set(magmom, 3)
2460 80 : DO i = 1, SIZE(magmom)
2461 60 : CALL dbcsr_init_p(magmom(i)%matrix)
2462 : CALL dbcsr_create(magmom(i)%matrix, template=matrix_s(1)%matrix, &
2463 60 : matrix_type=dbcsr_type_antisymmetric)
2464 60 : CALL cp_dbcsr_alloc_block_from_nbl(magmom(i)%matrix, sab_orb)
2465 80 : CALL dbcsr_set(magmom(i)%matrix, 0.0_dp)
2466 : END DO
2467 :
2468 20 : CALL build_local_magmom_matrix(qs_env, magmom, nmom, ref_point=rcc)
2469 :
2470 60 : ALLOCATE (mmom(SIZE(magmom)))
2471 20 : mmom(:) = 0.0_dp
2472 20 : IF (qs_env%run_rtp) THEN
2473 : ! get imaginary part of the density in rho_ao (the real part is not needed since the trace of the product
2474 : ! of a symmetric (REAL(rho_ao)) and an anti-symmetric (L_AO) matrix is zero)
2475 : ! There may be other cases, where the imaginary part of the density is relevant
2476 12 : NULLIFY (rho_ao)
2477 12 : CALL qs_rho_get(rho, rho_ao_im=rho_ao)
2478 : END IF
2479 : ! if the density is purely real this is an expensive way to calculate zero
2480 80 : DO i = 1, SIZE(magmom)
2481 60 : strace = 0._dp
2482 120 : DO ispin = 1, dft_control%nspins
2483 60 : CALL dbcsr_set(tmp_ao, 0.0_dp)
2484 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, magmom(i)%matrix, &
2485 60 : 0.0_dp, tmp_ao)
2486 60 : CALL dbcsr_trace(tmp_ao, trace)
2487 120 : strace = strace + trace
2488 : END DO
2489 80 : mmom(i) = strace
2490 : END DO
2491 :
2492 20 : CALL dbcsr_deallocate_matrix_set(magmom)
2493 : END IF
2494 :
2495 : ! velocity representations
2496 970 : IF (my_velreprs) THEN
2497 120 : ALLOCATE (rmom_vel(nm))
2498 40 : rmom_vel = 0.0_dp
2499 :
2500 120 : DO order = 1, nmom
2501 40 : SELECT CASE (order)
2502 :
2503 : CASE (1) ! expectation value of momentum
2504 40 : NULLIFY (momentum)
2505 40 : CALL dbcsr_allocate_matrix_set(momentum, 3)
2506 160 : DO i = 1, 3
2507 120 : CALL dbcsr_init_p(momentum(i)%matrix)
2508 : CALL dbcsr_create(momentum(i)%matrix, template=matrix_s(1)%matrix, &
2509 120 : matrix_type=dbcsr_type_antisymmetric)
2510 120 : CALL cp_dbcsr_alloc_block_from_nbl(momentum(i)%matrix, sab_orb)
2511 160 : CALL dbcsr_set(momentum(i)%matrix, 0.0_dp)
2512 : END DO
2513 40 : CALL build_lin_mom_matrix(qs_env, momentum)
2514 :
2515 : ! imaginary part of the density for RTP, real part gives 0 since momentum is antisymmetric
2516 40 : IF (qs_env%run_rtp) THEN
2517 30 : NULLIFY (rho_ao)
2518 30 : CALL qs_rho_get(rho, rho_ao_im=rho_ao)
2519 120 : DO idir = 1, SIZE(momentum)
2520 90 : strace = 0._dp
2521 180 : DO ispin = 1, dft_control%nspins
2522 90 : CALL dbcsr_set(tmp_ao, 0.0_dp)
2523 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, momentum(idir)%matrix, &
2524 90 : 0.0_dp, tmp_ao)
2525 90 : CALL dbcsr_trace(tmp_ao, trace)
2526 180 : strace = strace + trace
2527 : END DO
2528 120 : rmom_vel(idir) = rmom_vel(idir) + strace
2529 : END DO
2530 : END IF
2531 :
2532 40 : CALL dbcsr_deallocate_matrix_set(momentum)
2533 :
2534 : CASE (2) ! expectation value of quadrupole moment in vel. reprs.
2535 40 : ALLOCATE (qupole_der(9)) ! will contain the expectation values of r_\alpha * d/d r_\beta
2536 40 : qupole_der = 0._dp
2537 :
2538 40 : NULLIFY (rho_ao)
2539 40 : CALL qs_rho_get(rho, rho_ao=rho_ao)
2540 :
2541 : ! Calculate expectation value over real part
2542 40 : trace = 0._dp
2543 160 : DO i = 1, 3
2544 520 : DO idir = 1, 3
2545 360 : strace = 0._dp
2546 720 : DO ispin = 1, dft_control%nspins
2547 360 : CALL dbcsr_set(tmp_ao, 0._dp)
2548 360 : CALL dbcsr_multiply("T", "N", 1._dp, rho_ao(ispin)%matrix, moments_der(i, idir)%matrix, 0._dp, tmp_ao)
2549 360 : CALL dbcsr_trace(tmp_ao, trace)
2550 720 : strace = strace + trace
2551 : END DO
2552 480 : qupole_der((i - 1)*3 + idir) = qupole_der((i - 1)*3 + idir) + strace
2553 : END DO
2554 : END DO
2555 :
2556 40 : IF (qs_env%run_rtp) THEN
2557 30 : NULLIFY (rho_ao)
2558 30 : CALL qs_rho_get(rho, rho_ao_im=rho_ao)
2559 :
2560 : ! Calculate expectation value over imaginary part
2561 30 : trace = 0._dp
2562 120 : DO i = 1, 3
2563 390 : DO idir = 1, 3
2564 270 : strace = 0._dp
2565 540 : DO ispin = 1, dft_control%nspins
2566 270 : CALL dbcsr_set(tmp_ao, 0._dp)
2567 270 : CALL dbcsr_multiply("T", "N", 1._dp, rho_ao(ispin)%matrix, moments_der(i, idir)%matrix, 0._dp, tmp_ao)
2568 270 : CALL dbcsr_trace(tmp_ao, trace)
2569 540 : strace = strace + trace
2570 : END DO
2571 360 : qupole_der((i - 1)*3 + idir) = qupole_der((i - 1)*3 + idir) + strace
2572 : END DO
2573 : END DO
2574 : END IF
2575 :
2576 : ! calculate vel. reprs. of quadrupole moment from derivatives
2577 40 : rmom_vel(4) = -2*qupole_der(1) - rmom(1, 1)
2578 40 : rmom_vel(5) = -qupole_der(2) - qupole_der(4)
2579 40 : rmom_vel(6) = -qupole_der(3) - qupole_der(7)
2580 40 : rmom_vel(7) = -2*qupole_der(5) - rmom(1, 1)
2581 40 : rmom_vel(8) = -qupole_der(6) - qupole_der(8)
2582 40 : rmom_vel(9) = -2*qupole_der(9) - rmom(1, 1)
2583 :
2584 120 : DEALLOCATE (qupole_der)
2585 : CASE DEFAULT
2586 : END SELECT
2587 : END DO
2588 : END IF
2589 :
2590 970 : IF ((my_velreprs .AND. (nmoments >= 1)) .OR. magnetic) THEN
2591 42 : CALL dbcsr_deallocate_matrix(tmp_ao)
2592 : END IF
2593 970 : IF (my_velreprs .AND. (nmoments >= 2)) THEN
2594 40 : CALL dbcsr_deallocate_matrix_set(moments_der)
2595 : END IF
2596 :
2597 970 : description = "[DIPOLE]"
2598 970 : CALL cp_results_erase(results=results, description=description)
2599 : CALL put_results(results=results, description=description, &
2600 970 : values=rmom(2:4, 3))
2601 :
2602 970 : IF (magnetic .AND. my_velreprs) THEN
2603 18 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., mmom=mmom, rmom_vel=rmom_vel)
2604 952 : ELSE IF (magnetic .AND. .NOT. my_velreprs) THEN
2605 2 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., mmom=mmom)
2606 950 : ELSE IF (my_velreprs .AND. .NOT. magnetic) THEN
2607 22 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE., rmom_vel=rmom_vel)
2608 : ELSE
2609 928 : CALL print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic=.FALSE.)
2610 : END IF
2611 :
2612 970 : IF (my_com_nl) THEN
2613 40 : IF (magnetic) THEN
2614 72 : mmom(:) = nlcom_rxrv(:)
2615 : END IF
2616 40 : IF (my_velreprs .AND. (nmom >= 1)) THEN
2617 40 : DEALLOCATE (rmom_vel)
2618 40 : ALLOCATE (rmom_vel(21))
2619 160 : rmom_vel(1:3) = nlcom_rv
2620 : END IF
2621 40 : IF (my_velreprs .AND. (nmom >= 2)) THEN
2622 280 : rmom_vel(4:9) = nlcom_rrv
2623 280 : rmom_vel(10:15) = nlcom_rvr
2624 280 : rmom_vel(16:21) = nlcom_rrv_vrr
2625 : END IF
2626 40 : IF (magnetic .AND. .NOT. my_velreprs) THEN
2627 0 : CALL print_moments_nl(unit_number, nmom, rlab, mmom=mmom)
2628 40 : ELSE IF (my_velreprs .AND. .NOT. magnetic) THEN
2629 22 : CALL print_moments_nl(unit_number, nmom, rlab, rmom_vel=rmom_vel)
2630 18 : ELSE IF (my_velreprs .AND. magnetic) THEN
2631 18 : CALL print_moments_nl(unit_number, nmom, rlab, mmom=mmom, rmom_vel=rmom_vel)
2632 : END IF
2633 :
2634 : END IF
2635 :
2636 : IF (my_com_nl) THEN
2637 40 : IF (nmom >= 1 .AND. my_velreprs) DEALLOCATE (nlcom_rv)
2638 40 : IF (nmom >= 2 .AND. my_velreprs) THEN
2639 40 : DEALLOCATE (nlcom_rrv)
2640 40 : DEALLOCATE (nlcom_rvr)
2641 40 : DEALLOCATE (nlcom_rrv_vrr)
2642 : END IF
2643 40 : IF (magnetic) DEALLOCATE (nlcom_rxrv)
2644 : END IF
2645 :
2646 970 : DEALLOCATE (rmom)
2647 970 : DEALLOCATE (rlab)
2648 970 : IF (magnetic) THEN
2649 20 : DEALLOCATE (mmom)
2650 : END IF
2651 970 : IF (my_velreprs) THEN
2652 40 : DEALLOCATE (rmom_vel)
2653 : END IF
2654 :
2655 970 : CALL timestop(handle)
2656 :
2657 1940 : END SUBROUTINE qs_moment_locop
2658 :
2659 : ! **************************************************************************************************
2660 : !> \brief ...
2661 : !> \param label ...
2662 : !> \param ix ...
2663 : !> \param iy ...
2664 : !> \param iz ...
2665 : ! **************************************************************************************************
2666 7893 : SUBROUTINE set_label(label, ix, iy, iz)
2667 : CHARACTER(LEN=*), INTENT(OUT) :: label
2668 : INTEGER, INTENT(IN) :: ix, iy, iz
2669 :
2670 : INTEGER :: i
2671 :
2672 7893 : label = ""
2673 10885 : DO i = 1, ix
2674 10885 : WRITE (label(i:), "(A1)") "X"
2675 : END DO
2676 10885 : DO i = ix + 1, ix + iy
2677 10885 : WRITE (label(i:), "(A1)") "Y"
2678 : END DO
2679 10885 : DO i = ix + iy + 1, ix + iy + iz
2680 10885 : WRITE (label(i:), "(A1)") "Z"
2681 : END DO
2682 :
2683 7893 : END SUBROUTINE set_label
2684 :
2685 : ! **************************************************************************************************
2686 : !> \brief ...
2687 : !> \param unit_number ...
2688 : !> \param nmom ...
2689 : !> \param rmom ...
2690 : !> \param rlab ...
2691 : !> \param rcc ...
2692 : !> \param cell ...
2693 : !> \param periodic ...
2694 : !> \param mmom ...
2695 : !> \param rmom_vel ...
2696 : ! **************************************************************************************************
2697 1460 : SUBROUTINE print_moments(unit_number, nmom, rmom, rlab, rcc, cell, periodic, mmom, rmom_vel)
2698 : INTEGER, INTENT(IN) :: unit_number, nmom
2699 : REAL(dp), DIMENSION(:, :), INTENT(IN) :: rmom
2700 : CHARACTER(LEN=8), DIMENSION(:) :: rlab
2701 : REAL(dp), DIMENSION(3), INTENT(IN) :: rcc
2702 : TYPE(cell_type), POINTER :: cell
2703 : LOGICAL :: periodic
2704 : REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: mmom, rmom_vel
2705 :
2706 : INTEGER :: i, i0, i1, j, l
2707 : REAL(dp) :: dd
2708 :
2709 1460 : IF (unit_number > 0) THEN
2710 2270 : DO l = 0, nmom
2711 749 : SELECT CASE (l)
2712 : CASE (0)
2713 749 : WRITE (unit_number, "(T3,A,T33,3F16.8)") "Reference Point [Bohr]", rcc
2714 749 : WRITE (unit_number, "(T3,A)") "Charges"
2715 : WRITE (unit_number, "(T5,A,T18,F14.8,T36,A,T42,F14.8,T60,A,T67,F14.8)") &
2716 749 : "Electronic=", rmom(1, 1), "Core=", rmom(1, 2), "Total=", rmom(1, 3)
2717 : CASE (1)
2718 749 : IF (periodic) THEN
2719 246 : WRITE (unit_number, "(T3,A)") "Dipole vectors are based on the periodic (Berry phase) operator."
2720 246 : WRITE (unit_number, "(T3,A)") "They are defined modulo integer multiples of the cell matrix [Debye]."
2721 984 : WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[X] [", cell%hmat(1, :)*debye, "] [i]"
2722 984 : WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[Y]=[", cell%hmat(2, :)*debye, "]*[j]"
2723 984 : WRITE (unit_number, "(T3,A,3(F14.8,1X),A)") "[Z] [", cell%hmat(3, :)*debye, "] [k]"
2724 : ELSE
2725 503 : WRITE (unit_number, "(T3,A)") "Dipoles are based on the traditional operator."
2726 : END IF
2727 2996 : dd = SQRT(SUM(rmom(2:4, 3)**2))*debye
2728 749 : WRITE (unit_number, "(T3,A)") "Dipole moment [Debye]"
2729 : WRITE (unit_number, "(T5,3(A,A,E15.7,1X),T60,A,T68,F13.7)") &
2730 2996 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye, i=2, 4), "Total=", dd
2731 : CASE (2)
2732 21 : WRITE (unit_number, "(T3,A)") "Quadrupole moment [Debye*Angstrom]"
2733 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2734 84 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr, i=5, 7)
2735 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2736 84 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr, i=8, 10)
2737 : CASE (3)
2738 1 : WRITE (unit_number, "(T3,A)") "Octapole moment [Debye*Angstrom**2]"
2739 : WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
2740 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=11, 14)
2741 : WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
2742 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=15, 18)
2743 : WRITE (unit_number, "(T7,4(A,A,F14.8,3X))") &
2744 3 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr, i=19, 20)
2745 : CASE (4)
2746 1 : WRITE (unit_number, "(T3,A)") "Hexadecapole moment [Debye*Angstrom**3]"
2747 : WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
2748 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=21, 24)
2749 : WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
2750 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=25, 28)
2751 : WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
2752 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=29, 32)
2753 : WRITE (unit_number, "(T6,4(A,A,F14.8,2X))") &
2754 5 : (TRIM(rlab(i)), "=", rmom(i, 3)*debye/bohr/bohr/bohr, i=32, 35)
2755 : CASE DEFAULT
2756 0 : WRITE (unit_number, "(T3,A,A,I2)") "Higher moment [Debye*Angstrom**(L-1)]", &
2757 0 : " L=", l
2758 0 : i0 = (6 + 11*(l - 1) + 6*(l - 1)**2 + (l - 1)**3)/6
2759 0 : i1 = (6 + 11*l + 6*l**2 + l**3)/6 - 1
2760 0 : dd = debye/(bohr)**(l - 1)
2761 1521 : DO i = i0, i1, 3
2762 : WRITE (unit_number, "(T18,3(A,A,F14.8,4X))") &
2763 0 : (TRIM(rlab(j + 1)), "=", rmom(j + 1, 3)*dd, j=i, MIN(i1, i + 2))
2764 : END DO
2765 : END SELECT
2766 : END DO
2767 749 : IF (PRESENT(mmom)) THEN
2768 28 : IF (nmom >= 1) THEN
2769 112 : dd = SQRT(SUM(mmom(1:3)**2))
2770 28 : WRITE (unit_number, "(T3,A)") "Orbital angular momentum [a. u.]"
2771 : WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
2772 112 : (TRIM(rlab(i + 1)), "=", mmom(i), i=1, 3), "Total=", dd
2773 : END IF
2774 : END IF
2775 749 : IF (PRESENT(rmom_vel)) THEN
2776 96 : DO l = 1, nmom
2777 38 : SELECT CASE (l)
2778 : CASE (1)
2779 152 : dd = SQRT(SUM(rmom_vel(1:3)**2))
2780 38 : WRITE (unit_number, "(T3,A)") "Expectation value of momentum operator [a. u.]"
2781 : WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
2782 152 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=1, 3), "Total=", dd
2783 : CASE (2)
2784 20 : WRITE (unit_number, "(T3,A)") "Expectation value of quadrupole operator in vel. repr. [a. u.]"
2785 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2786 80 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=4, 6)
2787 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2788 138 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=7, 9)
2789 : CASE DEFAULT
2790 : END SELECT
2791 : END DO
2792 : END IF
2793 : END IF
2794 :
2795 1460 : END SUBROUTINE print_moments
2796 :
2797 : ! **************************************************************************************************
2798 : !> \brief ...
2799 : !> \param unit_number ...
2800 : !> \param nmom ...
2801 : !> \param rlab ...
2802 : !> \param mmom ...
2803 : !> \param rmom_vel ...
2804 : ! **************************************************************************************************
2805 58 : SUBROUTINE print_moments_nl(unit_number, nmom, rlab, mmom, rmom_vel)
2806 : INTEGER, INTENT(IN) :: unit_number, nmom
2807 : CHARACTER(LEN=8), DIMENSION(:) :: rlab
2808 : REAL(dp), DIMENSION(:), INTENT(IN), OPTIONAL :: mmom, rmom_vel
2809 :
2810 : INTEGER :: i, l
2811 : REAL(dp) :: dd
2812 :
2813 58 : IF (unit_number > 0) THEN
2814 38 : IF (PRESENT(mmom)) THEN
2815 27 : IF (nmom >= 1) THEN
2816 108 : dd = SQRT(SUM(mmom(1:3)**2))
2817 27 : WRITE (unit_number, "(T3,A)") "Expectation value of rx[r,V_nl] [a. u.]"
2818 : WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
2819 108 : (TRIM(rlab(i + 1)), "=", mmom(i), i=1, 3), "Total=", dd
2820 : END IF
2821 : END IF
2822 38 : IF (PRESENT(rmom_vel)) THEN
2823 96 : DO l = 1, nmom
2824 38 : SELECT CASE (l)
2825 : CASE (1)
2826 152 : dd = SQRT(SUM(rmom_vel(1:3)**2))
2827 38 : WRITE (unit_number, "(T3,A)") "Expectation value of [r,V_nl] [a. u.]"
2828 : WRITE (unit_number, "(T5,3(A,A,E16.8,1X),T64,A,T71,F14.8)") &
2829 152 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=1, 3), "Total=", dd
2830 : CASE (2)
2831 20 : WRITE (unit_number, "(T3,A)") "Expectation value of [rr,V_nl] [a. u.]"
2832 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2833 80 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=4, 6)
2834 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2835 80 : (TRIM(rlab(i + 1)), "=", rmom_vel(i), i=7, 9)
2836 20 : WRITE (unit_number, "(T3,A)") "Expectation value of r x V_nl x r [a. u.]"
2837 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2838 80 : (TRIM(rlab(i + 1 - 6)), "=", rmom_vel(i), i=10, 12)
2839 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2840 80 : (TRIM(rlab(i + 1 - 6)), "=", rmom_vel(i), i=13, 15)
2841 20 : WRITE (unit_number, "(T3,A)") "Expectation value of r x r x V_nl + V_nl x r x r [a. u.]"
2842 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2843 80 : (TRIM(rlab(i + 1 - 12)), "=", rmom_vel(i), i=16, 18)
2844 : WRITE (unit_number, "(T17,3(A,A,E16.8,9X))") &
2845 138 : (TRIM(rlab(i + 1 - 12)), "=", rmom_vel(i), i=19, 21)
2846 : CASE DEFAULT
2847 : END SELECT
2848 : END DO
2849 : END IF
2850 : END IF
2851 :
2852 58 : END SUBROUTINE print_moments_nl
2853 :
2854 : ! **************************************************************************************************
2855 : !> \brief Calculate the expectation value of operators related to non-local potential:
2856 : !> [r, Vnl], noted rv
2857 : !> r x [r,Vnl], noted rxrv
2858 : !> [rr,Vnl], noted rrv
2859 : !> r x Vnl x r, noted rvr
2860 : !> r x r x Vnl + Vnl x r x r, noted rrv_vrr
2861 : !> Note that the 3 first operator are commutator while the 2 last
2862 : !> are not. For reading clarity the same notation is used for all 5
2863 : !> operators.
2864 : !> \param qs_env ...
2865 : !> \param nlcom_rv ...
2866 : !> \param nlcom_rxrv ...
2867 : !> \param nlcom_rrv ...
2868 : !> \param nlcom_rvr ...
2869 : !> \param nlcom_rrv_vrr ...
2870 : !> \param ref_point ...
2871 : ! **************************************************************************************************
2872 76 : SUBROUTINE calculate_commutator_nl_terms(qs_env, nlcom_rv, nlcom_rxrv, nlcom_rrv, nlcom_rvr, &
2873 : nlcom_rrv_vrr, ref_point)
2874 :
2875 : TYPE(qs_environment_type), POINTER :: qs_env
2876 : REAL(dp), ALLOCATABLE, DIMENSION(:), OPTIONAL :: nlcom_rv, nlcom_rxrv, nlcom_rrv, &
2877 : nlcom_rvr, nlcom_rrv_vrr
2878 : REAL(dp), DIMENSION(3) :: ref_point
2879 :
2880 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_commutator_nl_terms'
2881 :
2882 : INTEGER :: handle, ind, ispin
2883 : LOGICAL :: calc_rrv, calc_rrv_vrr, calc_rv, &
2884 : calc_rvr, calc_rxrv
2885 : REAL(dp) :: eps_ppnl, strace, trace
2886 : TYPE(cell_type), POINTER :: cell
2887 76 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_rrv, matrix_rrv_vrr, matrix_rv, &
2888 76 : matrix_rvr, matrix_rxrv, matrix_s, &
2889 76 : rho_ao
2890 : TYPE(dbcsr_type), POINTER :: tmp_ao
2891 : TYPE(dft_control_type), POINTER :: dft_control
2892 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
2893 76 : POINTER :: sab_all, sab_orb, sap_ppnl
2894 76 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2895 76 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2896 : TYPE(qs_rho_type), POINTER :: rho
2897 :
2898 76 : CALL timeset(routineN, handle)
2899 :
2900 76 : calc_rv = .FALSE.
2901 76 : calc_rxrv = .FALSE.
2902 76 : calc_rrv = .FALSE.
2903 76 : calc_rvr = .FALSE.
2904 76 : calc_rrv_vrr = .FALSE.
2905 :
2906 : ! rv, rxrv and rrv are commutator matrices: anti-symmetric.
2907 : ! The real part of the density matrix rho_ao is symmetric so that
2908 : ! the expectation value of real density matrix is zero. Hence, if
2909 : ! the density matrix is real, no need to compute these quantities.
2910 : ! This is not the case for rvr and rrv_vrr which are symmetric.
2911 :
2912 76 : IF (ALLOCATED(nlcom_rv)) THEN
2913 76 : nlcom_rv(:) = 0._dp
2914 76 : IF (qs_env%run_rtp) calc_rv = .TRUE.
2915 : END IF
2916 76 : IF (ALLOCATED(nlcom_rxrv)) THEN
2917 54 : nlcom_rxrv(:) = 0._dp
2918 54 : IF (qs_env%run_rtp) calc_rxrv = .TRUE.
2919 : END IF
2920 76 : IF (ALLOCATED(nlcom_rrv)) THEN
2921 40 : nlcom_rrv(:) = 0._dp
2922 40 : IF (qs_env%run_rtp) calc_rrv = .TRUE.
2923 : END IF
2924 76 : IF (ALLOCATED(nlcom_rvr)) THEN
2925 40 : nlcom_rvr(:) = 0._dp
2926 40 : calc_rvr = .TRUE.
2927 : END IF
2928 76 : IF (ALLOCATED(nlcom_rrv_vrr)) THEN
2929 40 : nlcom_rrv_vrr(:) = 0._dp
2930 40 : calc_rrv_vrr = .TRUE.
2931 : END IF
2932 :
2933 76 : IF (.NOT. (calc_rv .OR. calc_rrv .OR. calc_rxrv .OR. calc_rvr .OR. calc_rrv_vrr)) THEN
2934 12 : CALL timestop(handle)
2935 12 : RETURN
2936 : END IF
2937 :
2938 64 : NULLIFY (cell, matrix_s, particle_set, qs_kind_set, rho, sab_all, sab_orb, sap_ppnl)
2939 : CALL get_qs_env(qs_env, &
2940 : cell=cell, &
2941 : dft_control=dft_control, &
2942 : matrix_s=matrix_s, &
2943 : particle_set=particle_set, &
2944 : qs_kind_set=qs_kind_set, &
2945 : rho=rho, &
2946 : sab_orb=sab_orb, &
2947 : sab_all=sab_all, &
2948 64 : sap_ppnl=sap_ppnl)
2949 :
2950 64 : eps_ppnl = dft_control%qs_control%eps_ppnl
2951 :
2952 : ! Allocate storage
2953 64 : NULLIFY (matrix_rv, matrix_rxrv, matrix_rrv, matrix_rvr, matrix_rrv_vrr)
2954 64 : IF (calc_rv) THEN
2955 54 : CALL dbcsr_allocate_matrix_set(matrix_rv, 3)
2956 216 : DO ind = 1, 3
2957 162 : CALL dbcsr_init_p(matrix_rv(ind)%matrix)
2958 : CALL dbcsr_create(matrix_rv(ind)%matrix, template=matrix_s(1)%matrix, &
2959 162 : matrix_type=dbcsr_type_antisymmetric)
2960 162 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_rv(ind)%matrix, sab_orb)
2961 216 : CALL dbcsr_set(matrix_rv(ind)%matrix, 0._dp)
2962 : END DO
2963 : END IF
2964 :
2965 64 : IF (calc_rxrv) THEN
2966 36 : CALL dbcsr_allocate_matrix_set(matrix_rxrv, 3)
2967 144 : DO ind = 1, 3
2968 108 : CALL dbcsr_init_p(matrix_rxrv(ind)%matrix)
2969 : CALL dbcsr_create(matrix_rxrv(ind)%matrix, template=matrix_s(1)%matrix, &
2970 108 : matrix_type=dbcsr_type_antisymmetric)
2971 108 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_rxrv(ind)%matrix, sab_orb)
2972 144 : CALL dbcsr_set(matrix_rxrv(ind)%matrix, 0._dp)
2973 : END DO
2974 : END IF
2975 :
2976 64 : IF (calc_rrv) THEN
2977 30 : CALL dbcsr_allocate_matrix_set(matrix_rrv, 6)
2978 210 : DO ind = 1, 6
2979 180 : CALL dbcsr_init_p(matrix_rrv(ind)%matrix)
2980 : CALL dbcsr_create(matrix_rrv(ind)%matrix, template=matrix_s(1)%matrix, &
2981 180 : matrix_type=dbcsr_type_antisymmetric)
2982 180 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_rrv(ind)%matrix, sab_orb)
2983 210 : CALL dbcsr_set(matrix_rrv(ind)%matrix, 0._dp)
2984 : END DO
2985 : END IF
2986 :
2987 64 : IF (calc_rvr) THEN
2988 40 : CALL dbcsr_allocate_matrix_set(matrix_rvr, 6)
2989 280 : DO ind = 1, 6
2990 240 : CALL dbcsr_init_p(matrix_rvr(ind)%matrix)
2991 : CALL dbcsr_create(matrix_rvr(ind)%matrix, template=matrix_s(1)%matrix, &
2992 240 : matrix_type=dbcsr_type_symmetric)
2993 240 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_rvr(ind)%matrix, sab_orb)
2994 280 : CALL dbcsr_set(matrix_rvr(ind)%matrix, 0._dp)
2995 : END DO
2996 : END IF
2997 64 : IF (calc_rrv_vrr) THEN
2998 40 : CALL dbcsr_allocate_matrix_set(matrix_rrv_vrr, 6)
2999 280 : DO ind = 1, 6
3000 240 : CALL dbcsr_init_p(matrix_rrv_vrr(ind)%matrix)
3001 : CALL dbcsr_create(matrix_rrv_vrr(ind)%matrix, template=matrix_s(1)%matrix, &
3002 240 : matrix_type=dbcsr_type_symmetric)
3003 240 : CALL cp_dbcsr_alloc_block_from_nbl(matrix_rrv_vrr(ind)%matrix, sab_orb)
3004 280 : CALL dbcsr_set(matrix_rrv_vrr(ind)%matrix, 0._dp)
3005 : END DO
3006 : END IF
3007 :
3008 : ! calculate evaluation of operators in AO basis set
3009 : CALL build_com_mom_nl(qs_kind_set, sab_orb, sap_ppnl, eps_ppnl, particle_set, cell, matrix_rv=matrix_rv, &
3010 : matrix_rxrv=matrix_rxrv, matrix_rrv=matrix_rrv, matrix_rvr=matrix_rvr, &
3011 64 : matrix_rrv_vrr=matrix_rrv_vrr, ref_point=ref_point)
3012 :
3013 : ! Calculate expectation values
3014 : ! Real part
3015 64 : NULLIFY (tmp_ao)
3016 64 : CALL dbcsr_init_p(tmp_ao)
3017 64 : CALL dbcsr_create(tmp_ao, template=matrix_s(1)%matrix, matrix_type=dbcsr_type_no_symmetry, name="tmp")
3018 64 : CALL cp_dbcsr_alloc_block_from_nbl(tmp_ao, sab_all)
3019 64 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3020 :
3021 64 : IF (calc_rvr .OR. calc_rrv_vrr) THEN
3022 40 : NULLIFY (rho_ao)
3023 40 : CALL qs_rho_get(rho, rho_ao=rho_ao)
3024 :
3025 40 : IF (calc_rvr) THEN
3026 : trace = 0._dp
3027 280 : DO ind = 1, SIZE(matrix_rvr)
3028 240 : strace = 0._dp
3029 480 : DO ispin = 1, dft_control%nspins
3030 240 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3031 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rvr(ind)%matrix, &
3032 240 : 0.0_dp, tmp_ao)
3033 240 : CALL dbcsr_trace(tmp_ao, trace)
3034 480 : strace = strace + trace
3035 : END DO
3036 280 : nlcom_rvr(ind) = nlcom_rvr(ind) + strace
3037 : END DO
3038 : END IF
3039 :
3040 40 : IF (calc_rrv_vrr) THEN
3041 : trace = 0._dp
3042 280 : DO ind = 1, SIZE(matrix_rrv_vrr)
3043 240 : strace = 0._dp
3044 480 : DO ispin = 1, dft_control%nspins
3045 240 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3046 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rrv_vrr(ind)%matrix, &
3047 240 : 0.0_dp, tmp_ao)
3048 240 : CALL dbcsr_trace(tmp_ao, trace)
3049 480 : strace = strace + trace
3050 : END DO
3051 280 : nlcom_rrv_vrr(ind) = nlcom_rrv_vrr(ind) + strace
3052 : END DO
3053 : END IF
3054 : END IF
3055 :
3056 : ! imagninary part of the density matrix
3057 64 : NULLIFY (rho_ao)
3058 64 : CALL qs_rho_get(rho, rho_ao_im=rho_ao)
3059 :
3060 64 : IF (calc_rv) THEN
3061 : trace = 0._dp
3062 216 : DO ind = 1, SIZE(matrix_rv)
3063 162 : strace = 0._dp
3064 324 : DO ispin = 1, dft_control%nspins
3065 162 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3066 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rv(ind)%matrix, &
3067 162 : 0.0_dp, tmp_ao)
3068 162 : CALL dbcsr_trace(tmp_ao, trace)
3069 324 : strace = strace + trace
3070 : END DO
3071 216 : nlcom_rv(ind) = nlcom_rv(ind) + strace
3072 : END DO
3073 : END IF
3074 :
3075 64 : IF (calc_rrv) THEN
3076 : trace = 0._dp
3077 210 : DO ind = 1, SIZE(matrix_rrv)
3078 180 : strace = 0._dp
3079 360 : DO ispin = 1, dft_control%nspins
3080 180 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3081 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rrv(ind)%matrix, &
3082 180 : 0.0_dp, tmp_ao)
3083 180 : CALL dbcsr_trace(tmp_ao, trace)
3084 360 : strace = strace + trace
3085 : END DO
3086 210 : nlcom_rrv(ind) = nlcom_rrv(ind) + strace
3087 : END DO
3088 : END IF
3089 :
3090 64 : IF (calc_rxrv) THEN
3091 : trace = 0._dp
3092 144 : DO ind = 1, SIZE(matrix_rxrv)
3093 108 : strace = 0._dp
3094 216 : DO ispin = 1, dft_control%nspins
3095 108 : CALL dbcsr_set(tmp_ao, 0.0_dp)
3096 : CALL dbcsr_multiply("T", "N", 1.0_dp, rho_ao(ispin)%matrix, matrix_rxrv(ind)%matrix, &
3097 108 : 0.0_dp, tmp_ao)
3098 108 : CALL dbcsr_trace(tmp_ao, trace)
3099 216 : strace = strace + trace
3100 : END DO
3101 144 : nlcom_rxrv(ind) = nlcom_rxrv(ind) + strace
3102 : END DO
3103 : END IF
3104 64 : CALL dbcsr_deallocate_matrix(tmp_ao)
3105 64 : IF (calc_rv) CALL dbcsr_deallocate_matrix_set(matrix_rv)
3106 64 : IF (calc_rxrv) CALL dbcsr_deallocate_matrix_set(matrix_rxrv)
3107 64 : IF (calc_rrv) CALL dbcsr_deallocate_matrix_set(matrix_rrv)
3108 64 : IF (calc_rvr) CALL dbcsr_deallocate_matrix_set(matrix_rvr)
3109 64 : IF (calc_rrv_vrr) CALL dbcsr_deallocate_matrix_set(matrix_rrv_vrr)
3110 :
3111 64 : CALL timestop(handle)
3112 76 : END SUBROUTINE calculate_commutator_nl_terms
3113 :
3114 : ! *****************************************************************************
3115 : !> \brief ...
3116 : !> \param qs_env ...
3117 : !> \param difdip ...
3118 : !> \param deltaR ...
3119 : !> \param order ...
3120 : !> \param rcc ...
3121 : !> \note calculate matrix elements <a|r_beta |db/dR_alpha > + <da/dR_alpha | r_beta | b >
3122 : !> be aware: < a | r_beta| db/dR_alpha > = - < da/dR_alpha | r_beta | b > only valid
3123 : !> if alpha .neq.beta
3124 : !> if alpha=beta: < a | r_beta| db/dR_alpha > = - < da/dR_alpha | r_beta | b > - < a | b >
3125 : !> modified from qs_efield_mo_derivatives
3126 : !> SL July 2015
3127 : ! **************************************************************************************************
3128 504 : SUBROUTINE dipole_deriv_ao(qs_env, difdip, deltaR, order, rcc)
3129 : TYPE(qs_environment_type), POINTER :: qs_env
3130 : TYPE(dbcsr_p_type), DIMENSION(:, :), &
3131 : INTENT(INOUT), POINTER :: difdip
3132 : REAL(KIND=dp), DIMENSION(:, :), INTENT(IN), &
3133 : POINTER :: deltaR
3134 : INTEGER, INTENT(IN) :: order
3135 : REAL(KIND=dp), DIMENSION(3), OPTIONAL :: rcc
3136 :
3137 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dipole_deriv_ao'
3138 :
3139 : INTEGER :: handle, i, iatom, icol, idir, ikind, inode, irow, iset, j, jatom, jkind, jset, &
3140 : last_jatom, lda, ldab, ldb, M_dim, maxsgf, natom, ncoa, ncob, nkind, nseta, nsetb, sgfa, &
3141 : sgfb
3142 504 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
3143 504 : npgfb, nsgfa, nsgfb
3144 504 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
3145 : LOGICAL :: found
3146 : REAL(dp) :: dab
3147 : REAL(dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
3148 504 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: work
3149 504 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :, :) :: difmab
3150 504 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
3151 504 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb
3152 504 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: mab
3153 504 : REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER :: difmab2
3154 504 : TYPE(block_p_type), ALLOCATABLE, DIMENSION(:, :) :: mint, mint2
3155 : TYPE(cell_type), POINTER :: cell
3156 504 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
3157 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
3158 : TYPE(neighbor_list_iterator_p_type), &
3159 504 : DIMENSION(:), POINTER :: nl_iterator
3160 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3161 504 : POINTER :: sab_all, sab_orb
3162 504 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
3163 504 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
3164 : TYPE(qs_kind_type), POINTER :: qs_kind
3165 :
3166 504 : CALL timeset(routineN, handle)
3167 :
3168 504 : NULLIFY (cell, particle_set, qs_kind_set, sab_orb, sab_all)
3169 : CALL get_qs_env(qs_env, cell=cell, particle_set=particle_set, &
3170 504 : qs_kind_set=qs_kind_set, sab_orb=sab_orb, sab_all=sab_all)
3171 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
3172 504 : maxco=ldab, maxsgf=maxsgf)
3173 :
3174 504 : nkind = SIZE(qs_kind_set)
3175 504 : natom = SIZE(particle_set)
3176 :
3177 504 : M_dim = ncoset(order) - 1
3178 :
3179 504 : IF (PRESENT(rcc)) THEN
3180 504 : rc = rcc
3181 : ELSE
3182 0 : rc = 0._dp
3183 : END IF
3184 :
3185 2520 : ALLOCATE (basis_set_list(nkind))
3186 :
3187 2520 : ALLOCATE (mab(ldab, ldab, M_dim))
3188 3024 : ALLOCATE (difmab2(ldab, ldab, M_dim, 3))
3189 2016 : ALLOCATE (work(ldab, maxsgf))
3190 6552 : ALLOCATE (mint(3, 3))
3191 6552 : ALLOCATE (mint2(3, 3))
3192 :
3193 413280 : mab(1:ldab, 1:ldab, 1:M_dim) = 0.0_dp
3194 1240344 : difmab2(1:ldab, 1:ldab, 1:M_dim, 1:3) = 0.0_dp
3195 34776 : work(1:ldab, 1:maxsgf) = 0.0_dp
3196 :
3197 2016 : DO i = 1, 3
3198 6552 : DO j = 1, 3
3199 4536 : NULLIFY (mint(i, j)%block)
3200 6048 : NULLIFY (mint2(i, j)%block)
3201 : END DO
3202 : END DO
3203 :
3204 : ! Set the basis_set_list(nkind) to point to the corresponding basis sets
3205 1512 : DO ikind = 1, nkind
3206 1008 : qs_kind => qs_kind_set(ikind)
3207 1008 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
3208 1512 : IF (ASSOCIATED(basis_set_a)) THEN
3209 1008 : basis_set_list(ikind)%gto_basis_set => basis_set_a
3210 : ELSE
3211 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
3212 : END IF
3213 : END DO
3214 :
3215 504 : CALL neighbor_list_iterator_create(nl_iterator, sab_all)
3216 20784 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
3217 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
3218 20280 : iatom=iatom, jatom=jatom, r=rab)
3219 :
3220 20280 : basis_set_a => basis_set_list(ikind)%gto_basis_set
3221 20280 : basis_set_b => basis_set_list(jkind)%gto_basis_set
3222 20280 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
3223 20280 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
3224 :
3225 : ! basis ikind
3226 20280 : first_sgfa => basis_set_a%first_sgf
3227 20280 : la_max => basis_set_a%lmax
3228 20280 : la_min => basis_set_a%lmin
3229 20280 : npgfa => basis_set_a%npgf
3230 20280 : nseta = basis_set_a%nset
3231 20280 : nsgfa => basis_set_a%nsgf_set
3232 20280 : rpgfa => basis_set_a%pgf_radius
3233 20280 : set_radius_a => basis_set_a%set_radius
3234 20280 : sphi_a => basis_set_a%sphi
3235 20280 : zeta => basis_set_a%zet
3236 : ! basis jkind
3237 20280 : first_sgfb => basis_set_b%first_sgf
3238 20280 : lb_max => basis_set_b%lmax
3239 20280 : lb_min => basis_set_b%lmin
3240 20280 : npgfb => basis_set_b%npgf
3241 20280 : nsetb = basis_set_b%nset
3242 20280 : nsgfb => basis_set_b%nsgf_set
3243 20280 : rpgfb => basis_set_b%pgf_radius
3244 20280 : set_radius_b => basis_set_b%set_radius
3245 20280 : sphi_b => basis_set_b%sphi
3246 20280 : zetb => basis_set_b%zet
3247 :
3248 20280 : IF (inode == 1) last_jatom = 0
3249 :
3250 : ! this guarentees minimum image convention
3251 : ! anything else would not make sense
3252 20280 : IF (jatom == last_jatom) THEN
3253 : CYCLE
3254 : END IF
3255 :
3256 2268 : last_jatom = jatom
3257 :
3258 2268 : irow = iatom
3259 2268 : icol = jatom
3260 :
3261 9072 : DO i = 1, 3
3262 29484 : DO j = 1, 3
3263 20412 : NULLIFY (mint(i, j)%block)
3264 : CALL dbcsr_get_block_p(matrix=difdip(i, j)%matrix, &
3265 : row=irow, col=icol, BLOCK=mint(i, j)%block, &
3266 20412 : found=found)
3267 27216 : CPASSERT(found)
3268 : END DO
3269 : END DO
3270 :
3271 9072 : ra(:) = particle_set(iatom)%r(:)
3272 9072 : rb(:) = particle_set(jatom)%r(:)
3273 2268 : rab(:) = pbc(rb, ra, cell)
3274 9072 : rac(:) = pbc(ra - rc, cell)
3275 9072 : rbc(:) = pbc(rb - rc, cell)
3276 2268 : dab = SQRT(rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3))
3277 :
3278 5040 : DO iset = 1, nseta
3279 2268 : ncoa = npgfa(iset)*ncoset(la_max(iset))
3280 2268 : sgfa = first_sgfa(1, iset)
3281 24816 : DO jset = 1, nsetb
3282 2268 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
3283 2268 : ncob = npgfb(jset)*ncoset(lb_max(jset))
3284 2268 : sgfb = first_sgfb(1, jset)
3285 2268 : ldab = MAX(ncoa, ncob)
3286 2268 : lda = ncoset(la_max(iset))*npgfa(iset)
3287 2268 : ldb = ncoset(lb_max(jset))*npgfb(jset)
3288 13608 : ALLOCATE (difmab(lda, ldb, M_dim, 3))
3289 :
3290 : ! Calculate integral (da|r|b)
3291 : CALL diff_momop2(la_max(iset), npgfa(iset), zeta(:, iset), &
3292 : rpgfa(:, iset), la_min(iset), lb_max(jset), npgfb(jset), &
3293 : zetb(:, jset), rpgfb(:, jset), lb_min(jset), order, rac, rbc, &
3294 2268 : difmab, deltaR=deltaR, iatom=iatom, jatom=jatom)
3295 :
3296 : ! *** Contraction step ***
3297 :
3298 9072 : DO idir = 1, 3 ! derivative of AO function
3299 29484 : DO j = 1, 3 ! position operator r_j
3300 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
3301 : 1.0_dp, difmab(1, 1, j, idir), SIZE(difmab, 1), &
3302 : sphi_b(1, sgfb), SIZE(sphi_b, 1), &
3303 20412 : 0.0_dp, work(1, 1), SIZE(work, 1))
3304 :
3305 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
3306 : 1.0_dp, sphi_a(1, sgfa), SIZE(sphi_a, 1), &
3307 : work(1, 1), SIZE(work, 1), &
3308 : 1.0_dp, mint(j, idir)%block(sgfa, sgfb), &
3309 27216 : SIZE(mint(j, idir)%block, 1))
3310 : END DO !j
3311 : END DO !idir
3312 4536 : DEALLOCATE (difmab)
3313 : END DO !jset
3314 : END DO !iset
3315 : END DO!iterator
3316 :
3317 504 : CALL neighbor_list_iterator_release(nl_iterator)
3318 :
3319 2016 : DO i = 1, 3
3320 6552 : DO j = 1, 3
3321 6048 : NULLIFY (mint(i, j)%block)
3322 : END DO
3323 : END DO
3324 :
3325 504 : DEALLOCATE (mab, difmab2, basis_set_list, work, mint, mint2)
3326 :
3327 504 : CALL timestop(handle)
3328 1512 : END SUBROUTINE dipole_deriv_ao
3329 :
3330 : ! **************************************************************************************************
3331 : !> \brief Get list of kpoints from input to compute dipole moment elements
3332 : !> \param qs_env ...
3333 : !> \param xkp ...
3334 : !> \param special_pnts ...
3335 : !> \author Shridhar Shanbhag
3336 : ! **************************************************************************************************
3337 10 : SUBROUTINE get_xkp_for_dipole_calc(qs_env, xkp, special_pnts)
3338 : TYPE(qs_environment_type), POINTER :: qs_env
3339 : TYPE(section_vals_type), POINTER :: kpnts, kpset
3340 : REAL(KIND=dp), DIMENSION(3, 3) :: cart_hmat, hmat
3341 :
3342 : CHARACTER(LEN=*), PARAMETER :: routineN = 'get_xkp_for_dipole_calc'
3343 :
3344 : CHARACTER(LEN=default_string_length) :: ustr
3345 : TYPE(kpoint_type), POINTER :: kpoint_work
3346 : TYPE(cell_type), POINTER :: cell
3347 : CHARACTER(LEN=default_string_length), &
3348 10 : DIMENSION(:), POINTER :: strptr
3349 : CHARACTER(LEN=default_string_length), &
3350 10 : DIMENSION(:), POINTER :: special_pnts, spname
3351 : CHARACTER(LEN=max_line_length) :: error_message
3352 : INTEGER :: handle, i, ik, ikk, ip, &
3353 : n_ptr, npline, nkp
3354 : LOGICAL :: explicit_kpnts, explicit_kpset
3355 10 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: kspecial, xkp
3356 : REAL(KIND=dp), DIMENSION(3) :: kpptr
3357 10 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
3358 :
3359 10 : CALL timeset(routineN, handle)
3360 10 : kpset => section_vals_get_subs_vals(qs_env%input, "DFT%PRINT%MOMENTS%KPOINT_SET")
3361 10 : kpnts => section_vals_get_subs_vals(qs_env%input, "DFT%PRINT%MOMENTS%KPOINTS")
3362 10 : CALL section_vals_get(kpset, explicit=explicit_kpset)
3363 10 : CALL section_vals_get(kpnts, explicit=explicit_kpnts)
3364 10 : IF (explicit_kpset .AND. explicit_kpnts) &
3365 0 : CPABORT("Both KPOINT_SET and KPOINTS present in MOMENTS section")
3366 :
3367 10 : IF (explicit_kpset) THEN
3368 4 : CALL get_qs_env(qs_env, cell=cell)
3369 4 : CALL get_cell(cell, h=hmat)
3370 4 : cart_hmat(:, :) = hmat(:, :)
3371 4 : IF (cell%input_cell_canonicalized) cart_hmat(:, :) = cell%input_hmat(:, :)
3372 4 : CALL section_vals_val_get(kpset, "NPOINTS", i_val=npline)
3373 4 : CALL section_vals_val_get(kpset, "UNITS", c_val=ustr)
3374 4 : CALL uppercase(ustr)
3375 4 : CALL section_vals_val_get(kpset, "SPECIAL_POINT", n_rep_val=n_ptr)
3376 4 : CPASSERT(n_ptr > 0)
3377 12 : ALLOCATE (kspecial(3, n_ptr))
3378 12 : ALLOCATE (spname(n_ptr))
3379 8 : DO ip = 1, n_ptr
3380 4 : CALL section_vals_val_get(kpset, "SPECIAL_POINT", i_rep_val=ip, c_vals=strptr)
3381 4 : IF (SIZE(strptr(:), 1) == 4) THEN
3382 2 : spname(ip) = strptr(1)
3383 8 : DO i = 1, 3
3384 6 : CALL read_float_object(strptr(i + 1), kpptr(i), error_message)
3385 8 : IF (LEN_TRIM(error_message) > 0) CPABORT(TRIM(error_message))
3386 : END DO
3387 2 : ELSE IF (SIZE(strptr(:), 1) == 3) THEN
3388 2 : spname(ip) = "not specified"
3389 8 : DO i = 1, 3
3390 6 : CALL read_float_object(strptr(i), kpptr(i), error_message)
3391 8 : IF (LEN_TRIM(error_message) > 0) CPABORT(TRIM(error_message))
3392 : END DO
3393 : ELSE
3394 0 : CPABORT("Input SPECIAL_POINT invalid")
3395 : END IF
3396 4 : SELECT CASE (ustr)
3397 : CASE ("B_VECTOR")
3398 16 : kspecial(1:3, ip) = kpptr(1:3)
3399 : CASE ("CART_ANGSTROM")
3400 : kspecial(1:3, ip) = (kpptr(1)*cart_hmat(1, 1:3) + &
3401 : kpptr(2)*cart_hmat(2, 1:3) + &
3402 0 : kpptr(3)*cart_hmat(3, 1:3))/twopi*angstrom
3403 : CASE ("CART_BOHR")
3404 : kspecial(1:3, ip) = (kpptr(1)*cart_hmat(1, 1:3) + &
3405 : kpptr(2)*cart_hmat(2, 1:3) + &
3406 0 : kpptr(3)*cart_hmat(3, 1:3))/twopi
3407 : CASE DEFAULT
3408 4 : CPABORT("Unknown unit <"//TRIM(ustr)//"> specified for k-point definition")
3409 : END SELECT
3410 : END DO
3411 4 : nkp = (n_ptr - 1)*npline + 1
3412 4 : CPASSERT(nkp >= 1)
3413 :
3414 : ! Initialize environment and calculate MOs
3415 12 : ALLOCATE (xkp(3, nkp))
3416 12 : ALLOCATE (special_pnts(nkp))
3417 8 : special_pnts(:) = ""
3418 16 : xkp(1:3, 1) = kspecial(1:3, 1)
3419 4 : ikk = 1
3420 4 : special_pnts(ikk) = spname(1)
3421 4 : DO ik = 2, n_ptr
3422 0 : DO ip = 1, npline
3423 0 : ikk = ikk + 1
3424 : xkp(1:3, ikk) = kspecial(1:3, ik - 1) + &
3425 : REAL(ip, KIND=dp)/REAL(npline, KIND=dp)* &
3426 0 : (kspecial(1:3, ik) - kspecial(1:3, ik - 1))
3427 : END DO
3428 4 : special_pnts(ikk) = spname(ik)
3429 : END DO
3430 12 : DEALLOCATE (spname, kspecial)
3431 6 : ELSE IF (explicit_kpnts) THEN
3432 2 : CALL get_qs_env(qs_env, particle_set=particle_set, cell=cell)
3433 2 : CALL get_cell(cell, h=hmat)
3434 2 : NULLIFY (kpoint_work)
3435 2 : CALL kpoint_create(kpoint_work)
3436 2 : CALL read_kpoint_section(kpoint_work, kpnts, hmat, cell)
3437 2 : CALL kpoint_initialize(kpoint_work, particle_set, cell)
3438 2 : nkp = kpoint_work%nkp
3439 6 : ALLOCATE (xkp(3, nkp))
3440 6 : ALLOCATE (special_pnts(nkp))
3441 4 : special_pnts(:) = ""
3442 10 : xkp(1:3, :) = kpoint_work%xkp(1:3, :)
3443 2 : CALL kpoint_release(kpoint_work)
3444 : ELSE
3445 : ! use k-point mesh from DFT calculation
3446 4 : CALL get_qs_env(qs_env, kpoints=kpoint_work)
3447 4 : nkp = kpoint_work%nkp
3448 4 : nkp = kpoint_work%nkp
3449 12 : ALLOCATE (xkp(3, nkp))
3450 12 : ALLOCATE (special_pnts(nkp))
3451 252 : special_pnts(:) = ""
3452 996 : xkp(1:3, :) = kpoint_work%xkp(1:3, :)
3453 : END IF
3454 10 : CALL timestop(handle)
3455 :
3456 10 : END SUBROUTINE get_xkp_for_dipole_calc
3457 : ! **************************************************************************************************
3458 : !> \brief Calculate local moment matrix for a periodic system for all image cells
3459 : !> \param qs_env ...
3460 : !> \param moments_rs_img ...
3461 : !> \param rcc ...
3462 : !> \author Shridhar Shanbhag
3463 : ! **************************************************************************************************
3464 6 : SUBROUTINE build_local_moment_matrix_rs_img(qs_env, moments_rs_img, rcc)
3465 :
3466 : TYPE(qs_environment_type), POINTER :: qs_env
3467 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: moments_rs_img
3468 : REAL(KIND=dp), DIMENSION(3), OPTIONAL :: rcc
3469 :
3470 : CHARACTER(LEN=*), PARAMETER :: routineN = 'build_local_moment_matrix_rs_img'
3471 :
3472 : INTEGER :: handle, i_dir, iatom, ic, ikind, iset, j, jatom, jkind, jset, &
3473 : ldsa, ldsb, ldwork, ncoa, ncob, nimg, nkind, nseta, nsetb, nsize, sgfa, sgfb
3474 : INTEGER, DIMENSION(3) :: icell
3475 6 : INTEGER, DIMENSION(:, :), POINTER :: index_to_cell
3476 6 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
3477 : LOGICAL :: found
3478 : REAL(dp), DIMENSION(3) :: ra, rab, rac, rb, rbc, rc
3479 6 : REAL(dp), DIMENSION(:, :), POINTER :: dblock, work
3480 6 : REAL(dp), DIMENSION(:, :, :), POINTER :: dipab
3481 : REAL(KIND=dp) :: dab
3482 : TYPE(cell_type), POINTER :: cell
3483 6 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp
3484 : TYPE(dft_control_type), POINTER :: dft_control
3485 6 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
3486 : TYPE(gto_basis_set_type), POINTER :: basis_set, basis_set_a, basis_set_b
3487 : TYPE(kpoint_type), POINTER :: kpoints_all
3488 : TYPE(mp_para_env_type), POINTER :: para_env
3489 : TYPE(neighbor_list_iterator_p_type), &
3490 6 : DIMENSION(:), POINTER :: nl_iterator
3491 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3492 6 : POINTER :: sab_all
3493 6 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
3494 6 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
3495 : TYPE(qs_kind_type), POINTER :: qs_kind
3496 :
3497 6 : CALL timeset(routineN, handle)
3498 :
3499 : CALL get_qs_env(qs_env=qs_env, &
3500 : dft_control=dft_control, &
3501 : qs_kind_set=qs_kind_set, &
3502 : matrix_ks_kp=matrix_ks_kp, &
3503 : particle_set=particle_set, &
3504 : cell=cell, &
3505 : para_env=para_env, &
3506 6 : sab_all=sab_all)
3507 :
3508 6 : NULLIFY (kpoints_all)
3509 6 : CALL kpoint_create(kpoints_all)
3510 6 : CALL kpoint_init_cell_index(kpoints_all, sab_all, para_env, nimg)
3511 :
3512 6 : nkind = SIZE(qs_kind_set)
3513 28 : ALLOCATE (basis_set_list(nkind))
3514 16 : DO ikind = 1, nkind
3515 10 : qs_kind => qs_kind_set(ikind)
3516 10 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set)
3517 16 : IF (ASSOCIATED(basis_set)) THEN
3518 10 : basis_set_list(ikind)%gto_basis_set => basis_set
3519 : ELSE
3520 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
3521 : END IF
3522 : END DO
3523 :
3524 6 : rc(:) = 0._dp
3525 6 : IF (PRESENT(rcc)) rc(:) = rcc(:)
3526 :
3527 6 : CALL get_particle_set(particle_set, qs_kind_set, basis=basis_set_list)
3528 6 : CALL get_kpoint_info(kpoints_all, cell_to_index=cell_to_index, index_to_cell=index_to_cell)
3529 6 : nsize = SIZE(index_to_cell, 2)
3530 6 : CPASSERT(SIZE(moments_rs_img, 2) == nsize)
3531 24 : DO i_dir = 1, 3
3532 1650 : DO j = 1, nsize
3533 1626 : ALLOCATE (moments_rs_img(i_dir, j)%matrix)
3534 : CALL dbcsr_create(matrix=moments_rs_img(i_dir, j)%matrix, &
3535 : template=matrix_ks_kp(1, 1)%matrix, &
3536 : matrix_type=dbcsr_type_no_symmetry, &
3537 1626 : name="DIPMAT")
3538 1626 : CALL cp_dbcsr_alloc_block_from_nbl(moments_rs_img(i_dir, j)%matrix, sab_all)
3539 1644 : CALL dbcsr_set(moments_rs_img(i_dir, j)%matrix, 0.0_dp)
3540 : END DO
3541 : END DO
3542 :
3543 6 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, maxco=ldwork)
3544 30 : ALLOCATE (dipab(ldwork, ldwork, 3))
3545 24 : ALLOCATE (work(ldwork, ldwork))
3546 :
3547 6 : CALL neighbor_list_iterator_create(nl_iterator, sab_all)
3548 1676 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
3549 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, &
3550 1670 : iatom=iatom, jatom=jatom, r=rab, cell=icell)
3551 :
3552 1670 : basis_set_a => basis_set_list(ikind)%gto_basis_set
3553 1670 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
3554 1670 : basis_set_b => basis_set_list(jkind)%gto_basis_set
3555 1670 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
3556 : ASSOCIATE ( &
3557 : ! basis ikind
3558 : first_sgfa => basis_set_a%first_sgf, &
3559 : la_max => basis_set_a%lmax, &
3560 : la_min => basis_set_a%lmin, &
3561 : npgfa => basis_set_a%npgf, &
3562 : nsgfa => basis_set_a%nsgf_set, &
3563 : rpgfa => basis_set_a%pgf_radius, &
3564 : set_radius_a => basis_set_a%set_radius, &
3565 : sphi_a => basis_set_a%sphi, &
3566 : zeta => basis_set_a%zet, &
3567 : ! basis jkind, &
3568 : first_sgfb => basis_set_b%first_sgf, &
3569 : lb_max => basis_set_b%lmax, &
3570 : lb_min => basis_set_b%lmin, &
3571 : npgfb => basis_set_b%npgf, &
3572 : nsgfb => basis_set_b%nsgf_set, &
3573 : rpgfb => basis_set_b%pgf_radius, &
3574 : set_radius_b => basis_set_b%set_radius, &
3575 : sphi_b => basis_set_b%sphi, &
3576 : zetb => basis_set_b%zet)
3577 :
3578 1670 : nseta = basis_set_a%nset
3579 1670 : nsetb = basis_set_b%nset
3580 :
3581 1670 : ldsa = SIZE(sphi_a, 1)
3582 1670 : ldsb = SIZE(sphi_b, 1)
3583 :
3584 1670 : NULLIFY (dblock)
3585 :
3586 1670 : ra = pbc(particle_set(iatom)%r(:), cell)
3587 6680 : rb(:) = ra(:) + rab(:)
3588 6680 : rac = ra - rc
3589 6680 : rbc = rb - rc
3590 6680 : dab = norm2(rab)
3591 :
3592 1670 : ic = cell_to_index(icell(1), icell(2), icell(3))
3593 :
3594 5010 : DO iset = 1, nseta
3595 :
3596 1670 : ncoa = npgfa(iset)*ncoset(la_max(iset))
3597 1670 : sgfa = first_sgfa(1, iset)
3598 :
3599 5010 : DO jset = 1, nsetb
3600 :
3601 1670 : IF (set_radius_a(iset) + set_radius_b(jset) < dab) CYCLE
3602 :
3603 1670 : ncob = npgfb(jset)*ncoset(lb_max(jset))
3604 1670 : sgfb = first_sgfb(1, jset)
3605 :
3606 : CALL moment(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), la_min(iset), &
3607 : lb_max(jset), npgfb(jset), zetb(:, jset), rpgfb(:, jset), 1, &
3608 1670 : rac, rbc, dipab)
3609 8350 : DO i_dir = 1, 3
3610 : CALL dbcsr_get_block_p(matrix=moments_rs_img(i_dir, ic)%matrix, &
3611 5010 : row=iatom, col=jatom, BLOCK=dblock, found=found)
3612 5010 : CPASSERT(found)
3613 : CALL dgemm("N", "N", ncoa, nsgfb(jset), ncob, &
3614 : 1.0_dp, dipab(1, 1, i_dir), ldwork, &
3615 5010 : sphi_b(1, sgfb), ldsb, 0.0_dp, work(1, 1), ldwork)
3616 :
3617 : CALL dgemm("T", "N", nsgfa(iset), nsgfb(jset), ncoa, &
3618 : 1.0_dp, sphi_a(1, sgfa), ldsa, &
3619 11690 : work(1, 1), ldwork, 1.0_dp, dblock(1, 1), SIZE(dblock, 1))
3620 : END DO
3621 : END DO
3622 : END DO
3623 : END ASSOCIATE
3624 : END DO
3625 6 : CALL neighbor_list_iterator_release(nl_iterator)
3626 6 : CALL kpoint_release(kpoints_all)
3627 6 : DEALLOCATE (dipab, work, basis_set_list)
3628 6 : CALL timestop(handle)
3629 :
3630 18 : END SUBROUTINE build_local_moment_matrix_rs_img
3631 :
3632 : ! **************************************************************************************************
3633 : !> \brief Calculates the dipole moments and berry curvature for periodic systems for kpoints
3634 : !> \param qs_env ...
3635 : !> \param xkp list of kpoints
3636 : !> \param dipole ...
3637 : !> \param rcc coordinates about which to calculate the dipole
3638 : !> \param berry_c berry curvature calculated using Ω^γ_n = Σ_m 2*Im[d^α_nm (d^β_mn)*]
3639 : !> \param do_parallel option to distribute the result in dipole across
3640 : !> different MPI ranks
3641 : !> \author Shridhar Shanbhag
3642 : ! **************************************************************************************************
3643 6 : SUBROUTINE qs_moment_kpoints_deep(qs_env, xkp, dipole, rcc, berry_c, do_parallel)
3644 : TYPE(qs_environment_type), POINTER :: qs_env
3645 : LOGICAL, OPTIONAL :: do_parallel
3646 : LOGICAL :: my_do_parallel, calc_bc
3647 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_kpoints_deep'
3648 : COMPLEX(KIND=dp) :: phase, tmp_max
3649 6 : COMPLEX(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: C_k, H_k, S_k, D_k, CDC, C_dH_C, &
3650 6 : C_dS_C, dH_dk_i, dS_dk_i
3651 6 : COMPLEX(KIND=dp), DIMENSION(:, :, :), ALLOCATABLE :: dip
3652 : COMPLEX(KIND=dp), DIMENSION(:, :, :, :, :), &
3653 : ALLOCATABLE :: dipole
3654 : INTEGER :: handle, i_dir, ikp, nkp, &
3655 : n_img_scf, n_img_all, nao, &
3656 : num_pe, num_copy, mepos, n, m, mu, &
3657 : ispin, nspin
3658 : INTEGER, DIMENSION(3) :: periodic
3659 6 : INTEGER, DIMENSION(:, :), POINTER :: index_to_cell_all
3660 6 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index_all
3661 : REAL(KIND=dp), DIMENSION(3), OPTIONAL :: rcc
3662 : REAL(KIND=dp), DIMENSION(3) :: my_rcc
3663 : REAL(KIND=dp), DIMENSION(3, 3) :: hmat
3664 6 : REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: eigenvals
3665 6 : REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: bc, xkp
3666 : REAL(KIND=dp), DIMENSION(:, :, :, :), &
3667 : ALLOCATABLE, OPTIONAL :: berry_c
3668 : REAL(KIND=dp), DIMENSION(:, :, :, :), &
3669 6 : ALLOCATABLE :: D_rs, H_rs, S_rs
3670 : TYPE(cell_type), POINTER :: cell
3671 6 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: moments_rs_img, matrix_ks_kp, &
3672 6 : matrix_s_kp
3673 : TYPE(dft_control_type), POINTER :: dft_control
3674 : TYPE(kpoint_type), POINTER :: kpoints_all, kpoints_scf
3675 6 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
3676 : TYPE(mp_para_env_type), POINTER :: para_env
3677 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3678 6 : POINTER :: sab_all
3679 :
3680 6 : CALL timeset(routineN, handle)
3681 6 : calc_bc = PRESENT(berry_c)
3682 6 : my_do_parallel = .FALSE.
3683 6 : my_rcc = 0.0_dp
3684 6 : IF (PRESENT(do_parallel)) my_do_parallel = do_parallel
3685 6 : IF (PRESENT(rcc)) my_rcc = rcc
3686 :
3687 : CALL get_qs_env(qs_env, &
3688 : matrix_ks_kp=matrix_ks_kp, &
3689 : matrix_s_kp=matrix_s_kp, &
3690 : sab_all=sab_all, &
3691 : cell=cell, &
3692 : kpoints=kpoints_scf, &
3693 : para_env=para_env, &
3694 : dft_control=dft_control, &
3695 6 : mos=mos)
3696 :
3697 6 : CALL get_mo_set(mo_set=mos(1), nao=nao)
3698 6 : CALL get_cell(cell=cell, h=hmat, periodic=periodic)
3699 6 : nspin = SIZE(matrix_ks_kp, 1)
3700 6 : nkp = SIZE(xkp, 2)
3701 :
3702 : ! create kpoint environment kpoints_all which contains all neighbor cells R
3703 : ! without considering any lattice symmetry
3704 6 : NULLIFY (kpoints_all)
3705 6 : CALL kpoint_create(kpoints_all)
3706 6 : CALL kpoint_init_cell_index(kpoints_all, sab_all, para_env, n_img_scf)
3707 :
3708 : CALL get_kpoint_info(kpoints_all, cell_to_index=cell_to_index_all, &
3709 6 : index_to_cell=index_to_cell_all)
3710 6 : n_img_all = SIZE(index_to_cell_all, 2)
3711 :
3712 6 : NULLIFY (moments_rs_img)
3713 6 : CALL dbcsr_allocate_matrix_set(moments_rs_img, 3, n_img_all)
3714 : ! D_μ,ν = <φ_μ|r|φ_ν>
3715 6 : CALL build_local_moment_matrix_rs_img(qs_env, moments_rs_img, rcc=my_rcc)
3716 :
3717 60 : ALLOCATE (S_rs(1, nao, nao, n_img_all), H_rs(nspin, nao, nao, n_img_all), source=0.0_dp)
3718 30 : ALLOCATE (D_rs(3, nao, nao, n_img_all), source=0.0_dp)
3719 :
3720 : ! Convert real-space dbcsr matrices into arrays
3721 6 : CALL replicate_rs_matrices(matrix_s_kp, kpoints_scf, S_rs, cell_to_index_all)
3722 6 : CALL replicate_rs_matrices(matrix_ks_kp, kpoints_scf, H_rs, cell_to_index_all)
3723 6 : CALL replicate_rs_matrices(moments_rs_img, kpoints_all, D_rs, cell_to_index_all)
3724 :
3725 6 : mepos = 0
3726 6 : num_pe = 1
3727 6 : num_copy = nkp
3728 6 : IF (my_do_parallel) THEN
3729 6 : mepos = para_env%mepos
3730 6 : num_pe = para_env%num_pe
3731 6 : num_copy = CEILING(REAL(nkp)/num_pe)
3732 : END IF
3733 :
3734 42 : ALLOCATE (dipole(nspin, num_copy, 3, nao, nao), source=z_zero)
3735 30 : IF (calc_bc) ALLOCATE (berry_c(nspin, num_copy, 3, nao), source=0.0_dp)
3736 :
3737 : !$OMP PARALLEL DEFAULT(NONE) PRIVATE(ikp, S_k, H_k, eigenvals, C_k, ispin, n, m, &
3738 : !$OMP i_dir, dS_dk_i, dH_dk_i, D_k, dip, bc, C_dS_C, C_dH_C, CDC, tmp_max, phase) &
3739 : !$OMP SHARED(num_pe, mepos, dipole, berry_c, nao, nspin, periodic, &
3740 6 : !$OMP nkp, xkp, S_rs, H_rs, D_rs, index_to_cell_all, hmat, calc_bc)
3741 : ALLOCATE (dS_dk_i(nao, nao), C_dS_C(nao, nao), dH_dk_i(nao, nao), C_dH_C(nao, nao), source=z_zero)
3742 : ALLOCATE (CDC(nao, nao), dip(3, nao, nao), S_k(nao, nao), H_k(nao, nao), source=z_zero)
3743 : ALLOCATE (C_k(nao, nao), D_k(nao, nao), source=z_zero)
3744 : ALLOCATE (eigenvals(nao), source=0.0_dp)
3745 : IF (calc_bc) ALLOCATE (bc(3, nao), source=0.0_dp)
3746 : !$OMP DO COLLAPSE(2)
3747 : DO ispin = 1, nspin
3748 : DO ikp = 1, nkp
3749 : IF (MOD(ikp - 1, num_pe) /= mepos) CYCLE
3750 :
3751 : ! S^R -> S(k), H^R -> H(k)
3752 : S_k = 0
3753 : H_k = 0
3754 : CALL rs_to_kp(S_rs(1, :, :, :), S_k, index_to_cell_all, xkp(:, ikp))
3755 : CALL rs_to_kp(H_rs(ispin, :, :, :), H_k, index_to_cell_all, xkp(:, ikp))
3756 :
3757 : ! Diagonalize H(k)C(k) = S(k)C(k)ε(k)
3758 : CALL geeig_right(H_k, S_k, eigenvals, C_k)
3759 :
3760 : ! To have a smooth complex phase of C(k) as function of k, for every n, we force
3761 : ! the largest C_μ,n(k) to be real.
3762 : ! This is important to have a continuous dipole moment d_nm(k) as a function of k
3763 : DO n = 1, nao
3764 : tmp_max = C_k(1, n)
3765 : DO mu = 1, nao
3766 : IF (ABS(C_k(mu, n)) < ABS(tmp_max)) CYCLE
3767 : tmp_max = C_k(mu, n)
3768 : END DO
3769 : phase = tmp_max/ABS(tmp_max)
3770 : C_k(:, n) = C_k(:, n)/phase
3771 : END DO
3772 :
3773 : DO i_dir = 1, 3 ! d^x, d^y, d^z
3774 :
3775 : IF (periodic(i_dir) == 0) CYCLE
3776 : ! ∇ S(k) = Σ_R iR S^R e^(ikR), ∇ H(k) = Σ_R iR H^R e^(ikR)
3777 : CALL rs_to_kp(S_rs(1, :, :, :), dS_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
3778 : CALL rs_to_kp(H_rs(ispin, :, :, :), dH_dk_i, index_to_cell_all, xkp(:, ikp), i_dir, hmat)
3779 :
3780 : ! Σ_R D^R e^(ikR) = D(k), D_μ,ν = <φ_μ|r|φ_ν>
3781 : CALL rs_to_kp(D_rs(i_dir, :, :, :), D_k(:, :), index_to_cell_all, xkp(:, ikp))
3782 :
3783 : ! Basis transform to Kohn-Sham basis: (C^H) ∇ S C, (C^H) ∇ H C, (C^H) D C
3784 : CALL gemm_square(C_k, 'C', dS_dk_i, 'N', C_k, 'N', C_dS_C)
3785 : CALL gemm_square(C_k, 'C', dH_dk_i, 'N', C_k, 'N', C_dH_C)
3786 : CALL gemm_square(C_k, 'C', D_k, 'N', C_k, 'N', CDC)
3787 :
3788 : ! Compute the dipole
3789 : ! d_nm (k) = - i/(ε(n)-ε(m)) [ (C^H)(dH(k)/dk)C ]_nm
3790 : ! + i ε(n)/(ε(n)-ε(m)) [ (C^H)(dS(k)/dk)C ]_nm + [ (C^H)D(k)C ]_nm
3791 : DO n = 1, nao
3792 : DO m = 1, nao
3793 : IF (n == m) CYCLE ! diagonal elements would need to be computed from
3794 : ! a numerical k-derivative which is not implemented
3795 : dip(i_dir, n, m) = -gaussi*C_dH_C(n, m)/(eigenvals(n) - eigenvals(m)) &
3796 : + gaussi*eigenvals(n)*C_dS_C(n, m)/(eigenvals(n) - eigenvals(m)) &
3797 : + CDC(n, m)
3798 : END DO
3799 : END DO
3800 : END DO
3801 : ! Compute the Berry curvature from the dipoles
3802 : ! Ω^γ_n = Σ_m 2*Im[d^α_nm d^β_mn], where, α, β, γ belong to {x, y, z}
3803 : IF (calc_bc) THEN
3804 : bc = 0.0_dp
3805 : DO i_dir = 1, 3
3806 : DO n = 1, nao
3807 : DO m = 1, nao
3808 : IF (n == m) CYCLE
3809 : bc(i_dir, n) = bc(i_dir, n) &
3810 : + 2*AIMAG(dip(1 + MOD(i_dir, 3), n, m)*dip(1 + MOD(i_dir + 1, 3), m, n))
3811 : END DO
3812 : END DO
3813 : END DO
3814 : END IF
3815 : ! Store the dipoles and berry curvature for each MPI rank
3816 : dipole(ispin, CEILING(REAL(ikp)/num_pe), :, :, :) = dip(:, :, :)
3817 : IF (calc_bc) berry_c(ispin, CEILING(REAL(ikp)/num_pe), :, :) = bc(:, :)
3818 : END DO
3819 : END DO
3820 : !$OMP END DO
3821 : DEALLOCATE (dS_dk_i, C_dS_C, dH_dk_i, C_dH_C, CDC, dip, S_k, H_k, C_k, D_k, eigenvals)
3822 : IF (calc_bc) DEALLOCATE (bc)
3823 : !$OMP END PARALLEL
3824 6 : DEALLOCATE (S_rs, H_rs, D_rs)
3825 6 : CALL dbcsr_deallocate_matrix_set(moments_rs_img)
3826 6 : CALL kpoint_release(kpoints_all)
3827 6 : CALL timestop(handle)
3828 24 : END SUBROUTINE qs_moment_kpoints_deep
3829 :
3830 : ! **************************************************************************************************
3831 : !> \brief Calculates interband k-point dipoles in the existing SCF MO basis.
3832 : !> \param qs_env ...
3833 : !> \param dipole ...
3834 : !> \param rcc retained for interface compatibility; interband dipoles are origin independent
3835 : !> \param nmo_spin_out number of SCF MOs available for each spin
3836 : ! **************************************************************************************************
3837 6 : SUBROUTINE qs_moment_kpoints_scf_mos(qs_env, dipole, rcc, nmo_spin_out)
3838 : TYPE(qs_environment_type), POINTER :: qs_env
3839 : COMPLEX(KIND=dp), DIMENSION(:, :, :, :, :), &
3840 : ALLOCATABLE :: dipole
3841 : REAL(KIND=dp), DIMENSION(3), OPTIONAL :: rcc
3842 : INTEGER, DIMENSION(:), ALLOCATABLE, INTENT(OUT), &
3843 : OPTIONAL :: nmo_spin_out
3844 :
3845 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_kpoints_scf_mos'
3846 :
3847 : INTEGER :: handle, i_dir, ikp, ikp_local, ispin, &
3848 : m, n, nao, nkp, nmo, nspin
3849 6 : INTEGER, DIMENSION(:), ALLOCATABLE :: nmo_spin
3850 : INTEGER, DIMENSION(2) :: kp_range
3851 6 : INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index
3852 : LOGICAL :: my_kpgrp
3853 : REAL(KIND=dp), PARAMETER :: eps_degenerate = 1.0E-10_dp
3854 : REAL(KIND=dp) :: cimag, creal, energy_diff
3855 6 : REAL(KIND=dp), DIMENSION(:), ALLOCATABLE :: eigenvalues_kp
3856 6 : REAL(KIND=dp), DIMENSION(:), POINTER :: eigenvals
3857 : TYPE(cp_blacs_env_type), POINTER :: blacs_env_all
3858 : TYPE(cp_fm_struct_type), POINTER :: moment_struct
3859 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
3860 : TYPE(cp_fm_type) :: fm_dummy, fm_tmp, mo_coeff_im_global, &
3861 : mo_coeff_re_global, moment_im, &
3862 : moment_re
3863 : TYPE(cp_fm_type), POINTER :: mo_coeff_im, mo_coeff_re
3864 6 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: overlap_deriv
3865 : TYPE(dbcsr_type), POINTER :: cmatrix, rmatrix
3866 : TYPE(dft_control_type), POINTER :: dft_control
3867 6 : TYPE(kpoint_env_p_type), DIMENSION(:), POINTER :: kp_env
3868 : TYPE(kpoint_env_type), POINTER :: kp
3869 : TYPE(kpoint_type), POINTER :: kpoints_scf
3870 6 : TYPE(mo_set_type), DIMENSION(:, :), POINTER :: mos_kp
3871 : TYPE(mp_para_env_type), POINTER :: para_env, para_env_kp
3872 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
3873 6 : POINTER :: sab_kp, sab_orb
3874 : TYPE(qs_ks_env_type), POINTER :: ks_env
3875 :
3876 6 : CALL timeset(routineN, handle)
3877 :
3878 6 : NULLIFY (blacs_env_all, cell_to_index, cmatrix, dft_control, eigenvals, fm_struct, kp, &
3879 6 : kp_env, kpoints_scf, ks_env, mo_coeff_im, mo_coeff_re, moment_struct, mos_kp, &
3880 6 : overlap_deriv, para_env, para_env_kp, rmatrix, sab_kp, sab_orb)
3881 : IF (PRESENT(rcc)) THEN
3882 : MARK_USED(rcc)
3883 : END IF
3884 :
3885 : CALL get_qs_env(qs_env, dft_control=dft_control, kpoints=kpoints_scf, ks_env=ks_env, &
3886 6 : para_env=para_env, sab_orb=sab_orb)
3887 6 : CPASSERT(ASSOCIATED(dft_control))
3888 6 : CPASSERT(ASSOCIATED(kpoints_scf))
3889 6 : CPASSERT(ASSOCIATED(ks_env))
3890 6 : CPASSERT(ASSOCIATED(para_env))
3891 6 : CPASSERT(ASSOCIATED(sab_orb))
3892 :
3893 : CALL get_kpoint_info(kpoints_scf, nkp=nkp, kp_range=kp_range, kp_env=kp_env, &
3894 : para_env_kp=para_env_kp, blacs_env_all=blacs_env_all, &
3895 6 : cell_to_index=cell_to_index, sab_nl=sab_kp)
3896 6 : IF (kp_range(2) >= kp_range(1)) THEN
3897 6 : CPASSERT(ASSOCIATED(kp_env))
3898 : END IF
3899 6 : CPASSERT(ASSOCIATED(para_env_kp))
3900 6 : CPASSERT(ASSOCIATED(blacs_env_all))
3901 6 : CPASSERT(ASSOCIATED(cell_to_index))
3902 6 : CPASSERT(ASSOCIATED(sab_kp))
3903 :
3904 : CALL build_overlap_matrix(ks_env, matrixkp_s=overlap_deriv, nderivative=1, &
3905 : basis_type_a="ORB", basis_type_b="ORB", sab_nl=sab_orb, &
3906 6 : ext_kpoints=kpoints_scf)
3907 :
3908 6 : nspin = dft_control%nspins
3909 6 : CALL dbcsr_get_info(overlap_deriv(1, 1)%matrix, nfullrows_total=nao)
3910 18 : ALLOCATE (nmo_spin(nspin), source=0)
3911 6 : IF (kp_range(2) >= kp_range(1)) THEN
3912 6 : kp => kp_env(1)%kpoint_env
3913 6 : mos_kp => kp%mos
3914 6 : CPASSERT(ASSOCIATED(mos_kp))
3915 12 : DO ispin = 1, nspin
3916 12 : CALL get_mo_set(mos_kp(1, ispin), nmo=nmo_spin(ispin))
3917 : END DO
3918 : END IF
3919 6 : CALL para_env%max(nmo_spin)
3920 48 : ALLOCATE (dipole(nspin, nkp, 3, MAXVAL(nmo_spin), MAXVAL(nmo_spin)), source=z_zero)
3921 6 : IF (PRESENT(nmo_spin_out)) THEN
3922 8 : ALLOCATE (nmo_spin_out(nspin))
3923 8 : nmo_spin_out(:) = nmo_spin(:)
3924 : END IF
3925 :
3926 6 : ALLOCATE (rmatrix, cmatrix)
3927 : CALL dbcsr_create(rmatrix, template=overlap_deriv(1, 1)%matrix, &
3928 6 : matrix_type=dbcsr_type_antisymmetric)
3929 : CALL dbcsr_create(cmatrix, template=overlap_deriv(1, 1)%matrix, &
3930 6 : matrix_type=dbcsr_type_symmetric)
3931 6 : CALL cp_dbcsr_alloc_block_from_nbl(rmatrix, sab_kp)
3932 6 : CALL cp_dbcsr_alloc_block_from_nbl(cmatrix, sab_kp)
3933 :
3934 258 : DO ikp = 1, nkp
3935 252 : my_kpgrp = (ikp >= kp_range(1) .AND. ikp <= kp_range(2))
3936 : IF (my_kpgrp) THEN
3937 234 : ikp_local = ikp - kp_range(1) + 1
3938 234 : kp => kp_env(ikp_local)%kpoint_env
3939 234 : mos_kp => kp%mos
3940 : ELSE
3941 252 : NULLIFY (kp, mos_kp)
3942 : END IF
3943 510 : DO ispin = 1, nspin
3944 252 : nmo = nmo_spin(ispin)
3945 756 : ALLOCATE (eigenvalues_kp(nmo), source=0.0_dp)
3946 :
3947 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nmo, &
3948 252 : para_env=para_env, context=blacs_env_all)
3949 252 : CALL cp_fm_create(mo_coeff_re_global, fm_struct)
3950 252 : CALL cp_fm_create(mo_coeff_im_global, fm_struct)
3951 252 : CALL cp_fm_create(fm_tmp, fm_struct)
3952 252 : CALL cp_fm_struct_release(fm_struct)
3953 : CALL cp_fm_struct_create(moment_struct, nrow_global=nmo, ncol_global=nmo, &
3954 252 : para_env=para_env, context=blacs_env_all)
3955 252 : CALL cp_fm_create(moment_re, moment_struct)
3956 252 : CALL cp_fm_create(moment_im, moment_struct)
3957 252 : CALL cp_fm_struct_release(moment_struct)
3958 :
3959 252 : IF (my_kpgrp) THEN
3960 234 : CALL get_mo_set(mos_kp(1, ispin), eigenvalues=eigenvals, mo_coeff=mo_coeff_re)
3961 234 : CALL get_mo_set(mos_kp(2, ispin), mo_coeff=mo_coeff_im)
3962 234 : CPASSERT(ASSOCIATED(eigenvals))
3963 234 : CPASSERT(ASSOCIATED(mo_coeff_re))
3964 234 : CPASSERT(ASSOCIATED(mo_coeff_im))
3965 772 : IF (para_env_kp%is_source()) eigenvalues_kp(1:nmo) = eigenvals(1:nmo)
3966 234 : CALL cp_fm_copy_general(mo_coeff_re, mo_coeff_re_global, para_env)
3967 234 : CALL cp_fm_copy_general(mo_coeff_im, mo_coeff_im_global, para_env)
3968 : ELSE
3969 18 : CALL cp_fm_copy_general(fm_dummy, mo_coeff_re_global, para_env)
3970 18 : CALL cp_fm_copy_general(fm_dummy, mo_coeff_im_global, para_env)
3971 : END IF
3972 252 : CALL para_env%sum(eigenvalues_kp)
3973 :
3974 1008 : DO i_dir = 1, 3
3975 756 : CALL dbcsr_set(rmatrix, 0.0_dp)
3976 756 : CALL dbcsr_set(cmatrix, 0.0_dp)
3977 : CALL rskp_transform(rmatrix=rmatrix, cmatrix=cmatrix, rsmat=overlap_deriv, &
3978 : ispin=i_dir + 1, xkp=kpoints_scf%xkp(:, ikp), &
3979 756 : cell_to_index=cell_to_index, sab_nl=sab_kp)
3980 :
3981 : ! Project the complex AO derivative operator as C^H A C. The
3982 : ! off-diagonal length-gauge dipoles follow from the energy-gap relation.
3983 756 : CALL cp_dbcsr_sm_fm_multiply(rmatrix, mo_coeff_re_global, fm_tmp, nmo)
3984 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3985 756 : 1.0_dp, mo_coeff_re_global, fm_tmp, 0.0_dp, moment_re)
3986 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3987 756 : -1.0_dp, mo_coeff_im_global, fm_tmp, 0.0_dp, moment_im)
3988 :
3989 756 : CALL cp_dbcsr_sm_fm_multiply(rmatrix, mo_coeff_im_global, fm_tmp, nmo)
3990 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3991 756 : 1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_im)
3992 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3993 756 : 1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_re)
3994 :
3995 756 : CALL cp_dbcsr_sm_fm_multiply(cmatrix, mo_coeff_re_global, fm_tmp, nmo)
3996 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3997 756 : 1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_im)
3998 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
3999 756 : 1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_re)
4000 :
4001 756 : CALL cp_dbcsr_sm_fm_multiply(cmatrix, mo_coeff_im_global, fm_tmp, nmo)
4002 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
4003 756 : -1.0_dp, mo_coeff_re_global, fm_tmp, 1.0_dp, moment_re)
4004 : CALL parallel_gemm("T", "N", nmo, nmo, nao, &
4005 756 : 1.0_dp, mo_coeff_im_global, fm_tmp, 1.0_dp, moment_im)
4006 :
4007 4236 : DO n = 1, nmo
4008 18108 : DO m = 1, nmo
4009 14124 : IF (n == m) CYCLE
4010 10896 : energy_diff = eigenvalues_kp(m) - eigenvalues_kp(n)
4011 10896 : IF (ABS(energy_diff) <= eps_degenerate) CYCLE
4012 10872 : CALL cp_fm_get_element(moment_re, m, n, creal)
4013 10872 : CALL cp_fm_get_element(moment_im, m, n, cimag)
4014 10872 : IF (para_env%is_source()) &
4015 22788 : dipole(ispin, ikp, i_dir, n, m) = CMPLX(creal, cimag, KIND=dp)/energy_diff
4016 : END DO
4017 : END DO
4018 : END DO
4019 252 : CALL cp_fm_release(mo_coeff_im_global)
4020 252 : CALL cp_fm_release(mo_coeff_re_global)
4021 252 : CALL cp_fm_release(moment_im)
4022 252 : CALL cp_fm_release(moment_re)
4023 252 : CALL cp_fm_release(fm_tmp)
4024 1008 : DEALLOCATE (eigenvalues_kp)
4025 : END DO
4026 : END DO
4027 :
4028 12 : DO ispin = 1, nspin
4029 264 : DO ikp = 1, nkp
4030 1014 : DO i_dir = 1, 3
4031 35712 : CALL para_env%sum(dipole(ispin, ikp, i_dir, :, :))
4032 : END DO
4033 : END DO
4034 : END DO
4035 :
4036 6 : CALL dbcsr_deallocate_matrix(cmatrix)
4037 6 : CALL dbcsr_deallocate_matrix(rmatrix)
4038 6 : CALL dbcsr_deallocate_matrix_set(overlap_deriv)
4039 6 : DEALLOCATE (nmo_spin)
4040 6 : CALL timestop(handle)
4041 :
4042 18 : END SUBROUTINE qs_moment_kpoints_scf_mos
4043 :
4044 : ! **************************************************************************************************
4045 : !> \brief Calculate and print dipole moment elements d_nm(k) for k-point calculations
4046 : !> \param qs_env ...
4047 : !> \param nmoments ...
4048 : !> \param reference ...
4049 : !> \param ref_point ...
4050 : !> \param max_nmo ...
4051 : !> \param unit_number ...
4052 : !> \author Shridhar Shanbhag
4053 : ! **************************************************************************************************
4054 10 : SUBROUTINE qs_moment_kpoints(qs_env, nmoments, reference, ref_point, max_nmo, unit_number)
4055 : TYPE(qs_environment_type), POINTER :: qs_env
4056 : INTEGER, INTENT(IN) :: nmoments, reference, max_nmo
4057 : REAL(dp), DIMENSION(:), INTENT(IN), POINTER :: ref_point
4058 : INTEGER, INTENT(IN) :: unit_number
4059 : CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_moment_kpoints'
4060 10 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks_kp
4061 10 : COMPLEX(KIND=dp), DIMENSION(:, :, :), ALLOCATABLE :: dipole_to_print
4062 : COMPLEX(KIND=dp), DIMENSION(:, :, :, :, :), &
4063 10 : ALLOCATABLE :: dipole
4064 : INTEGER :: handle, i_dir, ikp, nmo_dim, nkp, nao, &
4065 : num_pe, mepos, n, m, &
4066 : ispin, nspin, nmin, nmax, homo
4067 10 : INTEGER, DIMENSION(:), ALLOCATABLE :: nmo_spin_scf
4068 : LOGICAL :: explicit_kpnts, explicit_kpset, use_scf_mos
4069 : REAL(KIND=dp), DIMENSION(3) :: rcc
4070 10 : REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: xkp
4071 10 : REAL(KIND=dp), DIMENSION(:, :), ALLOCATABLE :: bc_to_print
4072 10 : REAL(KIND=dp), DIMENSION(:, :, :, :), ALLOCATABLE :: berry_c
4073 10 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
4074 : TYPE(mp_para_env_type), POINTER :: para_env
4075 : TYPE(section_vals_type), POINTER :: kpnts, kpset
4076 : CHARACTER(LEN=default_string_length), &
4077 10 : DIMENSION(:), POINTER :: special_pnts
4078 :
4079 10 : CALL timeset(routineN, handle)
4080 :
4081 10 : IF (nmoments > 1) CPABORT("KPOINT quadrupole and higher moments not implemented.")
4082 10 : IF (max_nmo < 0) CPABORT("Negative maximum number of molecular orbitals max_nmo provided.")
4083 :
4084 : CALL get_qs_env(qs_env, &
4085 : para_env=para_env, &
4086 : matrix_ks_kp=matrix_ks_kp, &
4087 10 : mos=mos)
4088 :
4089 10 : CALL get_mo_set(mo_set=mos(1), nao=nao)
4090 10 : CALL get_xkp_for_dipole_calc(qs_env, xkp, special_pnts)
4091 10 : CALL get_reference_point(rcc, qs_env=qs_env, reference=reference, ref_point=ref_point)
4092 10 : nspin = SIZE(matrix_ks_kp, 1)
4093 10 : nkp = SIZE(xkp, 2)
4094 :
4095 10 : kpset => section_vals_get_subs_vals(qs_env%input, "DFT%PRINT%MOMENTS%KPOINT_SET")
4096 10 : kpnts => section_vals_get_subs_vals(qs_env%input, "DFT%PRINT%MOMENTS%KPOINTS")
4097 10 : CALL section_vals_get(kpset, explicit=explicit_kpset)
4098 10 : CALL section_vals_get(kpnts, explicit=explicit_kpnts)
4099 10 : use_scf_mos = .NOT. explicit_kpset .AND. .NOT. explicit_kpnts
4100 :
4101 10 : IF (unit_number > 0) WRITE (unit_number, FMT="(/,T2,A)") &
4102 5 : '!-----------------------------------------------------------------------------!'
4103 10 : IF (unit_number > 0) WRITE (unit_number, "(T22,A)") "Periodic Dipole Matrix Elements"
4104 :
4105 10 : IF (use_scf_mos) THEN
4106 4 : CALL qs_moment_kpoints_scf_mos(qs_env, dipole, rcc, nmo_spin_scf)
4107 4 : nmo_dim = SIZE(dipole, 4)
4108 24 : ALLOCATE (berry_c(nspin, nkp, 3, nmo_dim), source=0.0_dp)
4109 8 : DO ispin = 1, nspin
4110 256 : DO ikp = 1, nkp
4111 996 : DO i_dir = 1, 3
4112 4160 : DO n = 1, nmo_dim
4113 17736 : DO m = 1, nmo_dim
4114 13824 : IF (n == m) CYCLE
4115 : berry_c(ispin, ikp, i_dir, n) = berry_c(ispin, ikp, i_dir, n) &
4116 : + 2*AIMAG(dipole(ispin, ikp, 1 + MOD(i_dir, 3), n, m)* &
4117 16992 : dipole(ispin, ikp, 1 + MOD(i_dir + 1, 3), m, n))
4118 : END DO
4119 : END DO
4120 : END DO
4121 : END DO
4122 : END DO
4123 : ELSE
4124 : CALL qs_moment_kpoints_deep(qs_env, &
4125 : xkp, &
4126 : dipole, &
4127 : rcc, &
4128 : berry_c, &
4129 6 : do_parallel=.TRUE.)
4130 6 : nmo_dim = nao
4131 : END IF
4132 :
4133 40 : ALLOCATE (dipole_to_print(3, nmo_dim, nmo_dim), source=z_zero)
4134 30 : ALLOCATE (bc_to_print(3, nmo_dim), source=0.0_dp)
4135 :
4136 10 : mepos = para_env%mepos
4137 10 : num_pe = para_env%num_pe
4138 :
4139 264 : DO ikp = 1, nkp
4140 520 : DO ispin = 1, nspin
4141 256 : CALL get_mo_set(mo_set=mos(ispin), homo=homo)
4142 256 : nmin = max(1, homo - (max_nmo - 1)/2)
4143 256 : nmax = min(nao, homo + max_nmo/2)
4144 256 : IF (max_nmo == 0) THEN
4145 0 : nmin = 1
4146 0 : nmax = nao
4147 : END IF
4148 256 : IF (use_scf_mos) THEN
4149 248 : nmax = min(nmax, nmo_spin_scf(ispin))
4150 : END IF
4151 256 : dipole_to_print = 0.0_dp
4152 256 : bc_to_print = 0.0_dp
4153 256 : IF (use_scf_mos) THEN
4154 19736 : dipole_to_print(:, :, :) = dipole(ispin, ikp, :, :, :)
4155 4472 : bc_to_print(:, :) = berry_c(ispin, ikp, :, :)
4156 8 : ELSE IF (mod(ikp - 1, num_pe) == mepos) THEN
4157 87268 : dipole_to_print(:, :, :) = dipole(ispin, CEILING(REAL(ikp)/num_pe), :, :, :)
4158 900 : bc_to_print(:, :) = berry_c(ispin, CEILING(REAL(ikp)/num_pe), :, :)
4159 : END IF
4160 256 : IF (.NOT. use_scf_mos) THEN
4161 8 : CALL para_env%sum(dipole_to_print)
4162 8 : CALL para_env%sum(bc_to_print)
4163 : END IF
4164 766 : IF (unit_number > 0) THEN
4165 128 : IF (special_pnts(ikp) /= "") WRITE (unit_number, "(/,2X,A,A)") &
4166 3 : "Special point: ", ADJUSTL(TRIM(special_pnts(ikp)))
4167 : WRITE (unit_number, "(/,1X,A,I3,1X,3(A,1F12.6))") &
4168 128 : "Kpoint:", ikp, ", kx:", xkp(1, ikp), ", ky:", xkp(2, ikp), ", kz:", xkp(3, ikp)
4169 128 : IF (nspin > 1) WRITE (unit_number, "(/,2X,A,I2)") "Open Shell System. Spin:", ispin
4170 : WRITE (unit_number, "(2X,A)") " kp n m Re(dx_nm) Im(dx_nm) &
4171 128 : & Re(dy_nm) Im(dy_nm) Re(dz_nm) Im(dz_nm)"
4172 676 : DO n = nmin, nmax
4173 3116 : DO m = nmin, nmax
4174 2440 : IF (n == m) CYCLE
4175 2988 : WRITE (unit_number, "(2X,I4,2I4,6(G11.3))") ikp, n, m, dipole_to_print(1:3, n, m)
4176 : END DO
4177 : END DO
4178 128 : WRITE (unit_number, "(/,1X,A)") "Berry Curvature"
4179 128 : WRITE (unit_number, "(2X,A)") " kp n YZ ZX XY"
4180 676 : DO n = nmin, nmax
4181 : WRITE (unit_number, "(2X,2I5,3(1X,G11.3))") &
4182 676 : ikp, n, bc_to_print(1, n), bc_to_print(2, n), bc_to_print(3, n)
4183 : END DO
4184 : END IF
4185 : END DO
4186 : END DO
4187 10 : DEALLOCATE (dipole_to_print, bc_to_print, berry_c, dipole)
4188 10 : IF (ALLOCATED(nmo_spin_scf)) DEALLOCATE (nmo_spin_scf)
4189 10 : DEALLOCATE (special_pnts, xkp)
4190 :
4191 10 : CALL timestop(handle)
4192 :
4193 40 : END SUBROUTINE qs_moment_kpoints
4194 :
4195 : END MODULE qs_moments
|