Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2025 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Calculate intrinsic atomic orbitals and analyze wavefunctions
10 : !> \par History
11 : !> 03.2023 created [JGH]
12 : !> \author JGH
13 : ! **************************************************************************************************
14 : MODULE iao_analysis
15 : USE ai_contraction, ONLY: block_add,&
16 : contraction
17 : USE ai_overlap, ONLY: overlap_ab
18 : USE atomic_charges, ONLY: print_atomic_charges
19 : USE atomic_kind_types, ONLY: atomic_kind_type,&
20 : get_atomic_kind
21 : USE auto_basis, ONLY: create_oce_basis
22 : USE basis_set_types, ONLY: deallocate_gto_basis_set,&
23 : get_gto_basis_set,&
24 : gto_basis_set_p_type,&
25 : gto_basis_set_type,&
26 : init_orb_basis_set
27 : USE bibliography, ONLY: Knizia2013,&
28 : cite_reference
29 : USE cell_types, ONLY: cell_type,&
30 : pbc
31 : USE cp_array_utils, ONLY: cp_2d_r_p_type
32 : USE cp_control_types, ONLY: dft_control_type
33 : USE cp_dbcsr_api, ONLY: &
34 : dbcsr_copy, dbcsr_create, dbcsr_distribution_type, dbcsr_get_block_p, dbcsr_get_info, &
35 : dbcsr_iterator_blocks_left, dbcsr_iterator_next_block, dbcsr_iterator_start, &
36 : dbcsr_iterator_stop, dbcsr_iterator_type, dbcsr_multiply, dbcsr_p_type, dbcsr_release, &
37 : dbcsr_replicate_all, dbcsr_set, dbcsr_type, dbcsr_type_no_symmetry
38 : USE cp_dbcsr_contrib, ONLY: dbcsr_reserve_diag_blocks,&
39 : dbcsr_trace
40 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
41 : copy_fm_to_dbcsr,&
42 : cp_dbcsr_plus_fm_fm_t,&
43 : cp_dbcsr_sm_fm_multiply,&
44 : dbcsr_deallocate_matrix_set
45 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale,&
46 : cp_fm_geadd,&
47 : cp_fm_invert,&
48 : cp_fm_rot_cols,&
49 : cp_fm_rot_rows
50 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
51 : cp_fm_struct_release,&
52 : cp_fm_struct_type
53 : USE cp_fm_types, ONLY: cp_fm_create,&
54 : cp_fm_get_diag,&
55 : cp_fm_get_element,&
56 : cp_fm_get_info,&
57 : cp_fm_release,&
58 : cp_fm_set_all,&
59 : cp_fm_to_fm,&
60 : cp_fm_type
61 : USE cp_log_handling, ONLY: cp_get_default_logger,&
62 : cp_logger_type
63 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
64 : cp_print_key_unit_nr
65 : USE cp_realspace_grid_cube, ONLY: cp_pw_to_cube
66 : USE iao_types, ONLY: iao_env_type
67 : USE input_constants, ONLY: do_iaoloc_enone,&
68 : do_iaoloc_pm2
69 : USE input_section_types, ONLY: section_get_ivals,&
70 : section_vals_get,&
71 : section_vals_type,&
72 : section_vals_val_get
73 : USE kinds, ONLY: default_path_length,&
74 : default_string_length,&
75 : dp
76 : USE machine, ONLY: m_walltime
77 : USE mathconstants, ONLY: twopi
78 : USE mathlib, ONLY: invmat_symm,&
79 : jacobi
80 : USE message_passing, ONLY: mp_comm_type
81 : USE min_basis_set, ONLY: create_minbas_set
82 : USE molden_utils, ONLY: write_mos_molden
83 : USE orbital_pointers, ONLY: ncoset
84 : USE parallel_gemm_api, ONLY: parallel_gemm
85 : USE particle_list_types, ONLY: particle_list_type
86 : USE particle_methods, ONLY: get_particle_set
87 : USE particle_types, ONLY: particle_type
88 : USE pw_env_types, ONLY: pw_env_get,&
89 : pw_env_type
90 : USE pw_pool_types, ONLY: pw_pool_type
91 : USE pw_types, ONLY: pw_c1d_gs_type,&
92 : pw_r3d_rs_type
93 : USE qs_collocate_density, ONLY: calculate_wavefunction
94 : USE qs_environment_types, ONLY: get_qs_env,&
95 : qs_environment_type
96 : USE qs_interactions, ONLY: init_interaction_radii_orb_basis
97 : USE qs_kind_types, ONLY: get_qs_kind,&
98 : qs_kind_type
99 : USE qs_ks_types, ONLY: get_ks_env,&
100 : qs_ks_env_type
101 : USE qs_loc_utils, ONLY: compute_berry_operator
102 : USE qs_localization_methods, ONLY: initialize_weights,&
103 : rotate_orbitals,&
104 : scdm_qrfact
105 : USE qs_mo_methods, ONLY: make_basis_lowdin
106 : USE qs_mo_types, ONLY: allocate_mo_set,&
107 : deallocate_mo_set,&
108 : get_mo_set,&
109 : init_mo_set,&
110 : mo_set_type,&
111 : set_mo_set
112 : USE qs_moments, ONLY: build_local_moment_matrix
113 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type,&
114 : release_neighbor_list_sets
115 : USE qs_neighbor_lists, ONLY: setup_neighbor_list
116 : USE qs_overlap, ONLY: build_overlap_matrix_simple
117 : USE qs_subsys_types, ONLY: qs_subsys_get,&
118 : qs_subsys_type
119 : #include "./base/base_uses.f90"
120 :
121 : IMPLICIT NONE
122 : PRIVATE
123 :
124 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'iao_analysis'
125 :
126 : PUBLIC :: iao_wfn_analysis, iao_charges, iao_calculate_dmat, print_center_spread
127 :
128 : INTERFACE iao_calculate_dmat
129 : MODULE PROCEDURE iao_calculate_dmat_diag, & ! diagonal occupation matrix
130 : iao_calculate_dmat_full ! full occupation matrix
131 : END INTERFACE
132 :
133 : ! **************************************************************************************************
134 :
135 : CONTAINS
136 :
137 : ! **************************************************************************************************
138 : !> \brief ...
139 : !> \param qs_env ...
140 : !> \param iao_env ...
141 : !> \param unit_nr ...
142 : !> \param c_iao_coef ...
143 : !> \param mos ...
144 : !> \param bond_centers ...
145 : ! **************************************************************************************************
146 34 : SUBROUTINE iao_wfn_analysis(qs_env, iao_env, unit_nr, c_iao_coef, mos, bond_centers)
147 : TYPE(qs_environment_type), POINTER :: qs_env
148 : TYPE(iao_env_type), INTENT(IN) :: iao_env
149 : INTEGER, INTENT(IN) :: unit_nr
150 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:), &
151 : OPTIONAL :: c_iao_coef
152 : TYPE(mo_set_type), DIMENSION(:), OPTIONAL, POINTER :: mos
153 : REAL(KIND=dp), DIMENSION(:, :, :), OPTIONAL :: bond_centers
154 :
155 : CHARACTER(len=*), PARAMETER :: routineN = 'iao_wfn_analysis'
156 :
157 : CHARACTER(LEN=2) :: element_symbol
158 : CHARACTER(LEN=default_string_length) :: bname
159 : INTEGER :: handle, i, iatom, ikind, isgf, ispin, &
160 : nao, natom, nimages, nkind, no, norb, &
161 : nref, ns, nsgf, nspin, nvec, nx, order
162 34 : INTEGER, ALLOCATABLE, DIMENSION(:) :: first_sgf, last_sgf, nsgfat
163 : INTEGER, DIMENSION(2) :: nocc
164 : LOGICAL :: cubes_iao, cubes_ibo, molden_iao, &
165 : molden_ibo, uniform_occupation
166 : REAL(KIND=dp) :: fin, fout, t1, t2, trace, zval
167 34 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: fdiag
168 34 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: mcharge
169 34 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: moments
170 34 : REAL(KIND=dp), DIMENSION(:), POINTER :: occupation_numbers
171 34 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:) :: smat_kind
172 34 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:, :) :: oce_atom
173 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
174 : TYPE(cp_fm_type) :: p_orb_ref, p_ref_orb, smo
175 34 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: c_loc_orb, ciao, cloc, cvec, iao_coef
176 34 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: zij_atom
177 : TYPE(cp_fm_type), POINTER :: mo_coeff
178 34 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: sref, sro, sxo
179 34 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s
180 : TYPE(dbcsr_type) :: dmat
181 : TYPE(dbcsr_type), POINTER :: smat
182 : TYPE(dft_control_type), POINTER :: dft_control
183 34 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: oce_basis_set_list, orb_basis_set_list, &
184 34 : ref_basis_set_list
185 : TYPE(gto_basis_set_type), POINTER :: ocebasis, orbbasis, refbasis
186 34 : TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: mo_iao, mo_loc
187 34 : TYPE(mo_set_type), DIMENSION(:), POINTER :: my_mos
188 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
189 34 : POINTER :: sro_list, srr_list, sxo_list
190 34 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
191 34 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
192 : TYPE(qs_kind_type), POINTER :: qs_kind
193 : TYPE(qs_ks_env_type), POINTER :: ks_env
194 : TYPE(section_vals_type), POINTER :: iao_cubes_section, iao_molden_section, &
195 : ibo_cc_section, ibo_cubes_section, &
196 : ibo_molden_section
197 :
198 : ! only do IAO analysis if explicitly requested
199 0 : CPASSERT(iao_env%do_iao)
200 :
201 : ! k-points?
202 34 : CALL get_qs_env(qs_env, dft_control=dft_control)
203 34 : nspin = dft_control%nspins
204 34 : nimages = dft_control%nimages
205 34 : IF (nimages > 1) THEN
206 0 : IF (unit_nr > 0) THEN
207 : WRITE (UNIT=unit_nr, FMT="(T2,A)") &
208 0 : "K-Points: Intrinsic Atomic Orbitals Analysis not available."
209 : END IF
210 : END IF
211 0 : IF (nimages > 1) RETURN
212 :
213 34 : CALL timeset(routineN, handle)
214 :
215 34 : IF (unit_nr > 0) THEN
216 17 : WRITE (unit_nr, '(/,T2,A)') '!-----------------------------------------------------------------------------!'
217 17 : WRITE (UNIT=unit_nr, FMT="(T24,A)") "INTRINSIC ATOMIC ORBITALS ANALYSIS"
218 17 : WRITE (UNIT=unit_nr, FMT="(T13,A)") "G. Knizia, J. Chem. Theory Comput. 9, 4834-4843 (2013)"
219 17 : WRITE (unit_nr, '(T2,A)') '!-----------------------------------------------------------------------------!'
220 : END IF
221 34 : CALL cite_reference(Knizia2013)
222 :
223 : ! input sections
224 34 : iao_molden_section => iao_env%iao_molden_section
225 34 : iao_cubes_section => iao_env%iao_cubes_section
226 34 : ibo_molden_section => iao_env%ibo_molden_section
227 34 : ibo_cubes_section => iao_env%ibo_cubes_section
228 34 : ibo_cc_section => iao_env%ibo_cc_section
229 :
230 : !
231 34 : molden_iao = .FALSE.
232 34 : IF (ASSOCIATED(iao_molden_section)) THEN
233 4 : CALL section_vals_get(iao_molden_section, explicit=molden_iao)
234 : END IF
235 34 : cubes_iao = .FALSE.
236 34 : IF (ASSOCIATED(iao_cubes_section)) THEN
237 4 : CALL section_vals_get(iao_cubes_section, explicit=cubes_iao)
238 : END IF
239 34 : molden_ibo = .FALSE.
240 34 : IF (ASSOCIATED(ibo_molden_section)) THEN
241 4 : CALL section_vals_get(ibo_molden_section, explicit=molden_ibo)
242 : END IF
243 34 : cubes_ibo = .FALSE.
244 34 : IF (ASSOCIATED(ibo_cubes_section)) THEN
245 4 : CALL section_vals_get(ibo_cubes_section, explicit=cubes_ibo)
246 : END IF
247 :
248 : ! check for or generate reference basis
249 34 : CALL create_minbas_set(qs_env, unit_nr)
250 :
251 : ! overlap matrices
252 34 : CALL get_qs_env(qs_env, matrix_s_kp=matrix_s)
253 34 : smat => matrix_s(1, 1)%matrix
254 : !
255 34 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
256 34 : nkind = SIZE(qs_kind_set)
257 276 : ALLOCATE (ref_basis_set_list(nkind), orb_basis_set_list(nkind))
258 104 : DO ikind = 1, nkind
259 70 : qs_kind => qs_kind_set(ikind)
260 70 : NULLIFY (ref_basis_set_list(ikind)%gto_basis_set)
261 70 : NULLIFY (orb_basis_set_list(ikind)%gto_basis_set)
262 70 : NULLIFY (refbasis, orbbasis)
263 70 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=orbbasis, basis_type="ORB")
264 70 : IF (ASSOCIATED(orbbasis)) orb_basis_set_list(ikind)%gto_basis_set => orbbasis
265 70 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=refbasis, basis_type="MIN")
266 104 : IF (ASSOCIATED(refbasis)) ref_basis_set_list(ikind)%gto_basis_set => refbasis
267 : END DO
268 :
269 : ! neighbor lists
270 34 : NULLIFY (srr_list, sro_list)
271 34 : CALL setup_neighbor_list(srr_list, ref_basis_set_list, qs_env=qs_env)
272 34 : CALL setup_neighbor_list(sro_list, ref_basis_set_list, orb_basis_set_list, qs_env=qs_env)
273 :
274 : ! Srr and Sro overlap matrices
275 34 : NULLIFY (sref, sro)
276 34 : CALL get_qs_env(qs_env, ks_env=ks_env)
277 : CALL build_overlap_matrix_simple(ks_env, sref, &
278 34 : ref_basis_set_list, ref_basis_set_list, srr_list)
279 : CALL build_overlap_matrix_simple(ks_env, sro, &
280 34 : ref_basis_set_list, orb_basis_set_list, sro_list)
281 : !
282 34 : IF (PRESENT(mos)) THEN
283 30 : my_mos => mos
284 : ELSE
285 4 : CALL get_qs_env(qs_env, mos=my_mos)
286 : END IF
287 34 : CALL get_mo_set(my_mos(1), mo_coeff=mo_coeff)
288 34 : CALL dbcsr_get_info(sro(1)%matrix, nfullrows_total=nref, nfullcols_total=nao)
289 :
290 : ! Projectors
291 34 : NULLIFY (fm_struct)
292 : CALL cp_fm_struct_create(fm_struct, context=mo_coeff%matrix_struct%context, nrow_global=nref, &
293 34 : ncol_global=nao, para_env=mo_coeff%matrix_struct%para_env)
294 34 : CALL cp_fm_create(p_ref_orb, fm_struct)
295 34 : CALL cp_fm_struct_release(fm_struct)
296 34 : NULLIFY (fm_struct)
297 : CALL cp_fm_struct_create(fm_struct, context=mo_coeff%matrix_struct%context, nrow_global=nao, &
298 34 : ncol_global=nref, para_env=mo_coeff%matrix_struct%para_env)
299 34 : CALL cp_fm_create(p_orb_ref, fm_struct)
300 34 : CALL cp_fm_struct_release(fm_struct)
301 : !
302 34 : CALL iao_projectors(smat, sref(1)%matrix, sro(1)%matrix, p_orb_ref, p_ref_orb, iao_env%eps_svd)
303 :
304 : ! occupied orbitals, orbitals considered for IAO generation
305 34 : nocc(1:2) = 0
306 70 : DO ispin = 1, nspin
307 : CALL get_mo_set(my_mos(ispin), mo_coeff=mo_coeff, nmo=norb, uniform_occupation=uniform_occupation, &
308 36 : occupation_numbers=occupation_numbers)
309 36 : IF (uniform_occupation) THEN
310 34 : nvec = norb
311 : ELSE
312 2 : nvec = 0
313 46 : DO i = 1, norb
314 46 : IF (occupation_numbers(i) > iao_env%eps_occ) THEN
315 44 : nvec = i
316 : ELSE
317 : EXIT
318 : END IF
319 : END DO
320 : END IF
321 106 : nocc(ispin) = nvec
322 : END DO
323 : ! generate IAOs
324 208 : ALLOCATE (iao_coef(nspin), cvec(nspin))
325 70 : DO ispin = 1, nspin
326 36 : CALL get_mo_set(my_mos(ispin), mo_coeff=mo_coeff)
327 36 : nvec = nocc(ispin)
328 70 : IF (nvec > 0) THEN
329 36 : NULLIFY (fm_struct)
330 36 : CALL cp_fm_struct_create(fm_struct, ncol_global=nvec, template_fmstruct=mo_coeff%matrix_struct)
331 36 : CALL cp_fm_create(cvec(ispin), fm_struct)
332 36 : CALL cp_fm_struct_release(fm_struct)
333 36 : CALL cp_fm_to_fm(mo_coeff, cvec(ispin), nvec)
334 : !
335 36 : NULLIFY (fm_struct)
336 36 : CALL cp_fm_struct_create(fm_struct, ncol_global=nref, template_fmstruct=mo_coeff%matrix_struct)
337 36 : CALL cp_fm_create(iao_coef(ispin), fm_struct)
338 36 : CALL cp_fm_struct_release(fm_struct)
339 : !
340 36 : CALL intrinsic_ao_calc(smat, p_orb_ref, p_ref_orb, cvec(ispin), iao_coef(ispin))
341 : END IF
342 : END DO
343 : !
344 34 : IF (iao_env%do_charges) THEN
345 : ! MOs in IAO basis
346 104 : ALLOCATE (ciao(nspin))
347 70 : DO ispin = 1, nspin
348 36 : CALL get_mo_set(my_mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=norb)
349 36 : CALL cp_fm_create(smo, mo_coeff%matrix_struct)
350 36 : NULLIFY (fm_struct)
351 36 : CALL cp_fm_struct_create(fm_struct, nrow_global=nref, template_fmstruct=mo_coeff%matrix_struct)
352 36 : CALL cp_fm_create(ciao(ispin), fm_struct)
353 36 : CALL cp_fm_struct_release(fm_struct)
354 : ! CIAO = A(T)*S*C
355 36 : CALL cp_dbcsr_sm_fm_multiply(smat, mo_coeff, smo, ncol=norb)
356 36 : CALL parallel_gemm('T', 'N', nref, norb, nao, 1.0_dp, iao_coef(ispin), smo, 0.0_dp, ciao(ispin))
357 106 : CALL cp_fm_release(smo)
358 : END DO
359 : !
360 : ! population analysis
361 34 : IF (unit_nr > 0) THEN
362 17 : WRITE (unit_nr, '(/,T2,A)') 'Intrinsic AO Population Analysis '
363 : END IF
364 34 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, natom=natom)
365 34 : CALL get_ks_env(ks_env=ks_env, particle_set=particle_set)
366 136 : ALLOCATE (mcharge(natom, nspin))
367 34 : CALL dbcsr_get_info(sref(1)%matrix, nfullrows_total=nref)
368 70 : DO ispin = 1, nspin
369 : CALL get_mo_set(my_mos(ispin), &
370 : uniform_occupation=uniform_occupation, &
371 36 : occupation_numbers=occupation_numbers)
372 : ! diagonal block matrix
373 36 : CALL dbcsr_create(dmat, template=sref(1)%matrix)
374 36 : CALL dbcsr_reserve_diag_blocks(dmat)
375 : !
376 36 : CALL iao_calculate_dmat(ciao(ispin), dmat, occupation_numbers, uniform_occupation)
377 36 : CALL dbcsr_trace(dmat, trace)
378 36 : IF (unit_nr > 0) THEN
379 18 : WRITE (unit_nr, '(T2,A,I2,T66,F15.4)') 'Number of Electrons: Trace(Piao) Spin ', ispin, trace
380 : END IF
381 36 : CALL iao_charges(dmat, mcharge(:, ispin))
382 142 : CALL dbcsr_release(dmat)
383 : END DO
384 : CALL print_atomic_charges(particle_set, qs_kind_set, unit_nr, "Intrinsic Atomic Orbital Charges", &
385 34 : electronic_charges=mcharge)
386 34 : DEALLOCATE (mcharge)
387 68 : CALL cp_fm_release(ciao)
388 : END IF
389 : !
390 : ! Deallocate the neighbor list structure
391 34 : CALL release_neighbor_list_sets(srr_list)
392 34 : CALL release_neighbor_list_sets(sro_list)
393 34 : IF (ASSOCIATED(sref)) CALL dbcsr_deallocate_matrix_set(sref)
394 34 : IF (ASSOCIATED(sro)) CALL dbcsr_deallocate_matrix_set(sro)
395 34 : CALL cp_fm_release(p_ref_orb)
396 34 : CALL cp_fm_release(p_orb_ref)
397 34 : CALL cp_fm_release(cvec)
398 34 : DEALLOCATE (orb_basis_set_list)
399 : !
400 34 : IF (iao_env%do_oce) THEN
401 : ! generate OCE basis
402 4 : IF (unit_nr > 0) THEN
403 2 : WRITE (unit_nr, '(T2,A)') "IAO One-Center Expansion: OCE Basis Set"
404 : END IF
405 4 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
406 4 : nkind = SIZE(qs_kind_set)
407 40 : ALLOCATE (oce_basis_set_list(nkind), orb_basis_set_list(nkind))
408 16 : DO ikind = 1, nkind
409 12 : qs_kind => qs_kind_set(ikind)
410 12 : NULLIFY (orb_basis_set_list(ikind)%gto_basis_set)
411 12 : NULLIFY (orbbasis)
412 12 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=orbbasis, basis_type="ORB")
413 16 : IF (ASSOCIATED(orbbasis)) orb_basis_set_list(ikind)%gto_basis_set => orbbasis
414 : END DO
415 16 : DO ikind = 1, nkind
416 12 : orbbasis => orb_basis_set_list(ikind)%gto_basis_set
417 12 : CPASSERT(ASSOCIATED(orbbasis))
418 12 : NULLIFY (ocebasis)
419 12 : CALL create_oce_basis(ocebasis, orbbasis, iao_env%lmax_oce, iao_env%nbas_oce)
420 12 : CALL init_orb_basis_set(ocebasis)
421 12 : CALL init_interaction_radii_orb_basis(ocebasis, dft_control%qs_control%eps_pgf_orb)
422 12 : oce_basis_set_list(ikind)%gto_basis_set => ocebasis
423 16 : IF (unit_nr > 0) THEN
424 6 : qs_kind => qs_kind_set(ikind)
425 6 : CALL get_qs_kind(qs_kind, zeff=zval, element_symbol=element_symbol)
426 6 : CALL get_gto_basis_set(ocebasis, name=bname, nsgf=nsgf)
427 6 : WRITE (unit_nr, '(T2,A,A,T14,A,I4,T40,A,A30)') "Kind: ", element_symbol, "NBasFun: ", nsgf, &
428 12 : "OCE Basis: ", ADJUSTL(TRIM(bname))
429 : END IF
430 : END DO
431 4 : IF (unit_nr > 0) WRITE (unit_nr, *)
432 : ! OCE basis overlap
433 24 : ALLOCATE (smat_kind(nkind))
434 16 : DO ikind = 1, nkind
435 12 : ocebasis => oce_basis_set_list(ikind)%gto_basis_set
436 12 : CALL get_gto_basis_set(gto_basis_set=ocebasis, nsgf=nsgf)
437 52 : ALLOCATE (smat_kind(ikind)%array(nsgf, nsgf))
438 : END DO
439 4 : CALL oce_overlap_matrix(smat_kind, oce_basis_set_list)
440 : ! overlap between IAO OCE basis and orbital basis
441 4 : NULLIFY (sxo, sxo_list)
442 4 : CALL setup_neighbor_list(sxo_list, oce_basis_set_list, orb_basis_set_list, qs_env=qs_env)
443 4 : CALL get_qs_env(qs_env, ks_env=ks_env)
444 : CALL build_overlap_matrix_simple(ks_env, sxo, &
445 4 : oce_basis_set_list, orb_basis_set_list, sxo_list)
446 : !
447 : ! One Center Expansion of IAOs
448 4 : CALL get_qs_env(qs_env=qs_env, natom=natom)
449 36 : ALLOCATE (oce_atom(natom, nspin))
450 4 : CALL iao_oce_expansion(qs_env, oce_basis_set_list, smat_kind, sxo, iao_coef, oce_atom, unit_nr)
451 : !
452 16 : DO ikind = 1, nkind
453 12 : ocebasis => oce_basis_set_list(ikind)%gto_basis_set
454 16 : CALL deallocate_gto_basis_set(ocebasis)
455 : END DO
456 4 : DEALLOCATE (oce_basis_set_list, orb_basis_set_list)
457 : !
458 4 : CALL release_neighbor_list_sets(sxo_list)
459 4 : IF (ASSOCIATED(sxo)) CALL dbcsr_deallocate_matrix_set(sxo)
460 16 : DO ikind = 1, nkind
461 16 : DEALLOCATE (smat_kind(ikind)%array)
462 : END DO
463 4 : DEALLOCATE (smat_kind)
464 8 : DO ispin = 1, nspin
465 24 : DO iatom = 1, natom
466 20 : DEALLOCATE (oce_atom(iatom, ispin)%array)
467 : END DO
468 : END DO
469 4 : DEALLOCATE (oce_atom)
470 : END IF
471 : !
472 34 : IF (molden_iao) THEN
473 : ! Print basis functions: molden file
474 4 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
475 4 : CALL get_ks_env(ks_env=ks_env, particle_set=particle_set)
476 4 : IF (unit_nr > 0) THEN
477 2 : WRITE (unit_nr, '(T2,A)') ' Write IAO in MOLDEN Format'
478 : END IF
479 16 : ALLOCATE (mo_iao(nspin))
480 8 : DO ispin = 1, nspin
481 4 : CALL get_mo_set(my_mos(ispin), nao=nao)
482 4 : CALL allocate_mo_set(mo_iao(ispin), nao, nref, nref, 0.0_dp, 1.0_dp, 0.0_dp)
483 4 : CALL init_mo_set(mo_iao(ispin), fm_ref=iao_coef(ispin), name="iao_set")
484 4 : CALL cp_fm_to_fm(iao_coef(ispin), mo_iao(ispin)%mo_coeff)
485 4 : CALL set_mo_set(mo_iao(ispin), homo=nref)
486 56 : mo_iao(ispin)%occupation_numbers = 1.0_dp
487 : END DO
488 : ! Print IAO basis functions: molden format
489 4 : CALL write_mos_molden(mo_iao, qs_kind_set, particle_set, iao_molden_section)
490 8 : DO ispin = 1, nspin
491 8 : CALL deallocate_mo_set(mo_iao(ispin))
492 : END DO
493 4 : DEALLOCATE (mo_iao)
494 : END IF
495 34 : IF (cubes_iao) THEN
496 4 : IF (unit_nr > 0) THEN
497 2 : WRITE (unit_nr, '(T2,A)') ' Write IAO as CUBE Files'
498 : END IF
499 : ! Print basis functions: cube file
500 4 : CALL print_iao_cubes(qs_env, iao_cubes_section, iao_coef, ref_basis_set_list)
501 : END IF
502 : !
503 : ! Intrinsic bond orbitals
504 34 : IF (iao_env%do_bondorbitals) THEN
505 32 : IF (unit_nr > 0) THEN
506 16 : WRITE (unit_nr, '(/,T2,A)') 'Intrinsic Bond Orbital Generation'
507 : END IF
508 : ! MOs in IAO basis -> ciao
509 98 : ALLOCATE (ciao(nspin))
510 66 : DO ispin = 1, nspin
511 34 : CALL get_mo_set(my_mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=norb)
512 34 : CALL cp_fm_create(smo, mo_coeff%matrix_struct)
513 34 : NULLIFY (fm_struct)
514 34 : CALL cp_fm_struct_create(fm_struct, nrow_global=nref, template_fmstruct=mo_coeff%matrix_struct)
515 34 : CALL cp_fm_create(ciao(ispin), fm_struct)
516 34 : CALL cp_fm_struct_release(fm_struct)
517 : ! CIAO = A(T)*S*C
518 34 : CALL cp_dbcsr_sm_fm_multiply(smat, mo_coeff, smo, ncol=norb)
519 34 : CALL parallel_gemm('T', 'N', nref, norb, nao, 1.0_dp, iao_coef(ispin), smo, 0.0_dp, ciao(ispin))
520 100 : CALL cp_fm_release(smo)
521 : END DO
522 : !
523 : ! localize occupied orbitals nocc(ispin), see IAO generation
524 : !
525 164 : ALLOCATE (cloc(nspin), c_loc_orb(nspin))
526 66 : DO ispin = 1, nspin
527 34 : NULLIFY (fm_struct)
528 : CALL cp_fm_struct_create(fm_struct, ncol_global=nocc(ispin), &
529 34 : template_fmstruct=ciao(ispin)%matrix_struct)
530 34 : CALL cp_fm_create(cloc(ispin), fm_struct)
531 34 : CALL cp_fm_struct_release(fm_struct)
532 66 : CALL cp_fm_to_fm(ciao(ispin), cloc(ispin), ncol=nocc(ispin))
533 : END DO
534 32 : CALL cp_fm_release(ciao)
535 32 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, natom=natom)
536 160 : ALLOCATE (first_sgf(natom), last_sgf(natom), nsgfat(natom))
537 32 : CALL get_ks_env(ks_env=ks_env, particle_set=particle_set)
538 : CALL get_particle_set(particle_set, qs_kind_set, first_sgf=first_sgf, last_sgf=last_sgf, &
539 32 : nsgf=nsgfat, basis=ref_basis_set_list)
540 :
541 32 : IF (iao_env%loc_operator /= do_iaoloc_pm2) THEN
542 0 : CPABORT("IAO localization operator NYA")
543 : END IF
544 32 : IF (iao_env%eloc_function /= do_iaoloc_enone) THEN
545 0 : CPABORT("IAO energy weight localization NYA")
546 : END IF
547 :
548 66 : DO ispin = 1, nspin
549 34 : nvec = nocc(ispin)
550 66 : IF (nvec > 0) THEN
551 326 : ALLOCATE (zij_atom(natom, 1), fdiag(nvec))
552 34 : NULLIFY (fm_struct)
553 : CALL cp_fm_struct_create(fm_struct, nrow_global=nvec, ncol_global=nvec, &
554 34 : template_fmstruct=cloc(ispin)%matrix_struct)
555 156 : DO iatom = 1, natom
556 122 : CALL cp_fm_create(zij_atom(iatom, 1), fm_struct)
557 122 : isgf = first_sgf(iatom)
558 : CALL parallel_gemm('T', 'N', nvec, nvec, nsgfat(iatom), 1.0_dp, cloc(ispin), cloc(ispin), &
559 : 0.0_dp, zij_atom(iatom, 1), &
560 156 : a_first_col=1, a_first_row=isgf, b_first_col=1, b_first_row=isgf)
561 : END DO
562 34 : CALL cp_fm_struct_release(fm_struct)
563 : !
564 34 : t1 = m_walltime()
565 34 : order = 4
566 34 : fin = 0.0_dp
567 156 : DO iatom = 1, natom
568 122 : CALL cp_fm_get_diag(zij_atom(iatom, 1), fdiag)
569 1028 : fin = fin + SUM(fdiag**order)
570 : END DO
571 34 : fin = fin**(1._dp/order)
572 : ! QR localization
573 34 : CALL scdm_qrfact(cloc(ispin))
574 : !
575 156 : DO iatom = 1, natom
576 122 : isgf = first_sgf(iatom)
577 : CALL parallel_gemm('T', 'N', nvec, nvec, nsgfat(iatom), 1.0_dp, cloc(ispin), cloc(ispin), &
578 : 0.0_dp, zij_atom(iatom, 1), &
579 156 : a_first_col=1, a_first_row=isgf, b_first_col=1, b_first_row=isgf)
580 : END DO
581 34 : fout = 0.0_dp
582 156 : DO iatom = 1, natom
583 122 : CALL cp_fm_get_diag(zij_atom(iatom, 1), fdiag)
584 1028 : fout = fout + SUM(fdiag**order)
585 : END DO
586 34 : fout = fout**(1._dp/order)
587 34 : DEALLOCATE (fdiag)
588 34 : t2 = m_walltime()
589 34 : IF (unit_nr > 0) THEN
590 : WRITE (unit_nr, '(T2,A,F14.8,A,F14.8,A,F8.2)') &
591 17 : 'SCDM pre-localization: fin=', fin, " fout=", fout, " Time=", t2 - t1
592 : END IF
593 : !
594 34 : CALL pm_localization(zij_atom, cloc(ispin), order, 1.E-12_dp, unit_nr)
595 : !
596 34 : CALL cp_fm_release(zij_atom)
597 34 : CALL get_mo_set(my_mos(ispin), nao=nao)
598 34 : NULLIFY (fm_struct)
599 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, &
600 34 : template_fmstruct=cloc(ispin)%matrix_struct)
601 34 : CALL cp_fm_create(c_loc_orb(ispin), fm_struct)
602 34 : CALL cp_fm_struct_release(fm_struct)
603 : CALL parallel_gemm('N', 'N', nao, nvec, nref, 1.0_dp, iao_coef(ispin), cloc(ispin), &
604 68 : 0.0_dp, c_loc_orb(ispin))
605 : END IF
606 : END DO
607 32 : DEALLOCATE (first_sgf, last_sgf, nsgfat)
608 32 : CALL cp_fm_release(cloc)
609 : !
610 32 : IF (iao_env%do_center) THEN
611 32 : IF (unit_nr > 0) THEN
612 16 : WRITE (unit_nr, '(T2,A)') ' Calculate Localized Orbital Centers and Spread'
613 16 : IF (iao_env%pos_periodic) THEN
614 13 : WRITE (unit_nr, '(T2,A)') ' Use Berry Phase Position Operator'
615 : ELSE
616 3 : WRITE (unit_nr, '(T2,A)') ' Use Local Position Operator'
617 : END IF
618 : END IF
619 96 : nvec = MAXVAL(nocc)
620 : ! x y z m2(1) m2(2)
621 128 : ALLOCATE (moments(5, nvec, nspin))
622 1230 : moments = 0.0_dp
623 32 : IF (iao_env%pos_periodic) THEN
624 26 : CALL center_spread_berry(qs_env, c_loc_orb, moments)
625 : ELSE
626 6 : CALL center_spread_loc(qs_env, c_loc_orb, moments)
627 : END IF
628 : !
629 32 : IF (ASSOCIATED(ibo_cc_section)) THEN
630 4 : CALL print_center_spread(moments, nocc, ibo_cc_section)
631 : END IF
632 : !
633 32 : IF (PRESENT(bond_centers)) THEN
634 28 : nx = SIZE(bond_centers, 1)
635 28 : no = SIZE(bond_centers, 2)
636 28 : ns = SIZE(bond_centers, 3)
637 28 : CPASSERT(no >= nvec)
638 28 : CPASSERT(ns == nspin)
639 28 : CPASSERT(nx >= 3)
640 28 : nx = MIN(nx, 5)
641 1054 : bond_centers(1:nx, 1:nvec, 1:ns) = moments(1:nx, 1:nvec, 1:ns)
642 : END IF
643 32 : DEALLOCATE (moments)
644 : END IF
645 : !
646 32 : IF (molden_ibo) THEN
647 4 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set)
648 4 : CALL get_ks_env(ks_env=ks_env, particle_set=particle_set)
649 4 : IF (unit_nr > 0) THEN
650 2 : WRITE (unit_nr, '(T2,A)') ' Write IBO in MOLDEN Format'
651 : END IF
652 16 : ALLOCATE (mo_loc(nspin))
653 8 : DO ispin = 1, nspin
654 4 : CALL get_mo_set(my_mos(ispin), nao=nao)
655 4 : nvec = nocc(ispin)
656 4 : CALL allocate_mo_set(mo_loc(ispin), nao, nvec, nvec, 0.0_dp, 1.0_dp, 0.0_dp)
657 4 : CALL init_mo_set(mo_loc(ispin), fm_ref=c_loc_orb(ispin), name="ibo_orb")
658 4 : CALL cp_fm_to_fm(c_loc_orb(ispin), mo_loc(ispin)%mo_coeff)
659 4 : CALL set_mo_set(mo_loc(ispin), homo=nvec)
660 40 : mo_loc(ispin)%occupation_numbers = 1.0_dp
661 : END DO
662 : ! Print IBO functions: molden format
663 4 : CALL write_mos_molden(mo_loc, qs_kind_set, particle_set, ibo_molden_section)
664 8 : DO ispin = 1, nspin
665 8 : CALL deallocate_mo_set(mo_loc(ispin))
666 : END DO
667 4 : DEALLOCATE (mo_loc)
668 : END IF
669 : !
670 32 : IF (cubes_ibo) THEN
671 4 : IF (unit_nr > 0) THEN
672 2 : WRITE (unit_nr, '(T2,A)') ' Write IBO on CUBE files'
673 : END IF
674 : ! Print localized orbital functions: cube file
675 4 : CALL print_ibo_cubes(qs_env, ibo_cubes_section, c_loc_orb)
676 : END IF
677 : !
678 32 : IF (PRESENT(mos) .AND. ALLOCATED(c_loc_orb)) THEN
679 : ! c_loc_orb -> mos
680 58 : DO ispin = 1, nspin
681 30 : CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff)
682 30 : nvec = nocc(ispin)
683 58 : CALL cp_fm_to_fm(c_loc_orb(ispin), mo_coeff, ncol=nvec)
684 : END DO
685 : END IF
686 32 : CALL cp_fm_release(c_loc_orb)
687 : END IF
688 34 : DEALLOCATE (ref_basis_set_list)
689 :
690 34 : IF (PRESENT(c_iao_coef)) THEN
691 30 : CALL cp_fm_release(c_iao_coef)
692 92 : ALLOCATE (c_iao_coef(nspin))
693 62 : DO ispin = 1, nspin
694 32 : CALL cp_fm_create(c_iao_coef(ispin), iao_coef(ispin)%matrix_struct)
695 62 : CALL cp_fm_to_fm(iao_coef(ispin), c_iao_coef(ispin))
696 : END DO
697 : END IF
698 34 : CALL cp_fm_release(iao_coef)
699 :
700 34 : IF (unit_nr > 0) THEN
701 : WRITE (unit_nr, '(T2,A)') &
702 17 : '!----------------------------END OF IAO ANALYSIS------------------------------!'
703 : END IF
704 :
705 34 : CALL timestop(handle)
706 :
707 204 : END SUBROUTINE iao_wfn_analysis
708 :
709 : ! **************************************************************************************************
710 : !> \brief Computes projector matrices for ref to orb basis and reverse
711 : !> \param smat ...
712 : !> \param sref ...
713 : !> \param s_r_o ...
714 : !> \param p_o_r ...
715 : !> \param p_r_o ...
716 : !> \param eps_svd ...
717 : ! **************************************************************************************************
718 238 : SUBROUTINE iao_projectors(smat, sref, s_r_o, p_o_r, p_r_o, eps_svd)
719 : TYPE(dbcsr_type), INTENT(INOUT) :: smat, sref, s_r_o
720 : TYPE(cp_fm_type), INTENT(INOUT) :: p_o_r, p_r_o
721 : REAL(KIND=dp), INTENT(IN) :: eps_svd
722 :
723 : CHARACTER(len=*), PARAMETER :: routineN = 'iao_projectors'
724 :
725 : INTEGER :: handle, norb, nref
726 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
727 : TYPE(cp_fm_type) :: fm_inv, fm_s, fm_sro
728 :
729 34 : CALL timeset(routineN, handle)
730 :
731 34 : CALL cp_fm_get_info(p_r_o, nrow_global=nref, ncol_global=norb)
732 34 : CALL cp_fm_create(fm_sro, p_r_o%matrix_struct)
733 34 : CALL copy_dbcsr_to_fm(s_r_o, fm_sro)
734 :
735 34 : NULLIFY (fm_struct)
736 : CALL cp_fm_struct_create(fm_struct, nrow_global=norb, ncol_global=norb, &
737 34 : template_fmstruct=p_r_o%matrix_struct)
738 34 : CALL cp_fm_create(fm_s, fm_struct, name="smat")
739 34 : CALL cp_fm_create(fm_inv, fm_struct, name="sinv")
740 34 : CALL cp_fm_struct_release(fm_struct)
741 34 : CALL copy_dbcsr_to_fm(smat, fm_s)
742 34 : CALL cp_fm_invert(fm_s, fm_inv, eps_svd=eps_svd)
743 34 : CALL parallel_gemm('N', 'T', norb, nref, norb, 1.0_dp, fm_inv, fm_sro, 0.0_dp, p_o_r)
744 34 : CALL cp_fm_release(fm_s)
745 34 : CALL cp_fm_release(fm_inv)
746 :
747 34 : NULLIFY (fm_struct)
748 : CALL cp_fm_struct_create(fm_struct, nrow_global=nref, ncol_global=nref, &
749 34 : template_fmstruct=p_r_o%matrix_struct)
750 34 : CALL cp_fm_create(fm_s, fm_struct, name="sref")
751 34 : CALL cp_fm_create(fm_inv, fm_struct, name="sinv")
752 34 : CALL cp_fm_struct_release(fm_struct)
753 34 : CALL copy_dbcsr_to_fm(sref, fm_s)
754 34 : CALL cp_fm_invert(fm_s, fm_inv, eps_svd=eps_svd)
755 34 : CALL parallel_gemm('N', 'N', nref, norb, nref, 1.0_dp, fm_inv, fm_sro, 0.0_dp, p_r_o)
756 34 : CALL cp_fm_release(fm_s)
757 34 : CALL cp_fm_release(fm_inv)
758 :
759 34 : CALL cp_fm_release(fm_sro)
760 :
761 34 : CALL timestop(handle)
762 :
763 34 : END SUBROUTINE iao_projectors
764 :
765 : ! **************************************************************************************************
766 : !> \brief Computes intrinsic orbitals for a given MO vector set
767 : !> \param smat ...
768 : !> \param p_o_r ...
769 : !> \param p_r_o ...
770 : !> \param cvec ...
771 : !> \param avec ...
772 : ! **************************************************************************************************
773 324 : SUBROUTINE intrinsic_ao_calc(smat, p_o_r, p_r_o, cvec, avec)
774 : TYPE(dbcsr_type), INTENT(INOUT) :: smat
775 : TYPE(cp_fm_type), INTENT(INOUT) :: p_o_r, p_r_o, cvec, avec
776 :
777 : CHARACTER(len=*), PARAMETER :: routineN = 'intrinsic_ao_calc'
778 :
779 : INTEGER :: handle, nao, norb, nref
780 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
781 : TYPE(cp_fm_type) :: ctvec, pc, sc, sct, vec1
782 :
783 36 : CALL timeset(routineN, handle)
784 :
785 : ! number of orbitals
786 36 : CALL cp_fm_get_info(cvec, ncol_global=norb)
787 : ! basis set sizes
788 36 : CALL cp_fm_get_info(p_r_o, nrow_global=nref, ncol_global=nao)
789 : ! temp array
790 36 : NULLIFY (fm_struct)
791 : CALL cp_fm_struct_create(fm_struct, nrow_global=nref, ncol_global=norb, &
792 36 : template_fmstruct=cvec%matrix_struct)
793 36 : CALL cp_fm_create(pc, fm_struct)
794 36 : CALL cp_fm_struct_release(fm_struct)
795 : ! CT = orth(Por.Pro.C)
796 36 : CALL parallel_gemm('N', 'N', nref, norb, nao, 1.0_dp, p_r_o, cvec, 0.0_dp, pc)
797 36 : CALL cp_fm_create(ctvec, cvec%matrix_struct)
798 36 : CALL parallel_gemm('N', 'N', nao, norb, nref, 1.0_dp, p_o_r, pc, 0.0_dp, ctvec)
799 36 : CALL cp_fm_release(pc)
800 36 : CALL make_basis_lowdin(ctvec, norb, smat)
801 : ! S*C and S*CT
802 36 : CALL cp_fm_create(sc, cvec%matrix_struct)
803 36 : CALL cp_dbcsr_sm_fm_multiply(smat, cvec, sc, ncol=norb)
804 36 : CALL cp_fm_create(sct, cvec%matrix_struct)
805 36 : CALL cp_dbcsr_sm_fm_multiply(smat, ctvec, sct, ncol=norb)
806 : CALL cp_fm_struct_create(fm_struct, nrow_global=norb, ncol_global=nref, &
807 36 : template_fmstruct=cvec%matrix_struct)
808 36 : CALL cp_fm_create(pc, fm_struct)
809 36 : CALL cp_fm_struct_release(fm_struct)
810 : ! V1 = (CT*SCT(T))Por
811 36 : CALL parallel_gemm('T', 'N', norb, nref, nao, 1.0_dp, sct, p_o_r, 0.0_dp, pc)
812 36 : NULLIFY (fm_struct)
813 : CALL cp_fm_struct_create(fm_struct, nrow_global=nao, ncol_global=nref, &
814 36 : template_fmstruct=cvec%matrix_struct)
815 36 : CALL cp_fm_create(vec1, fm_struct)
816 36 : CALL cp_fm_struct_release(fm_struct)
817 36 : CALL parallel_gemm('N', 'N', nao, nref, norb, 1.0_dp, ctvec, pc, 0.0_dp, vec1)
818 : ! A = C*SC(T)*V1
819 36 : CALL parallel_gemm('T', 'N', norb, nref, nao, 1.0_dp, sc, vec1, 0.0_dp, pc)
820 36 : CALL parallel_gemm('N', 'N', nao, nref, norb, 1.0_dp, cvec, pc, 0.0_dp, avec)
821 : ! V1 = Por - V1
822 36 : CALL cp_fm_geadd(1.0_dp, 'N', p_o_r, -1.0_dp, vec1)
823 : ! A = A + V1
824 36 : CALL cp_fm_geadd(1.0_dp, 'N', vec1, 1.0_dp, avec)
825 : ! A = A - C*SC(T)*V1
826 36 : CALL parallel_gemm('T', 'N', norb, nref, nao, 1.0_dp, sc, vec1, 0.0_dp, pc)
827 36 : CALL parallel_gemm('N', 'N', nao, nref, norb, -1.0_dp, cvec, pc, 1.0_dp, avec)
828 : ! A = orth(A)
829 36 : CALL make_basis_lowdin(avec, nref, smat)
830 :
831 : ! clean up
832 36 : CALL cp_fm_release(pc)
833 36 : CALL cp_fm_release(vec1)
834 36 : CALL cp_fm_release(sc)
835 36 : CALL cp_fm_release(sct)
836 36 : CALL cp_fm_release(ctvec)
837 :
838 36 : CALL timestop(handle)
839 :
840 36 : END SUBROUTINE intrinsic_ao_calc
841 :
842 : ! **************************************************************************************************
843 : !> \brief Calculate the density matrix from fm vectors using occupation numbers
844 : !> \param cvec ...
845 : !> \param density_matrix ...
846 : !> \param occupation ...
847 : !> \param uniform_occupation ...
848 : ! **************************************************************************************************
849 132 : SUBROUTINE iao_calculate_dmat_diag(cvec, density_matrix, occupation, uniform_occupation)
850 :
851 : TYPE(cp_fm_type), INTENT(IN) :: cvec
852 : TYPE(dbcsr_type) :: density_matrix
853 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: occupation
854 : LOGICAL, INTENT(IN) :: uniform_occupation
855 :
856 : CHARACTER(len=*), PARAMETER :: routineN = 'iao_calculate_dmat_diag'
857 :
858 : INTEGER :: handle, ncol
859 : REAL(KIND=dp) :: alpha
860 : TYPE(cp_fm_type) :: fm_tmp
861 :
862 132 : CALL timeset(routineN, handle)
863 :
864 132 : CALL dbcsr_set(density_matrix, 0.0_dp)
865 :
866 132 : CALL cp_fm_get_info(cvec, ncol_global=ncol)
867 132 : IF (.NOT. uniform_occupation) THEN
868 98 : CALL cp_fm_create(fm_tmp, cvec%matrix_struct)
869 98 : CALL cp_fm_to_fm(cvec, fm_tmp)
870 98 : CALL cp_fm_column_scale(fm_tmp, occupation(1:ncol))
871 98 : alpha = 1.0_dp
872 : CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
873 : matrix_v=cvec, matrix_g=fm_tmp, &
874 98 : ncol=ncol, alpha=alpha)
875 98 : CALL cp_fm_release(fm_tmp)
876 : ELSE
877 34 : alpha = occupation(1)
878 : CALL cp_dbcsr_plus_fm_fm_t(sparse_matrix=density_matrix, &
879 34 : matrix_v=cvec, ncol=ncol, alpha=alpha)
880 : END IF
881 :
882 132 : CALL timestop(handle)
883 :
884 132 : END SUBROUTINE iao_calculate_dmat_diag
885 :
886 : ! **************************************************************************************************
887 : !> \brief Calculate the density matrix from fm vectors using an occupation matrix
888 : !> \param cvec ...
889 : !> \param density_matrix ...
890 : !> \param weight ...
891 : !> \param occmat ...
892 : ! **************************************************************************************************
893 16 : SUBROUTINE iao_calculate_dmat_full(cvec, density_matrix, weight, occmat)
894 :
895 : TYPE(cp_fm_type), INTENT(IN) :: cvec
896 : TYPE(dbcsr_type) :: density_matrix
897 : REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: weight
898 : TYPE(cp_fm_type), INTENT(IN) :: occmat
899 :
900 : CHARACTER(len=*), PARAMETER :: routineN = 'iao_calculate_dmat_full'
901 :
902 : INTEGER :: handle, ic, jc, ncol
903 : REAL(KIND=dp) :: alpha
904 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
905 : TYPE(cp_fm_type) :: fm1, fm2
906 :
907 16 : CALL timeset(routineN, handle)
908 :
909 16 : CALL dbcsr_set(density_matrix, 0.0_dp)
910 :
911 : CALL cp_fm_struct_create(fm_struct, ncol_global=1, &
912 16 : template_fmstruct=cvec%matrix_struct)
913 16 : CALL cp_fm_create(fm1, fm_struct)
914 16 : CALL cp_fm_create(fm2, fm_struct)
915 16 : CALL cp_fm_struct_release(fm_struct)
916 :
917 16 : CALL cp_fm_get_info(cvec, ncol_global=ncol)
918 432 : DO ic = 1, ncol
919 416 : CALL cp_fm_to_fm(cvec, fm1, ncol=1, source_start=ic, target_start=1)
920 11248 : DO jc = 1, ncol
921 10816 : CALL cp_fm_to_fm(cvec, fm2, ncol=1, source_start=jc, target_start=1)
922 10816 : CALL cp_fm_get_element(occmat, ic, jc, alpha)
923 10816 : alpha = weight(ic)*alpha
924 : CALL cp_dbcsr_plus_fm_fm_t(density_matrix, fm1, fm2, ncol=1, &
925 11232 : alpha=alpha, symmetry_mode=1)
926 : END DO
927 : END DO
928 16 : CALL cp_fm_release(fm1)
929 16 : CALL cp_fm_release(fm2)
930 :
931 16 : CALL timestop(handle)
932 :
933 16 : END SUBROUTINE iao_calculate_dmat_full
934 :
935 : ! **************************************************************************************************
936 : !> \brief compute the atomic charges (orthogonal basis)
937 : !> \param p_matrix ...
938 : !> \param charges ...
939 : ! **************************************************************************************************
940 208 : SUBROUTINE iao_charges(p_matrix, charges)
941 : TYPE(dbcsr_type) :: p_matrix
942 : REAL(KIND=dp), DIMENSION(:) :: charges
943 :
944 : INTEGER :: i, iblock_col, iblock_row
945 : REAL(kind=dp) :: trace
946 208 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: p_block
947 : TYPE(dbcsr_iterator_type) :: iter
948 : TYPE(mp_comm_type) :: group
949 :
950 1120 : charges = 0.0_dp
951 :
952 208 : CALL dbcsr_iterator_start(iter, p_matrix)
953 664 : DO WHILE (dbcsr_iterator_blocks_left(iter))
954 456 : NULLIFY (p_block)
955 456 : CALL dbcsr_iterator_next_block(iter, iblock_row, iblock_col, p_block)
956 456 : CPASSERT(iblock_row == iblock_col)
957 456 : trace = 0.0_dp
958 1758 : DO i = 1, SIZE(p_block, 1)
959 1758 : trace = trace + p_block(i, i)
960 : END DO
961 456 : charges(iblock_row) = trace
962 : END DO
963 208 : CALL dbcsr_iterator_stop(iter)
964 :
965 208 : CALL dbcsr_get_info(p_matrix, group=group)
966 2032 : CALL group%sum(charges)
967 :
968 208 : END SUBROUTINE iao_charges
969 :
970 : ! **************************************************************************************************
971 : !> \brief Computes and prints the Cube Files for the intrinsic atomic orbitals
972 : !> \param qs_env ...
973 : !> \param print_section ...
974 : !> \param iao_coef ...
975 : !> \param basis_set_list ...
976 : ! **************************************************************************************************
977 4 : SUBROUTINE print_iao_cubes(qs_env, print_section, iao_coef, basis_set_list)
978 : TYPE(qs_environment_type), POINTER :: qs_env
979 : TYPE(section_vals_type), POINTER :: print_section
980 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: iao_coef
981 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
982 :
983 : CHARACTER(LEN=default_path_length) :: filename, title
984 : INTEGER :: i, i_rep, ispin, ivec, iw, j, n_rep, &
985 : nat, natom, norb, nspins, nstart
986 4 : INTEGER, DIMENSION(:), POINTER :: atom_list, blk_sizes, first_bas, stride
987 : LOGICAL :: mpi_io
988 4 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
989 : TYPE(cell_type), POINTER :: cell
990 : TYPE(cp_logger_type), POINTER :: logger
991 : TYPE(dft_control_type), POINTER :: dft_control
992 : TYPE(particle_list_type), POINTER :: particles
993 4 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
994 : TYPE(pw_c1d_gs_type) :: wf_g
995 : TYPE(pw_env_type), POINTER :: pw_env
996 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
997 : TYPE(pw_r3d_rs_type) :: wf_r
998 4 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
999 : TYPE(qs_subsys_type), POINTER :: subsys
1000 :
1001 8 : logger => cp_get_default_logger()
1002 4 : stride => section_get_ivals(print_section, "STRIDE")
1003 4 : CALL section_vals_val_get(print_section, "ATOM_LIST", n_rep_val=n_rep)
1004 :
1005 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
1006 4 : subsys=subsys, cell=cell, particle_set=particle_set, pw_env=pw_env, dft_control=dft_control)
1007 4 : CALL qs_subsys_get(subsys, particles=particles)
1008 :
1009 4 : CALL get_qs_env(qs_env=qs_env, natom=natom)
1010 20 : ALLOCATE (blk_sizes(natom), first_bas(0:natom))
1011 4 : CALL get_particle_set(particle_set, qs_kind_set, nsgf=blk_sizes, basis=basis_set_list)
1012 4 : first_bas(0) = 0
1013 20 : DO i = 1, natom
1014 20 : first_bas(i) = first_bas(i - 1) + blk_sizes(i)
1015 : END DO
1016 :
1017 4 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1018 4 : CALL auxbas_pw_pool%create_pw(wf_r)
1019 4 : CALL auxbas_pw_pool%create_pw(wf_g)
1020 :
1021 4 : nspins = SIZE(iao_coef)
1022 4 : nstart = MIN(1, n_rep)
1023 :
1024 8 : DO ispin = 1, nspins
1025 12 : DO i_rep = nstart, n_rep
1026 4 : CALL cp_fm_get_info(iao_coef(ispin), ncol_global=norb)
1027 4 : IF (i_rep == 0) THEN
1028 0 : nat = natom
1029 : ELSE
1030 4 : CALL section_vals_val_get(print_section, "ATOM_LIST", i_rep_val=i_rep, i_vals=atom_list)
1031 4 : nat = SIZE(atom_list)
1032 : END IF
1033 20 : DO i = 1, nat
1034 8 : IF (i_rep == 0) THEN
1035 0 : j = i
1036 : ELSE
1037 8 : j = atom_list(i)
1038 : END IF
1039 8 : CPASSERT(j >= 1 .AND. j <= natom)
1040 34 : DO ivec = first_bas(j - 1) + 1, first_bas(j)
1041 22 : WRITE (filename, '(a4,I5.5,a1,I1.1)') "IAO_", ivec, "_", ispin
1042 22 : WRITE (title, *) "Intrinsic Atomic Orbitals ", ivec, " atom ", j, " spin ", ispin
1043 22 : mpi_io = .TRUE.
1044 : iw = cp_print_key_unit_nr(logger, print_section, "", extension=".cube", &
1045 : middle_name=TRIM(filename), file_position="REWIND", log_filename=.FALSE., &
1046 22 : mpi_io=mpi_io)
1047 : CALL calculate_wavefunction(iao_coef(ispin), ivec, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
1048 22 : cell, dft_control, particle_set, pw_env)
1049 22 : CALL cp_pw_to_cube(wf_r, iw, title, particles=particles, stride=stride, mpi_io=mpi_io)
1050 30 : CALL cp_print_key_finished_output(iw, logger, print_section, "", mpi_io=mpi_io)
1051 : END DO
1052 : END DO
1053 : END DO
1054 : END DO
1055 4 : DEALLOCATE (blk_sizes, first_bas)
1056 4 : CALL auxbas_pw_pool%give_back_pw(wf_r)
1057 4 : CALL auxbas_pw_pool%give_back_pw(wf_g)
1058 :
1059 8 : END SUBROUTINE print_iao_cubes
1060 :
1061 : ! **************************************************************************************************
1062 : !> \brief Computes and prints the Cube Files for the intrinsic bond orbitals
1063 : !> \param qs_env ...
1064 : !> \param print_section ...
1065 : !> \param ibo_coef ...
1066 : ! **************************************************************************************************
1067 4 : SUBROUTINE print_ibo_cubes(qs_env, print_section, ibo_coef)
1068 : TYPE(qs_environment_type), POINTER :: qs_env
1069 : TYPE(section_vals_type), POINTER :: print_section
1070 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: ibo_coef
1071 :
1072 : CHARACTER(LEN=default_path_length) :: filename, title
1073 : INTEGER :: i, i_rep, ispin, iw, j, n_rep, norb, &
1074 : nspins, nstart, nstate
1075 4 : INTEGER, DIMENSION(:), POINTER :: state_list, stride
1076 : LOGICAL :: mpi_io
1077 4 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1078 : TYPE(cell_type), POINTER :: cell
1079 : TYPE(cp_logger_type), POINTER :: logger
1080 : TYPE(dft_control_type), POINTER :: dft_control
1081 : TYPE(particle_list_type), POINTER :: particles
1082 4 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1083 : TYPE(pw_c1d_gs_type) :: wf_g
1084 : TYPE(pw_env_type), POINTER :: pw_env
1085 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1086 : TYPE(pw_r3d_rs_type) :: wf_r
1087 4 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1088 : TYPE(qs_subsys_type), POINTER :: subsys
1089 :
1090 0 : CPASSERT(ASSOCIATED(print_section))
1091 :
1092 4 : logger => cp_get_default_logger()
1093 4 : stride => section_get_ivals(print_section, "STRIDE")
1094 4 : CALL section_vals_val_get(print_section, "STATE_LIST", n_rep_val=n_rep)
1095 :
1096 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, qs_kind_set=qs_kind_set, &
1097 4 : subsys=subsys, cell=cell, particle_set=particle_set, pw_env=pw_env, dft_control=dft_control)
1098 4 : CALL qs_subsys_get(subsys, particles=particles)
1099 :
1100 4 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1101 4 : CALL auxbas_pw_pool%create_pw(wf_r)
1102 4 : CALL auxbas_pw_pool%create_pw(wf_g)
1103 :
1104 4 : nspins = SIZE(ibo_coef)
1105 4 : nstart = MIN(1, n_rep)
1106 :
1107 8 : DO ispin = 1, nspins
1108 12 : DO i_rep = nstart, n_rep
1109 4 : CALL cp_fm_get_info(ibo_coef(ispin), ncol_global=norb)
1110 4 : IF (i_rep == 0) THEN
1111 0 : nstate = norb
1112 : ELSE
1113 4 : CALL section_vals_val_get(print_section, "STATE_LIST", i_rep_val=i_rep, i_vals=state_list)
1114 4 : nstate = SIZE(state_list)
1115 : END IF
1116 16 : DO i = 1, nstate
1117 4 : IF (i_rep == 0) THEN
1118 0 : j = i
1119 : ELSE
1120 4 : j = state_list(i)
1121 : END IF
1122 4 : CPASSERT(j >= 1 .AND. j <= norb)
1123 4 : WRITE (filename, '(a4,I5.5,a1,I1.1)') "IBO_", j, "_", ispin
1124 4 : WRITE (title, *) "Intrinsic Atomic Orbitals ", j, " spin ", ispin
1125 4 : mpi_io = .TRUE.
1126 : iw = cp_print_key_unit_nr(logger, print_section, "", extension=".cube", &
1127 : middle_name=TRIM(filename), file_position="REWIND", log_filename=.FALSE., &
1128 4 : mpi_io=mpi_io)
1129 : CALL calculate_wavefunction(ibo_coef(ispin), j, wf_r, wf_g, atomic_kind_set, qs_kind_set, &
1130 4 : cell, dft_control, particle_set, pw_env)
1131 4 : CALL cp_pw_to_cube(wf_r, iw, title, particles=particles, stride=stride, mpi_io=mpi_io)
1132 8 : CALL cp_print_key_finished_output(iw, logger, print_section, "", mpi_io=mpi_io)
1133 : END DO
1134 : END DO
1135 : END DO
1136 :
1137 4 : CALL auxbas_pw_pool%give_back_pw(wf_r)
1138 4 : CALL auxbas_pw_pool%give_back_pw(wf_g)
1139 :
1140 4 : END SUBROUTINE print_ibo_cubes
1141 :
1142 : ! **************************************************************************************************
1143 : !> \brief prints charge center and spreads for all orbitals
1144 : !> \param moments ...
1145 : !> \param nocc ...
1146 : !> \param print_section ...
1147 : !> \param iounit ...
1148 : ! **************************************************************************************************
1149 32 : SUBROUTINE print_center_spread(moments, nocc, print_section, iounit)
1150 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(IN) :: moments
1151 : INTEGER, DIMENSION(:), INTENT(IN) :: nocc
1152 : TYPE(section_vals_type), OPTIONAL, POINTER :: print_section
1153 : INTEGER, INTENT(IN), OPTIONAL :: iounit
1154 :
1155 : CHARACTER(LEN=default_path_length) :: filename
1156 : INTEGER :: is, ispin, iw, nspin
1157 : TYPE(cp_logger_type), POINTER :: logger
1158 :
1159 32 : logger => cp_get_default_logger()
1160 32 : nspin = SIZE(moments, 3)
1161 :
1162 32 : IF (PRESENT(print_section)) THEN
1163 4 : WRITE (filename, '(A18,I1.1)') "IBO_CENTERS_SPREAD"
1164 : iw = cp_print_key_unit_nr(logger, print_section, "", extension=".csp", &
1165 4 : middle_name=TRIM(filename), file_position="REWIND", log_filename=.FALSE.)
1166 28 : ELSEIF (PRESENT(iounit)) THEN
1167 28 : iw = iounit
1168 : ELSE
1169 0 : iw = -1
1170 : END IF
1171 32 : IF (iw > 0) THEN
1172 33 : DO ispin = 1, nspin
1173 17 : WRITE (iw, "(T2,A,i1)") "Intrinsic Bond Orbitals: Centers and Spread for Spin ", ispin
1174 17 : WRITE (iw, "(A7,T30,A6,T68,A7)") "State", "Center", "Spreads"
1175 133 : DO is = 1, nocc(ispin)
1176 117 : WRITE (iw, "(i7,3F15.8,8X,2F10.5)") is, moments(:, is, ispin)
1177 : END DO
1178 : END DO
1179 : END IF
1180 32 : IF (PRESENT(print_section)) THEN
1181 4 : CALL cp_print_key_finished_output(iw, logger, print_section, "")
1182 : END IF
1183 :
1184 32 : END SUBROUTINE print_center_spread
1185 :
1186 : ! **************************************************************************************************
1187 : !> \brief ...
1188 : !> \param qs_env ...
1189 : !> \param c_loc_orb ...
1190 : !> \param moments ...
1191 : ! **************************************************************************************************
1192 6 : SUBROUTINE center_spread_loc(qs_env, c_loc_orb, moments)
1193 : TYPE(qs_environment_type), POINTER :: qs_env
1194 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: c_loc_orb
1195 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: moments
1196 :
1197 : CHARACTER(len=*), PARAMETER :: routineN = 'center_spread_loc'
1198 : INTEGER, DIMENSION(6), PARAMETER :: list = (/1, 2, 3, 4, 7, 9/)
1199 :
1200 : INTEGER :: handle, i, iop, iorb, ispin, nao, norb, &
1201 : nspin
1202 : REAL(KIND=dp) :: xmii
1203 : REAL(KIND=dp), DIMENSION(3) :: rpoint
1204 : TYPE(cell_type), POINTER :: cell
1205 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1206 : TYPE(cp_fm_type) :: ccmat, ocvec
1207 6 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: dipmat
1208 6 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s
1209 : TYPE(dbcsr_type), POINTER :: omat, smat
1210 :
1211 6 : CALL timeset(routineN, handle)
1212 :
1213 6 : CALL get_qs_env(qs_env=qs_env, matrix_s_kp=matrix_s)
1214 6 : smat => matrix_s(1, 1)%matrix
1215 6 : rpoint = 0.0_dp
1216 6 : nspin = SIZE(c_loc_orb)
1217 228 : moments = 0.0_dp
1218 :
1219 60 : ALLOCATE (dipmat(9))
1220 60 : DO i = 1, 9
1221 54 : ALLOCATE (dipmat(i)%matrix)
1222 54 : CALL dbcsr_copy(dipmat(i)%matrix, smat)
1223 60 : CALL dbcsr_set(dipmat(i)%matrix, 0.0_dp)
1224 : END DO
1225 :
1226 6 : CALL build_local_moment_matrix(qs_env, dipmat, 2, rpoint)
1227 :
1228 12 : DO ispin = 1, nspin
1229 6 : CALL cp_fm_get_info(c_loc_orb(ispin), nrow_global=nao, ncol_global=norb)
1230 6 : CALL cp_fm_create(ocvec, c_loc_orb(ispin)%matrix_struct)
1231 6 : NULLIFY (fm_struct)
1232 : CALL cp_fm_struct_create(fm_struct, nrow_global=norb, ncol_global=norb, &
1233 6 : template_fmstruct=c_loc_orb(ispin)%matrix_struct)
1234 6 : CALL cp_fm_create(ccmat, fm_struct)
1235 6 : CALL cp_fm_struct_release(fm_struct)
1236 42 : DO i = 1, 6
1237 36 : iop = list(i)
1238 36 : omat => dipmat(iop)%matrix
1239 36 : CALL cp_dbcsr_sm_fm_multiply(omat, c_loc_orb(ispin), ocvec, ncol=norb)
1240 : CALL parallel_gemm('T', 'N', norb, norb, nao, 1.0_dp, c_loc_orb(ispin), ocvec, &
1241 36 : 0.0_dp, ccmat)
1242 258 : DO iorb = 1, norb
1243 216 : CALL cp_fm_get_element(ccmat, iorb, iorb, xmii)
1244 252 : IF (iop <= 3) THEN
1245 108 : moments(iop, iorb, ispin) = moments(iop, iorb, ispin) + xmii
1246 108 : moments(4, iorb, ispin) = moments(4, iorb, ispin) - xmii**2
1247 : ELSE
1248 108 : moments(4, iorb, ispin) = moments(4, iorb, ispin) + xmii
1249 : END IF
1250 : END DO
1251 : END DO
1252 6 : CALL cp_fm_release(ocvec)
1253 24 : CALL cp_fm_release(ccmat)
1254 : END DO
1255 :
1256 60 : DO i = 1, 9
1257 54 : CALL dbcsr_release(dipmat(i)%matrix)
1258 60 : DEALLOCATE (dipmat(i)%matrix)
1259 : END DO
1260 6 : DEALLOCATE (dipmat)
1261 :
1262 6 : CALL get_qs_env(qs_env=qs_env, cell=cell)
1263 12 : DO ispin = 1, nspin
1264 48 : DO iorb = 1, norb
1265 150 : moments(1:3, iorb, ispin) = pbc(moments(1:3, iorb, ispin), cell)
1266 : END DO
1267 : END DO
1268 :
1269 6 : CALL timestop(handle)
1270 :
1271 6 : END SUBROUTINE center_spread_loc
1272 :
1273 : ! **************************************************************************************************
1274 : !> \brief ...
1275 : !> \param qs_env ...
1276 : !> \param c_loc_orb ...
1277 : !> \param moments ...
1278 : ! **************************************************************************************************
1279 26 : SUBROUTINE center_spread_berry(qs_env, c_loc_orb, moments)
1280 : TYPE(qs_environment_type), POINTER :: qs_env
1281 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: c_loc_orb
1282 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: moments
1283 :
1284 : CHARACTER(len=*), PARAMETER :: routineN = 'center_spread_berry'
1285 :
1286 : COMPLEX(KIND=dp) :: z
1287 : INTEGER :: dim_op, handle, i, idir, ispin, istate, &
1288 : j, jdir, nao, norb, nspin
1289 : REAL(dp), DIMENSION(3) :: c, cpbc
1290 : REAL(dp), DIMENSION(6) :: weights
1291 : REAL(KIND=dp) :: imagpart, realpart, spread_i, spread_ii
1292 : TYPE(cell_type), POINTER :: cell
1293 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1294 : TYPE(cp_fm_type) :: opvec
1295 26 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: zij
1296 26 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
1297 26 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: op_sm_set
1298 :
1299 26 : CALL timeset(routineN, handle)
1300 :
1301 26 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, cell=cell)
1302 :
1303 26 : IF (cell%orthorhombic) THEN
1304 26 : dim_op = 3
1305 : ELSE
1306 0 : dim_op = 6
1307 : END IF
1308 312 : ALLOCATE (op_sm_set(2, dim_op))
1309 104 : DO i = 1, dim_op
1310 260 : DO j = 1, 2
1311 156 : NULLIFY (op_sm_set(j, i)%matrix)
1312 156 : ALLOCATE (op_sm_set(j, i)%matrix)
1313 156 : CALL dbcsr_copy(op_sm_set(j, i)%matrix, matrix_s(1)%matrix)
1314 234 : CALL dbcsr_set(op_sm_set(j, i)%matrix, 0.0_dp)
1315 : END DO
1316 : END DO
1317 26 : CALL initialize_weights(cell, weights)
1318 :
1319 26 : CALL compute_berry_operator(qs_env, cell, op_sm_set, dim_op)
1320 :
1321 26 : nspin = SIZE(c_loc_orb, 1)
1322 54 : DO ispin = 1, nspin
1323 28 : CALL cp_fm_get_info(c_loc_orb(ispin), nrow_global=nao, ncol_global=norb)
1324 28 : CALL cp_fm_create(opvec, c_loc_orb(ispin)%matrix_struct)
1325 28 : NULLIFY (fm_struct)
1326 : CALL cp_fm_struct_create(fm_struct, nrow_global=norb, ncol_global=norb, &
1327 28 : template_fmstruct=c_loc_orb(ispin)%matrix_struct)
1328 336 : ALLOCATE (zij(2, dim_op))
1329 :
1330 : ! Compute zij here
1331 112 : DO i = 1, dim_op
1332 280 : DO j = 1, 2
1333 168 : CALL cp_fm_create(zij(j, i), fm_struct)
1334 168 : CALL cp_fm_set_all(zij(j, i), 0.0_dp)
1335 168 : CALL cp_dbcsr_sm_fm_multiply(op_sm_set(j, i)%matrix, c_loc_orb(ispin), opvec, ncol=norb)
1336 252 : CALL parallel_gemm("T", "N", norb, norb, nao, 1.0_dp, c_loc_orb(ispin), opvec, 0.0_dp, zij(j, i))
1337 : END DO
1338 : END DO
1339 :
1340 28 : CALL cp_fm_struct_release(fm_struct)
1341 28 : CALL cp_fm_release(opvec)
1342 :
1343 184 : DO istate = 1, norb
1344 156 : c = 0.0_dp
1345 156 : spread_i = 0.0_dp
1346 156 : spread_ii = 0.0_dp
1347 624 : DO jdir = 1, dim_op
1348 468 : CALL cp_fm_get_element(zij(1, jdir), istate, istate, realpart)
1349 468 : CALL cp_fm_get_element(zij(2, jdir), istate, istate, imagpart)
1350 468 : z = CMPLX(realpart, imagpart, dp)
1351 : spread_i = spread_i - weights(jdir)* &
1352 468 : LOG(realpart*realpart + imagpart*imagpart)/twopi/twopi
1353 : spread_ii = spread_ii + weights(jdir)* &
1354 468 : (1.0_dp - (realpart*realpart + imagpart*imagpart))/twopi/twopi
1355 624 : IF (jdir < 4) THEN
1356 1872 : DO idir = 1, 3
1357 : c(idir) = c(idir) + &
1358 1872 : (cell%hmat(idir, jdir)/twopi)*AIMAG(LOG(z))
1359 : END DO
1360 : END IF
1361 : END DO
1362 156 : cpbc = pbc(c, cell)
1363 624 : moments(1:3, istate, ispin) = cpbc(1:3)
1364 156 : moments(4, istate, ispin) = spread_i
1365 184 : moments(5, istate, ispin) = spread_ii
1366 : END DO
1367 :
1368 82 : CALL cp_fm_release(zij)
1369 :
1370 : END DO
1371 :
1372 104 : DO i = 1, dim_op
1373 260 : DO j = 1, 2
1374 156 : CALL dbcsr_release(op_sm_set(j, i)%matrix)
1375 234 : DEALLOCATE (op_sm_set(j, i)%matrix)
1376 : END DO
1377 : END DO
1378 26 : DEALLOCATE (op_sm_set)
1379 :
1380 26 : CALL timestop(handle)
1381 :
1382 52 : END SUBROUTINE center_spread_berry
1383 :
1384 : ! **************************************************************************************************
1385 : !> \brief ...
1386 : !> \param qs_env ...
1387 : !> \param oce_basis_set_list ...
1388 : !> \param smat_kind ...
1389 : !> \param sxo ...
1390 : !> \param iao_coef ...
1391 : !> \param oce_atom ...
1392 : !> \param unit_nr ...
1393 : ! **************************************************************************************************
1394 4 : SUBROUTINE iao_oce_expansion(qs_env, oce_basis_set_list, smat_kind, sxo, iao_coef, oce_atom, unit_nr)
1395 : TYPE(qs_environment_type), POINTER :: qs_env
1396 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: oce_basis_set_list
1397 : TYPE(cp_2d_r_p_type), DIMENSION(:) :: smat_kind
1398 : TYPE(dbcsr_p_type), DIMENSION(:) :: sxo
1399 : TYPE(cp_fm_type), DIMENSION(:) :: iao_coef
1400 : TYPE(cp_2d_r_p_type), DIMENSION(:, :) :: oce_atom
1401 : INTEGER, INTENT(IN) :: unit_nr
1402 :
1403 : CHARACTER(len=*), PARAMETER :: routineN = 'iao_oce_expansion'
1404 :
1405 : INTEGER :: handle, i, i1, i2, iao, iatom, ikind, &
1406 : iset, ishell, ispin, l, m, maxl, n, &
1407 : natom, nkind, noce, ns, nset, nsgf, &
1408 : nspin
1409 4 : INTEGER, DIMENSION(:), POINTER :: iao_blk_sizes, nshell, oce_blk_sizes, &
1410 4 : orb_blk_sizes
1411 4 : INTEGER, DIMENSION(:, :), POINTER :: first_sgf, last_sgf, lval
1412 : LOGICAL :: found
1413 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: ev, vector
1414 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: amat, bmat, filter, oce_comp, prol, vec
1415 4 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: ablock
1416 4 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:) :: sinv_kind
1417 : TYPE(dbcsr_distribution_type) :: dbcsr_dist
1418 : TYPE(dbcsr_type) :: iao_vec, sx_vec
1419 : TYPE(gto_basis_set_type), POINTER :: oce_basis
1420 : TYPE(mp_comm_type) :: group
1421 4 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1422 4 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1423 : TYPE(qs_ks_env_type), POINTER :: ks_env
1424 :
1425 4 : CALL timeset(routineN, handle)
1426 :
1427 : ! basis sets: block sizes
1428 : CALL dbcsr_get_info(sxo(1)%matrix, row_blk_size=oce_blk_sizes, col_blk_size=orb_blk_sizes, &
1429 4 : distribution=dbcsr_dist)
1430 4 : CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, natom=natom)
1431 4 : CALL get_ks_env(ks_env=ks_env, particle_set=particle_set, qs_kind_set=qs_kind_set)
1432 12 : ALLOCATE (iao_blk_sizes(natom))
1433 20 : DO iatom = 1, natom
1434 16 : CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
1435 16 : CALL get_qs_kind(qs_kind_set(ikind), nsgf=ns, basis_type="MIN")
1436 20 : iao_blk_sizes(iatom) = ns
1437 : END DO
1438 :
1439 : CALL dbcsr_create(iao_vec, name="IAO_VEC", dist=dbcsr_dist, &
1440 : matrix_type=dbcsr_type_no_symmetry, row_blk_size=orb_blk_sizes, &
1441 4 : col_blk_size=iao_blk_sizes)
1442 : CALL dbcsr_create(sx_vec, name="SX_VEC", dist=dbcsr_dist, &
1443 : matrix_type=dbcsr_type_no_symmetry, row_blk_size=oce_blk_sizes, &
1444 4 : col_blk_size=iao_blk_sizes)
1445 4 : CALL dbcsr_reserve_diag_blocks(matrix=sx_vec)
1446 :
1447 4 : nkind = SIZE(smat_kind)
1448 24 : ALLOCATE (sinv_kind(nkind))
1449 16 : DO ikind = 1, nkind
1450 12 : noce = SIZE(smat_kind(ikind)%array, 1)
1451 48 : ALLOCATE (sinv_kind(ikind)%array(noce, noce))
1452 125116 : sinv_kind(ikind)%array = smat_kind(ikind)%array
1453 16 : CALL invmat_symm(sinv_kind(ikind)%array)
1454 : END DO
1455 4 : CALL dbcsr_get_info(iao_vec, group=group)
1456 :
1457 4 : nspin = SIZE(iao_coef, 1)
1458 16 : ALLOCATE (oce_comp(natom, nspin))
1459 24 : oce_comp = 0.0_dp
1460 8 : DO ispin = 1, nspin
1461 4 : CALL copy_fm_to_dbcsr(iao_coef(ispin), iao_vec)
1462 : CALL dbcsr_multiply("N", "N", 1.0_dp, sxo(1)%matrix, iao_vec, 0.0_dp, sx_vec, &
1463 4 : retain_sparsity=.TRUE.)
1464 20 : DO iatom = 1, natom
1465 16 : CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
1466 : CALL dbcsr_get_block_p(matrix=sx_vec, &
1467 16 : row=iatom, col=iatom, BLOCK=ablock, found=found)
1468 20 : IF (found) THEN
1469 8 : n = SIZE(ablock, 1)
1470 8 : m = SIZE(ablock, 2)
1471 213906 : ablock = MATMUL(sinv_kind(ikind)%array, ablock)
1472 88 : ALLOCATE (amat(n, m), bmat(m, m), ev(m), vec(m, m))
1473 25462 : amat(1:n, 1:m) = MATMUL(smat_kind(ikind)%array(1:n, 1:n), ablock(1:n, 1:m))
1474 9964 : bmat(1:m, 1:m) = MATMUL(TRANSPOSE(ablock(1:n, 1:m)), amat(1:n, 1:m))
1475 8 : CALL jacobi(bmat, ev, vec)
1476 30 : oce_comp(iatom, ispin) = SUM(ev(1:m))/REAL(m, KIND=dp)
1477 30 : DO i = 1, m
1478 22 : ev(i) = 1._dp/SQRT(ev(i))
1479 116 : bmat(1:m, i) = vec(1:m, i)*ev(i)
1480 : END DO
1481 714 : bmat(1:m, 1:m) = MATMUL(bmat(1:m, 1:m), TRANSPOSE(vec(1:m, 1:m)))
1482 14548 : ablock(1:n, 1:m) = MATMUL(ablock(1:n, 1:m), bmat(1:m, 1:m))
1483 8 : DEALLOCATE (amat, bmat, ev, vec)
1484 : END IF
1485 : END DO
1486 4 : CALL dbcsr_replicate_all(sx_vec)
1487 24 : DO iatom = 1, natom
1488 16 : CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
1489 : CALL dbcsr_get_block_p(matrix=sx_vec, &
1490 16 : row=iatom, col=iatom, BLOCK=ablock, found=found)
1491 16 : CPASSERT(found)
1492 16 : n = SIZE(ablock, 1)
1493 16 : m = SIZE(ablock, 2)
1494 64 : ALLOCATE (oce_atom(iatom, ispin)%array(n, m))
1495 4728 : oce_atom(iatom, ispin)%array = ablock
1496 : END DO
1497 : END DO
1498 :
1499 4 : CALL group%sum(oce_comp)
1500 4 : IF (unit_nr > 0) THEN
1501 10 : DO iatom = 1, natom
1502 8 : WRITE (unit_nr, "(T4,A,I6,T30,A,2F12.4)") "Atom:", iatom, " Completeness: ", oce_comp(iatom, 1:nspin)
1503 8 : CALL get_atomic_kind(particle_set(iatom)%atomic_kind, kind_number=ikind)
1504 8 : oce_basis => oce_basis_set_list(ikind)%gto_basis_set
1505 : CALL get_gto_basis_set(oce_basis, nset=nset, nshell=nshell, nsgf=nsgf, maxl=maxl, &
1506 8 : l=lval, first_sgf=first_sgf, last_sgf=last_sgf)
1507 72 : ALLOCATE (filter(nsgf, 0:maxl), vector(nsgf), prol(0:maxl, nspin))
1508 4496 : filter = 0.0_dp
1509 70 : DO iset = 1, nset
1510 238 : DO ishell = 1, nshell(iset)
1511 168 : l = lval(ishell, iset)
1512 168 : i1 = first_sgf(ishell, iset)
1513 168 : i2 = last_sgf(ishell, iset)
1514 970 : filter(i1:i2, l) = 1.0_dp
1515 : END DO
1516 : END DO
1517 : !
1518 8 : n = SIZE(oce_atom(iatom, 1)%array, 1)
1519 8 : m = SIZE(oce_atom(iatom, 1)%array, 2)
1520 8 : CPASSERT(n == nsgf)
1521 30 : DO iao = 1, m
1522 176 : prol = 0.0_dp
1523 44 : DO ispin = 1, nspin
1524 176 : DO l = 0, maxl
1525 14076 : vector(1:n) = oce_atom(iatom, ispin)%array(1:n, iao)*filter(1:n, l)
1526 1611250 : prol(l, ispin) = SUM(MATMUL(smat_kind(ikind)%array(1:n, 1:n), vector(1:n))*vector(1:n))
1527 : END DO
1528 : END DO
1529 294 : WRITE (unit_nr, "(T4,I3,T15,A,T39,(6F7.4))") iao, " l-contributions:", (SUM(prol(l, :)), l=0, maxl)
1530 : END DO
1531 18 : DEALLOCATE (filter, vector, prol)
1532 : END DO
1533 2 : WRITE (unit_nr, *)
1534 : END IF
1535 :
1536 4 : DEALLOCATE (oce_comp)
1537 16 : DO ikind = 1, nkind
1538 16 : DEALLOCATE (sinv_kind(ikind)%array)
1539 : END DO
1540 4 : DEALLOCATE (sinv_kind)
1541 4 : DEALLOCATE (iao_blk_sizes)
1542 4 : CALL dbcsr_release(iao_vec)
1543 4 : CALL dbcsr_release(sx_vec)
1544 :
1545 4 : CALL timestop(handle)
1546 :
1547 12 : END SUBROUTINE iao_oce_expansion
1548 :
1549 : ! **************************************************************************************************
1550 : !> \brief ...
1551 : !> \param smat_kind ...
1552 : !> \param basis_set_list ...
1553 : ! **************************************************************************************************
1554 4 : SUBROUTINE oce_overlap_matrix(smat_kind, basis_set_list)
1555 : TYPE(cp_2d_r_p_type), DIMENSION(:) :: smat_kind
1556 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
1557 :
1558 : CHARACTER(len=*), PARAMETER :: routineN = 'oce_overlap_matrix'
1559 :
1560 : INTEGER :: handle, ikind, iset, jset, ldsab, m1, &
1561 : m2, n1, n2, ncoa, ncob, nkind, nseta, &
1562 : sgfa, sgfb
1563 4 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, npgfa, nsgfa
1564 4 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa
1565 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: oint, owork
1566 : REAL(KIND=dp), DIMENSION(3) :: rab
1567 4 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: rpgfa, scon_a, smat, zeta
1568 : TYPE(gto_basis_set_type), POINTER :: basis_set
1569 :
1570 4 : CALL timeset(routineN, handle)
1571 :
1572 4 : rab(1:3) = 0.0_dp
1573 :
1574 4 : nkind = SIZE(smat_kind)
1575 4 : ldsab = 0
1576 16 : DO ikind = 1, nkind
1577 12 : basis_set => basis_set_list(ikind)%gto_basis_set
1578 12 : CPASSERT(ASSOCIATED(basis_set))
1579 12 : CALL get_gto_basis_set(gto_basis_set=basis_set, maxco=m1, nsgf=m2)
1580 16 : ldsab = MAX(m1, m2, ldsab)
1581 : END DO
1582 :
1583 24 : ALLOCATE (oint(ldsab, ldsab), owork(ldsab, ldsab))
1584 :
1585 16 : DO ikind = 1, nkind
1586 12 : basis_set => basis_set_list(ikind)%gto_basis_set
1587 12 : CPASSERT(ASSOCIATED(basis_set))
1588 12 : smat => smat_kind(ikind)%array
1589 125116 : smat = 0.0_dp
1590 : ! basis ikind
1591 12 : first_sgfa => basis_set%first_sgf
1592 12 : la_max => basis_set%lmax
1593 12 : la_min => basis_set%lmin
1594 12 : npgfa => basis_set%npgf
1595 12 : nseta = basis_set%nset
1596 12 : nsgfa => basis_set%nsgf_set
1597 12 : rpgfa => basis_set%pgf_radius
1598 12 : scon_a => basis_set%scon
1599 12 : zeta => basis_set%zet
1600 :
1601 118 : DO iset = 1, nseta
1602 :
1603 102 : ncoa = npgfa(iset)*ncoset(la_max(iset))
1604 102 : n1 = npgfa(iset)*(ncoset(la_max(iset)) - ncoset(la_min(iset) - 1))
1605 102 : sgfa = first_sgfa(1, iset)
1606 :
1607 1236 : DO jset = 1, nseta
1608 :
1609 1122 : ncob = npgfa(jset)*ncoset(la_max(jset))
1610 1122 : n2 = npgfa(jset)*(ncoset(la_max(jset)) - ncoset(la_min(jset) - 1))
1611 1122 : sgfb = first_sgfa(1, jset)
1612 :
1613 : ! calculate integrals and derivatives
1614 : CALL overlap_ab(la_max(iset), la_min(iset), npgfa(iset), rpgfa(:, iset), zeta(:, iset), &
1615 : la_max(jset), la_min(jset), npgfa(jset), rpgfa(:, jset), zeta(:, jset), &
1616 1122 : rab, sab=oint(:, :))
1617 : ! Contraction
1618 : CALL contraction(oint(:, :), owork, ca=scon_a(:, sgfa:), na=n1, ma=nsgfa(iset), &
1619 1122 : cb=scon_a(:, sgfb:), nb=n2, mb=nsgfa(jset), fscale=1.0_dp, trans=.FALSE.)
1620 : CALL block_add("IN", owork, nsgfa(iset), nsgfa(jset), smat, &
1621 1224 : sgfa, sgfb, trans=.FALSE.)
1622 :
1623 : END DO
1624 : END DO
1625 :
1626 : END DO
1627 4 : DEALLOCATE (oint, owork)
1628 :
1629 4 : CALL timestop(handle)
1630 :
1631 4 : END SUBROUTINE oce_overlap_matrix
1632 :
1633 : ! **************************************************************************************************
1634 : !> \brief 2 by 2 rotation optimization for the Pipek-Mezey operator
1635 : !> \param zij_fm_set ...
1636 : !> \param vectors ...
1637 : !> \param order ...
1638 : !> \param accuracy ...
1639 : !> \param unit_nr ...
1640 : !> \par History
1641 : !> 05-2005 created
1642 : !> 10-2023 adapted from jacobi_rotation_pipek [JGH]
1643 : !> \author MI
1644 : ! **************************************************************************************************
1645 34 : SUBROUTINE pm_localization(zij_fm_set, vectors, order, accuracy, unit_nr)
1646 :
1647 : TYPE(cp_fm_type), DIMENSION(:, :), INTENT(IN) :: zij_fm_set
1648 : TYPE(cp_fm_type), INTENT(IN) :: vectors
1649 : INTEGER, INTENT(IN) :: order
1650 : REAL(KIND=dp), INTENT(IN) :: accuracy
1651 : INTEGER, INTENT(IN) :: unit_nr
1652 :
1653 : INTEGER, PARAMETER :: max_sweeps = 250
1654 :
1655 : INTEGER :: iatom, istate, jstate, natom, nstate, &
1656 : sweeps
1657 : REAL(KIND=dp) :: aij, bij, ct, ftarget, mii, mij, mjj, &
1658 : st, t1, t2, theta, tolerance, tt
1659 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: fdiag
1660 : TYPE(cp_fm_type) :: rmat
1661 :
1662 34 : CALL cp_fm_create(rmat, zij_fm_set(1, 1)%matrix_struct)
1663 34 : CALL cp_fm_set_all(rmat, 0.0_dp, 1.0_dp)
1664 :
1665 34 : CALL cp_fm_get_info(rmat, nrow_global=nstate)
1666 102 : ALLOCATE (fdiag(nstate))
1667 34 : tolerance = 1.0e10_dp
1668 34 : sweeps = 0
1669 34 : natom = SIZE(zij_fm_set, 1)
1670 34 : IF (unit_nr > 0) THEN
1671 : WRITE (unit_nr, '(A,T30,A,T45,A,T63,A,T77,A)') &
1672 17 : " Jacobi Localization ", "Sweep", "Functional", "Gradient", "Time"
1673 : END IF
1674 : ! do jacobi sweeps until converged
1675 484 : DO sweeps = 1, max_sweeps
1676 484 : t1 = m_walltime()
1677 484 : tolerance = 0.0_dp
1678 7794 : DO istate = 1, nstate
1679 76778 : DO jstate = istate + 1, nstate
1680 : aij = 0.0_dp
1681 : bij = 0.0_dp
1682 612858 : DO iatom = 1, natom
1683 543874 : CALL cp_fm_get_element(zij_fm_set(iatom, 1), istate, istate, mii)
1684 543874 : CALL cp_fm_get_element(zij_fm_set(iatom, 1), istate, jstate, mij)
1685 543874 : CALL cp_fm_get_element(zij_fm_set(iatom, 1), jstate, jstate, mjj)
1686 612858 : IF (order == 2) THEN
1687 0 : aij = aij + 4._dp*mij**2 - (mii - mjj)**2
1688 0 : bij = bij + 4._dp*mij*(mii - mjj)
1689 543874 : ELSEIF (order == 4) THEN
1690 : aij = aij - mii**4 - mjj**4 + 6._dp*(mii**2 + mjj**2)*mij**2 + &
1691 543874 : mii**3*mjj + mii*mjj**3
1692 543874 : bij = bij + 4._dp*mij*(mii**3 - mjj**3)
1693 : ELSE
1694 0 : CPABORT("PM order")
1695 : END IF
1696 : END DO
1697 68984 : IF ((aij**2 + bij**2) < 1.E-10_dp) CYCLE
1698 68830 : tolerance = tolerance + bij**2
1699 68830 : theta = 0.25_dp*ATAN2(bij, -aij)
1700 68830 : ct = COS(theta)
1701 68830 : st = SIN(theta)
1702 :
1703 68830 : CALL cp_fm_rot_cols(rmat, istate, jstate, ct, st)
1704 :
1705 619468 : DO iatom = 1, natom
1706 543328 : CALL cp_fm_rot_cols(zij_fm_set(iatom, 1), istate, jstate, ct, st)
1707 612312 : CALL cp_fm_rot_rows(zij_fm_set(iatom, 1), istate, jstate, ct, st)
1708 : END DO
1709 : END DO
1710 : END DO
1711 484 : ftarget = 0.0_dp
1712 3462 : DO iatom = 1, natom
1713 2978 : CALL cp_fm_get_diag(zij_fm_set(iatom, 1), fdiag)
1714 57876 : ftarget = ftarget + SUM(fdiag**order)
1715 : END DO
1716 484 : ftarget = ftarget**(1._dp/order)
1717 484 : tolerance = SQRT(tolerance)
1718 484 : t2 = m_walltime()
1719 484 : tt = t2 - t1
1720 484 : IF (unit_nr > 0) THEN
1721 242 : WRITE (unit_nr, '(T31,I4,T39,F16.8,T55,G16.8,T71,F10.2)') sweeps, ftarget, tolerance, tt
1722 : END IF
1723 484 : IF (tolerance < accuracy) EXIT
1724 : END DO
1725 34 : DEALLOCATE (fdiag)
1726 :
1727 34 : CALL rotate_orbitals(rmat, vectors)
1728 34 : CALL cp_fm_release(rmat)
1729 :
1730 68 : END SUBROUTINE pm_localization
1731 : ! **************************************************************************************************
1732 :
1733 140 : END MODULE iao_analysis
|