Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : MODULE optimize_embedding_potential
9 :
10 : USE atomic_kind_types, ONLY: atomic_kind_type,&
11 : get_atomic_kind,&
12 : get_atomic_kind_set
13 : USE cell_types, ONLY: cell_type
14 : USE cp_blacs_env, ONLY: cp_blacs_env_create,&
15 : cp_blacs_env_release,&
16 : cp_blacs_env_type
17 : USE cp_control_types, ONLY: dft_control_type
18 : USE cp_dbcsr_api, ONLY: dbcsr_p_type
19 : USE cp_dbcsr_operations, ONLY: copy_dbcsr_to_fm,&
20 : dbcsr_deallocate_matrix_set
21 : USE cp_files, ONLY: close_file,&
22 : open_file
23 : USE cp_fm_basic_linalg, ONLY: cp_fm_column_scale,&
24 : cp_fm_scale,&
25 : cp_fm_scale_and_add,&
26 : cp_fm_trace
27 : USE cp_fm_diag, ONLY: choose_eigv_solver
28 : USE cp_fm_struct, ONLY: cp_fm_struct_create,&
29 : cp_fm_struct_release,&
30 : cp_fm_struct_type
31 : USE cp_fm_types, ONLY: &
32 : cp_fm_copy_general, cp_fm_create, cp_fm_get_element, cp_fm_get_info, cp_fm_release, &
33 : cp_fm_set_all, cp_fm_to_fm, cp_fm_to_fm_submat, cp_fm_type, cp_fm_write_unformatted
34 : USE cp_log_handling, ONLY: cp_get_default_logger,&
35 : cp_logger_type
36 : USE cp_output_handling, ONLY: cp_p_file,&
37 : cp_print_key_finished_output,&
38 : cp_print_key_should_output,&
39 : cp_print_key_unit_nr
40 : USE cp_realspace_grid_cube, ONLY: cp_cube_to_pw,&
41 : cp_pw_to_cube,&
42 : cp_pw_to_simple_volumetric
43 : USE embed_types, ONLY: opt_embed_pot_type
44 : USE force_env_types, ONLY: force_env_type
45 : USE input_constants, ONLY: &
46 : embed_diff, embed_fa, embed_grid_angstrom, embed_grid_bohr, embed_level_shift, embed_none, &
47 : embed_quasi_newton, embed_resp, embed_steep_desc
48 : USE input_section_types, ONLY: section_get_ival,&
49 : section_get_ivals,&
50 : section_get_rval,&
51 : section_vals_get_subs_vals,&
52 : section_vals_type,&
53 : section_vals_val_get
54 : USE kinds, ONLY: default_path_length,&
55 : dp
56 : USE lri_environment_types, ONLY: lri_kind_type
57 : USE mathconstants, ONLY: pi
58 : USE message_passing, ONLY: mp_para_env_type
59 : USE mixed_environment_utils, ONLY: get_subsys_map_index
60 : USE parallel_gemm_api, ONLY: parallel_gemm
61 : USE particle_list_types, ONLY: particle_list_type
62 : USE particle_types, ONLY: particle_type
63 : USE pw_env_types, ONLY: pw_env_get,&
64 : pw_env_type
65 : USE pw_methods, ONLY: &
66 : pw_axpy, pw_copy, pw_derive, pw_dr2, pw_integral_ab, pw_integrate_function, pw_scale, &
67 : pw_transfer, pw_zero
68 : USE pw_poisson_methods, ONLY: pw_poisson_solve
69 : USE pw_poisson_types, ONLY: pw_poisson_type
70 : USE pw_pool_types, ONLY: pw_pool_type
71 : USE pw_types, ONLY: pw_c1d_gs_type,&
72 : pw_r3d_rs_type
73 : USE qs_collocate_density, ONLY: calculate_rho_resp_all,&
74 : calculate_wavefunction,&
75 : collocate_function
76 : USE qs_environment_types, ONLY: get_qs_env,&
77 : qs_environment_type,&
78 : set_qs_env
79 : USE qs_integrate_potential_single, ONLY: integrate_v_rspace_one_center
80 : USE qs_kind_types, ONLY: get_qs_kind,&
81 : qs_kind_type
82 : USE qs_kinetic, ONLY: build_kinetic_matrix
83 : USE qs_ks_types, ONLY: qs_ks_env_type
84 : USE qs_mo_types, ONLY: get_mo_set,&
85 : mo_set_type
86 : USE qs_neighbor_list_types, ONLY: neighbor_list_set_p_type
87 : USE qs_rho_types, ONLY: qs_rho_get,&
88 : qs_rho_type
89 : USE qs_subsys_types, ONLY: qs_subsys_get,&
90 : qs_subsys_type
91 : USE xc, ONLY: smooth_cutoff
92 : USE xc_rho_cflags_types, ONLY: xc_rho_cflags_setall,&
93 : xc_rho_cflags_type
94 : USE xc_rho_set_types, ONLY: xc_rho_set_create,&
95 : xc_rho_set_release,&
96 : xc_rho_set_type,&
97 : xc_rho_set_update
98 : #include "./base/base_uses.f90"
99 :
100 : IMPLICIT NONE
101 :
102 : PRIVATE
103 :
104 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'optimize_embedding_potential'
105 :
106 : PUBLIC :: prepare_embed_opt, init_embed_pot, release_opt_embed, calculate_embed_pot_grad, &
107 : opt_embed_step, print_rho_diff, step_control, max_dens_diff, print_emb_opt_info, &
108 : conv_check_embed, make_subsys_embed_pot, print_embed_restart, find_aux_dimen, &
109 : read_embed_pot, understand_spin_states, given_embed_pot, print_rho_spin_diff, &
110 : print_pot_simple_grid, get_prev_density, get_max_subsys_diff, Coulomb_guess
111 :
112 : CONTAINS
113 :
114 : ! **************************************************************************************************
115 : !> \brief Find out whether we need to swap alpha- and beta- spind densities in the second subsystem
116 : !> \brief It's only needed because by default alpha-spins go first in a subsystem.
117 : !> \brief By swapping we impose the constraint:
118 : !> \brief rho_1(alpha) + rho_2(alpha) = rho_total(alpha)
119 : !> \brief rho_1(beta) + rho_2(beta) = rho_total(beta)
120 : !> \param force_env ...
121 : !> \param ref_subsys_number ...
122 : !> \param change_spin ...
123 : !> \param open_shell_embed ...
124 : !> \param all_nspins ...
125 : !> \return ...
126 : !> \author Vladimir Rybkin
127 : ! **************************************************************************************************
128 24 : SUBROUTINE understand_spin_states(force_env, ref_subsys_number, change_spin, open_shell_embed, all_nspins)
129 : TYPE(force_env_type), POINTER :: force_env
130 : INTEGER :: ref_subsys_number
131 : LOGICAL :: change_spin, open_shell_embed
132 : INTEGER, ALLOCATABLE, DIMENSION(:) :: all_nspins
133 :
134 : INTEGER :: i_force_eval, nspins, sub_spin_1, &
135 : sub_spin_2, total_spin
136 : INTEGER, DIMENSION(2) :: nelectron_spin
137 : INTEGER, DIMENSION(2, 3) :: all_spins
138 : TYPE(dft_control_type), POINTER :: dft_control
139 :
140 24 : change_spin = .FALSE.
141 24 : open_shell_embed = .FALSE.
142 72 : ALLOCATE (all_nspins(ref_subsys_number))
143 24 : IF (ref_subsys_number .EQ. 3) THEN
144 24 : all_spins = 0
145 96 : DO i_force_eval = 1, ref_subsys_number
146 : CALL get_qs_env(qs_env=force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
147 72 : nelectron_spin=nelectron_spin, dft_control=dft_control)
148 216 : all_spins(:, i_force_eval) = nelectron_spin
149 72 : nspins = dft_control%nspins
150 96 : all_nspins(i_force_eval) = nspins
151 : END DO
152 :
153 : ! Find out whether we need a spin-dependend embedding potential
154 24 : IF (.NOT. ((all_nspins(1) .EQ. 1) .AND. (all_nspins(2) .EQ. 1) .AND. (all_nspins(3) .EQ. 1))) &
155 12 : open_shell_embed = .TRUE.
156 :
157 : ! If it's open shell, we need to check spin states
158 24 : IF (open_shell_embed) THEN
159 :
160 12 : IF (all_nspins(3) .EQ. 1) THEN
161 : total_spin = 0
162 : ELSE
163 10 : total_spin = all_spins(1, 3) - all_spins(2, 3)
164 : END IF
165 12 : IF (all_nspins(1) .EQ. 1) THEN
166 : sub_spin_1 = 0
167 : ELSE
168 12 : sub_spin_1 = all_spins(1, 1) - all_spins(2, 1)
169 : END IF
170 12 : IF (all_nspins(2) .EQ. 1) THEN
171 : sub_spin_2 = 0
172 : ELSE
173 12 : sub_spin_2 = all_spins(1, 2) - all_spins(2, 2)
174 : END IF
175 12 : IF ((sub_spin_1 + sub_spin_2) .EQ. total_spin) THEN
176 10 : change_spin = .FALSE.
177 : ELSE
178 2 : IF (ABS(sub_spin_1 - sub_spin_2) .EQ. total_spin) THEN
179 2 : change_spin = .TRUE.
180 : ELSE
181 0 : CPABORT("Spin states of subsystems are not compatible.")
182 : END IF
183 : END IF
184 :
185 : END IF ! not open_shell
186 : ELSE
187 0 : CPABORT("Reference subsystem must be the third FORCE_EVAL.")
188 : END IF
189 :
190 24 : END SUBROUTINE understand_spin_states
191 :
192 : ! **************************************************************************************************
193 : !> \brief ...
194 : !> \param qs_env ...
195 : !> \param embed_pot ...
196 : !> \param add_const_pot ...
197 : !> \param Fermi_Amaldi ...
198 : !> \param const_pot ...
199 : !> \param open_shell_embed ...
200 : !> \param spin_embed_pot ...
201 : !> \param pot_diff ...
202 : !> \param Coulomb_guess ...
203 : !> \param grid_opt ...
204 : ! **************************************************************************************************
205 24 : SUBROUTINE init_embed_pot(qs_env, embed_pot, add_const_pot, Fermi_Amaldi, const_pot, open_shell_embed, &
206 : spin_embed_pot, pot_diff, Coulomb_guess, grid_opt)
207 : TYPE(qs_environment_type), POINTER :: qs_env
208 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot
209 : LOGICAL :: add_const_pot, Fermi_Amaldi
210 : TYPE(pw_r3d_rs_type), POINTER :: const_pot
211 : LOGICAL :: open_shell_embed
212 : TYPE(pw_r3d_rs_type), POINTER :: spin_embed_pot, pot_diff
213 : LOGICAL :: Coulomb_guess, grid_opt
214 :
215 : INTEGER :: nelectrons
216 : INTEGER, DIMENSION(2) :: nelectron_spin
217 : REAL(KIND=dp) :: factor
218 : TYPE(pw_env_type), POINTER :: pw_env
219 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
220 : TYPE(pw_r3d_rs_type), POINTER :: v_hartree_r_space
221 :
222 : ! Extract plane waves environment
223 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
224 : nelectron_spin=nelectron_spin, &
225 24 : v_hartree_rspace=v_hartree_r_space)
226 :
227 : ! Prepare plane-waves pool
228 24 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
229 :
230 : ! Create embedding potential and set to zero
231 : NULLIFY (embed_pot)
232 24 : ALLOCATE (embed_pot)
233 24 : CALL auxbas_pw_pool%create_pw(embed_pot)
234 24 : CALL pw_zero(embed_pot)
235 :
236 : ! Spin embedding potential if asked
237 24 : IF (open_shell_embed) THEN
238 : NULLIFY (spin_embed_pot)
239 12 : ALLOCATE (spin_embed_pot)
240 12 : CALL auxbas_pw_pool%create_pw(spin_embed_pot)
241 12 : CALL pw_zero(spin_embed_pot)
242 : END IF
243 :
244 : ! Coulomb guess/constant potential
245 24 : IF (Coulomb_guess) THEN
246 : NULLIFY (pot_diff)
247 2 : ALLOCATE (pot_diff)
248 2 : CALL auxbas_pw_pool%create_pw(pot_diff)
249 2 : CALL pw_zero(pot_diff)
250 : END IF
251 :
252 : ! Initialize constant part of the embedding potential
253 24 : IF (add_const_pot .AND. (.NOT. grid_opt)) THEN
254 : ! Now the constant potential is the Coulomb one
255 : NULLIFY (const_pot)
256 4 : ALLOCATE (const_pot)
257 4 : CALL auxbas_pw_pool%create_pw(const_pot)
258 4 : CALL pw_zero(const_pot)
259 : END IF
260 :
261 : ! Add Fermi-Amaldi potential if requested
262 24 : IF (Fermi_Amaldi) THEN
263 :
264 : ! Extract Hartree potential
265 6 : NULLIFY (v_hartree_r_space)
266 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, &
267 6 : v_hartree_rspace=v_hartree_r_space)
268 6 : CALL pw_copy(v_hartree_r_space, embed_pot)
269 :
270 : ! Calculate the number of electrons
271 6 : nelectrons = nelectron_spin(1) + nelectron_spin(2)
272 6 : factor = (REAL(nelectrons, dp) - 1.0_dp)/(REAL(nelectrons, dp))
273 :
274 : ! Scale the Hartree potential to get Fermi-Amaldi
275 6 : CALL pw_scale(embed_pot, a=factor)
276 :
277 : ! Copy Fermi-Amaldi to embedding potential for basis-based optimization
278 6 : IF (.NOT. grid_opt) CALL pw_copy(embed_pot, embed_pot)
279 :
280 : END IF
281 :
282 24 : END SUBROUTINE init_embed_pot
283 :
284 : ! **************************************************************************************************
285 : !> \brief Creates and allocates objects for optimization of embedding potential
286 : !> \param qs_env ...
287 : !> \param opt_embed ...
288 : !> \param opt_embed_section ...
289 : !> \author Vladimir Rybkin
290 : ! **************************************************************************************************
291 24 : SUBROUTINE prepare_embed_opt(qs_env, opt_embed, opt_embed_section)
292 : TYPE(qs_environment_type), POINTER :: qs_env
293 : TYPE(opt_embed_pot_type) :: opt_embed
294 : TYPE(section_vals_type), POINTER :: opt_embed_section
295 :
296 : INTEGER :: diff_size, i_dens, size_prev_dens
297 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
298 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
299 : TYPE(mp_para_env_type), POINTER :: para_env
300 : TYPE(pw_env_type), POINTER :: pw_env
301 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
302 :
303 : !TYPE(pw_env_type), POINTER :: pw_env
304 : !TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
305 :
306 : ! First, read the input
307 :
308 24 : CALL read_opt_embed_section(opt_embed, opt_embed_section)
309 :
310 : ! All these are needed for optimization in a finite Gaussian basis
311 24 : IF (.NOT. opt_embed%grid_opt) THEN
312 : ! Create blacs environment
313 : CALL get_qs_env(qs_env=qs_env, &
314 14 : para_env=para_env)
315 14 : NULLIFY (blacs_env)
316 14 : CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
317 :
318 : ! Reveal the dimension of the RI basis
319 14 : CALL find_aux_dimen(qs_env, opt_embed%dimen_aux)
320 :
321 : ! Prepare the object for integrals
322 14 : CALL make_lri_object(qs_env, opt_embed%lri)
323 :
324 : ! In case if spin embedding potential has to be optimized,
325 : ! the dimension of variational space is two times larger
326 14 : IF (opt_embed%open_shell_embed) THEN
327 6 : opt_embed%dimen_var_aux = 2*opt_embed%dimen_aux
328 : ELSE
329 8 : opt_embed%dimen_var_aux = opt_embed%dimen_aux
330 : END IF
331 :
332 : ! Allocate expansion coefficients and gradient
333 14 : NULLIFY (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, opt_embed%step, fm_struct)
334 :
335 14 : NULLIFY (opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, opt_embed%prev_step)
336 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
337 14 : nrow_global=opt_embed%dimen_var_aux, ncol_global=1)
338 : ALLOCATE (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, &
339 : opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, &
340 14 : opt_embed%step, opt_embed%prev_step)
341 14 : CALL cp_fm_create(opt_embed%embed_pot_grad, fm_struct, name="pot_grad")
342 14 : CALL cp_fm_create(opt_embed%embed_pot_coef, fm_struct, name="pot_coef")
343 14 : CALL cp_fm_create(opt_embed%prev_embed_pot_grad, fm_struct, name="prev_pot_grad")
344 14 : CALL cp_fm_create(opt_embed%prev_embed_pot_coef, fm_struct, name="prev_pot_coef")
345 14 : CALL cp_fm_create(opt_embed%step, fm_struct, name="step")
346 14 : CALL cp_fm_create(opt_embed%prev_step, fm_struct, name="prev_step")
347 :
348 14 : CALL cp_fm_struct_release(fm_struct)
349 14 : CALL cp_fm_set_all(opt_embed%embed_pot_grad, 0.0_dp)
350 14 : CALL cp_fm_set_all(opt_embed%prev_embed_pot_grad, 0.0_dp)
351 14 : CALL cp_fm_set_all(opt_embed%embed_pot_coef, 0.0_dp)
352 14 : CALL cp_fm_set_all(opt_embed%prev_embed_pot_coef, 0.0_dp)
353 14 : CALL cp_fm_set_all(opt_embed%step, 0.0_dp)
354 :
355 14 : CALL cp_fm_set_all(opt_embed%prev_step, 0.0_dp)
356 :
357 : ! Allocate Hessian
358 14 : NULLIFY (opt_embed%embed_pot_hess, opt_embed%prev_embed_pot_hess, fm_struct)
359 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
360 14 : nrow_global=opt_embed%dimen_var_aux, ncol_global=opt_embed%dimen_var_aux)
361 14 : ALLOCATE (opt_embed%embed_pot_hess, opt_embed%prev_embed_pot_hess)
362 14 : CALL cp_fm_create(opt_embed%embed_pot_hess, fm_struct, name="pot_Hess")
363 14 : CALL cp_fm_create(opt_embed%prev_embed_pot_hess, fm_struct, name="prev_pot_Hess")
364 14 : CALL cp_fm_struct_release(fm_struct)
365 :
366 : ! Special structure for the kinetic energy matrix
367 14 : NULLIFY (fm_struct, opt_embed%kinetic_mat)
368 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
369 14 : nrow_global=opt_embed%dimen_aux, ncol_global=opt_embed%dimen_aux)
370 14 : ALLOCATE (opt_embed%kinetic_mat)
371 14 : CALL cp_fm_create(opt_embed%kinetic_mat, fm_struct, name="kinetic_mat")
372 14 : CALL cp_fm_struct_release(fm_struct)
373 14 : CALL cp_fm_set_all(opt_embed%kinetic_mat, 0.0_dp)
374 :
375 : ! Hessian is set as a unit matrix
376 14 : CALL cp_fm_set_all(opt_embed%embed_pot_hess, 0.0_dp, -1.0_dp)
377 14 : CALL cp_fm_set_all(opt_embed%prev_embed_pot_hess, 0.0_dp, -1.0_dp)
378 :
379 : ! Release blacs environment
380 14 : CALL cp_blacs_env_release(blacs_env)
381 :
382 : END IF
383 :
384 24 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
385 24 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
386 24 : NULLIFY (opt_embed%prev_subsys_dens)
387 72 : size_prev_dens = SUM(opt_embed%all_nspins(1:(SIZE(opt_embed%all_nspins) - 1)))
388 144 : ALLOCATE (opt_embed%prev_subsys_dens(size_prev_dens))
389 96 : DO i_dens = 1, size_prev_dens
390 72 : CALL auxbas_pw_pool%create_pw(opt_embed%prev_subsys_dens(i_dens))
391 96 : CALL pw_zero(opt_embed%prev_subsys_dens(i_dens))
392 : END DO
393 72 : ALLOCATE (opt_embed%max_subsys_dens_diff(size_prev_dens))
394 :
395 : ! Array to store functional values
396 72 : ALLOCATE (opt_embed%w_func(opt_embed%n_iter))
397 1136 : opt_embed%w_func = 0.0_dp
398 :
399 : ! Allocate max_diff and int_diff
400 24 : diff_size = 1
401 24 : IF (opt_embed%open_shell_embed) diff_size = 2
402 48 : ALLOCATE (opt_embed%max_diff(diff_size))
403 48 : ALLOCATE (opt_embed%int_diff(diff_size))
404 48 : ALLOCATE (opt_embed%int_diff_square(diff_size))
405 :
406 : ! FAB update
407 24 : IF (opt_embed%fab) THEN
408 : NULLIFY (opt_embed%prev_embed_pot)
409 2 : ALLOCATE (opt_embed%prev_embed_pot)
410 2 : CALL auxbas_pw_pool%create_pw(opt_embed%prev_embed_pot)
411 2 : CALL pw_zero(opt_embed%prev_embed_pot)
412 2 : IF (opt_embed%open_shell_embed) THEN
413 : NULLIFY (opt_embed%prev_spin_embed_pot)
414 0 : ALLOCATE (opt_embed%prev_spin_embed_pot)
415 0 : CALL auxbas_pw_pool%create_pw(opt_embed%prev_spin_embed_pot)
416 0 : CALL pw_zero(opt_embed%prev_spin_embed_pot)
417 : END IF
418 : END IF
419 :
420 : ! Set allowed energy decrease parameter
421 24 : opt_embed%allowed_decrease = 0.0001_dp
422 :
423 : ! Regularization contribution is set to zero
424 24 : opt_embed%reg_term = 0.0_dp
425 :
426 : ! Step is accepted in the beginning
427 24 : opt_embed%accept_step = .TRUE.
428 24 : opt_embed%newton_step = .FALSE.
429 24 : opt_embed%last_accepted = 1
430 :
431 : ! Set maximum and minimum trust radii
432 24 : opt_embed%max_trad = opt_embed%trust_rad*7.900_dp
433 24 : opt_embed%min_trad = opt_embed%trust_rad*0.125*0.065_dp
434 :
435 24 : END SUBROUTINE prepare_embed_opt
436 :
437 : ! **************************************************************************************************
438 : !> \brief ...
439 : !> \param opt_embed ...
440 : !> \param opt_embed_section ...
441 : ! **************************************************************************************************
442 72 : SUBROUTINE read_opt_embed_section(opt_embed, opt_embed_section)
443 : TYPE(opt_embed_pot_type) :: opt_embed
444 : TYPE(section_vals_type), POINTER :: opt_embed_section
445 :
446 : INTEGER :: embed_guess, embed_optimizer
447 :
448 : ! Read keywords
449 : CALL section_vals_val_get(opt_embed_section, "REG_LAMBDA", &
450 24 : r_val=opt_embed%lambda)
451 :
452 : CALL section_vals_val_get(opt_embed_section, "N_ITER", &
453 24 : i_val=opt_embed%n_iter)
454 :
455 : CALL section_vals_val_get(opt_embed_section, "TRUST_RAD", &
456 24 : r_val=opt_embed%trust_rad)
457 :
458 : CALL section_vals_val_get(opt_embed_section, "DENS_CONV_MAX", &
459 24 : r_val=opt_embed%conv_max)
460 :
461 : CALL section_vals_val_get(opt_embed_section, "DENS_CONV_INT", &
462 24 : r_val=opt_embed%conv_int)
463 :
464 : CALL section_vals_val_get(opt_embed_section, "SPIN_DENS_CONV_MAX", &
465 24 : r_val=opt_embed%conv_max_spin)
466 :
467 : CALL section_vals_val_get(opt_embed_section, "SPIN_DENS_CONV_INT", &
468 24 : r_val=opt_embed%conv_int_spin)
469 :
470 : CALL section_vals_val_get(opt_embed_section, "CHARGE_DISTR_WIDTH", &
471 24 : r_val=opt_embed%eta)
472 :
473 : CALL section_vals_val_get(opt_embed_section, "READ_EMBED_POT", &
474 24 : l_val=opt_embed%read_embed_pot)
475 :
476 : CALL section_vals_val_get(opt_embed_section, "READ_EMBED_POT_CUBE", &
477 24 : l_val=opt_embed%read_embed_pot_cube)
478 :
479 : CALL section_vals_val_get(opt_embed_section, "GRID_OPT", &
480 24 : l_val=opt_embed%grid_opt)
481 :
482 : CALL section_vals_val_get(opt_embed_section, "LEEUWEN-BAERENDS", &
483 24 : l_val=opt_embed%leeuwen)
484 :
485 : CALL section_vals_val_get(opt_embed_section, "FAB", &
486 24 : l_val=opt_embed%fab)
487 :
488 : CALL section_vals_val_get(opt_embed_section, "VW_CUTOFF", &
489 24 : r_val=opt_embed%vw_cutoff)
490 :
491 : CALL section_vals_val_get(opt_embed_section, "VW_SMOOTH_CUT_RANGE", &
492 24 : r_val=opt_embed%vw_smooth_cutoff_range)
493 :
494 24 : CALL section_vals_val_get(opt_embed_section, "OPTIMIZER", i_val=embed_optimizer)
495 14 : SELECT CASE (embed_optimizer)
496 : CASE (embed_steep_desc)
497 14 : opt_embed%steep_desc = .TRUE.
498 : CASE (embed_quasi_newton)
499 4 : opt_embed%steep_desc = .FALSE.
500 4 : opt_embed%level_shift = .FALSE.
501 : CASE (embed_level_shift)
502 6 : opt_embed%steep_desc = .FALSE.
503 6 : opt_embed%level_shift = .TRUE.
504 : CASE DEFAULT
505 24 : opt_embed%steep_desc = .TRUE.
506 : END SELECT
507 :
508 24 : CALL section_vals_val_get(opt_embed_section, "POT_GUESS", i_val=embed_guess)
509 16 : SELECT CASE (embed_guess)
510 : CASE (embed_none)
511 16 : opt_embed%add_const_pot = .FALSE.
512 16 : opt_embed%Fermi_Amaldi = .FALSE.
513 16 : opt_embed%Coulomb_guess = .FALSE.
514 16 : opt_embed%diff_guess = .FALSE.
515 : CASE (embed_diff)
516 2 : opt_embed%add_const_pot = .TRUE.
517 2 : opt_embed%Fermi_Amaldi = .FALSE.
518 2 : opt_embed%Coulomb_guess = .FALSE.
519 2 : opt_embed%diff_guess = .TRUE.
520 : CASE (embed_fa)
521 4 : opt_embed%add_const_pot = .TRUE.
522 4 : opt_embed%Fermi_Amaldi = .TRUE.
523 4 : opt_embed%Coulomb_guess = .FALSE.
524 4 : opt_embed%diff_guess = .FALSE.
525 : CASE (embed_resp)
526 2 : opt_embed%add_const_pot = .TRUE.
527 2 : opt_embed%Fermi_Amaldi = .TRUE.
528 2 : opt_embed%Coulomb_guess = .TRUE.
529 2 : opt_embed%diff_guess = .FALSE.
530 : CASE DEFAULT
531 0 : opt_embed%add_const_pot = .FALSE.
532 0 : opt_embed%Fermi_Amaldi = .FALSE.
533 0 : opt_embed%Coulomb_guess = .FALSE.
534 24 : opt_embed%diff_guess = .FALSE.
535 : END SELECT
536 :
537 24 : END SUBROUTINE read_opt_embed_section
538 :
539 : ! **************************************************************************************************
540 : !> \brief Find the dimension of the auxiliary basis for the expansion of the embedding potential
541 : !> \param qs_env ...
542 : !> \param dimen_aux ...
543 : ! **************************************************************************************************
544 18 : SUBROUTINE find_aux_dimen(qs_env, dimen_aux)
545 : TYPE(qs_environment_type), POINTER :: qs_env
546 : INTEGER :: dimen_aux
547 :
548 : INTEGER :: iatom, ikind, nsgf
549 18 : INTEGER, ALLOCATABLE, DIMENSION(:) :: kind_of
550 18 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
551 18 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
552 18 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
553 :
554 : ! First, reveal the dimension of the RI basis
555 : CALL get_qs_env(qs_env=qs_env, &
556 : particle_set=particle_set, &
557 : qs_kind_set=qs_kind_set, &
558 18 : atomic_kind_set=atomic_kind_set)
559 :
560 18 : CALL get_atomic_kind_set(atomic_kind_set, kind_of=kind_of)
561 :
562 18 : dimen_aux = 0
563 82 : DO iatom = 1, SIZE(particle_set)
564 64 : ikind = kind_of(iatom)
565 64 : CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
566 82 : dimen_aux = dimen_aux + nsgf
567 : END DO
568 :
569 36 : END SUBROUTINE find_aux_dimen
570 :
571 : ! **************************************************************************************************
572 : !> \brief Prepare the lri_kind_type object for integrals between density and aux. basis functions
573 : !> \param qs_env ...
574 : !> \param lri ...
575 : ! **************************************************************************************************
576 14 : SUBROUTINE make_lri_object(qs_env, lri)
577 : TYPE(qs_environment_type), POINTER :: qs_env
578 : TYPE(lri_kind_type), DIMENSION(:), POINTER :: lri
579 :
580 : INTEGER :: ikind, natom, nkind, nsgf
581 14 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
582 : TYPE(atomic_kind_type), POINTER :: atomic_kind
583 14 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
584 :
585 14 : NULLIFY (atomic_kind, lri)
586 : CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, &
587 14 : qs_kind_set=qs_kind_set)
588 14 : nkind = SIZE(atomic_kind_set)
589 :
590 62 : ALLOCATE (lri(nkind))
591 : ! Here we need only v_int and acoef (the latter as dummies)
592 34 : DO ikind = 1, nkind
593 20 : NULLIFY (lri(ikind)%acoef)
594 20 : NULLIFY (lri(ikind)%v_int)
595 20 : atomic_kind => atomic_kind_set(ikind)
596 20 : CALL get_atomic_kind(atomic_kind=atomic_kind, natom=natom)
597 20 : CALL get_qs_kind(qs_kind=qs_kind_set(ikind), nsgf=nsgf, basis_type="RI_AUX")
598 80 : ALLOCATE (lri(ikind)%acoef(natom, nsgf))
599 2672 : lri(ikind)%acoef = 0._dp
600 60 : ALLOCATE (lri(ikind)%v_int(natom, nsgf))
601 2706 : lri(ikind)%v_int = 0._dp
602 : END DO
603 :
604 14 : END SUBROUTINE make_lri_object
605 :
606 : ! **************************************************************************************************
607 : !> \brief Read the external embedding potential, not to be optimized
608 : !> \param qs_env ...
609 : ! **************************************************************************************************
610 2 : SUBROUTINE given_embed_pot(qs_env)
611 : TYPE(qs_environment_type), POINTER :: qs_env
612 :
613 : LOGICAL :: open_shell_embed
614 : TYPE(dft_control_type), POINTER :: dft_control
615 : TYPE(pw_env_type), POINTER :: pw_env
616 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool_subsys
617 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot, spin_embed_pot
618 : TYPE(section_vals_type), POINTER :: input, qs_section
619 :
620 2 : qs_env%given_embed_pot = .TRUE.
621 2 : NULLIFY (input, dft_control, embed_pot, spin_embed_pot, embed_pot, spin_embed_pot, &
622 2 : qs_section)
623 : CALL get_qs_env(qs_env=qs_env, &
624 : input=input, &
625 : dft_control=dft_control, &
626 2 : pw_env=pw_env)
627 2 : qs_section => section_vals_get_subs_vals(input, "DFT%QS")
628 2 : open_shell_embed = .FALSE.
629 2 : IF (dft_control%nspins .EQ. 2) open_shell_embed = .TRUE.
630 :
631 : ! Prepare plane-waves pool
632 2 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool_subsys)
633 :
634 : ! Create embedding potential
635 : !CALL get_qs_env(qs_env=qs_env, &
636 : ! embed_pot=embed_pot)
637 2 : ALLOCATE (embed_pot)
638 2 : CALL auxbas_pw_pool_subsys%create_pw(embed_pot)
639 2 : IF (open_shell_embed) THEN
640 : ! Create spin embedding potential
641 2 : ALLOCATE (spin_embed_pot)
642 2 : CALL auxbas_pw_pool_subsys%create_pw(spin_embed_pot)
643 : END IF
644 : ! Read the cubes
645 2 : CALL read_embed_pot_cube(embed_pot, spin_embed_pot, qs_section, open_shell_embed)
646 :
647 2 : IF (.NOT. open_shell_embed) THEN
648 0 : CALL set_qs_env(qs_env=qs_env, embed_pot=embed_pot)
649 : ELSE
650 2 : CALL set_qs_env(qs_env=qs_env, embed_pot=embed_pot, spin_embed_pot=spin_embed_pot)
651 : END IF
652 :
653 2 : END SUBROUTINE given_embed_pot
654 :
655 : ! **************************************************************************************************
656 : !> \brief ...
657 : !> \param qs_env ...
658 : !> \param embed_pot ...
659 : !> \param spin_embed_pot ...
660 : !> \param section ...
661 : !> \param opt_embed ...
662 : ! **************************************************************************************************
663 6 : SUBROUTINE read_embed_pot(qs_env, embed_pot, spin_embed_pot, section, opt_embed)
664 : TYPE(qs_environment_type), POINTER :: qs_env
665 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot, spin_embed_pot
666 : TYPE(section_vals_type), POINTER :: section
667 : TYPE(opt_embed_pot_type) :: opt_embed
668 :
669 : ! Read the potential as a vector in the auxiliary basis
670 6 : IF (opt_embed%read_embed_pot) &
671 : CALL read_embed_pot_vector(qs_env, embed_pot, spin_embed_pot, section, &
672 4 : opt_embed%embed_pot_coef, opt_embed%open_shell_embed)
673 : ! Read the potential as a cube (two cubes for open shell)
674 6 : IF (opt_embed%read_embed_pot_cube) &
675 2 : CALL read_embed_pot_cube(embed_pot, spin_embed_pot, section, opt_embed%open_shell_embed)
676 :
677 6 : END SUBROUTINE read_embed_pot
678 :
679 : ! **************************************************************************************************
680 : !> \brief ...
681 : !> \param embed_pot ...
682 : !> \param spin_embed_pot ...
683 : !> \param section ...
684 : !> \param open_shell_embed ...
685 : ! **************************************************************************************************
686 4 : SUBROUTINE read_embed_pot_cube(embed_pot, spin_embed_pot, section, open_shell_embed)
687 : TYPE(pw_r3d_rs_type), INTENT(IN) :: embed_pot, spin_embed_pot
688 : TYPE(section_vals_type), POINTER :: section
689 : LOGICAL :: open_shell_embed
690 :
691 : CHARACTER(LEN=default_path_length) :: filename
692 : LOGICAL :: exist
693 : REAL(KIND=dp) :: scaling_factor
694 :
695 4 : exist = .FALSE.
696 4 : CALL section_vals_val_get(section, "EMBED_CUBE_FILE_NAME", c_val=filename)
697 4 : INQUIRE (FILE=filename, exist=exist)
698 4 : IF (.NOT. exist) &
699 0 : CPABORT("Embedding cube file not found. ")
700 :
701 4 : scaling_factor = 1.0_dp
702 4 : CALL cp_cube_to_pw(embed_pot, filename, scaling_factor)
703 :
704 : ! Spin-dependent part of the potential
705 4 : IF (open_shell_embed) THEN
706 4 : exist = .FALSE.
707 4 : CALL section_vals_val_get(section, "EMBED_SPIN_CUBE_FILE_NAME", c_val=filename)
708 4 : INQUIRE (FILE=filename, exist=exist)
709 4 : IF (.NOT. exist) &
710 0 : CPABORT("Embedding spin cube file not found. ")
711 :
712 : scaling_factor = 1.0_dp
713 4 : CALL cp_cube_to_pw(spin_embed_pot, filename, scaling_factor)
714 : END IF
715 :
716 4 : END SUBROUTINE read_embed_pot_cube
717 :
718 : ! **************************************************************************************************
719 : !> \brief Read the embedding potential from the binary file
720 : !> \param qs_env ...
721 : !> \param embed_pot ...
722 : !> \param spin_embed_pot ...
723 : !> \param section ...
724 : !> \param embed_pot_coef ...
725 : !> \param open_shell_embed ...
726 : ! **************************************************************************************************
727 4 : SUBROUTINE read_embed_pot_vector(qs_env, embed_pot, spin_embed_pot, section, embed_pot_coef, open_shell_embed)
728 : TYPE(qs_environment_type), POINTER :: qs_env
729 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
730 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
731 : TYPE(section_vals_type), POINTER :: section
732 : TYPE(cp_fm_type), INTENT(IN) :: embed_pot_coef
733 : LOGICAL, INTENT(IN) :: open_shell_embed
734 :
735 : CHARACTER(LEN=default_path_length) :: filename
736 : INTEGER :: dimen_aux, dimen_restart_basis, &
737 : dimen_var_aux, l_global, LLL, &
738 : nrow_local, restart_unit
739 4 : INTEGER, DIMENSION(:), POINTER :: row_indices
740 4 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: coef, coef_read
741 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
742 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
743 : TYPE(cp_fm_type) :: my_embed_pot_coef
744 : TYPE(mp_para_env_type), POINTER :: para_env
745 :
746 : ! Get the vector dimension
747 4 : CALL find_aux_dimen(qs_env, dimen_aux)
748 4 : IF (open_shell_embed) THEN
749 2 : dimen_var_aux = dimen_aux*2
750 : ELSE
751 2 : dimen_var_aux = dimen_aux
752 : END IF
753 :
754 : ! We need a temporary vector of coefficients
755 : CALL get_qs_env(qs_env=qs_env, &
756 4 : para_env=para_env)
757 4 : NULLIFY (blacs_env)
758 4 : NULLIFY (fm_struct)
759 4 : CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
760 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
761 4 : nrow_global=dimen_var_aux, ncol_global=1)
762 4 : CALL cp_fm_create(my_embed_pot_coef, fm_struct, name="my_pot_coef")
763 :
764 4 : CALL cp_fm_struct_release(fm_struct)
765 4 : CALL cp_fm_set_all(my_embed_pot_coef, 0.0_dp)
766 :
767 : ! Read the coefficients vector
768 4 : restart_unit = -1
769 :
770 : ! Allocate the attay to read the coefficients
771 12 : ALLOCATE (coef(dimen_var_aux))
772 636 : coef = 0.0_dp
773 :
774 4 : IF (para_env%is_source()) THEN
775 :
776 : ! Get the restart file name
777 2 : CALL embed_restart_file_name(filename, section)
778 :
779 : CALL open_file(file_name=filename, &
780 : file_action="READ", &
781 : file_form="UNFORMATTED", &
782 : file_status="OLD", &
783 2 : unit_number=restart_unit)
784 :
785 2 : READ (restart_unit) dimen_restart_basis
786 : ! Check the dimensions of the bases: the actual and the restart one
787 2 : IF (.NOT. (dimen_restart_basis == dimen_aux)) &
788 0 : CPABORT("Wrong dimension of the embedding basis in the restart file.")
789 :
790 4 : ALLOCATE (coef_read(dimen_var_aux))
791 318 : coef_read = 0.0_dp
792 :
793 2 : READ (restart_unit) coef_read
794 318 : coef(:) = coef_read(:)
795 2 : DEALLOCATE (coef_read)
796 :
797 : ! Close restart file
798 2 : CALL close_file(unit_number=restart_unit)
799 :
800 : END IF
801 :
802 : ! Broadcast the coefficients on all processes
803 4 : CALL para_env%bcast(coef)
804 :
805 : ! Copy to fm_type structure
806 : ! Information about full matrix gradient
807 : CALL cp_fm_get_info(matrix=my_embed_pot_coef, &
808 : nrow_local=nrow_local, &
809 4 : row_indices=row_indices)
810 :
811 320 : DO LLL = 1, nrow_local
812 316 : l_global = row_indices(LLL)
813 320 : my_embed_pot_coef%local_data(LLL, 1) = coef(l_global)
814 : END DO
815 :
816 4 : DEALLOCATE (coef)
817 :
818 : ! Copy to the my_embed_pot_coef to embed_pot_coef
819 4 : CALL cp_fm_copy_general(my_embed_pot_coef, embed_pot_coef, para_env)
820 :
821 : ! Build the embedding potential on the grid
822 : CALL update_embed_pot(embed_pot_coef, dimen_aux, embed_pot, spin_embed_pot, &
823 4 : qs_env, .FALSE., open_shell_embed)
824 :
825 : ! Release my_embed_pot_coef
826 4 : CALL cp_fm_release(my_embed_pot_coef)
827 :
828 : ! Release blacs environment
829 4 : CALL cp_blacs_env_release(blacs_env)
830 :
831 16 : END SUBROUTINE read_embed_pot_vector
832 :
833 : ! **************************************************************************************************
834 : !> \brief Find the embedding restart file name
835 : !> \param filename ...
836 : !> \param section ...
837 : ! **************************************************************************************************
838 2 : SUBROUTINE embed_restart_file_name(filename, section)
839 : CHARACTER(LEN=default_path_length), INTENT(OUT) :: filename
840 : TYPE(section_vals_type), POINTER :: section
841 :
842 : LOGICAL :: exist
843 :
844 2 : exist = .FALSE.
845 2 : CALL section_vals_val_get(section, "EMBED_RESTART_FILE_NAME", c_val=filename)
846 2 : INQUIRE (FILE=filename, exist=exist)
847 2 : IF (.NOT. exist) &
848 0 : CPABORT("Embedding restart file not found. ")
849 :
850 2 : END SUBROUTINE embed_restart_file_name
851 :
852 : ! **************************************************************************************************
853 : !> \brief Deallocate stuff for optimizing embedding potential
854 : !> \param opt_embed ...
855 : ! **************************************************************************************************
856 24 : SUBROUTINE release_opt_embed(opt_embed)
857 : TYPE(opt_embed_pot_type) :: opt_embed
858 :
859 : INTEGER :: i_dens, i_spin, ikind
860 :
861 24 : IF (.NOT. opt_embed%grid_opt) THEN
862 14 : CALL cp_fm_release(opt_embed%embed_pot_grad)
863 14 : CALL cp_fm_release(opt_embed%embed_pot_coef)
864 14 : CALL cp_fm_release(opt_embed%step)
865 14 : CALL cp_fm_release(opt_embed%prev_step)
866 14 : CALL cp_fm_release(opt_embed%embed_pot_hess)
867 14 : CALL cp_fm_release(opt_embed%prev_embed_pot_grad)
868 14 : CALL cp_fm_release(opt_embed%prev_embed_pot_coef)
869 14 : CALL cp_fm_release(opt_embed%prev_embed_pot_hess)
870 14 : CALL cp_fm_release(opt_embed%kinetic_mat)
871 0 : DEALLOCATE (opt_embed%embed_pot_grad, opt_embed%embed_pot_coef, &
872 0 : opt_embed%step, opt_embed%prev_step, opt_embed%embed_pot_hess, &
873 0 : opt_embed%prev_embed_pot_grad, opt_embed%prev_embed_pot_coef, &
874 14 : opt_embed%prev_embed_pot_hess, opt_embed%kinetic_mat)
875 14 : DEALLOCATE (opt_embed%w_func)
876 14 : DEALLOCATE (opt_embed%max_diff)
877 14 : DEALLOCATE (opt_embed%int_diff)
878 :
879 34 : DO ikind = 1, SIZE(opt_embed%lri)
880 20 : DEALLOCATE (opt_embed%lri(ikind)%v_int)
881 34 : DEALLOCATE (opt_embed%lri(ikind)%acoef)
882 : END DO
883 14 : DEALLOCATE (opt_embed%lri)
884 : END IF
885 :
886 24 : IF (ASSOCIATED(opt_embed%prev_subsys_dens)) THEN
887 96 : DO i_dens = 1, SIZE(opt_embed%prev_subsys_dens)
888 96 : CALL opt_embed%prev_subsys_dens(i_dens)%release()
889 : END DO
890 24 : DEALLOCATE (opt_embed%prev_subsys_dens)
891 : END IF
892 24 : DEALLOCATE (opt_embed%max_subsys_dens_diff)
893 :
894 24 : DEALLOCATE (opt_embed%all_nspins)
895 :
896 24 : IF (ASSOCIATED(opt_embed%const_pot)) THEN
897 4 : CALL opt_embed%const_pot%release()
898 4 : DEALLOCATE (opt_embed%const_pot)
899 : END IF
900 :
901 24 : IF (ASSOCIATED(opt_embed%pot_diff)) THEN
902 2 : CALL opt_embed%pot_diff%release()
903 2 : DEALLOCATE (opt_embed%pot_diff)
904 : END IF
905 :
906 24 : IF (ASSOCIATED(opt_embed%prev_embed_pot)) THEN
907 2 : CALL opt_embed%prev_embed_pot%release()
908 2 : DEALLOCATE (opt_embed%prev_embed_pot)
909 : END IF
910 24 : IF (ASSOCIATED(opt_embed%prev_spin_embed_pot)) THEN
911 0 : CALL opt_embed%prev_spin_embed_pot%release()
912 0 : DEALLOCATE (opt_embed%prev_spin_embed_pot)
913 : END IF
914 24 : IF (ASSOCIATED(opt_embed%v_w)) THEN
915 4 : DO i_spin = 1, SIZE(opt_embed%v_w)
916 4 : CALL opt_embed%v_w(i_spin)%release()
917 : END DO
918 2 : DEALLOCATE (opt_embed%v_w)
919 : END IF
920 :
921 24 : END SUBROUTINE release_opt_embed
922 :
923 : ! **************************************************************************************************
924 : !> \brief Calculates subsystem Coulomb potential from the RESP charges of the total system
925 : !> \param v_rspace ...
926 : !> \param rhs ...
927 : !> \param mapping_section ...
928 : !> \param qs_env ...
929 : !> \param nforce_eval ...
930 : !> \param iforce_eval ...
931 : !> \param eta ...
932 : ! **************************************************************************************************
933 4 : SUBROUTINE Coulomb_guess(v_rspace, rhs, mapping_section, qs_env, nforce_eval, iforce_eval, eta)
934 : TYPE(pw_r3d_rs_type) :: v_rspace
935 : REAL(KIND=dp), DIMENSION(:), POINTER :: rhs
936 : TYPE(section_vals_type), POINTER :: mapping_section
937 : TYPE(qs_environment_type), POINTER :: qs_env
938 : INTEGER :: nforce_eval, iforce_eval
939 : REAL(KIND=dp) :: eta
940 :
941 : INTEGER :: iparticle, jparticle, natom
942 4 : INTEGER, DIMENSION(:), POINTER :: map_index
943 : REAL(KIND=dp) :: dvol, normalize_factor
944 4 : REAL(KIND=dp), DIMENSION(:), POINTER :: rhs_subsys
945 : TYPE(particle_list_type), POINTER :: particles
946 : TYPE(pw_c1d_gs_type) :: v_resp_gspace
947 : TYPE(pw_env_type), POINTER :: pw_env
948 : TYPE(pw_poisson_type), POINTER :: poisson_env
949 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
950 : TYPE(pw_r3d_rs_type) :: rho_resp, v_resp_rspace
951 : TYPE(qs_subsys_type), POINTER :: subsys
952 :
953 : ! Get available particles
954 4 : NULLIFY (subsys)
955 4 : CALL get_qs_env(qs_env=qs_env, subsys=subsys, pw_env=pw_env)
956 4 : CALL qs_subsys_get(subsys, particles=particles)
957 4 : natom = particles%n_els
958 :
959 12 : ALLOCATE (rhs_subsys(natom))
960 :
961 4 : NULLIFY (map_index)
962 : CALL get_subsys_map_index(mapping_section, natom, iforce_eval, nforce_eval, &
963 4 : map_index, .TRUE.)
964 :
965 : ! Mapping particles from iforce_eval environment to the embed env
966 14 : DO iparticle = 1, natom
967 10 : jparticle = map_index(iparticle)
968 14 : rhs_subsys(iparticle) = rhs(jparticle)
969 : END DO
970 :
971 : ! Prepare plane waves
972 4 : NULLIFY (auxbas_pw_pool)
973 :
974 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool, &
975 4 : poisson_env=poisson_env)
976 :
977 4 : CALL auxbas_pw_pool%create_pw(v_resp_gspace)
978 :
979 4 : CALL auxbas_pw_pool%create_pw(v_resp_rspace)
980 :
981 4 : CALL auxbas_pw_pool%create_pw(rho_resp)
982 :
983 : ! Calculate charge density
984 4 : CALL pw_zero(rho_resp)
985 4 : CALL calculate_rho_resp_all(rho_resp, rhs_subsys, natom, eta, qs_env)
986 :
987 : ! Calculate potential
988 : CALL pw_poisson_solve(poisson_env, rho_resp, &
989 4 : vhartree=v_resp_rspace)
990 4 : dvol = v_resp_rspace%pw_grid%dvol
991 4 : CALL pw_scale(v_resp_rspace, dvol)
992 4 : normalize_factor = SQRT((eta/pi)**3)
993 : !normalize_factor = -2.0_dp
994 4 : CALL pw_scale(v_resp_rspace, normalize_factor)
995 :
996 : ! Hard copy potential
997 4 : CALL pw_copy(v_resp_rspace, v_rspace)
998 :
999 : ! Release plane waves
1000 4 : CALL v_resp_gspace%release()
1001 4 : CALL v_resp_rspace%release()
1002 4 : CALL rho_resp%release()
1003 :
1004 : ! Deallocate map_index array
1005 4 : DEALLOCATE (map_index)
1006 : ! Deallocate charges
1007 4 : DEALLOCATE (rhs_subsys)
1008 :
1009 4 : END SUBROUTINE Coulomb_guess
1010 :
1011 : ! **************************************************************************************************
1012 : !> \brief Creates a subsystem embedding potential
1013 : !> \param qs_env ...
1014 : !> \param embed_pot ...
1015 : !> \param embed_pot_subsys ...
1016 : !> \param spin_embed_pot ...
1017 : !> \param spin_embed_pot_subsys ...
1018 : !> \param open_shell_embed ...
1019 : !> \param change_spin_sign ...
1020 : !> \author Vladimir Rybkin
1021 : ! **************************************************************************************************
1022 120 : SUBROUTINE make_subsys_embed_pot(qs_env, embed_pot, embed_pot_subsys, &
1023 : spin_embed_pot, spin_embed_pot_subsys, open_shell_embed, &
1024 : change_spin_sign)
1025 : TYPE(qs_environment_type), POINTER :: qs_env
1026 : TYPE(pw_r3d_rs_type), INTENT(IN) :: embed_pot
1027 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot_subsys
1028 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
1029 : TYPE(pw_r3d_rs_type), POINTER :: spin_embed_pot_subsys
1030 : LOGICAL :: open_shell_embed, change_spin_sign
1031 :
1032 : TYPE(pw_env_type), POINTER :: pw_env
1033 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool_subsys
1034 :
1035 : ! Extract plane waves environment
1036 120 : CALL get_qs_env(qs_env, pw_env=pw_env)
1037 :
1038 : ! Prepare plane-waves pool
1039 120 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool_subsys)
1040 :
1041 : ! Create embedding potential and set to zero
1042 : NULLIFY (embed_pot_subsys)
1043 120 : ALLOCATE (embed_pot_subsys)
1044 120 : CALL auxbas_pw_pool_subsys%create_pw(embed_pot_subsys)
1045 :
1046 : ! Hard copy the grid
1047 120 : CALL pw_copy(embed_pot, embed_pot_subsys)
1048 :
1049 120 : IF (open_shell_embed) THEN
1050 : NULLIFY (spin_embed_pot_subsys)
1051 64 : ALLOCATE (spin_embed_pot_subsys)
1052 64 : CALL auxbas_pw_pool_subsys%create_pw(spin_embed_pot_subsys)
1053 : ! Hard copy the grid
1054 64 : IF (change_spin_sign) THEN
1055 8 : CALL pw_axpy(spin_embed_pot, spin_embed_pot_subsys, -1.0_dp, 0.0_dp, allow_noncompatible_grids=.TRUE.)
1056 : ELSE
1057 56 : CALL pw_copy(spin_embed_pot, spin_embed_pot_subsys)
1058 : END IF
1059 : END IF
1060 :
1061 120 : END SUBROUTINE make_subsys_embed_pot
1062 :
1063 : ! **************************************************************************************************
1064 : !> \brief Calculates the derivative of the embedding potential wrt to the expansion coefficients
1065 : !> \param qs_env ...
1066 : !> \param diff_rho_r ...
1067 : !> \param diff_rho_spin ...
1068 : !> \param opt_embed ...
1069 : !> \author Vladimir Rybkin
1070 : ! **************************************************************************************************
1071 :
1072 32 : SUBROUTINE calculate_embed_pot_grad(qs_env, diff_rho_r, diff_rho_spin, opt_embed)
1073 : TYPE(qs_environment_type), POINTER :: qs_env
1074 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r, diff_rho_spin
1075 : TYPE(opt_embed_pot_type) :: opt_embed
1076 :
1077 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_embed_pot_grad'
1078 :
1079 : INTEGER :: handle
1080 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1081 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1082 : TYPE(cp_fm_type) :: embed_pot_coeff_spin, &
1083 : embed_pot_coeff_spinless, &
1084 : regular_term, spin_reg, spinless_reg
1085 : TYPE(mp_para_env_type), POINTER :: para_env
1086 : TYPE(pw_env_type), POINTER :: pw_env
1087 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1088 :
1089 16 : CALL timeset(routineN, handle)
1090 :
1091 : ! We destroy the previous gradient and Hessian:
1092 : ! current data are now previous data
1093 16 : CALL cp_fm_to_fm(opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad)
1094 16 : CALL cp_fm_to_fm(opt_embed%embed_pot_Hess, opt_embed%prev_embed_pot_Hess)
1095 :
1096 16 : NULLIFY (pw_env)
1097 :
1098 16 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env, para_env=para_env)
1099 :
1100 : ! Get plane waves pool
1101 16 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1102 :
1103 : ! Calculate potential gradient coefficients
1104 : CALL calculate_embed_pot_grad_inner(qs_env, opt_embed%dimen_aux, diff_rho_r, diff_rho_spin, &
1105 : opt_embed%embed_pot_grad, &
1106 16 : opt_embed%open_shell_embed, opt_embed%lri)
1107 :
1108 : ! Add regularization with kinetic matrix
1109 16 : IF (opt_embed%i_iter .EQ. 1) THEN ! Else it is kept in memory
1110 12 : CALL compute_kinetic_mat(qs_env, opt_embed%kinetic_mat)
1111 : END IF
1112 :
1113 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
1114 16 : matrix_struct=fm_struct)
1115 16 : CALL cp_fm_create(regular_term, fm_struct, name="regular_term")
1116 16 : CALL cp_fm_set_all(regular_term, 0.0_dp)
1117 :
1118 : ! In case of open shell embedding we need two terms of dimen_aux=dimen_var_aux/2 for
1119 : ! the spinless and the spin parts
1120 16 : IF (opt_embed%open_shell_embed) THEN
1121 : ! Prepare auxiliary full matrices
1122 10 : NULLIFY (fm_struct, blacs_env)
1123 :
1124 : !CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
1125 :
1126 10 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, context=blacs_env)
1127 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
1128 10 : nrow_global=opt_embed%dimen_aux, ncol_global=1)
1129 10 : CALL cp_fm_create(embed_pot_coeff_spinless, fm_struct, name="pot_coeff_spinless")
1130 10 : CALL cp_fm_create(embed_pot_coeff_spin, fm_struct, name="pot_coeff_spin")
1131 10 : CALL cp_fm_create(spinless_reg, fm_struct, name="spinless_reg")
1132 10 : CALL cp_fm_create(spin_reg, fm_struct, name="spin_reg")
1133 10 : CALL cp_fm_set_all(embed_pot_coeff_spinless, 0.0_dp)
1134 10 : CALL cp_fm_set_all(embed_pot_coeff_spin, 0.0_dp)
1135 10 : CALL cp_fm_set_all(spinless_reg, 0.0_dp)
1136 10 : CALL cp_fm_set_all(spin_reg, 0.0_dp)
1137 10 : CALL cp_fm_struct_release(fm_struct)
1138 :
1139 : ! Copy coefficients to the auxiliary structures
1140 : CALL cp_fm_to_fm_submat(msource=opt_embed%embed_pot_coef, &
1141 : mtarget=embed_pot_coeff_spinless, &
1142 : nrow=opt_embed%dimen_aux, ncol=1, &
1143 : s_firstrow=1, s_firstcol=1, &
1144 10 : t_firstrow=1, t_firstcol=1)
1145 : CALL cp_fm_to_fm_submat(msource=opt_embed%embed_pot_coef, &
1146 : mtarget=embed_pot_coeff_spin, &
1147 : nrow=opt_embed%dimen_aux, ncol=1, &
1148 : s_firstrow=opt_embed%dimen_aux + 1, s_firstcol=1, &
1149 10 : t_firstrow=1, t_firstcol=1)
1150 : ! Multiply
1151 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
1152 : k=opt_embed%dimen_aux, alpha=1.0_dp, &
1153 : matrix_a=opt_embed%kinetic_mat, matrix_b=embed_pot_coeff_spinless, &
1154 10 : beta=0.0_dp, matrix_c=spinless_reg)
1155 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
1156 : k=opt_embed%dimen_aux, alpha=1.0_dp, &
1157 : matrix_a=opt_embed%kinetic_mat, matrix_b=embed_pot_coeff_spin, &
1158 10 : beta=0.0_dp, matrix_c=spin_reg)
1159 : ! Copy from the auxiliary structures to the full regularization term
1160 : CALL cp_fm_to_fm_submat(msource=spinless_reg, &
1161 : mtarget=regular_term, &
1162 : nrow=opt_embed%dimen_aux, ncol=1, &
1163 : s_firstrow=1, s_firstcol=1, &
1164 10 : t_firstrow=1, t_firstcol=1)
1165 : CALL cp_fm_to_fm_submat(msource=spin_reg, &
1166 : mtarget=regular_term, &
1167 : nrow=opt_embed%dimen_aux, ncol=1, &
1168 : s_firstrow=1, s_firstcol=1, &
1169 10 : t_firstrow=opt_embed%dimen_aux + 1, t_firstcol=1)
1170 : ! Release internally used auxiliary structures
1171 10 : CALL cp_fm_release(embed_pot_coeff_spinless)
1172 10 : CALL cp_fm_release(embed_pot_coeff_spin)
1173 10 : CALL cp_fm_release(spin_reg)
1174 10 : CALL cp_fm_release(spinless_reg)
1175 :
1176 : ELSE ! Simply multiply
1177 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
1178 : k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
1179 : matrix_a=opt_embed%kinetic_mat, matrix_b=opt_embed%embed_pot_coef, &
1180 6 : beta=0.0_dp, matrix_c=regular_term)
1181 : END IF
1182 :
1183 : ! Scale by the regularization parameter and add to the gradient
1184 16 : CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_grad, 4.0_dp*opt_embed%lambda, regular_term)
1185 :
1186 : ! Calculate the regularization contribution to the energy functional
1187 16 : CALL cp_fm_trace(opt_embed%embed_pot_coef, regular_term, opt_embed%reg_term)
1188 16 : opt_embed%reg_term = 2.0_dp*opt_embed%lambda*opt_embed%reg_term
1189 :
1190 : ! Deallocate regular term
1191 16 : CALL cp_fm_release(regular_term)
1192 :
1193 16 : CALL timestop(handle)
1194 :
1195 16 : END SUBROUTINE calculate_embed_pot_grad
1196 :
1197 : ! **************************************************************************************************
1198 : !> \brief Performs integration for the embedding potential gradient
1199 : !> \param qs_env ...
1200 : !> \param dimen_aux ...
1201 : !> \param rho_r ...
1202 : !> \param rho_spin ...
1203 : !> \param embed_pot_grad ...
1204 : !> \param open_shell_embed ...
1205 : !> \param lri ...
1206 : !> \author Vladimir Rybkin
1207 : ! **************************************************************************************************
1208 16 : SUBROUTINE calculate_embed_pot_grad_inner(qs_env, dimen_aux, rho_r, rho_spin, embed_pot_grad, &
1209 : open_shell_embed, lri)
1210 : TYPE(qs_environment_type), POINTER :: qs_env
1211 : INTEGER :: dimen_aux
1212 : TYPE(pw_r3d_rs_type), INTENT(IN) :: rho_r, rho_spin
1213 : TYPE(cp_fm_type), INTENT(IN) :: embed_pot_grad
1214 : LOGICAL :: open_shell_embed
1215 : TYPE(lri_kind_type), DIMENSION(:), POINTER :: lri
1216 :
1217 : CHARACTER(LEN=*), PARAMETER :: routineN = 'calculate_embed_pot_grad_inner'
1218 :
1219 : INTEGER :: handle, iatom, ikind, l_global, LLL, &
1220 : nrow_local, nsgf, start_pos
1221 16 : INTEGER, DIMENSION(:), POINTER :: row_indices
1222 16 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: pot_grad
1223 16 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1224 : TYPE(cell_type), POINTER :: cell
1225 : TYPE(dft_control_type), POINTER :: dft_control
1226 : TYPE(mp_para_env_type), POINTER :: para_env
1227 16 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1228 16 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1229 :
1230 : ! Needed to store integrals
1231 :
1232 16 : CALL timeset(routineN, handle)
1233 :
1234 : CALL get_qs_env(qs_env=qs_env, &
1235 : particle_set=particle_set, &
1236 : qs_kind_set=qs_kind_set, &
1237 : dft_control=dft_control, &
1238 : cell=cell, &
1239 : atomic_kind_set=atomic_kind_set, &
1240 16 : para_env=para_env)
1241 :
1242 : ! Create wf_vector and gradient
1243 16 : IF (open_shell_embed) THEN
1244 30 : ALLOCATE (pot_grad(dimen_aux*2))
1245 : ELSE
1246 18 : ALLOCATE (pot_grad(dimen_aux))
1247 : END IF
1248 :
1249 : ! Use lri subroutine
1250 38 : DO ikind = 1, SIZE(lri)
1251 2750 : lri(ikind)%v_int = 0.0_dp
1252 : END DO
1253 :
1254 : CALL integrate_v_rspace_one_center(rho_r, qs_env, lri, &
1255 16 : .FALSE., "RI_AUX")
1256 38 : DO ikind = 1, SIZE(lri)
1257 5462 : CALL para_env%sum(lri(ikind)%v_int)
1258 : END DO
1259 :
1260 2392 : pot_grad = 0.0_dp
1261 16 : start_pos = 1
1262 38 : DO ikind = 1, SIZE(lri)
1263 88 : DO iatom = 1, SIZE(lri(ikind)%v_int, DIM=1)
1264 50 : nsgf = SIZE(lri(ikind)%v_int(iatom, :))
1265 1826 : pot_grad(start_pos:start_pos + nsgf - 1) = lri(ikind)%v_int(iatom, :)
1266 72 : start_pos = start_pos + nsgf
1267 : END DO
1268 : END DO
1269 :
1270 : ! Open-shell embedding
1271 16 : IF (open_shell_embed) THEN
1272 20 : DO ikind = 1, SIZE(lri)
1273 920 : lri(ikind)%v_int = 0.0_dp
1274 : END DO
1275 :
1276 : CALL integrate_v_rspace_one_center(rho_spin, qs_env, lri, &
1277 10 : .FALSE., "RI_AUX")
1278 20 : DO ikind = 1, SIZE(lri)
1279 1820 : CALL para_env%sum(lri(ikind)%v_int)
1280 : END DO
1281 :
1282 10 : start_pos = dimen_aux + 1
1283 20 : DO ikind = 1, SIZE(lri)
1284 40 : DO iatom = 1, SIZE(lri(ikind)%v_int, DIM=1)
1285 20 : nsgf = SIZE(lri(ikind)%v_int(iatom, :))
1286 620 : pot_grad(start_pos:start_pos + nsgf - 1) = lri(ikind)%v_int(iatom, :)
1287 30 : start_pos = start_pos + nsgf
1288 : END DO
1289 : END DO
1290 : END IF
1291 :
1292 : ! Scale by the cell volume
1293 2392 : pot_grad = pot_grad*rho_r%pw_grid%dvol
1294 :
1295 : ! Information about full matrix gradient
1296 : CALL cp_fm_get_info(matrix=embed_pot_grad, &
1297 : nrow_local=nrow_local, &
1298 16 : row_indices=row_indices)
1299 :
1300 : ! Copy the gradient into the full matrix
1301 1204 : DO LLL = 1, nrow_local
1302 1188 : l_global = row_indices(LLL)
1303 1204 : embed_pot_grad%local_data(LLL, 1) = pot_grad(l_global)
1304 : END DO
1305 :
1306 16 : DEALLOCATE (pot_grad)
1307 :
1308 16 : CALL timestop(handle)
1309 :
1310 16 : END SUBROUTINE calculate_embed_pot_grad_inner
1311 :
1312 : ! **************************************************************************************************
1313 : !> \brief Calculates kinetic energy matrix in auxiliary basis in the fm format
1314 : !> \param qs_env ...
1315 : !> \param kinetic_mat ...
1316 : !> \author Vladimir Rybkin
1317 : ! **************************************************************************************************
1318 12 : SUBROUTINE compute_kinetic_mat(qs_env, kinetic_mat)
1319 : TYPE(qs_environment_type), POINTER :: qs_env
1320 : TYPE(cp_fm_type), INTENT(IN) :: kinetic_mat
1321 :
1322 : CHARACTER(LEN=*), PARAMETER :: routineN = 'compute_kinetic_mat'
1323 :
1324 : INTEGER :: handle
1325 12 : TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_t
1326 : TYPE(neighbor_list_set_p_type), DIMENSION(:), &
1327 12 : POINTER :: sab_orb
1328 : TYPE(qs_ks_env_type), POINTER :: ks_env
1329 :
1330 12 : CALL timeset(routineN, handle)
1331 :
1332 12 : NULLIFY (ks_env, sab_orb, matrix_t)
1333 :
1334 : ! First, get the dbcsr structure from the overlap matrix
1335 12 : CALL get_qs_env(qs_env=qs_env, ks_env=ks_env, sab_orb=sab_orb)
1336 :
1337 : ! Calculate kinetic matrix
1338 : CALL build_kinetic_matrix(ks_env, matrix_t=matrix_t, &
1339 : matrix_name="KINETIC ENERGY MATRIX", &
1340 : basis_type="RI_AUX", &
1341 12 : sab_nl=sab_orb, calculate_forces=.FALSE.)
1342 :
1343 : ! Change to the fm format
1344 12 : CALL copy_dbcsr_to_fm(matrix_t(1)%matrix, kinetic_mat)
1345 :
1346 : ! Release memory
1347 12 : CALL dbcsr_deallocate_matrix_set(matrix_t)
1348 :
1349 12 : CALL timestop(handle)
1350 :
1351 12 : END SUBROUTINE compute_kinetic_mat
1352 :
1353 : ! **************************************************************************************************
1354 : !> \brief Regularizes the Wu-Yang potential on the grid
1355 : !> \param potential ...
1356 : !> \param pw_env ...
1357 : !> \param lambda ...
1358 : !> \param reg_term ...
1359 : ! **************************************************************************************************
1360 6 : SUBROUTINE grid_regularize(potential, pw_env, lambda, reg_term)
1361 :
1362 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: potential
1363 : TYPE(pw_env_type), POINTER :: pw_env
1364 : REAL(KIND=dp) :: lambda, reg_term
1365 :
1366 : INTEGER :: i, j, k
1367 : INTEGER, DIMENSION(3) :: lb, n, ub
1368 : TYPE(pw_c1d_gs_type) :: dr2_pot, grid_reg_g, potential_g
1369 24 : TYPE(pw_c1d_gs_type), DIMENSION(3) :: dpot_g
1370 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1371 : TYPE(pw_r3d_rs_type) :: grid_reg, square_norm_dpot
1372 24 : TYPE(pw_r3d_rs_type), DIMENSION(3) :: dpot
1373 :
1374 : !
1375 : ! First, the contribution to the gradient
1376 : !
1377 :
1378 : ! Get some of the grids ready
1379 6 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1380 :
1381 6 : CALL auxbas_pw_pool%create_pw(potential_g)
1382 :
1383 6 : CALL auxbas_pw_pool%create_pw(dr2_pot)
1384 :
1385 6 : CALL auxbas_pw_pool%create_pw(grid_reg)
1386 :
1387 6 : CALL auxbas_pw_pool%create_pw(grid_reg_g)
1388 6 : CALL pw_zero(grid_reg_g)
1389 :
1390 : ! Transfer potential to the reciprocal space
1391 6 : CALL pw_transfer(potential, potential_g)
1392 :
1393 : ! Calculate second derivatives: dx^2, dy^2, dz^2
1394 24 : DO i = 1, 3
1395 18 : CALL pw_dr2(potential_g, dr2_pot, i, i)
1396 24 : CALL pw_axpy(dr2_pot, grid_reg_g, 1.0_dp)
1397 : END DO
1398 : ! Transfer potential to the real space
1399 6 : CALL pw_transfer(grid_reg_g, grid_reg)
1400 :
1401 : ! Update the potential with a regularization term
1402 6 : CALL pw_axpy(grid_reg, potential, -4.0_dp*lambda)
1403 :
1404 : !
1405 : ! Second, the contribution to the functional
1406 : !
1407 24 : DO i = 1, 3
1408 18 : CALL auxbas_pw_pool%create_pw(dpot(i))
1409 24 : CALL auxbas_pw_pool%create_pw(dpot_g(i))
1410 : END DO
1411 :
1412 6 : CALL auxbas_pw_pool%create_pw(square_norm_dpot)
1413 :
1414 24 : DO i = 1, 3
1415 18 : n(:) = 0
1416 18 : n(i) = 1
1417 18 : CALL pw_copy(potential_g, dpot_g(i))
1418 18 : CALL pw_derive(dpot_g(i), n(:))
1419 24 : CALL pw_transfer(dpot_g(i), dpot(i))
1420 : END DO
1421 :
1422 24 : lb(1:3) = square_norm_dpot%pw_grid%bounds_local(1, 1:3)
1423 24 : ub(1:3) = square_norm_dpot%pw_grid%bounds_local(2, 1:3)
1424 : !$OMP PARALLEL DO DEFAULT(NONE) &
1425 : !$OMP PRIVATE(i,j,k) &
1426 6 : !$OMP SHARED(dpot, lb, square_norm_dpot, ub)
1427 : DO k = lb(3), ub(3)
1428 : DO j = lb(2), ub(2)
1429 : DO i = lb(1), ub(1)
1430 : square_norm_dpot%array(i, j, k) = (dpot(1)%array(i, j, k)* &
1431 : dpot(1)%array(i, j, k) + &
1432 : dpot(2)%array(i, j, k)* &
1433 : dpot(2)%array(i, j, k) + &
1434 : dpot(3)%array(i, j, k)* &
1435 : dpot(3)%array(i, j, k))
1436 : END DO
1437 : END DO
1438 : END DO
1439 : !$OMP END PARALLEL DO
1440 :
1441 6 : reg_term = 2*lambda*pw_integrate_function(fun=square_norm_dpot)
1442 :
1443 : ! Release
1444 6 : CALL auxbas_pw_pool%give_back_pw(potential_g)
1445 6 : CALL auxbas_pw_pool%give_back_pw(dr2_pot)
1446 6 : CALL auxbas_pw_pool%give_back_pw(grid_reg)
1447 6 : CALL auxbas_pw_pool%give_back_pw(grid_reg_g)
1448 6 : CALL auxbas_pw_pool%give_back_pw(square_norm_dpot)
1449 24 : DO i = 1, 3
1450 18 : CALL auxbas_pw_pool%give_back_pw(dpot(i))
1451 24 : CALL auxbas_pw_pool%give_back_pw(dpot_g(i))
1452 : END DO
1453 :
1454 6 : END SUBROUTINE grid_regularize
1455 :
1456 : ! **************************************************************************************************
1457 : !> \brief Takes maximization step in embedding potential optimization
1458 : !> \param diff_rho_r ...
1459 : !> \param diff_rho_spin ...
1460 : !> \param opt_embed ...
1461 : !> \param embed_pot ...
1462 : !> \param spin_embed_pot ...
1463 : !> \param rho_r_ref ...
1464 : !> \param qs_env ...
1465 : !> \author Vladimir Rybkin
1466 : ! **************************************************************************************************
1467 24 : SUBROUTINE opt_embed_step(diff_rho_r, diff_rho_spin, opt_embed, embed_pot, spin_embed_pot, rho_r_ref, qs_env)
1468 :
1469 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: diff_rho_r, diff_rho_spin
1470 : TYPE(opt_embed_pot_type) :: opt_embed
1471 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
1472 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
1473 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r_ref
1474 : TYPE(qs_environment_type), POINTER :: qs_env
1475 :
1476 : CHARACTER(LEN=*), PARAMETER :: routineN = 'opt_embed_step'
1477 : REAL(KIND=dp), PARAMETER :: thresh = 0.000001_dp
1478 :
1479 : INTEGER :: handle, l_global, LLL, nrow_local
1480 24 : INTEGER, DIMENSION(:), POINTER :: row_indices
1481 24 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenval
1482 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1483 : TYPE(cp_fm_type) :: diag_grad, diag_step, fm_U, fm_U_scale
1484 : TYPE(pw_env_type), POINTER :: pw_env
1485 :
1486 24 : CALL timeset(routineN, handle)
1487 :
1488 24 : IF (opt_embed%grid_opt) THEN ! Grid based optimization
1489 :
1490 8 : opt_embed%step_len = opt_embed%trust_rad
1491 8 : CALL get_qs_env(qs_env=qs_env, pw_env=pw_env)
1492 8 : IF (opt_embed%leeuwen) THEN
1493 : CALL Leeuwen_Baerends_potential_update(pw_env, embed_pot, spin_embed_pot, diff_rho_r, diff_rho_spin, &
1494 2 : rho_r_ref, opt_embed%open_shell_embed, opt_embed%trust_rad)
1495 : ELSE
1496 6 : IF (opt_embed%fab) THEN
1497 : CALL FAB_update(qs_env, rho_r_ref, opt_embed%prev_embed_pot, opt_embed%prev_spin_embed_pot, &
1498 : embed_pot, spin_embed_pot, &
1499 : diff_rho_r, diff_rho_spin, opt_embed%v_w, opt_embed%i_iter, opt_embed%trust_rad, &
1500 2 : opt_embed%open_shell_embed, opt_embed%vw_cutoff, opt_embed%vw_smooth_cutoff_range)
1501 : ELSE
1502 4 : CALL grid_based_step(diff_rho_r, diff_rho_spin, pw_env, opt_embed, embed_pot, spin_embed_pot)
1503 : END IF
1504 : END IF
1505 :
1506 : ELSE ! Finite basis optimization
1507 : ! If the previous step has been rejected, we go back to the previous expansion coefficients
1508 16 : IF (.NOT. opt_embed%accept_step) &
1509 0 : CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_coef, -1.0_dp, opt_embed%step)
1510 :
1511 : ! Do a simple steepest descent
1512 16 : IF (opt_embed%steep_desc) THEN
1513 6 : IF (opt_embed%i_iter .GT. 2) &
1514 : opt_embed%trust_rad = Barzilai_Borwein(opt_embed%step, opt_embed%prev_step, &
1515 0 : opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad)
1516 6 : IF (ABS(opt_embed%trust_rad) .GT. opt_embed%max_trad) THEN
1517 0 : IF (opt_embed%trust_rad .GT. 0.0_dp) THEN
1518 0 : opt_embed%trust_rad = opt_embed%max_trad
1519 : ELSE
1520 0 : opt_embed%trust_rad = -opt_embed%max_trad
1521 : END IF
1522 : END IF
1523 :
1524 6 : CALL cp_fm_to_fm(opt_embed%step, opt_embed%prev_step)
1525 6 : CALL cp_fm_scale_and_add(0.0_dp, opt_embed%prev_step, 1.0_dp, opt_embed%step)
1526 6 : CALL cp_fm_set_all(opt_embed%step, 0.0_dp)
1527 6 : CALL cp_fm_scale_and_add(1.0_dp, opt_embed%step, opt_embed%trust_rad, opt_embed%embed_pot_grad)
1528 6 : opt_embed%step_len = opt_embed%trust_rad
1529 : ELSE
1530 :
1531 : ! First, update the Hessian inverse if needed
1532 10 : IF (opt_embed%i_iter > 1) THEN
1533 2 : IF (opt_embed%accept_step) & ! We don't update Hessian if the step has been rejected
1534 : CALL symm_rank_one_update(opt_embed%embed_pot_grad, opt_embed%prev_embed_pot_grad, &
1535 2 : opt_embed%step, opt_embed%prev_embed_pot_Hess, opt_embed%embed_pot_Hess)
1536 : END IF
1537 :
1538 : ! Add regularization term to the Hessian
1539 : !CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_Hess, 4.0_dp*opt_embed%lambda, &
1540 : ! opt_embed%kinetic_mat)
1541 :
1542 : ! Else use the first initial Hessian. Now it's just the unit matrix: embed_pot_hess
1543 : ! Second, invert the Hessian
1544 30 : ALLOCATE (eigenval(opt_embed%dimen_var_aux))
1545 1666 : eigenval = 0.0_dp
1546 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_hess, &
1547 10 : matrix_struct=fm_struct)
1548 10 : CALL cp_fm_create(fm_U, fm_struct, name="fm_U")
1549 10 : CALL cp_fm_create(fm_U_scale, fm_struct, name="fm_U")
1550 10 : CALL cp_fm_set_all(fm_U, 0.0_dp)
1551 10 : CALL cp_fm_set_all(fm_U_scale, 0.0_dp)
1552 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
1553 10 : matrix_struct=fm_struct)
1554 10 : CALL cp_fm_create(diag_grad, fm_struct, name="diag_grad")
1555 10 : CALL cp_fm_set_all(diag_grad, 0.0_dp)
1556 10 : CALL cp_fm_create(diag_step, fm_struct, name="diag_step")
1557 10 : CALL cp_fm_set_all(diag_step, 0.0_dp)
1558 :
1559 : ! Store the Hessian as it will be destroyed in diagonalization: use fm_U_scal for it
1560 10 : CALL cp_fm_to_fm(opt_embed%embed_pot_hess, fm_U_scale)
1561 :
1562 : ! Diagonalize Hessian
1563 10 : CALL choose_eigv_solver(opt_embed%embed_pot_hess, fm_U, eigenval)
1564 :
1565 : ! Copy the Hessian back
1566 10 : CALL cp_fm_to_fm(fm_U_scale, opt_embed%embed_pot_hess)
1567 :
1568 : ! Find the step in diagonal representation, begin with gradient
1569 : CALL parallel_gemm(transa="T", transb="N", m=opt_embed%dimen_var_aux, n=1, &
1570 : k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
1571 : matrix_a=fm_U, matrix_b=opt_embed%embed_pot_grad, beta=0.0_dp, &
1572 10 : matrix_c=diag_grad)
1573 :
1574 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, &
1575 : nrow_local=nrow_local, &
1576 10 : row_indices=row_indices)
1577 :
1578 838 : DO LLL = 1, nrow_local
1579 828 : l_global = row_indices(LLL)
1580 838 : IF (ABS(eigenval(l_global)) .GE. thresh) THEN
1581 : diag_step%local_data(LLL, 1) = &
1582 828 : -diag_grad%local_data(LLL, 1)/(eigenval(l_global))
1583 : ELSE
1584 0 : diag_step%local_data(LLL, 1) = 0.0_dp
1585 : END IF
1586 : END DO
1587 10 : CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
1588 :
1589 : ! Transform step to a non-diagonal representation
1590 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
1591 : k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
1592 : matrix_a=fm_U, matrix_b=diag_step, beta=0.0_dp, &
1593 10 : matrix_c=opt_embed%step)
1594 :
1595 : ! Now use fm_U_scale for scaled eigenvectors
1596 10 : CALL cp_fm_to_fm(fm_U, fm_U_scale)
1597 10 : CALL cp_fm_column_scale(fm_U_scale, eigenval)
1598 :
1599 10 : CALL cp_fm_release(fm_U_scale)
1600 :
1601 : ! Scale the step to fit within the trust radius: it it's less already,
1602 : ! then take the Newton step
1603 10 : CALL cp_fm_trace(opt_embed%step, opt_embed%step, opt_embed%step_len)
1604 10 : IF (opt_embed%step_len .GT. opt_embed%trust_rad) THEN
1605 :
1606 2 : IF (opt_embed%level_shift) THEN
1607 : ! Find a level shift parameter and apply it
1608 2 : CALL level_shift(opt_embed, diag_grad, eigenval, diag_step)
1609 : ELSE ! Just scale
1610 0 : CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
1611 0 : CALL cp_fm_scale(opt_embed%trust_rad/opt_embed%step_len, diag_step)
1612 : END IF
1613 2 : CALL cp_fm_trace(diag_step, diag_step, opt_embed%step_len)
1614 : ! Transform step to a non-diagonal representation
1615 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_var_aux, n=1, &
1616 : k=opt_embed%dimen_var_aux, alpha=1.0_dp, &
1617 : matrix_a=fm_U, matrix_b=diag_step, beta=0.0_dp, &
1618 2 : matrix_c=opt_embed%step)
1619 2 : CALL cp_fm_trace(opt_embed%step, opt_embed%step, opt_embed%step_len)
1620 :
1621 : ! Recalculate step in diagonal representation
1622 2 : opt_embed%newton_step = .FALSE.
1623 : ELSE
1624 8 : opt_embed%newton_step = .TRUE.
1625 : END IF
1626 :
1627 : ! Release some memory
1628 10 : DEALLOCATE (eigenval)
1629 : ! Release more memory
1630 10 : CALL cp_fm_release(diag_grad)
1631 10 : CALL cp_fm_release(diag_step)
1632 50 : CALL cp_fm_release(fm_U)
1633 :
1634 : END IF ! grad_descent
1635 :
1636 : ! Update the coefficients
1637 16 : CALL cp_fm_scale_and_add(1.0_dp, opt_embed%embed_pot_coef, 1.0_dp, opt_embed%step)
1638 :
1639 : ! Update the embedding potential
1640 : CALL update_embed_pot(opt_embed%embed_pot_coef, opt_embed%dimen_aux, embed_pot, &
1641 : spin_embed_pot, qs_env, opt_embed%add_const_pot, &
1642 16 : opt_embed%open_shell_embed, opt_embed%const_pot)
1643 : END IF ! Grid-based optimization
1644 :
1645 24 : CALL timestop(handle)
1646 :
1647 48 : END SUBROUTINE opt_embed_step
1648 :
1649 : !
1650 : ! **************************************************************************************************
1651 : !> \brief ...
1652 : !> \param diff_rho_r ...
1653 : !> \param diff_rho_spin ...
1654 : !> \param pw_env ...
1655 : !> \param opt_embed ...
1656 : !> \param embed_pot ...
1657 : !> \param spin_embed_pot ...
1658 : ! **************************************************************************************************
1659 4 : SUBROUTINE grid_based_step(diff_rho_r, diff_rho_spin, pw_env, opt_embed, embed_pot, spin_embed_pot)
1660 :
1661 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: diff_rho_r, diff_rho_spin
1662 : TYPE(pw_env_type), POINTER :: pw_env
1663 : TYPE(opt_embed_pot_type) :: opt_embed
1664 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
1665 : TYPE(pw_r3d_rs_type), POINTER :: spin_embed_pot
1666 :
1667 : CHARACTER(LEN=*), PARAMETER :: routineN = 'grid_based_step'
1668 :
1669 : INTEGER :: handle
1670 : REAL(KIND=dp) :: my_reg_term
1671 :
1672 4 : CALL timeset(routineN, handle)
1673 :
1674 : ! Take the step for spin-free part
1675 4 : CALL pw_axpy(diff_rho_r, embed_pot, opt_embed%step_len)
1676 : ! Regularize
1677 4 : CALL grid_regularize(embed_pot, pw_env, opt_embed%lambda, my_reg_term)
1678 4 : opt_embed%reg_term = opt_embed%reg_term + my_reg_term
1679 :
1680 4 : IF (opt_embed%open_shell_embed) THEN
1681 2 : CALL pw_axpy(diff_rho_spin, spin_embed_pot, opt_embed%step_len)
1682 2 : CALL grid_regularize(spin_embed_pot, pw_env, opt_embed%lambda, my_reg_term)
1683 2 : opt_embed%reg_term = opt_embed%reg_term + my_reg_term
1684 : END IF
1685 :
1686 4 : CALL timestop(handle)
1687 :
1688 4 : END SUBROUTINE grid_based_step
1689 :
1690 : ! **************************************************************************************************
1691 : !> \brief ... Adds variable part of to the embedding potential
1692 : !> \param embed_pot_coef ...
1693 : !> \param dimen_aux ...
1694 : !> \param embed_pot ...
1695 : !> \param spin_embed_pot ...
1696 : !> \param qs_env ...
1697 : !> \param add_const_pot ...
1698 : !> \param open_shell_embed ...
1699 : !> \param const_pot ...
1700 : !> \author Vladimir Rybkin
1701 : ! **************************************************************************************************
1702 :
1703 20 : SUBROUTINE update_embed_pot(embed_pot_coef, dimen_aux, embed_pot, spin_embed_pot, &
1704 : qs_env, add_const_pot, open_shell_embed, const_pot)
1705 : TYPE(cp_fm_type), INTENT(IN) :: embed_pot_coef
1706 : INTEGER :: dimen_aux
1707 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
1708 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
1709 : TYPE(qs_environment_type), POINTER :: qs_env
1710 : LOGICAL :: add_const_pot, open_shell_embed
1711 : TYPE(pw_r3d_rs_type), INTENT(IN), OPTIONAL :: const_pot
1712 :
1713 : CHARACTER(LEN=*), PARAMETER :: routineN = 'update_embed_pot'
1714 :
1715 : INTEGER :: handle, l_global, LLL, nrow_local
1716 20 : INTEGER, DIMENSION(:), POINTER :: row_indices
1717 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: wf_vector
1718 20 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
1719 : TYPE(cell_type), POINTER :: cell
1720 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1721 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
1722 : TYPE(cp_fm_type) :: embed_pot_coef_spin, &
1723 : embed_pot_coef_spinless
1724 : TYPE(cp_fm_type), POINTER :: mo_coeff
1725 : TYPE(dft_control_type), POINTER :: dft_control
1726 20 : TYPE(mo_set_type), DIMENSION(:), POINTER :: mos
1727 : TYPE(mp_para_env_type), POINTER :: para_env
1728 20 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
1729 : TYPE(pw_c1d_gs_type) :: rho_g
1730 : TYPE(pw_env_type), POINTER :: pw_env
1731 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1732 : TYPE(pw_r3d_rs_type) :: psi_L
1733 20 : TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
1734 :
1735 20 : CALL timeset(routineN, handle)
1736 : ! Get MO coefficients: we need only the structure, therefore don't care about the spin
1737 : CALL get_qs_env(qs_env=qs_env, &
1738 : particle_set=particle_set, &
1739 : qs_kind_set=qs_kind_set, &
1740 : dft_control=dft_control, &
1741 : cell=cell, &
1742 : atomic_kind_set=atomic_kind_set, &
1743 20 : pw_env=pw_env, mos=mos, para_env=para_env)
1744 20 : CALL get_mo_set(mo_set=mos(1), mo_coeff=mo_coeff)
1745 :
1746 : ! Get plane waves pool
1747 20 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1748 :
1749 : ! get some of the grids ready
1750 20 : CALL auxbas_pw_pool%create_pw(rho_g)
1751 :
1752 20 : CALL auxbas_pw_pool%create_pw(psi_L)
1753 :
1754 : ! Create wf_vector and auxiliary wave functions
1755 60 : ALLOCATE (wf_vector(dimen_aux))
1756 2308 : wf_vector = 0.0_dp
1757 :
1758 : ! Create auxiliary full matrices for open-shell case
1759 20 : IF (open_shell_embed) THEN
1760 12 : NULLIFY (blacs_env)
1761 12 : CALL cp_fm_get_info(matrix=embed_pot_coef, context=blacs_env)
1762 : CALL cp_fm_struct_create(fm_struct, para_env=para_env, context=blacs_env, &
1763 12 : nrow_global=dimen_aux, ncol_global=1)
1764 12 : CALL cp_fm_create(embed_pot_coef_spinless, fm_struct, name="pot_coeff_spinless")
1765 12 : CALL cp_fm_create(embed_pot_coef_spin, fm_struct, name="pot_coeff_spin")
1766 12 : CALL cp_fm_set_all(embed_pot_coef_spinless, 0.0_dp)
1767 12 : CALL cp_fm_set_all(embed_pot_coef_spin, 0.0_dp)
1768 12 : CALL cp_fm_struct_release(fm_struct)
1769 :
1770 : ! Copy coefficients to the auxiliary structures
1771 : CALL cp_fm_to_fm_submat(embed_pot_coef, &
1772 : mtarget=embed_pot_coef_spinless, &
1773 : nrow=dimen_aux, ncol=1, &
1774 : s_firstrow=1, s_firstcol=1, &
1775 12 : t_firstrow=1, t_firstcol=1)
1776 : CALL cp_fm_to_fm_submat(embed_pot_coef, &
1777 : mtarget=embed_pot_coef_spin, &
1778 : nrow=dimen_aux, ncol=1, &
1779 : s_firstrow=dimen_aux + 1, s_firstcol=1, &
1780 12 : t_firstrow=1, t_firstcol=1)
1781 :
1782 : ! Spinless potential
1783 : CALL cp_fm_get_info(matrix=embed_pot_coef_spinless, &
1784 : nrow_local=nrow_local, &
1785 12 : row_indices=row_indices)
1786 :
1787 : ! Copy fm_coeff to an array
1788 372 : DO LLL = 1, nrow_local
1789 360 : l_global = row_indices(LLL)
1790 372 : wf_vector(l_global) = embed_pot_coef_spinless%local_data(LLL, 1)
1791 : END DO
1792 12 : CALL para_env%sum(wf_vector)
1793 :
1794 : ! Calculate the variable part of the embedding potential
1795 : CALL collocate_function(wf_vector, psi_L, rho_g, atomic_kind_set, &
1796 : qs_kind_set, cell, particle_set, pw_env, &
1797 : dft_control%qs_control%eps_rho_rspace, &
1798 12 : basis_type="RI_AUX")
1799 : ! Update the full embedding potential
1800 12 : IF (add_const_pot) THEN
1801 0 : CALL pw_copy(const_pot, embed_pot)
1802 : ELSE
1803 12 : CALL pw_zero(embed_pot)
1804 : END IF
1805 :
1806 12 : CALL pw_axpy(psi_L, embed_pot)
1807 :
1808 : ! Spin-dependent potential
1809 732 : wf_vector = 0.0_dp
1810 : CALL cp_fm_get_info(matrix=embed_pot_coef_spin, &
1811 : nrow_local=nrow_local, &
1812 12 : row_indices=row_indices)
1813 :
1814 : ! Copy fm_coeff to an array
1815 372 : DO LLL = 1, nrow_local
1816 360 : l_global = row_indices(LLL)
1817 372 : wf_vector(l_global) = embed_pot_coef_spin%local_data(LLL, 1)
1818 : END DO
1819 12 : CALL para_env%sum(wf_vector)
1820 :
1821 : ! Calculate the variable part of the embedding potential
1822 : CALL collocate_function(wf_vector, psi_L, rho_g, atomic_kind_set, &
1823 : qs_kind_set, cell, particle_set, pw_env, &
1824 : dft_control%qs_control%eps_rho_rspace, &
1825 12 : basis_type="RI_AUX")
1826 : ! No constant potential for spin-dependent potential
1827 12 : CALL pw_zero(spin_embed_pot)
1828 12 : CALL pw_axpy(psi_L, spin_embed_pot)
1829 :
1830 : ELSE ! Closed shell
1831 :
1832 : CALL cp_fm_get_info(matrix=embed_pot_coef, &
1833 : nrow_local=nrow_local, &
1834 8 : row_indices=row_indices)
1835 :
1836 : ! Copy fm_coeff to an array
1837 792 : DO LLL = 1, nrow_local
1838 784 : l_global = row_indices(LLL)
1839 792 : wf_vector(l_global) = embed_pot_coef%local_data(LLL, 1)
1840 : END DO
1841 8 : CALL para_env%sum(wf_vector)
1842 :
1843 : ! Calculate the variable part of the embedding potential
1844 : CALL calculate_wavefunction(mo_coeff, 1, psi_L, rho_g, atomic_kind_set, &
1845 8 : qs_kind_set, cell, dft_control, particle_set, pw_env)
1846 :
1847 : CALL collocate_function(wf_vector, psi_L, rho_g, atomic_kind_set, &
1848 : qs_kind_set, cell, particle_set, pw_env, &
1849 : dft_control%qs_control%eps_rho_rspace, &
1850 8 : basis_type="RI_AUX")
1851 :
1852 : ! Update the full embedding potential
1853 8 : IF (add_const_pot) THEN
1854 2 : CALL pw_copy(const_pot, embed_pot)
1855 : ELSE
1856 6 : CALL pw_zero(embed_pot)
1857 : END IF
1858 :
1859 8 : CALL pw_axpy(psi_L, embed_pot)
1860 : END IF ! Open/closed shell
1861 :
1862 : ! Deallocate memory and release objects
1863 20 : DEALLOCATE (wf_vector)
1864 20 : CALL auxbas_pw_pool%give_back_pw(psi_L)
1865 20 : CALL auxbas_pw_pool%give_back_pw(rho_g)
1866 :
1867 20 : IF (open_shell_embed) THEN
1868 12 : CALL cp_fm_release(embed_pot_coef_spin)
1869 12 : CALL cp_fm_release(embed_pot_coef_spinless)
1870 : END IF
1871 :
1872 20 : CALL timestop(handle)
1873 :
1874 20 : END SUBROUTINE update_embed_pot
1875 :
1876 : ! **************************************************************************************************
1877 : !> \brief BFGS update of the inverse Hessian in the full matrix format
1878 : !> \param grad ...
1879 : !> \param prev_grad ...
1880 : !> \param step ...
1881 : !> \param prev_inv_Hess ...
1882 : !> \param inv_Hess ...
1883 : !> \author Vladimir Rybkin
1884 : ! **************************************************************************************************
1885 0 : SUBROUTINE inv_Hessian_update(grad, prev_grad, step, prev_inv_Hess, inv_Hess)
1886 : TYPE(cp_fm_type), INTENT(IN) :: grad, prev_grad, step, prev_inv_Hess, &
1887 : inv_Hess
1888 :
1889 : INTEGER :: mat_size
1890 : REAL(KIND=dp) :: factor1, s_dot_y, y_dot_B_inv_y
1891 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_mat, fm_struct_vec
1892 : TYPE(cp_fm_type) :: B_inv_y, B_inv_y_s, s_s, s_y, s_y_B_inv, &
1893 : y
1894 :
1895 : ! Recover the dimension
1896 : CALL cp_fm_get_info(matrix=inv_Hess, &
1897 0 : nrow_global=mat_size)
1898 :
1899 0 : CALL cp_fm_set_all(inv_Hess, 0.0_dp)
1900 0 : CALL cp_fm_to_fm(prev_inv_Hess, inv_Hess)
1901 :
1902 : ! Get full matrix structures
1903 0 : NULLIFY (fm_struct_mat, fm_struct_vec)
1904 :
1905 : CALL cp_fm_get_info(matrix=prev_inv_Hess, &
1906 0 : matrix_struct=fm_struct_mat)
1907 : CALL cp_fm_get_info(matrix=grad, &
1908 0 : matrix_struct=fm_struct_vec)
1909 :
1910 : ! Allocate intermediates
1911 0 : CALL cp_fm_create(B_inv_y, fm_struct_vec, name="B_inv_y")
1912 0 : CALL cp_fm_create(y, fm_struct_vec, name="y")
1913 :
1914 0 : CALL cp_fm_create(s_s, fm_struct_mat, name="s_s")
1915 0 : CALL cp_fm_create(s_y, fm_struct_mat, name="s_y")
1916 0 : CALL cp_fm_create(B_inv_y_s, fm_struct_mat, name="B_inv_y_s")
1917 0 : CALL cp_fm_create(s_y_B_inv, fm_struct_mat, name="s_y_B_inv")
1918 :
1919 0 : CALL cp_fm_set_all(B_inv_y, 0.0_dp)
1920 0 : CALL cp_fm_set_all(s_s, 0.0_dp)
1921 0 : CALL cp_fm_set_all(s_y, 0.0_dp)
1922 0 : CALL cp_fm_set_all(B_inv_y_s, 0.0_dp)
1923 0 : CALL cp_fm_set_all(s_y_B_inv, 0.0_dp)
1924 :
1925 : ! Calculate intermediates
1926 : ! y the is gradient difference
1927 0 : CALL cp_fm_get_info(matrix=grad)
1928 0 : CALL cp_fm_to_fm(grad, y)
1929 0 : CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
1930 :
1931 : ! First term
1932 : CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
1933 : k=mat_size, alpha=1.0_dp, &
1934 : matrix_a=prev_inv_Hess, matrix_b=y, beta=0.0_dp, &
1935 0 : matrix_c=B_inv_y)
1936 :
1937 : CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
1938 : k=1, alpha=1.0_dp, &
1939 : matrix_a=step, matrix_b=step, beta=0.0_dp, &
1940 0 : matrix_c=s_s)
1941 :
1942 : CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
1943 : k=1, alpha=1.0_dp, &
1944 : matrix_a=step, matrix_b=y, beta=0.0_dp, &
1945 0 : matrix_c=s_y)
1946 :
1947 0 : CALL cp_fm_trace(step, y, s_dot_y)
1948 :
1949 0 : CALL cp_fm_trace(y, y, s_dot_y)
1950 0 : CALL cp_fm_trace(step, step, s_dot_y)
1951 :
1952 0 : CALL cp_fm_trace(y, B_inv_y, y_dot_B_inv_y)
1953 :
1954 0 : factor1 = (s_dot_y + y_dot_B_inv_y)/(s_dot_y)**2
1955 :
1956 0 : CALL cp_fm_scale_and_add(1.0_dp, inv_Hess, factor1, s_s)
1957 :
1958 : ! Second term
1959 : CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
1960 : k=1, alpha=1.0_dp, &
1961 : matrix_a=B_inv_y, matrix_b=step, beta=0.0_dp, &
1962 0 : matrix_c=B_inv_y_s)
1963 :
1964 : CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=mat_size, &
1965 : k=mat_size, alpha=1.0_dp, &
1966 : matrix_a=s_y, matrix_b=prev_inv_Hess, beta=0.0_dp, &
1967 0 : matrix_c=s_y_B_inv)
1968 :
1969 0 : CALL cp_fm_scale_and_add(1.0_dp, B_inv_y_s, 1.0_dp, s_y_B_inv)
1970 :
1971 : ! Assemble the new inverse Hessian
1972 0 : CALL cp_fm_scale_and_add(1.0_dp, inv_Hess, -s_dot_y, B_inv_y_s)
1973 :
1974 : ! Deallocate intermediates
1975 0 : CALL cp_fm_release(y)
1976 0 : CALL cp_fm_release(B_inv_y)
1977 0 : CALL cp_fm_release(s_s)
1978 0 : CALL cp_fm_release(s_y)
1979 0 : CALL cp_fm_release(B_inv_y_s)
1980 0 : CALL cp_fm_release(s_y_B_inv)
1981 :
1982 0 : END SUBROUTINE inv_Hessian_update
1983 :
1984 : ! **************************************************************************************************
1985 : !> \brief ...
1986 : !> \param grad ...
1987 : !> \param prev_grad ...
1988 : !> \param step ...
1989 : !> \param prev_Hess ...
1990 : !> \param Hess ...
1991 : ! **************************************************************************************************
1992 0 : SUBROUTINE Hessian_update(grad, prev_grad, step, prev_Hess, Hess)
1993 : TYPE(cp_fm_type), INTENT(IN) :: grad, prev_grad, step, prev_Hess, Hess
1994 :
1995 : INTEGER :: mat_size
1996 : REAL(KIND=dp) :: s_b_s, y_t_s
1997 : TYPE(cp_blacs_env_type), POINTER :: blacs_env
1998 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_mat, fm_struct_vec, &
1999 : fm_struct_vec_t
2000 : TYPE(cp_fm_type) :: B_s, B_s_s_B, s_t_B, y, y_y_t
2001 : TYPE(mp_para_env_type), POINTER :: para_env
2002 :
2003 : ! Recover the dimension
2004 : CALL cp_fm_get_info(matrix=Hess, &
2005 0 : nrow_global=mat_size, para_env=para_env)
2006 :
2007 0 : CALL cp_fm_set_all(Hess, 0.0_dp)
2008 0 : CALL cp_fm_to_fm(prev_Hess, Hess)
2009 :
2010 : ! WARNING: our Hessian must be negative-definite, whereas BFGS makes it positive-definite!
2011 : ! Therefore, we change sign in the beginning and in the end.
2012 0 : CALL cp_fm_scale(-1.0_dp, Hess)
2013 :
2014 : ! Create blacs environment
2015 0 : NULLIFY (blacs_env)
2016 0 : CALL cp_blacs_env_create(blacs_env=blacs_env, para_env=para_env)
2017 :
2018 : ! Get full matrix structures
2019 0 : NULLIFY (fm_struct_mat, fm_struct_vec, fm_struct_vec_t)
2020 :
2021 : CALL cp_fm_get_info(matrix=prev_Hess, &
2022 0 : matrix_struct=fm_struct_mat)
2023 : CALL cp_fm_get_info(matrix=grad, &
2024 0 : matrix_struct=fm_struct_vec)
2025 : CALL cp_fm_struct_create(fm_struct_vec_t, para_env=para_env, context=blacs_env, &
2026 0 : nrow_global=1, ncol_global=mat_size)
2027 :
2028 : ! Allocate intermediates
2029 0 : CALL cp_fm_create(B_s, fm_struct_vec, name="B_s")
2030 0 : CALL cp_fm_create(s_t_B, fm_struct_vec_t, name="s_t_B")
2031 0 : CALL cp_fm_create(y, fm_struct_vec, name="y")
2032 :
2033 0 : CALL cp_fm_create(y_y_t, fm_struct_mat, name="y_y_t")
2034 0 : CALL cp_fm_create(B_s_s_B, fm_struct_mat, name="B_s_s_B")
2035 :
2036 0 : CALL cp_fm_set_all(y_y_t, 0.0_dp)
2037 0 : CALL cp_fm_set_all(y, 0.0_dp)
2038 0 : CALL cp_fm_set_all(B_s_s_B, 0.0_dp)
2039 0 : CALL cp_fm_set_all(B_s, 0.0_dp)
2040 0 : CALL cp_fm_set_all(s_t_B, 0.0_dp)
2041 :
2042 : ! Release the structure created only here
2043 0 : CALL cp_fm_struct_release(fm_struct_vec_t)
2044 :
2045 : ! Calculate intermediates
2046 : ! y the is gradient difference
2047 0 : CALL cp_fm_to_fm(grad, y)
2048 0 : CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
2049 :
2050 : ! First term
2051 : CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
2052 : k=1, alpha=1.0_dp, &
2053 : matrix_a=y, matrix_b=y, beta=0.0_dp, &
2054 0 : matrix_c=y_y_t)
2055 :
2056 0 : CALL cp_fm_trace(y, step, y_t_s)
2057 :
2058 0 : CALL cp_fm_scale_and_add(1.0_dp, Hess, (1.0_dp/y_t_s), y_y_t)
2059 :
2060 : ! Second term
2061 : CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
2062 : k=mat_size, alpha=1.0_dp, &
2063 : matrix_a=Hess, matrix_b=step, beta=0.0_dp, &
2064 0 : matrix_c=B_s)
2065 :
2066 0 : CALL cp_fm_trace(B_s, step, s_B_s)
2067 :
2068 : CALL parallel_gemm(transa="T", transb="N", m=1, n=mat_size, &
2069 : k=mat_size, alpha=1.0_dp, &
2070 : matrix_a=step, matrix_b=Hess, beta=0.0_dp, &
2071 0 : matrix_c=s_t_B)
2072 :
2073 : CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=mat_size, &
2074 : k=1, alpha=1.0_dp, &
2075 : matrix_a=B_s, matrix_b=s_t_B, beta=0.0_dp, &
2076 0 : matrix_c=B_s_s_B)
2077 :
2078 0 : CALL cp_fm_scale_and_add(1.0_dp, Hess, -(1.0_dp/s_B_s), B_s_s_B)
2079 :
2080 : ! WARNING: our Hessian must be negative-definite, whereas BFGS makes it positive-definite!
2081 : ! Therefore, we change sign in the beginning and in the end.
2082 0 : CALL cp_fm_scale(-1.0_dp, Hess)
2083 :
2084 : ! Release blacs environment
2085 0 : CALL cp_blacs_env_release(blacs_env)
2086 :
2087 : ! Deallocate intermediates
2088 0 : CALL cp_fm_release(y_y_t)
2089 0 : CALL cp_fm_release(B_s_s_B)
2090 0 : CALL cp_fm_release(B_s)
2091 0 : CALL cp_fm_release(s_t_B)
2092 0 : CALL cp_fm_release(y)
2093 :
2094 0 : END SUBROUTINE Hessian_update
2095 :
2096 : ! **************************************************************************************************
2097 : !> \brief ...
2098 : !> \param grad ...
2099 : !> \param prev_grad ...
2100 : !> \param step ...
2101 : !> \param prev_Hess ...
2102 : !> \param Hess ...
2103 : ! **************************************************************************************************
2104 10 : SUBROUTINE symm_rank_one_update(grad, prev_grad, step, prev_Hess, Hess)
2105 : TYPE(cp_fm_type), INTENT(IN) :: grad, prev_grad, step, prev_Hess, Hess
2106 :
2107 : INTEGER :: mat_size
2108 : REAL(KIND=dp) :: factor
2109 : TYPE(cp_fm_struct_type), POINTER :: fm_struct_mat, fm_struct_vec
2110 : TYPE(cp_fm_type) :: B_x, y, y_B_x_y_B_x
2111 :
2112 : ! Recover the dimension
2113 2 : CALL cp_fm_get_info(matrix=Hess, nrow_global=mat_size)
2114 :
2115 2 : CALL cp_fm_set_all(Hess, 0.0_dp)
2116 2 : CALL cp_fm_to_fm(prev_Hess, Hess)
2117 :
2118 : ! Get full matrix structures
2119 2 : NULLIFY (fm_struct_mat, fm_struct_vec)
2120 :
2121 : CALL cp_fm_get_info(matrix=prev_Hess, &
2122 2 : matrix_struct=fm_struct_mat)
2123 : CALL cp_fm_get_info(matrix=grad, &
2124 2 : matrix_struct=fm_struct_vec)
2125 :
2126 : ! Allocate intermediates
2127 2 : CALL cp_fm_create(y, fm_struct_vec, name="y")
2128 2 : CALL cp_fm_create(B_x, fm_struct_vec, name="B_x")
2129 2 : CALL cp_fm_create(y_B_x_y_B_x, fm_struct_mat, name="y_B_x_y_B_x")
2130 :
2131 2 : CALL cp_fm_set_all(y, 0.0_dp)
2132 2 : CALL cp_fm_set_all(B_x, 0.0_dp)
2133 2 : CALL cp_fm_set_all(y_B_x_y_B_x, 0.0_dp)
2134 :
2135 : ! Calculate intermediates
2136 : ! y the is gradient difference
2137 2 : CALL cp_fm_to_fm(grad, y)
2138 2 : CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, prev_grad)
2139 :
2140 : CALL parallel_gemm(transa="N", transb="N", m=mat_size, n=1, &
2141 : k=mat_size, alpha=1.0_dp, &
2142 : matrix_a=Hess, matrix_b=step, beta=0.0_dp, &
2143 2 : matrix_c=B_x)
2144 :
2145 2 : CALL cp_fm_scale_and_add(1.0_dp, y, -1.0_dp, B_x)
2146 :
2147 : CALL parallel_gemm(transa="N", transb="T", m=mat_size, n=mat_size, &
2148 : k=1, alpha=1.0_dp, &
2149 : matrix_a=y, matrix_b=y, beta=0.0_dp, &
2150 2 : matrix_c=y_B_x_y_B_x)
2151 :
2152 : ! Scaling factor
2153 2 : CALL cp_fm_trace(y, step, factor)
2154 :
2155 : ! Assemble the Hessian
2156 2 : CALL cp_fm_scale_and_add(1.0_dp, Hess, (1.0_dp/factor), y_B_x_y_B_x)
2157 :
2158 : ! Deallocate intermediates
2159 2 : CALL cp_fm_release(y)
2160 2 : CALL cp_fm_release(B_x)
2161 2 : CALL cp_fm_release(y_B_x_y_B_x)
2162 :
2163 2 : END SUBROUTINE symm_rank_one_update
2164 :
2165 : ! **************************************************************************************************
2166 : !> \brief Controls the step, changes the trust radius if needed in maximization of the V_emb
2167 : !> \param opt_embed ...
2168 : !> \author Vladimir Rybkin
2169 : ! **************************************************************************************************
2170 8 : SUBROUTINE step_control(opt_embed)
2171 : TYPE(opt_embed_pot_type) :: opt_embed
2172 :
2173 : CHARACTER(LEN=*), PARAMETER :: routineN = 'step_control'
2174 :
2175 : INTEGER :: handle
2176 : REAL(KIND=dp) :: actual_ener_change, ener_ratio, &
2177 : lin_term, pred_ener_change, quad_term
2178 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2179 : TYPE(cp_fm_type) :: H_b
2180 :
2181 2 : CALL timeset(routineN, handle)
2182 :
2183 2 : NULLIFY (fm_struct)
2184 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_grad, &
2185 2 : matrix_struct=fm_struct)
2186 2 : CALL cp_fm_create(H_b, fm_struct, name="H_b")
2187 2 : CALL cp_fm_set_all(H_b, 0.0_dp)
2188 :
2189 : ! Calculate the quadratic estimate for the energy
2190 : ! Linear term
2191 2 : CALL cp_fm_trace(opt_embed%step, opt_embed%embed_pot_grad, lin_term)
2192 :
2193 : ! Quadratic term
2194 : CALL parallel_gemm(transa="N", transb="N", m=opt_embed%dimen_aux, n=1, &
2195 : k=opt_embed%dimen_aux, alpha=1.0_dp, &
2196 : matrix_a=opt_embed%embed_pot_Hess, matrix_b=opt_embed%step, &
2197 2 : beta=0.0_dp, matrix_c=H_b)
2198 2 : CALL cp_fm_trace(opt_embed%step, H_b, quad_term)
2199 :
2200 2 : pred_ener_change = lin_term + 0.5_dp*quad_term
2201 :
2202 : ! Reveal actual energy change
2203 : actual_ener_change = opt_embed%w_func(opt_embed%i_iter) - &
2204 2 : opt_embed%w_func(opt_embed%last_accepted)
2205 :
2206 2 : ener_ratio = actual_ener_change/pred_ener_change
2207 :
2208 2 : CALL cp_fm_release(H_b)
2209 :
2210 2 : IF (actual_ener_change .GT. 0.0_dp) THEN ! If energy increases
2211 : ! We accept step
2212 2 : opt_embed%accept_step = .TRUE.
2213 : ! If energy change is larger than the predicted one, increase trust radius twice
2214 : ! Else (between 0 and 1) leave as it is, unless Newton step has been taken and if the step is less than max
2215 2 : IF ((ener_ratio .GT. 1.0_dp) .AND. (.NOT. opt_embed%newton_step) .AND. &
2216 : (opt_embed%trust_rad .LT. opt_embed%max_trad)) &
2217 0 : opt_embed%trust_rad = 2.0_dp*opt_embed%trust_rad
2218 : ELSE ! Energy decreases
2219 : ! If the decrease is not too large we allow this step to be taken
2220 : ! Otherwise, the step is rejected
2221 0 : IF (ABS(actual_ener_change) .GE. opt_embed%allowed_decrease) THEN
2222 0 : opt_embed%accept_step = .FALSE.
2223 : END IF
2224 : ! Trust radius is decreased 4 times unless it's smaller than the minimal allowed value
2225 0 : IF (opt_embed%trust_rad .GE. opt_embed%min_trad) &
2226 0 : opt_embed%trust_rad = 0.25_dp*opt_embed%trust_rad
2227 : END IF
2228 :
2229 2 : IF (opt_embed%accept_step) opt_embed%last_accepted = opt_embed%i_iter
2230 :
2231 2 : CALL timestop(handle)
2232 :
2233 2 : END SUBROUTINE step_control
2234 :
2235 : ! **************************************************************************************************
2236 : !> \brief ...
2237 : !> \param opt_embed ...
2238 : !> \param diag_grad ...
2239 : !> \param eigenval ...
2240 : !> \param diag_step ...
2241 : ! **************************************************************************************************
2242 2 : SUBROUTINE level_shift(opt_embed, diag_grad, eigenval, diag_step)
2243 : TYPE(opt_embed_pot_type) :: opt_embed
2244 : TYPE(cp_fm_type), INTENT(IN) :: diag_grad
2245 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: eigenval
2246 : TYPE(cp_fm_type), INTENT(IN) :: diag_step
2247 :
2248 : CHARACTER(LEN=*), PARAMETER :: routineN = 'level_shift'
2249 : INTEGER, PARAMETER :: max_iter = 25
2250 : REAL(KIND=dp), PARAMETER :: thresh = 0.00001_dp
2251 :
2252 : INTEGER :: handle, i_iter, l_global, LLL, &
2253 : min_index, nrow_local
2254 2 : INTEGER, ALLOCATABLE, DIMENSION(:) :: red_eigenval_map
2255 2 : INTEGER, DIMENSION(:), POINTER :: row_indices
2256 : LOGICAL :: converged, do_shift
2257 : REAL(KIND=dp) :: diag_grad_norm, grad_min, hess_min, shift, shift_max, shift_min, step_len, &
2258 : step_minus_trad, step_minus_trad_first, step_minus_trad_max, step_minus_trad_min
2259 : TYPE(mp_para_env_type), POINTER :: para_env
2260 :
2261 2 : CALL timeset(routineN, handle)
2262 :
2263 : ! Array properties
2264 : CALL cp_fm_get_info(matrix=opt_embed%embed_pot_coef, &
2265 : nrow_local=nrow_local, &
2266 : row_indices=row_indices, &
2267 2 : para_env=para_env)
2268 :
2269 242 : min_index = MINLOC(ABS(eigenval), dim=1)
2270 2 : hess_min = eigenval(min_index)
2271 2 : CALL cp_fm_get_element(diag_grad, min_index, 1, grad_min)
2272 :
2273 2 : CALL cp_fm_trace(diag_grad, diag_grad, diag_grad_norm)
2274 :
2275 2 : IF (hess_min .LT. 0.0_dp) THEN
2276 : !shift_min = -2.0_dp*(diag_grad_norm/opt_embed%trust_rad - min(hess_min, 0.0_dp))
2277 : !shift_max = max(0.0_dp, -hess_min + 0.5_dp*grad_min/opt_embed%trust_rad)
2278 : !shift_max = MIN(-hess_min+0.5_dp*grad_min/opt_embed%trust_rad, 0.0_dp)
2279 2 : shift_max = hess_min + 0.1
2280 : shift_min = diag_grad_norm/opt_embed%trust_rad
2281 2 : shift_min = 10.0_dp
2282 : !If (abs(shift_max) .LE. thresh) then
2283 : ! shift_min = -20.0_dp*(diag_grad_norm/opt_embed%trust_rad - min(hess_min, 0.0_dp))
2284 : !Else
2285 : ! shift_min = 20.0_dp*shift_max
2286 : !Endif
2287 :
2288 : ! The boundary values
2289 2 : step_minus_trad_max = shifted_step(diag_grad, eigenval, shift_max, opt_embed%trust_rad)
2290 2 : step_minus_trad_min = shifted_step(diag_grad, eigenval, shift_min, opt_embed%trust_rad)
2291 :
2292 : ! Find zero by bisection
2293 2 : converged = .FALSE.
2294 2 : do_shift = .FALSE.
2295 2 : IF (ABS(step_minus_trad_max) .LE. thresh) THEN
2296 0 : shift = shift_max
2297 : ELSE
2298 2 : IF (ABS(step_minus_trad_min) .LE. thresh) THEN
2299 0 : shift = shift_min
2300 : ELSE
2301 28 : DO i_iter = 1, max_iter
2302 28 : shift = 0.5_dp*(shift_max + shift_min)
2303 28 : step_minus_trad = shifted_step(diag_grad, eigenval, shift, opt_embed%trust_rad)
2304 28 : IF (i_iter .EQ. 1) step_minus_trad_first = step_minus_trad
2305 28 : IF (step_minus_trad .GT. 0.0_dp) shift_max = shift
2306 28 : IF (step_minus_trad .LT. 0.0_dp) shift_min = shift
2307 : !IF (ABS(shift_max-shift_min) .LT. thresh) converged = .TRUE.
2308 28 : IF (ABS(step_minus_trad) .LT. thresh) converged = .TRUE.
2309 26 : IF (converged) EXIT
2310 : END DO
2311 2 : IF (ABS(step_minus_trad) .LT. ABS(step_minus_trad_first)) do_shift = .TRUE.
2312 : END IF
2313 : END IF
2314 : ! Apply level-shifting
2315 2 : IF (converged .OR. do_shift) THEN
2316 122 : DO LLL = 1, nrow_local
2317 120 : l_global = row_indices(LLL)
2318 122 : IF (ABS(eigenval(l_global)) .GE. thresh) THEN
2319 : diag_step%local_data(LLL, 1) = &
2320 120 : -diag_grad%local_data(LLL, 1)/(eigenval(l_global) - shift)
2321 : ELSE
2322 0 : diag_step%local_data(LLL, 1) = 0.0_dp
2323 : END IF
2324 : END DO
2325 : END IF
2326 2 : IF (.NOT. converged) THEN ! Scale if shift has not been found
2327 0 : CALL cp_fm_trace(diag_step, diag_step, step_len)
2328 0 : CALL cp_fm_scale(opt_embed%trust_rad/step_len, diag_step)
2329 : END IF
2330 :
2331 : ! Special case
2332 : ELSE ! Hess min .LT. 0.0_dp
2333 : ! First, find all positive eigenvalues
2334 0 : ALLOCATE (red_eigenval_map(opt_embed%dimen_var_aux))
2335 0 : red_eigenval_map = 0
2336 0 : DO LLL = 1, nrow_local
2337 0 : l_global = row_indices(LLL)
2338 0 : IF (eigenval(l_global) .GE. 0.0_dp) THEN
2339 0 : red_eigenval_map(l_global) = 1
2340 : END IF
2341 : END DO
2342 0 : CALL para_env%sum(red_eigenval_map)
2343 :
2344 : ! Set shift as -hess_min and find step on the reduced space of negative-value
2345 : ! eigenvectors
2346 0 : shift = -hess_min
2347 0 : DO LLL = 1, nrow_local
2348 0 : l_global = row_indices(LLL)
2349 0 : IF (red_eigenval_map(l_global) .EQ. 0) THEN
2350 0 : IF (ABS(eigenval(l_global)) .GE. thresh) THEN
2351 : diag_step%local_data(LLL, 1) = &
2352 0 : -diag_grad%local_data(LLL, 1)/(eigenval(l_global) - shift)
2353 : ELSE
2354 0 : diag_step%local_data(LLL, 1) = 0.0_dp
2355 : END IF
2356 : ELSE
2357 0 : diag_step%local_data(LLL, 1) = 0.0_dp
2358 : END IF
2359 : END DO
2360 :
2361 : ! Find the step length of such a step
2362 0 : CALL cp_fm_trace(diag_step, diag_step, step_len)
2363 :
2364 : END IF
2365 :
2366 2 : CALL timestop(handle)
2367 :
2368 4 : END SUBROUTINE level_shift
2369 :
2370 : ! **************************************************************************************************
2371 : !> \brief ...
2372 : !> \param diag_grad ...
2373 : !> \param eigenval ...
2374 : !> \param shift ...
2375 : !> \param trust_rad ...
2376 : !> \return ...
2377 : ! **************************************************************************************************
2378 32 : FUNCTION shifted_step(diag_grad, eigenval, shift, trust_rad) RESULT(step_minus_trad)
2379 : TYPE(cp_fm_type), INTENT(IN) :: diag_grad
2380 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:), &
2381 : INTENT(IN) :: eigenval
2382 : REAL(KIND=dp), INTENT(IN) :: shift, trust_rad
2383 : REAL(KIND=dp) :: step_minus_trad
2384 :
2385 : REAL(KIND=dp), PARAMETER :: thresh = 0.000001_dp
2386 :
2387 : INTEGER :: l_global, LLL, nrow_local
2388 32 : INTEGER, DIMENSION(:), POINTER :: row_indices
2389 : REAL(KIND=dp) :: step, step_1d
2390 : TYPE(mp_para_env_type), POINTER :: para_env
2391 :
2392 : CALL cp_fm_get_info(matrix=diag_grad, &
2393 : nrow_local=nrow_local, &
2394 : row_indices=row_indices, &
2395 32 : para_env=para_env)
2396 :
2397 32 : step = 0.0_dp
2398 1952 : DO LLL = 1, nrow_local
2399 1920 : l_global = row_indices(LLL)
2400 1952 : IF ((ABS(eigenval(l_global)) .GE. thresh) .AND. (ABS(diag_grad%local_data(LLL, 1)) .GE. thresh)) THEN
2401 16 : step_1d = -diag_grad%local_data(LLL, 1)/(eigenval(l_global) + shift)
2402 16 : step = step + step_1d**2
2403 : END IF
2404 : END DO
2405 :
2406 32 : CALL para_env%sum(step)
2407 :
2408 32 : step_minus_trad = SQRT(step) - trust_rad
2409 :
2410 32 : END FUNCTION shifted_step
2411 :
2412 : ! **************************************************************************************************
2413 : !> \brief ...
2414 : !> \param step ...
2415 : !> \param prev_step ...
2416 : !> \param grad ...
2417 : !> \param prev_grad ...
2418 : !> \return ...
2419 : !> \retval length ...
2420 : ! **************************************************************************************************
2421 0 : FUNCTION Barzilai_Borwein(step, prev_step, grad, prev_grad) RESULT(length)
2422 : TYPE(cp_fm_type), INTENT(IN) :: step, prev_step, grad, prev_grad
2423 : REAL(KIND=dp) :: length
2424 :
2425 : REAL(KIND=dp) :: denominator, numerator
2426 : TYPE(cp_fm_struct_type), POINTER :: fm_struct
2427 : TYPE(cp_fm_type) :: grad_diff, step_diff
2428 :
2429 : ! Get full matrix structures
2430 0 : NULLIFY (fm_struct)
2431 :
2432 : CALL cp_fm_get_info(matrix=grad, &
2433 0 : matrix_struct=fm_struct)
2434 :
2435 : ! Allocate intermediates
2436 0 : CALL cp_fm_create(grad_diff, fm_struct, name="grad_diff")
2437 0 : CALL cp_fm_create(step_diff, fm_struct, name="step_diff")
2438 :
2439 : ! Calculate intermediates
2440 0 : CALL cp_fm_to_fm(grad, grad_diff)
2441 0 : CALL cp_fm_to_fm(step, step_diff)
2442 :
2443 0 : CALL cp_fm_scale_and_add(1.0_dp, grad_diff, -1.0_dp, prev_grad)
2444 0 : CALL cp_fm_scale_and_add(1.0_dp, step_diff, -1.0_dp, prev_step)
2445 :
2446 0 : CALL cp_fm_trace(step_diff, grad_diff, numerator)
2447 0 : CALL cp_fm_trace(grad_diff, grad_diff, denominator)
2448 :
2449 : ! Release intermediates
2450 0 : CALL cp_fm_release(grad_diff)
2451 0 : CALL cp_fm_release(step_diff)
2452 :
2453 0 : length = numerator/denominator
2454 :
2455 0 : END FUNCTION Barzilai_Borwein
2456 :
2457 : ! **************************************************************************************************
2458 : !> \brief ...
2459 : !> \param pw_env ...
2460 : !> \param embed_pot ...
2461 : !> \param spin_embed_pot ...
2462 : !> \param diff_rho_r ...
2463 : !> \param diff_rho_spin ...
2464 : !> \param rho_r_ref ...
2465 : !> \param open_shell_embed ...
2466 : !> \param step_len ...
2467 : ! **************************************************************************************************
2468 2 : SUBROUTINE Leeuwen_Baerends_potential_update(pw_env, embed_pot, spin_embed_pot, diff_rho_r, diff_rho_spin, &
2469 : rho_r_ref, open_shell_embed, step_len)
2470 : TYPE(pw_env_type), POINTER :: pw_env
2471 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
2472 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
2473 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r, diff_rho_spin
2474 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r_ref
2475 : LOGICAL, INTENT(IN) :: open_shell_embed
2476 : REAL(KIND=dp), INTENT(IN) :: step_len
2477 :
2478 : CHARACTER(LEN=*), PARAMETER :: routineN = 'Leeuwen_Baerends_potential_update'
2479 :
2480 : INTEGER :: handle, i, i_spin, j, k, nspins
2481 : INTEGER, DIMENSION(3) :: lb, ub
2482 : REAL(KIND=dp) :: my_rho, rho_cutoff
2483 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
2484 2 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: new_embed_pot, rho_n_1, temp_embed_pot
2485 :
2486 2 : CALL timeset(routineN, handle)
2487 :
2488 2 : rho_cutoff = EPSILON(0.0_dp)
2489 :
2490 : ! Prepare plane-waves pool
2491 2 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
2492 2 : NULLIFY (new_embed_pot)
2493 :
2494 2 : nspins = 1
2495 2 : IF (open_shell_embed) nspins = 2
2496 : NULLIFY (new_embed_pot)
2497 8 : ALLOCATE (new_embed_pot(nspins))
2498 6 : DO i_spin = 1, nspins
2499 4 : CALL auxbas_pw_pool%create_pw(new_embed_pot(i_spin))
2500 6 : CALL pw_zero(new_embed_pot(i_spin))
2501 : END DO
2502 :
2503 8 : lb(1:3) = embed_pot%pw_grid%bounds_local(1, 1:3)
2504 8 : ub(1:3) = embed_pot%pw_grid%bounds_local(2, 1:3)
2505 :
2506 2 : IF (.NOT. open_shell_embed) THEN
2507 : !$OMP PARALLEL DO DEFAULT(NONE) &
2508 : !$OMP PRIVATE(i,j,k, my_rho) &
2509 0 : !$OMP SHARED(new_embed_pot, embed_pot, diff_rho_r, rho_r_ref, lb, ub, rho_cutoff, step_len)
2510 : DO k = lb(3), ub(3)
2511 : DO j = lb(2), ub(2)
2512 : DO i = lb(1), ub(1)
2513 : IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
2514 : my_rho = rho_r_ref(1)%array(i, j, k)
2515 : ELSE
2516 : my_rho = rho_cutoff
2517 : END IF
2518 : new_embed_pot(1)%array(i, j, k) = step_len*embed_pot%array(i, j, k)* &
2519 : (diff_rho_r%array(i, j, k) + rho_r_ref(1)%array(i, j, k))/my_rho
2520 : END DO
2521 : END DO
2522 : END DO
2523 : !$OMP END PARALLEL DO
2524 0 : CALL pw_copy(new_embed_pot(1), embed_pot)
2525 :
2526 : ELSE
2527 : ! One has to work with spin components rather than with total and spin density
2528 2 : NULLIFY (rho_n_1)
2529 8 : ALLOCATE (rho_n_1(nspins))
2530 2 : NULLIFY (temp_embed_pot)
2531 8 : ALLOCATE (temp_embed_pot(nspins))
2532 6 : DO i_spin = 1, nspins
2533 4 : CALL auxbas_pw_pool%create_pw(rho_n_1(i_spin))
2534 4 : CALL pw_zero(rho_n_1(i_spin))
2535 4 : CALL auxbas_pw_pool%create_pw(temp_embed_pot(i_spin))
2536 6 : CALL pw_zero(temp_embed_pot(i_spin))
2537 : END DO
2538 2 : CALL pw_copy(diff_rho_r, rho_n_1(1))
2539 2 : CALL pw_copy(diff_rho_r, rho_n_1(2))
2540 2 : CALL pw_axpy(diff_rho_spin, rho_n_1(1), 1.0_dp)
2541 2 : CALL pw_axpy(diff_rho_spin, rho_n_1(2), -1.0_dp)
2542 2 : CALL pw_scale(rho_n_1(1), a=0.5_dp)
2543 2 : CALL pw_scale(rho_n_1(2), a=0.5_dp)
2544 :
2545 2 : CALL pw_copy(embed_pot, temp_embed_pot(1))
2546 2 : CALL pw_copy(embed_pot, temp_embed_pot(2))
2547 2 : CALL pw_axpy(spin_embed_pot, temp_embed_pot(1), 1.0_dp)
2548 2 : CALL pw_axpy(spin_embed_pot, temp_embed_pot(2), -1.0_dp)
2549 :
2550 2 : IF (SIZE(rho_r_ref) .EQ. 2) THEN
2551 2 : CALL pw_axpy(rho_r_ref(1), rho_n_1(1), 1.0_dp)
2552 2 : CALL pw_axpy(rho_r_ref(2), rho_n_1(2), 1.0_dp)
2553 :
2554 : !$OMP PARALLEL DO DEFAULT(NONE) &
2555 : !$OMP PRIVATE(i,j,k, my_rho) &
2556 2 : !$OMP SHARED(new_embed_pot, temp_embed_pot, rho_r_ref, rho_n_1, lb, ub, rho_cutoff, step_len)
2557 : DO k = lb(3), ub(3)
2558 : DO j = lb(2), ub(2)
2559 : DO i = lb(1), ub(1)
2560 : IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
2561 : my_rho = rho_r_ref(1)%array(i, j, k)
2562 : ELSE
2563 : my_rho = rho_cutoff
2564 : END IF
2565 : new_embed_pot(1)%array(i, j, k) = step_len*temp_embed_pot(1)%array(i, j, k)* &
2566 : (rho_n_1(1)%array(i, j, k))/my_rho
2567 : IF (rho_r_ref(2)%array(i, j, k) .GT. rho_cutoff) THEN
2568 : my_rho = rho_r_ref(2)%array(i, j, k)
2569 : ELSE
2570 : my_rho = rho_cutoff
2571 : END IF
2572 : new_embed_pot(2)%array(i, j, k) = step_len*temp_embed_pot(2)%array(i, j, k)* &
2573 : (rho_n_1(2)%array(i, j, k))/my_rho
2574 : END DO
2575 : END DO
2576 : END DO
2577 : !$OMP END PARALLEL DO
2578 :
2579 : ELSE ! Reference system is closed-shell
2580 0 : CALL pw_axpy(rho_r_ref(1), rho_n_1(1), 1.0_dp)
2581 : ! The beta spin component is here equal to the difference: nothing to do
2582 :
2583 : !$OMP PARALLEL DO DEFAULT(NONE) &
2584 : !$OMP PRIVATE(i,j,k, my_rho) &
2585 0 : !$OMP SHARED(new_embed_pot, rho_r_ref, temp_embed_pot, rho_n_1, lb, ub, rho_cutoff, step_len)
2586 : DO k = lb(3), ub(3)
2587 : DO j = lb(2), ub(2)
2588 : DO i = lb(1), ub(1)
2589 : IF (rho_r_ref(1)%array(i, j, k) .GT. rho_cutoff) THEN
2590 : my_rho = 0.5_dp*rho_r_ref(1)%array(i, j, k)
2591 : ELSE
2592 : my_rho = rho_cutoff
2593 : END IF
2594 : new_embed_pot(1)%array(i, j, k) = step_len*temp_embed_pot(1)%array(i, j, k)* &
2595 : (rho_n_1(1)%array(i, j, k))/my_rho
2596 : new_embed_pot(2)%array(i, j, k) = step_len*temp_embed_pot(2)%array(i, j, k)* &
2597 : (rho_n_1(2)%array(i, j, k))/my_rho
2598 : END DO
2599 : END DO
2600 : END DO
2601 : !$OMP END PARALLEL DO
2602 : END IF
2603 :
2604 2 : CALL pw_copy(new_embed_pot(1), embed_pot)
2605 2 : CALL pw_axpy(new_embed_pot(2), embed_pot, 1.0_dp)
2606 2 : CALL pw_scale(embed_pot, a=0.5_dp)
2607 2 : CALL pw_copy(new_embed_pot(1), spin_embed_pot)
2608 2 : CALL pw_axpy(new_embed_pot(2), spin_embed_pot, -1.0_dp)
2609 2 : CALL pw_scale(spin_embed_pot, a=0.5_dp)
2610 :
2611 6 : DO i_spin = 1, nspins
2612 4 : CALL rho_n_1(i_spin)%release()
2613 6 : CALL temp_embed_pot(i_spin)%release()
2614 : END DO
2615 2 : DEALLOCATE (rho_n_1)
2616 2 : DEALLOCATE (temp_embed_pot)
2617 : END IF
2618 :
2619 6 : DO i_spin = 1, nspins
2620 6 : CALL new_embed_pot(i_spin)%release()
2621 : END DO
2622 :
2623 2 : DEALLOCATE (new_embed_pot)
2624 :
2625 2 : CALL timestop(handle)
2626 :
2627 2 : END SUBROUTINE Leeuwen_Baerends_potential_update
2628 :
2629 : ! **************************************************************************************************
2630 : !> \brief ...
2631 : !> \param qs_env ...
2632 : !> \param rho_r_ref ...
2633 : !> \param prev_embed_pot ...
2634 : !> \param prev_spin_embed_pot ...
2635 : !> \param embed_pot ...
2636 : !> \param spin_embed_pot ...
2637 : !> \param diff_rho_r ...
2638 : !> \param diff_rho_spin ...
2639 : !> \param v_w_ref ...
2640 : !> \param i_iter ...
2641 : !> \param step_len ...
2642 : !> \param open_shell_embed ...
2643 : !> \param vw_cutoff ...
2644 : !> \param vw_smooth_cutoff_range ...
2645 : ! **************************************************************************************************
2646 2 : SUBROUTINE FAB_update(qs_env, rho_r_ref, prev_embed_pot, prev_spin_embed_pot, embed_pot, spin_embed_pot, &
2647 : diff_rho_r, diff_rho_spin, v_w_ref, i_iter, step_len, open_shell_embed, &
2648 : vw_cutoff, vw_smooth_cutoff_range)
2649 : TYPE(qs_environment_type), POINTER :: qs_env
2650 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r_ref
2651 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: prev_embed_pot
2652 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: prev_spin_embed_pot
2653 : TYPE(pw_r3d_rs_type), INTENT(INOUT) :: embed_pot
2654 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: spin_embed_pot
2655 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r, diff_rho_spin
2656 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: v_w_ref
2657 : INTEGER, INTENT(IN) :: i_iter
2658 : REAL(KIND=dp) :: step_len
2659 : LOGICAL :: open_shell_embed
2660 : REAL(KIND=dp) :: vw_cutoff, vw_smooth_cutoff_range
2661 :
2662 : CHARACTER(LEN=*), PARAMETER :: routineN = 'FAB_update'
2663 :
2664 : INTEGER :: handle, i_spin, nspins
2665 : TYPE(pw_env_type), POINTER :: pw_env
2666 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
2667 2 : TYPE(pw_r3d_rs_type), ALLOCATABLE, DIMENSION(:) :: new_embed_pot, temp_embed_pot, v_w
2668 2 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: curr_rho
2669 :
2670 2 : CALL timeset(routineN, handle)
2671 :
2672 : ! Update formula: v(n+1) = v(n-1) - v_w(ref) + v_w(n)
2673 :
2674 : CALL get_qs_env(qs_env=qs_env, &
2675 2 : pw_env=pw_env)
2676 : ! Get plane waves pool
2677 2 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
2678 :
2679 : ! We calculate von Weizsaecker potential for the reference density
2680 : ! only at the first iteration
2681 2 : IF (i_iter .LE. 1) THEN
2682 2 : nspins = SIZE(rho_r_ref)
2683 2 : NULLIFY (v_w_ref)
2684 8 : ALLOCATE (v_w_ref(nspins))
2685 4 : DO i_spin = 1, nspins
2686 4 : CALL auxbas_pw_pool%create_pw(v_w_ref(i_spin))
2687 : END DO
2688 2 : CALL Von_Weizsacker(rho_r_ref, v_w_ref, qs_env, vw_cutoff, vw_smooth_cutoff_range)
2689 : ! For the first step previous are set to current
2690 2 : CALL pw_copy(embed_pot, prev_embed_pot)
2691 2 : CALL pw_axpy(diff_rho_r, embed_pot, 0.5_dp)
2692 2 : IF (open_shell_embed) THEN
2693 0 : CALL pw_copy(spin_embed_pot, prev_spin_embed_pot)
2694 0 : CALL pw_axpy(diff_rho_r, embed_pot, 0.5_dp)
2695 : END IF
2696 :
2697 : ELSE
2698 :
2699 : ! Reference can be closed shell, but total embedding - open shell:
2700 : ! redefine nspins
2701 0 : nspins = 1
2702 0 : IF (open_shell_embed) nspins = 2
2703 0 : ALLOCATE (new_embed_pot(nspins))
2704 0 : ALLOCATE (v_w(nspins))
2705 0 : NULLIFY (curr_rho)
2706 0 : ALLOCATE (curr_rho(nspins))
2707 0 : DO i_spin = 1, nspins
2708 0 : CALL auxbas_pw_pool%create_pw(new_embed_pot(i_spin))
2709 0 : CALL pw_zero(new_embed_pot(i_spin))
2710 :
2711 0 : CALL auxbas_pw_pool%create_pw(v_w(i_spin))
2712 0 : CALL pw_zero(v_w(i_spin))
2713 :
2714 0 : CALL auxbas_pw_pool%create_pw(curr_rho(i_spin))
2715 0 : CALL pw_zero(curr_rho(i_spin))
2716 : END DO
2717 :
2718 : ! Now, deal with the current density
2719 :
2720 0 : IF (.NOT. open_shell_embed) THEN
2721 : ! Reconstruct current density
2722 0 : CALL pw_copy(diff_rho_r, curr_rho(1))
2723 0 : CALL pw_axpy(rho_r_ref(1), curr_rho(1), 1.0_dp)
2724 : ! Compute von Weizsaecker potential
2725 0 : CALL Von_Weizsacker(curr_rho, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
2726 : ! Compute new embedding potential
2727 0 : CALL pw_copy(prev_embed_pot, new_embed_pot(1))
2728 0 : CALL pw_axpy(v_w(1), new_embed_pot(1), step_len)
2729 0 : CALL pw_axpy(v_w_ref(1), new_embed_pot(1), -step_len)
2730 : ! Copy the potentials
2731 :
2732 0 : CALL pw_copy(embed_pot, prev_embed_pot)
2733 0 : CALL pw_copy(new_embed_pot(1), embed_pot)
2734 :
2735 : ELSE
2736 : ! Reconstruct current density
2737 0 : CALL pw_copy(diff_rho_r, curr_rho(1))
2738 0 : CALL pw_copy(diff_rho_r, curr_rho(2))
2739 0 : CALL pw_axpy(diff_rho_spin, curr_rho(1), 1.0_dp)
2740 0 : CALL pw_axpy(diff_rho_spin, curr_rho(2), -1.0_dp)
2741 0 : CALL pw_scale(curr_rho(1), a=0.5_dp)
2742 0 : CALL pw_scale(curr_rho(2), a=0.5_dp)
2743 :
2744 0 : IF (SIZE(rho_r_ref) .EQ. 1) THEN ! If reference system is closed-shell
2745 0 : CALL pw_axpy(rho_r_ref(1), curr_rho(1), 0.5_dp)
2746 0 : CALL pw_axpy(rho_r_ref(1), curr_rho(2), 0.5_dp)
2747 : ELSE ! If reference system is open-shell
2748 0 : CALL pw_axpy(rho_r_ref(1), curr_rho(1), 1.0_dp)
2749 0 : CALL pw_axpy(rho_r_ref(2), curr_rho(2), 1.0_dp)
2750 : END IF
2751 :
2752 : ! Compute von Weizsaecker potential
2753 0 : CALL Von_Weizsacker(curr_rho, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
2754 :
2755 : ! Reconstruct corrent spin components of the potential
2756 0 : ALLOCATE (temp_embed_pot(nspins))
2757 0 : DO i_spin = 1, nspins
2758 0 : CALL auxbas_pw_pool%create_pw(temp_embed_pot(i_spin))
2759 0 : CALL pw_zero(temp_embed_pot(i_spin))
2760 : END DO
2761 0 : CALL pw_copy(embed_pot, temp_embed_pot(1))
2762 0 : CALL pw_copy(embed_pot, temp_embed_pot(2))
2763 0 : CALL pw_axpy(spin_embed_pot, temp_embed_pot(1), 1.0_dp)
2764 0 : CALL pw_axpy(spin_embed_pot, temp_embed_pot(2), -1.0_dp)
2765 :
2766 : ! Compute new embedding potential
2767 0 : IF (SIZE(v_w_ref) .EQ. 1) THEN ! Reference system is closed-shell
2768 0 : CALL pw_copy(temp_embed_pot(1), new_embed_pot(1))
2769 0 : CALL pw_axpy(v_w(1), new_embed_pot(1), 0.5_dp*step_len)
2770 0 : CALL pw_axpy(v_w_ref(1), new_embed_pot(1), -0.5_dp*step_len)
2771 :
2772 0 : CALL pw_copy(temp_embed_pot(2), new_embed_pot(2))
2773 0 : CALL pw_axpy(v_w(2), new_embed_pot(2), 0.5_dp)
2774 0 : CALL pw_axpy(v_w_ref(1), new_embed_pot(2), -0.5_dp)
2775 :
2776 : ELSE ! Reference system is open-shell
2777 :
2778 0 : DO i_spin = 1, nspins
2779 0 : CALL pw_copy(temp_embed_pot(i_spin), new_embed_pot(i_spin))
2780 0 : CALL pw_axpy(v_w(1), new_embed_pot(i_spin), step_len)
2781 0 : CALL pw_axpy(v_w_ref(i_spin), new_embed_pot(i_spin), -step_len)
2782 : END DO
2783 : END IF
2784 :
2785 : ! Update embedding potentials
2786 0 : CALL pw_copy(embed_pot, prev_embed_pot)
2787 0 : CALL pw_copy(spin_embed_pot, prev_spin_embed_pot)
2788 :
2789 0 : CALL pw_copy(new_embed_pot(1), embed_pot)
2790 0 : CALL pw_axpy(new_embed_pot(2), embed_pot, 1.0_dp)
2791 0 : CALL pw_scale(embed_pot, a=0.5_dp)
2792 0 : CALL pw_copy(new_embed_pot(1), spin_embed_pot)
2793 0 : CALL pw_axpy(new_embed_pot(2), spin_embed_pot, -1.0_dp)
2794 0 : CALL pw_scale(spin_embed_pot, a=0.5_dp)
2795 :
2796 0 : DO i_spin = 1, nspins
2797 0 : CALL temp_embed_pot(i_spin)%release()
2798 : END DO
2799 0 : DEALLOCATE (temp_embed_pot)
2800 :
2801 : END IF
2802 :
2803 0 : DO i_spin = 1, nspins
2804 0 : CALL curr_rho(i_spin)%release()
2805 0 : CALL new_embed_pot(i_spin)%release()
2806 0 : CALL v_w(i_spin)%release()
2807 : END DO
2808 :
2809 0 : DEALLOCATE (new_embed_pot)
2810 0 : DEALLOCATE (v_w)
2811 0 : DEALLOCATE (curr_rho)
2812 :
2813 : END IF
2814 :
2815 2 : CALL timestop(handle)
2816 :
2817 4 : END SUBROUTINE FAB_update
2818 :
2819 : ! **************************************************************************************************
2820 : !> \brief ...
2821 : !> \param rho_r ...
2822 : !> \param v_w ...
2823 : !> \param qs_env ...
2824 : !> \param vw_cutoff ...
2825 : !> \param vw_smooth_cutoff_range ...
2826 : ! **************************************************************************************************
2827 2 : SUBROUTINE Von_Weizsacker(rho_r, v_w, qs_env, vw_cutoff, vw_smooth_cutoff_range)
2828 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
2829 : TYPE(pw_r3d_rs_type), DIMENSION(:), INTENT(IN) :: v_w
2830 : TYPE(qs_environment_type), POINTER :: qs_env
2831 : REAL(KIND=dp), INTENT(IN) :: vw_cutoff, vw_smooth_cutoff_range
2832 :
2833 : REAL(KIND=dp), PARAMETER :: one_4 = 0.25_dp, one_8 = 0.125_dp
2834 :
2835 : INTEGER :: i, i_spin, j, k, nspins
2836 : INTEGER, DIMENSION(3) :: lb, ub
2837 : REAL(KIND=dp) :: density_smooth_cut_range, my_rho, &
2838 : rho_cutoff
2839 2 : REAL(kind=dp), DIMENSION(:, :, :), POINTER :: rhoa, rhob
2840 2 : TYPE(pw_c1d_gs_type), DIMENSION(:), POINTER :: rho_g
2841 : TYPE(pw_env_type), POINTER :: pw_env
2842 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
2843 2 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: tau
2844 : TYPE(section_vals_type), POINTER :: input, xc_section
2845 : TYPE(xc_rho_cflags_type) :: needs
2846 : TYPE(xc_rho_set_type) :: rho_set
2847 :
2848 2 : rho_cutoff = EPSILON(0.0_dp)
2849 :
2850 2 : nspins = SIZE(rho_r)
2851 :
2852 2 : NULLIFY (xc_section)
2853 :
2854 : CALL get_qs_env(qs_env=qs_env, &
2855 : pw_env=pw_env, &
2856 2 : input=input)
2857 :
2858 : ! Get plane waves pool
2859 2 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
2860 :
2861 : ! get some of the grids ready
2862 2 : NULLIFY (rho_g)
2863 8 : ALLOCATE (rho_g(nspins))
2864 4 : DO i_spin = 1, nspins
2865 2 : CALL auxbas_pw_pool%create_pw(rho_g(i_spin))
2866 4 : CALL pw_transfer(rho_r(i_spin), rho_g(i_spin))
2867 : END DO
2868 :
2869 2 : xc_section => section_vals_get_subs_vals(input, "DFT%XC")
2870 :
2871 : CALL xc_rho_set_create(rho_set, &
2872 : rho_r(1)%pw_grid%bounds_local, &
2873 : rho_cutoff=section_get_rval(xc_section, "density_cutoff"), &
2874 : drho_cutoff=section_get_rval(xc_section, "gradient_cutoff"), &
2875 2 : tau_cutoff=section_get_rval(xc_section, "tau_cutoff"))
2876 :
2877 2 : CALL xc_rho_cflags_setall(needs, .FALSE.)
2878 :
2879 2 : IF (nspins .EQ. 2) THEN
2880 0 : needs%rho_spin = .TRUE.
2881 0 : needs%norm_drho_spin = .TRUE.
2882 0 : needs%laplace_rho_spin = .TRUE.
2883 : ELSE
2884 2 : needs%rho = .TRUE.
2885 2 : needs%norm_drho = .TRUE.
2886 2 : needs%laplace_rho = .TRUE.
2887 : END IF
2888 :
2889 : CALL xc_rho_set_update(rho_set, rho_r, rho_g, tau, needs, &
2890 : section_get_ival(xc_section, "XC_GRID%XC_DERIV"), &
2891 : section_get_ival(xc_section, "XC_GRID%XC_SMOOTH_RHO"), &
2892 2 : auxbas_pw_pool)
2893 :
2894 : CALL section_vals_val_get(xc_section, "DENSITY_CUTOFF", &
2895 2 : r_val=rho_cutoff)
2896 : CALL section_vals_val_get(xc_section, "DENSITY_SMOOTH_CUTOFF_RANGE", &
2897 2 : r_val=density_smooth_cut_range)
2898 :
2899 8 : lb(1:3) = rho_r(1)%pw_grid%bounds_local(1, 1:3)
2900 8 : ub(1:3) = rho_r(1)%pw_grid%bounds_local(2, 1:3)
2901 :
2902 2 : IF (nspins .EQ. 2) THEN
2903 : !$OMP PARALLEL DO DEFAULT(NONE) &
2904 : !$OMP PRIVATE(i,j,k, my_rho) &
2905 0 : !$OMP SHARED(v_w, rho_r, rho_set, lb, ub, rho_cutoff)
2906 : DO k = lb(3), ub(3)
2907 : DO j = lb(2), ub(2)
2908 : DO i = lb(1), ub(1)
2909 : IF (rho_r(1)%array(i, j, k) .GT. rho_cutoff) THEN
2910 : my_rho = rho_r(1)%array(i, j, k)
2911 : ELSE
2912 : my_rho = rho_cutoff
2913 : END IF
2914 : v_w(1)%array(i, j, k) = one_8*rho_set%norm_drhoa(i, j, k)**2/my_rho**2 - &
2915 : one_4*rho_set%laplace_rhoa(i, j, k)/my_rho
2916 :
2917 : IF (rho_r(2)%array(i, j, k) .GT. rho_cutoff) THEN
2918 : my_rho = rho_r(2)%array(i, j, k)
2919 : ELSE
2920 : my_rho = rho_cutoff
2921 : END IF
2922 : v_w(2)%array(i, j, k) = one_8*rho_set%norm_drhob(i, j, k)**2/my_rho**2 - &
2923 : one_4*rho_set%laplace_rhob(i, j, k)/my_rho
2924 : END DO
2925 : END DO
2926 : END DO
2927 : !$OMP END PARALLEL DO
2928 : ELSE
2929 : !$OMP PARALLEL DO DEFAULT(NONE) &
2930 : !$OMP PRIVATE(i,j,k, my_rho) &
2931 2 : !$OMP SHARED(v_w, rho_r, rho_set, lb, ub, rho_cutoff)
2932 : DO k = lb(3), ub(3)
2933 : DO j = lb(2), ub(2)
2934 : DO i = lb(1), ub(1)
2935 : IF (rho_r(1)%array(i, j, k) .GT. rho_cutoff) THEN
2936 : my_rho = rho_r(1)%array(i, j, k)
2937 : v_w(1)%array(i, j, k) = one_8*rho_set%norm_drho(i, j, k)**2/my_rho**2 - &
2938 : one_4*rho_set%laplace_rho(i, j, k)/my_rho
2939 : ELSE
2940 : v_w(1)%array(i, j, k) = 0.0_dp
2941 : END IF
2942 : END DO
2943 : END DO
2944 : END DO
2945 : !$OMP END PARALLEL DO
2946 :
2947 : END IF
2948 :
2949 : ! Smoothen the von Weizsaecker potential
2950 2 : IF (nspins == 2) THEN
2951 0 : density_smooth_cut_range = 0.5_dp*density_smooth_cut_range
2952 0 : rho_cutoff = 0.5_dp*rho_cutoff
2953 : END IF
2954 4 : DO i_spin = 1, nspins
2955 : CALL smooth_cutoff(pot=v_w(i_spin)%array, rho=rho_r(i_spin)%array, rhoa=rhoa, rhob=rhob, &
2956 : rho_cutoff=vw_cutoff, &
2957 4 : rho_smooth_cutoff_range=vw_smooth_cutoff_range)
2958 : END DO
2959 :
2960 2 : CALL xc_rho_set_release(rho_set, pw_pool=auxbas_pw_pool)
2961 :
2962 4 : DO i_spin = 1, nspins
2963 4 : CALL rho_g(i_spin)%release()
2964 : END DO
2965 2 : DEALLOCATE (rho_g)
2966 :
2967 46 : END SUBROUTINE Von_Weizsacker
2968 :
2969 : ! **************************************************************************************************
2970 : !> \brief ...
2971 : !> \param diff_rho_r ...
2972 : !> \return ...
2973 : ! **************************************************************************************************
2974 222 : FUNCTION max_dens_diff(diff_rho_r) RESULT(total_max_diff)
2975 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r
2976 : REAL(KIND=dp) :: total_max_diff
2977 :
2978 : INTEGER :: size_x, size_y, size_z
2979 : REAL(KIND=dp) :: max_diff
2980 222 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: grid_3d
2981 :
2982 : !, i_x, i_y, i_z
2983 :
2984 : ! Get the sizes
2985 222 : size_x = SIZE(diff_rho_r%array, 1)
2986 222 : size_y = SIZE(diff_rho_r%array, 2)
2987 222 : size_z = SIZE(diff_rho_r%array, 3)
2988 :
2989 : ! Allocate the density
2990 1110 : ALLOCATE (grid_3d(size_x, size_y, size_z))
2991 :
2992 : ! Copy density
2993 4589181 : grid_3d(:, :, :) = diff_rho_r%array(:, :, :)
2994 :
2995 : ! Find the maximum absolute value
2996 4589181 : max_diff = MAXVAL(ABS(grid_3d))
2997 222 : total_max_diff = max_diff
2998 222 : CALL diff_rho_r%pw_grid%para%group%max(total_max_diff)
2999 :
3000 : ! Deallocate the density
3001 222 : DEALLOCATE (grid_3d)
3002 :
3003 222 : END FUNCTION max_dens_diff
3004 :
3005 : ! **************************************************************************************************
3006 : !> \brief Prints a cube for the (rho_A + rho_B - rho_ref) to be minimized in embedding
3007 : !> \param diff_rho_r ...
3008 : !> \param i_iter ...
3009 : !> \param qs_env ...
3010 : !> \param final_one ...
3011 : !> \author Vladimir Rybkin
3012 : ! **************************************************************************************************
3013 48 : SUBROUTINE print_rho_diff(diff_rho_r, i_iter, qs_env, final_one)
3014 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r
3015 : INTEGER, INTENT(IN) :: i_iter
3016 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
3017 : LOGICAL, INTENT(IN) :: final_one
3018 :
3019 : CHARACTER(LEN=default_path_length) :: filename, my_pos_cube, title
3020 : INTEGER :: unit_nr
3021 : TYPE(cp_logger_type), POINTER :: logger
3022 : TYPE(particle_list_type), POINTER :: particles
3023 : TYPE(qs_subsys_type), POINTER :: subsys
3024 : TYPE(section_vals_type), POINTER :: dft_section, input
3025 :
3026 48 : NULLIFY (subsys, input)
3027 :
3028 : CALL get_qs_env(qs_env=qs_env, &
3029 : subsys=subsys, &
3030 48 : input=input)
3031 48 : dft_section => section_vals_get_subs_vals(input, "DFT")
3032 48 : CALL qs_subsys_get(subsys, particles=particles)
3033 :
3034 48 : logger => cp_get_default_logger()
3035 48 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3036 : "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF"), cp_p_file)) THEN
3037 10 : my_pos_cube = "REWIND"
3038 10 : IF (.NOT. final_one) THEN
3039 10 : WRITE (filename, '(a5,I3.3,a1,I1.1)') "DIFF_", i_iter
3040 : ELSE
3041 0 : WRITE (filename, '(a5,I3.3,a1,I1.1)') "DIFF"
3042 : END IF
3043 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF", &
3044 : extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
3045 10 : log_filename=.FALSE.)
3046 :
3047 10 : WRITE (title, *) "EMBEDDING DENSITY DIFFERENCE ", " optimization step ", i_iter
3048 : CALL cp_pw_to_cube(diff_rho_r, unit_nr, title, particles=particles, &
3049 10 : stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_DENS_DIFF%STRIDE"))
3050 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3051 10 : "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF")
3052 : END IF
3053 :
3054 48 : END SUBROUTINE print_rho_diff
3055 :
3056 : ! **************************************************************************************************
3057 : !> \brief Prints a cube for the (spin_rho_A + spin_rho_B - spin_rho_ref) to be minimized in embedding
3058 : !> \param spin_diff_rho_r ...
3059 : !> \param i_iter ...
3060 : !> \param qs_env ...
3061 : !> \param final_one ...
3062 : !> \author Vladimir Rybkin
3063 : ! **************************************************************************************************
3064 38 : SUBROUTINE print_rho_spin_diff(spin_diff_rho_r, i_iter, qs_env, final_one)
3065 : TYPE(pw_r3d_rs_type), INTENT(IN) :: spin_diff_rho_r
3066 : INTEGER, INTENT(IN) :: i_iter
3067 : TYPE(qs_environment_type), INTENT(IN), POINTER :: qs_env
3068 : LOGICAL, INTENT(IN) :: final_one
3069 :
3070 : CHARACTER(LEN=default_path_length) :: filename, my_pos_cube, title
3071 : INTEGER :: unit_nr
3072 : TYPE(cp_logger_type), POINTER :: logger
3073 : TYPE(particle_list_type), POINTER :: particles
3074 : TYPE(qs_subsys_type), POINTER :: subsys
3075 : TYPE(section_vals_type), POINTER :: dft_section, input
3076 :
3077 38 : NULLIFY (subsys, input)
3078 :
3079 : CALL get_qs_env(qs_env=qs_env, &
3080 : subsys=subsys, &
3081 38 : input=input)
3082 38 : dft_section => section_vals_get_subs_vals(input, "DFT")
3083 38 : CALL qs_subsys_get(subsys, particles=particles)
3084 :
3085 38 : logger => cp_get_default_logger()
3086 38 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3087 : "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF"), cp_p_file)) THEN
3088 0 : my_pos_cube = "REWIND"
3089 0 : IF (.NOT. final_one) THEN
3090 0 : WRITE (filename, '(a5,I3.3,a1,I1.1)') "SPIN_DIFF_", i_iter
3091 : ELSE
3092 0 : WRITE (filename, '(a9,I3.3,a1,I1.1)') "SPIN_DIFF"
3093 : END IF
3094 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF", &
3095 : extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
3096 0 : log_filename=.FALSE.)
3097 :
3098 0 : WRITE (title, *) "EMBEDDING SPIN DENSITY DIFFERENCE ", " optimization step ", i_iter
3099 : CALL cp_pw_to_cube(spin_diff_rho_r, unit_nr, title, particles=particles, &
3100 0 : stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_DENS_DIFF%STRIDE"))
3101 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3102 0 : "DFT%QS%OPT_EMBED%EMBED_DENS_DIFF")
3103 : END IF
3104 :
3105 38 : END SUBROUTINE print_rho_spin_diff
3106 : ! **************************************************************************************************
3107 : !> \brief Print embedding potential as a cube and as a binary (for restarting)
3108 : !> \param qs_env ...
3109 : !> \param dimen_aux ...
3110 : !> \param embed_pot_coef ...
3111 : !> \param embed_pot ...
3112 : !> \param i_iter ...
3113 : !> \param embed_pot_spin ...
3114 : !> \param open_shell_embed ...
3115 : !> \param grid_opt ...
3116 : !> \param final_one ...
3117 : ! **************************************************************************************************
3118 72 : SUBROUTINE print_embed_restart(qs_env, dimen_aux, embed_pot_coef, embed_pot, i_iter, &
3119 : embed_pot_spin, open_shell_embed, grid_opt, final_one)
3120 : TYPE(qs_environment_type), POINTER :: qs_env
3121 : INTEGER :: dimen_aux
3122 : TYPE(cp_fm_type), INTENT(IN), POINTER :: embed_pot_coef
3123 : TYPE(pw_r3d_rs_type), INTENT(IN) :: embed_pot
3124 : INTEGER :: i_iter
3125 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: embed_pot_spin
3126 : LOGICAL :: open_shell_embed, grid_opt, final_one
3127 :
3128 : CHARACTER(LEN=default_path_length) :: filename, my_pos_cube, title
3129 : INTEGER :: unit_nr
3130 : TYPE(cp_logger_type), POINTER :: logger
3131 : TYPE(particle_list_type), POINTER :: particles
3132 : TYPE(qs_subsys_type), POINTER :: subsys
3133 : TYPE(section_vals_type), POINTER :: dft_section, input
3134 :
3135 72 : NULLIFY (input)
3136 : CALL get_qs_env(qs_env=qs_env, subsys=subsys, &
3137 72 : input=input)
3138 :
3139 : ! First we print an unformatted file
3140 72 : IF (.NOT. grid_opt) THEN ! Only for finite basis optimization
3141 44 : logger => cp_get_default_logger()
3142 44 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3143 : "DFT%QS%OPT_EMBED%EMBED_POT_VECTOR"), cp_p_file)) THEN
3144 44 : IF (.NOT. final_one) THEN
3145 30 : WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
3146 : ELSE
3147 14 : WRITE (filename, '(a10,I3.3)') "embed_pot"
3148 : END IF
3149 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_VECTOR", extension=".wfn", &
3150 44 : file_form="UNFORMATTED", middle_name=TRIM(filename), file_position="REWIND")
3151 44 : IF (unit_nr > 0) THEN
3152 22 : WRITE (unit_nr) dimen_aux
3153 : END IF
3154 44 : CALL cp_fm_write_unformatted(embed_pot_coef, unit_nr)
3155 44 : IF (unit_nr > 0) THEN
3156 22 : CALL close_file(unit_nr)
3157 : END IF
3158 : END IF
3159 : END IF
3160 :
3161 : ! Second, cube files
3162 72 : dft_section => section_vals_get_subs_vals(input, "DFT")
3163 72 : CALL qs_subsys_get(subsys, particles=particles)
3164 :
3165 72 : logger => cp_get_default_logger()
3166 72 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3167 : "DFT%QS%OPT_EMBED%EMBED_POT_CUBE"), cp_p_file)) THEN
3168 32 : my_pos_cube = "REWIND"
3169 32 : IF (.NOT. final_one) THEN
3170 20 : WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
3171 : ELSE
3172 12 : WRITE (filename, '(a10,I3.3)') "embed_pot"
3173 : END IF
3174 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_CUBE", &
3175 : extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
3176 32 : log_filename=.FALSE.)
3177 :
3178 32 : WRITE (title, *) "EMBEDDING POTENTIAL at optimization step ", i_iter
3179 32 : CALL cp_pw_to_cube(embed_pot, unit_nr, title, particles=particles)
3180 : !, &
3181 : ! stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_POT_CUBE%STRIDE"))
3182 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3183 32 : "DFT%QS%OPT_EMBED%EMBED_POT_CUBE")
3184 32 : IF (open_shell_embed) THEN ! Print spin part of the embedding potential
3185 16 : my_pos_cube = "REWIND"
3186 16 : IF (.NOT. final_one) THEN
3187 10 : WRITE (filename, '(a15,I3.3)') "spin_embed_pot_", i_iter
3188 : ELSE
3189 6 : WRITE (filename, '(a15,I3.3)') "spin_embed_pot"
3190 : END IF
3191 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%EMBED_POT_CUBE", &
3192 : extension=".cube", middle_name=TRIM(filename), file_position=my_pos_cube, &
3193 16 : log_filename=.FALSE.)
3194 :
3195 16 : WRITE (title, *) "SPIN EMBEDDING POTENTIAL at optimization step ", i_iter
3196 16 : CALL cp_pw_to_cube(embed_pot_spin, unit_nr, title, particles=particles)
3197 : !, &
3198 : ! stride=section_get_ivals(dft_section, "QS%OPT_EMBED%EMBED_POT_CUBE%STRIDE"))
3199 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3200 16 : "DFT%QS%OPT_EMBED%EMBED_POT_CUBE")
3201 : END IF
3202 : END IF
3203 :
3204 72 : END SUBROUTINE print_embed_restart
3205 :
3206 : ! **************************************************************************************************
3207 : !> \brief Prints a volumetric file: X Y Z value for interfacing with external programs.
3208 : !> \param qs_env ...
3209 : !> \param embed_pot ...
3210 : !> \param embed_pot_spin ...
3211 : !> \param i_iter ...
3212 : !> \param open_shell_embed ...
3213 : !> \param final_one ...
3214 : !> \param qs_env_cluster ...
3215 : ! **************************************************************************************************
3216 72 : SUBROUTINE print_pot_simple_grid(qs_env, embed_pot, embed_pot_spin, i_iter, open_shell_embed, &
3217 : final_one, qs_env_cluster)
3218 : TYPE(qs_environment_type), POINTER :: qs_env
3219 : TYPE(pw_r3d_rs_type), INTENT(IN) :: embed_pot
3220 : TYPE(pw_r3d_rs_type), INTENT(IN), POINTER :: embed_pot_spin
3221 : INTEGER :: i_iter
3222 : LOGICAL :: open_shell_embed, final_one
3223 : TYPE(qs_environment_type), POINTER :: qs_env_cluster
3224 :
3225 : CHARACTER(LEN=default_path_length) :: filename
3226 : INTEGER :: my_units, unit_nr
3227 : LOGICAL :: angstrom, bohr
3228 : TYPE(cp_logger_type), POINTER :: logger
3229 : TYPE(pw_env_type), POINTER :: pw_env
3230 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
3231 : TYPE(pw_r3d_rs_type) :: pot_alpha, pot_beta
3232 : TYPE(section_vals_type), POINTER :: dft_section, input
3233 :
3234 72 : NULLIFY (input)
3235 72 : CALL get_qs_env(qs_env=qs_env, input=input, pw_env=pw_env)
3236 :
3237 : ! Second, cube files
3238 72 : dft_section => section_vals_get_subs_vals(input, "DFT")
3239 :
3240 72 : NULLIFY (logger)
3241 72 : logger => cp_get_default_logger()
3242 72 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3243 : "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID"), cp_p_file)) THEN
3244 :
3245 : ! Figure out the units
3246 16 : angstrom = .FALSE.
3247 16 : bohr = .TRUE.
3248 16 : CALL section_vals_val_get(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%UNITS", i_val=my_units)
3249 : SELECT CASE (my_units)
3250 : CASE (embed_grid_bohr)
3251 16 : bohr = .TRUE.
3252 16 : angstrom = .FALSE.
3253 : CASE (embed_grid_angstrom)
3254 : bohr = .FALSE.
3255 : angstrom = .TRUE.
3256 : CASE DEFAULT
3257 : bohr = .TRUE.
3258 : angstrom = .FALSE.
3259 : END SELECT
3260 :
3261 : ! Get alpha and beta potentials
3262 : ! Prepare plane-waves pool
3263 16 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
3264 :
3265 : ! Create embedding potential and set to zero
3266 16 : CALL auxbas_pw_pool%create_pw(pot_alpha)
3267 16 : CALL pw_zero(pot_alpha)
3268 :
3269 16 : CALL pw_copy(embed_pot, pot_alpha)
3270 :
3271 16 : IF (open_shell_embed) THEN
3272 0 : CALL auxbas_pw_pool%create_pw(pot_beta)
3273 0 : CALL pw_copy(embed_pot, pot_beta)
3274 : ! Add spin potential to the alpha, and subtract from the beta part
3275 0 : CALL pw_axpy(embed_pot_spin, pot_alpha, 1.0_dp)
3276 0 : CALL pw_axpy(embed_pot_spin, pot_beta, -1.0_dp)
3277 : END IF
3278 :
3279 16 : IF (.NOT. final_one) THEN
3280 10 : WRITE (filename, '(a10,I3.3)') "embed_pot_", i_iter
3281 : ELSE
3282 6 : WRITE (filename, '(a10,I3.3)') "embed_pot"
3283 : END IF
3284 : unit_nr = cp_print_key_unit_nr(logger, input, "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID", extension=".dat", &
3285 16 : middle_name=TRIM(filename), file_form="FORMATTED", file_position="REWIND")
3286 :
3287 16 : IF (open_shell_embed) THEN ! Print spin part of the embedding potential
3288 : CALL cp_pw_to_simple_volumetric(pw=pot_alpha, unit_nr=unit_nr, &
3289 : stride=section_get_ivals(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%STRIDE"), &
3290 0 : pw2=pot_beta)
3291 : ELSE
3292 : CALL cp_pw_to_simple_volumetric(pot_alpha, unit_nr, &
3293 16 : stride=section_get_ivals(dft_section, "QS%OPT_EMBED%WRITE_SIMPLE_GRID%STRIDE"))
3294 : END IF
3295 :
3296 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3297 16 : "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID")
3298 : ! Release structures
3299 16 : CALL pot_alpha%release()
3300 16 : IF (open_shell_embed) THEN
3301 0 : CALL pot_beta%release()
3302 : END IF
3303 :
3304 : END IF
3305 :
3306 : ! Fold the coordinates and write into separate file: needed to have the grid correspond to coordinates
3307 : ! Needed for external software.
3308 72 : CALL print_folded_coordinates(qs_env_cluster, input)
3309 :
3310 72 : END SUBROUTINE print_pot_simple_grid
3311 :
3312 : ! **************************************************************************************************
3313 : !> \brief ...
3314 : !> \param qs_env ...
3315 : !> \param input ...
3316 : ! **************************************************************************************************
3317 72 : SUBROUTINE print_folded_coordinates(qs_env, input)
3318 : TYPE(qs_environment_type), POINTER :: qs_env
3319 : TYPE(section_vals_type), POINTER :: input
3320 :
3321 72 : CHARACTER(LEN=2), ALLOCATABLE, DIMENSION(:) :: particles_el
3322 : CHARACTER(LEN=default_path_length) :: filename
3323 : INTEGER :: iat, n, unit_nr
3324 72 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: particles_r
3325 : REAL(KIND=dp), DIMENSION(3) :: center, r_pbc, s
3326 : TYPE(cell_type), POINTER :: cell
3327 : TYPE(cp_logger_type), POINTER :: logger
3328 : TYPE(particle_list_type), POINTER :: particles
3329 : TYPE(qs_subsys_type), POINTER :: subsys
3330 :
3331 72 : NULLIFY (logger)
3332 72 : logger => cp_get_default_logger()
3333 72 : IF (BTEST(cp_print_key_should_output(logger%iter_info, input, &
3334 : "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD"), cp_p_file)) THEN
3335 16 : CALL get_qs_env(qs_env=qs_env, cell=cell, subsys=subsys)
3336 16 : CALL qs_subsys_get(subsys=subsys, particles=particles)
3337 :
3338 : ! Prepare the file
3339 16 : WRITE (filename, '(a14)') "folded_cluster"
3340 : unit_nr = cp_print_key_unit_nr(logger, input, &
3341 : "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD", extension=".dat", &
3342 16 : middle_name=TRIM(filename), file_form="FORMATTED", file_position="REWIND")
3343 16 : IF (unit_nr > 0) THEN
3344 :
3345 8 : n = particles%n_els
3346 16 : ALLOCATE (particles_el(n))
3347 24 : ALLOCATE (particles_r(3, n))
3348 24 : DO iat = 1, n
3349 16 : CALL get_atomic_kind(particles%els(iat)%atomic_kind, element_symbol=particles_el(iat))
3350 72 : particles_r(:, iat) = particles%els(iat)%r(:)
3351 : END DO
3352 :
3353 : ! Fold the coordinates
3354 32 : center(:) = cell%hmat(:, 1)/2.0_dp + cell%hmat(:, 2)/2.0_dp + cell%hmat(:, 3)/2.0_dp
3355 :
3356 : ! Print folded coordinates to file
3357 24 : DO iat = 1, SIZE(particles_el)
3358 64 : r_pbc(:) = particles_r(:, iat) - center
3359 208 : s = MATMUL(cell%h_inv, r_pbc)
3360 64 : s = s - ANINT(s)
3361 208 : r_pbc = MATMUL(cell%hmat, s)
3362 64 : r_pbc = r_pbc + center
3363 24 : WRITE (unit_nr, '(a4,4f12.6)') particles_el(iat), r_pbc(:)
3364 : END DO
3365 :
3366 : CALL cp_print_key_finished_output(unit_nr, logger, input, &
3367 8 : "DFT%QS%OPT_EMBED%WRITE_SIMPLE_GRID/FOLD_COORD")
3368 :
3369 8 : DEALLOCATE (particles_el)
3370 8 : DEALLOCATE (particles_r)
3371 : END IF
3372 :
3373 : END IF ! Should output
3374 :
3375 72 : END SUBROUTINE print_folded_coordinates
3376 :
3377 : ! **************************************************************************************************
3378 : !> \brief ...
3379 : !> \param output_unit ...
3380 : !> \param step_num ...
3381 : !> \param opt_embed ...
3382 : ! **************************************************************************************************
3383 48 : SUBROUTINE print_emb_opt_info(output_unit, step_num, opt_embed)
3384 : INTEGER :: output_unit, step_num
3385 : TYPE(opt_embed_pot_type) :: opt_embed
3386 :
3387 48 : IF (output_unit > 0) THEN
3388 : WRITE (UNIT=output_unit, FMT="(/,T2,8('-'),A,I5,1X,12('-'))") &
3389 24 : " Optimize embedding potential info at step = ", step_num
3390 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3391 24 : " Functional value = ", opt_embed%w_func(step_num)
3392 24 : IF (step_num .GT. 1) THEN
3393 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3394 12 : " Real energy change = ", opt_embed%w_func(step_num) - &
3395 24 : opt_embed%w_func(step_num - 1)
3396 :
3397 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3398 12 : " Step size = ", opt_embed%step_len
3399 :
3400 : END IF
3401 :
3402 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3403 24 : " Trust radius = ", opt_embed%trust_rad
3404 :
3405 24 : WRITE (UNIT=output_unit, FMT="(T2,51('-'))")
3406 : END IF
3407 :
3408 48 : END SUBROUTINE print_emb_opt_info
3409 :
3410 : ! **************************************************************************************************
3411 : !> \brief ...
3412 : !> \param opt_embed ...
3413 : !> \param force_env ...
3414 : !> \param subsys_num ...
3415 : ! **************************************************************************************************
3416 96 : SUBROUTINE get_prev_density(opt_embed, force_env, subsys_num)
3417 : TYPE(opt_embed_pot_type) :: opt_embed
3418 : TYPE(force_env_type), POINTER :: force_env
3419 : INTEGER :: subsys_num
3420 :
3421 : INTEGER :: i_dens_start, i_spin, nspins
3422 96 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
3423 : TYPE(qs_rho_type), POINTER :: rho
3424 :
3425 96 : NULLIFY (rho_r, rho)
3426 96 : CALL get_qs_env(force_env%qs_env, rho=rho)
3427 96 : CALL qs_rho_get(rho_struct=rho, rho_r=rho_r)
3428 :
3429 96 : nspins = opt_embed%all_nspins(subsys_num)
3430 :
3431 240 : i_dens_start = SUM(opt_embed%all_nspins(1:subsys_num)) - nspins + 1
3432 :
3433 244 : DO i_spin = 1, nspins
3434 : opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1)%array(:, :, :) = &
3435 3059550 : rho_r(i_spin)%array(:, :, :)
3436 : END DO
3437 :
3438 96 : END SUBROUTINE get_prev_density
3439 :
3440 : ! **************************************************************************************************
3441 : !> \brief ...
3442 : !> \param opt_embed ...
3443 : !> \param force_env ...
3444 : !> \param subsys_num ...
3445 : ! **************************************************************************************************
3446 96 : SUBROUTINE get_max_subsys_diff(opt_embed, force_env, subsys_num)
3447 : TYPE(opt_embed_pot_type) :: opt_embed
3448 : TYPE(force_env_type), POINTER :: force_env
3449 : INTEGER :: subsys_num
3450 :
3451 : INTEGER :: i_dens_start, i_spin, nspins
3452 96 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r
3453 : TYPE(qs_rho_type), POINTER :: rho
3454 :
3455 96 : NULLIFY (rho_r, rho)
3456 96 : CALL get_qs_env(force_env%qs_env, rho=rho)
3457 96 : CALL qs_rho_get(rho_struct=rho, rho_r=rho_r)
3458 :
3459 96 : nspins = opt_embed%all_nspins(subsys_num)
3460 :
3461 240 : i_dens_start = SUM(opt_embed%all_nspins(1:subsys_num)) - nspins + 1
3462 :
3463 244 : DO i_spin = 1, nspins
3464 : CALL pw_axpy(rho_r(i_spin), opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1), 1.0_dp, -1.0_dp, &
3465 148 : allow_noncompatible_grids=.TRUE.)
3466 : opt_embed%max_subsys_dens_diff(i_dens_start + i_spin - 1) = &
3467 244 : max_dens_diff(opt_embed%prev_subsys_dens(i_dens_start + i_spin - 1))
3468 : END DO
3469 :
3470 96 : END SUBROUTINE get_max_subsys_diff
3471 :
3472 : ! **************************************************************************************************
3473 : !> \brief ...
3474 : !> \param opt_embed ...
3475 : !> \param diff_rho_r ...
3476 : !> \param diff_rho_spin ...
3477 : !> \param output_unit ...
3478 : ! **************************************************************************************************
3479 48 : SUBROUTINE conv_check_embed(opt_embed, diff_rho_r, diff_rho_spin, output_unit)
3480 : TYPE(opt_embed_pot_type) :: opt_embed
3481 : TYPE(pw_r3d_rs_type), INTENT(IN) :: diff_rho_r, diff_rho_spin
3482 : INTEGER :: output_unit
3483 :
3484 : INTEGER :: i_dens, i_dens_start, i_spin
3485 : LOGICAL :: conv_int_diff, conv_max_diff
3486 : REAL(KIND=dp) :: int_diff, int_diff_spin, &
3487 : int_diff_square, int_diff_square_spin, &
3488 : max_diff, max_diff_spin
3489 :
3490 : ! Calculate the convergence target values
3491 48 : opt_embed%max_diff(1) = max_dens_diff(diff_rho_r)
3492 48 : opt_embed%int_diff(1) = pw_integrate_function(fun=diff_rho_r, oprt='ABS')
3493 48 : opt_embed%int_diff_square(1) = pw_integral_ab(diff_rho_r, diff_rho_r)
3494 48 : IF (opt_embed%open_shell_embed) THEN
3495 26 : opt_embed%max_diff(2) = max_dens_diff(diff_rho_spin)
3496 26 : opt_embed%int_diff(2) = pw_integrate_function(fun=diff_rho_spin, oprt='ABS')
3497 26 : opt_embed%int_diff_square(2) = pw_integral_ab(diff_rho_spin, diff_rho_spin)
3498 : END IF
3499 :
3500 : ! Find out the convergence
3501 48 : max_diff = opt_embed%max_diff(1)
3502 :
3503 : ! Maximum value criterium
3504 : ! Open shell
3505 48 : IF (opt_embed%open_shell_embed) THEN
3506 26 : max_diff_spin = opt_embed%max_diff(2)
3507 26 : IF ((max_diff .LE. opt_embed%conv_max) .AND. (max_diff_spin .LE. opt_embed%conv_max_spin)) THEN
3508 : conv_max_diff = .TRUE.
3509 : ELSE
3510 12 : conv_max_diff = .FALSE.
3511 : END IF
3512 : ELSE
3513 : ! Closed shell
3514 22 : IF (max_diff .LE. opt_embed%conv_max) THEN
3515 : conv_max_diff = .TRUE.
3516 : ELSE
3517 8 : conv_max_diff = .FALSE.
3518 : END IF
3519 : END IF
3520 :
3521 : ! Integrated value criterium
3522 48 : int_diff = opt_embed%int_diff(1)
3523 : ! Open shell
3524 48 : IF (opt_embed%open_shell_embed) THEN
3525 26 : int_diff_spin = opt_embed%int_diff(2)
3526 26 : IF ((int_diff .LE. opt_embed%conv_int) .AND. (int_diff_spin .LE. opt_embed%conv_int_spin)) THEN
3527 : conv_int_diff = .TRUE.
3528 : ELSE
3529 6 : conv_int_diff = .FALSE.
3530 : END IF
3531 : ELSE
3532 : ! Closed shell
3533 22 : IF (int_diff .LE. opt_embed%conv_int) THEN
3534 : conv_int_diff = .TRUE.
3535 : ELSE
3536 10 : conv_int_diff = .FALSE.
3537 : END IF
3538 : END IF
3539 :
3540 : ! Integrated squared value criterium
3541 48 : int_diff_square = opt_embed%int_diff_square(1)
3542 : ! Open shell
3543 48 : IF (opt_embed%open_shell_embed) int_diff_square_spin = opt_embed%int_diff_square(2)
3544 :
3545 48 : IF ((conv_max_diff) .AND. (conv_int_diff)) THEN
3546 24 : opt_embed%converged = .TRUE.
3547 : ELSE
3548 24 : opt_embed%converged = .FALSE.
3549 : END IF
3550 :
3551 : ! Print the information
3552 48 : IF (output_unit > 0) THEN
3553 : WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
3554 24 : " Convergence check :"
3555 :
3556 : ! Maximum value of density
3557 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3558 24 : " Maximum density difference = ", max_diff
3559 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3560 24 : " Convergence limit for max. density diff. = ", opt_embed%conv_max
3561 :
3562 24 : IF (opt_embed%open_shell_embed) THEN
3563 :
3564 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3565 13 : " Maximum spin density difference = ", max_diff_spin
3566 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3567 13 : " Convergence limit for max. spin dens.diff.= ", opt_embed%conv_max_spin
3568 :
3569 : END IF
3570 :
3571 24 : IF (conv_max_diff) THEN
3572 : WRITE (UNIT=output_unit, FMT="(T2,2A)") &
3573 14 : " Convergence in max. density diff. = ", &
3574 28 : " YES"
3575 : ELSE
3576 : WRITE (UNIT=output_unit, FMT="(T2,2A)") &
3577 10 : " Convergence in max. density diff. = ", &
3578 20 : " NO"
3579 : END IF
3580 :
3581 : ! Integrated abs. value of density
3582 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3583 24 : " Integrated density difference = ", int_diff
3584 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3585 24 : " Conv. limit for integrated density diff. = ", opt_embed%conv_int
3586 24 : IF (opt_embed%open_shell_embed) THEN
3587 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3588 13 : " Integrated spin density difference = ", int_diff_spin
3589 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3590 13 : " Conv. limit for integrated spin dens.diff.= ", opt_embed%conv_int_spin
3591 : END IF
3592 :
3593 24 : IF (conv_int_diff) THEN
3594 : WRITE (UNIT=output_unit, FMT="(T2,2A)") &
3595 16 : " Convergence in integrated density diff. = ", &
3596 32 : " YES"
3597 : ELSE
3598 : WRITE (UNIT=output_unit, FMT="(T2,2A)") &
3599 8 : " Convergence in integrated density diff. = ", &
3600 16 : " NO"
3601 : END IF
3602 :
3603 : ! Integrated squared value of density
3604 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3605 24 : " Integrated squared density difference = ", int_diff_square
3606 24 : IF (opt_embed%open_shell_embed) THEN
3607 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.10)") &
3608 13 : " Integrated squared spin density difference= ", int_diff_square_spin
3609 : END IF
3610 :
3611 : ! Maximum subsystem density change
3612 : WRITE (UNIT=output_unit, FMT="(/,T2,A)") &
3613 24 : " Maximum density change in:"
3614 72 : DO i_dens = 1, (SIZE(opt_embed%all_nspins) - 1)
3615 120 : i_dens_start = SUM(opt_embed%all_nspins(1:i_dens)) - opt_embed%all_nspins(i_dens) + 1
3616 146 : DO i_spin = 1, opt_embed%all_nspins(i_dens)
3617 : WRITE (UNIT=output_unit, FMT="(T4,A10,I3,A6,I3,A1,F20.10)") &
3618 74 : " subsystem ", i_dens, ', spin', i_spin, ":", &
3619 196 : opt_embed%max_subsys_dens_diff(i_dens_start + i_spin - 1)
3620 : END DO
3621 : END DO
3622 :
3623 : END IF
3624 :
3625 48 : IF ((opt_embed%converged) .AND. (output_unit > 0)) THEN
3626 12 : WRITE (UNIT=output_unit, FMT="(/,T2,A)") REPEAT("*", 79)
3627 : WRITE (UNIT=output_unit, FMT="(T2,A,T25,A,T78,A)") &
3628 12 : "***", "EMBEDDING POTENTIAL OPTIMIZATION COMPLETED", "***"
3629 12 : WRITE (UNIT=output_unit, FMT="(T2,A)") REPEAT("*", 79)
3630 : END IF
3631 :
3632 48 : END SUBROUTINE conv_check_embed
3633 :
3634 : END MODULE optimize_embedding_potential
|