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 Utility subroutines for mixed CDFT calculations
10 : !> \par History
11 : !> separated from mixed_cdft_methods [01.2017]
12 : !> \author Nico Holmberg [01.2017]
13 : ! **************************************************************************************************
14 : MODULE mixed_cdft_utils
15 : USE atomic_kind_types, ONLY: atomic_kind_type
16 : USE cell_types, ONLY: cell_type
17 : USE cp_array_utils, ONLY: cp_1d_i_p_type,&
18 : cp_1d_r_p_type,&
19 : cp_2d_r_p_type
20 : USE cp_blacs_env, ONLY: cp_blacs_env_create,&
21 : cp_blacs_env_type
22 : USE cp_control_types, ONLY: dft_control_type
23 : USE cp_dbcsr_api, ONLY: dbcsr_desymmetrize,&
24 : dbcsr_get_info,&
25 : dbcsr_init_p,&
26 : dbcsr_p_type,&
27 : dbcsr_release,&
28 : dbcsr_release_p,&
29 : dbcsr_type
30 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
31 : copy_fm_to_dbcsr_bc
32 : USE cp_files, ONLY: open_file
33 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
34 : cp_fm_struct_release,&
35 : cp_fm_struct_type
36 : USE cp_fm_types, ONLY: cp_fm_copy_general,&
37 : cp_fm_create,&
38 : cp_fm_get_info,&
39 : cp_fm_release,&
40 : cp_fm_to_fm,&
41 : cp_fm_type
42 : USE cp_log_handling, ONLY: cp_get_default_logger,&
43 : cp_logger_create,&
44 : cp_logger_set,&
45 : cp_logger_type,&
46 : cp_to_string
47 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
48 : cp_print_key_unit_nr
49 : USE cp_realspace_grid_init, ONLY: init_input_type
50 : USE cp_subsys_types, ONLY: cp_subsys_get,&
51 : cp_subsys_type
52 : USE cube_utils, ONLY: init_cube_info,&
53 : return_cube_max_iradius
54 : USE d3_poly, ONLY: init_d3_poly_module
55 : USE force_env_types, ONLY: force_env_get,&
56 : force_env_type,&
57 : multiple_fe_list
58 : USE gaussian_gridlevels, ONLY: init_gaussian_gridlevel
59 : USE global_types, ONLY: global_environment_type
60 : USE hirshfeld_types, ONLY: create_hirshfeld_type,&
61 : release_hirshfeld_type,&
62 : set_hirshfeld_info
63 : USE input_constants, ONLY: becke_cutoff_element,&
64 : mixed_cdft_parallel,&
65 : mixed_cdft_parallel_nobuild,&
66 : mixed_cdft_serial,&
67 : outer_scf_becke_constraint,&
68 : outer_scf_hirshfeld_constraint,&
69 : shape_function_gaussian
70 : USE input_section_types, ONLY: section_vals_duplicate,&
71 : section_vals_get,&
72 : section_vals_get_subs_vals,&
73 : section_vals_release,&
74 : section_vals_type,&
75 : section_vals_val_get
76 : USE kinds, ONLY: default_path_length,&
77 : default_string_length,&
78 : dp
79 : USE message_passing, ONLY: mp_request_type,&
80 : mp_waitall
81 : USE mixed_cdft_types, ONLY: mixed_cdft_result_type_release,&
82 : mixed_cdft_result_type_set,&
83 : mixed_cdft_settings_type,&
84 : mixed_cdft_type,&
85 : mixed_cdft_work_type_init
86 : USE mixed_environment_types, ONLY: get_mixed_env,&
87 : mixed_environment_type
88 : USE pw_env_methods, ONLY: pw_env_create
89 : USE pw_env_types, ONLY: pw_env_get,&
90 : pw_env_type
91 : USE pw_grid_types, ONLY: HALFSPACE,&
92 : pw_grid_type
93 : USE pw_grids, ONLY: do_pw_grid_blocked_false,&
94 : pw_grid_create,&
95 : pw_grid_release
96 : USE pw_pool_types, ONLY: pw_pool_create,&
97 : pw_pool_p_type,&
98 : pw_pool_type
99 : USE qs_cdft_types, ONLY: cdft_control_create,&
100 : cdft_control_type
101 : USE qs_environment_types, ONLY: get_qs_env,&
102 : qs_environment_type
103 : USE qs_kind_types, ONLY: create_qs_kind_set,&
104 : qs_kind_type
105 : USE realspace_grid_types, ONLY: realspace_grid_desc_p_type,&
106 : realspace_grid_input_type,&
107 : realspace_grid_type,&
108 : rs_grid_create,&
109 : rs_grid_create_descriptor,&
110 : rs_grid_print
111 : #include "./base/base_uses.f90"
112 :
113 : IMPLICIT NONE
114 : PRIVATE
115 :
116 : ! Public subroutines
117 :
118 : PUBLIC :: mixed_cdft_parse_settings, mixed_cdft_transfer_settings, &
119 : mixed_cdft_init_structures, mixed_cdft_redistribute_arrays, &
120 : mixed_cdft_print_couplings, map_permutation_to_states, hfun_zero, &
121 : mixed_cdft_release_work, mixed_cdft_read_block_diag, &
122 : mixed_cdft_get_blocks, mixed_cdft_diagonalize_blocks, &
123 : mixed_cdft_assemble_block_diag
124 :
125 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mixed_cdft_utils'
126 :
127 : CONTAINS
128 :
129 : ! **************************************************************************************************
130 : !> \brief Parse settings for mixed cdft calculation and check their consistency
131 : !> \param force_env the force_env that holds the CDFT mixed_env
132 : !> \param mixed_env the mixed_env that holds the CDFT states
133 : !> \param mixed_cdft control section for mixed CDFT
134 : !> \param settings container for settings related to the mixed CDFT calculation
135 : !> \param natom the total number of atoms
136 : !> \par History
137 : !> 01.2017 created [Nico Holmberg]
138 : ! **************************************************************************************************
139 72 : SUBROUTINE mixed_cdft_parse_settings(force_env, mixed_env, mixed_cdft, &
140 : settings, natom)
141 : TYPE(force_env_type), POINTER :: force_env
142 : TYPE(mixed_environment_type), POINTER :: mixed_env
143 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
144 : TYPE(mixed_cdft_settings_type) :: settings
145 : INTEGER :: natom
146 :
147 : INTEGER :: i, iatom, iforce_eval, igroup, &
148 : nforce_eval, nkinds
149 72 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: constraint_type
150 72 : INTEGER, ALLOCATABLE, DIMENSION(:, :, :) :: array_sizes
151 : LOGICAL :: is_match
152 72 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
153 : TYPE(cdft_control_type), POINTER :: cdft_control
154 72 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:, :) :: atoms
155 72 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:, :) :: coeff
156 : TYPE(dft_control_type), POINTER :: dft_control
157 : TYPE(force_env_type), POINTER :: force_env_qs
158 : TYPE(pw_env_type), POINTER :: pw_env
159 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
160 : TYPE(qs_environment_type), POINTER :: qs_env
161 :
162 72 : NULLIFY (dft_control, qs_env, pw_env, auxbas_pw_pool, force_env_qs, &
163 72 : cdft_control)
164 : ! Allocate storage for temporaries used for checking settings consistency
165 72 : settings%max_nkinds = 30
166 72 : nforce_eval = SIZE(force_env%sub_force_env)
167 216 : ALLOCATE (settings%grid_span(nforce_eval))
168 216 : ALLOCATE (settings%npts(3, nforce_eval))
169 216 : ALLOCATE (settings%cutoff(nforce_eval))
170 144 : ALLOCATE (settings%rel_cutoff(nforce_eval))
171 144 : ALLOCATE (settings%spherical(nforce_eval))
172 216 : ALLOCATE (settings%rs_dims(2, nforce_eval))
173 144 : ALLOCATE (settings%odd(nforce_eval))
174 288 : ALLOCATE (settings%atoms(natom, nforce_eval))
175 72 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
176 88 : ALLOCATE (settings%coeffs(natom, nforce_eval))
177 154 : settings%coeffs = 0.0_dp
178 : END IF
179 : ! Some of the checked settings are only defined for certain types of constraints
180 : ! We nonetheless use arrays that are large enough to contain settings for all constraints
181 : ! This is not completely optimal...
182 216 : ALLOCATE (settings%si(6, nforce_eval))
183 216 : ALLOCATE (settings%sb(8, nforce_eval))
184 216 : ALLOCATE (settings%sr(5, nforce_eval))
185 216 : ALLOCATE (settings%cutoffs(settings%max_nkinds, nforce_eval))
186 144 : ALLOCATE (settings%radii(settings%max_nkinds, nforce_eval))
187 240 : settings%grid_span = 0
188 744 : settings%npts = 0
189 240 : settings%cutoff = 0.0_dp
190 240 : settings%rel_cutoff = 0.0_dp
191 240 : settings%spherical = 0
192 72 : settings%is_spherical = .FALSE.
193 576 : settings%rs_dims = 0
194 240 : settings%odd = 0
195 72 : settings%is_odd = .FALSE.
196 614 : settings%atoms = 0
197 1248 : settings%si = 0
198 1080 : settings%sr = 0.0_dp
199 1584 : settings%sb = .FALSE.
200 5280 : settings%cutoffs = 0.0_dp
201 5280 : settings%radii = 0.0_dp
202 : ! Get information from the sub_force_envs
203 240 : DO iforce_eval = 1, nforce_eval
204 168 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
205 144 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
206 144 : IF (mixed_env%do_mixed_qmmm_cdft) THEN
207 12 : qs_env => force_env_qs%qmmm_env%qs_env
208 : ELSE
209 132 : CALL force_env_get(force_env_qs, qs_env=qs_env)
210 : END IF
211 144 : CALL get_qs_env(qs_env, pw_env=pw_env, dft_control=dft_control)
212 144 : IF (.NOT. dft_control%qs_control%cdft) &
213 : CALL cp_abort(__LOCATION__, &
214 : "A mixed CDFT simulation with multiple force_evals was requested, "// &
215 0 : "but CDFT constraints were not active in the QS section of all force_evals!")
216 144 : cdft_control => dft_control%qs_control%cdft_control
217 144 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
218 1440 : settings%bo = auxbas_pw_pool%pw_grid%bounds_local
219 : ! Only the rank 0 process collects info about pw_grid and CDFT
220 216 : IF (force_env_qs%para_env%is_source()) THEN
221 : ! Grid settings
222 84 : settings%grid_span(iforce_eval) = auxbas_pw_pool%pw_grid%grid_span
223 336 : settings%npts(:, iforce_eval) = auxbas_pw_pool%pw_grid%npts
224 84 : settings%cutoff(iforce_eval) = auxbas_pw_pool%pw_grid%cutoff
225 84 : settings%rel_cutoff(iforce_eval) = dft_control%qs_control%relative_cutoff
226 84 : IF (auxbas_pw_pool%pw_grid%spherical) settings%spherical(iforce_eval) = 1
227 252 : settings%rs_dims(:, iforce_eval) = auxbas_pw_pool%pw_grid%para%group%num_pe_cart
228 84 : IF (auxbas_pw_pool%pw_grid%grid_span == HALFSPACE) settings%odd(iforce_eval) = 1
229 : ! Becke constraint atoms/coeffs
230 84 : IF (cdft_control%natoms > SIZE(settings%atoms, 1)) &
231 : CALL cp_abort(__LOCATION__, &
232 : "More CDFT constraint atoms than defined in mixed section. "// &
233 0 : "Use default values for MIXED\MAPPING.")
234 233 : settings%atoms(1:cdft_control%natoms, iforce_eval) = cdft_control%atoms
235 84 : IF (mixed_cdft%run_type == mixed_cdft_parallel) &
236 66 : settings%coeffs(1:cdft_control%natoms, iforce_eval) = cdft_control%group(1)%coeff
237 : ! Integer type settings
238 84 : IF (cdft_control%type == outer_scf_becke_constraint) THEN
239 76 : settings%si(1, iforce_eval) = cdft_control%becke_control%cutoff_type
240 76 : settings%si(2, iforce_eval) = cdft_control%becke_control%cavity_shape
241 : END IF
242 84 : settings%si(3, iforce_eval) = dft_control%multiplicity
243 84 : settings%si(4, iforce_eval) = SIZE(cdft_control%group)
244 84 : settings%si(5, iforce_eval) = cdft_control%type
245 84 : IF (cdft_control%type == outer_scf_hirshfeld_constraint) THEN
246 8 : settings%si(6, iforce_eval) = cdft_control%hirshfeld_control%shape_function
247 8 : settings%si(6, iforce_eval) = cdft_control%hirshfeld_control%gaussian_shape
248 : END IF
249 : ! Logicals
250 84 : IF (cdft_control%type == outer_scf_becke_constraint) THEN
251 76 : settings%sb(1, iforce_eval) = cdft_control%becke_control%cavity_confine
252 76 : settings%sb(2, iforce_eval) = cdft_control%becke_control%should_skip
253 76 : settings%sb(3, iforce_eval) = cdft_control%becke_control%print_cavity
254 76 : settings%sb(4, iforce_eval) = cdft_control%becke_control%in_memory
255 76 : settings%sb(5, iforce_eval) = cdft_control%becke_control%adjust
256 76 : settings%sb(8, iforce_eval) = cdft_control%becke_control%use_bohr
257 : END IF
258 84 : IF (cdft_control%type == outer_scf_hirshfeld_constraint) THEN
259 8 : settings%sb(8, iforce_eval) = cdft_control%hirshfeld_control%use_bohr
260 : END IF
261 84 : settings%sb(6, iforce_eval) = cdft_control%atomic_charges
262 84 : settings%sb(7, iforce_eval) = qs_env%has_unit_metric
263 : ! Reals
264 84 : IF (cdft_control%type == outer_scf_becke_constraint) THEN
265 76 : settings%sr(1, iforce_eval) = cdft_control%becke_control%rcavity
266 76 : settings%sr(2, iforce_eval) = cdft_control%becke_control%rglobal
267 76 : settings%sr(3, iforce_eval) = cdft_control%becke_control%eps_cavity
268 : END IF
269 84 : IF (cdft_control%type == outer_scf_hirshfeld_constraint) THEN
270 8 : settings%sr(2, iforce_eval) = cdft_control%hirshfeld_control%radius
271 : END IF
272 84 : settings%sr(4, iforce_eval) = dft_control%qs_control%eps_rho_rspace
273 84 : settings%sr(5, iforce_eval) = pw_env%cube_info(pw_env%auxbas_grid)%max_rad_ga
274 84 : IF (cdft_control%type == outer_scf_becke_constraint) THEN
275 76 : IF (cdft_control%becke_control%cutoff_type == becke_cutoff_element) THEN
276 50 : nkinds = SIZE(cdft_control%becke_control%cutoffs_tmp)
277 50 : IF (nkinds > settings%max_nkinds) &
278 : CALL cp_abort(__LOCATION__, &
279 : "More than "//TRIM(cp_to_string(settings%max_nkinds))// &
280 : " unique elements were defined in BECKE_CONSTRAINT\ELEMENT_CUTOFF. Are you sure"// &
281 0 : " your input is correct? If yes, please increase max_nkinds and recompile.")
282 150 : settings%cutoffs(1:nkinds, iforce_eval) = cdft_control%becke_control%cutoffs_tmp(:)
283 : END IF
284 76 : IF (cdft_control%becke_control%adjust) THEN
285 52 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
286 52 : IF (.NOT. SIZE(atomic_kind_set) == SIZE(cdft_control%becke_control%radii_tmp)) &
287 : CALL cp_abort(__LOCATION__, &
288 : "Length of keyword BECKE_CONSTRAINT\ATOMIC_RADII does not "// &
289 0 : "match number of atomic kinds in the input coordinate file.")
290 52 : nkinds = SIZE(cdft_control%becke_control%radii_tmp)
291 52 : IF (nkinds > settings%max_nkinds) &
292 : CALL cp_abort(__LOCATION__, &
293 : "More than "//TRIM(cp_to_string(settings%max_nkinds))// &
294 : " unique elements were defined in BECKE_CONSTRAINT\ATOMIC_RADII. Are you sure"// &
295 0 : " your input is correct? If yes, please increase max_nkinds and recompile.")
296 156 : settings%radii(1:nkinds, iforce_eval) = cdft_control%becke_control%radii_tmp(:)
297 : END IF
298 : END IF
299 108 : IF (cdft_control%type == outer_scf_hirshfeld_constraint) THEN
300 8 : IF (ASSOCIATED(cdft_control%hirshfeld_control%radii)) THEN
301 0 : CALL get_qs_env(qs_env, atomic_kind_set=atomic_kind_set)
302 0 : IF (.NOT. SIZE(atomic_kind_set) == SIZE(cdft_control%hirshfeld_control%radii)) &
303 : CALL cp_abort(__LOCATION__, &
304 : "Length of keyword HIRSHFELD_CONSTRAINT&RADII does not "// &
305 0 : "match number of atomic kinds in the input coordinate file.")
306 0 : nkinds = SIZE(cdft_control%hirshfeld_control%radii)
307 0 : IF (nkinds > settings%max_nkinds) &
308 : CALL cp_abort(__LOCATION__, &
309 : "More than "//TRIM(cp_to_string(settings%max_nkinds))// &
310 : " unique elements were defined in HIRSHFELD_CONSTRAINT&RADII. Are you sure"// &
311 0 : " your input is correct? If yes, please increase max_nkinds and recompile.")
312 0 : settings%radii(1:nkinds, iforce_eval) = cdft_control%hirshfeld_control%radii(:)
313 : END IF
314 : END IF
315 : END IF
316 : END DO
317 : ! Make sure the grids are consistent
318 408 : CALL force_env%para_env%sum(settings%grid_span)
319 1416 : CALL force_env%para_env%sum(settings%npts)
320 408 : CALL force_env%para_env%sum(settings%cutoff)
321 408 : CALL force_env%para_env%sum(settings%rel_cutoff)
322 408 : CALL force_env%para_env%sum(settings%spherical)
323 1080 : CALL force_env%para_env%sum(settings%rs_dims)
324 408 : CALL force_env%para_env%sum(settings%odd)
325 72 : is_match = .TRUE.
326 168 : DO iforce_eval = 2, nforce_eval
327 96 : is_match = is_match .AND. (settings%grid_span(1) == settings%grid_span(iforce_eval))
328 96 : is_match = is_match .AND. (settings%npts(1, 1) == settings%npts(1, iforce_eval))
329 96 : is_match = is_match .AND. (settings%cutoff(1) == settings%cutoff(iforce_eval))
330 96 : is_match = is_match .AND. (settings%rel_cutoff(1) == settings%rel_cutoff(iforce_eval))
331 96 : is_match = is_match .AND. (settings%spherical(1) == settings%spherical(iforce_eval))
332 96 : is_match = is_match .AND. (settings%rs_dims(1, 1) == settings%rs_dims(1, iforce_eval))
333 96 : is_match = is_match .AND. (settings%rs_dims(2, 1) == settings%rs_dims(2, iforce_eval))
334 168 : is_match = is_match .AND. (settings%odd(1) == settings%odd(iforce_eval))
335 : END DO
336 72 : IF (.NOT. is_match) &
337 : CALL cp_abort(__LOCATION__, &
338 0 : "Mismatch detected in the &MGRID settings of the CDFT force_evals.")
339 72 : IF (settings%spherical(1) == 1) settings%is_spherical = .TRUE.
340 72 : IF (settings%odd(1) == 1) settings%is_odd = .TRUE.
341 : ! Make sure CDFT settings are consistent
342 1156 : CALL force_env%para_env%sum(settings%atoms)
343 72 : IF (mixed_cdft%run_type == mixed_cdft_parallel) &
344 286 : CALL force_env%para_env%sum(settings%coeffs)
345 72 : settings%ncdft = 0
346 224 : DO i = 1, SIZE(settings%atoms, 1)
347 374 : DO iforce_eval = 2, nforce_eval
348 374 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
349 44 : IF (settings%atoms(i, 1) /= settings%atoms(i, iforce_eval)) is_match = .FALSE.
350 44 : IF (settings%coeffs(i, 1) /= settings%coeffs(i, iforce_eval)) is_match = .FALSE.
351 : END IF
352 : END DO
353 224 : IF (settings%atoms(i, 1) /= 0) settings%ncdft = settings%ncdft + 1
354 : END DO
355 72 : IF (.NOT. is_match .AND. mixed_cdft%run_type == mixed_cdft_parallel) &
356 : CALL cp_abort(__LOCATION__, &
357 : "Mismatch detected in the &CDFT section of the CDFT force_evals. "// &
358 : "Parallel mode mixed CDFT requires identical constraint definitions in both CDFT states. "// &
359 : "Switch to serial mode or disable keyword PARALLEL_BUILD if you "// &
360 0 : "want to use nonidentical constraint definitions.")
361 2424 : CALL force_env%para_env%sum(settings%si)
362 2088 : CALL force_env%para_env%sum(settings%sr)
363 648 : DO i = 1, SIZE(settings%sb, 1)
364 576 : CALL force_env%para_env%sum(settings%sb(i, 1))
365 1416 : DO iforce_eval = 2, nforce_eval
366 768 : CALL force_env%para_env%sum(settings%sb(i, iforce_eval))
367 1344 : IF (settings%sb(i, 1) .NEQV. settings%sb(i, iforce_eval)) is_match = .FALSE.
368 : END DO
369 : END DO
370 504 : DO i = 1, SIZE(settings%si, 1)
371 1080 : DO iforce_eval = 2, nforce_eval
372 1008 : IF (settings%si(i, 1) /= settings%si(i, iforce_eval)) is_match = .FALSE.
373 : END DO
374 : END DO
375 432 : DO i = 1, SIZE(settings%sr, 1)
376 912 : DO iforce_eval = 2, nforce_eval
377 840 : IF (settings%sr(i, 1) /= settings%sr(i, iforce_eval)) is_match = .FALSE.
378 : END DO
379 : END DO
380 72 : IF (.NOT. is_match) &
381 : CALL cp_abort(__LOCATION__, &
382 0 : "Mismatch detected in the &CDFT settings of the CDFT force_evals.")
383 : ! Some CDFT features are currently disabled for mixed calculations: check that these features were not requested
384 72 : IF (mixed_cdft%dlb .AND. .NOT. settings%sb(1, 1)) &
385 : CALL cp_abort(__LOCATION__, &
386 0 : "Parallel mode mixed CDFT load balancing requires Gaussian cavity confinement.")
387 : ! Check for identical constraints in case of run type serial/parallel_nobuild
388 72 : IF (mixed_cdft%run_type /= mixed_cdft_parallel) THEN
389 : ! Get array sizes
390 250 : ALLOCATE (array_sizes(nforce_eval, settings%si(4, 1), 2))
391 510 : array_sizes(:, :, :) = 0
392 174 : DO iforce_eval = 1, nforce_eval
393 124 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
394 122 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
395 122 : IF (mixed_env%do_mixed_qmmm_cdft) THEN
396 8 : qs_env => force_env_qs%qmmm_env%qs_env
397 : ELSE
398 114 : CALL force_env_get(force_env_qs, qs_env=qs_env)
399 : END IF
400 122 : CALL get_qs_env(qs_env, dft_control=dft_control)
401 122 : cdft_control => dft_control%qs_control%cdft_control
402 172 : IF (force_env_qs%para_env%is_source()) THEN
403 128 : DO igroup = 1, SIZE(cdft_control%group)
404 64 : array_sizes(iforce_eval, igroup, 1) = SIZE(cdft_control%group(igroup)%atoms)
405 126 : array_sizes(iforce_eval, igroup, 2) = SIZE(cdft_control%group(igroup)%coeff)
406 : END DO
407 : END IF
408 : END DO
409 : ! Sum up array sizes and check consistency
410 50 : CALL force_env%para_env%sum(array_sizes)
411 410 : IF (ANY(array_sizes(:, :, 1) /= array_sizes(1, 1, 1)) .OR. &
412 : ANY(array_sizes(:, :, 2) /= array_sizes(1, 1, 2))) &
413 0 : mixed_cdft%identical_constraints = .FALSE.
414 : ! Check constraint definitions
415 50 : IF (mixed_cdft%identical_constraints) THEN
416 : ! Prepare temporary storage
417 380 : ALLOCATE (atoms(nforce_eval, settings%si(4, 1)))
418 330 : ALLOCATE (coeff(nforce_eval, settings%si(4, 1)))
419 200 : ALLOCATE (constraint_type(nforce_eval, settings%si(4, 1)))
420 230 : constraint_type(:, :) = 0
421 174 : DO iforce_eval = 1, nforce_eval
422 252 : DO i = 1, settings%si(4, 1)
423 128 : NULLIFY (atoms(iforce_eval, i)%array)
424 : NULLIFY (coeff(iforce_eval, i)%array)
425 384 : ALLOCATE (atoms(iforce_eval, i)%array(array_sizes(iforce_eval, i, 1)))
426 384 : ALLOCATE (coeff(iforce_eval, i)%array(array_sizes(iforce_eval, i, 1)))
427 346 : atoms(iforce_eval, i)%array(:) = 0
428 470 : coeff(iforce_eval, i)%array(:) = 0
429 : END DO
430 : ! Get constraint definitions
431 124 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
432 122 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
433 122 : IF (mixed_env%do_mixed_qmmm_cdft) THEN
434 8 : qs_env => force_env_qs%qmmm_env%qs_env
435 : ELSE
436 114 : CALL force_env_get(force_env_qs, qs_env=qs_env)
437 : END IF
438 122 : CALL get_qs_env(qs_env, dft_control=dft_control)
439 122 : cdft_control => dft_control%qs_control%cdft_control
440 172 : IF (force_env_qs%para_env%is_source()) THEN
441 128 : DO i = 1, settings%si(4, 1)
442 173 : atoms(iforce_eval, i)%array(:) = cdft_control%group(i)%atoms
443 173 : coeff(iforce_eval, i)%array(:) = cdft_control%group(i)%coeff
444 126 : constraint_type(iforce_eval, i) = cdft_control%group(i)%constraint_type
445 : END DO
446 : END IF
447 : END DO
448 : ! Sum up constraint definitions and check consistency
449 100 : DO i = 1, settings%si(4, 1)
450 180 : DO iforce_eval = 1, nforce_eval
451 564 : CALL force_env%para_env%sum(atoms(iforce_eval, i)%array)
452 564 : CALL force_env%para_env%sum(coeff(iforce_eval, i)%array)
453 180 : CALL force_env%para_env%sum(constraint_type(iforce_eval, i))
454 : END DO
455 126 : DO iforce_eval = 2, nforce_eval
456 194 : DO iatom = 1, SIZE(atoms(1, i)%array)
457 120 : IF (atoms(1, i)%array(iatom) /= atoms(iforce_eval, i)%array(iatom)) &
458 0 : mixed_cdft%identical_constraints = .FALSE.
459 120 : IF (coeff(1, i)%array(iatom) /= coeff(iforce_eval, i)%array(iatom)) &
460 2 : mixed_cdft%identical_constraints = .FALSE.
461 194 : IF (.NOT. mixed_cdft%identical_constraints) EXIT
462 : END DO
463 76 : IF (constraint_type(1, i) /= constraint_type(iforce_eval, i)) &
464 0 : mixed_cdft%identical_constraints = .FALSE.
465 126 : IF (.NOT. mixed_cdft%identical_constraints) EXIT
466 : END DO
467 100 : IF (.NOT. mixed_cdft%identical_constraints) EXIT
468 : END DO
469 : ! Deallocate temporary storage
470 174 : DO iforce_eval = 1, nforce_eval
471 302 : DO i = 1, settings%si(4, 1)
472 128 : DEALLOCATE (atoms(iforce_eval, i)%array)
473 252 : DEALLOCATE (coeff(iforce_eval, i)%array)
474 : END DO
475 : END DO
476 50 : DEALLOCATE (atoms)
477 50 : DEALLOCATE (coeff)
478 50 : DEALLOCATE (constraint_type)
479 : END IF
480 50 : DEALLOCATE (array_sizes)
481 : END IF
482 : ! Deallocate some arrays that are no longer needed
483 72 : IF (mixed_cdft%identical_constraints .AND. mixed_cdft%run_type /= mixed_cdft_parallel_nobuild) THEN
484 228 : DO iforce_eval = 1, nforce_eval
485 160 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
486 138 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
487 138 : IF (mixed_env%do_mixed_qmmm_cdft) THEN
488 12 : qs_env => force_env_qs%qmmm_env%qs_env
489 : ELSE
490 126 : CALL force_env_get(force_env_qs, qs_env=qs_env)
491 : END IF
492 138 : CALL get_qs_env(qs_env, dft_control=dft_control)
493 138 : cdft_control => dft_control%qs_control%cdft_control
494 206 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
495 22 : IF (.NOT. dft_control%qs_control%gapw) THEN
496 44 : DO i = 1, SIZE(cdft_control%group)
497 22 : DEALLOCATE (cdft_control%group(i)%coeff)
498 44 : DEALLOCATE (cdft_control%group(i)%atoms)
499 : END DO
500 22 : IF (.NOT. cdft_control%atomic_charges) DEALLOCATE (cdft_control%atoms)
501 : END IF
502 116 : ELSE IF (mixed_cdft%run_type == mixed_cdft_serial) THEN
503 116 : IF (iforce_eval == 1) CYCLE
504 142 : DO igroup = 1, SIZE(cdft_control%group)
505 142 : IF (.NOT. dft_control%qs_control%gapw) THEN
506 72 : DEALLOCATE (cdft_control%group(igroup)%coeff)
507 72 : DEALLOCATE (cdft_control%group(igroup)%atoms)
508 : END IF
509 : END DO
510 70 : IF (cdft_control%type == outer_scf_becke_constraint) THEN
511 64 : IF (.NOT. cdft_control%atomic_charges) DEALLOCATE (cdft_control%atoms)
512 64 : IF (cdft_control%becke_control%cavity_confine) &
513 62 : CALL release_hirshfeld_type(cdft_control%becke_control%cavity_env)
514 64 : IF (cdft_control%becke_control%cutoff_type == becke_cutoff_element) &
515 42 : DEALLOCATE (cdft_control%becke_control%cutoffs_tmp)
516 64 : IF (cdft_control%becke_control%adjust) &
517 44 : DEALLOCATE (cdft_control%becke_control%radii_tmp)
518 : END IF
519 : END IF
520 : END DO
521 : END IF
522 :
523 144 : END SUBROUTINE mixed_cdft_parse_settings
524 :
525 : ! **************************************************************************************************
526 : !> \brief Transfer settings to mixed_cdft
527 : !> \param force_env the force_env that holds the CDFT states
528 : !> \param mixed_cdft the control section for mixed CDFT calculations
529 : !> \param settings container for settings related to the mixed CDFT calculation
530 : !> \par History
531 : !> 01.2017 created [Nico Holmberg]
532 : ! **************************************************************************************************
533 72 : SUBROUTINE mixed_cdft_transfer_settings(force_env, mixed_cdft, settings)
534 : TYPE(force_env_type), POINTER :: force_env
535 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
536 : TYPE(mixed_cdft_settings_type) :: settings
537 :
538 : INTEGER :: i, nkinds
539 : LOGICAL :: is_match
540 : TYPE(cdft_control_type), POINTER :: cdft_control
541 :
542 72 : NULLIFY (cdft_control)
543 72 : is_match = .TRUE.
544 : ! Transfer global settings
545 72 : mixed_cdft%multiplicity = settings%si(3, 1)
546 72 : mixed_cdft%has_unit_metric = settings%sb(7, 1)
547 72 : mixed_cdft%eps_rho_rspace = settings%sr(4, 1)
548 72 : mixed_cdft%nconstraint = settings%si(4, 1)
549 72 : settings%radius = settings%sr(5, 1)
550 : ! Transfer settings only needed if the constraint should be built in parallel
551 72 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
552 22 : IF (settings%sb(6, 1)) &
553 : CALL cp_abort(__LOCATION__, &
554 0 : "Calculation of atomic Becke charges not supported with parallel mode mixed CDFT")
555 22 : IF (mixed_cdft%nconstraint /= 1) &
556 : CALL cp_abort(__LOCATION__, &
557 0 : "Parallel mode mixed CDFT does not yet support multiple constraints.")
558 :
559 22 : IF (settings%si(5, 1) /= outer_scf_becke_constraint) &
560 : CALL cp_abort(__LOCATION__, &
561 0 : "Parallel mode mixed CDFT does not support Hirshfeld constraints.")
562 :
563 66 : ALLOCATE (mixed_cdft%cdft_control)
564 22 : CALL cdft_control_create(mixed_cdft%cdft_control)
565 22 : cdft_control => mixed_cdft%cdft_control
566 66 : ALLOCATE (cdft_control%atoms(settings%ncdft))
567 66 : cdft_control%atoms = settings%atoms(1:settings%ncdft, 1)
568 44 : ALLOCATE (cdft_control%group(1))
569 66 : ALLOCATE (cdft_control%group(1)%atoms(settings%ncdft))
570 66 : ALLOCATE (cdft_control%group(1)%coeff(settings%ncdft))
571 22 : NULLIFY (cdft_control%group(1)%weight)
572 22 : NULLIFY (cdft_control%group(1)%gradients)
573 22 : NULLIFY (cdft_control%group(1)%integrated)
574 66 : cdft_control%group(1)%atoms = cdft_control%atoms
575 66 : cdft_control%group(1)%coeff = settings%coeffs(1:settings%ncdft, 1)
576 22 : cdft_control%natoms = settings%ncdft
577 22 : cdft_control%atomic_charges = settings%sb(6, 1)
578 22 : cdft_control%becke_control%cutoff_type = settings%si(1, 1)
579 22 : cdft_control%becke_control%cavity_confine = settings%sb(1, 1)
580 22 : cdft_control%becke_control%should_skip = settings%sb(2, 1)
581 22 : cdft_control%becke_control%print_cavity = settings%sb(3, 1)
582 22 : cdft_control%becke_control%in_memory = settings%sb(4, 1)
583 22 : cdft_control%becke_control%adjust = settings%sb(5, 1)
584 22 : cdft_control%becke_control%cavity_shape = settings%si(2, 1)
585 22 : cdft_control%becke_control%use_bohr = settings%sb(8, 1)
586 22 : cdft_control%becke_control%rcavity = settings%sr(1, 1)
587 22 : cdft_control%becke_control%rglobal = settings%sr(2, 1)
588 22 : cdft_control%becke_control%eps_cavity = settings%sr(3, 1)
589 22 : nkinds = 0
590 22 : IF (cdft_control%becke_control%cutoff_type == becke_cutoff_element) THEN
591 2250 : CALL force_env%para_env%sum(settings%cutoffs)
592 558 : DO i = 1, SIZE(settings%cutoffs, 1)
593 540 : IF (settings%cutoffs(i, 1) /= settings%cutoffs(i, 2)) is_match = .FALSE.
594 558 : IF (settings%cutoffs(i, 1) /= 0.0_dp) nkinds = nkinds + 1
595 : END DO
596 18 : IF (.NOT. is_match) &
597 : CALL cp_abort(__LOCATION__, &
598 : "Mismatch detected in the &BECKE_CONSTRAINT "// &
599 0 : "&ELEMENT_CUTOFF settings of the two force_evals.")
600 54 : ALLOCATE (cdft_control%becke_control%cutoffs_tmp(nkinds))
601 54 : cdft_control%becke_control%cutoffs_tmp = settings%cutoffs(1:nkinds, 1)
602 : END IF
603 22 : nkinds = 0
604 22 : IF (cdft_control%becke_control%adjust) THEN
605 2250 : CALL force_env%para_env%sum(settings%radii)
606 558 : DO i = 1, SIZE(settings%radii, 1)
607 540 : IF (settings%radii(i, 1) /= settings%radii(i, 2)) is_match = .FALSE.
608 558 : IF (settings%radii(i, 1) /= 0.0_dp) nkinds = nkinds + 1
609 : END DO
610 18 : IF (.NOT. is_match) &
611 : CALL cp_abort(__LOCATION__, &
612 : "Mismatch detected in the &BECKE_CONSTRAINT "// &
613 0 : "&ATOMIC_RADII settings of the two force_evals.")
614 54 : ALLOCATE (cdft_control%becke_control%radii(nkinds))
615 54 : cdft_control%becke_control%radii = settings%radii(1:nkinds, 1)
616 : END IF
617 : END IF
618 :
619 72 : END SUBROUTINE mixed_cdft_transfer_settings
620 :
621 : ! **************************************************************************************************
622 : !> \brief Initialize all the structures needed for a mixed CDFT calculation
623 : !> \param force_env the force_env that holds the CDFT mixed_env
624 : !> \param force_env_qs the force_env that holds the qs_env, which is CDFT state specific
625 : !> \param mixed_env the mixed_env that holds the CDFT states
626 : !> \param mixed_cdft the control section for mixed CDFT calculations
627 : !> \param settings container for settings related to the mixed CDFT calculation
628 : !> \par History
629 : !> 01.2017 created [Nico Holmberg]
630 : ! **************************************************************************************************
631 72 : SUBROUTINE mixed_cdft_init_structures(force_env, force_env_qs, mixed_env, mixed_cdft, settings)
632 : TYPE(force_env_type), POINTER :: force_env, force_env_qs
633 : TYPE(mixed_environment_type), POINTER :: mixed_env
634 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
635 : TYPE(mixed_cdft_settings_type) :: settings
636 :
637 : CHARACTER(len=default_path_length) :: c_val, input_file_path, output_file_path
638 : INTEGER :: i, imap, iounit, j, lp, n_force_eval, &
639 : ncpu, nforce_eval, ntargets, offset, &
640 : unit_nr
641 72 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: bounds
642 : INTEGER, DIMENSION(2, 3) :: bo, bo_mixed
643 : INTEGER, DIMENSION(3) :: higher_grid_layout
644 144 : INTEGER, DIMENSION(:), POINTER :: i_force_eval, mixed_rs_dims, recvbuffer, &
645 144 : recvbuffer2, sendbuffer
646 : LOGICAL :: is_match
647 72 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
648 : TYPE(cell_type), POINTER :: cell_mix
649 : TYPE(cp_logger_type), POINTER :: logger
650 : TYPE(cp_subsys_type), POINTER :: subsys_mix
651 : TYPE(global_environment_type), POINTER :: globenv
652 288 : TYPE(mp_request_type), DIMENSION(3) :: req
653 : TYPE(pw_env_type), POINTER :: pw_env
654 : TYPE(pw_grid_type), POINTER :: pw_grid
655 72 : TYPE(pw_pool_p_type), DIMENSION(:), POINTER :: pw_pools
656 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
657 : TYPE(qs_environment_type), POINTER :: qs_env
658 72 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
659 : TYPE(realspace_grid_desc_p_type), DIMENSION(:), &
660 72 : POINTER :: rs_descs
661 : TYPE(realspace_grid_input_type) :: input_settings
662 72 : TYPE(realspace_grid_type), DIMENSION(:), POINTER :: rs_grids
663 : TYPE(section_vals_type), POINTER :: force_env_section, force_env_sections, kind_section, &
664 : print_section, root_section, rs_grid_section, subsys_section
665 :
666 72 : NULLIFY (cell_mix, subsys_mix, force_env_section, subsys_section, &
667 72 : print_section, root_section, kind_section, force_env_sections, &
668 72 : rs_grid_section, auxbas_pw_pool, pw_env, pw_pools, pw_grid, &
669 72 : sendbuffer, qs_env, mixed_rs_dims, i_force_eval, recvbuffer, &
670 72 : recvbuffer2, globenv, atomic_kind_set, qs_kind_set, rs_descs, &
671 72 : rs_grids)
672 :
673 144 : logger => cp_get_default_logger()
674 72 : CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
675 72 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
676 72 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
677 72 : is_match = .TRUE.
678 72 : nforce_eval = SIZE(force_env%sub_force_env)
679 72 : ncpu = force_env%para_env%num_pe
680 : ! Get infos about the mixed subsys
681 72 : IF (.NOT. mixed_env%do_mixed_qmmm_cdft) THEN
682 : CALL force_env_get(force_env=force_env, &
683 64 : subsys=subsys_mix)
684 : ELSE
685 : CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
686 8 : cp_subsys=subsys_mix)
687 : END IF
688 : ! Init structures only needed when the CDFT states are treated in parallel
689 72 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
690 : ! Start building the mixed auxbas_pw_pool
691 22 : CALL pw_env_create(mixed_cdft%pw_env)
692 : ! Decide what kind of layout to use and setup the grid
693 : ! Processor mappings currently supported:
694 : ! (2np,1) --> (np,1)
695 : ! (nx,2ny) --> (nx,ny)
696 : ! (nx,ny) --> (nx*ny/2,1) (required when xc_smooth is in use and with intermediate proc counts)
697 : !
698 : ! For cases 2 and 3, dlb redistributes YZ slices from overloaded processors to underloaded processors
699 : ! For case 1, XZ slices are redistributed
700 : ! TODO: Unify mappings. Now we essentially have separate code for cases 1-2 and 3.
701 : ! This leads to very messy code especially with dlb turned on...
702 : ! In terms of memory usage, it would be beneficial to replace case 1 with 3
703 : ! and implement a similar arbitrary mapping to replace case 2
704 :
705 22 : mixed_cdft%is_pencil = .FALSE. ! Flag to control the first two mappings
706 22 : mixed_cdft%is_special = .FALSE. ! Flag to control the last mapping
707 : ! With xc smoothing, the grid is always (ncpu/2,1) distributed
708 : ! and correct behavior cannot be guaranteed for ncpu/2 > nx, so we abort...
709 22 : IF (ncpu/2 > settings%npts(1, 1)) &
710 0 : CPABORT("ncpu/2 => nx: decrease ncpu or disable xc_smoothing")
711 : !
712 22 : ALLOCATE (mixed_rs_dims(2))
713 22 : IF (settings%rs_dims(2, 1) /= 1) mixed_cdft%is_pencil = .TRUE.
714 22 : IF (.NOT. mixed_cdft%is_pencil .AND. ncpu > settings%npts(1, 1)) mixed_cdft%is_special = .TRUE.
715 22 : IF (mixed_cdft%is_special) THEN
716 0 : mixed_rs_dims = [-1, -1]
717 22 : ELSE IF (mixed_cdft%is_pencil) THEN
718 0 : mixed_rs_dims = [settings%rs_dims(1, 1), 2*settings%rs_dims(2, 1)]
719 : ELSE
720 66 : mixed_rs_dims = [2*settings%rs_dims(1, 1), 1]
721 : END IF
722 22 : IF (.NOT. mixed_env%do_mixed_qmmm_cdft) THEN
723 : CALL force_env_get(force_env=force_env, &
724 18 : cell=cell_mix)
725 : ELSE
726 : CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
727 4 : cell=cell_mix)
728 : END IF
729 : CALL pw_grid_create(pw_grid, force_env%para_env, cell_mix%hmat, grid_span=settings%grid_span(1), &
730 : npts=settings%npts(:, 1), cutoff=settings%cutoff(1), &
731 : spherical=settings%is_spherical, odd=settings%is_odd, &
732 : fft_usage=.TRUE., ncommensurate=0, icommensurate=1, &
733 : blocked=do_pw_grid_blocked_false, rs_dims=mixed_rs_dims, &
734 22 : iounit=iounit)
735 : ! Check if the layout was successfully created
736 22 : IF (mixed_cdft%is_special) THEN
737 0 : IF (.NOT. pw_grid%para%group%num_pe_cart(2) /= 1) is_match = .FALSE.
738 22 : ELSE IF (mixed_cdft%is_pencil) THEN
739 0 : IF (.NOT. pw_grid%para%group%num_pe_cart(1) == mixed_rs_dims(1)) is_match = .FALSE.
740 : ELSE
741 22 : IF (.NOT. pw_grid%para%group%num_pe_cart(2) == 1) is_match = .FALSE.
742 : END IF
743 : IF (.NOT. is_match) &
744 : CALL cp_abort(__LOCATION__, &
745 : "Unable to create a suitable grid distribution "// &
746 : "for mixed CDFT calculations. Try decreasing the total number "// &
747 0 : "of processors or disabling xc_smoothing.")
748 22 : DEALLOCATE (mixed_rs_dims)
749 : ! Create the pool
750 220 : bo_mixed = pw_grid%bounds_local
751 44 : ALLOCATE (pw_pools(1))
752 22 : NULLIFY (pw_pools(1)%pool)
753 22 : CALL pw_pool_create(pw_pools(1)%pool, pw_grid=pw_grid)
754 : ! Initialize Gaussian cavity confinement
755 22 : IF (mixed_cdft%cdft_control%becke_control%cavity_confine) THEN
756 22 : CALL create_hirshfeld_type(mixed_cdft%cdft_control%becke_control%cavity_env)
757 : CALL set_hirshfeld_info(mixed_cdft%cdft_control%becke_control%cavity_env, &
758 : shape_function_type=shape_function_gaussian, iterative=.FALSE., &
759 : radius_type=mixed_cdft%cdft_control%becke_control%cavity_shape, &
760 22 : use_bohr=mixed_cdft%cdft_control%becke_control%use_bohr)
761 : END IF
762 : ! Gaussian confinement/wavefunction overlap method needs qs_kind_set
763 : ! Gaussian cavity confinement also needs the auxbas_rs_grid
764 22 : IF (mixed_cdft%cdft_control%becke_control%cavity_confine .OR. &
765 : mixed_cdft%wfn_overlap_method) THEN
766 : print_section => section_vals_get_subs_vals(force_env_section, &
767 22 : "PRINT%GRID_INFORMATION")
768 22 : ALLOCATE (mixed_cdft%pw_env%gridlevel_info)
769 : CALL init_gaussian_gridlevel(mixed_cdft%pw_env%gridlevel_info, &
770 : ngrid_levels=1, cutoff=settings%cutoff, &
771 : rel_cutoff=settings%rel_cutoff(1), &
772 22 : print_section=print_section)
773 44 : ALLOCATE (rs_descs(1))
774 374 : ALLOCATE (rs_grids(1))
775 638 : ALLOCATE (mixed_cdft%pw_env%cube_info(1))
776 22 : higher_grid_layout = [-1, -1, -1]
777 22 : CALL init_d3_poly_module()
778 : CALL init_cube_info(mixed_cdft%pw_env%cube_info(1), &
779 : pw_grid%dr(:), pw_grid%dh(:, :), &
780 : pw_grid%dh_inv(:, :), &
781 22 : pw_grid%orthorhombic, settings%radius)
782 22 : NULLIFY (root_section, force_env_section, force_env_sections, rs_grid_section)
783 22 : CALL force_env_get(force_env, root_section=root_section)
784 22 : force_env_sections => section_vals_get_subs_vals(root_section, "FORCE_EVAL")
785 22 : CALL multiple_fe_list(force_env_sections, root_section, i_force_eval, n_force_eval)
786 : CALL section_vals_duplicate(force_env_sections, force_env_section, &
787 22 : i_force_eval(2), i_force_eval(2))
788 22 : rs_grid_section => section_vals_get_subs_vals(force_env_section, "DFT%MGRID%RS_GRID")
789 : CALL init_input_type(input_settings, &
790 : nsmax=2*MAX(1, return_cube_max_iradius(mixed_cdft%pw_env%cube_info(1))) + 1, &
791 : rs_grid_section=rs_grid_section, ilevel=1, &
792 22 : higher_grid_layout=higher_grid_layout)
793 22 : NULLIFY (rs_descs(1)%rs_desc)
794 22 : CALL rs_grid_create_descriptor(rs_descs(1)%rs_desc, pw_grid, input_settings)
795 22 : IF (rs_descs(1)%rs_desc%distributed) higher_grid_layout = rs_descs(1)%rs_desc%group_dim
796 22 : CALL rs_grid_create(rs_grids(1), rs_descs(1)%rs_desc)
797 22 : CALL rs_grid_print(rs_grids(1), iounit)
798 22 : mixed_cdft%pw_env%rs_descs => rs_descs
799 22 : mixed_cdft%pw_env%rs_grids => rs_grids
800 : ! qs_kind_set
801 : subsys_section => section_vals_get_subs_vals(force_env_sections, "SUBSYS", &
802 22 : i_rep_section=i_force_eval(1))
803 22 : kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
804 22 : NULLIFY (qs_kind_set)
805 22 : CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
806 : CALL create_qs_kind_set(qs_kind_set, atomic_kind_set, kind_section, &
807 22 : force_env%para_env, force_env_section, silent=.FALSE.)
808 22 : mixed_cdft%qs_kind_set => qs_kind_set
809 22 : DEALLOCATE (i_force_eval)
810 22 : CALL section_vals_release(force_env_section)
811 : END IF
812 : CALL force_env_get(force_env=force_env, &
813 22 : force_env_section=force_env_section)
814 22 : CALL pw_grid_release(pw_grid)
815 22 : mixed_cdft%pw_env%auxbas_grid = 1
816 22 : NULLIFY (mixed_cdft%pw_env%pw_pools)
817 22 : mixed_cdft%pw_env%pw_pools => pw_pools
818 220 : bo = settings%bo
819 : ! Determine which processors need to exchange data when redistributing the weight/gradient
820 22 : IF (.NOT. mixed_cdft%is_special) THEN
821 22 : ALLOCATE (mixed_cdft%dest_list(2))
822 22 : ALLOCATE (mixed_cdft%source_list(2))
823 22 : imap = force_env%para_env%mepos/2
824 66 : mixed_cdft%dest_list = [imap, imap + force_env%para_env%num_pe/2]
825 : imap = MOD(force_env%para_env%mepos, force_env%para_env%num_pe/2) + &
826 22 : MODULO(force_env%para_env%mepos, force_env%para_env%num_pe/2)
827 66 : mixed_cdft%source_list = [imap, imap + 1]
828 : ! Determine bounds of the data that is replicated
829 22 : ALLOCATE (mixed_cdft%recv_bo(4))
830 22 : ALLOCATE (sendbuffer(2), recvbuffer(2), recvbuffer2(2))
831 22 : IF (mixed_cdft%is_pencil) THEN
832 0 : sendbuffer = [bo_mixed(1, 2), bo_mixed(2, 2)]
833 : ELSE
834 66 : sendbuffer = [bo_mixed(1, 1), bo_mixed(2, 1)]
835 : END IF
836 : ! Communicate bounds in steps
837 : CALL force_env%para_env%isend(msgin=sendbuffer, dest=mixed_cdft%dest_list(1), &
838 22 : request=req(1))
839 : CALL force_env%para_env%irecv(msgout=recvbuffer, source=mixed_cdft%source_list(1), &
840 22 : request=req(2))
841 : CALL force_env%para_env%irecv(msgout=recvbuffer2, source=mixed_cdft%source_list(2), &
842 22 : request=req(3))
843 22 : CALL req(1)%wait()
844 : CALL force_env%para_env%isend(msgin=sendbuffer, dest=mixed_cdft%dest_list(2), &
845 22 : request=req(1))
846 22 : CALL mp_waitall(req)
847 110 : mixed_cdft%recv_bo(1:2) = recvbuffer
848 110 : mixed_cdft%recv_bo(3:4) = recvbuffer2
849 22 : DEALLOCATE (sendbuffer, recvbuffer, recvbuffer2)
850 : ELSE
851 0 : IF (mixed_env%do_mixed_qmmm_cdft) THEN
852 0 : qs_env => force_env_qs%qmmm_env%qs_env
853 : ELSE
854 0 : CALL force_env_get(force_env_qs, qs_env=qs_env)
855 : END IF
856 0 : CALL get_qs_env(qs_env, pw_env=pw_env)
857 0 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
858 : ! work out the pw grid points each proc holds in the two (identical) parallel proc groups
859 : ! note we only care about the x dir since we assume the y dir is not subdivided
860 0 : ALLOCATE (bounds(0:auxbas_pw_pool%pw_grid%para%group%num_pe - 1, 1:2))
861 0 : DO i = 0, auxbas_pw_pool%pw_grid%para%group%num_pe - 1
862 0 : bounds(i, 1:2) = auxbas_pw_pool%pw_grid%para%bo(1:2, 1, i, 1)
863 0 : bounds(i, 1:2) = bounds(i, 1:2) - auxbas_pw_pool%pw_grid%npts(1)/2 - 1
864 : END DO
865 : ! work out which procs to send my grid points
866 : ! first get the number of target procs per group
867 0 : ntargets = 0
868 0 : offset = -1
869 0 : DO i = 0, auxbas_pw_pool%pw_grid%para%group%num_pe - 1
870 0 : IF ((bounds(i, 1) >= bo_mixed(1, 1) .AND. bounds(i, 1) <= bo_mixed(2, 1)) .OR. &
871 0 : (bounds(i, 2) >= bo_mixed(1, 1) .AND. bounds(i, 2) <= bo_mixed(2, 1))) THEN
872 0 : ntargets = ntargets + 1
873 0 : IF (offset == -1) offset = i
874 0 : ELSE IF (bounds(i, 2) > bo_mixed(2, 1)) THEN
875 : EXIT
876 : ELSE
877 0 : CYCLE
878 : END IF
879 : END DO
880 0 : ALLOCATE (mixed_cdft%dest_list(ntargets))
881 0 : ALLOCATE (mixed_cdft%dest_list_bo(2, ntargets))
882 : ! now determine the actual grid points to send
883 0 : j = 1
884 0 : DO i = offset, offset + ntargets - 1
885 0 : mixed_cdft%dest_list(j) = i
886 : mixed_cdft%dest_list_bo(:, j) = [bo_mixed(1, 1) + (bounds(i, 1) - bo_mixed(1, 1)), &
887 0 : bo_mixed(2, 1) + (bounds(i, 2) - bo_mixed(2, 1))]
888 0 : j = j + 1
889 : END DO
890 0 : ALLOCATE (mixed_cdft%dest_list_save(ntargets), mixed_cdft%dest_bo_save(2, ntargets))
891 : ! We need to store backups of these arrays since they might get reallocated during dlb
892 0 : mixed_cdft%dest_list_save = mixed_cdft%dest_list
893 0 : mixed_cdft%dest_bo_save = mixed_cdft%dest_list_bo
894 : ! finally determine which procs will send me grid points
895 : ! now we need info about y dir also
896 0 : DEALLOCATE (bounds)
897 0 : ALLOCATE (bounds(0:pw_pools(1)%pool%pw_grid%para%group%num_pe - 1, 1:4))
898 0 : DO i = 0, pw_pools(1)%pool%pw_grid%para%group%num_pe - 1
899 0 : bounds(i, 1:2) = pw_pools(1)%pool%pw_grid%para%bo(1:2, 1, i, 1)
900 0 : bounds(i, 3:4) = pw_pools(1)%pool%pw_grid%para%bo(1:2, 2, i, 1)
901 0 : bounds(i, 1:2) = bounds(i, 1:2) - pw_pools(1)%pool%pw_grid%npts(1)/2 - 1
902 0 : bounds(i, 3:4) = bounds(i, 3:4) - pw_pools(1)%pool%pw_grid%npts(2)/2 - 1
903 : END DO
904 0 : ntargets = 0
905 0 : offset = -1
906 0 : DO i = 0, pw_pools(1)%pool%pw_grid%para%group%num_pe - 1
907 0 : IF ((bo(1, 1) >= bounds(i, 1) .AND. bo(1, 1) <= bounds(i, 2)) .OR. &
908 0 : (bo(2, 1) >= bounds(i, 1) .AND. bo(2, 1) <= bounds(i, 2))) THEN
909 0 : ntargets = ntargets + 1
910 0 : IF (offset == -1) offset = i
911 0 : ELSE IF (bo(2, 1) < bounds(i, 1)) THEN
912 : EXIT
913 : ELSE
914 0 : CYCLE
915 : END IF
916 : END DO
917 0 : ALLOCATE (mixed_cdft%source_list(ntargets))
918 0 : ALLOCATE (mixed_cdft%source_list_bo(4, ntargets))
919 0 : j = 1
920 0 : DO i = offset, offset + ntargets - 1
921 0 : mixed_cdft%source_list(j) = i
922 0 : IF (bo(1, 1) >= bounds(i, 1) .AND. bo(2, 1) <= bounds(i, 2)) THEN
923 : mixed_cdft%source_list_bo(:, j) = [bo(1, 1), bo(2, 1), &
924 0 : bounds(i, 3), bounds(i, 4)]
925 0 : ELSE IF (bo(1, 1) >= bounds(i, 1) .AND. bo(1, 1) <= bounds(i, 2)) THEN
926 : mixed_cdft%source_list_bo(:, j) = [bo(1, 1), bounds(i, 2), &
927 0 : bounds(i, 3), bounds(i, 4)]
928 : ELSE
929 : mixed_cdft%source_list_bo(:, j) = [bounds(i, 1), bo(2, 1), &
930 0 : bounds(i, 3), bounds(i, 4)]
931 : END IF
932 0 : j = j + 1
933 : END DO
934 0 : ALLOCATE (mixed_cdft%source_list_save(ntargets), mixed_cdft%source_bo_save(4, ntargets))
935 : ! We need to store backups of these arrays since they might get reallocated during dlb
936 0 : mixed_cdft%source_list_save = mixed_cdft%source_list
937 0 : mixed_cdft%source_bo_save = mixed_cdft%source_list_bo
938 0 : DEALLOCATE (bounds)
939 : END IF
940 : ELSE
941 : ! Create loggers to redirect the output of all CDFT states to different files
942 : ! even when the states are treated in serial (the initial print of QS data [basis set etc] for
943 : ! all states unfortunately goes to the first log file)
944 50 : CALL force_env_get(force_env, root_section=root_section)
945 224 : ALLOCATE (mixed_cdft%sub_logger(nforce_eval - 1))
946 124 : DO i = 1, nforce_eval - 1
947 74 : IF (force_env%para_env%is_source()) THEN
948 : CALL section_vals_val_get(root_section, "GLOBAL%PROJECT_NAME", &
949 37 : c_val=input_file_path)
950 37 : lp = LEN_TRIM(input_file_path)
951 37 : input_file_path(lp + 1:LEN(input_file_path)) = "-r-"//ADJUSTL(cp_to_string(i + 1))
952 37 : lp = LEN_TRIM(input_file_path)
953 37 : output_file_path = input_file_path(1:lp)//".out"
954 : CALL open_file(file_name=output_file_path, file_status="UNKNOWN", &
955 : file_action="WRITE", file_position="APPEND", &
956 37 : unit_number=unit_nr)
957 : ELSE
958 37 : unit_nr = -1
959 : END IF
960 : CALL cp_logger_create(mixed_cdft%sub_logger(i)%p, &
961 : para_env=force_env%para_env, &
962 : default_global_unit_nr=unit_nr, &
963 74 : close_global_unit_on_dealloc=.FALSE.)
964 : ! Try to use better names for the local log if it is not too late
965 : CALL section_vals_val_get(root_section, "GLOBAL%OUTPUT_FILE_NAME", &
966 74 : c_val=c_val)
967 74 : IF (c_val /= "") THEN
968 : CALL cp_logger_set(mixed_cdft%sub_logger(i)%p, &
969 0 : local_filename=TRIM(c_val)//"_localLog")
970 : END IF
971 74 : CALL section_vals_val_get(root_section, "GLOBAL%PROJECT", c_val=c_val)
972 74 : IF (c_val /= "") THEN
973 : CALL cp_logger_set(mixed_cdft%sub_logger(i)%p, &
974 74 : local_filename=TRIM(c_val)//"_localLog")
975 : END IF
976 74 : IF (LEN_TRIM(c_val) > default_string_length) THEN
977 0 : CPWARN("The mixed CDFT project name will be truncated.")
978 : END IF
979 74 : mixed_cdft%sub_logger(i)%p%iter_info%project_name = TRIM(c_val)
980 : CALL section_vals_val_get(root_section, "GLOBAL%PRINT_LEVEL", &
981 124 : i_val=mixed_cdft%sub_logger(i)%p%iter_info%print_level)
982 : END DO
983 50 : IF (mixed_cdft%wfn_overlap_method) THEN
984 : ! qs_kind_set
985 6 : NULLIFY (root_section, force_env_section, force_env_sections, rs_grid_section)
986 6 : CALL force_env_get(force_env, root_section=root_section)
987 6 : force_env_sections => section_vals_get_subs_vals(root_section, "FORCE_EVAL")
988 6 : CALL multiple_fe_list(force_env_sections, root_section, i_force_eval, n_force_eval)
989 : CALL section_vals_duplicate(force_env_sections, force_env_section, &
990 6 : i_force_eval(2), i_force_eval(2))
991 : subsys_section => section_vals_get_subs_vals(force_env_sections, "SUBSYS", &
992 6 : i_rep_section=i_force_eval(1))
993 6 : kind_section => section_vals_get_subs_vals(subsys_section, "KIND")
994 6 : NULLIFY (qs_kind_set)
995 6 : CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
996 : CALL create_qs_kind_set(qs_kind_set, atomic_kind_set, kind_section, &
997 6 : force_env%para_env, force_env_section, silent=.FALSE.)
998 6 : mixed_cdft%qs_kind_set => qs_kind_set
999 6 : DEALLOCATE (i_force_eval)
1000 6 : CALL section_vals_release(force_env_section)
1001 6 : mixed_cdft%qs_kind_set => qs_kind_set
1002 : END IF
1003 : CALL force_env_get(force_env=force_env, &
1004 50 : force_env_section=force_env_section)
1005 : END IF
1006 : ! Deallocate settings temporaries
1007 72 : DEALLOCATE (settings%grid_span)
1008 72 : DEALLOCATE (settings%npts)
1009 72 : DEALLOCATE (settings%spherical)
1010 72 : DEALLOCATE (settings%rs_dims)
1011 72 : DEALLOCATE (settings%odd)
1012 72 : DEALLOCATE (settings%atoms)
1013 72 : IF (mixed_cdft%run_type == mixed_cdft_parallel) &
1014 22 : DEALLOCATE (settings%coeffs)
1015 72 : DEALLOCATE (settings%cutoffs)
1016 72 : DEALLOCATE (settings%radii)
1017 72 : DEALLOCATE (settings%si)
1018 72 : DEALLOCATE (settings%sr)
1019 72 : DEALLOCATE (settings%sb)
1020 72 : DEALLOCATE (settings%cutoff)
1021 72 : DEALLOCATE (settings%rel_cutoff)
1022 : ! Setup mixed blacs_env for redistributing arrays during ET coupling calculation
1023 72 : IF (mixed_env%do_mixed_et) THEN
1024 72 : NULLIFY (root_section)
1025 72 : CALL force_env_get(force_env, globenv=globenv, root_section=root_section)
1026 : CALL cp_blacs_env_create(mixed_cdft%blacs_env, force_env%para_env, globenv%blacs_grid_layout, &
1027 72 : globenv%blacs_repeatable)
1028 : END IF
1029 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
1030 72 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1031 :
1032 360 : END SUBROUTINE mixed_cdft_init_structures
1033 :
1034 : ! **************************************************************************************************
1035 : !> \brief Redistribute arrays needed for an ET coupling calculation from individual CDFT states to
1036 : !> the mixed CDFT env, that is, move the arrays to the correct blacs context. For parallel
1037 : !> simulations, the array processor distributions also change from N to 2N processors.
1038 : !> \param force_env the force_env that holds the CDFT states
1039 : !> \par History
1040 : !> 01.2017 created [Nico Holmberg]
1041 : ! **************************************************************************************************
1042 94 : SUBROUTINE mixed_cdft_redistribute_arrays(force_env)
1043 : TYPE(force_env_type), POINTER :: force_env
1044 :
1045 : INTEGER :: iforce_eval, ispin, ivar, ncol_overlap, &
1046 : ncol_wmat, nforce_eval, nrow_overlap, &
1047 : nrow_wmat, nspins, nvar
1048 94 : INTEGER, ALLOCATABLE, DIMENSION(:) :: ncol_mo, nrow_mo
1049 : LOGICAL :: uniform_occupation
1050 94 : LOGICAL, ALLOCATABLE, DIMENSION(:) :: has_occupation_numbers
1051 94 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:, :) :: occno_tmp
1052 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1053 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo, fm_struct_overlap, &
1054 : fm_struct_tmp, fm_struct_wmat
1055 : TYPE(cp_fm_type) :: matrix_s_tmp, mixed_matrix_s_tmp
1056 94 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :) :: matrix_p_tmp, mixed_matrix_p_tmp, &
1057 94 : mixed_wmat_tmp, mo_coeff_tmp, wmat_tmp
1058 94 : TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: mixed_mo_coeff
1059 94 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: density_matrix, w_matrix
1060 : TYPE(dbcsr_type) :: desymm_tmp
1061 : TYPE(dbcsr_type), POINTER :: mixed_matrix_s
1062 : TYPE(dft_control_type), POINTER :: dft_control
1063 : TYPE(force_env_type), POINTER :: force_env_qs
1064 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1065 : TYPE(mixed_environment_type), POINTER :: mixed_env
1066 : TYPE(qs_environment_type), POINTER :: qs_env
1067 :
1068 94 : NULLIFY (mixed_env, mixed_cdft, qs_env, dft_control, fm_struct_mo, &
1069 94 : fm_struct_wmat, fm_struct_overlap, fm_struct_tmp, &
1070 94 : mixed_mo_coeff, mixed_matrix_s, density_matrix, blacs_env, w_matrix, force_env_qs)
1071 0 : CPASSERT(ASSOCIATED(force_env))
1072 94 : mixed_env => force_env%mixed_env
1073 94 : nforce_eval = SIZE(force_env%sub_force_env)
1074 94 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
1075 94 : CPASSERT(ASSOCIATED(mixed_cdft))
1076 94 : CALL mixed_cdft_work_type_init(mixed_cdft%matrix)
1077 : ! Get nspins and query for non-uniform occupation numbers
1078 282 : ALLOCATE (has_occupation_numbers(nforce_eval))
1079 306 : has_occupation_numbers = .FALSE.
1080 306 : DO iforce_eval = 1, nforce_eval
1081 212 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1082 176 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
1083 176 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1084 24 : qs_env => force_env_qs%qmmm_env%qs_env
1085 : ELSE
1086 152 : CALL force_env_get(force_env_qs, qs_env=qs_env)
1087 : END IF
1088 176 : CALL get_qs_env(qs_env, dft_control=dft_control)
1089 176 : CPASSERT(ASSOCIATED(dft_control))
1090 176 : nspins = dft_control%nspins
1091 176 : IF (force_env_qs%para_env%is_source()) &
1092 236 : has_occupation_numbers(iforce_eval) = ALLOCATED(dft_control%qs_control%cdft_control%occupations)
1093 : END DO
1094 94 : CALL force_env%para_env%sum(has_occupation_numbers(1))
1095 212 : DO iforce_eval = 2, nforce_eval
1096 118 : CALL force_env%para_env%sum(has_occupation_numbers(iforce_eval))
1097 118 : IF (has_occupation_numbers(1) .NEQV. has_occupation_numbers(iforce_eval)) &
1098 : CALL cp_abort(__LOCATION__, &
1099 94 : "Mixing of uniform and non-uniform occupations is not allowed.")
1100 : END DO
1101 94 : uniform_occupation = .NOT. has_occupation_numbers(1)
1102 94 : DEALLOCATE (has_occupation_numbers)
1103 : ! Get number of weight functions per state as well as the type of each constraint
1104 94 : nvar = SIZE(dft_control%qs_control%cdft_control%target)
1105 94 : IF (.NOT. ALLOCATED(mixed_cdft%constraint_type)) THEN
1106 288 : ALLOCATE (mixed_cdft%constraint_type(nvar, nforce_eval))
1107 412 : mixed_cdft%constraint_type(:, :) = 0
1108 72 : IF (mixed_cdft%identical_constraints) THEN
1109 142 : DO ivar = 1, nvar
1110 : mixed_cdft%constraint_type(ivar, :) = &
1111 310 : dft_control%qs_control%cdft_control%group(ivar)%constraint_type
1112 : END DO
1113 : ELSE
1114 : ! Possibly couple spin and charge constraints
1115 6 : DO iforce_eval = 1, nforce_eval
1116 4 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1117 4 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1118 0 : qs_env => force_env%sub_force_env(iforce_eval)%force_env%qmmm_env%qs_env
1119 : ELSE
1120 4 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, qs_env=qs_env)
1121 : END IF
1122 4 : CALL get_qs_env(qs_env, dft_control=dft_control)
1123 6 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1124 4 : DO ivar = 1, nvar
1125 : mixed_cdft%constraint_type(ivar, iforce_eval) = &
1126 4 : dft_control%qs_control%cdft_control%group(ivar)%constraint_type
1127 : END DO
1128 : END IF
1129 : END DO
1130 2 : CALL force_env%para_env%sum(mixed_cdft%constraint_type)
1131 : END IF
1132 : END IF
1133 : ! Transfer data from sub_force_envs to temporaries
1134 988 : ALLOCATE (mixed_cdft%matrix%mixed_mo_coeff(nforce_eval, nspins))
1135 94 : mixed_mo_coeff => mixed_cdft%matrix%mixed_mo_coeff
1136 688 : ALLOCATE (mixed_cdft%matrix%w_matrix(nforce_eval, nvar))
1137 94 : w_matrix => mixed_cdft%matrix%w_matrix
1138 94 : CALL dbcsr_init_p(mixed_cdft%matrix%mixed_matrix_s)
1139 94 : mixed_matrix_s => mixed_cdft%matrix%mixed_matrix_s
1140 94 : IF (mixed_cdft%calculate_metric) THEN
1141 144 : ALLOCATE (mixed_cdft%matrix%density_matrix(nforce_eval, nspins))
1142 14 : density_matrix => mixed_cdft%matrix%density_matrix
1143 : END IF
1144 1488 : ALLOCATE (mo_coeff_tmp(nforce_eval, nspins), wmat_tmp(nforce_eval, nvar))
1145 376 : ALLOCATE (nrow_mo(nspins), ncol_mo(nspins))
1146 210 : IF (mixed_cdft%calculate_metric) ALLOCATE (matrix_p_tmp(nforce_eval, nspins))
1147 94 : IF (.NOT. uniform_occupation) THEN
1148 140 : ALLOCATE (mixed_cdft%occupations(nforce_eval, nspins))
1149 126 : ALLOCATE (occno_tmp(nforce_eval, nspins))
1150 : END IF
1151 306 : DO iforce_eval = 1, nforce_eval
1152 : ! Temporary arrays need to be nulled on every process
1153 636 : DO ispin = 1, nspins
1154 : ! Valgrind 3.12/gfortran 4.8.4 oddly complains here (unconditional jump)
1155 : ! if mixed_cdft%calculate_metric = .FALSE. and the need to null the array
1156 : ! is queried with IF (mixed_cdft%calculate_metric) &
1157 424 : IF (.NOT. uniform_occupation) &
1158 268 : NULLIFY (occno_tmp(iforce_eval, ispin)%array)
1159 : END DO
1160 212 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1161 : ! From this point onward, we access data local to the sub_force_envs
1162 : ! Get qs_env
1163 176 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
1164 176 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1165 24 : qs_env => force_env_qs%qmmm_env%qs_env
1166 : ELSE
1167 152 : CALL force_env_get(force_env_qs, qs_env=qs_env)
1168 : END IF
1169 176 : CALL get_qs_env(qs_env, dft_control=dft_control, blacs_env=blacs_env)
1170 : ! Store dimensions of the transferred arrays
1171 : CALL dbcsr_get_info(dft_control%qs_control%cdft_control%matrix_s%matrix, &
1172 176 : nfullrows_total=nrow_overlap, nfullcols_total=ncol_overlap)
1173 : CALL dbcsr_get_info(dft_control%qs_control%cdft_control%wmat(1)%matrix, &
1174 176 : nfullrows_total=nrow_wmat, nfullcols_total=ncol_wmat)
1175 : ! MO Coefficients
1176 528 : DO ispin = 1, nspins
1177 : CALL cp_fm_get_info(dft_control%qs_control%cdft_control%mo_coeff(ispin), &
1178 352 : ncol_global=ncol_mo(ispin), nrow_global=nrow_mo(ispin))
1179 : CALL cp_fm_create(matrix=mo_coeff_tmp(iforce_eval, ispin), &
1180 : matrix_struct=dft_control%qs_control%cdft_control%mo_coeff(ispin)%matrix_struct, &
1181 : name="MO_COEFF_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_" &
1182 352 : //TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1183 : CALL cp_fm_to_fm(dft_control%qs_control%cdft_control%mo_coeff(ispin), &
1184 528 : mo_coeff_tmp(iforce_eval, ispin))
1185 : END DO
1186 176 : CALL cp_fm_release(dft_control%qs_control%cdft_control%mo_coeff)
1187 : ! Matrix representation(s) of the weight function(s) (dbcsr -> fm)
1188 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nrow_wmat, ncol_global=ncol_wmat, context=blacs_env, &
1189 : para_env=force_env%sub_force_env(iforce_eval)%force_env%para_env, &
1190 176 : square_blocks=.TRUE.)
1191 356 : DO ivar = 1, nvar
1192 180 : CALL cp_fm_create(wmat_tmp(iforce_eval, ivar), fm_struct_tmp, name="w_matrix")
1193 180 : CALL dbcsr_desymmetrize(dft_control%qs_control%cdft_control%wmat(ivar)%matrix, desymm_tmp)
1194 180 : CALL copy_dbcsr_to_fm(desymm_tmp, wmat_tmp(iforce_eval, ivar))
1195 180 : CALL dbcsr_release(desymm_tmp)
1196 356 : CALL dbcsr_release_p(dft_control%qs_control%cdft_control%wmat(ivar)%matrix)
1197 : END DO
1198 176 : DEALLOCATE (dft_control%qs_control%cdft_control%wmat)
1199 176 : CALL cp_fm_struct_release(fm_struct_tmp)
1200 : ! Overlap matrix is the same for all sub_force_envs, so we just copy the first one (dbcsr -> fm)
1201 176 : IF (iforce_eval == 1) THEN
1202 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=nrow_overlap, &
1203 : ncol_global=ncol_overlap, context=blacs_env, &
1204 76 : para_env=force_env%sub_force_env(iforce_eval)%force_env%para_env)
1205 76 : CALL cp_fm_create(matrix_s_tmp, fm_struct_tmp, name="s_matrix")
1206 76 : CALL cp_fm_struct_release(fm_struct_tmp)
1207 76 : CALL dbcsr_desymmetrize(dft_control%qs_control%cdft_control%matrix_s%matrix, desymm_tmp)
1208 76 : CALL copy_dbcsr_to_fm(desymm_tmp, matrix_s_tmp)
1209 76 : CALL dbcsr_release(desymm_tmp)
1210 : END IF
1211 176 : CALL dbcsr_release_p(dft_control%qs_control%cdft_control%matrix_s%matrix)
1212 : ! Density_matrix (dbcsr -> fm)
1213 176 : IF (mixed_cdft%calculate_metric) THEN
1214 72 : DO ispin = 1, nspins
1215 : ! Size AOxAO
1216 : CALL cp_fm_struct_create(fm_struct_tmp, nrow_global=ncol_overlap, &
1217 : ncol_global=ncol_overlap, context=blacs_env, &
1218 48 : para_env=force_env%sub_force_env(iforce_eval)%force_env%para_env)
1219 48 : CALL cp_fm_create(matrix_p_tmp(iforce_eval, ispin), fm_struct_tmp, name="dm_matrix")
1220 48 : CALL cp_fm_struct_release(fm_struct_tmp)
1221 48 : CALL dbcsr_desymmetrize(dft_control%qs_control%cdft_control%matrix_p(ispin)%matrix, desymm_tmp)
1222 48 : CALL copy_dbcsr_to_fm(desymm_tmp, matrix_p_tmp(iforce_eval, ispin))
1223 48 : CALL dbcsr_release(desymm_tmp)
1224 72 : CALL dbcsr_release_p(dft_control%qs_control%cdft_control%matrix_p(ispin)%matrix)
1225 : END DO
1226 24 : DEALLOCATE (dft_control%qs_control%cdft_control%matrix_p)
1227 : END IF
1228 : ! Occupation numbers
1229 446 : IF (.NOT. uniform_occupation) THEN
1230 84 : DO ispin = 1, nspins
1231 56 : IF (ncol_mo(ispin) /= SIZE(dft_control%qs_control%cdft_control%occupations(ispin)%array)) &
1232 0 : CPABORT("Array dimensions dont match.")
1233 56 : IF (force_env_qs%para_env%is_source()) THEN
1234 84 : ALLOCATE (occno_tmp(iforce_eval, ispin)%array(ncol_mo(ispin)))
1235 126 : occno_tmp(iforce_eval, ispin)%array = dft_control%qs_control%cdft_control%occupations(ispin)%array
1236 : END IF
1237 84 : DEALLOCATE (dft_control%qs_control%cdft_control%occupations(ispin)%array)
1238 : END DO
1239 28 : DEALLOCATE (dft_control%qs_control%cdft_control%occupations)
1240 : END IF
1241 : END DO
1242 : ! Create needed fm structs
1243 : CALL cp_fm_struct_create(fm_struct_wmat, nrow_global=nrow_wmat, ncol_global=ncol_wmat, &
1244 94 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
1245 : CALL cp_fm_struct_create(fm_struct_overlap, nrow_global=nrow_overlap, ncol_global=ncol_overlap, &
1246 94 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
1247 : ! Redistribute arrays with copy_general (this is not optimal for dbcsr matrices but...)
1248 : ! We use this method for the serial case (mixed_cdft%run_type == mixed_cdft_serial) as well to move the arrays to the
1249 : ! correct blacs_env, which is impossible using a simple copy of the arrays
1250 594 : ALLOCATE (mixed_wmat_tmp(nforce_eval, nvar))
1251 94 : IF (mixed_cdft%calculate_metric) &
1252 130 : ALLOCATE (mixed_matrix_p_tmp(nforce_eval, nspins))
1253 306 : DO iforce_eval = 1, nforce_eval
1254 : ! MO coefficients
1255 636 : DO ispin = 1, nspins
1256 424 : NULLIFY (fm_struct_mo)
1257 : CALL cp_fm_struct_create(fm_struct_mo, nrow_global=nrow_mo(ispin), ncol_global=ncol_mo(ispin), &
1258 424 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
1259 : CALL cp_fm_create(matrix=mixed_mo_coeff(iforce_eval, ispin), &
1260 : matrix_struct=fm_struct_mo, &
1261 : name="MO_COEFF_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_" &
1262 424 : //TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1263 : CALL cp_fm_copy_general(mo_coeff_tmp(iforce_eval, ispin), &
1264 : mixed_mo_coeff(iforce_eval, ispin), &
1265 424 : mixed_cdft%blacs_env%para_env)
1266 424 : CALL cp_fm_release(mo_coeff_tmp(iforce_eval, ispin))
1267 636 : CALL cp_fm_struct_release(fm_struct_mo)
1268 : END DO
1269 : ! Weight
1270 428 : DO ivar = 1, nvar
1271 216 : NULLIFY (w_matrix(iforce_eval, ivar)%matrix)
1272 216 : CALL dbcsr_init_p(w_matrix(iforce_eval, ivar)%matrix)
1273 : CALL cp_fm_create(matrix=mixed_wmat_tmp(iforce_eval, ivar), &
1274 : matrix_struct=fm_struct_wmat, &
1275 216 : name="WEIGHT_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_MATRIX")
1276 : CALL cp_fm_copy_general(wmat_tmp(iforce_eval, ivar), &
1277 : mixed_wmat_tmp(iforce_eval, ivar), &
1278 216 : mixed_cdft%blacs_env%para_env)
1279 216 : CALL cp_fm_release(wmat_tmp(iforce_eval, ivar))
1280 : ! (fm -> dbcsr)
1281 : CALL copy_fm_to_dbcsr_bc(mixed_wmat_tmp(iforce_eval, ivar), &
1282 216 : w_matrix(iforce_eval, ivar)%matrix)
1283 428 : CALL cp_fm_release(mixed_wmat_tmp(iforce_eval, ivar))
1284 : END DO
1285 : ! Density matrix (fm -> dbcsr)
1286 306 : IF (mixed_cdft%calculate_metric) THEN
1287 90 : DO ispin = 1, nspins
1288 60 : NULLIFY (density_matrix(iforce_eval, ispin)%matrix)
1289 60 : CALL dbcsr_init_p(density_matrix(iforce_eval, ispin)%matrix)
1290 : CALL cp_fm_create(matrix=mixed_matrix_p_tmp(iforce_eval, ispin), &
1291 : matrix_struct=fm_struct_overlap, &
1292 : name="DENSITY_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_"// &
1293 60 : TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1294 : CALL cp_fm_copy_general(matrix_p_tmp(iforce_eval, ispin), &
1295 : mixed_matrix_p_tmp(iforce_eval, ispin), &
1296 60 : mixed_cdft%blacs_env%para_env)
1297 60 : CALL cp_fm_release(matrix_p_tmp(iforce_eval, ispin))
1298 : CALL copy_fm_to_dbcsr_bc(mixed_matrix_p_tmp(iforce_eval, ispin), &
1299 60 : density_matrix(iforce_eval, ispin)%matrix)
1300 90 : CALL cp_fm_release(mixed_matrix_p_tmp(iforce_eval, ispin))
1301 : END DO
1302 : END IF
1303 : END DO
1304 94 : CALL cp_fm_struct_release(fm_struct_wmat)
1305 94 : DEALLOCATE (mo_coeff_tmp, wmat_tmp, mixed_wmat_tmp)
1306 94 : IF (mixed_cdft%calculate_metric) THEN
1307 14 : DEALLOCATE (matrix_p_tmp)
1308 14 : DEALLOCATE (mixed_matrix_p_tmp)
1309 : END IF
1310 : ! Overlap (fm -> dbcsr)
1311 : CALL cp_fm_create(matrix=mixed_matrix_s_tmp, &
1312 : matrix_struct=fm_struct_overlap, &
1313 94 : name="OVERLAP_MATRIX")
1314 94 : CALL cp_fm_struct_release(fm_struct_overlap)
1315 : CALL cp_fm_copy_general(matrix_s_tmp, &
1316 : mixed_matrix_s_tmp, &
1317 94 : mixed_cdft%blacs_env%para_env)
1318 94 : CALL cp_fm_release(matrix_s_tmp)
1319 94 : CALL copy_fm_to_dbcsr_bc(mixed_matrix_s_tmp, mixed_matrix_s)
1320 94 : CALL cp_fm_release(mixed_matrix_s_tmp)
1321 : ! Occupation numbers
1322 94 : IF (.NOT. uniform_occupation) THEN
1323 42 : DO iforce_eval = 1, nforce_eval
1324 98 : DO ispin = 1, nspins
1325 168 : ALLOCATE (mixed_cdft%occupations(iforce_eval, ispin)%array(ncol_mo(ispin)))
1326 252 : mixed_cdft%occupations(iforce_eval, ispin)%array = 0.0_dp
1327 56 : IF (ASSOCIATED(occno_tmp(iforce_eval, ispin)%array)) THEN
1328 126 : mixed_cdft%occupations(iforce_eval, ispin)%array = occno_tmp(iforce_eval, ispin)%array
1329 28 : DEALLOCATE (occno_tmp(iforce_eval, ispin)%array)
1330 : END IF
1331 476 : CALL force_env%para_env%sum(mixed_cdft%occupations(iforce_eval, ispin)%array)
1332 : END DO
1333 : END DO
1334 14 : DEALLOCATE (occno_tmp)
1335 : END IF
1336 94 : DEALLOCATE (ncol_mo, nrow_mo)
1337 :
1338 282 : END SUBROUTINE mixed_cdft_redistribute_arrays
1339 : ! **************************************************************************************************
1340 : !> \brief Routine to print out the electronic coupling(s) between CDFT states.
1341 : !> \param force_env the force_env that holds the CDFT states
1342 : !> \par History
1343 : !> 11.17 created [Nico Holmberg]
1344 : ! **************************************************************************************************
1345 94 : SUBROUTINE mixed_cdft_print_couplings(force_env)
1346 : TYPE(force_env_type), POINTER :: force_env
1347 :
1348 : INTEGER :: iounit, ipermutation, istate, ivar, &
1349 : jstate, nforce_eval, npermutations, &
1350 : nvar
1351 : TYPE(cp_logger_type), POINTER :: logger
1352 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1353 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
1354 :
1355 94 : NULLIFY (print_section, mixed_cdft)
1356 :
1357 94 : logger => cp_get_default_logger()
1358 94 : CPASSERT(ASSOCIATED(force_env))
1359 : CALL force_env_get(force_env=force_env, &
1360 94 : force_env_section=force_env_section)
1361 94 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
1362 94 : CPASSERT(ASSOCIATED(mixed_cdft))
1363 94 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1364 94 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
1365 : !
1366 94 : CPASSERT(ALLOCATED(mixed_cdft%results%strength))
1367 94 : CPASSERT(ALLOCATED(mixed_cdft%results%W_diagonal))
1368 94 : CPASSERT(ALLOCATED(mixed_cdft%results%S))
1369 94 : CPASSERT(ALLOCATED(mixed_cdft%results%energy))
1370 94 : nforce_eval = SIZE(force_env%sub_force_env)
1371 94 : nvar = SIZE(mixed_cdft%results%strength, 1)
1372 94 : npermutations = nforce_eval*(nforce_eval - 1)/2 ! Size of upper triangular part
1373 94 : IF (iounit > 0) THEN
1374 : WRITE (iounit, '(/,T3,A,T66)') &
1375 47 : '------------------------- CDFT coupling information --------------------------'
1376 : WRITE (iounit, '(T3,A,T66,(3X,F12.2))') &
1377 47 : 'Information at step (fs):', mixed_cdft%sim_step*mixed_cdft%sim_dt
1378 135 : DO ipermutation = 1, npermutations
1379 88 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1380 88 : WRITE (iounit, '(/,T3,A)') REPEAT('#', 44)
1381 88 : WRITE (iounit, '(T3,A,I3,A,I3,A)') '###### CDFT states I =', istate, ' and J = ', jstate, ' ######'
1382 88 : WRITE (iounit, '(T3,A)') REPEAT('#', 44)
1383 177 : DO ivar = 1, nvar
1384 89 : IF (ivar > 1) &
1385 1 : WRITE (iounit, '(A)') ''
1386 89 : WRITE (iounit, '(T3,A,T60,(3X,I18))') 'Atomic group:', ivar
1387 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1388 89 : 'Strength of constraint I:', mixed_cdft%results%strength(ivar, istate)
1389 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1390 89 : 'Strength of constraint J:', mixed_cdft%results%strength(ivar, jstate)
1391 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1392 89 : 'Final value of constraint I:', mixed_cdft%results%W_diagonal(ivar, istate)
1393 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1394 177 : 'Final value of constraint J:', mixed_cdft%results%W_diagonal(ivar, jstate)
1395 : END DO
1396 : WRITE (iounit, '(/,T3,A,T60,(3X,F18.12))') &
1397 88 : 'Overlap between states I and J:', mixed_cdft%results%S(istate, jstate)
1398 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1399 88 : 'Charge transfer energy (J-I) (Hartree):', (mixed_cdft%results%energy(jstate) - mixed_cdft%results%energy(istate))
1400 88 : WRITE (iounit, *)
1401 88 : IF (ALLOCATED(mixed_cdft%results%rotation)) THEN
1402 86 : IF (ABS(mixed_cdft%results%rotation(ipermutation))*1.0E3_dp >= 0.1_dp) THEN
1403 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1404 83 : 'Diabatic electronic coupling (rotation, mHartree):', &
1405 166 : ABS(mixed_cdft%results%rotation(ipermutation)*1.0E3_dp)
1406 : ELSE
1407 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1408 3 : 'Diabatic electronic coupling (rotation, microHartree):', &
1409 6 : ABS(mixed_cdft%results%rotation(ipermutation)*1.0E6_dp)
1410 : END IF
1411 : END IF
1412 88 : IF (ALLOCATED(mixed_cdft%results%lowdin)) THEN
1413 10 : IF (ABS(mixed_cdft%results%lowdin(ipermutation))*1.0E3_dp >= 0.1_dp) THEN
1414 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1415 9 : 'Diabatic electronic coupling (Lowdin, mHartree):', &
1416 18 : ABS(mixed_cdft%results%lowdin(ipermutation)*1.0E3_dp)
1417 : ELSE
1418 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1419 1 : 'Diabatic electronic coupling (Lowdin, microHartree):', &
1420 2 : ABS(mixed_cdft%results%lowdin(ipermutation)*1.0E6_dp)
1421 : END IF
1422 : END IF
1423 88 : IF (ALLOCATED(mixed_cdft%results%wfn)) THEN
1424 6 : IF (mixed_cdft%results%wfn(ipermutation)*1.0E3_dp >= 0.1_dp) THEN
1425 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1426 5 : 'Diabatic electronic coupling (wfn overlap, mHartree):', &
1427 10 : ABS(mixed_cdft%results%wfn(ipermutation)*1.0E3_dp)
1428 : ELSE
1429 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1430 1 : 'Diabatic electronic coupling (wfn overlap, microHartree):', &
1431 2 : ABS(mixed_cdft%results%wfn(ipermutation)*1.0E6_dp)
1432 : END IF
1433 : END IF
1434 88 : IF (ALLOCATED(mixed_cdft%results%nonortho)) THEN
1435 : WRITE (iounit, '(T3,A,T60,(3X,F18.12))') &
1436 50 : 'Diabatic electronic coupling (nonorthogonal, Hartree):', mixed_cdft%results%nonortho(ipermutation)
1437 : END IF
1438 223 : IF (ALLOCATED(mixed_cdft%results%metric)) THEN
1439 9 : WRITE (iounit, *)
1440 9 : IF (SIZE(mixed_cdft%results%metric, 2) == 1) THEN
1441 : WRITE (iounit, '(T3,A,T66,(3X,F12.6))') &
1442 0 : 'Coupling reliability metric (0 is ideal):', mixed_cdft%results%metric(ipermutation, 1)
1443 : ELSE
1444 : WRITE (iounit, '(T3,A,T54,(3X,2F12.6))') &
1445 9 : 'Coupling reliability metric (0 is ideal):', &
1446 18 : mixed_cdft%results%metric(ipermutation, 1), mixed_cdft%results%metric(ipermutation, 2)
1447 : END IF
1448 : END IF
1449 : END DO
1450 : WRITE (iounit, '(T3,A)') &
1451 47 : '------------------------------------------------------------------------------'
1452 : END IF
1453 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
1454 94 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1455 :
1456 94 : END SUBROUTINE mixed_cdft_print_couplings
1457 :
1458 : ! **************************************************************************************************
1459 : !> \brief Release storage reserved for mixed CDFT matrices
1460 : !> \param force_env the force_env that holds the CDFT states
1461 : !> \par History
1462 : !> 11.17 created [Nico Holmberg]
1463 : ! **************************************************************************************************
1464 94 : SUBROUTINE mixed_cdft_release_work(force_env)
1465 : TYPE(force_env_type), POINTER :: force_env
1466 :
1467 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1468 :
1469 94 : NULLIFY (mixed_cdft)
1470 :
1471 94 : CPASSERT(ASSOCIATED(force_env))
1472 94 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
1473 94 : CPASSERT(ASSOCIATED(mixed_cdft))
1474 94 : CALL mixed_cdft_result_type_release(mixed_cdft%results)
1475 :
1476 94 : END SUBROUTINE mixed_cdft_release_work
1477 :
1478 : ! **************************************************************************************************
1479 : !> \brief Given the size of a symmetric matrix and a permutation index, returns indices (i, j) of the
1480 : !> off-diagonal element that corresponds to the permutation index. Assumes that the permutation
1481 : !> index was computed by going through the upper triangular part of the input matrix row-by-row.
1482 : !> \param n the size of the symmetric matrix
1483 : !> \param ipermutation the permutation index
1484 : !> \param i the row index corresponding to ipermutation
1485 : !> \param j the column index corresponding to ipermutation
1486 : ! **************************************************************************************************
1487 1248 : SUBROUTINE map_permutation_to_states(n, ipermutation, i, j)
1488 : INTEGER, INTENT(IN) :: n, ipermutation
1489 : INTEGER, INTENT(OUT) :: i, j
1490 :
1491 : INTEGER :: kcol, kpermutation, krow, npermutations
1492 :
1493 1248 : npermutations = n*(n - 1)/2 ! Size of upper triangular part
1494 1248 : IF (ipermutation > npermutations) &
1495 0 : CPABORT("Permutation index out of bounds")
1496 1248 : kpermutation = 0
1497 2124 : DO krow = 1, n
1498 7566 : DO kcol = krow + 1, n
1499 6690 : kpermutation = kpermutation + 1
1500 7566 : IF (kpermutation == ipermutation) THEN
1501 1248 : i = krow
1502 1248 : j = kcol
1503 1248 : RETURN
1504 : END IF
1505 : END DO
1506 : END DO
1507 :
1508 : END SUBROUTINE map_permutation_to_states
1509 :
1510 : ! **************************************************************************************************
1511 : !> \brief Determine confinement bounds along confinement dir (hardcoded to be z)
1512 : !> and determine the number of nonzero entries
1513 : !> Optionally zero entries below a given threshold
1514 : !> \param fun input 3D potential (real space)
1515 : !> \param th threshold for screening values
1516 : !> \param just_zero determines if fun should only be zeroed without returning bounds/work
1517 : !> \param bounds the confinement bounds: fun is nonzero only between these values along 3rd dimension
1518 : !> \param work an estimate of the total number of grid points where fun is nonzero
1519 : ! **************************************************************************************************
1520 34 : SUBROUTINE hfun_zero(fun, th, just_zero, bounds, work)
1521 : REAL(KIND=dp), DIMENSION(:, :, :), INTENT(INOUT) :: fun
1522 : REAL(KIND=dp), INTENT(IN) :: th
1523 : LOGICAL :: just_zero
1524 : INTEGER, OPTIONAL :: bounds(2), work
1525 :
1526 : INTEGER :: i1, i2, i3, lb, n1, n2, n3, nzeroed, &
1527 : nzeroed_total, ub
1528 : LOGICAL :: lb_final, ub_final
1529 :
1530 34 : n1 = SIZE(fun, 1)
1531 34 : n2 = SIZE(fun, 2)
1532 34 : n3 = SIZE(fun, 3)
1533 34 : nzeroed_total = 0
1534 34 : IF (.NOT. just_zero) THEN
1535 34 : CPASSERT(PRESENT(bounds))
1536 34 : CPASSERT(PRESENT(work))
1537 : lb = 1
1538 : lb_final = .FALSE.
1539 : ub_final = .FALSE.
1540 : END IF
1541 1586 : DO i3 = 1, n3
1542 1552 : IF (.NOT. just_zero) nzeroed = 0
1543 75920 : DO i2 = 1, n2
1544 1956496 : DO i1 = 1, n1
1545 1954944 : IF (fun(i1, i2, i3) < th) THEN
1546 983300 : IF (.NOT. just_zero) THEN
1547 983300 : nzeroed = nzeroed + 1
1548 983300 : nzeroed_total = nzeroed_total + 1
1549 : ELSE
1550 0 : fun(i1, i2, i3) = 0.0_dp
1551 : END IF
1552 : END IF
1553 : END DO
1554 : END DO
1555 1586 : IF (.NOT. just_zero) THEN
1556 1552 : IF (nzeroed == (n2*n1)) THEN
1557 80 : IF (.NOT. lb_final) THEN
1558 : lb = i3
1559 56 : ELSE IF (.NOT. ub_final) THEN
1560 8 : ub = i3
1561 8 : ub_final = .TRUE.
1562 : END IF
1563 : ELSE
1564 : IF (.NOT. lb_final) lb_final = .TRUE.
1565 : IF (ub_final) ub_final = .FALSE. ! Safeguard against "holes"
1566 : END IF
1567 : END IF
1568 : END DO
1569 34 : IF (.NOT. just_zero) THEN
1570 34 : IF (.NOT. ub_final) ub = n3
1571 34 : bounds(1) = lb
1572 34 : bounds(2) = ub
1573 102 : bounds = bounds - (n3/2) - 1
1574 34 : work = n3*n2*n1 - nzeroed_total
1575 : END IF
1576 :
1577 34 : END SUBROUTINE hfun_zero
1578 :
1579 : ! **************************************************************************************************
1580 : !> \brief Read input section related to block diagonalization of the mixed CDFT Hamiltonian matrix.
1581 : !> \param force_env the force_env that holds the CDFT states
1582 : !> \param blocks list of CDFT states defining the matrix blocks
1583 : !> \param ignore_excited flag that determines if excited states resulting from the block
1584 : !> diagonalization process should be ignored
1585 : !> \param nrecursion integer that determines how many steps of recursive block diagonalization
1586 : !> is performed (1 if disabled)
1587 : !> \par History
1588 : !> 01.18 created [Nico Holmberg]
1589 : ! **************************************************************************************************
1590 8 : SUBROUTINE mixed_cdft_read_block_diag(force_env, blocks, ignore_excited, nrecursion)
1591 : TYPE(force_env_type), POINTER :: force_env
1592 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:), &
1593 : INTENT(OUT) :: blocks
1594 : LOGICAL, INTENT(OUT) :: ignore_excited
1595 : INTEGER, INTENT(OUT) :: nrecursion
1596 :
1597 : INTEGER :: i, j, k, l, nblk, nforce_eval
1598 8 : INTEGER, DIMENSION(:), POINTER :: tmplist
1599 : LOGICAL :: do_recursive, explicit, has_duplicates
1600 : TYPE(section_vals_type), POINTER :: block_section, force_env_section
1601 :
1602 : EXTERNAL :: dsygv
1603 :
1604 8 : NULLIFY (force_env_section, block_section)
1605 0 : CPASSERT(ASSOCIATED(force_env))
1606 8 : nforce_eval = SIZE(force_env%sub_force_env)
1607 :
1608 : CALL force_env_get(force_env=force_env, &
1609 8 : force_env_section=force_env_section)
1610 8 : block_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%BLOCK_DIAGONALIZE")
1611 :
1612 8 : CALL section_vals_get(block_section, explicit=explicit)
1613 8 : IF (.NOT. explicit) &
1614 : CALL cp_abort(__LOCATION__, &
1615 : "Block diagonalization of CDFT Hamiltonian was requested, but the "// &
1616 0 : "corresponding input section is missing!")
1617 :
1618 8 : CALL section_vals_val_get(block_section, "BLOCK", n_rep_val=nblk)
1619 44 : ALLOCATE (blocks(nblk))
1620 28 : DO i = 1, nblk
1621 20 : NULLIFY (blocks(i)%array)
1622 20 : CALL section_vals_val_get(block_section, "BLOCK", i_rep_val=i, i_vals=tmplist)
1623 20 : IF (SIZE(tmplist) < 1) &
1624 0 : CPABORT("Each BLOCK must contain at least 1 state.")
1625 60 : ALLOCATE (blocks(i)%array(SIZE(tmplist)))
1626 66 : blocks(i)%array(:) = tmplist(:)
1627 : END DO
1628 8 : CALL section_vals_val_get(block_section, "IGNORE_EXCITED", l_val=ignore_excited)
1629 8 : CALL section_vals_val_get(block_section, "RECURSIVE_DIAGONALIZATION", l_val=do_recursive)
1630 : ! Check that the requested states exist
1631 28 : DO i = 1, nblk
1632 66 : DO j = 1, SIZE(blocks(i)%array)
1633 38 : IF (blocks(i)%array(j) < 1 .OR. blocks(i)%array(j) > nforce_eval) &
1634 20 : CPABORT("Requested state does not exist.")
1635 : END DO
1636 : END DO
1637 : ! Check for duplicates
1638 8 : has_duplicates = .FALSE.
1639 28 : DO i = 1, nblk
1640 : ! Within same block
1641 58 : DO j = 1, SIZE(blocks(i)%array)
1642 76 : DO k = j + 1, SIZE(blocks(i)%array)
1643 56 : IF (blocks(i)%array(j) == blocks(i)%array(k)) has_duplicates = .TRUE.
1644 : END DO
1645 : END DO
1646 : ! Within different blocks
1647 46 : DO j = i + 1, nblk
1648 74 : DO k = 1, SIZE(blocks(i)%array)
1649 122 : DO l = 1, SIZE(blocks(j)%array)
1650 104 : IF (blocks(i)%array(k) == blocks(j)%array(l)) has_duplicates = .TRUE.
1651 : END DO
1652 : END DO
1653 : END DO
1654 : END DO
1655 8 : IF (has_duplicates) CPABORT("Duplicate states are not allowed.")
1656 8 : nrecursion = 1
1657 8 : IF (do_recursive) THEN
1658 2 : IF (MODULO(nblk, 2) /= 0) THEN
1659 : CALL cp_warn(__LOCATION__, &
1660 : "Number of blocks not divisible with 2. Recursive diagonalization not possible. "// &
1661 0 : "Calculation proceeds without.")
1662 0 : nrecursion = 1
1663 : ELSE
1664 2 : nrecursion = nblk/2
1665 : END IF
1666 2 : IF (nrecursion /= 1 .AND. .NOT. ignore_excited) &
1667 : CALL cp_abort(__LOCATION__, &
1668 0 : "Keyword IGNORE_EXCITED must be active for recursive diagonalization.")
1669 : END IF
1670 :
1671 32 : END SUBROUTINE mixed_cdft_read_block_diag
1672 :
1673 : ! **************************************************************************************************
1674 : !> \brief Assembles the matrix blocks from the mixed CDFT Hamiltonian.
1675 : !> \param mixed_cdft the env that holds the CDFT states
1676 : !> \param blocks list of CDFT states defining the matrix blocks
1677 : !> \param H_block list of Hamiltonian matrix blocks
1678 : !> \param S_block list of overlap matrix blocks
1679 : !> \par History
1680 : !> 01.18 created [Nico Holmberg]
1681 : ! **************************************************************************************************
1682 10 : SUBROUTINE mixed_cdft_get_blocks(mixed_cdft, blocks, H_block, S_block)
1683 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1684 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:) :: blocks
1685 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:), &
1686 : INTENT(OUT) :: H_block, S_block
1687 :
1688 : INTEGER :: i, icol, irow, j, k, nblk
1689 :
1690 : EXTERNAL :: dsygv
1691 :
1692 10 : CPASSERT(ASSOCIATED(mixed_cdft))
1693 :
1694 10 : nblk = SIZE(blocks)
1695 98 : ALLOCATE (H_block(nblk), S_block(nblk))
1696 34 : DO i = 1, nblk
1697 24 : NULLIFY (H_block(i)%array)
1698 24 : NULLIFY (S_block(i)%array)
1699 96 : ALLOCATE (H_block(i)%array(SIZE(blocks(i)%array), SIZE(blocks(i)%array)))
1700 96 : ALLOCATE (S_block(i)%array(SIZE(blocks(i)%array), SIZE(blocks(i)%array)))
1701 24 : icol = 0
1702 70 : DO j = 1, SIZE(blocks(i)%array)
1703 46 : irow = 0
1704 46 : icol = icol + 1
1705 160 : DO k = 1, SIZE(blocks(i)%array)
1706 90 : irow = irow + 1
1707 90 : H_block(i)%array(irow, icol) = mixed_cdft%results%H(blocks(i)%array(k), blocks(i)%array(j))
1708 136 : S_block(i)%array(irow, icol) = mixed_cdft%results%S(blocks(i)%array(k), blocks(i)%array(j))
1709 : END DO
1710 : END DO
1711 : ! Check that none of the interaction energies is repulsive
1712 160 : IF (ANY(H_block(i)%array >= 0.0_dp)) &
1713 : CALL cp_abort(__LOCATION__, &
1714 : "At least one of the interaction energies within block "//TRIM(ADJUSTL(cp_to_string(i)))// &
1715 10 : " is repulsive.")
1716 : END DO
1717 :
1718 10 : END SUBROUTINE mixed_cdft_get_blocks
1719 :
1720 : ! **************************************************************************************************
1721 : !> \brief Diagonalizes each of the matrix blocks.
1722 : !> \param blocks list of CDFT states defining the matrix blocks
1723 : !> \param H_block list of Hamiltonian matrix blocks
1724 : !> \param S_block list of overlap matrix blocks
1725 : !> \param eigenvalues list of eigenvalues for each block
1726 : !> \par History
1727 : !> 01.18 created [Nico Holmberg]
1728 : ! **************************************************************************************************
1729 10 : SUBROUTINE mixed_cdft_diagonalize_blocks(blocks, H_block, S_block, eigenvalues)
1730 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:) :: blocks
1731 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:) :: H_block, S_block
1732 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:), &
1733 : INTENT(OUT) :: eigenvalues
1734 :
1735 : INTEGER :: i, info, nblk, work_array_size
1736 10 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: work
1737 10 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: H_mat_copy, S_mat_copy
1738 :
1739 : EXTERNAL :: dsygv
1740 :
1741 10 : nblk = SIZE(blocks)
1742 54 : ALLOCATE (eigenvalues(nblk))
1743 34 : DO i = 1, nblk
1744 24 : NULLIFY (eigenvalues(i)%array)
1745 72 : ALLOCATE (eigenvalues(i)%array(SIZE(blocks(i)%array)))
1746 70 : eigenvalues(i)%array = 0.0_dp
1747 : ! Workspace query
1748 24 : ALLOCATE (work(1))
1749 24 : info = 0
1750 96 : ALLOCATE (H_mat_copy(SIZE(blocks(i)%array), SIZE(blocks(i)%array)))
1751 72 : ALLOCATE (S_mat_copy(SIZE(blocks(i)%array), SIZE(blocks(i)%array)))
1752 160 : H_mat_copy(:, :) = H_block(i)%array(:, :) ! Need explicit copies because dsygv destroys original values
1753 160 : S_mat_copy(:, :) = S_block(i)%array(:, :)
1754 : CALL dsygv(1, 'V', 'U', SIZE(blocks(i)%array), H_mat_copy, SIZE(blocks(i)%array), &
1755 24 : S_mat_copy, SIZE(blocks(i)%array), eigenvalues(i)%array, work, -1, info)
1756 24 : work_array_size = NINT(work(1))
1757 24 : DEALLOCATE (H_mat_copy, S_mat_copy)
1758 : ! Allocate work array
1759 24 : DEALLOCATE (work)
1760 72 : ALLOCATE (work(work_array_size))
1761 1588 : work = 0.0_dp
1762 : ! Solve Hc = eSc
1763 24 : info = 0
1764 : CALL dsygv(1, 'V', 'U', SIZE(blocks(i)%array), H_block(i)%array, SIZE(blocks(i)%array), &
1765 24 : S_block(i)%array, SIZE(blocks(i)%array), eigenvalues(i)%array, work, work_array_size, info)
1766 24 : IF (info /= 0) THEN
1767 0 : IF (info > SIZE(blocks(i)%array)) THEN
1768 0 : CPABORT("Matrix S is not positive definite")
1769 : ELSE
1770 0 : CPABORT("Diagonalization of H matrix failed.")
1771 : END IF
1772 : END IF
1773 34 : DEALLOCATE (work)
1774 : END DO
1775 :
1776 10 : END SUBROUTINE mixed_cdft_diagonalize_blocks
1777 :
1778 : ! **************************************************************************************************
1779 : !> \brief Assembles the new block diagonalized mixed CDFT Hamiltonian and overlap matrices.
1780 : !> \param mixed_cdft the env that holds the CDFT states
1781 : !> \param blocks list of CDFT states defining the matrix blocks
1782 : !> \param H_block list of Hamiltonian matrix blocks
1783 : !> \param eigenvalues list of eigenvalues for each block
1784 : !> \param n size of the new Hamiltonian and overlap matrices
1785 : !> \param iounit the output unit
1786 : !> \par History
1787 : !> 01.18 created [Nico Holmberg]
1788 : ! **************************************************************************************************
1789 10 : SUBROUTINE mixed_cdft_assemble_block_diag(mixed_cdft, blocks, H_block, eigenvalues, &
1790 : n, iounit)
1791 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1792 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:) :: blocks
1793 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:) :: H_block
1794 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:) :: eigenvalues
1795 : INTEGER :: n, iounit
1796 :
1797 : CHARACTER(LEN=20) :: ilabel, jlabel
1798 : CHARACTER(LEN=3) :: tmp
1799 : INTEGER :: i, icol, ipermutation, irow, j, k, l, &
1800 : nblk, npermutations
1801 : LOGICAL :: ignore_excited
1802 10 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: H_mat, H_offdiag, S_mat, S_offdiag
1803 :
1804 : EXTERNAL :: dsygv
1805 :
1806 60 : ALLOCATE (H_mat(n, n), S_mat(n, n))
1807 10 : nblk = SIZE(blocks)
1808 10 : ignore_excited = (nblk == n)
1809 : ! The diagonal contains the eigenvalues of each block
1810 10 : IF (iounit > 0) WRITE (iounit, '(/,T3,A)') "Eigenvalues of the block diagonalized states"
1811 126 : H_mat(:, :) = 0.0_dp
1812 126 : S_mat(:, :) = 0.0_dp
1813 10 : k = 1
1814 34 : DO i = 1, nblk
1815 24 : IF (iounit > 0) WRITE (iounit, '(T6,A,I3)') "Block", i
1816 42 : DO j = 1, SIZE(eigenvalues(i)%array)
1817 28 : H_mat(k, k) = eigenvalues(i)%array(j)
1818 28 : S_mat(k, k) = 1.0_dp
1819 28 : k = k + 1
1820 28 : IF (iounit > 0) THEN
1821 14 : IF (j == 1) THEN
1822 12 : WRITE (iounit, '(T9,A,T58,(3X,F20.14))') 'Ground state energy:', eigenvalues(i)%array(j)
1823 : ELSE
1824 : WRITE (iounit, '(T9,A,I2,A,T58,(3X,F20.14))') &
1825 2 : 'Excited state (', j - 1, ' ) energy:', eigenvalues(i)%array(j)
1826 : END IF
1827 : END IF
1828 32 : IF (ignore_excited .AND. j == 1) EXIT
1829 : END DO
1830 : END DO
1831 : ! Transform the off-diagonal blocks using the eigenvectors of each block
1832 10 : npermutations = nblk*(nblk - 1)/2
1833 10 : IF (iounit > 0) WRITE (iounit, '(/,T3,A)') "Interactions between block diagonalized states"
1834 30 : DO ipermutation = 1, npermutations
1835 20 : CALL map_permutation_to_states(nblk, ipermutation, i, j)
1836 : ! Get the untransformed off-diagonal block
1837 80 : ALLOCATE (H_offdiag(SIZE(blocks(i)%array), SIZE(blocks(j)%array)))
1838 60 : ALLOCATE (S_offdiag(SIZE(blocks(i)%array), SIZE(blocks(j)%array)))
1839 58 : icol = 0
1840 58 : DO k = 1, SIZE(blocks(j)%array)
1841 38 : irow = 0
1842 38 : icol = icol + 1
1843 134 : DO l = 1, SIZE(blocks(i)%array)
1844 76 : irow = irow + 1
1845 76 : H_offdiag(irow, icol) = mixed_cdft%results%H(blocks(i)%array(l), blocks(j)%array(k))
1846 114 : S_offdiag(irow, icol) = mixed_cdft%results%S(blocks(i)%array(l), blocks(j)%array(k))
1847 : END DO
1848 : END DO
1849 : ! Check that none of the interaction energies is repulsive
1850 134 : IF (ANY(H_offdiag >= 0.0_dp)) &
1851 : CALL cp_abort(__LOCATION__, &
1852 : "At least one of the interaction energies between blocks "//TRIM(ADJUSTL(cp_to_string(i)))// &
1853 0 : " and "//TRIM(ADJUSTL(cp_to_string(j)))//" is repulsive.")
1854 : ! Now transform: C_i^T * H * C_j
1855 952 : H_offdiag(:, :) = MATMUL(H_offdiag, H_block(j)%array)
1856 972 : H_offdiag(:, :) = MATMUL(TRANSPOSE(H_block(i)%array), H_offdiag)
1857 952 : S_offdiag(:, :) = MATMUL(S_offdiag, H_block(j)%array)
1858 972 : S_offdiag(:, :) = MATMUL(TRANSPOSE(H_block(i)%array), S_offdiag)
1859 : ! Make sure the transformation preserves the sign of elements in the S and H matrices
1860 : ! The S/H matrices contain only positive/negative values so that any sign flipping occurs in the
1861 : ! same elements in both matrices
1862 : ! Check for sign flipping using the S matrix
1863 30 : IF (ANY(S_offdiag < 0.0_dp)) THEN
1864 58 : DO l = 1, SIZE(S_offdiag, 2)
1865 134 : DO k = 1, SIZE(S_offdiag, 1)
1866 114 : IF (S_offdiag(k, l) < 0.0_dp) THEN
1867 36 : S_offdiag(k, l) = -1.0_dp*S_offdiag(k, l)
1868 36 : H_offdiag(k, l) = -1.0_dp*H_offdiag(k, l)
1869 : END IF
1870 : END DO
1871 : END DO
1872 : END IF
1873 20 : IF (ignore_excited) THEN
1874 18 : H_mat(i, j) = H_offdiag(1, 1)
1875 18 : H_mat(j, i) = H_mat(i, j)
1876 18 : S_mat(i, j) = S_offdiag(1, 1)
1877 18 : S_mat(j, i) = S_mat(i, j)
1878 : ELSE
1879 2 : irow = 1
1880 2 : icol = 1
1881 2 : DO k = 1, i - 1
1882 2 : irow = irow + SIZE(blocks(k)%array)
1883 : END DO
1884 4 : DO k = 1, j - 1
1885 4 : icol = icol + SIZE(blocks(k)%array)
1886 : END DO
1887 14 : H_mat(irow:irow + SIZE(H_offdiag, 1) - 1, icol:icol + SIZE(H_offdiag, 2) - 1) = H_offdiag(:, :)
1888 14 : H_mat(icol:icol + SIZE(H_offdiag, 2) - 1, irow:irow + SIZE(H_offdiag, 1) - 1) = TRANSPOSE(H_offdiag)
1889 14 : S_mat(irow:irow + SIZE(H_offdiag, 1) - 1, icol:icol + SIZE(H_offdiag, 2) - 1) = S_offdiag(:, :)
1890 14 : S_mat(icol:icol + SIZE(H_offdiag, 2) - 1, irow:irow + SIZE(H_offdiag, 1) - 1) = TRANSPOSE(S_offdiag)
1891 : END IF
1892 20 : IF (iounit > 0) THEN
1893 10 : WRITE (iounit, '(/,T3,A)') REPEAT('#', 39)
1894 10 : WRITE (iounit, '(T3,A,I3,A,I3,A)') '###### Blocks I =', i, ' and J = ', j, ' ######'
1895 10 : WRITE (iounit, '(T3,A)') REPEAT('#', 39)
1896 10 : WRITE (iounit, '(T3,A)') 'Interaction energies'
1897 21 : DO irow = 1, SIZE(H_offdiag, 1)
1898 20 : ilabel = "(ground state)"
1899 20 : IF (irow > 1) THEN
1900 10 : IF (ignore_excited) EXIT
1901 1 : WRITE (tmp, '(I3)') irow - 1
1902 1 : ilabel = "(excited state "//TRIM(ADJUSTL(tmp))//")"
1903 : END IF
1904 34 : DO icol = 1, SIZE(H_offdiag, 2)
1905 21 : jlabel = "(ground state)"
1906 21 : IF (icol > 1) THEN
1907 10 : IF (ignore_excited) EXIT
1908 2 : WRITE (tmp, '(I3)') icol - 1
1909 2 : jlabel = "(excited state "//TRIM(ADJUSTL(tmp))//")"
1910 : END IF
1911 24 : WRITE (iounit, '(T6,A,T58,(3X,F20.14))') TRIM(ilabel)//'-'//TRIM(jlabel)//':', H_offdiag(irow, icol)
1912 : END DO
1913 : END DO
1914 10 : WRITE (iounit, '(T3,A)') 'Overlaps'
1915 21 : DO irow = 1, SIZE(H_offdiag, 1)
1916 20 : ilabel = "(ground state)"
1917 20 : IF (irow > 1) THEN
1918 10 : IF (ignore_excited) EXIT
1919 1 : ilabel = "(excited state)"
1920 1 : WRITE (tmp, '(I3)') irow - 1
1921 1 : ilabel = "(excited state "//TRIM(ADJUSTL(tmp))//")"
1922 : END IF
1923 34 : DO icol = 1, SIZE(H_offdiag, 2)
1924 21 : jlabel = "(ground state)"
1925 21 : IF (icol > 1) THEN
1926 10 : IF (ignore_excited) EXIT
1927 2 : WRITE (tmp, '(I3)') icol - 1
1928 2 : jlabel = "(excited state "//TRIM(ADJUSTL(tmp))//")"
1929 : END IF
1930 24 : WRITE (iounit, '(T6,A,T58,(3X,F20.14))') TRIM(ilabel)//'-'//TRIM(jlabel)//':', S_offdiag(irow, icol)
1931 : END DO
1932 : END DO
1933 : END IF
1934 50 : DEALLOCATE (H_offdiag, S_offdiag)
1935 : END DO
1936 10 : CALL mixed_cdft_result_type_set(mixed_cdft%results, H=H_mat, S=S_mat)
1937 : ! Deallocate work
1938 10 : DEALLOCATE (H_mat, S_mat)
1939 :
1940 10 : END SUBROUTINE mixed_cdft_assemble_block_diag
1941 :
1942 : END MODULE mixed_cdft_utils
|