Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Some utilities for the construction of
10 : !> the localization environment
11 : !> \author MI (05-2005)
12 : ! **************************************************************************************************
13 : MODULE qs_loc_utils
14 :
15 : USE ai_moments, ONLY: contract_cossin,&
16 : cossin
17 : USE basis_set_types, ONLY: gto_basis_set_p_type,&
18 : gto_basis_set_type
19 : USE block_p_types, ONLY: block_p_type
20 : USE cell_types, ONLY: cell_type,&
21 : pbc
22 : USE cp_array_utils, ONLY: cp_1d_r_p_type
23 : USE cp_control_types, ONLY: dft_control_type
24 : USE cp_dbcsr_api, ONLY: dbcsr_copy,&
25 : dbcsr_get_block_p,&
26 : dbcsr_p_type,&
27 : dbcsr_set,&
28 : dbcsr_type
29 : USE cp_dbcsr_operations, ONLY: cp_dbcsr_sm_fm_multiply
30 : USE cp_files, ONLY: close_file,&
31 : open_file
32 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale
33 : USE cp_fm_diag, ONLY: choose_eigv_solver
34 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
35 : cp_fm_struct_release,&
36 : cp_fm_struct_type
37 : USE cp_fm_types, ONLY: &
38 : cp_fm_create, cp_fm_get_info, cp_fm_get_submatrix, cp_fm_release, cp_fm_set_all, &
39 : cp_fm_set_submatrix, cp_fm_to_fm, cp_fm_type, cp_fm_write_unformatted
40 : USE cp_log_handling, ONLY: cp_get_default_logger,&
41 : cp_logger_get_default_io_unit,&
42 : cp_logger_type,&
43 : cp_to_string
44 : USE cp_output_handling, ONLY: cp_p_file,&
45 : cp_print_key_finished_output,&
46 : cp_print_key_generate_filename,&
47 : cp_print_key_should_output,&
48 : cp_print_key_unit_nr
49 : USE distribution_1d_types, ONLY: distribution_1d_type
50 : USE input_constants, ONLY: &
51 : do_loc_crazy, do_loc_direct, do_loc_gapo, do_loc_jacobi, do_loc_l1_norm_sd, do_loc_none, &
52 : do_loc_scdm, energy_loc_range, op_loc_berry, op_loc_boys, op_loc_pipek, state_loc_all, &
53 : state_loc_list, state_loc_mixed, state_loc_none, state_loc_range
54 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
55 : section_vals_type,&
56 : section_vals_val_get
57 : USE kinds, ONLY: default_path_length,&
58 : default_string_length,&
59 : dp
60 : USE mathconstants, ONLY: twopi
61 : USE memory_utilities, ONLY: reallocate
62 : USE message_passing, ONLY: mp_para_env_type
63 : USE orbital_pointers, ONLY: ncoset
64 : USE parallel_gemm_api, ONLY: parallel_gemm
65 : USE particle_types, ONLY: particle_type
66 : USE qs_environment_types, ONLY: get_qs_env,&
67 : qs_environment_type
68 : USE qs_kind_types, ONLY: get_qs_kind,&
69 : get_qs_kind_set,&
70 : qs_kind_type
71 : USE qs_loc_types, ONLY: get_qs_loc_env,&
72 : localized_wfn_control_create,&
73 : localized_wfn_control_release,&
74 : localized_wfn_control_type,&
75 : qs_loc_env_type,&
76 : set_qs_loc_env
77 : USE qs_localization_methods, ONLY: initialize_weights
78 : USE qs_mo_methods, ONLY: make_mo_eig
79 : USE qs_mo_types, ONLY: get_mo_set,&
80 : mo_set_type
81 : USE qs_neighbor_list_types, ONLY: get_iterator_info,&
82 : neighbor_list_iterate,&
83 : neighbor_list_iterator_create,&
84 : neighbor_list_iterator_p_type,&
85 : neighbor_list_iterator_release,&
86 : neighbor_list_set_p_type
87 : USE qs_scf_types, ONLY: ot_method_nr
88 : USE scf_control_types, ONLY: scf_control_type
89 : #include "./base/base_uses.f90"
90 :
91 : IMPLICIT NONE
92 :
93 : PRIVATE
94 :
95 : ! *** Global parameters ***
96 :
97 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_loc_utils'
98 :
99 : ! *** Public ***
100 : PUBLIC :: qs_loc_env_init, loc_write_restart, &
101 : retain_history, qs_loc_init, compute_berry_operator, &
102 : set_loc_centers, set_loc_wfn_lists, qs_loc_control_init
103 :
104 : CONTAINS
105 :
106 : ! **************************************************************************************************
107 : !> \brief copy old mos to new ones, allocating as necessary
108 : !> \param mo_loc_history ...
109 : !> \param mo_loc ...
110 : ! **************************************************************************************************
111 10 : SUBROUTINE retain_history(mo_loc_history, mo_loc)
112 :
113 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: mo_loc_history
114 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: mo_loc
115 :
116 : CHARACTER(len=*), PARAMETER :: routineN = 'retain_history'
117 :
118 : INTEGER :: handle, i, ncol_hist, ncol_loc
119 :
120 10 : CALL timeset(routineN, handle)
121 :
122 10 : IF (.NOT. ASSOCIATED(mo_loc_history)) THEN
123 8 : ALLOCATE (mo_loc_history(SIZE(mo_loc)))
124 4 : DO i = 1, SIZE(mo_loc_history)
125 4 : CALL cp_fm_create(mo_loc_history(i), mo_loc(i)%matrix_struct)
126 : END DO
127 : END IF
128 :
129 20 : DO i = 1, SIZE(mo_loc_history)
130 10 : CALL cp_fm_get_info(mo_loc_history(i), ncol_global=ncol_hist)
131 10 : CALL cp_fm_get_info(mo_loc(i), ncol_global=ncol_loc)
132 10 : CPASSERT(ncol_hist == ncol_loc)
133 30 : CALL cp_fm_to_fm(mo_loc(i), mo_loc_history(i))
134 : END DO
135 :
136 10 : CALL timestop(handle)
137 :
138 10 : END SUBROUTINE retain_history
139 :
140 : ! **************************************************************************************************
141 : !> \brief rotate the mo_new, so that the orbitals are as similar
142 : !> as possible to ones in mo_ref.
143 : !> \param mo_new ...
144 : !> \param mo_ref ...
145 : !> \param matrix_S ...
146 : ! **************************************************************************************************
147 8 : SUBROUTINE rotate_state_to_ref(mo_new, mo_ref, matrix_S)
148 :
149 : TYPE(cp_fm_type), INTENT(IN) :: mo_new, mo_ref
150 : TYPE(dbcsr_type), POINTER :: matrix_S
151 :
152 : CHARACTER(len=*), PARAMETER :: routineN = 'rotate_state_to_ref'
153 :
154 : INTEGER :: handle, ncol, ncol_ref, nrow
155 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenvalues
156 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_tmp
157 : TYPE(cp_fm_type) :: o1, o2, o3, o4, smo
158 :
159 8 : CALL timeset(routineN, handle)
160 :
161 8 : CALL cp_fm_get_info(mo_new, nrow_global=nrow, ncol_global=ncol)
162 8 : CALL cp_fm_get_info(mo_ref, ncol_global=ncol_ref)
163 8 : CPASSERT(ncol == ncol_ref)
164 :
165 8 : NULLIFY (fm_struct_tmp)
166 8 : CALL cp_fm_create(smo, mo_ref%matrix_struct)
167 :
168 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol, &
169 : ncol_global=ncol, para_env=mo_new%matrix_struct%para_env, &
170 8 : context=mo_new%matrix_struct%context)
171 8 : CALL cp_fm_create(o1, fm_struct_tmp)
172 8 : CALL cp_fm_create(o2, fm_struct_tmp)
173 8 : CALL cp_fm_create(o3, fm_struct_tmp)
174 8 : CALL cp_fm_create(o4, fm_struct_tmp)
175 8 : CALL cp_fm_struct_release(fm_struct_tmp)
176 :
177 : ! o1 = (mo_new)^T matrix_S mo_ref
178 8 : CALL cp_dbcsr_sm_fm_multiply(matrix_S, mo_ref, smo, ncol)
179 8 : CALL parallel_gemm('T', 'N', ncol, ncol, nrow, 1.0_dp, mo_new, smo, 0.0_dp, o1)
180 :
181 : ! o2 = (o1^T o1)
182 8 : CALL parallel_gemm('T', 'N', ncol, ncol, ncol, 1.0_dp, o1, o1, 0.0_dp, o2)
183 :
184 : ! o2 = (o1^T o1)^-1/2
185 24 : ALLOCATE (eigenvalues(ncol))
186 8 : CALL choose_eigv_solver(o2, o3, eigenvalues)
187 8 : CALL cp_fm_to_fm(o3, o4)
188 72 : eigenvalues(:) = 1.0_dp/SQRT(eigenvalues(:))
189 8 : CALL cp_fm_column_scale(o4, eigenvalues)
190 8 : CALL parallel_gemm('N', 'T', ncol, ncol, ncol, 1.0_dp, o3, o4, 0.0_dp, o2)
191 :
192 : ! o3 = o1 (o1^T o1)^-1/2
193 8 : CALL parallel_gemm('N', 'N', ncol, ncol, ncol, 1.0_dp, o1, o2, 0.0_dp, o3)
194 :
195 : ! mo_new o1 (o1^T o1)^-1/2
196 8 : CALL parallel_gemm('N', 'N', nrow, ncol, ncol, 1.0_dp, mo_new, o3, 0.0_dp, smo)
197 8 : CALL cp_fm_to_fm(smo, mo_new)
198 :
199 : ! XXXXXXX testing
200 : ! CALL parallel_gemm('N','T',ncol,ncol,ncol,1.0_dp,o3,o3,0.0_dp,o1)
201 : ! WRITE(*,*) o1%local_data
202 : ! CALL parallel_gemm('T','N',ncol,ncol,ncol,1.0_dp,o3,o3,0.0_dp,o1)
203 : ! WRITE(*,*) o1%local_data
204 :
205 8 : CALL cp_fm_release(o1)
206 8 : CALL cp_fm_release(o2)
207 8 : CALL cp_fm_release(o3)
208 8 : CALL cp_fm_release(o4)
209 8 : CALL cp_fm_release(smo)
210 :
211 8 : CALL timestop(handle)
212 :
213 32 : END SUBROUTINE rotate_state_to_ref
214 :
215 : ! **************************************************************************************************
216 : !> \brief allocates the data, and initializes the operators
217 : !> \param qs_loc_env new environment for the localization calculations
218 : !> \param localized_wfn_control variables and directives for the localization
219 : !> \param qs_env the qs_env in which the qs_env lives
220 : !> \param myspin ...
221 : !> \param do_localize ...
222 : !> \param loc_coeff ...
223 : !> \param mo_loc_history ...
224 : !> \par History
225 : !> 04.2005 created [MI]
226 : !> \author MI
227 : !> \note
228 : !> similar to the old one, but not quite
229 : ! **************************************************************************************************
230 864 : SUBROUTINE qs_loc_env_init(qs_loc_env, localized_wfn_control, qs_env, myspin, do_localize, &
231 432 : loc_coeff, mo_loc_history)
232 :
233 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
234 : TYPE(localized_wfn_control_type), POINTER :: localized_wfn_control
235 : TYPE(qs_environment_type), POINTER :: qs_env
236 : INTEGER, INTENT(IN), OPTIONAL :: myspin
237 : LOGICAL, INTENT(IN), OPTIONAL :: do_localize
238 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN), &
239 : OPTIONAL :: loc_coeff
240 : TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER :: mo_loc_history
241 :
242 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_env_init'
243 :
244 : INTEGER :: dim_op, handle, i, iatom, imo, imoloc, &
245 : ispin, j, l_spin, lb, nao, naosub, &
246 : natoms, nmo, nmosub, nspins, s_spin, ub
247 : REAL(KIND=dp) :: my_occ, occ_imo
248 432 : REAL(KIND=dp), DIMENSION(:), POINTER :: occupations
249 432 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: vecbuffer
250 : TYPE(cell_type), POINTER :: cell
251 : TYPE(cp_fm_struct_type), POINTER :: tmp_fm_struct
252 432 : TYPE(cp_fm_type), DIMENSION(:), POINTER :: moloc_coeff
253 : TYPE(cp_fm_type), POINTER :: mat_ptr, mo_coeff
254 432 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_s
255 : TYPE(distribution_1d_type), POINTER :: local_molecules
256 432 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
257 : TYPE(mp_para_env_type), POINTER :: para_env
258 432 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
259 :
260 432 : CALL timeset(routineN, handle)
261 :
262 432 : NULLIFY (mos, matrix_s, moloc_coeff, particle_set, para_env, cell, local_molecules, occupations, mat_ptr)
263 432 : IF (PRESENT(do_localize)) qs_loc_env%do_localize = do_localize
264 432 : IF (qs_loc_env%do_localize) THEN
265 : CALL get_qs_env(qs_env=qs_env, matrix_s=matrix_s, cell=cell, &
266 : local_molecules=local_molecules, particle_set=particle_set, &
267 432 : para_env=para_env, mos=mos)
268 432 : nspins = SIZE(mos, 1)
269 432 : s_spin = 1
270 432 : l_spin = nspins
271 432 : IF (PRESENT(myspin)) THEN
272 144 : s_spin = myspin
273 144 : l_spin = myspin
274 : END IF
275 1840 : ALLOCATE (moloc_coeff(s_spin:l_spin))
276 976 : DO ispin = s_spin, l_spin
277 544 : NULLIFY (tmp_fm_struct, mo_coeff)
278 544 : CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, nao=nao, nmo=nmo)
279 544 : nmosub = localized_wfn_control%nloc_states(ispin)
280 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nao, &
281 544 : ncol_global=nmosub, para_env=para_env, context=mo_coeff%matrix_struct%context)
282 544 : CALL cp_fm_create(moloc_coeff(ispin), tmp_fm_struct)
283 :
284 : CALL cp_fm_get_info(moloc_coeff(ispin), nrow_global=naosub, &
285 544 : ncol_global=nmosub)
286 544 : CPASSERT(nao == naosub)
287 544 : IF ((localized_wfn_control%do_homo) .OR. &
288 : (localized_wfn_control%set_of_states == state_loc_mixed)) THEN
289 532 : CPASSERT(nmo >= nmosub)
290 : ELSE
291 12 : CPASSERT(nao - nmo >= nmosub)
292 : END IF
293 544 : CALL cp_fm_set_all(moloc_coeff(ispin), 0.0_dp)
294 2064 : CALL cp_fm_struct_release(tmp_fm_struct)
295 : END DO ! ispin
296 : ! Copy the submatrix
297 :
298 432 : IF (PRESENT(loc_coeff)) ALLOCATE (mat_ptr)
299 :
300 976 : DO ispin = s_spin, l_spin
301 : CALL get_mo_set(mos(ispin), mo_coeff=mo_coeff, &
302 544 : occupation_numbers=occupations, nao=nao, nmo=nmo)
303 544 : lb = localized_wfn_control%lu_bound_states(1, ispin)
304 544 : ub = localized_wfn_control%lu_bound_states(2, ispin)
305 :
306 544 : IF (PRESENT(loc_coeff)) THEN
307 380 : mat_ptr = loc_coeff(ispin)
308 : ELSE
309 164 : mat_ptr => mo_coeff
310 : END IF
311 544 : IF ((localized_wfn_control%set_of_states == state_loc_list) .OR. &
312 : (localized_wfn_control%set_of_states == state_loc_mixed)) THEN
313 372 : ALLOCATE (vecbuffer(1, nao))
314 124 : IF (localized_wfn_control%do_homo) THEN
315 110 : my_occ = occupations(localized_wfn_control%loc_states(1, ispin))
316 : END IF
317 124 : nmosub = SIZE(localized_wfn_control%loc_states, 1)
318 124 : CPASSERT(nmosub > 0)
319 124 : imoloc = 0
320 874 : DO i = lb, ub
321 : ! Get the index in the subset
322 750 : imoloc = imoloc + 1
323 : ! Get the index in the full set
324 750 : imo = localized_wfn_control%loc_states(i, ispin)
325 750 : IF (localized_wfn_control%do_homo) THEN
326 616 : occ_imo = occupations(imo)
327 616 : IF (ABS(occ_imo - my_occ) > localized_wfn_control%eps_occ) THEN
328 0 : IF (localized_wfn_control%localization_method /= do_loc_none) &
329 : CALL cp_abort(__LOCATION__, &
330 : "States with different occupations "// &
331 0 : "cannot be rotated together")
332 : END IF
333 : END IF
334 : ! Take the imo vector from the full set and copy in the imoloc vector of the subset
335 : CALL cp_fm_get_submatrix(mat_ptr, vecbuffer, 1, imo, &
336 750 : nao, 1, transpose=.TRUE.)
337 : CALL cp_fm_set_submatrix(moloc_coeff(ispin), vecbuffer, 1, imoloc, &
338 874 : nao, 1, transpose=.TRUE.)
339 : END DO
340 124 : DEALLOCATE (vecbuffer)
341 : ELSE
342 420 : my_occ = occupations(lb)
343 420 : occ_imo = occupations(ub)
344 420 : IF (ABS(occ_imo - my_occ) > localized_wfn_control%eps_occ) THEN
345 0 : IF (localized_wfn_control%localization_method /= do_loc_none) &
346 : CALL cp_abort(__LOCATION__, &
347 : "States with different occupations "// &
348 0 : "cannot be rotated together")
349 : END IF
350 420 : nmosub = localized_wfn_control%nloc_states(ispin)
351 420 : CALL cp_fm_to_fm(mat_ptr, moloc_coeff(ispin), nmosub, lb, 1)
352 : END IF
353 :
354 : ! we have the mo's to be localized now, see if we can rotate them according to the history
355 : ! only do that if we have a history of course. The history is filled
356 1520 : IF (PRESENT(mo_loc_history)) THEN
357 100 : IF (localized_wfn_control%use_history .AND. ASSOCIATED(mo_loc_history)) THEN
358 : CALL rotate_state_to_ref(moloc_coeff(ispin), &
359 8 : mo_loc_history(ispin), matrix_s(1)%matrix)
360 : END IF
361 : END IF
362 :
363 : END DO
364 :
365 432 : IF (PRESENT(loc_coeff)) DEALLOCATE (mat_ptr)
366 :
367 : CALL set_qs_loc_env(qs_loc_env=qs_loc_env, cell=cell, local_molecules=local_molecules, &
368 : moloc_coeff=moloc_coeff, particle_set=particle_set, para_env=para_env, &
369 432 : localized_wfn_control=localized_wfn_control)
370 :
371 : ! Prepare the operators
372 432 : NULLIFY (tmp_fm_struct, mo_coeff)
373 1296 : nmosub = MAXVAL(localized_wfn_control%nloc_states)
374 432 : CALL get_mo_set(mos(1), mo_coeff=mo_coeff)
375 : CALL cp_fm_struct_create(tmp_fm_struct, nrow_global=nmosub, &
376 432 : ncol_global=nmosub, para_env=para_env, context=mo_coeff%matrix_struct%context)
377 :
378 432 : IF (localized_wfn_control%operator_type == op_loc_berry) THEN
379 432 : IF (qs_loc_env%cell%orthorhombic) THEN
380 420 : dim_op = 3
381 : ELSE
382 12 : dim_op = 6
383 : END IF
384 432 : CALL set_qs_loc_env(qs_loc_env=qs_loc_env, dim_op=dim_op)
385 5292 : ALLOCATE (qs_loc_env%op_sm_set(2, dim_op))
386 1764 : DO i = 1, dim_op
387 4428 : DO j = 1, SIZE(qs_loc_env%op_sm_set, 1)
388 2664 : NULLIFY (qs_loc_env%op_sm_set(j, i)%matrix)
389 2664 : ALLOCATE (qs_loc_env%op_sm_set(j, i)%matrix)
390 : CALL dbcsr_copy(qs_loc_env%op_sm_set(j, i)%matrix, matrix_s(1)%matrix, &
391 2664 : name="qs_loc_env%op_sm_"//TRIM(ADJUSTL(cp_to_string(j)))//"-"//TRIM(ADJUSTL(cp_to_string(i))))
392 3996 : CALL dbcsr_set(qs_loc_env%op_sm_set(j, i)%matrix, 0.0_dp)
393 : END DO
394 : END DO
395 :
396 0 : ELSEIF (localized_wfn_control%operator_type == op_loc_pipek) THEN
397 0 : natoms = SIZE(qs_loc_env%particle_set, 1)
398 0 : ALLOCATE (qs_loc_env%op_fm_set(natoms, 1))
399 0 : CALL set_qs_loc_env(qs_loc_env=qs_loc_env, dim_op=natoms)
400 0 : DO ispin = 1, SIZE(qs_loc_env%op_fm_set, 2)
401 0 : CALL get_mo_set(mos(ispin), nmo=nmo)
402 0 : DO iatom = 1, natoms
403 0 : CALL cp_fm_create(qs_loc_env%op_fm_set(iatom, ispin), tmp_fm_struct)
404 :
405 0 : CALL cp_fm_get_info(qs_loc_env%op_fm_set(iatom, ispin), nrow_global=nmosub)
406 0 : CPASSERT(nmo >= nmosub)
407 0 : CALL cp_fm_set_all(qs_loc_env%op_fm_set(iatom, ispin), 0.0_dp)
408 : END DO ! iatom
409 : END DO ! ispin
410 : ELSE
411 0 : CPABORT("Type of operator not implemented")
412 : END IF
413 432 : CALL cp_fm_struct_release(tmp_fm_struct)
414 :
415 432 : IF (localized_wfn_control%operator_type == op_loc_berry) THEN
416 :
417 432 : CALL initialize_weights(qs_loc_env%cell, qs_loc_env%weights)
418 :
419 432 : CALL get_berry_operator(qs_loc_env, qs_env)
420 :
421 : ELSEIF (localized_wfn_control%operator_type == op_loc_pipek) THEN
422 :
423 : !! here we don't have to do anything
424 : !! CALL get_pipek_mezey_operator ( qs_loc_env, qs_env )
425 :
426 : END IF
427 :
428 432 : qs_loc_env%molecular_states = .FALSE.
429 432 : qs_loc_env%wannier_states = .FALSE.
430 : END IF
431 432 : CALL timestop(handle)
432 :
433 432 : END SUBROUTINE qs_loc_env_init
434 :
435 : ! **************************************************************************************************
436 : !> \brief A wrapper to compute the Berry operator for periodic systems
437 : !> \param qs_loc_env new environment for the localization calculations
438 : !> \param qs_env the qs_env in which the qs_env lives
439 : !> \par History
440 : !> 04.2005 created [MI]
441 : !> 04.2018 modified [RZK, ZL]
442 : !> \author MI
443 : ! **************************************************************************************************
444 432 : SUBROUTINE get_berry_operator(qs_loc_env, qs_env)
445 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
446 : TYPE(qs_environment_type), POINTER :: qs_env
447 :
448 : CHARACTER(len=*), PARAMETER :: routineN = 'get_berry_operator'
449 :
450 : INTEGER :: dim_op, handle
451 : TYPE(cell_type), POINTER :: cell
452 432 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: op_sm_set
453 :
454 432 : CALL timeset(routineN, handle)
455 :
456 432 : NULLIFY (cell, op_sm_set)
457 : CALL get_qs_loc_env(qs_loc_env=qs_loc_env, op_sm_set=op_sm_set, &
458 432 : cell=cell, dim_op=dim_op)
459 432 : CALL compute_berry_operator(qs_env, cell, op_sm_set, dim_op)
460 :
461 432 : CALL timestop(handle)
462 432 : END SUBROUTINE get_berry_operator
463 :
464 : ! **************************************************************************************************
465 : !> \brief Computes the Berry operator for periodic systems
466 : !> used to define the spread of the MOS
467 : !> Here the matrix elements of the type <mu|cos(kr)|nu> and <mu|sin(kr)|nu>
468 : !> are computed, where mu and nu are the contracted basis functions.
469 : !> Namely the Berry operator is exp(ikr)
470 : !> k is defined somewhere
471 : !> the pair lists are exploited and sparse matrixes are constructed
472 : !> \param qs_env the qs_env in which the qs_env lives
473 : !> \param cell ...
474 : !> \param op_sm_set ...
475 : !> \param dim_op ...
476 : !> \par History
477 : !> 04.2005 created [MI]
478 : !> 04.2018 wrapped old code [RZK, ZL]
479 : !> \author MI
480 : !> \note
481 : !> The intgrals are computed analytically using the primitives GTO
482 : !> The contraction is performed block-wise
483 : ! **************************************************************************************************
484 458 : SUBROUTINE compute_berry_operator(qs_env, cell, op_sm_set, dim_op)
485 : TYPE(qs_environment_type), POINTER :: qs_env
486 : TYPE(cell_type), POINTER :: cell
487 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: op_sm_set
488 : INTEGER :: dim_op
489 :
490 : CHARACTER(len=*), PARAMETER :: routineN = 'compute_berry_operator'
491 :
492 : INTEGER :: handle, i, iatom, icol, ikind, inode, irow, iset, jatom, jkind, jset, last_jatom, &
493 : ldab, ldsa, ldsb, ldwork, maxl, ncoa, ncob, nkind, nrow, nseta, nsetb, sgfa, sgfb
494 : INTEGER, DIMENSION(3) :: perd0
495 458 : INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min, npgfa, &
496 458 : npgfb, nsgfa, nsgfb
497 458 : INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb
498 : LOGICAL :: found, new_atom_b
499 : REAL(KIND=dp) :: dab, kvec(3), rab2, vector_k(3, 6)
500 : REAL(KIND=dp), DIMENSION(3) :: ra, rab, rb
501 458 : REAL(KIND=dp), DIMENSION(:), POINTER :: set_radius_a, set_radius_b
502 458 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: cosab, rpgfa, rpgfb, sinab, sphi_a, &
503 458 : sphi_b, work, zeta, zetb
504 458 : TYPE(block_p_type), DIMENSION(:), POINTER :: op_cos, op_sin
505 458 : TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list
506 : TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b
507 : TYPE(neighbor_list_iterator_p_type), &
508 458 : DIMENSION(:), POINTER :: nl_iterator
509 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
510 458 : POINTER :: sab_orb
511 458 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
512 458 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
513 : TYPE(qs_kind_type), POINTER :: qs_kind
514 :
515 458 : CALL timeset(routineN, handle)
516 458 : NULLIFY (qs_kind, qs_kind_set)
517 458 : NULLIFY (particle_set)
518 458 : NULLIFY (sab_orb)
519 458 : NULLIFY (cosab, sinab, work)
520 458 : NULLIFY (la_max, la_min, lb_max, lb_min, npgfa, npgfb, nsgfa, nsgfb)
521 458 : NULLIFY (set_radius_a, set_radius_b, rpgfa, rpgfb, sphi_a, sphi_b, zeta, zetb)
522 :
523 : CALL get_qs_env(qs_env=qs_env, qs_kind_set=qs_kind_set, &
524 458 : particle_set=particle_set, sab_orb=sab_orb)
525 :
526 458 : nkind = SIZE(qs_kind_set)
527 :
528 : CALL get_qs_kind_set(qs_kind_set=qs_kind_set, &
529 458 : maxco=ldwork, maxlgto=maxl)
530 458 : ldab = ldwork
531 1832 : ALLOCATE (cosab(ldab, ldab))
532 125502 : cosab = 0.0_dp
533 1374 : ALLOCATE (sinab(ldab, ldab))
534 125502 : sinab = 0.0_dp
535 1374 : ALLOCATE (work(ldwork, ldwork))
536 125502 : work = 0.0_dp
537 :
538 2784 : ALLOCATE (op_cos(dim_op))
539 2326 : ALLOCATE (op_sin(dim_op))
540 1868 : DO i = 1, dim_op
541 1410 : NULLIFY (op_cos(i)%block)
542 1868 : NULLIFY (op_sin(i)%block)
543 : END DO
544 :
545 458 : kvec = 0.0_dp
546 458 : vector_k = 0.0_dp
547 1832 : vector_k(:, 1) = twopi*cell%h_inv(1, :)
548 1832 : vector_k(:, 2) = twopi*cell%h_inv(2, :)
549 1832 : vector_k(:, 3) = twopi*cell%h_inv(3, :)
550 1832 : vector_k(:, 4) = twopi*(cell%h_inv(1, :) + cell%h_inv(2, :))
551 1832 : vector_k(:, 5) = twopi*(cell%h_inv(1, :) + cell%h_inv(3, :))
552 1832 : vector_k(:, 6) = twopi*(cell%h_inv(2, :) + cell%h_inv(3, :))
553 :
554 : ! This operator can be used only for periodic systems
555 : ! If an isolated system is used the periodicity is overimposed
556 1832 : perd0(1:3) = cell%perd(1:3)
557 1832 : cell%perd(1:3) = 1
558 :
559 2186 : ALLOCATE (basis_set_list(nkind))
560 1270 : DO ikind = 1, nkind
561 812 : qs_kind => qs_kind_set(ikind)
562 812 : CALL get_qs_kind(qs_kind=qs_kind, basis_set=basis_set_a)
563 1270 : IF (ASSOCIATED(basis_set_a)) THEN
564 812 : basis_set_list(ikind)%gto_basis_set => basis_set_a
565 : ELSE
566 0 : NULLIFY (basis_set_list(ikind)%gto_basis_set)
567 : END IF
568 : END DO
569 458 : CALL neighbor_list_iterator_create(nl_iterator, sab_orb)
570 73548 : DO WHILE (neighbor_list_iterate(nl_iterator) == 0)
571 : CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, inode=inode, &
572 73090 : iatom=iatom, jatom=jatom, r=rab)
573 73090 : basis_set_a => basis_set_list(ikind)%gto_basis_set
574 73090 : IF (.NOT. ASSOCIATED(basis_set_a)) CYCLE
575 73090 : basis_set_b => basis_set_list(jkind)%gto_basis_set
576 73090 : IF (.NOT. ASSOCIATED(basis_set_b)) CYCLE
577 73090 : ra = pbc(particle_set(iatom)%r, cell)
578 : ! basis ikind
579 73090 : first_sgfa => basis_set_a%first_sgf
580 73090 : la_max => basis_set_a%lmax
581 73090 : la_min => basis_set_a%lmin
582 73090 : npgfa => basis_set_a%npgf
583 73090 : nseta = basis_set_a%nset
584 73090 : nsgfa => basis_set_a%nsgf_set
585 73090 : rpgfa => basis_set_a%pgf_radius
586 73090 : set_radius_a => basis_set_a%set_radius
587 73090 : sphi_a => basis_set_a%sphi
588 73090 : zeta => basis_set_a%zet
589 : ! basis jkind
590 73090 : first_sgfb => basis_set_b%first_sgf
591 73090 : lb_max => basis_set_b%lmax
592 73090 : lb_min => basis_set_b%lmin
593 73090 : npgfb => basis_set_b%npgf
594 73090 : nsetb = basis_set_b%nset
595 73090 : nsgfb => basis_set_b%nsgf_set
596 73090 : rpgfb => basis_set_b%pgf_radius
597 73090 : set_radius_b => basis_set_b%set_radius
598 73090 : sphi_b => basis_set_b%sphi
599 73090 : zetb => basis_set_b%zet
600 :
601 73090 : ldsa = SIZE(sphi_a, 1)
602 73090 : ldsb = SIZE(sphi_b, 1)
603 73090 : IF (inode == 1) last_jatom = 0
604 :
605 292360 : rb = rab + ra
606 :
607 73090 : IF (jatom /= last_jatom) THEN
608 : new_atom_b = .TRUE.
609 : last_jatom = jatom
610 : ELSE
611 : new_atom_b = .FALSE.
612 : END IF
613 :
614 : IF (new_atom_b) THEN
615 17763 : IF (iatom <= jatom) THEN
616 9273 : irow = iatom
617 9273 : icol = jatom
618 : ELSE
619 8490 : irow = jatom
620 8490 : icol = iatom
621 : END IF
622 :
623 71520 : DO i = 1, dim_op
624 53757 : NULLIFY (op_cos(i)%block)
625 : CALL dbcsr_get_block_p(matrix=op_sm_set(1, i)%matrix, &
626 53757 : row=irow, col=icol, block=op_cos(i)%block, found=found)
627 53757 : NULLIFY (op_sin(i)%block)
628 : CALL dbcsr_get_block_p(matrix=op_sm_set(2, i)%matrix, &
629 71520 : row=irow, col=icol, block=op_sin(i)%block, found=found)
630 : END DO
631 : END IF ! new_atom_b
632 :
633 73090 : rab2 = rab(1)*rab(1) + rab(2)*rab(2) + rab(3)*rab(3)
634 73090 : dab = SQRT(rab2)
635 :
636 73090 : nrow = 0
637 229305 : DO iset = 1, nseta
638 :
639 155757 : ncoa = npgfa(iset)*ncoset(la_max(iset))
640 155757 : sgfa = first_sgfa(1, iset)
641 :
642 507779 : DO jset = 1, nsetb
643 :
644 352022 : ncob = npgfb(jset)*ncoset(lb_max(jset))
645 352022 : sgfb = first_sgfb(1, jset)
646 :
647 507779 : IF (set_radius_a(iset) + set_radius_b(jset) >= dab) THEN
648 :
649 : ! *** Calculate the primitive overlap integrals ***
650 715734 : DO i = 1, dim_op
651 2218920 : kvec(1:3) = vector_k(1:3, i)
652 187888998 : cosab = 0.0_dp
653 187888998 : sinab = 0.0_dp
654 : CALL cossin(la_max(iset), npgfa(iset), zeta(:, iset), rpgfa(:, iset), &
655 : la_min(iset), lb_max(jset), npgfb(jset), zetb(:, jset), &
656 : rpgfb(:, jset), lb_min(jset), &
657 554730 : ra, rb, kvec, cosab, sinab)
658 : CALL contract_cossin(op_cos(i)%block, op_sin(i)%block, &
659 : iatom, ncoa, nsgfa(iset), sgfa, sphi_a, ldsa, &
660 : jatom, ncob, nsgfb(jset), sgfb, sphi_b, ldsb, &
661 715734 : cosab, sinab, ldab, work, ldwork)
662 : END DO
663 :
664 : END IF ! >= dab
665 :
666 : END DO ! jset
667 :
668 228847 : nrow = nrow + ncoa
669 :
670 : END DO ! iset
671 :
672 : END DO
673 458 : CALL neighbor_list_iterator_release(nl_iterator)
674 :
675 : ! Set back the correct periodicity
676 1832 : cell%perd(1:3) = perd0(1:3)
677 :
678 1868 : DO i = 1, dim_op
679 1410 : NULLIFY (op_cos(i)%block)
680 1868 : NULLIFY (op_sin(i)%block)
681 : END DO
682 458 : DEALLOCATE (op_cos, op_sin)
683 :
684 458 : DEALLOCATE (cosab, sinab, work, basis_set_list)
685 :
686 458 : CALL timestop(handle)
687 916 : END SUBROUTINE compute_berry_operator
688 :
689 : ! **************************************************************************************************
690 : !> \brief ...
691 : !> \param qs_loc_env ...
692 : !> \param section ...
693 : !> \param mo_array ...
694 : !> \param coeff_localized ...
695 : !> \param do_homo ...
696 : !> \param evals ...
697 : !> \param do_mixed ...
698 : ! **************************************************************************************************
699 294 : SUBROUTINE loc_write_restart(qs_loc_env, section, mo_array, coeff_localized, &
700 : do_homo, evals, do_mixed)
701 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
702 : TYPE(section_vals_type), POINTER :: section
703 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mo_array
704 : TYPE(cp_fm_type), DIMENSION(:), INTENT(IN) :: coeff_localized
705 : LOGICAL, INTENT(IN) :: do_homo
706 : TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
707 : POINTER :: evals
708 : LOGICAL, INTENT(IN), OPTIONAL :: do_mixed
709 :
710 : CHARACTER(LEN=*), PARAMETER :: routineN = 'loc_write_restart'
711 :
712 : CHARACTER(LEN=default_path_length) :: filename
713 : CHARACTER(LEN=default_string_length) :: my_middle
714 : INTEGER :: handle, ispin, max_block, nao, nloc, &
715 : nmo, output_unit, rst_unit
716 : LOGICAL :: my_do_mixed
717 : TYPE(cp_logger_type), POINTER :: logger
718 : TYPE(section_vals_type), POINTER :: print_key
719 :
720 294 : CALL timeset(routineN, handle)
721 294 : NULLIFY (logger)
722 294 : logger => cp_get_default_logger()
723 294 : output_unit = cp_logger_get_default_io_unit(logger)
724 :
725 294 : IF (qs_loc_env%do_localize) THEN
726 :
727 278 : print_key => section_vals_get_subs_vals(section, "LOC_RESTART")
728 278 : IF (BTEST(cp_print_key_should_output(logger%iter_info, &
729 : section, "LOC_RESTART"), &
730 : cp_p_file)) THEN
731 :
732 : ! Open file
733 30 : rst_unit = -1
734 :
735 30 : my_do_mixed = .FALSE.
736 30 : IF (PRESENT(do_mixed)) my_do_mixed = do_mixed
737 30 : IF (do_homo) THEN
738 30 : my_middle = "LOC_HOMO"
739 0 : ELSEIF (my_do_mixed) THEN
740 0 : my_middle = "LOC_MIXED"
741 : ELSE
742 0 : my_middle = "LOC_LUMO"
743 : END IF
744 :
745 : rst_unit = cp_print_key_unit_nr(logger, section, "LOC_RESTART", &
746 : extension=".wfn", file_status="REPLACE", file_action="WRITE", &
747 30 : file_form="UNFORMATTED", middle_name=TRIM(my_middle))
748 :
749 30 : IF (rst_unit > 0) filename = cp_print_key_generate_filename(logger, print_key, &
750 : middle_name=TRIM(my_middle), extension=".wfn", &
751 15 : my_local=.FALSE.)
752 :
753 30 : IF (output_unit > 0) THEN
754 : WRITE (UNIT=output_unit, FMT="(/,T2,A, A/)") &
755 15 : "LOCALIZATION| Write restart file for the localized MOS : ", &
756 30 : TRIM(filename)
757 : END IF
758 :
759 30 : IF (rst_unit > 0) THEN
760 15 : WRITE (rst_unit) qs_loc_env%localized_wfn_control%set_of_states
761 15 : WRITE (rst_unit) qs_loc_env%localized_wfn_control%lu_bound_states
762 15 : WRITE (rst_unit) qs_loc_env%localized_wfn_control%nloc_states
763 : END IF
764 :
765 70 : DO ispin = 1, SIZE(coeff_localized)
766 30 : ASSOCIATE (mo_coeff => coeff_localized(ispin))
767 40 : CALL cp_fm_get_info(mo_coeff, nrow_global=nao, ncol_global=nmo, ncol_block=max_block)
768 40 : nloc = qs_loc_env%localized_wfn_control%nloc_states(ispin)
769 40 : IF (rst_unit > 0) THEN
770 20 : WRITE (rst_unit) qs_loc_env%localized_wfn_control%loc_states(1:nloc, ispin)
771 20 : IF (do_homo .OR. my_do_mixed) THEN
772 20 : WRITE (rst_unit) nmo, &
773 20 : mo_array(ispin)%homo, &
774 20 : mo_array(ispin)%lfomo, &
775 40 : mo_array(ispin)%nelectron
776 456 : WRITE (rst_unit) mo_array(ispin)%eigenvalues(1:nmo), &
777 476 : mo_array(ispin)%occupation_numbers(1:nmo)
778 : ELSE
779 0 : WRITE (rst_unit) nmo
780 0 : WRITE (rst_unit) evals(ispin)%array(1:nmo)
781 : END IF
782 : END IF
783 :
784 80 : CALL cp_fm_write_unformatted(mo_coeff, rst_unit)
785 : END ASSOCIATE
786 :
787 : END DO
788 :
789 : CALL cp_print_key_finished_output(rst_unit, logger, section, &
790 30 : "LOC_RESTART")
791 : END IF
792 :
793 : END IF
794 :
795 294 : CALL timestop(handle)
796 :
797 294 : END SUBROUTINE loc_write_restart
798 :
799 : ! **************************************************************************************************
800 : !> \brief ...
801 : !> \param qs_loc_env ...
802 : !> \param mos ...
803 : !> \param mos_localized ...
804 : !> \param section ...
805 : !> \param section2 ...
806 : !> \param para_env ...
807 : !> \param do_homo ...
808 : !> \param restart_found ...
809 : !> \param evals ...
810 : !> \param do_mixed ...
811 : ! **************************************************************************************************
812 6 : SUBROUTINE loc_read_restart(qs_loc_env, mos, mos_localized, section, section2, para_env, &
813 : do_homo, restart_found, evals, do_mixed)
814 :
815 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
816 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
817 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: mos_localized
818 : TYPE(section_vals_type), POINTER :: section, section2
819 : TYPE(mp_para_env_type), POINTER :: para_env
820 : LOGICAL, INTENT(IN) :: do_homo
821 : LOGICAL, INTENT(INOUT) :: restart_found
822 : TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
823 : POINTER :: evals
824 : LOGICAL, INTENT(IN), OPTIONAL :: do_mixed
825 :
826 : CHARACTER(len=*), PARAMETER :: routineN = 'loc_read_restart'
827 :
828 : CHARACTER(LEN=25) :: fname_key
829 : CHARACTER(LEN=default_path_length) :: filename
830 : CHARACTER(LEN=default_string_length) :: my_middle
831 : INTEGER :: handle, homo_read, i, ispin, lfomo_read, max_nloc, n_rep_val, nao, &
832 : nelectron_read, nloc, nmo, nmo_read, nspin, output_unit, rst_unit
833 : LOGICAL :: file_exists, my_do_mixed
834 6 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eig_read, occ_read
835 6 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: vecbuffer
836 : TYPE(cp_logger_type), POINTER :: logger
837 : TYPE(section_vals_type), POINTER :: print_key
838 :
839 6 : CALL timeset(routineN, handle)
840 :
841 6 : logger => cp_get_default_logger()
842 :
843 6 : nspin = SIZE(mos_localized)
844 6 : nao = mos(1)%nao
845 6 : rst_unit = -1
846 :
847 : output_unit = cp_print_key_unit_nr(logger, section2, &
848 6 : "PROGRAM_RUN_INFO", extension=".Log")
849 :
850 6 : my_do_mixed = .FALSE.
851 6 : IF (PRESENT(do_mixed)) my_do_mixed = do_mixed
852 6 : IF (do_homo) THEN
853 6 : fname_key = "LOCHOMO_RESTART_FILE_NAME"
854 0 : ELSEIF (my_do_mixed) THEN
855 0 : fname_key = "LOCMIXD_RESTART_FILE_NAME"
856 : ELSE
857 0 : fname_key = "LOCLUMO_RESTART_FILE_NAME"
858 0 : IF (.NOT. PRESENT(evals)) &
859 0 : CPABORT("Missing argument to localize unoccupied states.")
860 : END IF
861 :
862 6 : file_exists = .FALSE.
863 6 : CALL section_vals_val_get(section, fname_key, n_rep_val=n_rep_val)
864 6 : IF (n_rep_val > 0) THEN
865 0 : CALL section_vals_val_get(section, fname_key, c_val=filename)
866 : ELSE
867 :
868 6 : print_key => section_vals_get_subs_vals(section2, "LOC_RESTART")
869 6 : IF (do_homo) THEN
870 6 : my_middle = "LOC_HOMO"
871 0 : ELSEIF (my_do_mixed) THEN
872 0 : my_middle = "LOC_MIXED"
873 : ELSE
874 0 : my_middle = "LOC_LUMO"
875 : END IF
876 : filename = cp_print_key_generate_filename(logger, print_key, &
877 : middle_name=TRIM(my_middle), extension=".wfn", &
878 6 : my_local=.FALSE.)
879 : END IF
880 :
881 6 : IF (para_env%is_source()) INQUIRE (FILE=filename, exist=file_exists)
882 :
883 6 : IF (file_exists) THEN
884 2 : IF (para_env%is_source()) THEN
885 : CALL open_file(file_name=filename, &
886 : file_action="READ", &
887 : file_form="UNFORMATTED", &
888 : file_status="OLD", &
889 2 : unit_number=rst_unit)
890 :
891 2 : READ (rst_unit) qs_loc_env%localized_wfn_control%set_of_states
892 2 : READ (rst_unit) qs_loc_env%localized_wfn_control%lu_bound_states
893 2 : READ (rst_unit) qs_loc_env%localized_wfn_control%nloc_states
894 : END IF
895 : ELSE
896 4 : IF (output_unit > 0) WRITE (output_unit, "(/,T10,A)") &
897 1 : "Restart file not available filename=<"//TRIM(filename)//'>'
898 : END IF
899 6 : CALL para_env%bcast(file_exists)
900 :
901 6 : IF (file_exists) THEN
902 4 : restart_found = .TRUE.
903 :
904 4 : CALL para_env%bcast(qs_loc_env%localized_wfn_control%set_of_states)
905 4 : CALL para_env%bcast(qs_loc_env%localized_wfn_control%lu_bound_states)
906 4 : CALL para_env%bcast(qs_loc_env%localized_wfn_control%nloc_states)
907 :
908 12 : max_nloc = MAXVAL(qs_loc_env%localized_wfn_control%nloc_states(:))
909 :
910 12 : ALLOCATE (vecbuffer(1, nao))
911 4 : IF (ASSOCIATED(qs_loc_env%localized_wfn_control%loc_states)) THEN
912 2 : DEALLOCATE (qs_loc_env%localized_wfn_control%loc_states)
913 : END IF
914 12 : ALLOCATE (qs_loc_env%localized_wfn_control%loc_states(max_nloc, 2))
915 56 : qs_loc_env%localized_wfn_control%loc_states = 0
916 :
917 10 : DO ispin = 1, nspin
918 6 : IF (do_homo .OR. do_mixed) THEN
919 6 : nmo = mos(ispin)%nmo
920 : ELSE
921 0 : nmo = SIZE(evals(ispin)%array, 1)
922 : END IF
923 6 : IF (para_env%is_source() .AND. (nmo > 0)) THEN
924 3 : nloc = qs_loc_env%localized_wfn_control%nloc_states(ispin)
925 3 : READ (rst_unit) qs_loc_env%localized_wfn_control%loc_states(1:nloc, ispin)
926 3 : IF (do_homo .OR. do_mixed) THEN
927 3 : READ (rst_unit) nmo_read, homo_read, lfomo_read, nelectron_read
928 12 : ALLOCATE (eig_read(nmo_read), occ_read(nmo_read))
929 79 : eig_read = 0.0_dp
930 79 : occ_read = 0.0_dp
931 3 : READ (rst_unit) eig_read(1:nmo_read), occ_read(1:nmo_read)
932 : ELSE
933 0 : READ (rst_unit) nmo_read
934 0 : ALLOCATE (eig_read(nmo_read))
935 0 : eig_read = 0.0_dp
936 0 : READ (rst_unit) eig_read(1:nmo_read)
937 : END IF
938 3 : IF (nmo_read < nmo) &
939 : CALL cp_warn(__LOCATION__, &
940 : "The number of MOs on the restart unit is smaller than the number of "// &
941 0 : "the allocated MOs. ")
942 3 : IF (nmo_read > nmo) &
943 : CALL cp_warn(__LOCATION__, &
944 : "The number of MOs on the restart unit is greater than the number of "// &
945 0 : "the allocated MOs. The read MO set will be truncated!")
946 :
947 3 : nmo = MIN(nmo, nmo_read)
948 3 : IF (do_homo .OR. do_mixed) THEN
949 79 : mos(ispin)%eigenvalues(1:nmo) = eig_read(1:nmo)
950 79 : mos(ispin)%occupation_numbers(1:nmo) = occ_read(1:nmo)
951 3 : DEALLOCATE (eig_read, occ_read)
952 : ELSE
953 0 : evals(ispin)%array(1:nmo) = eig_read(1:nmo)
954 0 : DEALLOCATE (eig_read)
955 : END IF
956 :
957 : END IF
958 6 : IF (do_homo .OR. do_mixed) THEN
959 310 : CALL para_env%bcast(mos(ispin)%eigenvalues)
960 310 : CALL para_env%bcast(mos(ispin)%occupation_numbers)
961 : ELSE
962 0 : CALL para_env%bcast(evals(ispin)%array)
963 : END IF
964 :
965 162 : DO i = 1, nmo
966 152 : IF (para_env%is_source()) THEN
967 15236 : READ (rst_unit) vecbuffer
968 : ELSE
969 7656 : vecbuffer(1, :) = 0.0_dp
970 : END IF
971 60792 : CALL para_env%bcast(vecbuffer)
972 : CALL cp_fm_set_submatrix(mos_localized(ispin), &
973 158 : vecbuffer, 1, i, nao, 1, transpose=.TRUE.)
974 : END DO
975 : END DO
976 :
977 108 : CALL para_env%bcast(qs_loc_env%localized_wfn_control%loc_states)
978 :
979 4 : DEALLOCATE (vecbuffer)
980 :
981 : END IF
982 :
983 : ! Close restart file
984 6 : IF (para_env%is_source()) THEN
985 3 : IF (file_exists) CALL close_file(unit_number=rst_unit)
986 : END IF
987 :
988 6 : CALL timestop(handle)
989 :
990 12 : END SUBROUTINE loc_read_restart
991 :
992 : ! **************************************************************************************************
993 : !> \brief initializes everything needed for localization of the HOMOs
994 : !> \param qs_loc_env ...
995 : !> \param loc_section ...
996 : !> \param do_homo ...
997 : !> \param do_mixed ...
998 : !> \param do_xas ...
999 : !> \param nloc_xas ...
1000 : !> \param spin_xas ...
1001 : !> \par History
1002 : !> 2009 created
1003 : ! **************************************************************************************************
1004 384 : SUBROUTINE qs_loc_control_init(qs_loc_env, loc_section, do_homo, do_mixed, &
1005 : do_xas, nloc_xas, spin_xas)
1006 :
1007 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
1008 : TYPE(section_vals_type), POINTER :: loc_section
1009 : LOGICAL, INTENT(IN) :: do_homo
1010 : LOGICAL, INTENT(IN), OPTIONAL :: do_mixed, do_xas
1011 : INTEGER, INTENT(IN), OPTIONAL :: nloc_xas, spin_xas
1012 :
1013 : LOGICAL :: my_do_mixed
1014 : TYPE(localized_wfn_control_type), POINTER :: localized_wfn_control
1015 :
1016 384 : NULLIFY (localized_wfn_control)
1017 :
1018 384 : IF (PRESENT(do_mixed)) THEN
1019 2 : my_do_mixed = do_mixed
1020 : ELSE
1021 382 : my_do_mixed = .FALSE.
1022 : END IF
1023 384 : CALL localized_wfn_control_create(localized_wfn_control)
1024 384 : CALL set_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
1025 384 : CALL localized_wfn_control_release(localized_wfn_control)
1026 384 : CALL get_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
1027 384 : localized_wfn_control%do_homo = do_homo
1028 384 : localized_wfn_control%do_mixed = my_do_mixed
1029 : CALL read_loc_section(localized_wfn_control, loc_section, qs_loc_env%do_localize, &
1030 384 : my_do_mixed, do_xas, nloc_xas, spin_xas)
1031 :
1032 384 : END SUBROUTINE qs_loc_control_init
1033 :
1034 : ! **************************************************************************************************
1035 : !> \brief initializes everything needed for localization of the molecular orbitals
1036 : !> \param qs_env ...
1037 : !> \param qs_loc_env ...
1038 : !> \param localize_section ...
1039 : !> \param mos_localized ...
1040 : !> \param do_homo ...
1041 : !> \param do_mo_cubes ...
1042 : !> \param mo_loc_history ...
1043 : !> \param evals ...
1044 : !> \param tot_zeff_corr ...
1045 : !> \param do_mixed ...
1046 : ! **************************************************************************************************
1047 294 : SUBROUTINE qs_loc_init(qs_env, qs_loc_env, localize_section, mos_localized, &
1048 : do_homo, do_mo_cubes, mo_loc_history, evals, &
1049 : tot_zeff_corr, do_mixed)
1050 :
1051 : TYPE(qs_environment_type), POINTER :: qs_env
1052 : TYPE(qs_loc_env_type), POINTER :: qs_loc_env
1053 : TYPE(section_vals_type), POINTER :: localize_section
1054 : TYPE(cp_fm_type), DIMENSION(:), INTENT(INOUT) :: mos_localized
1055 : LOGICAL, OPTIONAL :: do_homo, do_mo_cubes
1056 : TYPE(cp_fm_type), DIMENSION(:), OPTIONAL, POINTER :: mo_loc_history
1057 : TYPE(cp_1d_r_p_type), DIMENSION(:), OPTIONAL, &
1058 : POINTER :: evals
1059 : REAL(KIND=dp), INTENT(IN), OPTIONAL :: tot_zeff_corr
1060 : LOGICAL, OPTIONAL :: do_mixed
1061 :
1062 : CHARACTER(len=*), PARAMETER :: routineN = 'qs_loc_init'
1063 :
1064 : INTEGER :: handle, homo, i, ilast_intocc, ilow, ispin, iup, n_mo(2), n_mos(2), nao, &
1065 : nelectron, nextra, nmoloc(2), nocc, npocc, nspin, output_unit
1066 : LOGICAL :: my_do_homo, my_do_mixed, my_do_mo_cubes, &
1067 : restart_found
1068 : REAL(KIND=dp) :: maxocc, my_tot_zeff_corr
1069 294 : REAL(KIND=dp), DIMENSION(:), POINTER :: mo_eigenvalues, occupation
1070 : TYPE(cp_fm_type), POINTER :: mo_coeff
1071 : TYPE(cp_logger_type), POINTER :: logger
1072 294 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: ks_rmpv, mo_derivs
1073 : TYPE(dft_control_type), POINTER :: dft_control
1074 : TYPE(localized_wfn_control_type), POINTER :: localized_wfn_control
1075 294 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1076 : TYPE(mp_para_env_type), POINTER :: para_env
1077 : TYPE(scf_control_type), POINTER :: scf_control
1078 : TYPE(section_vals_type), POINTER :: loc_print_section
1079 :
1080 294 : CALL timeset(routineN, handle)
1081 :
1082 294 : NULLIFY (mos, mo_coeff, mo_eigenvalues, occupation, ks_rmpv, mo_derivs, scf_control, para_env)
1083 : CALL get_qs_env(qs_env, &
1084 : mos=mos, &
1085 : matrix_ks=ks_rmpv, &
1086 : mo_derivs=mo_derivs, &
1087 : scf_control=scf_control, &
1088 : dft_control=dft_control, &
1089 294 : para_env=para_env)
1090 :
1091 294 : loc_print_section => section_vals_get_subs_vals(localize_section, "PRINT")
1092 :
1093 294 : logger => cp_get_default_logger()
1094 294 : output_unit = cp_logger_get_default_io_unit(logger)
1095 :
1096 294 : nspin = SIZE(mos)
1097 294 : IF (PRESENT(do_homo)) THEN
1098 294 : my_do_homo = do_homo
1099 : ELSE
1100 0 : my_do_homo = .TRUE.
1101 : END IF
1102 294 : IF (PRESENT(do_mo_cubes)) THEN
1103 104 : my_do_mo_cubes = do_mo_cubes
1104 : ELSE
1105 : my_do_mo_cubes = .FALSE.
1106 : END IF
1107 294 : IF (PRESENT(do_mixed)) THEN
1108 2 : my_do_mixed = do_mixed
1109 : ELSE
1110 292 : my_do_mixed = .FALSE.
1111 : END IF
1112 294 : IF (PRESENT(tot_zeff_corr)) THEN
1113 2 : my_tot_zeff_corr = tot_zeff_corr
1114 : ELSE
1115 292 : my_tot_zeff_corr = 0.0_dp
1116 : END IF
1117 294 : restart_found = .FALSE.
1118 :
1119 294 : IF (qs_loc_env%do_localize) THEN
1120 : ! Some setup for MOs to be localized
1121 278 : CALL get_qs_loc_env(qs_loc_env, localized_wfn_control=localized_wfn_control)
1122 278 : IF (localized_wfn_control%loc_restart) THEN
1123 6 : IF (localized_wfn_control%nextra > 0) THEN
1124 : ! currently only the occupied guess is read
1125 0 : my_do_homo = .FALSE.
1126 : END IF
1127 : CALL loc_read_restart(qs_loc_env, mos, mos_localized, localize_section, &
1128 : loc_print_section, para_env, my_do_homo, restart_found, evals=evals, &
1129 6 : do_mixed=my_do_mixed)
1130 9 : IF (output_unit > 0) WRITE (output_unit, "(/,T2,A,A)") "LOCALIZATION| ", &
1131 6 : " The orbitals to be localized are read from localization restart file."
1132 18 : nmoloc = localized_wfn_control%nloc_states
1133 18 : localized_wfn_control%nguess = nmoloc
1134 6 : IF (localized_wfn_control%nextra > 0) THEN
1135 : ! reset different variables in localized_wfn_control:
1136 : ! lu_bound_states, nloc_states, loc_states
1137 0 : localized_wfn_control%loc_restart = restart_found
1138 0 : localized_wfn_control%set_of_states = state_loc_mixed
1139 0 : DO ispin = 1, nspin
1140 : CALL get_mo_set(mos(ispin), homo=homo, occupation_numbers=occupation, &
1141 0 : maxocc=maxocc)
1142 0 : nextra = localized_wfn_control%nextra
1143 0 : nocc = homo
1144 0 : DO i = nocc, 1, -1
1145 0 : IF (maxocc - occupation(i) < localized_wfn_control%eps_occ) THEN
1146 0 : ilast_intocc = i
1147 0 : EXIT
1148 : END IF
1149 : END DO
1150 0 : nocc = ilast_intocc
1151 0 : npocc = homo - nocc
1152 0 : nmoloc(ispin) = nocc + nextra
1153 0 : localized_wfn_control%lu_bound_states(1, ispin) = 1
1154 0 : localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
1155 0 : localized_wfn_control%nloc_states(ispin) = nmoloc(ispin)
1156 : END DO
1157 0 : my_do_homo = .FALSE.
1158 : END IF
1159 : END IF
1160 278 : IF (.NOT. restart_found) THEN
1161 274 : nmoloc = 0
1162 648 : DO ispin = 1, nspin
1163 : CALL get_mo_set(mos(ispin), nmo=n_mo(ispin), nelectron=nelectron, homo=homo, nao=nao, &
1164 : mo_coeff=mo_coeff, eigenvalues=mo_eigenvalues, occupation_numbers=occupation, &
1165 374 : maxocc=maxocc)
1166 : ! Get eigenstates (only needed if not already calculated before)
1167 : IF ((.NOT. my_do_mo_cubes) &
1168 : ! .OR. section_get_ival(dft_section,"PRINT%MO_CUBES%NHOMO")==0)&
1169 374 : .AND. my_do_homo .AND. qs_env%scf_env%method == ot_method_nr .AND. (.NOT. dft_control%restricted)) THEN
1170 30 : CALL make_mo_eig(mos, nspin, ks_rmpv, scf_control, mo_derivs)
1171 : END IF
1172 1022 : IF (localized_wfn_control%set_of_states == state_loc_all .AND. my_do_homo) THEN
1173 334 : nmoloc(ispin) = NINT(nelectron/occupation(1))
1174 334 : IF (n_mo(ispin) > homo) THEN
1175 30 : DO i = nmoloc(ispin), 1, -1
1176 30 : IF (occupation(1) - occupation(i) < localized_wfn_control%eps_occ) THEN
1177 14 : ilast_intocc = i
1178 14 : EXIT
1179 : END IF
1180 : END DO
1181 : ELSE
1182 320 : ilast_intocc = nmoloc(ispin)
1183 : END IF
1184 334 : nmoloc(ispin) = ilast_intocc
1185 334 : localized_wfn_control%lu_bound_states(1, ispin) = 1
1186 334 : localized_wfn_control%lu_bound_states(2, ispin) = ilast_intocc
1187 334 : IF (nmoloc(ispin) /= n_mo(ispin)) THEN
1188 14 : IF (output_unit > 0) &
1189 : WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,F12.6,A,F12.6,A)") &
1190 7 : "LOCALIZATION| Spin ", ispin, " The first ", &
1191 7 : ilast_intocc, " occupied orbitals are localized,", " with energies from ", &
1192 14 : mo_eigenvalues(1), " to ", mo_eigenvalues(ilast_intocc), " [a.u.]."
1193 : END IF
1194 40 : ELSE IF (localized_wfn_control%set_of_states == energy_loc_range .AND. my_do_homo) THEN
1195 12 : ilow = 0
1196 12 : iup = 0
1197 20 : DO i = 1, n_mo(ispin)
1198 20 : IF (mo_eigenvalues(i) >= localized_wfn_control%lu_ene_bound(1)) THEN
1199 : ilow = i
1200 : EXIT
1201 : END IF
1202 : END DO
1203 324 : DO i = n_mo(ispin), 1, -1
1204 324 : IF (mo_eigenvalues(i) <= localized_wfn_control%lu_ene_bound(2)) THEN
1205 : iup = i
1206 : EXIT
1207 : END IF
1208 : END DO
1209 12 : localized_wfn_control%lu_bound_states(1, ispin) = ilow
1210 12 : localized_wfn_control%lu_bound_states(2, ispin) = iup
1211 12 : localized_wfn_control%nloc_states(ispin) = iup - ilow + 1
1212 12 : nmoloc(ispin) = localized_wfn_control%nloc_states(ispin)
1213 12 : IF (occupation(ilow) - occupation(iup) > localized_wfn_control%eps_occ) THEN
1214 : CALL cp_abort(__LOCATION__, &
1215 : "The selected energy range includes orbitals with different occupation number. "// &
1216 0 : "The localization procedure cannot be applied.")
1217 : END IF
1218 18 : IF (output_unit > 0) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", ispin, " : ", &
1219 12 : nmoloc(ispin), " orbitals in the selected energy range are localized."
1220 28 : ELSE IF (localized_wfn_control%set_of_states == state_loc_all .AND. (.NOT. my_do_homo)) THEN
1221 0 : nmoloc(ispin) = n_mo(ispin) - homo
1222 0 : localized_wfn_control%lu_bound_states(1, ispin) = homo + 1
1223 0 : localized_wfn_control%lu_bound_states(2, ispin) = n_mo(ispin)
1224 0 : IF (output_unit > 0) &
1225 : WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,F12.6,A,F12.6,A)") &
1226 0 : "LOCALIZATION| Spin ", ispin, " The first ", &
1227 0 : nmoloc(ispin), " virtual orbitals are localized,", " with energies from ", &
1228 0 : mo_eigenvalues(homo + 1), " to ", mo_eigenvalues(n_mo(ispin)), " [a.u.]."
1229 28 : ELSE IF (localized_wfn_control%set_of_states == state_loc_mixed) THEN
1230 2 : nextra = localized_wfn_control%nextra
1231 2 : nocc = homo
1232 6 : DO i = nocc, 1, -1
1233 6 : IF (maxocc - occupation(i) < localized_wfn_control%eps_occ) THEN
1234 2 : ilast_intocc = i
1235 2 : EXIT
1236 : END IF
1237 : END DO
1238 2 : nocc = ilast_intocc
1239 2 : npocc = homo - nocc
1240 2 : nmoloc(ispin) = nocc + nextra
1241 2 : localized_wfn_control%lu_bound_states(1, ispin) = 1
1242 2 : localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
1243 2 : IF (output_unit > 0) &
1244 : WRITE (output_unit, "(/,T2,A,I4,A,I6,A,/,T15,A,I6,/,T15,A,I6,/,T15,A,I6,/,T15,A,F12.6,A)") &
1245 1 : "LOCALIZATION| Spin ", ispin, " The first ", &
1246 1 : nmoloc(ispin), " orbitals are localized.", &
1247 1 : "Number of fully occupied MOs: ", nocc, &
1248 1 : "Number of partially occupied MOs: ", npocc, &
1249 1 : "Number of extra degrees of freedom: ", nextra, &
1250 2 : "Excess charge: ", my_tot_zeff_corr, " electrons"
1251 : ELSE
1252 26 : nmoloc(ispin) = MIN(localized_wfn_control%nloc_states(1), n_mo(ispin))
1253 33 : IF (output_unit > 0 .AND. my_do_homo) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", ispin, &
1254 14 : " : ", nmoloc(ispin), " occupied orbitals are localized, as given in the input list."
1255 19 : IF (output_unit > 0 .AND. (.NOT. my_do_homo)) WRITE (output_unit, "(/,T2,A,I4,A,I6,A)") "LOCALIZATION| Spin ", &
1256 12 : ispin, " : ", nmoloc(ispin), " unoccupied orbitals are localized, as given in the input list."
1257 26 : IF (n_mo(ispin) > homo .AND. my_do_homo) THEN
1258 8 : ilow = localized_wfn_control%loc_states(1, ispin)
1259 56 : DO i = 2, nmoloc(ispin)
1260 48 : iup = localized_wfn_control%loc_states(i, ispin)
1261 56 : IF (ABS(occupation(ilow) - occupation(iup)) > localized_wfn_control%eps_occ) THEN
1262 : ! write warning
1263 : CALL cp_warn(__LOCATION__, &
1264 : "User requested the calculation of localized wavefunction from a subset of MOs, "// &
1265 : "including MOs with different occupations. Check the selected subset, "// &
1266 : "the electronic density is not invariant with "// &
1267 0 : "respect to rotations among orbitals with different occupation numbers!")
1268 : END IF
1269 : END DO
1270 : END IF
1271 : END IF
1272 : END DO ! ispin
1273 822 : n_mos(:) = nao - n_mo(:)
1274 274 : IF (my_do_homo .OR. my_do_mixed) n_mos = n_mo
1275 274 : CALL set_loc_wfn_lists(localized_wfn_control, nmoloc, n_mos, nspin)
1276 : END IF
1277 278 : CALL set_loc_centers(localized_wfn_control, nmoloc, nspin)
1278 278 : IF (my_do_homo .OR. my_do_mixed) THEN
1279 : CALL qs_loc_env_init(qs_loc_env, localized_wfn_control, qs_env, &
1280 272 : loc_coeff=mos_localized, mo_loc_history=mo_loc_history)
1281 : END IF
1282 : ELSE
1283 : ! Let's inform in case the section is not present in the input
1284 : CALL cp_warn(__LOCATION__, &
1285 : "User requested the calculation of the localized wavefunction but the section "// &
1286 16 : "LOCALIZE was not specified. Localization will not be performed!")
1287 : END IF
1288 :
1289 294 : CALL timestop(handle)
1290 :
1291 294 : END SUBROUTINE qs_loc_init
1292 :
1293 : ! **************************************************************************************************
1294 : !> \brief read the controlparameter from input, using the new input scheme
1295 : !> \param localized_wfn_control ...
1296 : !> \param loc_section ...
1297 : !> \param localize ...
1298 : !> \param do_mixed ...
1299 : !> \param do_xas ...
1300 : !> \param nloc_xas ...
1301 : !> \param spin_channel_xas ...
1302 : !> \par History
1303 : !> 05.2005 created [MI]
1304 : ! **************************************************************************************************
1305 768 : SUBROUTINE read_loc_section(localized_wfn_control, loc_section, &
1306 : localize, do_mixed, do_xas, nloc_xas, spin_channel_xas)
1307 :
1308 : TYPE(localized_wfn_control_type), POINTER :: localized_wfn_control
1309 : TYPE(section_vals_type), POINTER :: loc_section
1310 : LOGICAL, INTENT(OUT) :: localize
1311 : LOGICAL, INTENT(IN), OPTIONAL :: do_mixed, do_xas
1312 : INTEGER, INTENT(IN), OPTIONAL :: nloc_xas, spin_channel_xas
1313 :
1314 : INTEGER :: i, ind, ir, n_list, n_rep, n_state, &
1315 : nextra, nline, other_spin, &
1316 : output_unit, spin_xas
1317 384 : INTEGER, DIMENSION(:), POINTER :: list, loc_list
1318 : LOGICAL :: my_do_mixed, my_do_xas
1319 384 : REAL(dp), POINTER :: ene(:)
1320 : TYPE(cp_logger_type), POINTER :: logger
1321 : TYPE(section_vals_type), POINTER :: loc_print_section
1322 :
1323 384 : my_do_xas = .FALSE.
1324 384 : spin_xas = 1
1325 384 : IF (PRESENT(do_xas)) THEN
1326 90 : my_do_xas = do_xas
1327 90 : CPASSERT(PRESENT(nloc_xas))
1328 : END IF
1329 384 : IF (PRESENT(spin_channel_xas)) spin_xas = spin_channel_xas
1330 384 : my_do_mixed = .FALSE.
1331 384 : IF (PRESENT(do_mixed)) THEN
1332 384 : my_do_mixed = do_mixed
1333 : END IF
1334 384 : CPASSERT(ASSOCIATED(loc_section))
1335 384 : NULLIFY (logger)
1336 384 : logger => cp_get_default_logger()
1337 :
1338 384 : CALL section_vals_val_get(loc_section, "_SECTION_PARAMETERS_", l_val=localize)
1339 384 : IF (localize) THEN
1340 352 : loc_print_section => section_vals_get_subs_vals(loc_section, "PRINT")
1341 352 : NULLIFY (list)
1342 352 : NULLIFY (loc_list)
1343 2464 : localized_wfn_control%lu_bound_states = 0
1344 1056 : localized_wfn_control%lu_ene_bound = 0.0_dp
1345 1056 : localized_wfn_control%nloc_states = 0
1346 352 : localized_wfn_control%set_of_states = 0
1347 352 : localized_wfn_control%nextra = 0
1348 352 : n_state = 0
1349 :
1350 : CALL section_vals_val_get(loc_section, "MAX_ITER", &
1351 352 : i_val=localized_wfn_control%max_iter)
1352 : CALL section_vals_val_get(loc_section, "MAX_CRAZY_ANGLE", &
1353 352 : r_val=localized_wfn_control%max_crazy_angle)
1354 : CALL section_vals_val_get(loc_section, "CRAZY_SCALE", &
1355 352 : r_val=localized_wfn_control%crazy_scale)
1356 : CALL section_vals_val_get(loc_section, "EPS_OCCUPATION", &
1357 352 : r_val=localized_wfn_control%eps_occ)
1358 : CALL section_vals_val_get(loc_section, "CRAZY_USE_DIAG", &
1359 352 : l_val=localized_wfn_control%crazy_use_diag)
1360 : CALL section_vals_val_get(loc_section, "OUT_ITER_EACH", &
1361 352 : i_val=localized_wfn_control%out_each)
1362 : CALL section_vals_val_get(loc_section, "EPS_LOCALIZATION", &
1363 352 : r_val=localized_wfn_control%eps_localization)
1364 : CALL section_vals_val_get(loc_section, "MIN_OR_MAX", &
1365 352 : i_val=localized_wfn_control%min_or_max)
1366 : CALL section_vals_val_get(loc_section, "JACOBI_FALLBACK", &
1367 352 : l_val=localized_wfn_control%jacobi_fallback)
1368 : CALL section_vals_val_get(loc_section, "JACOBI_REFINEMENT", &
1369 352 : l_val=localized_wfn_control%jacobi_refinement)
1370 : CALL section_vals_val_get(loc_section, "METHOD", &
1371 352 : i_val=localized_wfn_control%localization_method)
1372 : CALL section_vals_val_get(loc_section, "OPERATOR", &
1373 352 : i_val=localized_wfn_control%operator_type)
1374 : CALL section_vals_val_get(loc_section, "RESTART", &
1375 352 : l_val=localized_wfn_control%loc_restart)
1376 : CALL section_vals_val_get(loc_section, "USE_HISTORY", &
1377 352 : l_val=localized_wfn_control%use_history)
1378 : CALL section_vals_val_get(loc_section, "NEXTRA", &
1379 352 : i_val=localized_wfn_control%nextra)
1380 : CALL section_vals_val_get(loc_section, "CPO_GUESS", &
1381 352 : i_val=localized_wfn_control%coeff_po_guess)
1382 : CALL section_vals_val_get(loc_section, "CPO_GUESS_SPACE", &
1383 352 : i_val=localized_wfn_control%coeff_po_guess_mo_space)
1384 : CALL section_vals_val_get(loc_section, "CG_PO", &
1385 352 : l_val=localized_wfn_control%do_cg_po)
1386 :
1387 352 : IF (localized_wfn_control%do_homo) THEN
1388 : ! List of States HOMO
1389 344 : CALL section_vals_val_get(loc_section, "LIST", n_rep_val=n_rep)
1390 344 : IF (n_rep > 0) THEN
1391 14 : n_list = 0
1392 28 : DO ir = 1, n_rep
1393 14 : NULLIFY (list)
1394 14 : CALL section_vals_val_get(loc_section, "LIST", i_rep_val=ir, i_vals=list)
1395 28 : IF (ASSOCIATED(list)) THEN
1396 14 : CALL reallocate(loc_list, 1, n_list + SIZE(list))
1397 90 : DO i = 1, SIZE(list)
1398 90 : loc_list(n_list + i) = list(i)
1399 : END DO ! i
1400 14 : n_list = n_list + SIZE(list)
1401 : END IF
1402 : END DO ! ir
1403 14 : IF (n_list /= 0) THEN
1404 14 : localized_wfn_control%set_of_states = state_loc_list
1405 42 : ALLOCATE (localized_wfn_control%loc_states(n_list, 2))
1406 194 : localized_wfn_control%loc_states = 0
1407 180 : localized_wfn_control%loc_states(:, 1) = loc_list(:)
1408 180 : localized_wfn_control%loc_states(:, 2) = loc_list(:)
1409 14 : localized_wfn_control%nloc_states(1) = n_list
1410 14 : localized_wfn_control%nloc_states(2) = n_list
1411 14 : IF (my_do_xas) THEN
1412 4 : other_spin = 2
1413 4 : IF (spin_xas == 2) other_spin = 1
1414 4 : localized_wfn_control%nloc_states(other_spin) = 0
1415 22 : localized_wfn_control%loc_states(:, other_spin) = 0
1416 : END IF
1417 14 : DEALLOCATE (loc_list)
1418 : END IF
1419 : END IF
1420 :
1421 : ELSE
1422 : ! List of States LUMO
1423 8 : CALL section_vals_val_get(loc_section, "LIST_UNOCCUPIED", n_rep_val=n_rep)
1424 8 : IF (n_rep > 0) THEN
1425 6 : n_list = 0
1426 12 : DO ir = 1, n_rep
1427 6 : NULLIFY (list)
1428 6 : CALL section_vals_val_get(loc_section, "LIST_UNOCCUPIED", i_rep_val=ir, i_vals=list)
1429 12 : IF (ASSOCIATED(list)) THEN
1430 6 : CALL reallocate(loc_list, 1, n_list + SIZE(list))
1431 46 : DO i = 1, SIZE(list)
1432 46 : loc_list(n_list + i) = list(i)
1433 : END DO ! i
1434 6 : n_list = n_list + SIZE(list)
1435 : END IF
1436 : END DO ! ir
1437 6 : IF (n_list /= 0) THEN
1438 6 : localized_wfn_control%set_of_states = state_loc_list
1439 18 : ALLOCATE (localized_wfn_control%loc_states(n_list, 2))
1440 98 : localized_wfn_control%loc_states = 0
1441 92 : localized_wfn_control%loc_states(:, 1) = loc_list(:)
1442 92 : localized_wfn_control%loc_states(:, 2) = loc_list(:)
1443 6 : localized_wfn_control%nloc_states(1) = n_list
1444 6 : DEALLOCATE (loc_list)
1445 : END IF
1446 : END IF
1447 : END IF
1448 :
1449 352 : IF (localized_wfn_control%set_of_states == 0) THEN
1450 332 : CALL section_vals_val_get(loc_section, "ENERGY_RANGE", r_vals=ene)
1451 332 : IF (ene(1) /= ene(2)) THEN
1452 10 : localized_wfn_control%set_of_states = energy_loc_range
1453 10 : localized_wfn_control%lu_ene_bound(1) = ene(1)
1454 10 : localized_wfn_control%lu_ene_bound(2) = ene(2)
1455 : END IF
1456 : END IF
1457 :
1458 : ! All States or XAS specific states
1459 352 : IF (localized_wfn_control%set_of_states == 0) THEN
1460 322 : IF (my_do_xas) THEN
1461 70 : localized_wfn_control%set_of_states = state_loc_range
1462 210 : localized_wfn_control%nloc_states(:) = 0
1463 210 : localized_wfn_control%lu_bound_states(1, :) = 0
1464 210 : localized_wfn_control%lu_bound_states(2, :) = 0
1465 70 : localized_wfn_control%nloc_states(spin_xas) = nloc_xas
1466 70 : localized_wfn_control%lu_bound_states(1, spin_xas) = 1
1467 70 : localized_wfn_control%lu_bound_states(2, spin_xas) = nloc_xas
1468 252 : ELSE IF (my_do_mixed) THEN
1469 2 : localized_wfn_control%set_of_states = state_loc_mixed
1470 2 : nextra = localized_wfn_control%nextra
1471 : ELSE
1472 250 : localized_wfn_control%set_of_states = state_loc_all
1473 : END IF
1474 : END IF
1475 :
1476 : localized_wfn_control%print_centers = &
1477 : BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
1478 352 : "WANNIER_CENTERS"), cp_p_file)
1479 : localized_wfn_control%print_spreads = &
1480 : BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
1481 352 : "WANNIER_SPREADS"), cp_p_file)
1482 : localized_wfn_control%print_cubes = &
1483 : BTEST(cp_print_key_should_output(logger%iter_info, loc_print_section, &
1484 352 : "WANNIER_CUBES"), cp_p_file)
1485 :
1486 : output_unit = cp_print_key_unit_nr(logger, loc_print_section, "PROGRAM_RUN_INFO", &
1487 352 : extension=".Log")
1488 :
1489 352 : IF (output_unit > 0) THEN
1490 : WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
1491 176 : "LOCALIZE| The spread relative to a set of orbitals is computed"
1492 :
1493 301 : SELECT CASE (localized_wfn_control%set_of_states)
1494 : CASE (state_loc_all)
1495 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1496 125 : "LOCALIZE| Orbitals to be localized: All orbitals"
1497 : WRITE (UNIT=output_unit, FMT="(T2,A,/,T12,A,F16.8)") &
1498 125 : "LOCALIZE| If fractional occupation, fully occupied MOs are those ", &
1499 250 : "within occupation tolerance of ", localized_wfn_control%eps_occ
1500 : CASE (state_loc_range)
1501 : WRITE (UNIT=output_unit, FMT="(T2,A,T65,I8,A,I8)") &
1502 35 : "LOCALIZE| Orbitals to be localized: Those with index between ", &
1503 35 : localized_wfn_control%lu_bound_states(1, spin_xas), " and ", &
1504 70 : localized_wfn_control%lu_bound_states(2, spin_xas)
1505 : CASE (state_loc_list)
1506 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1507 10 : "LOCALIZE| Orbitals to be localized: Those with index in the following list"
1508 10 : nline = localized_wfn_control%nloc_states(1)/10 + 1
1509 10 : ind = 0
1510 21 : DO i = 1, nline
1511 21 : IF (ind + 10 < localized_wfn_control%nloc_states(1)) THEN
1512 1 : WRITE (UNIT=output_unit, FMT="(T8,10I7)") localized_wfn_control%loc_states(ind + 1:ind + 10, 1)
1513 1 : ind = ind + 10
1514 : ELSE
1515 : WRITE (UNIT=output_unit, FMT="(T8,10I7)") &
1516 10 : localized_wfn_control%loc_states(ind + 1:localized_wfn_control%nloc_states(1), 1)
1517 10 : ind = localized_wfn_control%nloc_states(1)
1518 : END IF
1519 : END DO
1520 : CASE (energy_loc_range)
1521 : WRITE (UNIT=output_unit, FMT="(T2,A,T65,/,f16.6,A,f16.6,A)") &
1522 5 : "LOCALIZE| Orbitals to be localized: Those with energy in the range between ", &
1523 10 : localized_wfn_control%lu_ene_bound(1), " and ", localized_wfn_control%lu_ene_bound(2), " a.u."
1524 : CASE (state_loc_mixed)
1525 : WRITE (UNIT=output_unit, FMT="(T2,A,I4,A)") &
1526 1 : "LOCALIZE| Orbitals to be localized: Occupied orbitals + ", nextra, " orbitals"
1527 : CASE DEFAULT
1528 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1529 176 : "LOCALIZE| Orbitals to be localized: None "
1530 : END SELECT
1531 :
1532 352 : SELECT CASE (localized_wfn_control%operator_type)
1533 : CASE (op_loc_berry)
1534 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1535 176 : "LOCALIZE| Spread defined by the Berry phase operator "
1536 : CASE (op_loc_boys)
1537 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1538 0 : "LOCALIZE| Spread defined by the Boys phase operator "
1539 : CASE DEFAULT
1540 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1541 176 : "LOCALIZE| Spread defined by the Pipek phase operator "
1542 : END SELECT
1543 :
1544 311 : SELECT CASE (localized_wfn_control%localization_method)
1545 : CASE (do_loc_jacobi)
1546 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1547 135 : "LOCALIZE| Optimal unitary transformation generated by Jacobi algorithm"
1548 : CASE (do_loc_crazy)
1549 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1550 29 : "LOCALIZE| Optimal unitary transformation generated by Crazy angle algorithm"
1551 : WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
1552 29 : "LOCALIZE| maximum angle: ", localized_wfn_control%max_crazy_angle
1553 : WRITE (UNIT=output_unit, FMT="(T2,A,F16.8)") &
1554 29 : "LOCALIZE| scaling: ", localized_wfn_control%crazy_scale
1555 : WRITE (UNIT=output_unit, FMT="(T2,A,L1)") &
1556 29 : "LOCALIZE| use diag:", localized_wfn_control%crazy_use_diag
1557 : CASE (do_loc_gapo)
1558 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1559 1 : "LOCALIZE| Optimal unitary transformation generated by gradient ascent algorithm "
1560 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1561 1 : "LOCALIZE| for partially occupied wannier functions"
1562 : CASE (do_loc_direct)
1563 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1564 1 : "LOCALIZE| Optimal unitary transformation generated by direct algorithm"
1565 : CASE (do_loc_l1_norm_sd)
1566 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1567 9 : "LOCALIZE| Optimal unitary transformation generated by "
1568 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1569 9 : "LOCALIZE| steepest descent algorithm applied on an approximate l1 norm"
1570 : CASE (do_loc_none)
1571 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1572 0 : "LOCALIZE| No unitary transformation is applied"
1573 : CASE (do_loc_scdm)
1574 : WRITE (UNIT=output_unit, FMT="(T2,A)") &
1575 176 : "LOCALIZE| Pivoted QR decomposition is used to transform coefficients"
1576 : END SELECT
1577 :
1578 : END IF ! process has output_unit
1579 :
1580 352 : CALL cp_print_key_finished_output(output_unit, logger, loc_print_section, "PROGRAM_RUN_INFO")
1581 :
1582 : ELSE
1583 32 : localized_wfn_control%localization_method = do_loc_none
1584 32 : localized_wfn_control%localization_method = state_loc_none
1585 32 : localized_wfn_control%print_centers = .FALSE.
1586 32 : localized_wfn_control%print_spreads = .FALSE.
1587 32 : localized_wfn_control%print_cubes = .FALSE.
1588 : END IF
1589 :
1590 384 : END SUBROUTINE read_loc_section
1591 :
1592 : ! **************************************************************************************************
1593 : !> \brief create the center and spread array and the file names for the output
1594 : !> \param localized_wfn_control ...
1595 : !> \param nmoloc ...
1596 : !> \param nspins ...
1597 : !> \par History
1598 : !> 04.2005 created [MI]
1599 : ! **************************************************************************************************
1600 432 : SUBROUTINE set_loc_centers(localized_wfn_control, nmoloc, nspins)
1601 :
1602 : TYPE(localized_wfn_control_type) :: localized_wfn_control
1603 : INTEGER, DIMENSION(2), INTENT(IN) :: nmoloc
1604 : INTEGER, INTENT(IN) :: nspins
1605 :
1606 : INTEGER :: ispin
1607 :
1608 1018 : DO ispin = 1, nspins
1609 1716 : ALLOCATE (localized_wfn_control%centers_set(ispin)%array(6, nmoloc(ispin)))
1610 27954 : localized_wfn_control%centers_set(ispin)%array = 0.0_dp
1611 : END DO
1612 :
1613 432 : END SUBROUTINE set_loc_centers
1614 :
1615 : ! **************************************************************************************************
1616 : !> \brief create the lists of mos that are taken into account
1617 : !> \param localized_wfn_control ...
1618 : !> \param nmoloc ...
1619 : !> \param nmo ...
1620 : !> \param nspins ...
1621 : !> \param my_spin ...
1622 : !> \par History
1623 : !> 04.2005 created [MI]
1624 : ! **************************************************************************************************
1625 316 : SUBROUTINE set_loc_wfn_lists(localized_wfn_control, nmoloc, nmo, nspins, my_spin)
1626 :
1627 : TYPE(localized_wfn_control_type) :: localized_wfn_control
1628 : INTEGER, DIMENSION(2), INTENT(IN) :: nmoloc, nmo
1629 : INTEGER, INTENT(IN) :: nspins
1630 : INTEGER, INTENT(IN), OPTIONAL :: my_spin
1631 :
1632 : CHARACTER(len=*), PARAMETER :: routineN = 'set_loc_wfn_lists'
1633 :
1634 : INTEGER :: i, ispin, max_iloc, max_nmoloc, state
1635 :
1636 316 : CALL timeset(routineN, state)
1637 :
1638 948 : localized_wfn_control%nloc_states(1:2) = nmoloc(1:2)
1639 316 : max_nmoloc = MAX(nmoloc(1), nmoloc(2))
1640 :
1641 334 : SELECT CASE (localized_wfn_control%set_of_states)
1642 : CASE (state_loc_list)
1643 : ! List
1644 18 : CPASSERT(ASSOCIATED(localized_wfn_control%loc_states))
1645 52 : DO ispin = 1, nspins
1646 34 : localized_wfn_control%lu_bound_states(1, ispin) = 1
1647 34 : localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
1648 52 : IF (nmoloc(ispin) < 1) THEN
1649 4 : localized_wfn_control%lu_bound_states(1, ispin) = 0
1650 22 : localized_wfn_control%loc_states(:, ispin) = 0
1651 : END IF
1652 : END DO
1653 : CASE (state_loc_range)
1654 : ! Range
1655 114 : ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
1656 446 : localized_wfn_control%loc_states = 0
1657 114 : DO ispin = 1, nspins
1658 : localized_wfn_control%lu_bound_states(1, ispin) = &
1659 76 : localized_wfn_control%lu_bound_states(1, my_spin)
1660 : localized_wfn_control%lu_bound_states(2, ispin) = &
1661 76 : localized_wfn_control%lu_bound_states(1, my_spin) + nmoloc(ispin) - 1
1662 76 : max_iloc = localized_wfn_control%lu_bound_states(2, ispin)
1663 242 : DO i = 1, nmoloc(ispin)
1664 242 : localized_wfn_control%loc_states(i, ispin) = localized_wfn_control%lu_bound_states(1, ispin) + i - 1
1665 : END DO
1666 76 : CPASSERT(max_iloc <= nmo(ispin))
1667 38 : MARK_USED(nmo)
1668 : END DO
1669 : CASE (energy_loc_range)
1670 : ! Energy
1671 30 : ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
1672 214 : localized_wfn_control%loc_states = 0
1673 22 : DO ispin = 1, nspins
1674 134 : DO i = 1, nmoloc(ispin)
1675 124 : localized_wfn_control%loc_states(i, ispin) = localized_wfn_control%lu_bound_states(1, ispin) + i - 1
1676 : END DO
1677 : END DO
1678 : CASE (state_loc_all)
1679 : ! All
1680 744 : ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
1681 4624 : localized_wfn_control%loc_states = 0
1682 :
1683 248 : IF (localized_wfn_control%lu_bound_states(1, 1) == 1) THEN
1684 582 : DO ispin = 1, nspins
1685 334 : localized_wfn_control%lu_bound_states(1, ispin) = 1
1686 334 : localized_wfn_control%lu_bound_states(2, ispin) = nmoloc(ispin)
1687 334 : IF (nmoloc(ispin) < 1) localized_wfn_control%lu_bound_states(1, ispin) = 0
1688 3176 : DO i = 1, nmoloc(ispin)
1689 2928 : localized_wfn_control%loc_states(i, ispin) = i
1690 : END DO
1691 : END DO
1692 : ELSE
1693 0 : DO ispin = 1, nspins
1694 0 : IF (nmoloc(ispin) < 1) localized_wfn_control%lu_bound_states(1, ispin) = 0
1695 0 : DO i = 1, nmoloc(ispin)
1696 : localized_wfn_control%loc_states(i, ispin) = &
1697 0 : localized_wfn_control%lu_bound_states(1, ispin) + i - 1
1698 : END DO
1699 : END DO
1700 : END IF
1701 : CASE (state_loc_mixed)
1702 : ! Mixed
1703 6 : ALLOCATE (localized_wfn_control%loc_states(max_nmoloc, 2))
1704 178 : localized_wfn_control%loc_states = 0
1705 320 : DO ispin = 1, nspins
1706 90 : DO i = 1, nmoloc(ispin)
1707 88 : localized_wfn_control%loc_states(i, ispin) = i
1708 : END DO
1709 : END DO
1710 : END SELECT
1711 :
1712 316 : CALL timestop(state)
1713 :
1714 316 : END SUBROUTINE set_loc_wfn_lists
1715 :
1716 : END MODULE qs_loc_utils
1717 :
|