Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Methods for mixed CDFT calculations
10 : !> \par History
11 : !> Separated CDFT routines from mixed_environment_utils
12 : !> \author Nico Holmberg [01.2017]
13 : ! **************************************************************************************************
14 : MODULE mixed_cdft_methods
15 : USE ao_util, ONLY: exp_radius_very_extended
16 : USE atomic_kind_types, ONLY: atomic_kind_type,&
17 : get_atomic_kind
18 : USE cell_types, ONLY: cell_type,&
19 : pbc
20 : USE cp_array_utils, ONLY: cp_1d_i_p_type,&
21 : cp_1d_r_p_type,&
22 : cp_2d_r_p_type
23 : USE cp_control_types, ONLY: dft_control_type
24 : USE cp_dbcsr_api, ONLY: &
25 : dbcsr_add, dbcsr_copy, dbcsr_create, dbcsr_init_p, dbcsr_p_type, dbcsr_release, &
26 : dbcsr_release_p, dbcsr_scale, dbcsr_type
27 : USE cp_dbcsr_diag, ONLY: cp_dbcsr_syevd
28 : USE cp_dbcsr_operations, ONLY: cp_dbcsr_sm_fm_multiply
29 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale,&
30 : cp_fm_invert,&
31 : cp_fm_transpose
32 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
33 : cp_fm_struct_release,&
34 : cp_fm_struct_type
35 : USE cp_fm_types, ONLY: cp_fm_create,&
36 : cp_fm_get_info,&
37 : cp_fm_release,&
38 : cp_fm_set_all,&
39 : cp_fm_to_fm,&
40 : cp_fm_type,&
41 : cp_fm_write_formatted
42 : USE cp_log_handling, ONLY: cp_get_default_logger,&
43 : cp_logger_type,&
44 : cp_to_string
45 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
46 : cp_print_key_unit_nr
47 : USE cp_realspace_grid_cube, ONLY: cp_pw_to_cube
48 : USE cp_subsys_types, ONLY: cp_subsys_get,&
49 : cp_subsys_type
50 : USE cp_units, ONLY: cp_unit_from_cp2k
51 : USE force_env_types, ONLY: force_env_get,&
52 : force_env_type,&
53 : use_qmmm,&
54 : use_qmmmx,&
55 : use_qs_force
56 : USE grid_api, ONLY: GRID_FUNC_AB,&
57 : collocate_pgf_product
58 : USE hirshfeld_methods, ONLY: create_shape_function
59 : USE hirshfeld_types, ONLY: hirshfeld_type
60 : USE input_constants, ONLY: &
61 : becke_cutoff_element, becke_cutoff_global, cdft_alpha_constraint, cdft_beta_constraint, &
62 : cdft_charge_constraint, cdft_magnetization_constraint, mix_cdft, mixed_cdft_parallel, &
63 : mixed_cdft_parallel_nobuild, mixed_cdft_serial, outer_scf_becke_constraint
64 : USE input_section_types, ONLY: section_get_lval,&
65 : section_vals_get,&
66 : section_vals_get_subs_vals,&
67 : section_vals_type,&
68 : section_vals_val_get
69 : USE kinds, ONLY: default_path_length,&
70 : dp
71 : USE machine, ONLY: m_walltime
72 : USE mathlib, ONLY: diamat_all
73 : USE memory_utilities, ONLY: reallocate
74 : USE message_passing, ONLY: mp_request_type,&
75 : mp_testall,&
76 : mp_waitall
77 : USE mixed_cdft_types, ONLY: mixed_cdft_result_type_set,&
78 : mixed_cdft_settings_type,&
79 : mixed_cdft_type,&
80 : mixed_cdft_type_create,&
81 : mixed_cdft_work_type_release
82 : USE mixed_cdft_utils, ONLY: &
83 : hfun_zero, map_permutation_to_states, mixed_cdft_assemble_block_diag, &
84 : mixed_cdft_diagonalize_blocks, mixed_cdft_get_blocks, mixed_cdft_init_structures, &
85 : mixed_cdft_parse_settings, mixed_cdft_print_couplings, mixed_cdft_read_block_diag, &
86 : mixed_cdft_redistribute_arrays, mixed_cdft_release_work, mixed_cdft_transfer_settings
87 : USE mixed_environment_types, ONLY: get_mixed_env,&
88 : mixed_environment_type,&
89 : set_mixed_env
90 : USE parallel_gemm_api, ONLY: parallel_gemm
91 : USE particle_list_types, ONLY: particle_list_type
92 : USE particle_types, ONLY: particle_type
93 : USE pw_env_types, ONLY: pw_env_get,&
94 : pw_env_type
95 : USE pw_methods, ONLY: pw_copy,&
96 : pw_scale,&
97 : pw_zero
98 : USE pw_pool_types, ONLY: pw_pool_type
99 : USE qs_cdft_types, ONLY: cdft_control_type
100 : USE qs_energy_types, ONLY: qs_energy_type
101 : USE qs_environment_types, ONLY: get_qs_env,&
102 : qs_environment_type
103 : USE qs_kind_types, ONLY: qs_kind_type
104 : USE qs_mo_io, ONLY: read_mo_set_from_restart,&
105 : wfn_restart_file_name
106 : USE qs_mo_methods, ONLY: make_basis_simple,&
107 : make_basis_sm
108 : USE qs_mo_types, ONLY: allocate_mo_set,&
109 : deallocate_mo_set,&
110 : mo_set_type,&
111 : set_mo_set
112 : USE realspace_grid_types, ONLY: realspace_grid_type,&
113 : rs_grid_zero,&
114 : transfer_rs2pw
115 : USE util, ONLY: sort
116 : #include "./base/base_uses.f90"
117 :
118 : IMPLICIT NONE
119 :
120 : PRIVATE
121 :
122 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'mixed_cdft_methods'
123 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .FALSE.
124 :
125 : TYPE buffers_idx_irr
126 : INTEGER :: imap(6) = 0
127 : INTEGER, DIMENSION(:), &
128 : POINTER :: iv => null()
129 : REAL(KIND=dp), POINTER, &
130 : DIMENSION(:, :, :) :: r3 => null()
131 : REAL(KIND=dp), POINTER, &
132 : DIMENSION(:, :, :, :) :: r4 => null()
133 : END TYPE buffers_idx_irr
134 :
135 : TYPE buffers_bi
136 : LOGICAL, POINTER, DIMENSION(:) :: bv => NULL()
137 : INTEGER, POINTER, DIMENSION(:) :: iv => NULL()
138 : END TYPE buffers_bi
139 :
140 : PUBLIC :: mixed_cdft_init, &
141 : mixed_cdft_build_weight, &
142 : mixed_cdft_calculate_coupling
143 :
144 : CONTAINS
145 :
146 : ! **************************************************************************************************
147 : !> \brief Initialize a mixed CDFT calculation
148 : !> \param force_env the force_env that holds the CDFT states
149 : !> \param calculate_forces determines if forces should be calculated
150 : !> \par History
151 : !> 01.2016 created [Nico Holmberg]
152 : ! **************************************************************************************************
153 530 : SUBROUTINE mixed_cdft_init(force_env, calculate_forces)
154 : TYPE(force_env_type), POINTER :: force_env
155 : LOGICAL, INTENT(IN) :: calculate_forces
156 :
157 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_init'
158 :
159 : INTEGER :: et_freq, handle, iforce_eval, iounit, &
160 : mixing_type, nforce_eval
161 : LOGICAL :: explicit, is_parallel, is_qmmm
162 : TYPE(cp_logger_type), POINTER :: logger
163 : TYPE(cp_subsys_type), POINTER :: subsys_mix
164 : TYPE(force_env_type), POINTER :: force_env_qs
165 : TYPE(mixed_cdft_settings_type) :: settings
166 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
167 : TYPE(mixed_environment_type), POINTER :: mixed_env
168 : TYPE(particle_list_type), POINTER :: particles_mix
169 : TYPE(section_vals_type), POINTER :: force_env_section, mapping_section, &
170 : md_section, mixed_section, &
171 : print_section, root_section
172 :
173 530 : NULLIFY (subsys_mix, force_env_qs, force_env_section, print_section, &
174 530 : root_section, mixed_section, md_section, mixed_env, mixed_cdft, &
175 530 : mapping_section)
176 :
177 : NULLIFY (settings%grid_span, settings%npts, settings%cutoff, settings%rel_cutoff, &
178 : settings%spherical, settings%rs_dims, settings%odd, settings%atoms, &
179 : settings%coeffs, settings%si, settings%sr, &
180 : settings%cutoffs, settings%radii)
181 :
182 530 : is_qmmm = .FALSE.
183 1060 : logger => cp_get_default_logger()
184 530 : CPASSERT(ASSOCIATED(force_env))
185 530 : nforce_eval = SIZE(force_env%sub_force_env)
186 530 : CALL timeset(routineN, handle)
187 530 : CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
188 530 : mixed_env => force_env%mixed_env
189 530 : mixed_section => section_vals_get_subs_vals(force_env_section, "MIXED")
190 530 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
191 530 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
192 : ! Check if a mixed CDFT calculation is requested
193 530 : CALL section_vals_val_get(mixed_section, "MIXING_TYPE", i_val=mixing_type)
194 530 : IF (mixing_type == mix_cdft .AND. .NOT. ASSOCIATED(mixed_env%cdft_control)) THEN
195 78 : mixed_env%do_mixed_cdft = .TRUE.
196 156 : IF (mixed_env%do_mixed_cdft) THEN
197 : ! Sanity check
198 78 : IF (nforce_eval < 2) THEN
199 : CALL cp_abort(__LOCATION__, &
200 0 : "Mixed CDFT calculation requires at least 2 force_evals.")
201 : END IF
202 78 : mapping_section => section_vals_get_subs_vals(mixed_section, "MAPPING")
203 78 : CALL section_vals_get(mapping_section, explicit=explicit)
204 : ! The sub_force_envs must share the same geometrical structure
205 78 : IF (explicit) THEN
206 0 : CPABORT("Please disable section &MAPPING for mixed CDFT calculations")
207 : END IF
208 78 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%COUPLING", i_val=et_freq)
209 78 : IF (et_freq < 0) THEN
210 0 : mixed_env%do_mixed_et = .FALSE.
211 : ELSE
212 78 : mixed_env%do_mixed_et = .TRUE.
213 78 : IF (et_freq == 0) THEN
214 0 : mixed_env%et_freq = 1
215 : ELSE
216 78 : mixed_env%et_freq = et_freq
217 : END IF
218 : END IF
219 : ! Start initializing the mixed_cdft type
220 : ! First determine if the calculation is pure DFT or QMMM and find the qs force_env
221 258 : DO iforce_eval = 1, nforce_eval
222 180 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
223 296 : SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
224 : CASE (use_qs_force)
225 142 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
226 : CASE (use_qmmm)
227 12 : is_qmmm = .TRUE.
228 : ! This is really the container for QMMM
229 12 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
230 : CASE (use_qmmmx)
231 0 : CPABORT("No force mixing allowed for mixed CDFT QM/MM")
232 : CASE DEFAULT
233 : CALL cp_abort(__LOCATION__, &
234 : "Only use_qs_force and use_qmmm are "// &
235 154 : "supported for mixed_cdft_init")
236 : END SELECT
237 232 : CPASSERT(ASSOCIATED(force_env_qs))
238 : END DO
239 : ! Get infos about the mixed subsys
240 78 : IF (.NOT. is_qmmm) THEN
241 : CALL force_env_get(force_env=force_env, &
242 70 : subsys=subsys_mix)
243 : CALL cp_subsys_get(subsys=subsys_mix, &
244 70 : particles=particles_mix)
245 : ELSE
246 : CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
247 8 : cp_subsys=subsys_mix)
248 : CALL cp_subsys_get(subsys=subsys_mix, &
249 8 : particles=particles_mix)
250 : END IF
251 : ! Init mixed_cdft_type
252 78 : ALLOCATE (mixed_cdft)
253 78 : CALL mixed_cdft_type_create(mixed_cdft)
254 78 : mixed_cdft%first_iteration = .TRUE.
255 : ! Determine what run type to use
256 78 : IF (mixed_env%ngroups == 1) THEN
257 : ! States treated in serial, possibly copying CDFT weight function and gradients from state to state
258 52 : mixed_cdft%run_type = mixed_cdft_serial
259 26 : ELSE IF (mixed_env%ngroups == 2) THEN
260 26 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%PARALLEL_BUILD", l_val=is_parallel)
261 26 : IF (is_parallel) THEN
262 : ! Treat states in parallel, build weight function and gradients in parallel before SCF process
263 24 : mixed_cdft%run_type = mixed_cdft_parallel
264 24 : IF (.NOT. nforce_eval == 2) THEN
265 : CALL cp_abort(__LOCATION__, &
266 0 : "Parallel mode mixed CDFT calculation supports only 2 force_evals.")
267 : END IF
268 : ELSE
269 : ! Treat states in parallel, but each states builds its own weight function and gradients
270 2 : mixed_cdft%run_type = mixed_cdft_parallel_nobuild
271 : END IF
272 : ELSE
273 0 : mixed_cdft%run_type = mixed_cdft_parallel_nobuild
274 : END IF
275 : ! Store QMMM flag
276 78 : mixed_env%do_mixed_qmmm_cdft = is_qmmm
277 : ! Setup dynamic load balancing
278 78 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%DLB", l_val=mixed_cdft%dlb)
279 78 : mixed_cdft%dlb = mixed_cdft%dlb .AND. calculate_forces ! disable if forces are not needed
280 78 : mixed_cdft%dlb = mixed_cdft%dlb .AND. (mixed_cdft%run_type == mixed_cdft_parallel) ! disable if not parallel
281 78 : IF (mixed_cdft%dlb) THEN
282 40 : ALLOCATE (mixed_cdft%dlb_control)
283 4 : NULLIFY (mixed_cdft%dlb_control%weight, mixed_cdft%dlb_control%gradients, &
284 4 : mixed_cdft%dlb_control%cavity, mixed_cdft%dlb_control%target_list, &
285 4 : mixed_cdft%dlb_control%bo, mixed_cdft%dlb_control%expected_work, &
286 4 : mixed_cdft%dlb_control%prediction_error, mixed_cdft%dlb_control%sendbuff, &
287 4 : mixed_cdft%dlb_control%recvbuff, mixed_cdft%dlb_control%recv_work_repl, &
288 4 : mixed_cdft%dlb_control%recv_info)
289 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%LOAD_SCALE", &
290 4 : r_val=mixed_cdft%dlb_control%load_scale)
291 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%VERY_OVERLOADED", &
292 4 : r_val=mixed_cdft%dlb_control%very_overloaded)
293 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%MORE_WORK", &
294 4 : i_val=mixed_cdft%dlb_control%more_work)
295 : END IF
296 : ! Metric/Wavefunction overlap method/Lowdin orthogonalization/CDFT-CI
297 78 : mixed_cdft%calculate_metric = .FALSE.
298 78 : mixed_cdft%wfn_overlap_method = .FALSE.
299 78 : mixed_cdft%use_lowdin = .FALSE.
300 78 : mixed_cdft%do_ci = .FALSE.
301 78 : mixed_cdft%nonortho_coupling = .FALSE.
302 78 : mixed_cdft%identical_constraints = .TRUE.
303 78 : mixed_cdft%block_diagonalize = .FALSE.
304 78 : IF (mixed_env%do_mixed_et) THEN
305 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%METRIC", &
306 78 : l_val=mixed_cdft%calculate_metric)
307 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%WFN_OVERLAP", &
308 78 : l_val=mixed_cdft%wfn_overlap_method)
309 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%LOWDIN", &
310 78 : l_val=mixed_cdft%use_lowdin)
311 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%CI", &
312 78 : l_val=mixed_cdft%do_ci)
313 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%NONORTHOGONAL_COUPLING", &
314 78 : l_val=mixed_cdft%nonortho_coupling)
315 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%BLOCK_DIAGONALIZE", &
316 78 : l_val=mixed_cdft%block_diagonalize)
317 : END IF
318 : ! Inversion method
319 78 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%EPS_SVD", r_val=mixed_cdft%eps_svd)
320 78 : IF (mixed_cdft%eps_svd < 0.0_dp .OR. mixed_cdft%eps_svd > 1.0_dp) THEN
321 0 : CPABORT("Illegal value for EPS_SVD. Value must be between 0.0 and 1.0.")
322 : END IF
323 : ! MD related settings
324 78 : CALL force_env_get(force_env, root_section=root_section)
325 78 : md_section => section_vals_get_subs_vals(root_section, "MOTION%MD")
326 78 : CALL section_vals_val_get(md_section, "TIMESTEP", r_val=mixed_cdft%sim_dt)
327 78 : CALL section_vals_val_get(md_section, "STEP_START_VAL", i_val=mixed_cdft%sim_step)
328 78 : mixed_cdft%sim_step = mixed_cdft%sim_step - 1 ! to get the first step correct
329 78 : mixed_cdft%sim_dt = cp_unit_from_cp2k(mixed_cdft%sim_dt, "fs")
330 : ! Parse constraint settings from the individual force_evals and check consistency
331 : CALL mixed_cdft_parse_settings(force_env, mixed_env, mixed_cdft, &
332 78 : settings, natom=SIZE(particles_mix%els))
333 : ! Transfer settings to mixed_cdft
334 78 : CALL mixed_cdft_transfer_settings(force_env, mixed_cdft, settings)
335 : ! Initilize necessary structures
336 78 : CALL mixed_cdft_init_structures(force_env, force_env_qs, mixed_env, mixed_cdft, settings)
337 : ! Write information about the mixed CDFT calculation
338 78 : IF (iounit > 0) THEN
339 39 : WRITE (iounit, *) ""
340 : WRITE (iounit, FMT="(T2,A,T71)") &
341 39 : "MIXED_CDFT| Activating mixed CDFT calculation"
342 : WRITE (iounit, FMT="(T2,A,T71,I10)") &
343 39 : "MIXED_CDFT| Number of CDFT states: ", nforce_eval
344 51 : SELECT CASE (mixed_cdft%run_type)
345 : CASE (mixed_cdft_parallel)
346 : WRITE (iounit, FMT="(T2,A,T71)") &
347 12 : "MIXED_CDFT| CDFT states calculation mode: parallel with build"
348 : WRITE (iounit, FMT="(T2,A,T71)") &
349 12 : "MIXED_CDFT| Becke constraint is first built using all available processors"
350 : WRITE (iounit, FMT="(T2,A,T71)") &
351 12 : " and then copied to both states with their own processor groups"
352 : CASE (mixed_cdft_serial)
353 : WRITE (iounit, FMT="(T2,A,T71)") &
354 26 : "MIXED_CDFT| CDFT states calculation mode: serial"
355 26 : IF (mixed_cdft%identical_constraints) THEN
356 : WRITE (iounit, FMT="(T2,A,T71)") &
357 25 : "MIXED_CDFT| The constraints are built before the SCF procedure of the first"
358 : WRITE (iounit, FMT="(T2,A,T71)") &
359 25 : " CDFT state and subsequently copied to the other states"
360 : ELSE
361 : WRITE (iounit, FMT="(T2,A,T71)") &
362 1 : "MIXED_CDFT| The constraints are separately built for all CDFT states"
363 : END IF
364 : CASE (mixed_cdft_parallel_nobuild)
365 : WRITE (iounit, FMT="(T2,A,T71)") &
366 1 : "MIXED_CDFT| CDFT states calculation mode: parallel without build"
367 : WRITE (iounit, FMT="(T2,A,T71)") &
368 1 : "MIXED_CDFT| The constraints are separately built for all CDFT states"
369 : CASE DEFAULT
370 39 : CPABORT("Unknown mixed CDFT run type.")
371 : END SELECT
372 : WRITE (iounit, FMT="(T2,A,T71,L10)") &
373 39 : "MIXED_CDFT| Calculating electronic coupling between states: ", mixed_env%do_mixed_et
374 : WRITE (iounit, FMT="(T2,A,T71,L10)") &
375 39 : "MIXED_CDFT| Calculating electronic coupling reliability metric: ", mixed_cdft%calculate_metric
376 : WRITE (iounit, FMT="(T2,A,T71,L10)") &
377 39 : "MIXED_CDFT| Configuration interaction (CDFT-CI) was requested: ", mixed_cdft%do_ci
378 : WRITE (iounit, FMT="(T2,A,T71,L10)") &
379 39 : "MIXED_CDFT| Block diagonalizing the mixed CDFT Hamiltonian: ", mixed_cdft%block_diagonalize
380 39 : IF (mixed_cdft%run_type == mixed_cdft_parallel) THEN
381 : WRITE (iounit, FMT="(T2,A,T71,L10)") &
382 12 : "MIXED_CDFT| Dynamic load balancing enabled: ", mixed_cdft%dlb
383 12 : IF (mixed_cdft%dlb) THEN
384 2 : WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Dynamic load balancing parameters:"
385 : WRITE (iounit, FMT="(T2,A,T71,F10.2)") &
386 2 : "MIXED_CDFT| load_scale:", mixed_cdft%dlb_control%load_scale
387 : WRITE (iounit, FMT="(T2,A,T71,F10.2)") &
388 2 : "MIXED_CDFT| very_overloaded:", mixed_cdft%dlb_control%very_overloaded
389 : WRITE (iounit, FMT="(T2,A,T71,I10)") &
390 2 : "MIXED_CDFT| more_work:", mixed_cdft%dlb_control%more_work
391 : END IF
392 : END IF
393 39 : IF (mixed_env%do_mixed_et) THEN
394 39 : IF (mixed_cdft%eps_svd == 0.0_dp) THEN
395 31 : WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Matrix inversions calculated with LU decomposition."
396 : ELSE
397 8 : WRITE (iounit, FMT="(T2,A,T71)") "MIXED_CDFT| Matrix inversions calculated with SVD decomposition."
398 8 : WRITE (iounit, FMT="(T2,A,T71,ES10.2)") "MIXED_CDFT| EPS_SVD:", mixed_cdft%eps_svd
399 : END IF
400 : END IF
401 : END IF
402 78 : CALL set_mixed_env(mixed_env, cdft_control=mixed_cdft)
403 : END IF
404 : END IF
405 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
406 530 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
407 530 : CALL timestop(handle)
408 :
409 5300 : END SUBROUTINE mixed_cdft_init
410 :
411 : ! **************************************************************************************************
412 : !> \brief Driver routine to handle the build of CDFT weight/gradient in parallel and serial modes
413 : !> \param force_env the force_env that holds the CDFT states
414 : !> \param calculate_forces if forces should be calculated
415 : !> \param iforce_eval index of the currently active CDFT state (serial mode only)
416 : !> \par History
417 : !> 01.2017 created [Nico Holmberg]
418 : ! **************************************************************************************************
419 286 : SUBROUTINE mixed_cdft_build_weight(force_env, calculate_forces, iforce_eval)
420 : TYPE(force_env_type), POINTER :: force_env
421 : LOGICAL, INTENT(IN) :: calculate_forces
422 : INTEGER, INTENT(IN), OPTIONAL :: iforce_eval
423 :
424 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
425 :
426 286 : NULLIFY (mixed_cdft)
427 286 : CPASSERT(ASSOCIATED(force_env))
428 286 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
429 286 : CPASSERT(ASSOCIATED(mixed_cdft))
430 286 : IF (.NOT. PRESENT(iforce_eval)) THEN
431 136 : SELECT CASE (mixed_cdft%run_type)
432 : CASE (mixed_cdft_parallel)
433 36 : CALL mixed_cdft_build_weight_parallel(force_env, calculate_forces)
434 : CASE (mixed_cdft_parallel_nobuild)
435 100 : CALL mixed_cdft_set_flags(force_env)
436 : CASE DEFAULT
437 : ! Do nothing
438 : END SELECT
439 : ELSE
440 334 : SELECT CASE (mixed_cdft%run_type)
441 : CASE (mixed_cdft_serial)
442 186 : CALL mixed_cdft_transfer_weight(force_env, calculate_forces, iforce_eval)
443 : CASE DEFAULT
444 : ! Do nothing
445 : END SELECT
446 : END IF
447 :
448 286 : END SUBROUTINE mixed_cdft_build_weight
449 :
450 : ! **************************************************************************************************
451 : !> \brief Build CDFT weight and gradient on 2N processors and copy it to two N processor subgroups
452 : !> \param force_env the force_env that holds the CDFT states
453 : !> \param calculate_forces if forces should be calculted
454 : !> \par History
455 : !> 01.2016 created [Nico Holmberg]
456 : ! **************************************************************************************************
457 36 : SUBROUTINE mixed_cdft_build_weight_parallel(force_env, calculate_forces)
458 : TYPE(force_env_type), POINTER :: force_env
459 : LOGICAL, INTENT(IN) :: calculate_forces
460 :
461 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_build_weight_parallel'
462 :
463 : INTEGER :: handle, handle2, i, iforce_eval, ind, INDEX(6), iounit, j, lb_min, &
464 : my_special_work, natom, nforce_eval, recv_offset, ub_max
465 : INTEGER, DIMENSION(2, 3) :: bo
466 36 : INTEGER, DIMENSION(:), POINTER :: lb, sendbuffer_i, ub
467 : REAL(KIND=dp) :: t1, t2
468 36 : TYPE(buffers_idx_irr), DIMENSION(:), POINTER :: recvbuffer
469 : TYPE(cdft_control_type), POINTER :: cdft_control, cdft_control_target
470 : TYPE(cp_logger_type), POINTER :: logger
471 : TYPE(cp_subsys_type), POINTER :: subsys_mix
472 : TYPE(dft_control_type), POINTER :: dft_control
473 : TYPE(force_env_type), POINTER :: force_env_qs
474 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
475 : TYPE(mixed_environment_type), POINTER :: mixed_env
476 36 : TYPE(mp_request_type), DIMENSION(:), POINTER :: req_total
477 : TYPE(particle_list_type), POINTER :: particles_mix
478 : TYPE(pw_env_type), POINTER :: pw_env
479 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool, mixed_auxbas_pw_pool
480 : TYPE(qs_environment_type), POINTER :: qs_env
481 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
482 :
483 36 : NULLIFY (subsys_mix, force_env_qs, particles_mix, force_env_section, print_section, &
484 36 : mixed_env, mixed_cdft, pw_env, auxbas_pw_pool, mixed_auxbas_pw_pool, &
485 36 : qs_env, dft_control, sendbuffer_i, lb, ub, req_total, recvbuffer, &
486 36 : cdft_control, cdft_control_target)
487 :
488 72 : logger => cp_get_default_logger()
489 36 : CPASSERT(ASSOCIATED(force_env))
490 36 : nforce_eval = SIZE(force_env%sub_force_env)
491 36 : CALL timeset(routineN, handle)
492 36 : t1 = m_walltime()
493 : ! Get infos about the mixed subsys
494 : CALL force_env_get(force_env=force_env, &
495 : subsys=subsys_mix, &
496 36 : force_env_section=force_env_section)
497 : CALL cp_subsys_get(subsys=subsys_mix, &
498 36 : particles=particles_mix)
499 108 : DO iforce_eval = 1, nforce_eval
500 72 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
501 36 : SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
502 : CASE (use_qs_force)
503 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
504 : CASE (use_qmmm)
505 0 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
506 : CASE DEFAULT
507 : CALL cp_abort(__LOCATION__, &
508 : "Only use_qs_force and use_qmmm are "// &
509 72 : "supported for mixed_cdft_build_weight_parallel")
510 : END SELECT
511 : END DO
512 36 : IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
513 : CALL force_env_get(force_env=force_env_qs, &
514 : qs_env=qs_env, &
515 28 : subsys=subsys_mix)
516 : CALL cp_subsys_get(subsys=subsys_mix, &
517 28 : particles=particles_mix)
518 : ELSE
519 8 : qs_env => force_env_qs%qmmm_env%qs_env
520 8 : CALL get_qs_env(qs_env, cp_subsys=subsys_mix)
521 : CALL cp_subsys_get(subsys=subsys_mix, &
522 8 : particles=particles_mix)
523 : END IF
524 36 : mixed_env => force_env%mixed_env
525 36 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
526 36 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
527 36 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
528 36 : CPASSERT(ASSOCIATED(mixed_cdft))
529 36 : cdft_control => mixed_cdft%cdft_control
530 36 : CPASSERT(ASSOCIATED(cdft_control))
531 : ! Calculate the Becke weight function and gradient on all np processors
532 36 : CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=mixed_auxbas_pw_pool)
533 36 : natom = SIZE(particles_mix%els)
534 36 : CALL mixed_becke_constraint(force_env, calculate_forces)
535 : ! Start replicating the working arrays on both np/2 processor groups
536 36 : mixed_cdft%sim_step = mixed_cdft%sim_step + 1
537 36 : CALL get_qs_env(qs_env, pw_env=pw_env, dft_control=dft_control)
538 36 : cdft_control_target => dft_control%qs_control%cdft_control
539 36 : CPASSERT(dft_control%qs_control%cdft)
540 36 : CPASSERT(ASSOCIATED(cdft_control_target))
541 36 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
542 360 : bo = auxbas_pw_pool%pw_grid%bounds_local
543 : ! First determine the size of the arrays along the confinement dir
544 36 : IF (mixed_cdft%is_special) THEN
545 : my_special_work = 2
546 : ELSE
547 36 : my_special_work = 1
548 : END IF
549 432 : ALLOCATE (recvbuffer(SIZE(mixed_cdft%source_list)))
550 252 : ALLOCATE (req_total(my_special_work*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)))
551 144 : ALLOCATE (lb(SIZE(mixed_cdft%source_list)), ub(SIZE(mixed_cdft%source_list)))
552 36 : IF (cdft_control%becke_control%cavity_confine) THEN
553 : ! Gaussian confinement => the bounds depend on the processor and need to be communicated
554 34 : ALLOCATE (sendbuffer_i(2))
555 204 : sendbuffer_i = cdft_control%becke_control%confine_bounds
556 102 : DO i = 1, SIZE(mixed_cdft%source_list)
557 68 : ALLOCATE (recvbuffer(i)%iv(2))
558 : CALL force_env%para_env%irecv(msgout=recvbuffer(i)%iv, source=mixed_cdft%source_list(i), &
559 102 : request=req_total(i))
560 : END DO
561 68 : DO i = 1, my_special_work
562 136 : DO j = 1, SIZE(mixed_cdft%dest_list)
563 68 : ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
564 : CALL force_env%para_env%isend(msgin=sendbuffer_i, &
565 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
566 102 : request=req_total(ind))
567 : END DO
568 : END DO
569 34 : CALL mp_waitall(req_total)
570 : ! Find the largest/smallest value of ub/lb
571 34 : DEALLOCATE (sendbuffer_i)
572 34 : lb_min = HUGE(0)
573 34 : ub_max = -HUGE(0)
574 102 : DO i = 1, SIZE(mixed_cdft%source_list)
575 68 : lb(i) = recvbuffer(i)%iv(1)
576 68 : ub(i) = recvbuffer(i)%iv(2)
577 68 : IF (lb(i) < lb_min) lb_min = lb(i)
578 68 : IF (ub(i) > ub_max) ub_max = ub(i)
579 102 : DEALLOCATE (recvbuffer(i)%iv)
580 : END DO
581 : ! Take into account the grids already communicated during dlb
582 34 : IF (mixed_cdft%dlb) THEN
583 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
584 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
585 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
586 16 : DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
587 16 : IF (LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3) &
588 0 : < lb_min) lb_min = LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)
589 16 : IF (UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3) &
590 8 : > ub_max) ub_max = UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)
591 : END DO
592 : END IF
593 : END DO
594 : END IF
595 : END IF
596 : ELSE
597 : ! No confinement
598 2 : ub_max = bo(2, 3)
599 2 : lb_min = bo(1, 3)
600 6 : lb = lb_min
601 6 : ub = ub_max
602 : END IF
603 : ! Determine the sender specific indices of grid slices that are to be received
604 36 : CALL timeset(routineN//"_comm", handle2)
605 108 : DO j = 1, SIZE(recvbuffer)
606 72 : ind = j + (j/2)
607 108 : IF (mixed_cdft%is_special) THEN
608 : recvbuffer(j)%imap = [mixed_cdft%source_list_bo(1, j), mixed_cdft%source_list_bo(2, j), &
609 : mixed_cdft%source_list_bo(3, j), mixed_cdft%source_list_bo(4, j), &
610 0 : lb(j), ub(j)]
611 72 : ELSE IF (mixed_cdft%is_pencil) THEN
612 0 : recvbuffer(j)%imap = [bo(1, 1), bo(2, 1), mixed_cdft%recv_bo(ind), mixed_cdft%recv_bo(ind + 1), lb(j), ub(j)]
613 : ELSE
614 504 : recvbuffer(j)%imap = [mixed_cdft%recv_bo(ind), mixed_cdft%recv_bo(ind + 1), bo(1, 2), bo(2, 2), lb(j), ub(j)]
615 : END IF
616 : END DO
617 36 : IF (mixed_cdft%dlb .AND. .NOT. mixed_cdft%is_special) THEN
618 8 : IF (mixed_cdft%dlb_control%recv_work_repl(1) .OR. mixed_cdft%dlb_control%recv_work_repl(2)) THEN
619 24 : DO j = 1, 2
620 16 : recv_offset = 0
621 16 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
622 16 : recv_offset = SUM(mixed_cdft%dlb_control%recv_info(j)%target_list(2, :))
623 : END IF
624 24 : IF (mixed_cdft%is_pencil) THEN
625 0 : recvbuffer(j)%imap(1) = recvbuffer(j)%imap(1) + recv_offset
626 : ELSE
627 16 : recvbuffer(j)%imap(3) = recvbuffer(j)%imap(3) + recv_offset
628 : END IF
629 : END DO
630 : END IF
631 : END IF
632 : ! Transfer the arrays one-by-one and deallocate shared storage
633 : ! Start with the weight function
634 108 : DO j = 1, SIZE(mixed_cdft%source_list)
635 : ALLOCATE (recvbuffer(j)%r3(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
636 : recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
637 360 : recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)))
638 :
639 : CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r3, source=mixed_cdft%source_list(j), &
640 108 : request=req_total(j))
641 : END DO
642 72 : DO i = 1, my_special_work
643 144 : DO j = 1, SIZE(mixed_cdft%dest_list)
644 72 : ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
645 108 : IF (mixed_cdft%is_special) THEN
646 : CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%weight, &
647 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
648 0 : request=req_total(ind))
649 : ELSE
650 : CALL force_env%para_env%isend(msgin=mixed_cdft%weight, dest=mixed_cdft%dest_list(j), &
651 72 : request=req_total(ind))
652 : END IF
653 : END DO
654 : END DO
655 36 : CALL mp_waitall(req_total)
656 36 : IF (mixed_cdft%is_special) THEN
657 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
658 0 : DEALLOCATE (mixed_cdft%sendbuff(j)%weight)
659 : END DO
660 : ELSE
661 36 : DEALLOCATE (mixed_cdft%weight)
662 : END IF
663 : ! In principle, we could reduce the memory footprint of becke_pot by only transferring the nonzero portion
664 : ! of the potential, but this would require a custom integrate_v_rspace
665 36 : ALLOCATE (cdft_control_target%group(1)%weight)
666 36 : CALL auxbas_pw_pool%create_pw(cdft_control_target%group(1)%weight)
667 36 : CALL pw_zero(cdft_control_target%group(1)%weight)
668 : ! Assemble the recved slices
669 108 : DO j = 1, SIZE(mixed_cdft%source_list)
670 : cdft_control_target%group(1)%weight%array(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
671 : recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
672 7517624 : recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r3
673 : END DO
674 : ! Do the same for slices sent during dlb
675 36 : IF (mixed_cdft%dlb) THEN
676 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
677 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
678 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
679 16 : DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
680 : index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 1), &
681 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 1), &
682 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 2), &
683 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 2), &
684 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3), &
685 104 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, 3)]
686 : cdft_control_target%group(1)%weight%array(INDEX(1):INDEX(2), &
687 : INDEX(3):INDEX(4), &
688 : INDEX(5):INDEX(6)) = &
689 14096 : mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight
690 16 : DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight)
691 : END DO
692 : END IF
693 : END DO
694 : END IF
695 : END IF
696 : ! Gaussian confinement cavity
697 36 : IF (cdft_control%becke_control%cavity_confine) THEN
698 102 : DO j = 1, SIZE(mixed_cdft%source_list)
699 : CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r3, source=mixed_cdft%source_list(j), &
700 102 : request=req_total(j))
701 : END DO
702 68 : DO i = 1, my_special_work
703 136 : DO j = 1, SIZE(mixed_cdft%dest_list)
704 68 : ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
705 102 : IF (mixed_cdft%is_special) THEN
706 : CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%cavity, &
707 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
708 0 : request=req_total(ind))
709 : ELSE
710 : CALL force_env%para_env%isend(msgin=mixed_cdft%cavity, dest=mixed_cdft%dest_list(j), &
711 68 : request=req_total(ind))
712 : END IF
713 : END DO
714 : END DO
715 34 : CALL mp_waitall(req_total)
716 34 : IF (mixed_cdft%is_special) THEN
717 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
718 0 : DEALLOCATE (mixed_cdft%sendbuff(j)%cavity)
719 : END DO
720 : ELSE
721 34 : DEALLOCATE (mixed_cdft%cavity)
722 : END IF
723 : ! We only need the nonzero part of the confinement cavity
724 : ALLOCATE (cdft_control_target%becke_control%cavity_mat(bo(1, 1):bo(2, 1), &
725 : bo(1, 2):bo(2, 2), &
726 170 : lb_min:ub_max))
727 3504226 : cdft_control_target%becke_control%cavity_mat = 0.0_dp
728 :
729 102 : DO j = 1, SIZE(mixed_cdft%source_list)
730 : cdft_control_target%becke_control%cavity_mat(recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
731 : recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
732 7136554 : recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r3
733 : END DO
734 34 : IF (mixed_cdft%dlb) THEN
735 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
736 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
737 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
738 16 : DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
739 : index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 1), &
740 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 1), &
741 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 2), &
742 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 2), &
743 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 3), &
744 104 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, 3)]
745 : cdft_control_target%becke_control%cavity_mat(INDEX(1):INDEX(2), &
746 : INDEX(3):INDEX(4), &
747 : INDEX(5):INDEX(6)) = &
748 14096 : mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity
749 16 : DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity)
750 : END DO
751 : END IF
752 : END DO
753 : END IF
754 : END IF
755 : END IF
756 108 : DO j = 1, SIZE(mixed_cdft%source_list)
757 108 : DEALLOCATE (recvbuffer(j)%r3)
758 : END DO
759 36 : IF (calculate_forces) THEN
760 : ! Gradients of the weight function
761 72 : DO j = 1, SIZE(mixed_cdft%source_list)
762 : ALLOCATE (recvbuffer(j)%r4(3*natom, recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
763 : recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
764 288 : recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)))
765 : CALL force_env%para_env%irecv(msgout=recvbuffer(j)%r4, source=mixed_cdft%source_list(j), &
766 72 : request=req_total(j))
767 : END DO
768 48 : DO i = 1, my_special_work
769 96 : DO j = 1, SIZE(mixed_cdft%dest_list)
770 48 : ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + SIZE(mixed_cdft%source_list)
771 72 : IF (mixed_cdft%is_special) THEN
772 : CALL force_env%para_env%isend(msgin=mixed_cdft%sendbuff(j)%gradients, &
773 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
774 0 : request=req_total(ind))
775 : ELSE
776 : CALL force_env%para_env%isend(msgin=cdft_control%group(1)%gradients, dest=mixed_cdft%dest_list(j), &
777 48 : request=req_total(ind))
778 : END IF
779 : END DO
780 : END DO
781 24 : CALL mp_waitall(req_total)
782 24 : IF (mixed_cdft%is_special) THEN
783 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
784 0 : DEALLOCATE (mixed_cdft%sendbuff(j)%gradients)
785 : END DO
786 0 : DEALLOCATE (mixed_cdft%sendbuff)
787 : ELSE
788 24 : DEALLOCATE (cdft_control%group(1)%gradients)
789 : END IF
790 : ALLOCATE (cdft_control_target%group(1)%gradients(3*natom, bo(1, 1):bo(2, 1), &
791 144 : bo(1, 2):bo(2, 2), lb_min:ub_max))
792 72 : DO j = 1, SIZE(mixed_cdft%source_list)
793 : cdft_control_target%group(1)%gradients(:, recvbuffer(j)%imap(1):recvbuffer(j)%imap(2), &
794 : recvbuffer(j)%imap(3):recvbuffer(j)%imap(4), &
795 39235744 : recvbuffer(j)%imap(5):recvbuffer(j)%imap(6)) = recvbuffer(j)%r4
796 72 : DEALLOCATE (recvbuffer(j)%r4)
797 : END DO
798 24 : IF (mixed_cdft%dlb) THEN
799 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
800 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
801 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
802 16 : DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
803 : index = [LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 2), &
804 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 2), &
805 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 3), &
806 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 3), &
807 : LBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 4), &
808 104 : UBOUND(mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, 4)]
809 : cdft_control_target%group(1)%gradients(:, INDEX(1):INDEX(2), &
810 : INDEX(3):INDEX(4), &
811 : INDEX(5):INDEX(6)) = &
812 90896 : mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients
813 16 : DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients)
814 : END DO
815 : END IF
816 : END DO
817 : END IF
818 : END IF
819 : END IF
820 : ! Clean up remaining temporaries
821 36 : IF (mixed_cdft%dlb) THEN
822 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
823 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
824 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
825 8 : IF (ASSOCIATED(mixed_cdft%dlb_control%recv_info(j)%target_list)) THEN
826 8 : DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%target_list)
827 : END IF
828 8 : DEALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs)
829 : END IF
830 : END DO
831 8 : DEALLOCATE (mixed_cdft%dlb_control%recv_info, mixed_cdft%dlb_control%recvbuff)
832 : END IF
833 8 : IF (ASSOCIATED(mixed_cdft%dlb_control%target_list)) THEN
834 4 : DEALLOCATE (mixed_cdft%dlb_control%target_list)
835 : END IF
836 8 : DEALLOCATE (mixed_cdft%dlb_control%recv_work_repl)
837 : END IF
838 36 : DEALLOCATE (recvbuffer)
839 36 : DEALLOCATE (req_total)
840 36 : DEALLOCATE (lb)
841 36 : DEALLOCATE (ub)
842 36 : CALL timestop(handle2)
843 : ! Set some flags so the weight is not rebuilt during SCF
844 36 : cdft_control_target%external_control = .TRUE.
845 36 : cdft_control_target%need_pot = .FALSE.
846 36 : cdft_control_target%transfer_pot = .FALSE.
847 : ! Store the bound indices for force calculation
848 36 : IF (calculate_forces) THEN
849 24 : cdft_control_target%becke_control%confine_bounds(2) = ub_max
850 24 : cdft_control_target%becke_control%confine_bounds(1) = lb_min
851 : END IF
852 : CALL pw_scale(cdft_control_target%group(1)%weight, &
853 36 : cdft_control_target%group(1)%weight%pw_grid%dvol)
854 : ! Set flags for ET coupling calculation
855 36 : IF (mixed_env%do_mixed_et) THEN
856 36 : IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
857 36 : dft_control%qs_control%cdft_control%do_et = .TRUE.
858 36 : dft_control%qs_control%cdft_control%calculate_metric = mixed_cdft%calculate_metric
859 : ELSE
860 0 : dft_control%qs_control%cdft_control%do_et = .FALSE.
861 0 : dft_control%qs_control%cdft_control%calculate_metric = .FALSE.
862 : END IF
863 : END IF
864 36 : t2 = m_walltime()
865 36 : IF (iounit > 0) THEN
866 18 : WRITE (iounit, '(A)') ' '
867 18 : WRITE (iounit, '(T2,A,F6.1,A)') 'MIXED_CDFT| Becke constraint built in ', t2 - t1, ' seconds'
868 18 : WRITE (iounit, '(A)') ' '
869 : END IF
870 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
871 36 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
872 36 : CALL timestop(handle)
873 :
874 108 : END SUBROUTINE mixed_cdft_build_weight_parallel
875 :
876 : ! **************************************************************************************************
877 : !> \brief Transfer CDFT weight/gradient between force_evals
878 : !> \param force_env the force_env that holds the CDFT sub_force_envs
879 : !> \param calculate_forces if forces should be computed
880 : !> \param iforce_eval index of the currently active CDFT state
881 : !> \par History
882 : !> 01.2017 created [Nico Holmberg]
883 : ! **************************************************************************************************
884 296 : SUBROUTINE mixed_cdft_transfer_weight(force_env, calculate_forces, iforce_eval)
885 : TYPE(force_env_type), POINTER :: force_env
886 : LOGICAL, INTENT(IN) :: calculate_forces
887 : INTEGER, INTENT(IN) :: iforce_eval
888 :
889 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_transfer_weight'
890 :
891 : INTEGER :: bounds_of(8), handle, iatom, igroup, &
892 : jforce_eval, nforce_eval
893 : LOGICAL, SAVE :: first_call = .TRUE.
894 : TYPE(cdft_control_type), POINTER :: cdft_control_source, cdft_control_target
895 : TYPE(dft_control_type), POINTER :: dft_control_source, dft_control_target
896 : TYPE(force_env_type), POINTER :: force_env_qs_source, force_env_qs_target
897 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
898 : TYPE(mixed_environment_type), POINTER :: mixed_env
899 : TYPE(pw_env_type), POINTER :: pw_env_source, pw_env_target
900 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool_source, &
901 : auxbas_pw_pool_target
902 : TYPE(qs_environment_type), POINTER :: qs_env_source, qs_env_target
903 :
904 148 : NULLIFY (mixed_cdft, dft_control_source, dft_control_target, force_env_qs_source, &
905 148 : force_env_qs_target, pw_env_source, pw_env_target, auxbas_pw_pool_source, &
906 148 : auxbas_pw_pool_target, qs_env_source, qs_env_target, mixed_env, &
907 148 : cdft_control_source, cdft_control_target)
908 148 : mixed_env => force_env%mixed_env
909 148 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
910 148 : CALL timeset(routineN, handle)
911 148 : IF (iforce_eval == 1) THEN
912 : jforce_eval = 1
913 : ELSE
914 86 : jforce_eval = iforce_eval - 1
915 : END IF
916 148 : nforce_eval = SIZE(force_env%sub_force_env)
917 296 : SELECT CASE (force_env%sub_force_env(jforce_eval)%force_env%in_use)
918 : CASE (use_qs_force, use_qmmm)
919 148 : force_env_qs_source => force_env%sub_force_env(jforce_eval)%force_env
920 148 : force_env_qs_target => force_env%sub_force_env(iforce_eval)%force_env
921 : CASE DEFAULT
922 : CALL cp_abort(__LOCATION__, &
923 : "Only use_qs_force and use_qmmm are "// &
924 148 : "supported for mixed_cdft_transfer_weight")
925 : END SELECT
926 148 : IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
927 : CALL force_env_get(force_env=force_env_qs_source, &
928 132 : qs_env=qs_env_source)
929 : CALL force_env_get(force_env=force_env_qs_target, &
930 132 : qs_env=qs_env_target)
931 : ELSE
932 16 : qs_env_source => force_env_qs_source%qmmm_env%qs_env
933 16 : qs_env_target => force_env_qs_target%qmmm_env%qs_env
934 : END IF
935 148 : IF (iforce_eval == 1) THEN
936 : ! The first force_eval builds the weight function and gradients in qs_cdft_methods.F
937 : ! Set some flags so the constraint is saved if the constraint definitions are identical in all CDFT states
938 62 : CALL get_qs_env(qs_env_source, dft_control=dft_control_source)
939 62 : cdft_control_source => dft_control_source%qs_control%cdft_control
940 62 : cdft_control_source%external_control = .FALSE.
941 62 : cdft_control_source%need_pot = .TRUE.
942 62 : IF (mixed_cdft%identical_constraints) THEN
943 60 : cdft_control_source%transfer_pot = .TRUE.
944 : ELSE
945 2 : cdft_control_source%transfer_pot = .FALSE.
946 : END IF
947 62 : mixed_cdft%sim_step = mixed_cdft%sim_step + 1
948 : ELSE
949 : ! Transfer the constraint from the ith force_eval to the i+1th
950 : CALL get_qs_env(qs_env_source, dft_control=dft_control_source, &
951 86 : pw_env=pw_env_source)
952 86 : CALL pw_env_get(pw_env_source, auxbas_pw_pool=auxbas_pw_pool_source)
953 86 : cdft_control_source => dft_control_source%qs_control%cdft_control
954 : CALL get_qs_env(qs_env_target, dft_control=dft_control_target, &
955 86 : pw_env=pw_env_target)
956 86 : CALL pw_env_get(pw_env_target, auxbas_pw_pool=auxbas_pw_pool_target)
957 86 : cdft_control_target => dft_control_target%qs_control%cdft_control
958 : ! The constraint can be transferred only when the constraint defitions are identical in all CDFT states
959 86 : IF (mixed_cdft%identical_constraints) THEN
960 : ! Weight function
961 170 : DO igroup = 1, SIZE(cdft_control_target%group)
962 86 : ALLOCATE (cdft_control_target%group(igroup)%weight)
963 86 : CALL auxbas_pw_pool_target%create_pw(cdft_control_target%group(igroup)%weight)
964 : ! We have ensured that the grids are consistent => no danger in using explicit copy
965 86 : CALL pw_copy(cdft_control_source%group(igroup)%weight, cdft_control_target%group(igroup)%weight)
966 86 : CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%group(igroup)%weight)
967 170 : DEALLOCATE (cdft_control_source%group(igroup)%weight)
968 : END DO
969 : ! Cavity
970 84 : IF (cdft_control_source%type == outer_scf_becke_constraint) THEN
971 78 : IF (cdft_control_source%becke_control%cavity_confine) THEN
972 72 : CALL auxbas_pw_pool_target%create_pw(cdft_control_target%becke_control%cavity)
973 72 : CALL pw_copy(cdft_control_source%becke_control%cavity, cdft_control_target%becke_control%cavity)
974 72 : CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%becke_control%cavity)
975 : END IF
976 : END IF
977 : ! Gradients
978 84 : IF (calculate_forces) THEN
979 40 : DO igroup = 1, SIZE(cdft_control_source%group)
980 : bounds_of = [LBOUND(cdft_control_source%group(igroup)%gradients, 1), &
981 : UBOUND(cdft_control_source%group(igroup)%gradients, 1), &
982 : LBOUND(cdft_control_source%group(igroup)%gradients, 2), &
983 : UBOUND(cdft_control_source%group(igroup)%gradients, 2), &
984 : LBOUND(cdft_control_source%group(igroup)%gradients, 3), &
985 : UBOUND(cdft_control_source%group(igroup)%gradients, 3), &
986 : LBOUND(cdft_control_source%group(igroup)%gradients, 4), &
987 340 : UBOUND(cdft_control_source%group(igroup)%gradients, 4)]
988 : ALLOCATE (cdft_control_target%group(igroup)% &
989 : gradients(bounds_of(1):bounds_of(2), bounds_of(3):bounds_of(4), &
990 120 : bounds_of(5):bounds_of(6), bounds_of(7):bounds_of(8)))
991 17857864 : cdft_control_target%group(igroup)%gradients = cdft_control_source%group(igroup)%gradients
992 40 : DEALLOCATE (cdft_control_source%group(igroup)%gradients)
993 : END DO
994 : END IF
995 : ! Atomic weight functions needed for CDFT charges
996 84 : IF (cdft_control_source%atomic_charges) THEN
997 18 : IF (.NOT. ASSOCIATED(cdft_control_target%charge)) THEN
998 10 : ALLOCATE (cdft_control_target%charge(cdft_control_target%natoms))
999 : END IF
1000 54 : DO iatom = 1, cdft_control_target%natoms
1001 36 : CALL auxbas_pw_pool_target%create_pw(cdft_control_target%charge(iatom))
1002 36 : CALL pw_copy(cdft_control_source%charge(iatom), cdft_control_target%charge(iatom))
1003 54 : CALL auxbas_pw_pool_source%give_back_pw(cdft_control_source%charge(iatom))
1004 : END DO
1005 : END IF
1006 : ! Set some flags so the weight is not rebuilt during SCF
1007 84 : cdft_control_target%external_control = .FALSE.
1008 84 : cdft_control_target%need_pot = .FALSE.
1009 : ! For states i+1 < nforce_eval, prevent deallocation of constraint
1010 84 : IF (iforce_eval == nforce_eval) THEN
1011 60 : cdft_control_target%transfer_pot = .FALSE.
1012 : ELSE
1013 24 : cdft_control_target%transfer_pot = .TRUE.
1014 : END IF
1015 84 : cdft_control_target%first_iteration = .FALSE.
1016 : ELSE
1017 : ! Force rebuild of constraint and dont save it
1018 2 : cdft_control_target%external_control = .FALSE.
1019 2 : cdft_control_target%need_pot = .TRUE.
1020 2 : cdft_control_target%transfer_pot = .FALSE.
1021 2 : IF (first_call) THEN
1022 2 : cdft_control_target%first_iteration = .TRUE.
1023 : ELSE
1024 0 : cdft_control_target%first_iteration = .FALSE.
1025 : END IF
1026 : END IF
1027 : END IF
1028 : ! Set flags for ET coupling calculation
1029 148 : IF (mixed_env%do_mixed_et) THEN
1030 148 : IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
1031 148 : IF (iforce_eval == 1) THEN
1032 62 : cdft_control_source%do_et = .TRUE.
1033 62 : cdft_control_source%calculate_metric = mixed_cdft%calculate_metric
1034 : ELSE
1035 86 : cdft_control_target%do_et = .TRUE.
1036 86 : cdft_control_target%calculate_metric = mixed_cdft%calculate_metric
1037 : END IF
1038 : ELSE
1039 0 : IF (iforce_eval == 1) THEN
1040 0 : cdft_control_source%do_et = .FALSE.
1041 0 : cdft_control_source%calculate_metric = .FALSE.
1042 : ELSE
1043 0 : cdft_control_target%do_et = .FALSE.
1044 0 : cdft_control_target%calculate_metric = .FALSE.
1045 : END IF
1046 : END IF
1047 : END IF
1048 148 : IF (iforce_eval == nforce_eval .AND. first_call) first_call = .FALSE.
1049 148 : CALL timestop(handle)
1050 :
1051 148 : END SUBROUTINE mixed_cdft_transfer_weight
1052 :
1053 : ! **************************************************************************************************
1054 : !> \brief In case CDFT states are treated in parallel, sets flags so that each CDFT state
1055 : !> builds their own weight functions and gradients
1056 : !> \param force_env the force_env that holds the CDFT sub_force_envs
1057 : !> \par History
1058 : !> 09.2018 created [Nico Holmberg]
1059 : ! **************************************************************************************************
1060 4 : SUBROUTINE mixed_cdft_set_flags(force_env)
1061 : TYPE(force_env_type), POINTER :: force_env
1062 :
1063 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_set_flags'
1064 :
1065 : INTEGER :: handle, iforce_eval, nforce_eval
1066 : LOGICAL, SAVE :: first_call = .TRUE.
1067 : TYPE(cdft_control_type), POINTER :: cdft_control
1068 : TYPE(dft_control_type), POINTER :: dft_control
1069 : TYPE(force_env_type), POINTER :: force_env_qs
1070 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1071 : TYPE(mixed_environment_type), POINTER :: mixed_env
1072 : TYPE(qs_environment_type), POINTER :: qs_env
1073 :
1074 2 : NULLIFY (mixed_cdft, dft_control, force_env_qs, qs_env, mixed_env, cdft_control)
1075 2 : mixed_env => force_env%mixed_env
1076 2 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
1077 2 : CALL timeset(routineN, handle)
1078 2 : nforce_eval = SIZE(force_env%sub_force_env)
1079 6 : DO iforce_eval = 1, nforce_eval
1080 4 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1081 2 : SELECT CASE (force_env%sub_force_env(iforce_eval)%force_env%in_use)
1082 : CASE (use_qs_force, use_qmmm)
1083 0 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
1084 : CASE DEFAULT
1085 : CALL cp_abort(__LOCATION__, &
1086 : "Only use_qs_force and use_qmmm are "// &
1087 2 : "supported for mixed_cdft_set_flags")
1088 : END SELECT
1089 2 : IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1090 2 : CALL force_env_get(force_env=force_env_qs, qs_env=qs_env)
1091 : ELSE
1092 0 : qs_env => force_env_qs%qmmm_env%qs_env
1093 : END IF
1094 : ! All force_evals build the weight function and gradients in qs_cdft_methods.F
1095 : ! Update flags to match run type
1096 2 : CALL get_qs_env(qs_env, dft_control=dft_control)
1097 2 : cdft_control => dft_control%qs_control%cdft_control
1098 2 : cdft_control%external_control = .FALSE.
1099 2 : cdft_control%need_pot = .TRUE.
1100 2 : cdft_control%transfer_pot = .FALSE.
1101 2 : IF (first_call) THEN
1102 2 : cdft_control%first_iteration = .TRUE.
1103 : ELSE
1104 0 : cdft_control%first_iteration = .FALSE.
1105 : END IF
1106 : ! Set flags for ET coupling calculation
1107 4 : IF (mixed_env%do_mixed_et) THEN
1108 2 : IF (MODULO(mixed_cdft%sim_step, mixed_env%et_freq) == 0) THEN
1109 2 : cdft_control%do_et = .TRUE.
1110 2 : cdft_control%calculate_metric = mixed_cdft%calculate_metric
1111 : ELSE
1112 0 : cdft_control%do_et = .FALSE.
1113 0 : cdft_control%calculate_metric = .FALSE.
1114 : END IF
1115 : END IF
1116 : END DO
1117 2 : mixed_cdft%sim_step = mixed_cdft%sim_step + 1
1118 2 : IF (first_call) first_call = .FALSE.
1119 2 : CALL timestop(handle)
1120 :
1121 2 : END SUBROUTINE mixed_cdft_set_flags
1122 :
1123 : ! **************************************************************************************************
1124 : !> \brief Driver routine to calculate the electronic coupling(s) between CDFT states.
1125 : !> \param force_env the force_env that holds the CDFT states
1126 : !> \par History
1127 : !> 02.15 created [Nico Holmberg]
1128 : ! **************************************************************************************************
1129 200 : SUBROUTINE mixed_cdft_calculate_coupling(force_env)
1130 : TYPE(force_env_type), POINTER :: force_env
1131 :
1132 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_coupling'
1133 :
1134 : INTEGER :: handle
1135 :
1136 100 : CPASSERT(ASSOCIATED(force_env))
1137 100 : CALL timeset(routineN, handle)
1138 : ! Move needed arrays from individual CDFT states to the mixed CDFT env
1139 100 : CALL mixed_cdft_redistribute_arrays(force_env)
1140 : ! Calculate the mixed CDFT Hamiltonian and overlap matrices.
1141 : ! All work matrices defined in the wavefunction basis get deallocated on exit.
1142 : ! Any analyses which depend on these work matrices are performed within.
1143 100 : CALL mixed_cdft_interaction_matrices(force_env)
1144 : ! Calculate eletronic couplings between states (Lowdin/rotation)
1145 100 : CALL mixed_cdft_calculate_coupling_low(force_env)
1146 : ! Print out couplings
1147 100 : CALL mixed_cdft_print_couplings(force_env)
1148 : ! Block diagonalize the mixed CDFT Hamiltonian matrix
1149 100 : CALL mixed_cdft_block_diag(force_env)
1150 : ! CDFT Configuration Interaction
1151 100 : CALL mixed_cdft_configuration_interaction(force_env)
1152 : ! Clean up
1153 100 : CALL mixed_cdft_release_work(force_env)
1154 100 : CALL timestop(handle)
1155 :
1156 100 : END SUBROUTINE mixed_cdft_calculate_coupling
1157 :
1158 : ! **************************************************************************************************
1159 : !> \brief Routine to calculate the mixed CDFT Hamiltonian and overlap matrices.
1160 : !> \param force_env the force_env that holds the CDFT states
1161 : !> \par History
1162 : !> 11.17 created [Nico Holmberg]
1163 : ! **************************************************************************************************
1164 100 : SUBROUTINE mixed_cdft_interaction_matrices(force_env)
1165 : TYPE(force_env_type), POINTER :: force_env
1166 :
1167 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_interaction_matrices'
1168 :
1169 : INTEGER :: check_ao(2), check_mo(2), handle, iforce_eval, ipermutation, ispin, istate, ivar, &
1170 : j, jstate, k, moeigvalunit, mounit, nao, ncol_local, nforce_eval, nmo, npermutations, &
1171 : nrow_local, nspins, nvar
1172 : INTEGER, ALLOCATABLE, DIMENSION(:) :: ncol_mo, nrow_mo
1173 100 : INTEGER, ALLOCATABLE, DIMENSION(:, :) :: homo
1174 : LOGICAL :: nelectron_mismatch, print_mo, &
1175 : print_mo_eigval, should_scale, &
1176 : uniform_occupation
1177 : REAL(KIND=dp) :: c(2), eps_occupied, nelectron_tot, &
1178 : sum_a(2), sum_b(2)
1179 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coupling_nonortho, eigenv, energy, Sda
1180 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: H_mat, S_det, S_mat, strength, tmp_mat, &
1181 100 : W_diagonal, Wad, Wda
1182 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: a, b
1183 100 : REAL(KIND=dp), DIMENSION(:), POINTER :: mo_eigval
1184 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_mo, mo_mo_fmstruct
1185 : TYPE(cp_fm_type) :: inverse_mat, Tinverse, tmp2
1186 100 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:) :: mo_overlap
1187 100 : TYPE(cp_fm_type), ALLOCATABLE, DIMENSION(:, :, :) :: w_matrix_mo
1188 100 : TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: mixed_mo_coeff
1189 : TYPE(cp_logger_type), POINTER :: logger
1190 100 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: density_matrix, density_matrix_diff, &
1191 100 : w_matrix
1192 : TYPE(dbcsr_type), POINTER :: mixed_matrix_s
1193 : TYPE(dft_control_type), POINTER :: dft_control
1194 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1195 : TYPE(mixed_environment_type), POINTER :: mixed_env
1196 : TYPE(qs_energy_type), POINTER :: energy_qs
1197 : TYPE(qs_environment_type), POINTER :: qs_env
1198 : TYPE(section_vals_type), POINTER :: force_env_section, mixed_cdft_section, &
1199 : print_section
1200 :
1201 100 : NULLIFY (force_env_section, print_section, mixed_cdft_section, &
1202 100 : mixed_env, mixed_cdft, qs_env, dft_control, fm_struct_mo, &
1203 100 : density_matrix_diff, mo_mo_fmstruct, &
1204 100 : mixed_mo_coeff, mixed_matrix_s, &
1205 100 : density_matrix, energy_qs, w_matrix, mo_eigval)
1206 200 : logger => cp_get_default_logger()
1207 100 : CPASSERT(ASSOCIATED(force_env))
1208 100 : CALL timeset(routineN, handle)
1209 : CALL force_env_get(force_env=force_env, &
1210 100 : force_env_section=force_env_section)
1211 100 : mixed_env => force_env%mixed_env
1212 100 : nforce_eval = SIZE(force_env%sub_force_env)
1213 100 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1214 100 : IF (section_get_lval(print_section, "MO_OVERLAP_MATRIX")) THEN
1215 2 : print_mo = .TRUE.
1216 2 : mounit = cp_print_key_unit_nr(logger, print_section, extension='.moOverlap', on_file=.TRUE.)
1217 : ELSE
1218 : print_mo = .FALSE.
1219 : END IF
1220 100 : IF (section_get_lval(print_section, "MO_OVERLAP_EIGENVALUES")) THEN
1221 14 : print_mo_eigval = .TRUE.
1222 14 : moeigvalunit = cp_print_key_unit_nr(logger, print_section, extension='.moOverlapEigval', on_file=.TRUE.)
1223 : ELSE
1224 : print_mo_eigval = .FALSE.
1225 : END IF
1226 100 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
1227 : ! Get redistributed work matrices
1228 100 : CPASSERT(ASSOCIATED(mixed_cdft))
1229 100 : CPASSERT(ASSOCIATED(mixed_cdft%matrix%mixed_mo_coeff))
1230 100 : CPASSERT(ASSOCIATED(mixed_cdft%matrix%w_matrix))
1231 100 : CPASSERT(ASSOCIATED(mixed_cdft%matrix%mixed_matrix_s))
1232 100 : mixed_mo_coeff => mixed_cdft%matrix%mixed_mo_coeff
1233 100 : w_matrix => mixed_cdft%matrix%w_matrix
1234 100 : mixed_matrix_s => mixed_cdft%matrix%mixed_matrix_s
1235 100 : IF (mixed_cdft%calculate_metric) THEN
1236 14 : CPASSERT(ASSOCIATED(mixed_cdft%matrix%density_matrix))
1237 14 : density_matrix => mixed_cdft%matrix%density_matrix
1238 : END IF
1239 : ! Get number of weight functions per state
1240 100 : nvar = SIZE(w_matrix, 2)
1241 100 : nspins = SIZE(mixed_mo_coeff, 2)
1242 : ! Check that the number of MOs/AOs is equal in every CDFT state
1243 400 : ALLOCATE (nrow_mo(nspins), ncol_mo(nspins))
1244 294 : DO ispin = 1, nspins
1245 194 : CALL cp_fm_get_info(mixed_mo_coeff(1, ispin), ncol_global=check_mo(1), nrow_global=check_ao(1))
1246 536 : DO iforce_eval = 2, nforce_eval
1247 242 : CALL cp_fm_get_info(mixed_mo_coeff(iforce_eval, ispin), ncol_global=check_mo(2), nrow_global=check_ao(2))
1248 242 : IF (check_ao(1) /= check_ao(2)) THEN
1249 : CALL cp_abort(__LOCATION__, &
1250 0 : "The number of atomic orbitals must be the same in every CDFT state.")
1251 : END IF
1252 436 : IF (check_mo(1) /= check_mo(2)) THEN
1253 : CALL cp_abort(__LOCATION__, &
1254 0 : "The number of molecular orbitals must be the same in every CDFT state.")
1255 : END IF
1256 : END DO
1257 : END DO
1258 : ! Allocate work
1259 100 : npermutations = nforce_eval*(nforce_eval - 1)/2 ! Size of upper triangular part
1260 1426 : ALLOCATE (w_matrix_mo(nforce_eval, nforce_eval, nvar))
1261 782 : ALLOCATE (mo_overlap(npermutations), S_det(npermutations, nspins))
1262 800 : ALLOCATE (a(nspins, nvar, npermutations), b(nspins, nvar, npermutations))
1263 100 : a = 0.0_dp
1264 100 : b = 0.0_dp
1265 100 : IF (mixed_cdft%calculate_metric) THEN
1266 106 : ALLOCATE (density_matrix_diff(npermutations, nspins))
1267 42 : DO ispin = 1, nspins
1268 78 : DO ipermutation = 1, npermutations
1269 36 : NULLIFY (density_matrix_diff(ipermutation, ispin)%matrix)
1270 36 : CALL dbcsr_init_p(density_matrix_diff(ipermutation, ispin)%matrix)
1271 36 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1272 : CALL dbcsr_copy(density_matrix_diff(ipermutation, ispin)%matrix, &
1273 64 : density_matrix(istate, ispin)%matrix, name="DENSITY_MATRIX")
1274 : END DO
1275 : END DO
1276 : END IF
1277 : ! Check for uniform occupations
1278 100 : uniform_occupation = .NOT. ALLOCATED(mixed_cdft%occupations)
1279 100 : should_scale = .FALSE.
1280 100 : IF (.NOT. uniform_occupation) THEN
1281 56 : ALLOCATE (homo(nforce_eval, nspins))
1282 14 : mixed_cdft_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT")
1283 14 : CALL section_vals_val_get(mixed_cdft_section, "EPS_OCCUPIED", r_val=eps_occupied)
1284 14 : IF (eps_occupied > 1.0_dp .OR. eps_occupied < 0.0_dp) THEN
1285 : CALL cp_abort(__LOCATION__, &
1286 0 : "Keyword EPS_OCCUPIED only accepts values between 0.0 and 1.0")
1287 : END IF
1288 14 : IF (mixed_cdft%eps_svd == 0.0_dp) THEN
1289 : CALL cp_warn(__LOCATION__, &
1290 : "The usage of SVD based matrix inversions with fractionally occupied "// &
1291 0 : "orbitals is strongly recommended to screen nearly orthogonal states.")
1292 : END IF
1293 28 : CALL section_vals_val_get(mixed_cdft_section, "SCALE_WITH_OCCUPATION_NUMBERS", l_val=should_scale)
1294 : END IF
1295 : ! Start the actual calculation
1296 294 : DO ispin = 1, nspins
1297 : ! Create the MOxMO fm struct (mo_mo_fm_pools%struct)
1298 : ! The number of MOs/AOs is equal to the number of columns/rows of mo_coeff(:,:)%matrix
1299 194 : NULLIFY (fm_struct_mo, mo_mo_fmstruct)
1300 194 : CALL cp_fm_get_info(mixed_mo_coeff(1, ispin), ncol_global=ncol_mo(ispin), nrow_global=nrow_mo(ispin))
1301 194 : nao = nrow_mo(ispin)
1302 194 : IF (uniform_occupation) THEN
1303 166 : nmo = ncol_mo(ispin)
1304 : ELSE
1305 28 : nmo = ncol_mo(ispin)
1306 : ! Find indices of highest (fractionally) occupied molecular orbital
1307 84 : homo(:, ispin) = nmo
1308 84 : DO istate = 1, nforce_eval
1309 152 : DO j = nmo, 1, -1
1310 124 : IF (mixed_cdft%occupations(istate, ispin)%array(j) >= eps_occupied) THEN
1311 56 : homo(istate, ispin) = j
1312 56 : EXIT
1313 : END IF
1314 : END DO
1315 : END DO
1316 : ! Make matrices square by using the largest homo and emit warning if a state has fewer occupied MOs
1317 : ! Although it would be possible to handle the nonsquare situation as well,
1318 : ! all CDFT states should be in the same spin state for meaningful results
1319 84 : nmo = MAXVAL(homo(:, ispin))
1320 : ! Also check that the number of electrons is conserved (using a fixed sensible threshold)
1321 28 : nelectron_mismatch = .FALSE.
1322 92 : nelectron_tot = SUM(mixed_cdft%occupations(1, ispin)%array(1:nmo))
1323 56 : DO istate = 2, nforce_eval
1324 120 : IF (ABS(SUM(mixed_cdft%occupations(istate, ispin)%array(1:nmo)) - nelectron_tot) > 1.0E-4_dp) THEN
1325 0 : nelectron_mismatch = .TRUE.
1326 : END IF
1327 : END DO
1328 84 : IF (ANY(homo(:, ispin) /= nmo)) THEN
1329 0 : IF (ispin == 1) THEN
1330 : CALL cp_warn(__LOCATION__, &
1331 : "The number of occupied alpha MOs is not constant across all CDFT states. "// &
1332 0 : "Calculation proceeds but the results will likely be meaningless.")
1333 : ELSE
1334 : CALL cp_warn(__LOCATION__, &
1335 : "The number of occupied beta MOs is not constant across all CDFT states. "// &
1336 0 : "Calculation proceeds but the results will likely be meaningless.")
1337 : END IF
1338 28 : ELSE IF (nelectron_mismatch) THEN
1339 0 : IF (ispin == 1) THEN
1340 : CALL cp_warn(__LOCATION__, &
1341 : "The number of alpha electrons is not constant across all CDFT states. "// &
1342 0 : "Calculation proceeds but the results will likely be meaningless.")
1343 : ELSE
1344 : CALL cp_warn(__LOCATION__, &
1345 : "The number of beta electrons is not constant across all CDFT states. "// &
1346 0 : "Calculation proceeds but the results will likely be meaningless.")
1347 : END IF
1348 : END IF
1349 : END IF
1350 : CALL cp_fm_struct_create(fm_struct_mo, nrow_global=nao, ncol_global=nmo, &
1351 194 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
1352 : CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, &
1353 194 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
1354 : ! Allocate work
1355 : CALL cp_fm_create(matrix=tmp2, matrix_struct=fm_struct_mo, &
1356 194 : name="ET_TMP_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1357 194 : CALL cp_fm_struct_release(fm_struct_mo)
1358 : CALL cp_fm_create(matrix=inverse_mat, matrix_struct=mo_mo_fmstruct, &
1359 194 : name="INVERSE_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1360 : CALL cp_fm_create(matrix=Tinverse, matrix_struct=mo_mo_fmstruct, &
1361 194 : name="T_INVERSE_"//TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1362 552 : DO istate = 1, npermutations
1363 : CALL cp_fm_create(matrix=mo_overlap(istate), matrix_struct=mo_mo_fmstruct, &
1364 : name="MO_OVERLAP_"//TRIM(ADJUSTL(cp_to_string(istate)))//"_"// &
1365 552 : TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1366 : END DO
1367 392 : DO ivar = 1, nvar
1368 836 : DO istate = 1, nforce_eval
1369 1810 : DO jstate = 1, nforce_eval
1370 1168 : IF (istate == jstate) CYCLE
1371 : CALL cp_fm_create(matrix=w_matrix_mo(istate, jstate, ivar), matrix_struct=mo_mo_fmstruct, &
1372 : name="W_"//TRIM(ADJUSTL(cp_to_string(istate)))//"_"// &
1373 : TRIM(ADJUSTL(cp_to_string(jstate)))//"_"// &
1374 1612 : TRIM(ADJUSTL(cp_to_string(ivar)))//"_MATRIX")
1375 : END DO
1376 : END DO
1377 : END DO
1378 194 : CALL cp_fm_struct_release(mo_mo_fmstruct)
1379 : ! Remove empty MOs and (possibly) scale rest with occupation numbers
1380 194 : IF (.NOT. uniform_occupation) THEN
1381 84 : DO iforce_eval = 1, nforce_eval
1382 56 : CALL cp_fm_to_fm(mixed_mo_coeff(iforce_eval, ispin), tmp2, nmo, 1, 1)
1383 56 : CALL cp_fm_release(mixed_mo_coeff(iforce_eval, ispin))
1384 : CALL cp_fm_create(mixed_mo_coeff(iforce_eval, ispin), &
1385 : matrix_struct=tmp2%matrix_struct, &
1386 : name="MO_COEFF_"//TRIM(ADJUSTL(cp_to_string(iforce_eval)))//"_" &
1387 56 : //TRIM(ADJUSTL(cp_to_string(ispin)))//"_MATRIX")
1388 56 : CALL cp_fm_to_fm(tmp2, mixed_mo_coeff(iforce_eval, ispin))
1389 56 : IF (should_scale) THEN
1390 : CALL cp_fm_column_scale(mixed_mo_coeff(iforce_eval, ispin), &
1391 40 : mixed_cdft%occupations(iforce_eval, ispin)%array(1:nmo))
1392 : END IF
1393 84 : DEALLOCATE (mixed_cdft%occupations(iforce_eval, ispin)%array)
1394 : END DO
1395 : END IF
1396 : ! calculate the MO overlaps (C_j)^T S C_i
1397 194 : ipermutation = 0
1398 630 : DO istate = 1, nforce_eval
1399 988 : DO jstate = istate + 1, nforce_eval
1400 358 : ipermutation = ipermutation + 1
1401 : CALL cp_dbcsr_sm_fm_multiply(mixed_matrix_s, mixed_mo_coeff(istate, ispin), &
1402 358 : tmp2, nmo, 1.0_dp, 0.0_dp)
1403 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
1404 : mixed_mo_coeff(jstate, ispin), &
1405 358 : tmp2, 0.0_dp, mo_overlap(ipermutation))
1406 794 : IF (print_mo) THEN
1407 : CALL cp_fm_write_formatted(mo_overlap(ipermutation), mounit, &
1408 : "# MO overlap matrix (step "//TRIM(ADJUSTL(cp_to_string(mixed_cdft%sim_step)))// &
1409 : "): CDFT states "//TRIM(ADJUSTL(cp_to_string(istate)))//" and "// &
1410 : TRIM(ADJUSTL(cp_to_string(jstate)))//" (spin "// &
1411 4 : TRIM(ADJUSTL(cp_to_string(ispin)))//")")
1412 : END IF
1413 : END DO
1414 : END DO
1415 : ! calculate the MO-representations of the restraint matrices of all CDFT states
1416 392 : DO ivar = 1, nvar
1417 836 : DO jstate = 1, nforce_eval
1418 1810 : DO istate = 1, nforce_eval
1419 1168 : IF (istate == jstate) CYCLE
1420 : ! State i: (C_j)^T W_i C_i
1421 : CALL cp_dbcsr_sm_fm_multiply(w_matrix(istate, ivar)%matrix, &
1422 : mixed_mo_coeff(istate, ispin), &
1423 724 : tmp2, nmo, 1.0_dp, 0.0_dp)
1424 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
1425 : mixed_mo_coeff(jstate, ispin), &
1426 1612 : tmp2, 0.0_dp, w_matrix_mo(istate, jstate, ivar))
1427 : END DO
1428 : END DO
1429 : END DO
1430 552 : DO ipermutation = 1, npermutations
1431 : ! Invert and calculate determinant of MO overlaps
1432 358 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1433 358 : IF (print_mo_eigval) THEN
1434 28 : NULLIFY (mo_eigval)
1435 : CALL cp_fm_invert(mo_overlap(ipermutation), inverse_mat, &
1436 : S_det(ipermutation, ispin), eps_svd=mixed_cdft%eps_svd, &
1437 28 : eigval=mo_eigval)
1438 28 : IF (moeigvalunit > 0) THEN
1439 14 : IF (mixed_cdft%eps_svd == 0.0_dp) THEN
1440 : WRITE (moeigvalunit, '(A,I2,A,I2,A,I1,A)') &
1441 0 : "# MO Overlap matrix eigenvalues for CDFT states ", istate, " and ", jstate, &
1442 0 : " (spin ", ispin, ")"
1443 : ELSE
1444 : WRITE (moeigvalunit, '(A,I2,A,I2,A,I1,A)') &
1445 14 : "# MO Overlap matrix singular values for CDFT states ", istate, " and ", jstate, &
1446 28 : " (spin ", ispin, ")"
1447 : END IF
1448 14 : WRITE (moeigvalunit, '(A1, A9, A12)') "#", "Index", ADJUSTL("Value")
1449 46 : DO j = 1, SIZE(mo_eigval)
1450 46 : WRITE (moeigvalunit, '(I10, F12.8)') j, mo_eigval(j)
1451 : END DO
1452 : END IF
1453 28 : DEALLOCATE (mo_eigval)
1454 : ELSE
1455 : CALL cp_fm_invert(mo_overlap(ipermutation), inverse_mat, &
1456 330 : S_det(ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
1457 : END IF
1458 358 : CALL cp_fm_get_info(inverse_mat, nrow_local=nrow_local, ncol_local=ncol_local)
1459 : ! Calculate <Psi_i | w_j(r) | Psi_j> for ivar:th constraint
1460 924 : DO j = 1, ncol_local
1461 1437 : DO k = 1, nrow_local
1462 1597 : DO ivar = 1, nvar
1463 : b(ispin, ivar, ipermutation) = b(ispin, ivar, ipermutation) + &
1464 : w_matrix_mo(jstate, istate, ivar)%local_data(k, j)* &
1465 1031 : inverse_mat%local_data(k, j)
1466 : END DO
1467 : END DO
1468 : END DO
1469 : ! Calculate <Psi_j | w_i(r) | Psi_i> for ivar:th constraint
1470 358 : CALL cp_fm_transpose(inverse_mat, Tinverse)
1471 924 : DO j = 1, ncol_local
1472 1437 : DO k = 1, nrow_local
1473 1597 : DO ivar = 1, nvar
1474 : a(ispin, ivar, ipermutation) = a(ispin, ivar, ipermutation) + &
1475 : w_matrix_mo(istate, jstate, ivar)%local_data(k, j)* &
1476 1031 : Tinverse%local_data(k, j)
1477 : END DO
1478 : END DO
1479 : END DO
1480 : ! Handle different constraint types
1481 720 : DO ivar = 1, nvar
1482 362 : SELECT CASE (mixed_cdft%constraint_type(ivar, istate))
1483 : CASE (cdft_charge_constraint)
1484 : ! No action needed
1485 : CASE (cdft_magnetization_constraint)
1486 0 : IF (ispin == 2) a(ispin, ivar, ipermutation) = -a(ispin, ivar, ipermutation)
1487 : CASE (cdft_alpha_constraint)
1488 : ! Constraint applied to alpha electrons only, set integrals involving beta to zero
1489 4 : IF (ispin == 2) a(ispin, ivar, ipermutation) = 0.0_dp
1490 : CASE (cdft_beta_constraint)
1491 : ! Constraint applied to beta electrons only, set integrals involving alpha to zero
1492 4 : IF (ispin == 1) a(ispin, ivar, ipermutation) = 0.0_dp
1493 : CASE DEFAULT
1494 362 : CPABORT("Unknown constraint type.")
1495 : END SELECT
1496 358 : SELECT CASE (mixed_cdft%constraint_type(ivar, jstate))
1497 : CASE (cdft_charge_constraint)
1498 : ! No action needed
1499 : CASE (cdft_magnetization_constraint)
1500 0 : IF (ispin == 2) b(ispin, ivar, ipermutation) = -b(ispin, ivar, ipermutation)
1501 : CASE (cdft_alpha_constraint)
1502 : ! Constraint applied to alpha electrons only, set integrals involving beta to zero
1503 4 : IF (ispin == 2) b(ispin, ivar, ipermutation) = 0.0_dp
1504 : CASE (cdft_beta_constraint)
1505 : ! Constraint applied to beta electrons only, set integrals involving alpha to zero
1506 4 : IF (ispin == 1) b(ispin, ivar, ipermutation) = 0.0_dp
1507 : CASE DEFAULT
1508 362 : CPABORT("Unknown constraint type.")
1509 : END SELECT
1510 : END DO
1511 : ! Compute density matrix difference P = P_j - P_i
1512 358 : IF (mixed_cdft%calculate_metric) THEN
1513 : CALL dbcsr_add(density_matrix_diff(ipermutation, ispin)%matrix, &
1514 36 : density_matrix(jstate, ispin)%matrix, -1.0_dp, 1.0_dp)
1515 : END IF
1516 : !
1517 1082 : CALL force_env%para_env%sum(a(ispin, :, ipermutation))
1518 1992 : CALL force_env%para_env%sum(b(ispin, :, ipermutation))
1519 : END DO
1520 : ! Release work
1521 194 : CALL cp_fm_release(tmp2)
1522 392 : DO ivar = 1, nvar
1523 836 : DO jstate = 1, nforce_eval
1524 1810 : DO istate = 1, nforce_eval
1525 1168 : IF (istate == jstate) CYCLE
1526 1612 : CALL cp_fm_release(w_matrix_mo(istate, jstate, ivar))
1527 : END DO
1528 : END DO
1529 : END DO
1530 552 : DO ipermutation = 1, npermutations
1531 552 : CALL cp_fm_release(mo_overlap(ipermutation))
1532 : END DO
1533 194 : CALL cp_fm_release(Tinverse)
1534 294 : CALL cp_fm_release(inverse_mat)
1535 : END DO
1536 100 : DEALLOCATE (mo_overlap)
1537 100 : DEALLOCATE (w_matrix_mo)
1538 100 : IF (.NOT. uniform_occupation) THEN
1539 14 : DEALLOCATE (homo)
1540 14 : DEALLOCATE (mixed_cdft%occupations)
1541 : END IF
1542 100 : IF (print_mo) THEN
1543 : CALL cp_print_key_finished_output(mounit, logger, force_env_section, &
1544 2 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO", on_file=.TRUE.)
1545 : END IF
1546 100 : IF (print_mo_eigval) THEN
1547 : CALL cp_print_key_finished_output(moeigvalunit, logger, force_env_section, &
1548 14 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO", on_file=.TRUE.)
1549 : END IF
1550 : ! solve eigenstates for the projector matrix
1551 400 : ALLOCATE (Wda(nvar, npermutations))
1552 300 : ALLOCATE (Sda(npermutations))
1553 104 : IF (.NOT. mixed_cdft%identical_constraints) ALLOCATE (Wad(nvar, npermutations))
1554 282 : DO ipermutation = 1, npermutations
1555 182 : IF (nspins == 2) THEN
1556 176 : Sda(ipermutation) = ABS(S_det(ipermutation, 1)*S_det(ipermutation, 2))
1557 : ELSE
1558 6 : Sda(ipermutation) = S_det(ipermutation, 1)**2
1559 : END IF
1560 : ! Finalize <Psi_j | w_i(r) | Psi_i> by multiplication with Sda
1561 466 : DO ivar = 1, nvar
1562 366 : IF (mixed_cdft%identical_constraints) THEN
1563 : Wda(ivar, ipermutation) = (SUM(a(:, ivar, ipermutation)) + SUM(b(:, ivar, ipermutation)))* &
1564 898 : Sda(ipermutation)/2.0_dp
1565 : ELSE
1566 6 : Wda(ivar, ipermutation) = SUM(a(:, ivar, ipermutation))*Sda(ipermutation)
1567 6 : Wad(ivar, ipermutation) = SUM(b(:, ivar, ipermutation))*Sda(ipermutation)
1568 : END IF
1569 : END DO
1570 : END DO
1571 100 : DEALLOCATE (a, b, S_det)
1572 : ! Transfer info about the constraint calculations
1573 800 : ALLOCATE (W_diagonal(nvar, nforce_eval), strength(nvar, nforce_eval), energy(nforce_eval))
1574 100 : W_diagonal = 0.0_dp
1575 324 : DO iforce_eval = 1, nforce_eval
1576 552 : strength(:, iforce_eval) = mixed_env%strength(iforce_eval, :)
1577 : END DO
1578 100 : energy = 0.0_dp
1579 324 : DO iforce_eval = 1, nforce_eval
1580 224 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1581 186 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1582 24 : qs_env => force_env%sub_force_env(iforce_eval)%force_env%qmmm_env%qs_env
1583 : ELSE
1584 162 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, qs_env=qs_env)
1585 : END IF
1586 186 : CALL get_qs_env(qs_env, energy=energy_qs, dft_control=dft_control)
1587 286 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1588 226 : W_diagonal(:, iforce_eval) = dft_control%qs_control%cdft_control%value(:)
1589 150 : energy(iforce_eval) = energy_qs%total
1590 : END IF
1591 : END DO
1592 100 : CALL force_env%para_env%sum(W_diagonal)
1593 100 : CALL force_env%para_env%sum(energy)
1594 : CALL mixed_cdft_result_type_set(mixed_cdft%results, Wda=Wda, W_diagonal=W_diagonal, &
1595 100 : energy=energy, strength=strength)
1596 100 : IF (.NOT. mixed_cdft%identical_constraints) CALL mixed_cdft_result_type_set(mixed_cdft%results, Wad=Wad)
1597 : ! Construct S
1598 400 : ALLOCATE (S_mat(nforce_eval, nforce_eval))
1599 324 : DO istate = 1, nforce_eval
1600 324 : S_mat(istate, istate) = 1.0_dp
1601 : END DO
1602 282 : DO ipermutation = 1, npermutations
1603 182 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1604 182 : S_mat(istate, jstate) = Sda(ipermutation)
1605 282 : S_mat(jstate, istate) = Sda(ipermutation)
1606 : END DO
1607 100 : CALL mixed_cdft_result_type_set(mixed_cdft%results, S=S_mat)
1608 : ! Invert S via eigendecomposition and compute S^-(1/2)
1609 400 : ALLOCATE (eigenv(nforce_eval), tmp_mat(nforce_eval, nforce_eval))
1610 100 : CALL diamat_all(S_mat, eigenv, .TRUE.)
1611 100 : tmp_mat = 0.0_dp
1612 324 : DO istate = 1, nforce_eval
1613 224 : IF (eigenv(istate) < 1.0e-14_dp) THEN
1614 : ! Safeguard against division with 0 and negative numbers
1615 10 : eigenv(istate) = 1.0e-14_dp
1616 : CALL cp_warn(__LOCATION__, &
1617 : "The overlap matrix is numerically nearly singular. "// &
1618 10 : "Calculation proceeds but the results might be meaningless.")
1619 : END IF
1620 324 : tmp_mat(istate, istate) = 1.0_dp/SQRT(eigenv(istate))
1621 : END DO
1622 5940 : tmp_mat(:, :) = MATMUL(tmp_mat, TRANSPOSE(S_mat))
1623 10356 : S_mat(:, :) = MATMUL(S_mat, tmp_mat) ! S^(-1/2)
1624 100 : CALL mixed_cdft_result_type_set(mixed_cdft%results, S_minushalf=S_mat)
1625 100 : DEALLOCATE (eigenv, tmp_mat, S_mat)
1626 : ! Construct nonorthogonal diabatic Hamiltonian matrix H''
1627 300 : ALLOCATE (H_mat(nforce_eval, nforce_eval))
1628 118 : IF (mixed_cdft%nonortho_coupling) ALLOCATE (coupling_nonortho(npermutations))
1629 324 : DO istate = 1, nforce_eval
1630 324 : H_mat(istate, istate) = energy(istate)
1631 : END DO
1632 282 : DO ipermutation = 1, npermutations
1633 182 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1634 182 : sum_a = 0.0_dp
1635 182 : sum_b = 0.0_dp
1636 366 : DO ivar = 1, nvar
1637 : ! V_J * <Psi_J | w_J(r) | Psi_J>
1638 184 : sum_b(1) = sum_b(1) + strength(ivar, jstate)*W_diagonal(ivar, jstate)
1639 : ! V_I * <Psi_I | w_I(r) | Psi_I>
1640 184 : sum_a(1) = sum_a(1) + strength(ivar, istate)*W_diagonal(ivar, istate)
1641 366 : IF (mixed_cdft%identical_constraints) THEN
1642 : ! V_J * W_IJ
1643 182 : sum_b(2) = sum_b(2) + strength(ivar, jstate)*Wda(ivar, ipermutation)
1644 : ! V_I * W_JI
1645 182 : sum_a(2) = sum_a(2) + strength(ivar, istate)*Wda(ivar, ipermutation)
1646 : ELSE
1647 : ! V_J * W_IJ
1648 2 : sum_b(2) = sum_b(2) + strength(ivar, jstate)*Wad(ivar, ipermutation)
1649 : ! V_I * W_JI
1650 2 : sum_a(2) = sum_a(2) + strength(ivar, istate)*Wda(ivar, ipermutation)
1651 : END IF
1652 : END DO
1653 : ! Denote F_X = <Psi_X | H_X + V_X*w_X(r) | Psi_X> = E_X + V_X*<Psi_X | w_X(r) | Psi_X>
1654 : ! H_IJ = F_J*S_IJ - V_J * W_IJ
1655 182 : c(1) = (energy(jstate) + sum_b(1))*Sda(ipermutation) - sum_b(2)
1656 : ! H_JI = F_I*S_JI - V_I * W_JI
1657 182 : c(2) = (energy(istate) + sum_a(1))*Sda(ipermutation) - sum_a(2)
1658 : ! H''(I,J) = 0.5*(H_IJ+H_JI) = H''(J,I)
1659 182 : H_mat(istate, jstate) = (c(1) + c(2))*0.5_dp
1660 182 : H_mat(jstate, istate) = H_mat(istate, jstate)
1661 464 : IF (mixed_cdft%nonortho_coupling) coupling_nonortho(ipermutation) = H_mat(istate, jstate)
1662 : END DO
1663 100 : CALL mixed_cdft_result_type_set(mixed_cdft%results, H=H_mat)
1664 100 : DEALLOCATE (H_mat, W_diagonal, Wda, strength, energy, Sda)
1665 100 : IF (ALLOCATED(Wad)) DEALLOCATE (Wad)
1666 100 : IF (mixed_cdft%nonortho_coupling) THEN
1667 18 : CALL mixed_cdft_result_type_set(mixed_cdft%results, nonortho=coupling_nonortho)
1668 18 : DEALLOCATE (coupling_nonortho)
1669 : END IF
1670 : ! Compute metric to assess reliability of coupling
1671 100 : IF (mixed_cdft%calculate_metric) CALL mixed_cdft_calculate_metric(force_env, mixed_cdft, density_matrix_diff, ncol_mo)
1672 : ! Compute coupling also with the wavefunction overlap method, see Migliore2009
1673 : ! Requires the unconstrained KS ground state wavefunction as input
1674 100 : IF (mixed_cdft%wfn_overlap_method) THEN
1675 8 : IF (.NOT. uniform_occupation) THEN
1676 : CALL cp_abort(__LOCATION__, &
1677 0 : "Wavefunction overlap method supports only uniformly occupied MOs.")
1678 : END IF
1679 8 : CALL mixed_cdft_wfn_overlap_method(force_env, mixed_cdft, ncol_mo, nrow_mo)
1680 : END IF
1681 : ! Release remaining work
1682 100 : DEALLOCATE (nrow_mo, ncol_mo)
1683 100 : CALL mixed_cdft_work_type_release(mixed_cdft%matrix)
1684 100 : CALL timestop(handle)
1685 :
1686 300 : END SUBROUTINE mixed_cdft_interaction_matrices
1687 :
1688 : ! **************************************************************************************************
1689 : !> \brief Routine to calculate the CDFT electronic couplings.
1690 : !> \param force_env the force_env that holds the CDFT states
1691 : !> \par History
1692 : !> 11.17 created [Nico Holmberg]
1693 : ! **************************************************************************************************
1694 100 : SUBROUTINE mixed_cdft_calculate_coupling_low(force_env)
1695 : TYPE(force_env_type), POINTER :: force_env
1696 :
1697 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_coupling_low'
1698 :
1699 : INTEGER :: handle, ipermutation, istate, jstate, &
1700 : nforce_eval, npermutations, nvar
1701 : LOGICAL :: use_lowdin, use_rotation
1702 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coupling_lowdin, coupling_rotation, &
1703 100 : eigenv
1704 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: tmp_mat, W_mat
1705 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1706 :
1707 100 : NULLIFY (mixed_cdft)
1708 100 : CPASSERT(ASSOCIATED(force_env))
1709 100 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
1710 100 : CALL timeset(routineN, handle)
1711 100 : CPASSERT(ASSOCIATED(mixed_cdft))
1712 100 : CPASSERT(ALLOCATED(mixed_cdft%results%W_diagonal))
1713 100 : CPASSERT(ALLOCATED(mixed_cdft%results%Wda))
1714 100 : CPASSERT(ALLOCATED(mixed_cdft%results%S_minushalf))
1715 100 : CPASSERT(ALLOCATED(mixed_cdft%results%H))
1716 : ! Decide which methods to use for computing the coupling
1717 : ! Default behavior is to use rotation when a single constraint is active, otherwise uses Lowdin orthogonalization
1718 : ! The latter can also be explicitly requested when a single constraint is active
1719 : ! Possibly computes the coupling additionally with the wavefunction overlap method
1720 100 : nforce_eval = SIZE(mixed_cdft%results%H, 1)
1721 100 : nvar = SIZE(mixed_cdft%results%Wda, 1)
1722 100 : npermutations = nforce_eval*(nforce_eval - 1)/2
1723 400 : ALLOCATE (tmp_mat(nforce_eval, nforce_eval))
1724 100 : IF (nvar == 1 .AND. mixed_cdft%identical_constraints) THEN
1725 96 : use_rotation = .TRUE.
1726 96 : use_lowdin = mixed_cdft%use_lowdin
1727 : ELSE
1728 : use_rotation = .FALSE.
1729 : use_lowdin = .TRUE.
1730 : END IF
1731 : ! Calculate coupling by rotating the CDFT states to eigenstates of the weight matrix W (single constraint only)
1732 : IF (use_rotation) THEN
1733 : ! Construct W
1734 480 : ALLOCATE (W_mat(nforce_eval, nforce_eval), coupling_rotation(npermutations))
1735 288 : ALLOCATE (eigenv(nforce_eval))
1736 : ! W_mat(i, i) = N_i where N_i is the value of the constraint in state i
1737 312 : DO istate = 1, nforce_eval
1738 528 : W_mat(istate, istate) = SUM(mixed_cdft%results%W_diagonal(:, istate))
1739 : END DO
1740 : ! W_mat(i, j) = <Psi_i|w(r)|Psi_j>
1741 274 : DO ipermutation = 1, npermutations
1742 178 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1743 356 : W_mat(istate, jstate) = SUM(mixed_cdft%results%Wda(:, ipermutation))
1744 452 : W_mat(jstate, istate) = W_mat(istate, jstate)
1745 : END DO
1746 : ! Solve generalized eigenvalue equation WV = SVL
1747 : ! Convert to standard eigenvalue problem via symmetric orthogonalisation
1748 5036 : tmp_mat(:, :) = MATMUL(W_mat, mixed_cdft%results%S_minushalf) ! W * S^(-1/2)
1749 5036 : W_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, tmp_mat) ! W' = S^(-1/2) * W * S^(-1/2)
1750 96 : CALL diamat_all(W_mat, eigenv, .TRUE.) ! Solve W'V' = AV'
1751 9188 : tmp_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, W_mat) ! Reverse transformation V = S^(-1/2) V'
1752 : ! Construct final, orthogonal diabatic Hamiltonian matrix H
1753 9188 : W_mat(:, :) = MATMUL(mixed_cdft%results%H, tmp_mat) ! H'' * V
1754 10168 : W_mat(:, :) = MATMUL(TRANSPOSE(tmp_mat), W_mat) ! H = V^T * H'' * V
1755 274 : DO ipermutation = 1, npermutations
1756 178 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1757 274 : coupling_rotation(ipermutation) = W_mat(istate, jstate)
1758 : END DO
1759 96 : CALL mixed_cdft_result_type_set(mixed_cdft%results, rotation=coupling_rotation)
1760 96 : DEALLOCATE (W_mat, coupling_rotation, eigenv)
1761 : END IF
1762 : ! Calculate coupling by Lowdin orthogonalization
1763 100 : IF (use_lowdin) THEN
1764 60 : ALLOCATE (coupling_lowdin(npermutations))
1765 780 : tmp_mat(:, :) = MATMUL(mixed_cdft%results%H, mixed_cdft%results%S_minushalf) ! H'' * S^(-1/2)
1766 : ! Final orthogonal diabatic Hamiltonian matrix H
1767 580 : tmp_mat(:, :) = MATMUL(mixed_cdft%results%S_minushalf, tmp_mat) ! H = S^(-1/2) * H'' * S^(-1/2)
1768 40 : DO ipermutation = 1, npermutations
1769 20 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
1770 40 : coupling_lowdin(ipermutation) = tmp_mat(istate, jstate)
1771 : END DO
1772 20 : CALL mixed_cdft_result_type_set(mixed_cdft%results, lowdin=coupling_lowdin)
1773 20 : DEALLOCATE (coupling_lowdin)
1774 : END IF
1775 100 : DEALLOCATE (tmp_mat)
1776 100 : CALL timestop(handle)
1777 :
1778 200 : END SUBROUTINE mixed_cdft_calculate_coupling_low
1779 :
1780 : ! **************************************************************************************************
1781 : !> \brief Performs a configuration interaction calculation in the basis spanned by the CDFT states.
1782 : !> \param force_env the force_env that holds the CDFT states
1783 : !> \par History
1784 : !> 11.17 created [Nico Holmberg]
1785 : ! **************************************************************************************************
1786 100 : SUBROUTINE mixed_cdft_configuration_interaction(force_env)
1787 : TYPE(force_env_type), POINTER :: force_env
1788 :
1789 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_configuration_interaction'
1790 :
1791 : INTEGER :: handle, info, iounit, istate, ivar, &
1792 : nforce_eval, work_array_size
1793 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenv, work
1794 100 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: H_mat, H_mat_copy, S_mat, S_mat_copy
1795 : REAL(KIND=dp), EXTERNAL :: dnrm2
1796 : TYPE(cp_logger_type), POINTER :: logger
1797 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1798 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
1799 :
1800 : EXTERNAL :: dsygv
1801 :
1802 100 : NULLIFY (logger, force_env_section, print_section, mixed_cdft)
1803 :
1804 100 : CPASSERT(ASSOCIATED(force_env))
1805 100 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
1806 100 : CPASSERT(ASSOCIATED(mixed_cdft))
1807 :
1808 100 : IF (.NOT. mixed_cdft%do_ci) RETURN
1809 :
1810 20 : logger => cp_get_default_logger()
1811 20 : CALL timeset(routineN, handle)
1812 : CALL force_env_get(force_env=force_env, &
1813 20 : force_env_section=force_env_section)
1814 20 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1815 20 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
1816 :
1817 20 : CPASSERT(ALLOCATED(mixed_cdft%results%S))
1818 20 : CPASSERT(ALLOCATED(mixed_cdft%results%H))
1819 20 : nforce_eval = SIZE(mixed_cdft%results%S, 1)
1820 120 : ALLOCATE (S_mat(nforce_eval, nforce_eval), H_mat(nforce_eval, nforce_eval))
1821 60 : ALLOCATE (eigenv(nforce_eval))
1822 168 : S_mat(:, :) = mixed_cdft%results%S(:, :)
1823 168 : H_mat(:, :) = mixed_cdft%results%H(:, :)
1824 : ! Workspace query
1825 20 : ALLOCATE (work(1))
1826 20 : info = 0
1827 100 : ALLOCATE (H_mat_copy(nforce_eval, nforce_eval), S_mat_copy(nforce_eval, nforce_eval))
1828 168 : H_mat_copy(:, :) = H_mat(:, :) ! Need explicit copies because dsygv destroys original values
1829 168 : S_mat_copy(:, :) = S_mat(:, :)
1830 20 : CALL dsygv(1, 'V', 'U', nforce_eval, H_mat_copy, nforce_eval, S_mat_copy, nforce_eval, eigenv, work, -1, info)
1831 20 : work_array_size = NINT(work(1))
1832 20 : DEALLOCATE (H_mat_copy, S_mat_copy)
1833 : ! Allocate work array
1834 20 : DEALLOCATE (work)
1835 60 : ALLOCATE (work(work_array_size))
1836 20 : work = 0.0_dp
1837 : ! Solve Hc = eSc
1838 20 : info = 0
1839 20 : CALL dsygv(1, 'V', 'U', nforce_eval, H_mat, nforce_eval, S_mat, nforce_eval, eigenv, work, work_array_size, info)
1840 20 : IF (info /= 0) THEN
1841 0 : IF (info > nforce_eval) THEN
1842 0 : CPABORT("Matrix S is not positive definite")
1843 : ELSE
1844 0 : CPABORT("Diagonalization of H matrix failed.")
1845 : END IF
1846 : END IF
1847 : ! dsygv returns eigenvectors (stored in columns of H_mat) that are normalized to H^T * S * H = I
1848 : ! Renormalize eigenvectors to H^T * H = I
1849 64 : DO ivar = 1, nforce_eval
1850 168 : H_mat(:, ivar) = H_mat(:, ivar)/dnrm2(nforce_eval, H_mat(:, ivar), 1)
1851 : END DO
1852 20 : DEALLOCATE (work)
1853 20 : IF (iounit > 0) THEN
1854 10 : WRITE (iounit, '(/,T3,A)') '------------------ CDFT Configuration Interaction (CDFT-CI) ------------------'
1855 32 : DO ivar = 1, nforce_eval
1856 22 : IF (ivar == 1) THEN
1857 10 : WRITE (iounit, '(T3,A,T58,(3X,F20.14))') 'Ground state energy:', eigenv(ivar)
1858 : ELSE
1859 12 : WRITE (iounit, '(/,T3,A,I2,A,T58,(3X,F20.14))') 'Excited state (', ivar - 1, ' ) energy:', eigenv(ivar)
1860 : END IF
1861 58 : DO istate = 1, nforce_eval, 2
1862 48 : IF (istate == 1) THEN
1863 : WRITE (iounit, '(T3,A,T54,(3X,2F12.6))') &
1864 22 : 'Expansion coefficients:', H_mat(istate, ivar), H_mat(istate + 1, ivar)
1865 4 : ELSE IF (istate < nforce_eval) THEN
1866 4 : WRITE (iounit, '(T54,(3X,2F12.6))') H_mat(istate, ivar), H_mat(istate + 1, ivar)
1867 : ELSE
1868 0 : WRITE (iounit, '(T54,(3X,F12.6))') H_mat(istate, ivar)
1869 : END IF
1870 : END DO
1871 : END DO
1872 : WRITE (iounit, '(T3,A)') &
1873 10 : '------------------------------------------------------------------------------'
1874 : END IF
1875 20 : DEALLOCATE (S_mat, H_mat, eigenv)
1876 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
1877 20 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1878 20 : CALL timestop(handle)
1879 :
1880 20 : END SUBROUTINE mixed_cdft_configuration_interaction
1881 : ! **************************************************************************************************
1882 : !> \brief Block diagonalizes the mixed CDFT Hamiltonian matrix.
1883 : !> \param force_env the force_env that holds the CDFT states
1884 : !> \par History
1885 : !> 11.17 created [Nico Holmberg]
1886 : !> 01.18 added recursive diagonalization
1887 : !> split to subroutines [Nico Holmberg]
1888 : ! **************************************************************************************************
1889 100 : SUBROUTINE mixed_cdft_block_diag(force_env)
1890 : TYPE(force_env_type), POINTER :: force_env
1891 :
1892 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_block_diag'
1893 :
1894 : INTEGER :: handle, i, iounit, irecursion, j, n, &
1895 : nblk, nforce_eval, nrecursion
1896 : LOGICAL :: ignore_excited
1897 100 : TYPE(cp_1d_i_p_type), ALLOCATABLE, DIMENSION(:) :: blocks
1898 100 : TYPE(cp_1d_r_p_type), ALLOCATABLE, DIMENSION(:) :: eigenvalues
1899 100 : TYPE(cp_2d_r_p_type), ALLOCATABLE, DIMENSION(:) :: H_block, S_block
1900 : TYPE(cp_logger_type), POINTER :: logger
1901 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
1902 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
1903 :
1904 : EXTERNAL :: dsygv
1905 :
1906 100 : NULLIFY (logger, force_env_section, print_section, mixed_cdft)
1907 :
1908 100 : CPASSERT(ASSOCIATED(force_env))
1909 100 : CALL get_mixed_env(force_env%mixed_env, cdft_control=mixed_cdft)
1910 100 : CPASSERT(ASSOCIATED(mixed_cdft))
1911 :
1912 100 : IF (.NOT. mixed_cdft%block_diagonalize) RETURN
1913 :
1914 8 : logger => cp_get_default_logger()
1915 8 : CALL timeset(routineN, handle)
1916 :
1917 8 : CPASSERT(ALLOCATED(mixed_cdft%results%S))
1918 8 : CPASSERT(ALLOCATED(mixed_cdft%results%H))
1919 8 : nforce_eval = SIZE(mixed_cdft%results%S, 1)
1920 :
1921 : CALL force_env_get(force_env=force_env, &
1922 8 : force_env_section=force_env_section)
1923 8 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1924 8 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
1925 : ! Read block definitions from input
1926 8 : CALL mixed_cdft_read_block_diag(force_env, blocks, ignore_excited, nrecursion)
1927 8 : nblk = SIZE(blocks)
1928 : ! Start block diagonalization
1929 18 : DO irecursion = 1, nrecursion
1930 : ! Print block definitions
1931 10 : IF (iounit > 0 .AND. irecursion == 1) THEN
1932 4 : WRITE (iounit, '(/,T3,A)') '-------------------------- CDFT BLOCK DIAGONALIZATION ------------------------'
1933 4 : WRITE (iounit, '(T3,A)') 'Block diagonalizing the mixed CDFT Hamiltonian'
1934 4 : WRITE (iounit, '(T3,A,I3)') 'Number of blocks:', nblk
1935 4 : WRITE (iounit, '(T3,A,L3)') 'Ignoring excited states within blocks:', ignore_excited
1936 4 : WRITE (iounit, '(/,T3,A)') 'List of CDFT states for each block'
1937 14 : DO i = 1, nblk
1938 33 : WRITE (iounit, '(T6,A,I3,A,6I3)') 'Block', i, ':', (blocks(i)%array(j), j=1, SIZE(blocks(i)%array))
1939 : END DO
1940 : END IF
1941 : ! Recursive diagonalization: update counters and references
1942 10 : IF (irecursion > 1) THEN
1943 2 : nblk = nblk/2
1944 10 : ALLOCATE (blocks(nblk))
1945 2 : j = 1
1946 6 : DO i = 1, nblk
1947 4 : NULLIFY (blocks(i)%array)
1948 4 : ALLOCATE (blocks(i)%array(2))
1949 12 : blocks(i)%array = [j, j + 1]
1950 6 : j = j + 2
1951 : END DO
1952 : ! Print info
1953 2 : IF (iounit > 0) THEN
1954 1 : WRITE (iounit, '(/, T3,A)') 'Recursive block diagonalization of the mixed CDFT Hamiltonian'
1955 1 : WRITE (iounit, '(T6,A)') 'Block diagonalization is continued until only two matrix blocks remain.'
1956 1 : WRITE (iounit, '(T6,A)') 'The new blocks are formed by collecting pairs of blocks from the previous'
1957 1 : WRITE (iounit, '(T6,A)') 'block diagonalized matrix in ascending order.'
1958 1 : WRITE (iounit, '(/,T3,A,I3,A,I3)') 'Recursion step:', irecursion - 1, ' of ', nrecursion - 1
1959 1 : WRITE (iounit, '(/,T3,A)') 'List of old block indices for each new block'
1960 3 : DO i = 1, nblk
1961 7 : WRITE (iounit, '(T6,A,I3,A,6I3)') 'Block', i, ':', (blocks(i)%array(j), j=1, SIZE(blocks(i)%array))
1962 : END DO
1963 : END IF
1964 : END IF
1965 : ! Get the Hamiltonian and overlap matrices of each block
1966 10 : CALL mixed_cdft_get_blocks(mixed_cdft, blocks, H_block, S_block)
1967 : ! Diagonalize blocks
1968 10 : CALL mixed_cdft_diagonalize_blocks(blocks, H_block, S_block, eigenvalues)
1969 : ! Assemble the block diagonalized matrices
1970 10 : IF (ignore_excited) THEN
1971 8 : n = nblk
1972 : ELSE
1973 2 : n = nforce_eval
1974 : END IF
1975 10 : CALL mixed_cdft_assemble_block_diag(mixed_cdft, blocks, H_block, eigenvalues, n, iounit)
1976 : ! Deallocate work
1977 34 : DO i = 1, nblk
1978 24 : DEALLOCATE (H_block(i)%array)
1979 24 : DEALLOCATE (S_block(i)%array)
1980 24 : DEALLOCATE (eigenvalues(i)%array)
1981 34 : DEALLOCATE (blocks(i)%array)
1982 : END DO
1983 18 : DEALLOCATE (H_block, S_block, eigenvalues, blocks)
1984 : END DO ! recursion
1985 8 : IF (iounit > 0) THEN
1986 : WRITE (iounit, '(T3,A)') &
1987 4 : '------------------------------------------------------------------------------'
1988 : END IF
1989 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
1990 8 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
1991 8 : CALL timestop(handle)
1992 :
1993 100 : END SUBROUTINE mixed_cdft_block_diag
1994 : ! **************************************************************************************************
1995 : !> \brief Routine to calculate the CDFT electronic coupling reliability metric
1996 : !> \param force_env the force_env that holds the CDFT states
1997 : !> \param mixed_cdft the mixed_cdft env
1998 : !> \param density_matrix_diff array holding difference density matrices (P_j - P_i) for every CDFT
1999 : !> state permutation
2000 : !> \param ncol_mo the number of MOs per spin
2001 : !> \par History
2002 : !> 11.17 created [Nico Holmberg]
2003 : ! **************************************************************************************************
2004 14 : SUBROUTINE mixed_cdft_calculate_metric(force_env, mixed_cdft, density_matrix_diff, ncol_mo)
2005 : TYPE(force_env_type), POINTER :: force_env
2006 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
2007 : TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: density_matrix_diff
2008 : INTEGER, DIMENSION(:) :: ncol_mo
2009 :
2010 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_calculate_metric'
2011 :
2012 : INTEGER :: handle, ipermutation, ispin, j, &
2013 : nforce_eval, npermutations, nspins
2014 14 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: evals
2015 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: metric
2016 : TYPE(dbcsr_type) :: e_vectors
2017 :
2018 14 : CALL timeset(routineN, handle)
2019 14 : nforce_eval = SIZE(mixed_cdft%results%H, 1)
2020 14 : npermutations = nforce_eval*(nforce_eval - 1)/2
2021 14 : nspins = SIZE(density_matrix_diff, 2)
2022 56 : ALLOCATE (metric(npermutations, nspins))
2023 14 : metric = 0.0_dp
2024 14 : CALL dbcsr_create(e_vectors, template=density_matrix_diff(1, 1)%matrix)
2025 42 : DO ispin = 1, nspins
2026 84 : ALLOCATE (evals(ncol_mo(ispin)))
2027 64 : DO ipermutation = 1, npermutations
2028 : ! Take into account doubly occupied orbitals without LSD
2029 36 : IF (nspins == 1) THEN
2030 0 : CALL dbcsr_scale(density_matrix_diff(ipermutation, 1)%matrix, alpha_scalar=0.5_dp)
2031 : END IF
2032 : ! Diagonalize difference density matrix
2033 : CALL cp_dbcsr_syevd(density_matrix_diff(ipermutation, ispin)%matrix, e_vectors, evals, &
2034 36 : para_env=force_env%para_env, blacs_env=mixed_cdft%blacs_env)
2035 36 : CALL dbcsr_release_p(density_matrix_diff(ipermutation, ispin)%matrix)
2036 100 : DO j = 1, ncol_mo(ispin)
2037 72 : metric(ipermutation, ispin) = metric(ipermutation, ispin) + (evals(j)**2 - evals(j)**4)
2038 : END DO
2039 : END DO
2040 42 : DEALLOCATE (evals)
2041 : END DO
2042 14 : CALL dbcsr_release(e_vectors)
2043 14 : DEALLOCATE (density_matrix_diff)
2044 78 : metric(:, :) = metric(:, :)/4.0_dp
2045 14 : CALL mixed_cdft_result_type_set(mixed_cdft%results, metric=metric)
2046 14 : DEALLOCATE (metric)
2047 14 : CALL timestop(handle)
2048 :
2049 28 : END SUBROUTINE mixed_cdft_calculate_metric
2050 :
2051 : ! **************************************************************************************************
2052 : !> \brief Routine to calculate the electronic coupling according to the wavefunction overlap method
2053 : !> \param force_env the force_env that holds the CDFT states
2054 : !> \param mixed_cdft the mixed_cdft env
2055 : !> \param ncol_mo the number of MOs per spin
2056 : !> \param nrow_mo the number of AOs per spin
2057 : !> \par History
2058 : !> 11.17 created [Nico Holmberg]
2059 : ! **************************************************************************************************
2060 8 : SUBROUTINE mixed_cdft_wfn_overlap_method(force_env, mixed_cdft, ncol_mo, nrow_mo)
2061 : TYPE(force_env_type), POINTER :: force_env
2062 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
2063 : INTEGER, DIMENSION(:) :: ncol_mo, nrow_mo
2064 :
2065 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_cdft_wfn_overlap_method'
2066 :
2067 : CHARACTER(LEN=default_path_length) :: file_name
2068 : INTEGER :: handle, ipermutation, ispin, istate, &
2069 : jstate, nao, nforce_eval, nmo, &
2070 : npermutations, nspins
2071 : LOGICAL :: exist, natom_mismatch
2072 : REAL(KIND=dp) :: energy_diff, maxocc, Sda
2073 8 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coupling_wfn
2074 8 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: overlaps
2075 8 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2076 : TYPE(cp_fm_struct_type), POINTER :: mo_mo_fmstruct
2077 : TYPE(cp_fm_type) :: inverse_mat, mo_overlap_wfn, mo_tmp
2078 8 : TYPE(cp_fm_type), DIMENSION(:, :), POINTER :: mixed_mo_coeff
2079 : TYPE(cp_logger_type), POINTER :: logger
2080 : TYPE(cp_subsys_type), POINTER :: subsys_mix
2081 : TYPE(dbcsr_type), POINTER :: mixed_matrix_s
2082 8 : TYPE(mo_set_type), ALLOCATABLE, DIMENSION(:) :: mo_set
2083 8 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2084 8 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2085 : TYPE(section_vals_type), POINTER :: force_env_section, mixed_cdft_section
2086 :
2087 8 : NULLIFY (mixed_cdft_section, subsys_mix, particle_set, qs_kind_set, atomic_kind_set, &
2088 8 : mixed_mo_coeff, mixed_matrix_s, force_env_section)
2089 16 : logger => cp_get_default_logger()
2090 :
2091 8 : CALL timeset(routineN, handle)
2092 8 : nforce_eval = SIZE(mixed_cdft%results%H, 1)
2093 8 : npermutations = nforce_eval*(nforce_eval - 1)/2
2094 8 : nspins = SIZE(nrow_mo)
2095 8 : mixed_mo_coeff => mixed_cdft%matrix%mixed_mo_coeff
2096 8 : mixed_matrix_s => mixed_cdft%matrix%mixed_matrix_s
2097 : CALL force_env_get(force_env=force_env, &
2098 8 : force_env_section=force_env_section)
2099 : ! Create mo_set for input wfn
2100 40 : ALLOCATE (mo_set(nspins))
2101 8 : IF (nspins == 2) THEN
2102 8 : maxocc = 1.0_dp
2103 : ELSE
2104 0 : maxocc = 2.0_dp
2105 : END IF
2106 24 : DO ispin = 1, nspins
2107 16 : nao = nrow_mo(ispin)
2108 16 : nmo = ncol_mo(ispin)
2109 : ! Only OT with fully occupied orbitals is implicitly supported
2110 : CALL allocate_mo_set(mo_set(ispin), nao=nao, nmo=nmo, nelectron=INT(maxocc*nmo), &
2111 : n_el_f=REAL(maxocc*nmo, dp), maxocc=maxocc, &
2112 16 : flexible_electron_count=0.0_dp)
2113 16 : CALL set_mo_set(mo_set(ispin), uniform_occupation=.TRUE., homo=nmo)
2114 16 : ALLOCATE (mo_set(ispin)%mo_coeff)
2115 : CALL cp_fm_create(matrix=mo_set(ispin)%mo_coeff, &
2116 : matrix_struct=mixed_mo_coeff(1, ispin)%matrix_struct, &
2117 16 : name="GS_MO_COEFF"//TRIM(ADJUSTL(cp_to_string(ispin)))//"MATRIX")
2118 48 : ALLOCATE (mo_set(ispin)%eigenvalues(nmo))
2119 40 : ALLOCATE (mo_set(ispin)%occupation_numbers(nmo))
2120 : END DO
2121 : ! Read wfn file (note we assume that the basis set is the same)
2122 8 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
2123 : ! This really shouldnt be a problem?
2124 : CALL cp_abort(__LOCATION__, &
2125 0 : "QMMM + wavefunction overlap method not supported.")
2126 : END IF
2127 8 : CALL force_env_get(force_env=force_env, subsys=subsys_mix)
2128 8 : mixed_cdft_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT")
2129 8 : CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set, particle_set=particle_set)
2130 8 : CPASSERT(ASSOCIATED(mixed_cdft%qs_kind_set))
2131 8 : IF (force_env%para_env%is_source()) THEN
2132 4 : CALL wfn_restart_file_name(file_name, exist, mixed_cdft_section, logger)
2133 : END IF
2134 8 : CALL force_env%para_env%bcast(exist)
2135 8 : CALL force_env%para_env%bcast(file_name)
2136 8 : IF (.NOT. exist) THEN
2137 : CALL cp_abort(__LOCATION__, &
2138 : "User requested to restart the wavefunction from the file named: "// &
2139 : TRIM(file_name)//". This file does not exist. Please check the existence of"// &
2140 : " the file or change properly the value of the keyword WFN_RESTART_FILE_NAME in"// &
2141 0 : " section FORCE_EVAL\MIXED\MIXED_CDFT.")
2142 : END IF
2143 : CALL read_mo_set_from_restart(mo_array=mo_set, qs_kind_set=mixed_cdft%qs_kind_set, particle_set=particle_set, &
2144 : para_env=force_env%para_env, id_nr=0, multiplicity=mixed_cdft%multiplicity, &
2145 : dft_section=mixed_cdft_section, natom_mismatch=natom_mismatch, &
2146 8 : cdft=.TRUE.)
2147 8 : IF (natom_mismatch) THEN
2148 : CALL cp_abort(__LOCATION__, &
2149 0 : "Restart wfn file has a wrong number of atoms")
2150 : END IF
2151 : ! Orthonormalize wfn
2152 24 : DO ispin = 1, nspins
2153 24 : IF (mixed_cdft%has_unit_metric) THEN
2154 0 : CALL make_basis_simple(mo_set(ispin)%mo_coeff, ncol_mo(ispin))
2155 : ELSE
2156 16 : CALL make_basis_sm(mo_set(ispin)%mo_coeff, ncol_mo(ispin), mixed_matrix_s)
2157 : END IF
2158 : END DO
2159 : ! Calculate MO overlaps between reference state (R) and CDFT state pairs I/J
2160 24 : ALLOCATE (coupling_wfn(npermutations))
2161 32 : ALLOCATE (overlaps(2, npermutations, nspins))
2162 8 : overlaps = 0.0_dp
2163 24 : DO ispin = 1, nspins
2164 : ! Allocate work
2165 16 : nao = nrow_mo(ispin)
2166 16 : nmo = ncol_mo(ispin)
2167 : CALL cp_fm_struct_create(mo_mo_fmstruct, nrow_global=nmo, ncol_global=nmo, &
2168 16 : context=mixed_cdft%blacs_env, para_env=force_env%para_env)
2169 : CALL cp_fm_create(matrix=mo_overlap_wfn, matrix_struct=mo_mo_fmstruct, &
2170 16 : name="MO_OVERLAP_MATRIX_WFN")
2171 : CALL cp_fm_create(matrix=inverse_mat, matrix_struct=mo_mo_fmstruct, &
2172 16 : name="INVERSE_MO_OVERLAP_MATRIX_WFN")
2173 16 : CALL cp_fm_struct_release(mo_mo_fmstruct)
2174 : CALL cp_fm_create(matrix=mo_tmp, &
2175 : matrix_struct=mixed_mo_coeff(1, ispin)%matrix_struct, &
2176 16 : name="OVERLAP_MO_COEFF_WFN")
2177 40 : DO ipermutation = 1, npermutations
2178 24 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
2179 : ! S*C_r
2180 : CALL cp_dbcsr_sm_fm_multiply(mixed_matrix_s, mo_set(ispin)%mo_coeff, &
2181 24 : mo_tmp, nmo, 1.0_dp, 0.0_dp)
2182 : ! C_i^T * (S*C_r)
2183 24 : CALL cp_fm_set_all(mo_overlap_wfn, alpha=0.0_dp)
2184 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
2185 : mixed_mo_coeff(istate, ispin), &
2186 24 : mo_tmp, 0.0_dp, mo_overlap_wfn)
2187 24 : CALL cp_fm_invert(mo_overlap_wfn, inverse_mat, overlaps(1, ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
2188 : ! C_j^T * (S*C_r)
2189 24 : CALL cp_fm_set_all(mo_overlap_wfn, alpha=0.0_dp)
2190 : CALL parallel_gemm('T', 'N', nmo, nmo, nao, 1.0_dp, &
2191 : mixed_mo_coeff(jstate, ispin), &
2192 24 : mo_tmp, 0.0_dp, mo_overlap_wfn)
2193 64 : CALL cp_fm_invert(mo_overlap_wfn, inverse_mat, overlaps(2, ipermutation, ispin), eps_svd=mixed_cdft%eps_svd)
2194 : END DO
2195 16 : CALL cp_fm_release(mo_overlap_wfn)
2196 16 : CALL cp_fm_release(inverse_mat)
2197 16 : CALL cp_fm_release(mo_tmp)
2198 56 : CALL deallocate_mo_set(mo_set(ispin))
2199 : END DO
2200 8 : DEALLOCATE (mo_set)
2201 20 : DO ipermutation = 1, npermutations
2202 12 : CALL map_permutation_to_states(nforce_eval, ipermutation, istate, jstate)
2203 12 : IF (nspins == 2) THEN
2204 12 : overlaps(1, ipermutation, 1) = ABS(overlaps(1, ipermutation, 1)*overlaps(1, ipermutation, 2)) ! A in eq. 12c
2205 12 : overlaps(2, ipermutation, 1) = ABS(overlaps(2, ipermutation, 1)*overlaps(2, ipermutation, 2)) ! B in eq. 12c
2206 : ELSE
2207 0 : overlaps(1, ipermutation, 1) = overlaps(1, ipermutation, 1)**2
2208 0 : overlaps(2, ipermutation, 1) = overlaps(2, ipermutation, 1)**2
2209 : END IF
2210 : ! Calculate coupling using eq. 12c
2211 : ! The coupling is singular if A = B (i.e. states I/J are identical or charge in ground state is fully delocalized)
2212 32 : IF (ABS(overlaps(1, ipermutation, 1) - overlaps(2, ipermutation, 1)) <= 1.0e-14_dp) THEN
2213 : CALL cp_warn(__LOCATION__, &
2214 : "Coupling between states is singular and set to zero. "// &
2215 : "Potential causes: coupling is computed between identical CDFT states or the spin/charge "// &
2216 2 : "density is fully delocalized in the unconstrained ground state.")
2217 2 : coupling_wfn(ipermutation) = 0.0_dp
2218 : ELSE
2219 10 : energy_diff = mixed_cdft%results%energy(jstate) - mixed_cdft%results%energy(istate)
2220 10 : Sda = mixed_cdft%results%S(istate, jstate)
2221 : coupling_wfn(ipermutation) = ABS((overlaps(1, ipermutation, 1)*overlaps(2, ipermutation, 1)/ &
2222 : (overlaps(1, ipermutation, 1)**2 - overlaps(2, ipermutation, 1)**2))* &
2223 : (energy_diff)/(1.0_dp - Sda**2)* &
2224 : (1.0_dp - (overlaps(1, ipermutation, 1)**2 + overlaps(2, ipermutation, 1)**2)/ &
2225 : (2.0_dp*overlaps(1, ipermutation, 1)*overlaps(2, ipermutation, 1))* &
2226 10 : Sda))
2227 : END IF
2228 : END DO
2229 8 : DEALLOCATE (overlaps)
2230 8 : CALL mixed_cdft_result_type_set(mixed_cdft%results, wfn=coupling_wfn)
2231 8 : DEALLOCATE (coupling_wfn)
2232 8 : CALL timestop(handle)
2233 :
2234 16 : END SUBROUTINE mixed_cdft_wfn_overlap_method
2235 :
2236 : ! **************************************************************************************************
2237 : !> \brief Becke constraint adapted to mixed calculations, details in qs_cdft_methods.F
2238 : !> \param force_env the force_env that holds the CDFT states
2239 : !> \param calculate_forces determines if forces should be calculted
2240 : !> \par History
2241 : !> 02.2016 created [Nico Holmberg]
2242 : !> 03.2016 added dynamic load balancing (dlb)
2243 : !> changed pw_p_type data types to rank-3 reals to accommodate dlb
2244 : !> and to reduce overall memory footprint
2245 : !> split to subroutines [Nico Holmberg]
2246 : !> 04.2016 introduced mixed grid mapping [Nico Holmberg]
2247 : ! **************************************************************************************************
2248 36 : SUBROUTINE mixed_becke_constraint(force_env, calculate_forces)
2249 : TYPE(force_env_type), POINTER :: force_env
2250 : LOGICAL, INTENT(IN) :: calculate_forces
2251 :
2252 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint'
2253 :
2254 : INTEGER :: handle
2255 36 : INTEGER, ALLOCATABLE, DIMENSION(:) :: catom
2256 : LOGICAL :: in_memory, store_vectors
2257 36 : LOGICAL, ALLOCATABLE, DIMENSION(:) :: is_constraint
2258 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: coefficients
2259 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: position_vecs, R12
2260 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: pair_dist_vecs
2261 : TYPE(cp_logger_type), POINTER :: logger
2262 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
2263 : TYPE(mixed_environment_type), POINTER :: mixed_env
2264 :
2265 36 : NULLIFY (mixed_env, mixed_cdft)
2266 36 : store_vectors = .TRUE.
2267 36 : logger => cp_get_default_logger()
2268 36 : CALL timeset(routineN, handle)
2269 36 : mixed_env => force_env%mixed_env
2270 36 : CALL get_mixed_env(mixed_env, cdft_control=mixed_cdft)
2271 : CALL mixed_becke_constraint_init(force_env, mixed_cdft, calculate_forces, &
2272 : is_constraint, in_memory, store_vectors, &
2273 : R12, position_vecs, pair_dist_vecs, &
2274 36 : coefficients, catom)
2275 : CALL mixed_becke_constraint_low(force_env, mixed_cdft, in_memory, &
2276 : is_constraint, store_vectors, R12, &
2277 : position_vecs, pair_dist_vecs, &
2278 36 : coefficients, catom)
2279 36 : CALL timestop(handle)
2280 :
2281 36 : END SUBROUTINE mixed_becke_constraint
2282 : ! **************************************************************************************************
2283 : !> \brief Initialize the mixed Becke constraint calculation
2284 : !> \param force_env the force_env that holds the CDFT states
2285 : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
2286 : !> \param calculate_forces determines if forces should be calculted
2287 : !> \param is_constraint a list used to determine which atoms in the system define the constraint
2288 : !> \param in_memory decides whether to build the weight function gradients in parallel before solving
2289 : !> the CDFT states or later during the SCF procedure of the individual states
2290 : !> \param store_vectors should temporary arrays be stored in memory to accelerate the calculation
2291 : !> \param R12 temporary array holding the pairwise atomic distances
2292 : !> \param position_vecs temporary array holding the pbc corrected atomic position vectors
2293 : !> \param pair_dist_vecs temporary array holding the pairwise displament vectors
2294 : !> \param coefficients array that determines how atoms should be summed to form the constraint
2295 : !> \param catom temporary array to map the global index of constraint atoms to their position
2296 : !> in a list that holds only constraint atoms
2297 : !> \par History
2298 : !> 03.2016 created [Nico Holmberg]
2299 : ! **************************************************************************************************
2300 36 : SUBROUTINE mixed_becke_constraint_init(force_env, mixed_cdft, calculate_forces, &
2301 : is_constraint, in_memory, store_vectors, &
2302 : R12, position_vecs, pair_dist_vecs, coefficients, &
2303 : catom)
2304 : TYPE(force_env_type), POINTER :: force_env
2305 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
2306 : LOGICAL, INTENT(IN) :: calculate_forces
2307 : LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(OUT) :: is_constraint
2308 : LOGICAL, INTENT(OUT) :: in_memory
2309 : LOGICAL, INTENT(IN) :: store_vectors
2310 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
2311 : INTENT(out) :: R12, position_vecs
2312 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
2313 : INTENT(out) :: pair_dist_vecs
2314 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:), &
2315 : INTENT(OUT) :: coefficients
2316 : INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(out) :: catom
2317 :
2318 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_init'
2319 :
2320 : CHARACTER(len=2) :: element_symbol
2321 : INTEGER :: atom_a, bounds(2), handle, i, iatom, iex, iforce_eval, ikind, iounit, ithread, j, &
2322 : jatom, katom, my_work, my_work_size, natom, nforce_eval, nkind, np(3), npme, nthread, &
2323 : numexp, offset_dlb, unit_nr
2324 : INTEGER, DIMENSION(2, 3) :: bo, bo_conf
2325 36 : INTEGER, DIMENSION(:), POINTER :: atom_list, cores, stride
2326 : LOGICAL :: build, mpi_io
2327 : REAL(kind=dp) :: alpha, chi, coef, ircov, jrcov, ra(3), &
2328 : radius, uij
2329 : REAL(kind=dp), DIMENSION(3) :: cell_v, dist_vec, dr, r, r1, shift
2330 36 : REAL(KIND=dp), DIMENSION(:), POINTER :: radii_list
2331 36 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: pab
2332 36 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
2333 : TYPE(cdft_control_type), POINTER :: cdft_control
2334 : TYPE(cell_type), POINTER :: cell
2335 : TYPE(cp_logger_type), POINTER :: logger
2336 : TYPE(cp_subsys_type), POINTER :: subsys_mix
2337 : TYPE(force_env_type), POINTER :: force_env_qs
2338 : TYPE(hirshfeld_type), POINTER :: cavity_env
2339 : TYPE(particle_list_type), POINTER :: particles
2340 36 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
2341 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
2342 36 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
2343 : TYPE(realspace_grid_type), POINTER :: rs_cavity
2344 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
2345 :
2346 36 : NULLIFY (pab, cell, force_env_qs, particle_set, force_env_section, print_section, &
2347 36 : qs_kind_set, particles, subsys_mix, rs_cavity, cavity_env, auxbas_pw_pool, &
2348 36 : atomic_kind_set, radii_list, cdft_control)
2349 72 : logger => cp_get_default_logger()
2350 36 : nforce_eval = SIZE(force_env%sub_force_env)
2351 36 : CALL timeset(routineN, handle)
2352 36 : CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
2353 36 : IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
2354 : CALL force_env_get(force_env=force_env, &
2355 : subsys=subsys_mix, &
2356 28 : cell=cell)
2357 : CALL cp_subsys_get(subsys=subsys_mix, &
2358 : particles=particles, &
2359 28 : particle_set=particle_set)
2360 : ELSE
2361 24 : DO iforce_eval = 1, nforce_eval
2362 16 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
2363 24 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
2364 : END DO
2365 : CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
2366 : cp_subsys=subsys_mix, &
2367 8 : cell=cell)
2368 : CALL cp_subsys_get(subsys=subsys_mix, &
2369 : particles=particles, &
2370 8 : particle_set=particle_set)
2371 : END IF
2372 36 : natom = SIZE(particles%els)
2373 36 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
2374 36 : cdft_control => mixed_cdft%cdft_control
2375 36 : CPASSERT(ASSOCIATED(cdft_control))
2376 36 : IF (.NOT. ASSOCIATED(cdft_control%becke_control%cutoffs)) THEN
2377 24 : CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
2378 72 : ALLOCATE (cdft_control%becke_control%cutoffs(natom))
2379 30 : SELECT CASE (cdft_control%becke_control%cutoff_type)
2380 : CASE (becke_cutoff_global)
2381 18 : cdft_control%becke_control%cutoffs(:) = cdft_control%becke_control%rglobal
2382 : CASE (becke_cutoff_element)
2383 18 : IF (.NOT. SIZE(atomic_kind_set) == SIZE(cdft_control%becke_control%cutoffs_tmp)) THEN
2384 : CALL cp_abort(__LOCATION__, &
2385 : "Size of keyword BECKE_CONSTRAINT\ELEMENT_CUTOFFS does "// &
2386 0 : "not match number of atomic kinds in the input coordinate file.")
2387 : END IF
2388 54 : DO ikind = 1, SIZE(atomic_kind_set)
2389 36 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=katom, atom_list=atom_list)
2390 90 : DO iatom = 1, katom
2391 36 : atom_a = atom_list(iatom)
2392 72 : cdft_control%becke_control%cutoffs(atom_a) = cdft_control%becke_control%cutoffs_tmp(ikind)
2393 : END DO
2394 : END DO
2395 42 : DEALLOCATE (cdft_control%becke_control%cutoffs_tmp)
2396 : END SELECT
2397 : END IF
2398 36 : build = .FALSE.
2399 36 : IF (cdft_control%becke_control%adjust .AND. &
2400 : .NOT. ASSOCIATED(cdft_control%becke_control%aij)) THEN
2401 72 : ALLOCATE (cdft_control%becke_control%aij(natom, natom))
2402 18 : build = .TRUE.
2403 : END IF
2404 108 : ALLOCATE (catom(cdft_control%natoms))
2405 : IF (cdft_control%save_pot .OR. &
2406 : cdft_control%becke_control%cavity_confine .OR. &
2407 36 : cdft_control%becke_control%should_skip .OR. &
2408 : mixed_cdft%first_iteration) THEN
2409 108 : ALLOCATE (is_constraint(natom))
2410 36 : is_constraint = .FALSE.
2411 : END IF
2412 36 : in_memory = calculate_forces .AND. cdft_control%becke_control%in_memory
2413 36 : IF (in_memory .NEQV. calculate_forces) THEN
2414 : CALL cp_abort(__LOCATION__, &
2415 : "The flag BECKE_CONSTRAINT\IN_MEMORY must be activated "// &
2416 0 : "for the calculation of mixed CDFT forces")
2417 : END IF
2418 108 : IF (in_memory .OR. mixed_cdft%first_iteration) ALLOCATE (coefficients(natom))
2419 108 : DO i = 1, cdft_control%natoms
2420 72 : catom(i) = cdft_control%atoms(i)
2421 : IF (cdft_control%save_pot .OR. &
2422 : cdft_control%becke_control%cavity_confine .OR. &
2423 72 : cdft_control%becke_control%should_skip .OR. &
2424 : mixed_cdft%first_iteration) THEN
2425 72 : is_constraint(catom(i)) = .TRUE.
2426 : END IF
2427 108 : IF (in_memory .OR. mixed_cdft%first_iteration) THEN
2428 72 : coefficients(catom(i)) = cdft_control%group(1)%coeff(i)
2429 : END IF
2430 : END DO
2431 36 : CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=auxbas_pw_pool)
2432 360 : bo = auxbas_pw_pool%pw_grid%bounds_local
2433 144 : np = auxbas_pw_pool%pw_grid%npts
2434 144 : dr = auxbas_pw_pool%pw_grid%dr
2435 144 : shift = -REAL(MODULO(np, 2), dp)*dr/2.0_dp
2436 36 : IF (store_vectors) THEN
2437 108 : IF (in_memory) ALLOCATE (pair_dist_vecs(3, natom, natom))
2438 108 : ALLOCATE (position_vecs(3, natom))
2439 : END IF
2440 144 : DO i = 1, 3
2441 144 : cell_v(i) = cell%hmat(i, i)
2442 : END DO
2443 144 : ALLOCATE (R12(natom, natom))
2444 72 : DO iatom = 1, natom - 1
2445 108 : DO jatom = iatom + 1, natom
2446 144 : r = particle_set(iatom)%r
2447 144 : r1 = particle_set(jatom)%r
2448 144 : DO i = 1, 3
2449 108 : r(i) = MODULO(r(i), cell%hmat(i, i)) - cell%hmat(i, i)/2._dp
2450 144 : r1(i) = MODULO(r1(i), cell%hmat(i, i)) - cell%hmat(i, i)/2._dp
2451 : END DO
2452 144 : dist_vec = (r - r1) - ANINT((r - r1)/cell_v)*cell_v
2453 36 : IF (store_vectors) THEN
2454 144 : position_vecs(:, iatom) = r(:)
2455 144 : IF (iatom == 1 .AND. jatom == natom) position_vecs(:, jatom) = r1(:)
2456 36 : IF (in_memory) THEN
2457 96 : pair_dist_vecs(:, iatom, jatom) = dist_vec(:)
2458 96 : pair_dist_vecs(:, jatom, iatom) = -dist_vec(:)
2459 : END IF
2460 : END IF
2461 144 : R12(iatom, jatom) = NORM2(dist_vec)
2462 36 : R12(jatom, iatom) = R12(iatom, jatom)
2463 72 : IF (build) THEN
2464 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2465 18 : kind_number=ikind)
2466 18 : ircov = cdft_control%becke_control%radii(ikind)
2467 : CALL get_atomic_kind(atomic_kind=particle_set(jatom)%atomic_kind, &
2468 18 : kind_number=ikind)
2469 18 : jrcov = cdft_control%becke_control%radii(ikind)
2470 18 : IF (ircov /= jrcov) THEN
2471 18 : chi = ircov/jrcov
2472 18 : uij = (chi - 1.0_dp)/(chi + 1.0_dp)
2473 18 : cdft_control%becke_control%aij(iatom, jatom) = uij/(uij**2 - 1.0_dp)
2474 18 : IF (cdft_control%becke_control%aij(iatom, jatom) &
2475 : > 0.5_dp) THEN
2476 0 : cdft_control%becke_control%aij(iatom, jatom) = 0.5_dp
2477 18 : ELSE IF (cdft_control%becke_control%aij(iatom, jatom) &
2478 : < -0.5_dp) THEN
2479 0 : cdft_control%becke_control%aij(iatom, jatom) = -0.5_dp
2480 : END IF
2481 : ELSE
2482 0 : cdft_control%becke_control%aij(iatom, jatom) = 0.0_dp
2483 : END IF
2484 : cdft_control%becke_control%aij(jatom, iatom) = &
2485 18 : -cdft_control%becke_control%aij(iatom, jatom)
2486 : END IF
2487 : END DO
2488 : END DO
2489 : ! Dump some additional information about the calculation
2490 36 : IF (mixed_cdft%first_iteration) THEN
2491 24 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
2492 24 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
2493 24 : IF (iounit > 0) THEN
2494 : WRITE (iounit, '(/,T3,A,T66)') &
2495 12 : '-------------------------- Becke atomic parameters ---------------------------'
2496 12 : IF (cdft_control%becke_control%adjust) THEN
2497 : WRITE (iounit, '(T3,A,A)') &
2498 9 : 'Atom Element Coefficient', ' Cutoff (angstrom) CDFT Radius (angstrom)'
2499 27 : DO iatom = 1, natom
2500 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2501 : element_symbol=element_symbol, &
2502 18 : kind_number=ikind)
2503 18 : ircov = cp_unit_from_cp2k(cdft_control%becke_control%radii(ikind), "angstrom")
2504 18 : IF (is_constraint(iatom)) THEN
2505 18 : coef = coefficients(iatom)
2506 : ELSE
2507 0 : coef = 0.0_dp
2508 : END IF
2509 : WRITE (iounit, "(i6,T14,A2,T22,F8.3,T44,F8.3,T73,F8.3)") &
2510 18 : iatom, ADJUSTR(element_symbol), coef, &
2511 18 : cp_unit_from_cp2k(cdft_control%becke_control%cutoffs(iatom), "angstrom"), &
2512 63 : ircov
2513 : END DO
2514 : ELSE
2515 : WRITE (iounit, '(T3,A,A)') &
2516 3 : 'Atom Element Coefficient', ' Cutoff (angstrom)'
2517 9 : DO iatom = 1, natom
2518 : CALL get_atomic_kind(atomic_kind=particle_set(iatom)%atomic_kind, &
2519 6 : element_symbol=element_symbol)
2520 6 : IF (is_constraint(iatom)) THEN
2521 6 : coef = coefficients(iatom)
2522 : ELSE
2523 0 : coef = 0.0_dp
2524 : END IF
2525 : WRITE (iounit, "(i6,T14,A2,T22,F8.3,T44,F8.3)") &
2526 6 : iatom, ADJUSTR(element_symbol), coef, &
2527 15 : cp_unit_from_cp2k(cdft_control%becke_control%cutoffs(iatom), "angstrom")
2528 : END DO
2529 : END IF
2530 : WRITE (iounit, '(T3,A)') &
2531 12 : '------------------------------------------------------------------------------'
2532 : END IF
2533 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
2534 24 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
2535 24 : mixed_cdft%first_iteration = .FALSE.
2536 : END IF
2537 :
2538 36 : IF (cdft_control%becke_control%cavity_confine) THEN
2539 34 : CPASSERT(ASSOCIATED(mixed_cdft%qs_kind_set))
2540 34 : cavity_env => cdft_control%becke_control%cavity_env
2541 34 : qs_kind_set => mixed_cdft%qs_kind_set
2542 34 : CALL cp_subsys_get(subsys_mix, atomic_kind_set=atomic_kind_set)
2543 34 : nkind = SIZE(qs_kind_set)
2544 34 : IF (.NOT. ASSOCIATED(cavity_env%kind_shape_fn)) THEN
2545 22 : IF (ASSOCIATED(cdft_control%becke_control%radii)) THEN
2546 54 : ALLOCATE (radii_list(SIZE(cdft_control%becke_control%radii)))
2547 54 : DO ikind = 1, SIZE(cdft_control%becke_control%radii)
2548 54 : IF (cavity_env%use_bohr) THEN
2549 0 : radii_list(ikind) = cdft_control%becke_control%radii(ikind)
2550 : ELSE
2551 36 : radii_list(ikind) = cp_unit_from_cp2k(cdft_control%becke_control%radii(ikind), "angstrom")
2552 : END IF
2553 : END DO
2554 : END IF
2555 : CALL create_shape_function(cavity_env, qs_kind_set, atomic_kind_set, &
2556 : radius=cdft_control%becke_control%rcavity, &
2557 22 : radii_list=radii_list)
2558 22 : IF (ASSOCIATED(radii_list)) THEN
2559 18 : DEALLOCATE (radii_list)
2560 : END IF
2561 : END IF
2562 34 : NULLIFY (rs_cavity)
2563 : CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_rs_grid=rs_cavity, &
2564 34 : auxbas_pw_pool=auxbas_pw_pool)
2565 : ! be careful in parallel nsmax is chosen with multigrid in mind!
2566 34 : CALL rs_grid_zero(rs_cavity)
2567 34 : ALLOCATE (pab(1, 1))
2568 34 : nthread = 1
2569 34 : ithread = 0
2570 102 : DO ikind = 1, SIZE(atomic_kind_set)
2571 68 : numexp = cavity_env%kind_shape_fn(ikind)%numexp
2572 68 : IF (numexp <= 0) CYCLE
2573 68 : CALL get_atomic_kind(atomic_kind_set(ikind), natom=katom, atom_list=atom_list)
2574 204 : ALLOCATE (cores(katom))
2575 136 : DO iex = 1, numexp
2576 68 : alpha = cavity_env%kind_shape_fn(ikind)%zet(iex)
2577 68 : coef = cavity_env%kind_shape_fn(ikind)%coef(iex)
2578 68 : npme = 0
2579 136 : cores = 0
2580 136 : DO iatom = 1, katom
2581 136 : IF (rs_cavity%desc%parallel .AND. .NOT. rs_cavity%desc%distributed) THEN
2582 : ! replicated realspace grid, split the atoms up between procs
2583 68 : IF (MODULO(iatom, rs_cavity%desc%group_size) == rs_cavity%desc%my_pos) THEN
2584 34 : npme = npme + 1
2585 34 : cores(npme) = iatom
2586 : END IF
2587 : ELSE
2588 0 : npme = npme + 1
2589 0 : cores(npme) = iatom
2590 : END IF
2591 : END DO
2592 170 : DO j = 1, npme
2593 34 : iatom = cores(j)
2594 34 : atom_a = atom_list(iatom)
2595 34 : pab(1, 1) = coef
2596 34 : IF (store_vectors) THEN
2597 136 : ra(:) = position_vecs(:, atom_a) + cell_v(:)/2._dp
2598 : ELSE
2599 0 : ra(:) = pbc(particle_set(atom_a)%r, cell)
2600 : END IF
2601 102 : IF (is_constraint(atom_a)) THEN
2602 : radius = exp_radius_very_extended(la_min=0, la_max=0, lb_min=0, lb_max=0, &
2603 : ra=ra, rb=ra, rp=ra, &
2604 : zetp=alpha, eps=mixed_cdft%eps_rho_rspace, &
2605 : pab=pab, o1=0, o2=0, & ! without map_consistent
2606 34 : prefactor=1.0_dp, cutoff=0.0_dp)
2607 :
2608 : CALL collocate_pgf_product(0, alpha, 0, 0, 0.0_dp, 0, ra, &
2609 : [0.0_dp, 0.0_dp, 0.0_dp], 1.0_dp, pab, 0, 0, &
2610 : rs_cavity, &
2611 : radius=radius, ga_gb_function=GRID_FUNC_AB, &
2612 : use_subpatch=.TRUE., &
2613 34 : subpatch_pattern=0)
2614 : END IF
2615 : END DO
2616 : END DO
2617 170 : DEALLOCATE (cores)
2618 : END DO
2619 34 : DEALLOCATE (pab)
2620 34 : CALL auxbas_pw_pool%create_pw(cdft_control%becke_control%cavity)
2621 34 : CALL transfer_rs2pw(rs_cavity, cdft_control%becke_control%cavity)
2622 : CALL hfun_zero(cdft_control%becke_control%cavity%array, &
2623 : cdft_control%becke_control%eps_cavity, &
2624 34 : just_zero=.FALSE., bounds=bounds, work=my_work)
2625 34 : IF (bounds(2) < bo(2, 3)) THEN
2626 8 : bounds(2) = bounds(2) - 1
2627 : ELSE
2628 26 : bounds(2) = bo(2, 3)
2629 : END IF
2630 34 : IF (bounds(1) > bo(1, 3)) THEN
2631 : ! In the special case bounds(1) == bounds(2) == bo(2, 3), after this check
2632 : ! bounds(1) > bounds(2) and the subsequent gradient allocation (:, :, :, bounds(1):bounds(2))
2633 : ! will correctly allocate a 0-sized array
2634 8 : bounds(1) = bounds(1) + 1
2635 : ELSE
2636 26 : bounds(1) = bo(1, 3)
2637 : END IF
2638 34 : IF (bounds(1) > bounds(2)) THEN
2639 0 : my_work_size = 0
2640 : ELSE
2641 34 : my_work_size = (bounds(2) - bounds(1) + 1)
2642 34 : IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
2643 0 : my_work_size = my_work_size*(bo(2, 2) - bo(1, 2) + 1)
2644 : ELSE
2645 34 : my_work_size = my_work_size*(bo(2, 1) - bo(1, 1) + 1)
2646 : END IF
2647 : END IF
2648 102 : cdft_control%becke_control%confine_bounds = bounds
2649 34 : IF (cdft_control%becke_control%print_cavity) THEN
2650 : CALL hfun_zero(cdft_control%becke_control%cavity%array, &
2651 0 : cdft_control%becke_control%eps_cavity, just_zero=.TRUE.)
2652 : NULLIFY (stride)
2653 0 : ALLOCATE (stride(3))
2654 0 : stride = [2, 2, 2]
2655 0 : mpi_io = .TRUE.
2656 : unit_nr = cp_print_key_unit_nr(logger, print_section, "", &
2657 : middle_name="BECKE_CAVITY", &
2658 : extension=".cube", file_position="REWIND", &
2659 0 : log_filename=.FALSE., mpi_io=mpi_io)
2660 0 : IF (force_env%para_env%is_source() .AND. unit_nr < 1) THEN
2661 : CALL cp_abort(__LOCATION__, &
2662 0 : "Please turn on PROGRAM_RUN_INFO to print cavity")
2663 : END IF
2664 : CALL cp_pw_to_cube(cdft_control%becke_control%cavity, &
2665 : unit_nr, "CAVITY", particles=particles, &
2666 0 : stride=stride, mpi_io=mpi_io)
2667 0 : CALL cp_print_key_finished_output(unit_nr, logger, print_section, '', mpi_io=mpi_io)
2668 0 : DEALLOCATE (stride)
2669 : END IF
2670 : END IF
2671 36 : bo_conf = bo
2672 36 : IF (cdft_control%becke_control%cavity_confine) THEN
2673 102 : bo_conf(:, 3) = cdft_control%becke_control%confine_bounds
2674 : END IF
2675 : ! Load balance
2676 36 : IF (mixed_cdft%dlb) THEN
2677 : CALL mixed_becke_constraint_dlb(force_env, mixed_cdft, my_work, &
2678 8 : my_work_size, natom, bo, bo_conf)
2679 : END IF
2680 : ! The bounds have been finalized => time to allocate storage for working matrices
2681 36 : offset_dlb = 0
2682 36 : IF (mixed_cdft%dlb) THEN
2683 8 : IF (mixed_cdft%dlb_control%send_work .AND. .NOT. mixed_cdft%is_special) THEN
2684 8 : offset_dlb = SUM(mixed_cdft%dlb_control%target_list(2, :))
2685 : END IF
2686 : END IF
2687 36 : IF (cdft_control%becke_control%cavity_confine) THEN
2688 : ! Get rid of the zero part of the confinement cavity (cr3d -> real(:,:,:))
2689 34 : IF (mixed_cdft%is_special) THEN
2690 0 : ALLOCATE (mixed_cdft%sendbuff(SIZE(mixed_cdft%dest_list)))
2691 0 : DO i = 1, SIZE(mixed_cdft%dest_list)
2692 : ALLOCATE (mixed_cdft%sendbuff(i)%cavity(mixed_cdft%dest_list_bo(1, i):mixed_cdft%dest_list_bo(2, i), &
2693 0 : bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2694 : mixed_cdft%sendbuff(i)%cavity = cdft_control%becke_control%cavity%array(mixed_cdft%dest_list_bo(1, i): &
2695 : mixed_cdft%dest_list_bo(2, i), &
2696 : bo(1, 2):bo(2, 2), &
2697 0 : bo_conf(1, 3):bo_conf(2, 3))
2698 : END DO
2699 34 : ELSE IF (mixed_cdft%is_pencil) THEN
2700 0 : ALLOCATE (mixed_cdft%cavity(bo(1, 1) + offset_dlb:bo(2, 1), bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2701 : mixed_cdft%cavity = cdft_control%becke_control%cavity%array(bo(1, 1) + offset_dlb:bo(2, 1), &
2702 : bo(1, 2):bo(2, 2), &
2703 0 : bo_conf(1, 3):bo_conf(2, 3))
2704 : ELSE
2705 170 : ALLOCATE (mixed_cdft%cavity(bo(1, 1):bo(2, 1), bo(1, 2) + offset_dlb:bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2706 : mixed_cdft%cavity = cdft_control%becke_control%cavity%array(bo(1, 1):bo(2, 1), &
2707 : bo(1, 2) + offset_dlb:bo(2, 2), &
2708 3568226 : bo_conf(1, 3):bo_conf(2, 3))
2709 : END IF
2710 34 : CALL auxbas_pw_pool%give_back_pw(cdft_control%becke_control%cavity)
2711 : END IF
2712 36 : IF (mixed_cdft%is_special) THEN
2713 0 : DO i = 1, SIZE(mixed_cdft%dest_list)
2714 : ALLOCATE (mixed_cdft%sendbuff(i)%weight(mixed_cdft%dest_list_bo(1, i):mixed_cdft%dest_list_bo(2, i), &
2715 0 : bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2716 0 : mixed_cdft%sendbuff(i)%weight = 0.0_dp
2717 : END DO
2718 36 : ELSE IF (mixed_cdft%is_pencil) THEN
2719 0 : ALLOCATE (mixed_cdft%weight(bo(1, 1) + offset_dlb:bo(2, 1), bo(1, 2):bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2720 0 : mixed_cdft%weight = 0.0_dp
2721 : ELSE
2722 180 : ALLOCATE (mixed_cdft%weight(bo(1, 1):bo(2, 1), bo(1, 2) + offset_dlb:bo(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
2723 1879397 : mixed_cdft%weight = 0.0_dp
2724 : END IF
2725 36 : IF (in_memory) THEN
2726 24 : IF (mixed_cdft%is_special) THEN
2727 0 : DO i = 1, SIZE(mixed_cdft%dest_list)
2728 : ALLOCATE (mixed_cdft%sendbuff(i)%gradients(3*natom, mixed_cdft%dest_list_bo(1, i): &
2729 : mixed_cdft%dest_list_bo(2, i), &
2730 : bo(1, 2):bo(2, 2), &
2731 0 : bo_conf(1, 3):bo_conf(2, 3)))
2732 0 : mixed_cdft%sendbuff(i)%gradients = 0.0_dp
2733 : END DO
2734 24 : ELSE IF (mixed_cdft%is_pencil) THEN
2735 : ALLOCATE (cdft_control%group(1)%gradients(3*natom, bo(1, 1) + offset_dlb:bo(2, 1), &
2736 : bo(1, 2):bo(2, 2), &
2737 0 : bo_conf(1, 3):bo_conf(2, 3)))
2738 0 : cdft_control%group(1)%gradients = 0.0_dp
2739 : ELSE
2740 : ALLOCATE (cdft_control%group(1)%gradients(3*natom, bo(1, 1):bo(2, 1), &
2741 : bo(1, 2) + offset_dlb:bo(2, 2), &
2742 144 : bo_conf(1, 3):bo_conf(2, 3)))
2743 9808936 : cdft_control%group(1)%gradients = 0.0_dp
2744 : END IF
2745 : END IF
2746 :
2747 36 : CALL timestop(handle)
2748 :
2749 36 : END SUBROUTINE mixed_becke_constraint_init
2750 :
2751 : ! **************************************************************************************************
2752 : !> \brief Setup load balancing for mixed Becke calculation
2753 : !> \param force_env the force_env that holds the CDFT states
2754 : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
2755 : !> \param my_work an estimate of the work per processor
2756 : !> \param my_work_size size of the smallest array slice per processor. overloaded processors will
2757 : !> redistribute works as integer multiples of this value.
2758 : !> \param natom the total number of atoms
2759 : !> \param bo bounds of the realspace grid that holds the electron density
2760 : !> \param bo_conf same as bo, but bounds along z-direction have been compacted with confinement
2761 : !> \par History
2762 : !> 03.2016 created [Nico Holmberg]
2763 : ! **************************************************************************************************
2764 8 : SUBROUTINE mixed_becke_constraint_dlb(force_env, mixed_cdft, my_work, &
2765 : my_work_size, natom, bo, bo_conf)
2766 : TYPE(force_env_type), POINTER :: force_env
2767 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
2768 : INTEGER, INTENT(IN) :: my_work, my_work_size, natom
2769 : INTEGER, DIMENSION(2, 3) :: bo, bo_conf
2770 :
2771 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_dlb'
2772 : INTEGER, PARAMETER :: should_deallocate = 7000, &
2773 : uninitialized = -7000
2774 :
2775 : CHARACTER(len=2) :: dummy
2776 : INTEGER :: actually_sent, exhausted_work, handle, i, ind, iounit, ispecial, j, max_targets, &
2777 : more_work, my_pos, my_special_work, my_target, no_overloaded, no_underloaded, nsend, &
2778 : nsend_limit, nsend_max, offset, offset_proc, offset_special, send_total, tags(2)
2779 8 : INTEGER, DIMENSION(:), POINTER :: buffsize, cumulative_work, expected_work, load_imbalance, &
2780 16 : nrecv, nsend_proc, sendbuffer, should_warn, tmp, work_index, work_size
2781 8 : INTEGER, DIMENSION(:, :), POINTER :: targets, tmp_bo
2782 : LOGICAL :: consistent
2783 16 : LOGICAL, DIMENSION(:), POINTER :: mask_recv, mask_send, touched
2784 : REAL(kind=dp) :: average_work, load_scale, &
2785 : very_overloaded, work_factor
2786 8 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: cavity
2787 16 : TYPE(buffers_bi), DIMENSION(:), POINTER :: recvbuffer, sbuff
2788 : TYPE(cdft_control_type), POINTER :: cdft_control
2789 : TYPE(cp_logger_type), POINTER :: logger
2790 40 : TYPE(mp_request_type), DIMENSION(4) :: req
2791 8 : TYPE(mp_request_type), DIMENSION(:), POINTER :: req_recv, req_total
2792 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
2793 :
2794 16 : logger => cp_get_default_logger()
2795 8 : CALL timeset(routineN, handle)
2796 8 : mixed_cdft%dlb_control%recv_work = .FALSE.
2797 8 : mixed_cdft%dlb_control%send_work = .FALSE.
2798 8 : NULLIFY (expected_work, work_index, load_imbalance, work_size, &
2799 8 : cumulative_work, sendbuffer, buffsize, req_recv, req_total, &
2800 8 : tmp, nrecv, nsend_proc, targets, tmp_bo, touched, &
2801 8 : mask_recv, mask_send, cavity, recvbuffer, sbuff, force_env_section, &
2802 8 : print_section, cdft_control)
2803 8 : CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
2804 8 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
2805 8 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
2806 8 : cdft_control => mixed_cdft%cdft_control
2807 : ! These numerical values control data redistribution and are system sensitive
2808 : ! Currently they are not refined during run time which may cause crashes
2809 : ! However, using too many processors or a confinement cavity that is too large relative to the
2810 : ! total system volume are more likely culprits.
2811 8 : load_scale = mixed_cdft%dlb_control%load_scale
2812 8 : very_overloaded = mixed_cdft%dlb_control%very_overloaded
2813 8 : more_work = mixed_cdft%dlb_control%more_work
2814 8 : max_targets = 40
2815 8 : work_factor = 0.8_dp
2816 : ! Reset targets/sources
2817 8 : IF (mixed_cdft%is_special) THEN
2818 0 : DEALLOCATE (mixed_cdft%dest_list, mixed_cdft%dest_list_bo, &
2819 0 : mixed_cdft%source_list, mixed_cdft%source_list_bo)
2820 : ALLOCATE (mixed_cdft%dest_list(SIZE(mixed_cdft%dest_list_save)), &
2821 : mixed_cdft%dest_list_bo(SIZE(mixed_cdft%dest_bo_save, 1), SIZE(mixed_cdft%dest_bo_save, 2)), &
2822 : mixed_cdft%source_list(SIZE(mixed_cdft%source_list_save)), &
2823 0 : mixed_cdft%source_list_bo(SIZE(mixed_cdft%source_bo_save, 1), SIZE(mixed_cdft%source_bo_save, 2)))
2824 0 : mixed_cdft%dest_list = mixed_cdft%dest_list_save
2825 0 : mixed_cdft%source_list = mixed_cdft%source_list_save
2826 0 : mixed_cdft%dest_list_bo = mixed_cdft%dest_bo_save
2827 0 : mixed_cdft%source_list_bo = mixed_cdft%source_bo_save
2828 : END IF
2829 : ALLOCATE (mixed_cdft%dlb_control%expected_work(force_env%para_env%num_pe), &
2830 : expected_work(force_env%para_env%num_pe), &
2831 48 : work_size(force_env%para_env%num_pe))
2832 : IF (debug_this_module) THEN
2833 : ALLOCATE (should_warn(force_env%para_env%num_pe))
2834 : should_warn = 0
2835 : END IF
2836 24 : expected_work = 0
2837 8 : expected_work(force_env%para_env%mepos + 1) = my_work
2838 24 : work_size = 0
2839 8 : work_size(force_env%para_env%mepos + 1) = my_work_size
2840 8 : IF (ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
2841 4 : IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
2842 : work_size(force_env%para_env%mepos + 1) = work_size(force_env%para_env%mepos + 1) - &
2843 : NINT(REAL(mixed_cdft%dlb_control% &
2844 : prediction_error(force_env%para_env%mepos + 1), dp)/ &
2845 0 : REAL(bo(2, 1) - bo(1, 1) + 1, dp))
2846 : ELSE
2847 : work_size(force_env%para_env%mepos + 1) = work_size(force_env%para_env%mepos + 1) - &
2848 : NINT(REAL(mixed_cdft%dlb_control% &
2849 : prediction_error(force_env%para_env%mepos + 1), dp)/ &
2850 4 : REAL(bo(2, 2) - bo(1, 2) + 1, dp))
2851 : END IF
2852 : END IF
2853 40 : CALL force_env%para_env%sum(expected_work)
2854 40 : CALL force_env%para_env%sum(work_size)
2855 : ! We store the unsorted expected work to refine the estimate on subsequent calls to this routine
2856 40 : mixed_cdft%dlb_control%expected_work = expected_work
2857 : ! Take into account the prediction error of the last step
2858 8 : IF (ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
2859 20 : expected_work = expected_work - mixed_cdft%dlb_control%prediction_error
2860 : END IF
2861 : !
2862 24 : average_work = REAL(SUM(expected_work), dp)/REAL(force_env%para_env%num_pe, dp)
2863 : ALLOCATE (work_index(force_env%para_env%num_pe), &
2864 : load_imbalance(force_env%para_env%num_pe), &
2865 48 : targets(2, force_env%para_env%num_pe))
2866 40 : load_imbalance = expected_work - NINT(average_work)
2867 8 : no_overloaded = 0
2868 8 : no_underloaded = 0
2869 56 : targets = 0
2870 : ! Convert the load imbalance to a multiple of the actual work size
2871 24 : DO i = 1, force_env%para_env%num_pe
2872 24 : IF (load_imbalance(i) > 0) THEN
2873 8 : no_overloaded = no_overloaded + 1
2874 : ! Allow heavily overloaded processors to dump more data since most likely they have a lot of 'real' work
2875 8 : IF (expected_work(i) > NINT(very_overloaded*average_work)) THEN
2876 0 : load_imbalance(i) = (CEILING(REAL(load_imbalance(i), dp)/REAL(work_size(i), dp)) + more_work)*work_size(i)
2877 : ELSE
2878 8 : load_imbalance(i) = CEILING(REAL(load_imbalance(i), dp)/REAL(work_size(i), dp))*work_size(i)
2879 : END IF
2880 : ELSE
2881 : ! Allow the underloaded processors to take load_scale amount of additional work
2882 : ! otherwise we may be unable to exhaust all overloaded processors
2883 8 : load_imbalance(i) = NINT(load_imbalance(i)*load_scale)
2884 8 : no_underloaded = no_underloaded + 1
2885 : END IF
2886 : END DO
2887 8 : CALL sort(expected_work, force_env%para_env%num_pe, indices=work_index)
2888 : ! Redistribute work in order from the most overloaded processors to the most underloaded processors
2889 : ! Each underloaded processor is limited to one overloaded processor
2890 8 : IF (load_imbalance(force_env%para_env%mepos + 1) > 0) THEN
2891 4 : offset = 0
2892 4 : mixed_cdft%dlb_control%send_work = .TRUE.
2893 : ! Build up the total amount of work that needs redistribution
2894 12 : ALLOCATE (cumulative_work(force_env%para_env%num_pe))
2895 12 : cumulative_work = 0
2896 4 : DO i = force_env%para_env%num_pe, force_env%para_env%num_pe - no_overloaded + 1, -1
2897 4 : IF (work_index(i) == force_env%para_env%mepos + 1) THEN
2898 : EXIT
2899 : ELSE
2900 0 : offset = offset + load_imbalance(work_index(i))
2901 0 : IF (i == force_env%para_env%num_pe) THEN
2902 0 : cumulative_work(i) = load_imbalance(work_index(i))
2903 : ELSE
2904 0 : cumulative_work(i) = cumulative_work(i + 1) + load_imbalance(work_index(i))
2905 : END IF
2906 : END IF
2907 : END DO
2908 4 : my_pos = i
2909 4 : j = force_env%para_env%num_pe
2910 4 : nsend_max = load_imbalance(work_index(j))/work_size(work_index(j))
2911 4 : exhausted_work = 0
2912 : ! Determine send offset by going through all processors that are more overloaded than my_pos
2913 4 : DO i = 1, no_underloaded
2914 4 : IF (my_pos == force_env%para_env%num_pe) EXIT
2915 0 : nsend = -load_imbalance(work_index(i))/work_size(work_index(j))
2916 0 : IF (nsend < 1) nsend = 1
2917 0 : nsend_max = nsend_max - nsend
2918 0 : IF (nsend_max < 0) nsend = nsend + nsend_max
2919 0 : exhausted_work = exhausted_work + nsend*work_size(work_index(j))
2920 0 : offset = offset - nsend*work_size(work_index(j))
2921 0 : IF (offset < 0) EXIT
2922 4 : IF (exhausted_work == cumulative_work(j)) THEN
2923 0 : j = j - 1
2924 0 : nsend_max = load_imbalance(work_index(j))/work_size(work_index(j))
2925 : END IF
2926 : END DO
2927 : ! Underloaded processors were fully exhausted: rewind index
2928 : ! Load balancing will fail if this happens on multiple processors
2929 4 : IF (i > no_underloaded) THEN
2930 0 : i = no_underloaded
2931 : END IF
2932 4 : my_target = i
2933 4 : DEALLOCATE (cumulative_work)
2934 : ! Determine how much and who to send slices of my grid points
2935 4 : nsend_max = load_imbalance(force_env%para_env%mepos + 1)/work_size(force_env%para_env%mepos + 1)
2936 : ! This the actual number of available array slices
2937 4 : IF (mixed_cdft%is_pencil .OR. mixed_cdft%is_special) THEN
2938 0 : nsend_limit = bo(2, 1) - bo(1, 1) + 1
2939 : ELSE
2940 4 : nsend_limit = bo(2, 2) - bo(1, 2) + 1
2941 : END IF
2942 4 : IF (.NOT. mixed_cdft%is_special) THEN
2943 4 : ALLOCATE (mixed_cdft%dlb_control%target_list(3, max_targets))
2944 : ELSE
2945 0 : ALLOCATE (mixed_cdft%dlb_control%target_list(3 + 2*SIZE(mixed_cdft%dest_list), max_targets))
2946 0 : ALLOCATE (touched(SIZE(mixed_cdft%dest_list)))
2947 0 : touched = .FALSE.
2948 : END IF
2949 644 : mixed_cdft%dlb_control%target_list = uninitialized
2950 4 : i = 1
2951 4 : ispecial = 1
2952 4 : offset_special = 0
2953 4 : targets(1, my_pos) = my_target
2954 4 : send_total = 0
2955 : ! Main loop. Note, we actually allow my_pos to offload more slices than nsend_max
2956 : DO
2957 4 : nsend = -load_imbalance(work_index(my_target))/work_size(force_env%para_env%mepos + 1)
2958 4 : IF (nsend < 1) nsend = 1 ! send at least one block
2959 : ! Prevent over redistribution: leave at least (1-work_factor)*nsend_limit slices to my_pos
2960 4 : IF (nsend > NINT(work_factor*nsend_limit - send_total)) THEN
2961 : nsend = NINT(work_factor*nsend_limit - send_total)
2962 : IF (debug_this_module) THEN
2963 : should_warn(force_env%para_env%mepos + 1) = 1
2964 : END IF
2965 : END IF
2966 4 : mixed_cdft%dlb_control%target_list(1, i) = work_index(my_target) - 1 ! This is the actual processor rank
2967 4 : IF (mixed_cdft%is_special) THEN
2968 0 : mixed_cdft%dlb_control%target_list(2, i) = 0
2969 0 : actually_sent = nsend
2970 0 : DO j = ispecial, SIZE(mixed_cdft%dest_list)
2971 0 : mixed_cdft%dlb_control%target_list(2, i) = mixed_cdft%dlb_control%target_list(2, i) + 1
2972 0 : touched(j) = .TRUE.
2973 0 : IF (nsend < mixed_cdft%dest_list_bo(2, j) - mixed_cdft%dest_list_bo(1, j) + 1) THEN
2974 0 : mixed_cdft%dlb_control%target_list(3 + 2*j - 1, i) = mixed_cdft%dest_list_bo(1, j)
2975 0 : mixed_cdft%dlb_control%target_list(3 + 2*j, i) = mixed_cdft%dest_list_bo(1, j) + nsend - 1
2976 0 : mixed_cdft%dest_list_bo(1, j) = mixed_cdft%dest_list_bo(1, j) + nsend
2977 0 : nsend = 0
2978 0 : EXIT
2979 : ELSE
2980 0 : mixed_cdft%dlb_control%target_list(3 + 2*j - 1, i) = mixed_cdft%dest_list_bo(1, j)
2981 0 : mixed_cdft%dlb_control%target_list(3 + 2*j, i) = mixed_cdft%dest_list_bo(2, j)
2982 0 : nsend = nsend - (mixed_cdft%dest_list_bo(2, j) - mixed_cdft%dest_list_bo(1, j) + 1)
2983 0 : mixed_cdft%dest_list_bo(1:2, j) = should_deallocate
2984 : END IF
2985 0 : IF (nsend <= 0) EXIT
2986 : END DO
2987 0 : IF (mixed_cdft%dest_list_bo(1, ispecial) == should_deallocate) ispecial = j + 1
2988 0 : actually_sent = actually_sent - nsend
2989 0 : nsend_max = nsend_max - actually_sent
2990 0 : send_total = send_total + actually_sent
2991 : ELSE
2992 4 : mixed_cdft%dlb_control%target_list(2, i) = nsend
2993 4 : nsend_max = nsend_max - nsend
2994 4 : send_total = send_total + nsend
2995 : END IF
2996 4 : IF (nsend_max < 0) nsend_max = 0
2997 4 : IF (nsend_max == 0) EXIT
2998 0 : IF (my_target /= no_underloaded) THEN
2999 0 : my_target = my_target + 1
3000 : ELSE
3001 : ! If multiple processors execute this block load balancing will fail
3002 0 : mixed_cdft%dlb_control%target_list(2, i) = mixed_cdft%dlb_control%target_list(2, i) + nsend_max
3003 0 : nsend_max = 0
3004 0 : EXIT
3005 : END IF
3006 0 : i = i + 1
3007 4 : IF (i > max_targets) THEN
3008 : CALL cp_abort(__LOCATION__, &
3009 0 : "Load balancing error: increase max_targets")
3010 : END IF
3011 : END DO
3012 4 : IF (.NOT. mixed_cdft%is_special) THEN
3013 4 : CALL reallocate(mixed_cdft%dlb_control%target_list, 1, 3, 1, i)
3014 : ELSE
3015 0 : CALL reallocate(mixed_cdft%dlb_control%target_list, 1, 3 + 2*SIZE(mixed_cdft%dest_list), 1, i)
3016 : END IF
3017 4 : targets(2, my_pos) = my_target
3018 : ! Equalize the load on the target processors
3019 4 : IF (.NOT. mixed_cdft%is_special) THEN
3020 4 : IF (send_total > NINT(work_factor*nsend_limit)) send_total = NINT(work_factor*nsend_limit) - 1
3021 4 : nsend = NINT(REAL(send_total, dp)/REAL(SIZE(mixed_cdft%dlb_control%target_list, 2), dp))
3022 8 : mixed_cdft%dlb_control%target_list(2, :) = nsend
3023 : END IF
3024 : ELSE
3025 4 : DO i = 1, no_underloaded
3026 4 : IF (work_index(i) == force_env%para_env%mepos + 1) EXIT
3027 : END DO
3028 : my_pos = i
3029 : END IF
3030 104 : CALL force_env%para_env%sum(targets)
3031 : IF (debug_this_module) THEN
3032 : CALL force_env%para_env%sum(should_warn)
3033 : IF (ANY(should_warn == 1)) THEN
3034 : CALL cp_warn(__LOCATION__, &
3035 : "MIXED_CDFT DLB: Attempted to redistribute more array"// &
3036 : " slices than actually available. Leaving a fraction of the total"// &
3037 : " slices on the overloaded processor. Perhaps you have set LOAD_SCALE too high?")
3038 : END IF
3039 : DEALLOCATE (should_warn)
3040 : END IF
3041 : ! check that there is one-to-one mapping between over- and underloaded processors
3042 8 : IF (force_env%para_env%is_source()) THEN
3043 4 : consistent = .TRUE.
3044 4 : DO i = force_env%para_env%num_pe - 1, force_env%para_env%num_pe - no_overloaded + 1, -1
3045 0 : IF (targets(1, i) > no_underloaded) consistent = .FALSE.
3046 4 : IF (targets(1, i) > targets(2, i + 1)) THEN
3047 : CYCLE
3048 : ELSE
3049 0 : consistent = .FALSE.
3050 : END IF
3051 : END DO
3052 4 : IF (.NOT. consistent) THEN
3053 : IF (debug_this_module .AND. iounit > 0) THEN
3054 : DO i = force_env%para_env%num_pe - 1, force_env%para_env%num_pe - no_overloaded + 1, -1
3055 : WRITE (iounit, '(A,I8,I8,I8,I8,I8)') &
3056 : 'load balancing info', load_imbalance(i), work_index(i), &
3057 : work_size(i), targets(1, i), targets(2, i)
3058 : END DO
3059 : END IF
3060 : CALL cp_abort(__LOCATION__, &
3061 : "Load balancing error: too much data to redistribute."// &
3062 : " Increase LOAD_SCALE or change the number of processors."// &
3063 : " If the confinement cavity occupies a large volume relative"// &
3064 0 : " to the total system volume, it might be worth disabling DLB.")
3065 : END IF
3066 : END IF
3067 : ! Tell the target processors which grid points they should compute
3068 8 : IF (my_pos <= no_underloaded) THEN
3069 4 : DO i = force_env%para_env%num_pe, force_env%para_env%num_pe - no_overloaded + 1, -1
3070 4 : IF (targets(1, i) <= my_pos .AND. targets(2, i) >= my_pos) THEN
3071 4 : mixed_cdft%dlb_control%recv_work = .TRUE.
3072 4 : mixed_cdft%dlb_control%my_source = work_index(i) - 1
3073 4 : EXIT
3074 : END IF
3075 : END DO
3076 4 : IF (mixed_cdft%dlb_control%recv_work) THEN
3077 4 : IF (.NOT. mixed_cdft%is_special) THEN
3078 4 : ALLOCATE (mixed_cdft%dlb_control%bo(12))
3079 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%bo, source=mixed_cdft%dlb_control%my_source, &
3080 4 : request=req(1))
3081 4 : CALL req(1)%wait()
3082 12 : mixed_cdft%dlb_control%my_dest_repl = [mixed_cdft%dlb_control%bo(11), mixed_cdft%dlb_control%bo(12)]
3083 12 : mixed_cdft%dlb_control%dest_tags_repl = [mixed_cdft%dlb_control%bo(9), mixed_cdft%dlb_control%bo(10)]
3084 : ALLOCATE (mixed_cdft%dlb_control%cavity(mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
3085 : mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
3086 20 : mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
3087 : ALLOCATE (mixed_cdft%dlb_control%weight(mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
3088 : mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
3089 20 : mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
3090 : ALLOCATE (mixed_cdft%dlb_control%gradients(3*natom, &
3091 : mixed_cdft%dlb_control%bo(1):mixed_cdft%dlb_control%bo(2), &
3092 : mixed_cdft%dlb_control%bo(3):mixed_cdft%dlb_control%bo(4), &
3093 24 : mixed_cdft%dlb_control%bo(7):mixed_cdft%dlb_control%bo(8)))
3094 22724 : mixed_cdft%dlb_control%gradients = 0.0_dp
3095 3524 : mixed_cdft%dlb_control%weight = 0.0_dp
3096 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%cavity, source=mixed_cdft%dlb_control%my_source, &
3097 4 : request=req(1))
3098 4 : CALL req(1)%wait()
3099 4 : DEALLOCATE (mixed_cdft%dlb_control%bo)
3100 : ELSE
3101 0 : ALLOCATE (buffsize(1))
3102 : CALL force_env%para_env%irecv(msgout=buffsize, source=mixed_cdft%dlb_control%my_source, &
3103 0 : request=req(1))
3104 0 : CALL req(1)%wait()
3105 0 : ALLOCATE (mixed_cdft%dlb_control%bo(12*buffsize(1)))
3106 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%bo, source=mixed_cdft%dlb_control%my_source, &
3107 0 : request=req(1))
3108 0 : ALLOCATE (mixed_cdft%dlb_control%sendbuff(buffsize(1)))
3109 0 : ALLOCATE (req_recv(buffsize(1)))
3110 0 : DEALLOCATE (buffsize)
3111 0 : CALL req(1)%wait()
3112 0 : DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
3113 : ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity(mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
3114 : mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
3115 : mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
3116 : mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
3117 : mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
3118 0 : mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
3119 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%sendbuff(j)%cavity, &
3120 : source=mixed_cdft%dlb_control%my_source, &
3121 0 : request=req_recv(j))
3122 : ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight(mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
3123 : mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
3124 : mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
3125 : mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
3126 : mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
3127 0 : mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
3128 : ALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients(3*natom, &
3129 : mixed_cdft%dlb_control%bo(12*(j - 1) + 1): &
3130 : mixed_cdft%dlb_control%bo(12*(j - 1) + 2), &
3131 : mixed_cdft%dlb_control%bo(12*(j - 1) + 3): &
3132 : mixed_cdft%dlb_control%bo(12*(j - 1) + 4), &
3133 : mixed_cdft%dlb_control%bo(12*(j - 1) + 7): &
3134 0 : mixed_cdft%dlb_control%bo(12*(j - 1) + 8)))
3135 0 : mixed_cdft%dlb_control%sendbuff(j)%weight = 0.0_dp
3136 0 : mixed_cdft%dlb_control%sendbuff(j)%gradients = 0.0_dp
3137 : mixed_cdft%dlb_control%sendbuff(j)%tag = [mixed_cdft%dlb_control%bo(12*(j - 1) + 9), &
3138 0 : mixed_cdft%dlb_control%bo(12*(j - 1) + 10)]
3139 : mixed_cdft%dlb_control%sendbuff(j)%rank = [mixed_cdft%dlb_control%bo(12*(j - 1) + 11), &
3140 0 : mixed_cdft%dlb_control%bo(12*(j - 1) + 12)]
3141 : END DO
3142 0 : CALL mp_waitall(req_recv)
3143 0 : DEALLOCATE (req_recv)
3144 : END IF
3145 : END IF
3146 : ELSE
3147 4 : IF (.NOT. mixed_cdft%is_special) THEN
3148 4 : offset = 0
3149 4 : ALLOCATE (sendbuffer(12))
3150 4 : send_total = 0
3151 8 : DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
3152 : tags = [(i - 1)*3 + 1 + force_env%para_env%mepos*6*max_targets, &
3153 12 : (i - 1)*3 + 1 + 3*max_targets + force_env%para_env%mepos*6*max_targets] ! Unique communicator tags
3154 4 : mixed_cdft%dlb_control%target_list(3, i) = tags(1)
3155 4 : IF (mixed_cdft%is_pencil) THEN
3156 : sendbuffer = [bo_conf(1, 1) + offset, &
3157 : bo_conf(1, 1) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3158 : bo_conf(1, 2), bo_conf(2, 2), bo(1, 3), bo(2, 3), bo_conf(1, 3), bo_conf(2, 3), &
3159 0 : tags(1), tags(2), mixed_cdft%dest_list(1), mixed_cdft%dest_list(2)]
3160 : ELSE
3161 : sendbuffer = [bo_conf(1, 1), bo_conf(2, 1), &
3162 : bo_conf(1, 2) + offset, &
3163 : bo_conf(1, 2) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3164 : bo(1, 3), bo(2, 3), bo_conf(1, 3), bo_conf(2, 3), tags(1), tags(2), &
3165 52 : mixed_cdft%dest_list(1), mixed_cdft%dest_list(2)]
3166 : END IF
3167 4 : send_total = send_total + mixed_cdft%dlb_control%target_list(2, i) - 1
3168 : CALL force_env%para_env%isend(msgin=sendbuffer, dest=mixed_cdft%dlb_control%target_list(1, i), &
3169 4 : request=req(1))
3170 4 : CALL req(1)%wait()
3171 4 : IF (mixed_cdft%is_pencil) THEN
3172 : ALLOCATE (cavity(bo_conf(1, 1) + offset: &
3173 : bo_conf(1, 1) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3174 0 : bo_conf(1, 2):bo_conf(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
3175 : cavity = cdft_control%becke_control%cavity%array(bo_conf(1, 1) + offset: &
3176 : bo_conf(1, 1) + offset + &
3177 : (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3178 : bo_conf(1, 2):bo_conf(2, 2), &
3179 0 : bo_conf(1, 3):bo_conf(2, 3))
3180 : ELSE
3181 : ALLOCATE (cavity(bo_conf(1, 1):bo_conf(2, 1), &
3182 : bo_conf(1, 2) + offset: &
3183 : bo_conf(1, 2) + offset + (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3184 20 : bo_conf(1, 3):bo_conf(2, 3)))
3185 : cavity = cdft_control%becke_control%cavity%array(bo_conf(1, 1):bo_conf(2, 1), &
3186 : bo_conf(1, 2) + offset: &
3187 : bo_conf(1, 2) + offset + &
3188 : (mixed_cdft%dlb_control%target_list(2, i) - 1), &
3189 7044 : bo_conf(1, 3):bo_conf(2, 3))
3190 : END IF
3191 : CALL force_env%para_env%isend(msgin=cavity, &
3192 : dest=mixed_cdft%dlb_control%target_list(1, i), &
3193 4 : request=req(1))
3194 4 : CALL req(1)%wait()
3195 4 : offset = offset + mixed_cdft%dlb_control%target_list(2, i)
3196 8 : DEALLOCATE (cavity)
3197 : END DO
3198 4 : IF (mixed_cdft%is_pencil) THEN
3199 0 : mixed_cdft%dlb_control%distributed(1) = bo_conf(1, 1)
3200 0 : mixed_cdft%dlb_control%distributed(2) = bo_conf(1, 1) + offset - 1
3201 : ELSE
3202 4 : mixed_cdft%dlb_control%distributed(1) = bo_conf(1, 2)
3203 4 : mixed_cdft%dlb_control%distributed(2) = bo_conf(1, 2) + offset - 1
3204 : END IF
3205 4 : DEALLOCATE (sendbuffer)
3206 : ELSE
3207 0 : ALLOCATE (buffsize(1))
3208 0 : DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
3209 0 : buffsize = mixed_cdft%dlb_control%target_list(2, i)
3210 : ! Unique communicator tags (dont actually need these, should be removed)
3211 : tags = [(i - 1)*3 + 1 + force_env%para_env%mepos*6*max_targets, &
3212 0 : (i - 1)*3 + 1 + 3*max_targets + force_env%para_env%mepos*6*max_targets]
3213 0 : DO j = 4, SIZE(mixed_cdft%dlb_control%target_list, 1)
3214 0 : IF (mixed_cdft%dlb_control%target_list(j, i) > uninitialized) EXIT
3215 : END DO
3216 0 : offset_special = j
3217 0 : offset_proc = j - 4 - (j - 4)/2
3218 : CALL force_env%para_env%isend(msgin=buffsize, &
3219 : dest=mixed_cdft%dlb_control%target_list(1, i), &
3220 0 : request=req(1))
3221 0 : CALL req(1)%wait()
3222 0 : ALLOCATE (sendbuffer(12*buffsize(1)))
3223 0 : DO j = 1, buffsize(1)
3224 : sendbuffer(12*(j - 1) + 1:12*(j - 1) + 12) = [mixed_cdft%dlb_control%target_list(offset_special + 2*(j - 1), i), &
3225 : mixed_cdft%dlb_control%target_list(offset_special + 2*j - 1, i), &
3226 : bo_conf(1, 2), bo_conf(2, 2), bo(1, 3), bo(2, 3), &
3227 : bo_conf(1, 3), bo_conf(2, 3), tags(1), tags(2), &
3228 : mixed_cdft%dest_list(j + offset_proc), &
3229 0 : mixed_cdft%dest_list(j + offset_proc) + force_env%para_env%num_pe/2]
3230 : END DO
3231 : CALL force_env%para_env%isend(msgin=sendbuffer, &
3232 : dest=mixed_cdft%dlb_control%target_list(1, i), &
3233 0 : request=req(1))
3234 0 : CALL req(1)%wait()
3235 0 : DEALLOCATE (sendbuffer)
3236 0 : DO j = 1, buffsize(1)
3237 : ALLOCATE (cavity(mixed_cdft%dlb_control%target_list(offset_special + 2*(j - 1), i): &
3238 : mixed_cdft%dlb_control%target_list(offset_special + 2*j - 1, i), &
3239 0 : bo_conf(1, 2):bo_conf(2, 2), bo_conf(1, 3):bo_conf(2, 3)))
3240 : cavity = cdft_control%becke_control%cavity%array(LBOUND(cavity, 1):UBOUND(cavity, 1), &
3241 : bo_conf(1, 2):bo_conf(2, 2), &
3242 0 : bo_conf(1, 3):bo_conf(2, 3))
3243 : CALL force_env%para_env%isend(msgin=cavity, &
3244 : dest=mixed_cdft%dlb_control%target_list(1, i), &
3245 0 : request=req(1))
3246 0 : CALL req(1)%wait()
3247 0 : DEALLOCATE (cavity)
3248 : END DO
3249 : END DO
3250 0 : DEALLOCATE (buffsize)
3251 : END IF
3252 : END IF
3253 8 : DEALLOCATE (expected_work, work_size, load_imbalance, work_index, targets)
3254 : ! Once calculated, data defined on the distributed grid points is sent directly to the processors that own the
3255 : ! grid points after the constraint is copied onto the two processor groups, instead of sending the data back to
3256 : ! the original owner
3257 8 : IF (mixed_cdft%is_special) THEN
3258 0 : my_special_work = 2
3259 0 : ALLOCATE (mask_send(SIZE(mixed_cdft%dest_list)), mask_recv(SIZE(mixed_cdft%source_list)))
3260 0 : ALLOCATE (nsend_proc(SIZE(mixed_cdft%dest_list)), nrecv(SIZE(mixed_cdft%source_list)))
3261 0 : nrecv = 0
3262 0 : nsend_proc = 0
3263 0 : mask_recv = .FALSE.
3264 0 : mask_send = .FALSE.
3265 : ELSE
3266 : my_special_work = 1
3267 : END IF
3268 72 : ALLOCATE (recvbuffer(SIZE(mixed_cdft%source_list)), sbuff(SIZE(mixed_cdft%dest_list)))
3269 56 : ALLOCATE (req_total(my_special_work*SIZE(mixed_cdft%source_list) + (my_special_work**2)*SIZE(mixed_cdft%dest_list)))
3270 24 : ALLOCATE (mixed_cdft%dlb_control%recv_work_repl(SIZE(mixed_cdft%source_list)))
3271 24 : DO i = 1, SIZE(mixed_cdft%source_list)
3272 16 : NULLIFY (recvbuffer(i)%bv, recvbuffer(i)%iv)
3273 16 : ALLOCATE (recvbuffer(i)%bv(1), recvbuffer(i)%iv(3))
3274 : CALL force_env%para_env%irecv(msgout=recvbuffer(i)%bv, &
3275 : source=mixed_cdft%source_list(i), &
3276 16 : request=req_total(i), tag=1)
3277 24 : IF (mixed_cdft%is_special) THEN
3278 : CALL force_env%para_env%irecv(msgout=recvbuffer(i)%iv, &
3279 : source=mixed_cdft%source_list(i), &
3280 : request=req_total(i + SIZE(mixed_cdft%source_list)), &
3281 0 : tag=2)
3282 : END IF
3283 : END DO
3284 16 : DO i = 1, my_special_work
3285 32 : DO j = 1, SIZE(mixed_cdft%dest_list)
3286 16 : IF (i == 1) THEN
3287 16 : NULLIFY (sbuff(j)%iv, sbuff(j)%bv)
3288 16 : ALLOCATE (sbuff(j)%bv(1))
3289 32 : sbuff(j)%bv = mixed_cdft%dlb_control%send_work
3290 16 : IF (mixed_cdft%is_special) THEN
3291 0 : ALLOCATE (sbuff(j)%iv(3))
3292 0 : sbuff(j)%iv(1:2) = mixed_cdft%dest_list_bo(1:2, j)
3293 0 : sbuff(j)%iv(3) = 0
3294 0 : IF (sbuff(j)%iv(1) == should_deallocate) mask_send(j) = .TRUE.
3295 0 : IF (mixed_cdft%dlb_control%send_work) THEN
3296 0 : sbuff(j)%bv = touched(j)
3297 0 : IF (touched(j)) THEN
3298 0 : nsend = 0
3299 0 : DO ispecial = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
3300 0 : IF (mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), ispecial) /= uninitialized) THEN
3301 0 : nsend = nsend + 1
3302 : END IF
3303 : END DO
3304 0 : sbuff(j)%iv(3) = nsend
3305 0 : nsend_proc(j) = nsend
3306 : END IF
3307 : END IF
3308 : END IF
3309 : END IF
3310 16 : ind = j + (i - 1)*SIZE(mixed_cdft%dest_list) + my_special_work*SIZE(mixed_cdft%source_list)
3311 : CALL force_env%para_env%isend(msgin=sbuff(j)%bv, &
3312 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
3313 16 : request=req_total(ind), tag=1)
3314 24 : IF (mixed_cdft%is_special) THEN
3315 : CALL force_env%para_env%isend(msgin=sbuff(j)%iv, &
3316 : dest=mixed_cdft%dest_list(j) + (i - 1)*force_env%para_env%num_pe/2, &
3317 0 : request=req_total(ind + 2*SIZE(mixed_cdft%dest_list)), tag=2)
3318 : END IF
3319 : END DO
3320 : END DO
3321 8 : CALL mp_waitall(req_total)
3322 8 : DEALLOCATE (req_total)
3323 24 : DO i = 1, SIZE(mixed_cdft%source_list)
3324 16 : mixed_cdft%dlb_control%recv_work_repl(i) = recvbuffer(i)%bv(1)
3325 16 : IF (mixed_cdft%is_special .AND. mixed_cdft%dlb_control%recv_work_repl(i)) THEN
3326 0 : mixed_cdft%source_list_bo(1:2, i) = recvbuffer(i)%iv(1:2)
3327 0 : nrecv(i) = recvbuffer(i)%iv(3)
3328 0 : IF (recvbuffer(i)%iv(1) == should_deallocate) mask_recv(i) = .TRUE.
3329 : END IF
3330 16 : DEALLOCATE (recvbuffer(i)%bv)
3331 24 : IF (ASSOCIATED(recvbuffer(i)%iv)) DEALLOCATE (recvbuffer(i)%iv)
3332 : END DO
3333 24 : DO j = 1, SIZE(mixed_cdft%dest_list)
3334 16 : DEALLOCATE (sbuff(j)%bv)
3335 24 : IF (ASSOCIATED(sbuff(j)%iv)) DEALLOCATE (sbuff(j)%iv)
3336 : END DO
3337 8 : DEALLOCATE (recvbuffer)
3338 : ! For some reason if debug_this_module is true and is_special is false, the deallocate statement
3339 : ! on line 3433 gets executed no matter what (gfortran 5.3.0 bug?). Printing out the variable seems to fix it...
3340 : IF (debug_this_module) THEN
3341 : WRITE (dummy, *) mixed_cdft%is_special
3342 : END IF
3343 :
3344 8 : IF (.NOT. mixed_cdft%is_special) THEN
3345 8 : IF (mixed_cdft%dlb_control%send_work) THEN
3346 32 : ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl) + 2))
3347 4 : ALLOCATE (sendbuffer(6))
3348 4 : IF (mixed_cdft%is_pencil) THEN
3349 : sendbuffer = [SIZE(mixed_cdft%dlb_control%target_list, 2), bo_conf(1, 3), bo_conf(2, 3), &
3350 0 : bo_conf(1, 1), bo_conf(1, 2), bo_conf(2, 2)]
3351 : ELSE
3352 : sendbuffer = [SIZE(mixed_cdft%dlb_control%target_list, 2), bo_conf(1, 3), bo_conf(2, 3), &
3353 28 : bo_conf(1, 2), bo_conf(1, 1), bo_conf(2, 1)]
3354 : END IF
3355 8 : ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3356 24 : ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl)))
3357 : END IF
3358 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3359 24 : ALLOCATE (mixed_cdft%dlb_control%recv_info(2))
3360 8 : NULLIFY (mixed_cdft%dlb_control%recv_info(1)%target_list, mixed_cdft%dlb_control%recv_info(2)%target_list)
3361 24 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(2))
3362 8 : NULLIFY (mixed_cdft%dlb_control%recvbuff(1)%buffs, mixed_cdft%dlb_control%recvbuff(2)%buffs)
3363 : END IF
3364 : ! First communicate which grid points were distributed
3365 8 : IF (mixed_cdft%dlb_control%send_work) THEN
3366 12 : ind = COUNT(mixed_cdft%dlb_control%recv_work_repl) + 1
3367 12 : DO i = 1, 2
3368 : CALL force_env%para_env%isend(msgin=sendbuffer, &
3369 : dest=mixed_cdft%dest_list(i), &
3370 8 : request=req_total(ind))
3371 12 : ind = ind + 1
3372 : END DO
3373 : END IF
3374 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3375 8 : ind = 1
3376 24 : DO i = 1, 2
3377 24 : IF (mixed_cdft%dlb_control%recv_work_repl(i)) THEN
3378 8 : ALLOCATE (mixed_cdft%dlb_control%recv_info(i)%matrix_info(6))
3379 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recv_info(i)%matrix_info, &
3380 : source=mixed_cdft%source_list(i), &
3381 8 : request=req_total(ind))
3382 8 : ind = ind + 1
3383 : END IF
3384 : END DO
3385 : END IF
3386 8 : IF (ASSOCIATED(req_total)) THEN
3387 8 : CALL mp_waitall(req_total)
3388 : END IF
3389 : ! Now communicate which processor handles which grid points
3390 8 : IF (mixed_cdft%dlb_control%send_work) THEN
3391 12 : ind = COUNT(mixed_cdft%dlb_control%recv_work_repl) + 1
3392 12 : DO i = 1, 2
3393 8 : IF (i == 2) THEN
3394 8 : mixed_cdft%dlb_control%target_list(3, :) = mixed_cdft%dlb_control%target_list(3, :) + 3*max_targets
3395 : END IF
3396 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%target_list, &
3397 : dest=mixed_cdft%dest_list(i), &
3398 8 : request=req_total(ind))
3399 12 : ind = ind + 1
3400 : END DO
3401 : END IF
3402 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3403 8 : ind = 1
3404 24 : DO i = 1, 2
3405 24 : IF (mixed_cdft%dlb_control%recv_work_repl(i)) THEN
3406 : ALLOCATE (mixed_cdft%dlb_control%recv_info(i)% &
3407 24 : target_list(3, mixed_cdft%dlb_control%recv_info(i)%matrix_info(1)))
3408 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recv_info(i)%target_list, &
3409 : source=mixed_cdft%source_list(i), &
3410 8 : request=req_total(ind))
3411 8 : ind = ind + 1
3412 : END IF
3413 : END DO
3414 : END IF
3415 8 : IF (ASSOCIATED(req_total)) THEN
3416 8 : CALL mp_waitall(req_total)
3417 8 : DEALLOCATE (req_total)
3418 : END IF
3419 8 : IF (ASSOCIATED(sendbuffer)) DEALLOCATE (sendbuffer)
3420 : ELSE
3421 0 : IF (mixed_cdft%dlb_control%send_work) THEN
3422 0 : ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl) + 2*COUNT(touched)))
3423 0 : ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3424 0 : ALLOCATE (req_total(COUNT(mixed_cdft%dlb_control%recv_work_repl)))
3425 : END IF
3426 0 : IF (mixed_cdft%dlb_control%send_work) THEN
3427 0 : ind = COUNT(mixed_cdft%dlb_control%recv_work_repl)
3428 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
3429 0 : IF (touched(j)) THEN
3430 0 : ALLOCATE (sbuff(j)%iv(4 + 3*nsend_proc(j)))
3431 0 : sbuff(j)%iv(1:4) = [bo_conf(1, 2), bo_conf(2, 2), bo_conf(1, 3), bo_conf(2, 3)]
3432 0 : offset = 5
3433 0 : DO i = 1, SIZE(mixed_cdft%dlb_control%target_list, 2)
3434 0 : IF (mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), i) /= uninitialized) THEN
3435 : sbuff(j)%iv(offset:offset + 2) = [mixed_cdft%dlb_control%target_list(1, i), &
3436 : mixed_cdft%dlb_control%target_list(4 + 2*(j - 1), i), &
3437 0 : mixed_cdft%dlb_control%target_list(4 + 2*j - 1, i)]
3438 0 : offset = offset + 3
3439 : END IF
3440 : END DO
3441 0 : DO ispecial = 1, my_special_work
3442 : CALL force_env%para_env%isend(msgin=sbuff(j)%iv, &
3443 : dest=mixed_cdft%dest_list(j) + (ispecial - 1)*force_env%para_env%num_pe/2, &
3444 0 : request=req_total(ind + ispecial))
3445 : END DO
3446 0 : ind = ind + my_special_work
3447 : END IF
3448 : END DO
3449 : END IF
3450 0 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3451 0 : ALLOCATE (mixed_cdft%dlb_control%recv_info(SIZE(mixed_cdft%source_list)))
3452 0 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(SIZE(mixed_cdft%source_list)))
3453 0 : ind = 1
3454 0 : DO j = 1, SIZE(mixed_cdft%source_list)
3455 : NULLIFY (mixed_cdft%dlb_control%recv_info(j)%target_list, &
3456 0 : mixed_cdft%dlb_control%recvbuff(j)%buffs)
3457 0 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
3458 0 : ALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info(4 + 3*nrecv(j)))
3459 : CALL force_env%para_env%irecv(mixed_cdft%dlb_control%recv_info(j)%matrix_info, &
3460 : source=mixed_cdft%source_list(j), &
3461 0 : request=req_total(ind))
3462 0 : ind = ind + 1
3463 : END IF
3464 : END DO
3465 : END IF
3466 0 : IF (ASSOCIATED(req_total)) THEN
3467 0 : CALL mp_waitall(req_total)
3468 0 : DEALLOCATE (req_total)
3469 : END IF
3470 0 : IF (ANY(mask_send)) THEN
3471 : ALLOCATE (tmp(SIZE(mixed_cdft%dest_list) - COUNT(mask_send)), &
3472 0 : tmp_bo(2, SIZE(mixed_cdft%dest_list) - COUNT(mask_send)))
3473 0 : i = 1
3474 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
3475 0 : IF (.NOT. mask_send(j)) THEN
3476 0 : tmp(i) = mixed_cdft%dest_list(j)
3477 0 : tmp_bo(1:2, i) = mixed_cdft%dest_list_bo(1:2, j)
3478 0 : i = i + 1
3479 : END IF
3480 : END DO
3481 0 : DEALLOCATE (mixed_cdft%dest_list, mixed_cdft%dest_list_bo)
3482 0 : ALLOCATE (mixed_cdft%dest_list(SIZE(tmp)), mixed_cdft%dest_list_bo(2, SIZE(tmp)))
3483 0 : mixed_cdft%dest_list = tmp
3484 0 : mixed_cdft%dest_list_bo = tmp_bo
3485 0 : DEALLOCATE (tmp, tmp_bo)
3486 : END IF
3487 0 : IF (ANY(mask_recv)) THEN
3488 : ALLOCATE (tmp(SIZE(mixed_cdft%source_list) - COUNT(mask_recv)), &
3489 0 : tmp_bo(4, SIZE(mixed_cdft%source_list) - COUNT(mask_recv)))
3490 0 : i = 1
3491 0 : DO j = 1, SIZE(mixed_cdft%source_list)
3492 0 : IF (.NOT. mask_recv(j)) THEN
3493 0 : tmp(i) = mixed_cdft%source_list(j)
3494 0 : tmp_bo(1:4, i) = mixed_cdft%source_list_bo(1:4, j)
3495 0 : i = i + 1
3496 : END IF
3497 : END DO
3498 0 : DEALLOCATE (mixed_cdft%source_list, mixed_cdft%source_list_bo)
3499 0 : ALLOCATE (mixed_cdft%source_list(SIZE(tmp)), mixed_cdft%source_list_bo(4, SIZE(tmp)))
3500 0 : mixed_cdft%source_list = tmp
3501 0 : mixed_cdft%source_list_bo = tmp_bo
3502 0 : DEALLOCATE (tmp, tmp_bo)
3503 : END IF
3504 0 : DEALLOCATE (mask_recv, mask_send)
3505 0 : DEALLOCATE (nsend_proc, nrecv)
3506 0 : IF (mixed_cdft%dlb_control%send_work) THEN
3507 0 : DO j = 1, SIZE(mixed_cdft%dest_list)
3508 0 : IF (touched(j)) DEALLOCATE (sbuff(j)%iv)
3509 : END DO
3510 0 : IF (ASSOCIATED(touched)) DEALLOCATE (touched)
3511 : END IF
3512 : END IF
3513 8 : DEALLOCATE (sbuff)
3514 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
3515 8 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
3516 8 : CALL timestop(handle)
3517 :
3518 16 : END SUBROUTINE mixed_becke_constraint_dlb
3519 :
3520 : ! **************************************************************************************************
3521 : !> \brief Low level routine to build mixed Becke constraint and gradients
3522 : !> \param force_env the force_env that holds the CDFT states
3523 : !> \param mixed_cdft container for structures needed to build the mixed CDFT constraint
3524 : !> \param in_memory decides whether to build the weight function gradients in parallel before solving
3525 : !> the CDFT states or later during the SCF procedure of the individual states
3526 : !> \param is_constraint a list used to determine which atoms in the system define the constraint
3527 : !> \param store_vectors should temporary arrays be stored in memory to accelerate the calculation
3528 : !> \param R12 temporary array holding the pairwise atomic distances
3529 : !> \param position_vecs temporary array holding the pbc corrected atomic position vectors
3530 : !> \param pair_dist_vecs temporary array holding the pairwise displament vectors
3531 : !> \param coefficients array that determines how atoms should be summed to form the constraint
3532 : !> \param catom temporary array to map the global index of constraint atoms to their position
3533 : !> in a list that holds only constraint atoms
3534 : !> \par History
3535 : !> 03.2016 created [Nico Holmberg]
3536 : ! **************************************************************************************************
3537 36 : SUBROUTINE mixed_becke_constraint_low(force_env, mixed_cdft, in_memory, &
3538 : is_constraint, store_vectors, R12, position_vecs, &
3539 : pair_dist_vecs, coefficients, catom)
3540 : TYPE(force_env_type), POINTER :: force_env
3541 : TYPE(mixed_cdft_type), POINTER :: mixed_cdft
3542 : LOGICAL, INTENT(IN) :: in_memory
3543 : LOGICAL, ALLOCATABLE, DIMENSION(:), INTENT(INOUT) :: is_constraint
3544 : LOGICAL, INTENT(IN) :: store_vectors
3545 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :), &
3546 : INTENT(INOUT) :: R12, position_vecs
3547 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :), &
3548 : INTENT(INOUT) :: pair_dist_vecs
3549 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:), &
3550 : INTENT(INOUT) :: coefficients
3551 : INTEGER, ALLOCATABLE, DIMENSION(:), INTENT(INOUT) :: catom
3552 :
3553 : CHARACTER(len=*), PARAMETER :: routineN = 'mixed_becke_constraint_low'
3554 :
3555 : INTEGER :: handle, i, iatom, icomm, iforce_eval, index, iounit, ip, ispecial, iwork, j, &
3556 : jatom, jcomm, k, my_special_work, my_work, natom, nbuffs, nforce_eval, np(3), &
3557 : nsent_total, nskipped, nwork, offset, offset_repl
3558 36 : INTEGER, DIMENSION(:), POINTER :: work, work_dlb
3559 36 : INTEGER, DIMENSION(:, :), POINTER :: nsent
3560 : LOGICAL :: completed_recv, should_communicate
3561 36 : LOGICAL, ALLOCATABLE, DIMENSION(:) :: skip_me
3562 36 : LOGICAL, ALLOCATABLE, DIMENSION(:, :) :: completed
3563 : REAL(kind=dp) :: dist1, dist2, dmyexp, my1, my1_homo, &
3564 : myexp, sum_cell_f_all, &
3565 : sum_cell_f_constr, th, tmp_const
3566 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:) :: cell_functions, distances, ds_dR_i, &
3567 36 : ds_dR_j
3568 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :) :: d_sum_const_dR, d_sum_Pm_dR, &
3569 36 : distance_vecs, dP_i_dRi
3570 36 : REAL(kind=dp), ALLOCATABLE, DIMENSION(:, :, :) :: dP_i_dRj
3571 : REAL(kind=dp), DIMENSION(3) :: cell_v, dist_vec, dmy_dR_i, dmy_dR_j, &
3572 : dr, dr1_r2, dr_i_dR, dr_ij_dR, &
3573 : dr_j_dR, grid_p, r, r1, shift
3574 36 : REAL(kind=dp), DIMENSION(:), POINTER :: cutoffs
3575 36 : REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: cavity, weight
3576 36 : REAL(KIND=dp), DIMENSION(:, :, :, :), POINTER :: gradients
3577 : TYPE(cdft_control_type), POINTER :: cdft_control
3578 : TYPE(cell_type), POINTER :: cell
3579 : TYPE(cp_logger_type), POINTER :: logger
3580 : TYPE(cp_subsys_type), POINTER :: subsys_mix
3581 : TYPE(force_env_type), POINTER :: force_env_qs
3582 36 : TYPE(mp_request_type), DIMENSION(:), POINTER :: req_recv, req_total
3583 36 : TYPE(mp_request_type), DIMENSION(:, :), POINTER :: req_send
3584 : TYPE(particle_list_type), POINTER :: particles
3585 36 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
3586 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
3587 : TYPE(section_vals_type), POINTER :: force_env_section, print_section
3588 :
3589 72 : logger => cp_get_default_logger()
3590 36 : NULLIFY (work, req_recv, req_send, work_dlb, nsent, cutoffs, cavity, &
3591 36 : weight, gradients, cell, subsys_mix, force_env_qs, &
3592 36 : particle_set, particles, auxbas_pw_pool, force_env_section, &
3593 36 : print_section, cdft_control)
3594 36 : CALL timeset(routineN, handle)
3595 36 : nforce_eval = SIZE(force_env%sub_force_env)
3596 36 : CALL force_env_get(force_env=force_env, force_env_section=force_env_section)
3597 36 : print_section => section_vals_get_subs_vals(force_env_section, "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
3598 36 : iounit = cp_print_key_unit_nr(logger, print_section, '', extension='.mixedLog')
3599 36 : IF (.NOT. force_env%mixed_env%do_mixed_qmmm_cdft) THEN
3600 : CALL force_env_get(force_env=force_env, &
3601 : subsys=subsys_mix, &
3602 28 : cell=cell)
3603 : CALL cp_subsys_get(subsys=subsys_mix, &
3604 : particles=particles, &
3605 28 : particle_set=particle_set)
3606 : ELSE
3607 24 : DO iforce_eval = 1, nforce_eval
3608 16 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
3609 24 : force_env_qs => force_env%sub_force_env(iforce_eval)%force_env
3610 : END DO
3611 : CALL get_qs_env(force_env_qs%qmmm_env%qs_env, &
3612 : cp_subsys=subsys_mix, &
3613 8 : cell=cell)
3614 : CALL cp_subsys_get(subsys=subsys_mix, &
3615 : particles=particles, &
3616 8 : particle_set=particle_set)
3617 : END IF
3618 36 : natom = SIZE(particles%els)
3619 36 : cdft_control => mixed_cdft%cdft_control
3620 36 : CALL pw_env_get(pw_env=mixed_cdft%pw_env, auxbas_pw_pool=auxbas_pw_pool)
3621 144 : np = auxbas_pw_pool%pw_grid%npts
3622 144 : dr = auxbas_pw_pool%pw_grid%dr
3623 144 : shift = -REAL(MODULO(np, 2), dp)*dr/2.0_dp
3624 180 : ALLOCATE (cell_functions(natom), skip_me(natom))
3625 36 : IF (store_vectors) THEN
3626 72 : ALLOCATE (distances(natom))
3627 108 : ALLOCATE (distance_vecs(3, natom))
3628 : END IF
3629 36 : IF (in_memory) THEN
3630 24 : ALLOCATE (ds_dR_j(3))
3631 24 : ALLOCATE (ds_dR_i(3))
3632 72 : ALLOCATE (d_sum_Pm_dR(3, natom))
3633 48 : ALLOCATE (d_sum_const_dR(3, natom))
3634 96 : ALLOCATE (dP_i_dRj(3, natom, natom))
3635 48 : ALLOCATE (dP_i_dRi(3, natom))
3636 24 : th = 1.0e-8_dp
3637 : END IF
3638 36 : IF (mixed_cdft%dlb) THEN
3639 32 : ALLOCATE (work(force_env%para_env%num_pe), work_dlb(force_env%para_env%num_pe))
3640 24 : work = 0
3641 24 : work_dlb = 0
3642 : END IF
3643 36 : my_work = 1
3644 36 : my_special_work = 1
3645 : ! Load balancing: allocate storage for receiving buffers and post recv requests
3646 36 : IF (mixed_cdft%dlb) THEN
3647 8 : IF (mixed_cdft%dlb_control%recv_work) THEN
3648 4 : my_work = 2
3649 4 : IF (.NOT. mixed_cdft%is_special) THEN
3650 40 : ALLOCATE (req_send(2, 3))
3651 : ELSE
3652 0 : ALLOCATE (req_send(2, 3*SIZE(mixed_cdft%dlb_control%sendbuff)))
3653 : END IF
3654 : END IF
3655 16 : IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
3656 8 : IF (.NOT. mixed_cdft%is_special) THEN
3657 8 : offset_repl = 0
3658 8 : IF (mixed_cdft%dlb_control%recv_work_repl(1) .AND. mixed_cdft%dlb_control%recv_work_repl(2)) THEN
3659 : ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2) + &
3660 0 : SIZE(mixed_cdft%dlb_control%recv_info(2)%target_list, 2))))
3661 0 : offset_repl = 3*SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2)
3662 8 : ELSE IF (mixed_cdft%dlb_control%recv_work_repl(1)) THEN
3663 0 : ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(1)%target_list, 2))))
3664 : ELSE
3665 48 : ALLOCATE (req_recv(3*(SIZE(mixed_cdft%dlb_control%recv_info(2)%target_list, 2))))
3666 : END IF
3667 : ELSE
3668 0 : nbuffs = 0
3669 0 : offset_repl = 1
3670 0 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
3671 0 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
3672 0 : nbuffs = nbuffs + (SIZE(mixed_cdft%dlb_control%recv_info(j)%matrix_info) - 4)/3
3673 : END IF
3674 : END DO
3675 0 : ALLOCATE (req_recv(3*nbuffs))
3676 : END IF
3677 24 : DO j = 1, SIZE(mixed_cdft%dlb_control%recv_work_repl)
3678 24 : IF (mixed_cdft%dlb_control%recv_work_repl(j)) THEN
3679 8 : IF (.NOT. mixed_cdft%is_special) THEN
3680 8 : offset = 0
3681 8 : index = j + (j/2)
3682 64 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(SIZE(mixed_cdft%dlb_control%recv_info(j)%target_list, 2)))
3683 16 : DO i = 1, SIZE(mixed_cdft%dlb_control%recv_info(j)%target_list, 2)
3684 8 : IF (mixed_cdft%is_pencil) THEN
3685 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3686 : weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3687 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3688 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3689 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3690 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3691 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3692 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3693 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3694 : cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3695 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3696 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3697 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3698 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3699 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3700 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3701 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3702 : gradients(3*natom, &
3703 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3704 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3705 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3706 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3707 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3708 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3709 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3710 : ELSE
3711 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3712 : weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3713 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3714 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3715 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3716 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3717 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3718 40 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3719 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3720 : cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3721 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3722 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3723 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3724 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3725 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3726 40 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3727 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3728 : gradients(3*natom, &
3729 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(5): &
3730 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(6), &
3731 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset: &
3732 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4) + offset + &
3733 : (mixed_cdft%dlb_control%recv_info(j)%target_list(2, i) - 1), &
3734 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2): &
3735 48 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3)))
3736 : END IF
3737 :
3738 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, &
3739 : source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
3740 : request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 1), &
3741 8 : tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i))
3742 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, &
3743 : source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
3744 : request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 2), &
3745 8 : tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i) + 1)
3746 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, &
3747 : source=mixed_cdft%dlb_control%recv_info(j)%target_list(1, i), &
3748 : request=req_recv(3*(i - 1) + (j - 1)*offset_repl + 3), &
3749 8 : tag=mixed_cdft%dlb_control%recv_info(j)%target_list(3, i) + 2)
3750 16 : offset = offset + mixed_cdft%dlb_control%recv_info(j)%target_list(2, i)
3751 : END DO
3752 8 : DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info)
3753 : ELSE
3754 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)% &
3755 0 : buffs((SIZE(mixed_cdft%dlb_control%recv_info(j)%matrix_info) - 4)/3))
3756 0 : index = 6
3757 0 : DO i = 1, SIZE(mixed_cdft%dlb_control%recvbuff(j)%buffs)
3758 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3759 : weight(mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
3760 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
3761 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
3762 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
3763 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
3764 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
3765 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3766 : cavity(mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
3767 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
3768 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
3769 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
3770 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
3771 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
3772 : ALLOCATE (mixed_cdft%dlb_control%recvbuff(j)%buffs(i)% &
3773 : gradients(3*natom, mixed_cdft%dlb_control%recv_info(j)%matrix_info(index): &
3774 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(index + 1), &
3775 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(1): &
3776 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(2), &
3777 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(3): &
3778 0 : mixed_cdft%dlb_control%recv_info(j)%matrix_info(4)))
3779 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%cavity, &
3780 : source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
3781 0 : request=req_recv(offset_repl), tag=1)
3782 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%weight, &
3783 : source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
3784 0 : request=req_recv(offset_repl + 1), tag=2)
3785 : CALL force_env%para_env%irecv(msgout=mixed_cdft%dlb_control%recvbuff(j)%buffs(i)%gradients, &
3786 : source=mixed_cdft%dlb_control%recv_info(j)%matrix_info(index - 1), &
3787 0 : request=req_recv(offset_repl + 2), tag=3)
3788 0 : index = index + 3
3789 0 : offset_repl = offset_repl + 3
3790 : END DO
3791 0 : DEALLOCATE (mixed_cdft%dlb_control%recv_info(j)%matrix_info)
3792 : END IF
3793 : END IF
3794 : END DO
3795 : END IF
3796 : END IF
3797 36 : cutoffs => cdft_control%becke_control%cutoffs
3798 36 : should_communicate = .FALSE.
3799 144 : DO i = 1, 3
3800 144 : cell_v(i) = cell%hmat(i, i)
3801 : END DO
3802 76 : DO iwork = my_work, 1, -1
3803 40 : IF (iwork == 2) THEN
3804 4 : IF (.NOT. mixed_cdft%is_special) THEN
3805 4 : cavity => mixed_cdft%dlb_control%cavity
3806 4 : weight => mixed_cdft%dlb_control%weight
3807 4 : gradients => mixed_cdft%dlb_control%gradients
3808 4 : ALLOCATE (completed(2, 3), nsent(2, 3))
3809 : ELSE
3810 0 : my_special_work = SIZE(mixed_cdft%dlb_control%sendbuff)
3811 0 : ALLOCATE (completed(2, 3*my_special_work), nsent(2, 3*my_special_work))
3812 : END IF
3813 4 : completed = .FALSE.
3814 40 : nsent = 0
3815 : ELSE
3816 36 : IF (.NOT. mixed_cdft%is_special) THEN
3817 36 : weight => mixed_cdft%weight
3818 36 : cavity => mixed_cdft%cavity
3819 36 : gradients => cdft_control%group(1)%gradients
3820 : ELSE
3821 0 : my_special_work = SIZE(mixed_cdft%dest_list)
3822 : END IF
3823 : END IF
3824 116 : DO ispecial = 1, my_special_work
3825 40 : nwork = 0
3826 40 : IF (mixed_cdft%is_special) THEN
3827 0 : IF (iwork == 1) THEN
3828 0 : weight => mixed_cdft%sendbuff(ispecial)%weight
3829 0 : cavity => mixed_cdft%sendbuff(ispecial)%cavity
3830 0 : gradients => mixed_cdft%sendbuff(ispecial)%gradients
3831 : ELSE
3832 0 : weight => mixed_cdft%dlb_control%sendbuff(ispecial)%weight
3833 0 : cavity => mixed_cdft%dlb_control%sendbuff(ispecial)%cavity
3834 0 : gradients => mixed_cdft%dlb_control%sendbuff(ispecial)%gradients
3835 : END IF
3836 : END IF
3837 1021 : DO k = LBOUND(weight, 1), UBOUND(weight, 1)
3838 901 : IF (mixed_cdft%dlb .AND. mixed_cdft%is_pencil .AND. .NOT. mixed_cdft%is_special) THEN
3839 0 : IF (mixed_cdft%dlb_control%send_work) THEN
3840 0 : IF (k >= mixed_cdft%dlb_control%distributed(1) .AND. &
3841 : k <= mixed_cdft%dlb_control%distributed(2)) THEN
3842 : CYCLE
3843 : END IF
3844 : END IF
3845 : END IF
3846 41952 : DO j = LBOUND(weight, 2), UBOUND(weight, 2)
3847 39209 : IF (mixed_cdft%dlb .AND. .NOT. mixed_cdft%is_pencil .AND. .NOT. mixed_cdft%is_special) THEN
3848 6400 : IF (mixed_cdft%dlb_control%send_work) THEN
3849 3120 : IF (j >= mixed_cdft%dlb_control%distributed(1) .AND. &
3850 : j <= mixed_cdft%dlb_control%distributed(2)) THEN
3851 : CYCLE
3852 : END IF
3853 : END IF
3854 : END IF
3855 : ! Check if any of the buffers have become available for deallocation
3856 39209 : IF (should_communicate) THEN
3857 108 : DO icomm = 1, SIZE(nsent, 2)
3858 270 : DO jcomm = 1, SIZE(nsent, 1)
3859 162 : IF (nsent(jcomm, icomm) == 1) CYCLE
3860 55 : completed(jcomm, icomm) = req_send(jcomm, icomm)%test()
3861 55 : IF (completed(jcomm, icomm)) THEN
3862 24 : nsent(jcomm, icomm) = nsent(jcomm, icomm) + 1
3863 24 : nsent_total = nsent_total + 1
3864 24 : IF (nsent_total == SIZE(nsent, 1)*SIZE(nsent, 2)) should_communicate = .FALSE.
3865 : END IF
3866 187 : IF (ALL(completed(:, icomm))) THEN
3867 12 : IF (MODULO(icomm, 3) == 1) THEN
3868 4 : IF (.NOT. mixed_cdft%is_special) THEN
3869 4 : DEALLOCATE (mixed_cdft%dlb_control%cavity)
3870 : ELSE
3871 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%cavity)
3872 : END IF
3873 8 : ELSE IF (MODULO(icomm, 3) == 2) THEN
3874 4 : IF (.NOT. mixed_cdft%is_special) THEN
3875 4 : DEALLOCATE (mixed_cdft%dlb_control%weight)
3876 : ELSE
3877 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%weight)
3878 : END IF
3879 : ELSE
3880 4 : IF (.NOT. mixed_cdft%is_special) THEN
3881 4 : DEALLOCATE (mixed_cdft%dlb_control%gradients)
3882 : ELSE
3883 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff((icomm - 1)/3 + 1)%gradients)
3884 : END IF
3885 : END IF
3886 : END IF
3887 : END DO
3888 : END DO
3889 : END IF
3890 : ! Poll to prevent starvation
3891 39209 : IF (ASSOCIATED(req_recv)) THEN
3892 6400 : completed_recv = mp_testall(req_recv)
3893 : END IF
3894 : !
3895 1926389 : DO i = LBOUND(weight, 3), UBOUND(weight, 3)
3896 1807861 : IF (cdft_control%becke_control%cavity_confine) THEN
3897 1716736 : IF (cavity(k, j, i) < cdft_control%becke_control%eps_cavity) CYCLE
3898 : END IF
3899 988401 : grid_p(1) = k*dr(1) + shift(1)
3900 988401 : grid_p(2) = j*dr(2) + shift(2)
3901 988401 : grid_p(3) = i*dr(3) + shift(3)
3902 988401 : nskipped = 0
3903 2965203 : cell_functions = 1.0_dp
3904 988401 : skip_me = .FALSE.
3905 988401 : IF (store_vectors) distances = 0.0_dp
3906 988401 : IF (in_memory) THEN
3907 675116 : d_sum_Pm_dR = 0.0_dp
3908 675116 : d_sum_const_dR = 0.0_dp
3909 675116 : dP_i_dRi = 0.0_dp
3910 : END IF
3911 2554568 : DO iatom = 1, natom
3912 1976802 : IF (skip_me(iatom)) THEN
3913 65541 : cell_functions(iatom) = 0.0_dp
3914 65541 : IF (cdft_control%becke_control%should_skip) THEN
3915 37642 : IF (is_constraint(iatom)) nskipped = nskipped + 1
3916 37642 : IF (nskipped == cdft_control%natoms) THEN
3917 0 : IF (in_memory) THEN
3918 0 : IF (cdft_control%becke_control%cavity_confine) THEN
3919 0 : cavity(k, j, i) = 0.0_dp
3920 : END IF
3921 : END IF
3922 : EXIT
3923 : END IF
3924 : END IF
3925 : CYCLE
3926 : END IF
3927 1911261 : IF (store_vectors) THEN
3928 1911261 : IF (distances(iatom) == 0.0_dp) THEN
3929 6889176 : r = position_vecs(:, iatom)
3930 6889176 : dist_vec = (r - grid_p) - ANINT((r - grid_p)/cell_v)*cell_v
3931 6889176 : dist1 = NORM2(dist_vec)
3932 6889176 : distance_vecs(:, iatom) = dist_vec
3933 1722294 : distances(iatom) = dist1
3934 : ELSE
3935 755868 : dist_vec = distance_vecs(:, iatom)
3936 : dist1 = distances(iatom)
3937 : END IF
3938 : ELSE
3939 0 : r = particle_set(iatom)%r
3940 0 : DO ip = 1, 3
3941 0 : r(ip) = MODULO(r(ip), cell%hmat(ip, ip)) - cell%hmat(ip, ip)/2._dp
3942 : END DO
3943 0 : dist_vec = (r - grid_p) - ANINT((r - grid_p)/cell_v)*cell_v
3944 0 : dist1 = NORM2(dist_vec)
3945 : END IF
3946 2489027 : IF (dist1 <= cutoffs(iatom)) THEN
3947 509029 : IF (in_memory) THEN
3948 : IF (dist1 <= th) dist1 = th
3949 1184700 : dr_i_dR(:) = dist_vec(:)/dist1
3950 : END IF
3951 1527087 : DO jatom = 1, natom
3952 1527087 : IF (jatom /= iatom) THEN
3953 509029 : IF (jatom < iatom) THEN
3954 254521 : IF (.NOT. skip_me(jatom)) CYCLE
3955 : END IF
3956 320062 : IF (store_vectors) THEN
3957 320062 : IF (distances(jatom) == 0.0_dp) THEN
3958 1018032 : r1 = position_vecs(:, jatom)
3959 1018032 : dist_vec = (r1 - grid_p) - ANINT((r1 - grid_p)/cell_v)*cell_v
3960 1018032 : dist2 = NORM2(dist_vec)
3961 1018032 : distance_vecs(:, jatom) = dist_vec
3962 254508 : distances(jatom) = dist2
3963 : ELSE
3964 262216 : dist_vec = distance_vecs(:, jatom)
3965 : dist2 = distances(jatom)
3966 : END IF
3967 : ELSE
3968 0 : r1 = particle_set(jatom)%r
3969 0 : DO ip = 1, 3
3970 0 : r1(ip) = MODULO(r1(ip), cell%hmat(ip, ip)) - cell%hmat(ip, ip)/2._dp
3971 : END DO
3972 0 : dist_vec = (r1 - grid_p) - ANINT((r1 - grid_p)/cell_v)*cell_v
3973 0 : dist2 = NORM2(dist_vec)
3974 : END IF
3975 320062 : IF (in_memory) THEN
3976 191129 : IF (store_vectors) THEN
3977 764516 : dr1_r2 = pair_dist_vecs(:, iatom, jatom)
3978 : ELSE
3979 0 : dr1_r2 = (r - r1) - ANINT((r - r1)/cell_v)*cell_v
3980 : END IF
3981 : IF (dist2 <= th) dist2 = th
3982 191129 : tmp_const = (R12(iatom, jatom)**3)
3983 764516 : dr_ij_dR(:) = dr1_r2(:)/tmp_const
3984 : !derivativ w.r.t. Rj
3985 764516 : dr_j_dR = dist_vec(:)/dist2
3986 764516 : dmy_dR_j(:) = -(dr_j_dR(:)/R12(iatom, jatom) - (dist1 - dist2)*dr_ij_dR(:))
3987 : !derivativ w.r.t. Ri
3988 764516 : dmy_dR_i(:) = dr_i_dR(:)/R12(iatom, jatom) - (dist1 - dist2)*dr_ij_dR(:)
3989 : END IF
3990 320062 : my1 = (dist1 - dist2)/R12(iatom, jatom)
3991 320062 : IF (cdft_control%becke_control%adjust) THEN
3992 166839 : my1_homo = my1
3993 : my1 = my1 + &
3994 166839 : cdft_control%becke_control%aij(iatom, jatom)*(1.0_dp - my1**2)
3995 : END IF
3996 320062 : myexp = 1.5_dp*my1 - 0.5_dp*my1**3
3997 320062 : IF (in_memory) THEN
3998 191129 : dmyexp = 1.5_dp - 1.5_dp*my1**2
3999 : tmp_const = (1.5_dp**2)*dmyexp*(1 - myexp**2)* &
4000 191129 : (1.0_dp - ((1.5_dp*myexp - 0.5_dp*(myexp**3))**2))
4001 :
4002 764516 : ds_dR_i(:) = -0.5_dp*tmp_const*dmy_dR_i(:)
4003 764516 : ds_dR_j(:) = -0.5_dp*tmp_const*dmy_dR_j(:)
4004 191129 : IF (cdft_control%becke_control%adjust) THEN
4005 102514 : tmp_const = 1.0_dp - 2.0_dp*my1_homo*cdft_control%becke_control%aij(iatom, jatom)
4006 410056 : ds_dR_i(:) = ds_dR_i(:)*tmp_const
4007 410056 : ds_dR_j(:) = ds_dR_j(:)*tmp_const
4008 : END IF
4009 : END IF
4010 320062 : myexp = 1.5_dp*myexp - 0.5_dp*myexp**3
4011 320062 : myexp = 1.5_dp*myexp - 0.5_dp*myexp**3
4012 320062 : tmp_const = 0.5_dp*(1.0_dp - myexp)
4013 320062 : cell_functions(iatom) = cell_functions(iatom)*tmp_const
4014 320062 : IF (in_memory) THEN
4015 191129 : IF (ABS(tmp_const) <= th) tmp_const = tmp_const + th
4016 764516 : dP_i_dRi(:, iatom) = dP_i_dRi(:, iatom) + ds_dR_i(:)/tmp_const
4017 764516 : dP_i_dRj(:, iatom, jatom) = ds_dR_j(:)/tmp_const
4018 : END IF
4019 :
4020 320062 : IF (dist2 <= cutoffs(jatom)) THEN
4021 188967 : tmp_const = 0.5_dp*(1.0_dp + myexp)
4022 188967 : cell_functions(jatom) = cell_functions(jatom)*tmp_const
4023 188967 : IF (in_memory) THEN
4024 105046 : IF (ABS(tmp_const) <= th) tmp_const = tmp_const + th
4025 420184 : dP_i_dRj(:, jatom, iatom) = -ds_dR_i(:)/tmp_const
4026 420184 : dP_i_dRi(:, jatom) = dP_i_dRi(:, jatom) - ds_dR_j(:)/tmp_const
4027 : END IF
4028 : ELSE
4029 131095 : skip_me(jatom) = .TRUE.
4030 : END IF
4031 : END IF
4032 : END DO
4033 509029 : IF (in_memory) THEN
4034 1184700 : dP_i_dRi(:, iatom) = cell_functions(iatom)*dP_i_dRi(:, iatom)
4035 1184700 : d_sum_Pm_dR(:, iatom) = d_sum_Pm_dR(:, iatom) + dP_i_dRi(:, iatom)
4036 296175 : IF (is_constraint(iatom)) THEN
4037 : d_sum_const_dR(:, iatom) = d_sum_const_dR(:, iatom) + dP_i_dRi(:, iatom)* &
4038 1184700 : coefficients(iatom)
4039 : END IF
4040 888525 : DO jatom = 1, natom
4041 888525 : IF (jatom /= iatom) THEN
4042 296175 : IF (jatom < iatom) THEN
4043 148094 : IF (.NOT. skip_me(jatom)) THEN
4044 420184 : dP_i_dRj(:, iatom, jatom) = cell_functions(iatom)*dP_i_dRj(:, iatom, jatom)
4045 420184 : d_sum_Pm_dR(:, jatom) = d_sum_Pm_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)
4046 105046 : IF (is_constraint(iatom)) THEN
4047 : d_sum_const_dR(:, jatom) = d_sum_const_dR(:, jatom) + &
4048 : dP_i_dRj(:, iatom, jatom)* &
4049 420184 : coefficients(iatom)
4050 : END IF
4051 : CYCLE
4052 : END IF
4053 : END IF
4054 764516 : dP_i_dRj(:, iatom, jatom) = cell_functions(iatom)*dP_i_dRj(:, iatom, jatom)
4055 764516 : d_sum_Pm_dR(:, jatom) = d_sum_Pm_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)
4056 191129 : IF (is_constraint(iatom)) THEN
4057 : d_sum_const_dR(:, jatom) = d_sum_const_dR(:, jatom) + dP_i_dRj(:, iatom, jatom)* &
4058 764516 : coefficients(iatom)
4059 : END IF
4060 : END IF
4061 : END DO
4062 : END IF
4063 : ELSE
4064 1402232 : cell_functions(iatom) = 0.0_dp
4065 1402232 : skip_me(iatom) = .TRUE.
4066 1402232 : IF (cdft_control%becke_control%should_skip) THEN
4067 858928 : IF (is_constraint(iatom)) nskipped = nskipped + 1
4068 858928 : IF (nskipped == cdft_control%natoms) THEN
4069 410635 : IF (in_memory) THEN
4070 252800 : IF (cdft_control%becke_control%cavity_confine) THEN
4071 252800 : cavity(k, j, i) = 0.0_dp
4072 : END IF
4073 : END IF
4074 : EXIT
4075 : END IF
4076 : END IF
4077 : END IF
4078 : END DO
4079 988401 : IF (nskipped == cdft_control%natoms) CYCLE
4080 : sum_cell_f_constr = 0.0_dp
4081 1733298 : DO ip = 1, cdft_control%natoms
4082 : sum_cell_f_constr = sum_cell_f_constr + cell_functions(catom(ip))* &
4083 1733298 : cdft_control%group(1)%coeff(ip)
4084 : END DO
4085 577766 : sum_cell_f_all = 0.0_dp
4086 577766 : nwork = nwork + 1
4087 1733298 : DO ip = 1, natom
4088 1733298 : sum_cell_f_all = sum_cell_f_all + cell_functions(ip)
4089 : END DO
4090 577766 : IF (in_memory) THEN
4091 1266948 : DO iatom = 1, natom
4092 1266948 : IF (ABS(sum_cell_f_all) > 0.0_dp) THEN
4093 : gradients(3*(iatom - 1) + 1:3*(iatom - 1) + 3, k, j, i) = &
4094 : d_sum_const_dR(:, iatom)/sum_cell_f_all - sum_cell_f_constr* &
4095 1529032 : d_sum_Pm_dR(:, iatom)/(sum_cell_f_all**2)
4096 : END IF
4097 : END DO
4098 : END IF
4099 616975 : IF (ABS(sum_cell_f_all) > 0.000001) THEN
4100 320062 : weight(k, j, i) = sum_cell_f_constr/sum_cell_f_all
4101 : END IF
4102 : END DO ! i
4103 : END DO ! j
4104 : END DO ! k
4105 : ! Load balancing: post send requests
4106 80 : IF (iwork == 2) THEN
4107 4 : IF (.NOT. mixed_cdft%is_special) THEN
4108 12 : DO i = 1, SIZE(req_send, 1)
4109 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%cavity, &
4110 : dest=mixed_cdft%dlb_control%my_dest_repl(i), &
4111 : request=req_send(i, 1), &
4112 8 : tag=mixed_cdft%dlb_control%dest_tags_repl(i))
4113 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%weight, &
4114 : dest=mixed_cdft%dlb_control%my_dest_repl(i), &
4115 : request=req_send(i, 2), &
4116 8 : tag=mixed_cdft%dlb_control%dest_tags_repl(i) + 1)
4117 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%gradients, &
4118 : dest=mixed_cdft%dlb_control%my_dest_repl(i), &
4119 : request=req_send(i, 3), &
4120 12 : tag=mixed_cdft%dlb_control%dest_tags_repl(i) + 2)
4121 : END DO
4122 : should_communicate = .TRUE.
4123 : nsent_total = 0
4124 : ELSE
4125 0 : DO i = 1, SIZE(req_send, 1)
4126 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%cavity, &
4127 : dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
4128 0 : request=req_send(i, 3*(ispecial - 1) + 1), tag=1)
4129 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%weight, &
4130 : dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
4131 0 : request=req_send(i, 3*(ispecial - 1) + 2), tag=2)
4132 : CALL force_env%para_env%isend(msgin=mixed_cdft%dlb_control%sendbuff(ispecial)%gradients, &
4133 : dest=mixed_cdft%dlb_control%sendbuff(ispecial)%rank(i), &
4134 0 : request=req_send(i, 3*(ispecial - 1) + 3), tag=3)
4135 : END DO
4136 0 : IF (ispecial == my_special_work) THEN
4137 0 : should_communicate = .TRUE.
4138 0 : nsent_total = 0
4139 : END IF
4140 : END IF
4141 4 : work(mixed_cdft%dlb_control%my_source + 1) = work(mixed_cdft%dlb_control%my_source + 1) + nwork
4142 4 : work_dlb(force_env%para_env%mepos + 1) = work_dlb(force_env%para_env%mepos + 1) + nwork
4143 : ELSE
4144 36 : IF (mixed_cdft%dlb) work(force_env%para_env%mepos + 1) = work(force_env%para_env%mepos + 1) + nwork
4145 36 : IF (mixed_cdft%dlb) work_dlb(force_env%para_env%mepos + 1) = work_dlb(force_env%para_env%mepos + 1) + nwork
4146 : END IF
4147 : END DO ! ispecial
4148 : END DO ! iwork
4149 : ! Load balancing: wait for communication and deallocate sending buffers
4150 36 : IF (mixed_cdft%dlb) THEN
4151 16 : IF (mixed_cdft%dlb_control%recv_work .AND. &
4152 : ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
4153 48 : ALLOCATE (req_total(SIZE(req_recv) + SIZE(req_send, 1)*SIZE(req_send, 2)))
4154 4 : index = SIZE(req_recv)
4155 28 : req_total(1:index) = req_recv
4156 16 : DO i = 1, SIZE(req_send, 2)
4157 40 : DO j = 1, SIZE(req_send, 1)
4158 24 : index = index + 1
4159 36 : req_total(index) = req_send(j, i)
4160 : END DO
4161 : END DO
4162 4 : CALL mp_waitall(req_total)
4163 4 : DEALLOCATE (req_total)
4164 4 : IF (ASSOCIATED(mixed_cdft%dlb_control%cavity)) THEN
4165 0 : DEALLOCATE (mixed_cdft%dlb_control%cavity)
4166 : END IF
4167 4 : IF (ASSOCIATED(mixed_cdft%dlb_control%weight)) THEN
4168 0 : DEALLOCATE (mixed_cdft%dlb_control%weight)
4169 : END IF
4170 4 : IF (ASSOCIATED(mixed_cdft%dlb_control%gradients)) THEN
4171 0 : DEALLOCATE (mixed_cdft%dlb_control%gradients)
4172 : END IF
4173 4 : IF (mixed_cdft%is_special) THEN
4174 0 : DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
4175 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%cavity)) THEN
4176 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity)
4177 : END IF
4178 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%weight)) THEN
4179 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight)
4180 : END IF
4181 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%gradients)) THEN
4182 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients)
4183 : END IF
4184 : END DO
4185 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff)
4186 : END IF
4187 4 : DEALLOCATE (req_send, req_recv)
4188 4 : ELSE IF (mixed_cdft%dlb_control%recv_work) THEN
4189 0 : IF (should_communicate) THEN
4190 0 : CALL mp_waitall(req_send)
4191 : END IF
4192 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%cavity)) THEN
4193 0 : DEALLOCATE (mixed_cdft%dlb_control%cavity)
4194 : END IF
4195 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%weight)) THEN
4196 0 : DEALLOCATE (mixed_cdft%dlb_control%weight)
4197 : END IF
4198 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%gradients)) THEN
4199 0 : DEALLOCATE (mixed_cdft%dlb_control%gradients)
4200 : END IF
4201 0 : IF (mixed_cdft%is_special) THEN
4202 0 : DO j = 1, SIZE(mixed_cdft%dlb_control%sendbuff)
4203 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%cavity)) THEN
4204 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%cavity)
4205 : END IF
4206 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%weight)) THEN
4207 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%weight)
4208 : END IF
4209 0 : IF (ASSOCIATED(mixed_cdft%dlb_control%sendbuff(j)%gradients)) THEN
4210 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff(j)%gradients)
4211 : END IF
4212 : END DO
4213 0 : DEALLOCATE (mixed_cdft%dlb_control%sendbuff)
4214 : END IF
4215 0 : DEALLOCATE (req_send)
4216 8 : ELSE IF (ANY(mixed_cdft%dlb_control%recv_work_repl)) THEN
4217 4 : CALL mp_waitall(req_recv)
4218 4 : DEALLOCATE (req_recv)
4219 : END IF
4220 : END IF
4221 36 : IF (mixed_cdft%dlb) THEN
4222 40 : CALL force_env%para_env%sum(work)
4223 40 : CALL force_env%para_env%sum(work_dlb)
4224 8 : IF (.NOT. ASSOCIATED(mixed_cdft%dlb_control%prediction_error)) THEN
4225 12 : ALLOCATE (mixed_cdft%dlb_control%prediction_error(force_env%para_env%num_pe))
4226 : END IF
4227 40 : mixed_cdft%dlb_control%prediction_error = mixed_cdft%dlb_control%expected_work - work
4228 : IF (debug_this_module .AND. iounit > 0) THEN
4229 : DO i = 1, SIZE(work, 1)
4230 : WRITE (iounit, '(A,I10,I10,I10)') &
4231 : 'Work', work(i), work_dlb(i), mixed_cdft%dlb_control%expected_work(i)
4232 : END DO
4233 : END IF
4234 8 : DEALLOCATE (work, work_dlb, mixed_cdft%dlb_control%expected_work)
4235 : END IF
4236 36 : NULLIFY (gradients, weight, cavity)
4237 36 : IF (ALLOCATED(coefficients)) THEN
4238 36 : DEALLOCATE (coefficients)
4239 : END IF
4240 36 : IF (in_memory) THEN
4241 24 : DEALLOCATE (ds_dR_j)
4242 24 : DEALLOCATE (ds_dR_i)
4243 24 : DEALLOCATE (d_sum_Pm_dR)
4244 24 : DEALLOCATE (d_sum_const_dR)
4245 24 : DEALLOCATE (dP_i_dRj)
4246 24 : DEALLOCATE (dP_i_dRi)
4247 24 : NULLIFY (gradients)
4248 24 : IF (store_vectors) THEN
4249 24 : DEALLOCATE (pair_dist_vecs)
4250 : END IF
4251 : END IF
4252 36 : NULLIFY (cutoffs)
4253 36 : IF (ALLOCATED(is_constraint)) THEN
4254 36 : DEALLOCATE (is_constraint)
4255 : END IF
4256 36 : DEALLOCATE (catom)
4257 36 : DEALLOCATE (R12)
4258 36 : DEALLOCATE (cell_functions)
4259 36 : DEALLOCATE (skip_me)
4260 36 : IF (ALLOCATED(completed)) THEN
4261 4 : DEALLOCATE (completed)
4262 : END IF
4263 36 : IF (ASSOCIATED(nsent)) THEN
4264 4 : DEALLOCATE (nsent)
4265 : END IF
4266 36 : IF (store_vectors) THEN
4267 36 : DEALLOCATE (distances)
4268 36 : DEALLOCATE (distance_vecs)
4269 36 : DEALLOCATE (position_vecs)
4270 : END IF
4271 36 : IF (ASSOCIATED(req_send)) THEN
4272 0 : DEALLOCATE (req_send)
4273 : END IF
4274 36 : IF (ASSOCIATED(req_recv)) THEN
4275 0 : DEALLOCATE (req_recv)
4276 : END IF
4277 : CALL cp_print_key_finished_output(iounit, logger, force_env_section, &
4278 36 : "MIXED%MIXED_CDFT%PRINT%PROGRAM_RUN_INFO")
4279 36 : CALL timestop(handle)
4280 :
4281 72 : END SUBROUTINE mixed_becke_constraint_low
4282 :
4283 0 : END MODULE mixed_cdft_methods
|