Line data Source code
1 : !--------------------------------------------------------------------------------------------------!
2 : ! CP2K: A general program to perform molecular dynamics simulations !
3 : ! Copyright 2000-2024 CP2K developers group <https://cp2k.org> !
4 : ! !
5 : ! SPDX-License-Identifier: GPL-2.0-or-later !
6 : !--------------------------------------------------------------------------------------------------!
7 :
8 : ! **************************************************************************************************
9 : !> \brief Interface for the force calculations
10 : !> \par History
11 : !> cjm, FEB-20-2001: pass variable box_ref
12 : !> cjm, SEPT-12-2002: major reorganization
13 : !> fawzi, APR-12-2003: introduced force_env (based on the work by CJM&JGH)
14 : !> fawzi, NOV-3-2004: reorganized interface for f77 interface
15 : !> \author fawzi
16 : ! **************************************************************************************************
17 : MODULE force_env_methods
18 : USE atprop_types, ONLY: atprop_init,&
19 : atprop_type
20 : USE bibliography, ONLY: Heaton_Burgess2007,&
21 : Huang2011,&
22 : cite_reference
23 : USE cell_methods, ONLY: cell_create,&
24 : init_cell
25 : USE cell_types, ONLY: cell_clone,&
26 : cell_release,&
27 : cell_sym_triclinic,&
28 : cell_type,&
29 : real_to_scaled,&
30 : scaled_to_real
31 : USE constraint_fxd, ONLY: fix_atom_control
32 : USE constraint_vsite, ONLY: vsite_force_control
33 : USE cp_control_types, ONLY: dft_control_type
34 : USE cp_fm_basic_linalg, ONLY: cp_fm_scale_and_add
35 : USE cp_fm_types, ONLY: cp_fm_copy_general
36 : USE cp_iter_types, ONLY: cp_iteration_info_copy_iter
37 : USE cp_log_handling, ONLY: cp_add_default_logger,&
38 : cp_get_default_logger,&
39 : cp_logger_type,&
40 : cp_rm_default_logger,&
41 : cp_to_string
42 : USE cp_output_handling, ONLY: cp_print_key_finished_output,&
43 : cp_print_key_unit_nr,&
44 : low_print_level
45 : USE cp_result_methods, ONLY: cp_results_erase,&
46 : cp_results_mp_bcast,&
47 : get_results,&
48 : test_for_result
49 : USE cp_result_types, ONLY: cp_result_copy,&
50 : cp_result_create,&
51 : cp_result_p_type,&
52 : cp_result_release,&
53 : cp_result_type
54 : USE cp_subsys_types, ONLY: cp_subsys_get,&
55 : cp_subsys_p_type,&
56 : cp_subsys_set,&
57 : cp_subsys_type
58 : USE eip_environment_types, ONLY: eip_environment_type
59 : USE eip_silicon, ONLY: eip_bazant,&
60 : eip_lenosky
61 : USE embed_types, ONLY: embed_env_type,&
62 : opt_dmfet_pot_type,&
63 : opt_embed_pot_type
64 : USE external_potential_methods, ONLY: add_external_potential
65 : USE fist_environment_types, ONLY: fist_environment_type
66 : USE fist_force, ONLY: fist_calc_energy_force
67 : USE force_env_types, ONLY: &
68 : force_env_get, force_env_get_natom, force_env_p_type, force_env_set, force_env_type, &
69 : use_eip_force, use_embed, use_fist_force, use_ipi, use_mixed_force, use_nnp_force, &
70 : use_prog_name, use_pwdft_force, use_qmmm, use_qmmmx, use_qs_force
71 : USE force_env_utils, ONLY: rescale_forces,&
72 : write_atener,&
73 : write_forces
74 : USE force_fields_util, ONLY: get_generic_info
75 : USE fp_methods, ONLY: fp_eval
76 : USE fparser, ONLY: EvalErrType,&
77 : evalf,&
78 : evalfd,&
79 : finalizef,&
80 : initf,&
81 : parsef
82 : USE global_types, ONLY: global_environment_type,&
83 : globenv_retain
84 : USE grrm_utils, ONLY: write_grrm
85 : USE input_constants, ONLY: &
86 : debug_run, dfet, dmfet, mix_cdft, mix_coupled, mix_generic, mix_linear_combination, &
87 : mix_minimum, mix_restrained, mixed_cdft_serial, use_bazant_eip, use_lenosky_eip
88 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
89 : section_vals_retain,&
90 : section_vals_type,&
91 : section_vals_val_get
92 : USE ipi_environment_types, ONLY: ipi_environment_type
93 : USE ipi_server, ONLY: request_forces
94 : USE kahan_sum, ONLY: accurate_sum
95 : USE kinds, ONLY: default_path_length,&
96 : default_string_length,&
97 : dp
98 : USE machine, ONLY: m_memory
99 : USE mathlib, ONLY: abnormal_value
100 : USE message_passing, ONLY: mp_para_env_type
101 : USE metadynamics_types, ONLY: meta_env_type
102 : USE mixed_cdft_methods, ONLY: mixed_cdft_build_weight,&
103 : mixed_cdft_calculate_coupling,&
104 : mixed_cdft_init
105 : USE mixed_energy_types, ONLY: mixed_energy_type,&
106 : mixed_force_type
107 : USE mixed_environment_types, ONLY: get_mixed_env,&
108 : mixed_environment_type
109 : USE mixed_environment_utils, ONLY: get_subsys_map_index,&
110 : mixed_map_forces
111 : USE molecule_kind_list_types, ONLY: molecule_kind_list_type
112 : USE molecule_kind_types, ONLY: get_molecule_kind,&
113 : molecule_kind_type
114 : USE nnp_environment_types, ONLY: nnp_type
115 : USE nnp_force, ONLY: nnp_calc_energy_force
116 : USE optimize_dmfet_potential, ONLY: build_full_dm,&
117 : check_dmfet,&
118 : prepare_dmfet_opt,&
119 : release_dmfet_opt,&
120 : subsys_spin
121 : USE optimize_embedding_potential, ONLY: &
122 : Coulomb_guess, calculate_embed_pot_grad, conv_check_embed, get_max_subsys_diff, &
123 : get_prev_density, init_embed_pot, make_subsys_embed_pot, opt_embed_step, &
124 : prepare_embed_opt, print_emb_opt_info, print_embed_restart, print_pot_simple_grid, &
125 : print_rho_diff, print_rho_spin_diff, read_embed_pot, release_opt_embed, step_control, &
126 : understand_spin_states
127 : USE particle_list_types, ONLY: particle_list_p_type,&
128 : particle_list_type
129 : USE physcon, ONLY: debye
130 : USE pw_env_types, ONLY: pw_env_get,&
131 : pw_env_type
132 : USE pw_methods, ONLY: pw_axpy,&
133 : pw_copy,&
134 : pw_integral_ab,&
135 : pw_zero
136 : USE pw_pool_types, ONLY: pw_pool_type
137 : USE pw_types, ONLY: pw_r3d_rs_type
138 : USE pwdft_environment, ONLY: pwdft_calc_energy_force
139 : USE pwdft_environment_types, ONLY: pwdft_environment_type
140 : USE qmmm_force, ONLY: qmmm_calc_energy_force
141 : USE qmmm_types, ONLY: qmmm_env_type
142 : USE qmmm_util, ONLY: apply_qmmm_translate
143 : USE qmmmx_force, ONLY: qmmmx_calc_energy_force
144 : USE qmmmx_types, ONLY: qmmmx_env_type
145 : USE qs_energy_types, ONLY: qs_energy_type
146 : USE qs_environment_types, ONLY: get_qs_env,&
147 : qs_environment_type,&
148 : set_qs_env
149 : USE qs_force, ONLY: qs_calc_energy_force
150 : USE qs_rho_types, ONLY: qs_rho_get,&
151 : qs_rho_type
152 : USE restraint, ONLY: restraint_control
153 : USE scine_utils, ONLY: write_scine
154 : USE string_utilities, ONLY: compress
155 : USE virial_methods, ONLY: write_stress_tensor,&
156 : write_stress_tensor_components
157 : USE virial_types, ONLY: symmetrize_virial,&
158 : virial_p_type,&
159 : virial_type,&
160 : zero_virial
161 : #include "./base/base_uses.f90"
162 :
163 : IMPLICIT NONE
164 :
165 : PRIVATE
166 :
167 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'force_env_methods'
168 :
169 : PUBLIC :: force_env_create, &
170 : force_env_calc_energy_force, &
171 : force_env_calc_num_pressure
172 :
173 : INTEGER, SAVE, PRIVATE :: last_force_env_id = 0
174 :
175 : CONTAINS
176 :
177 : ! **************************************************************************************************
178 : !> \brief Interface routine for force and energy calculations
179 : !> \param force_env the force_env of which you want the energy and forces
180 : !> \param calc_force if false the forces *might* be left unchanged
181 : !> or be invalid, no guarantees can be given. Defaults to true
182 : !> \param consistent_energies Performs an additional qs_ks_update_qs_env, so
183 : !> that the energies are appropriate to the forces, they are in the
184 : !> non-selfconsistent case not consistent to each other! [08.2005, TdK]
185 : !> \param skip_external_control ...
186 : !> \param eval_energy_forces ...
187 : !> \param require_consistent_energy_force ...
188 : !> \param linres ...
189 : !> \param calc_stress_tensor ...
190 : !> \author CJM & fawzi
191 : ! **************************************************************************************************
192 196140 : RECURSIVE SUBROUTINE force_env_calc_energy_force(force_env, calc_force, &
193 : consistent_energies, skip_external_control, eval_energy_forces, &
194 : require_consistent_energy_force, linres, calc_stress_tensor)
195 :
196 : TYPE(force_env_type), POINTER :: force_env
197 : LOGICAL, INTENT(IN), OPTIONAL :: calc_force, consistent_energies, skip_external_control, &
198 : eval_energy_forces, require_consistent_energy_force, linres, calc_stress_tensor
199 :
200 : REAL(kind=dp), PARAMETER :: ateps = 1.0E-6_dp
201 :
202 : INTEGER :: i, ikind, j, nat, ndigits, nfixed_atoms, &
203 : nfixed_atoms_total, nkind, &
204 : output_unit, print_forces, print_grrm, &
205 : print_scine
206 : LOGICAL :: calculate_forces, calculate_stress_tensor, energy_consistency, eval_ef, &
207 : linres_run, my_skip, print_components
208 : REAL(KIND=dp) :: checksum, e_entropy, e_gap, e_pot, &
209 : sum_energy, sum_pv_virial, &
210 : sum_stress_tensor
211 : REAL(KIND=dp), DIMENSION(3) :: grand_total_force, total_force
212 : REAL(KIND=dp), DIMENSION(3, 3) :: atomic_stress_tensor, diff_stress_tensor
213 : TYPE(atprop_type), POINTER :: atprop_env
214 : TYPE(cell_type), POINTER :: cell
215 : TYPE(cp_logger_type), POINTER :: logger
216 : TYPE(cp_subsys_type), POINTER :: subsys
217 : TYPE(molecule_kind_list_type), POINTER :: molecule_kinds
218 98070 : TYPE(molecule_kind_type), DIMENSION(:), POINTER :: molecule_kind_set
219 : TYPE(molecule_kind_type), POINTER :: molecule_kind
220 : TYPE(particle_list_type), POINTER :: core_particles, particles, &
221 : shell_particles
222 : TYPE(virial_type), POINTER :: virial
223 :
224 98070 : NULLIFY (logger, virial, subsys, atprop_env, cell)
225 196140 : logger => cp_get_default_logger()
226 98070 : eval_ef = .TRUE.
227 98070 : my_skip = .FALSE.
228 98070 : calculate_forces = .TRUE.
229 98070 : energy_consistency = .FALSE.
230 98070 : linres_run = .FALSE.
231 98070 : e_gap = -1.0_dp
232 98070 : e_entropy = -1.0_dp
233 :
234 98070 : IF (PRESENT(eval_energy_forces)) eval_ef = eval_energy_forces
235 98070 : IF (PRESENT(skip_external_control)) my_skip = skip_external_control
236 98070 : IF (PRESENT(calc_force)) calculate_forces = calc_force
237 98070 : IF (PRESENT(calc_stress_tensor)) THEN
238 7344 : calculate_stress_tensor = calc_stress_tensor
239 : ELSE
240 90726 : calculate_stress_tensor = calculate_forces
241 : END IF
242 98070 : IF (PRESENT(consistent_energies)) energy_consistency = consistent_energies
243 98070 : IF (PRESENT(linres)) linres_run = linres
244 :
245 98070 : CPASSERT(ASSOCIATED(force_env))
246 98070 : CPASSERT(force_env%ref_count > 0)
247 98070 : CALL force_env_get(force_env, subsys=subsys)
248 98070 : CALL force_env_set(force_env, additional_potential=0.0_dp)
249 98070 : CALL cp_subsys_get(subsys, virial=virial, atprop=atprop_env, cell=cell)
250 98070 : IF (virial%pv_availability) CALL zero_virial(virial, reset=.FALSE.)
251 :
252 98070 : nat = force_env_get_natom(force_env)
253 98070 : CALL atprop_init(atprop_env, nat)
254 98070 : IF (eval_ef) THEN
255 175061 : SELECT CASE (force_env%in_use)
256 : CASE (use_fist_force)
257 77131 : CALL fist_calc_energy_force(force_env%fist_env)
258 : CASE (use_qs_force)
259 16157 : CALL qs_calc_energy_force(force_env%qs_env, calculate_forces, energy_consistency, linres_run)
260 : CASE (use_pwdft_force)
261 14 : IF (virial%pv_availability .AND. calculate_stress_tensor) THEN
262 0 : CALL pwdft_calc_energy_force(force_env%pwdft_env, calculate_forces,.NOT. virial%pv_numer)
263 : ELSE
264 14 : CALL pwdft_calc_energy_force(force_env%pwdft_env, calculate_forces, .FALSE.)
265 : END IF
266 14 : e_gap = force_env%pwdft_env%energy%band_gap
267 14 : e_entropy = force_env%pwdft_env%energy%entropy
268 : CASE (use_eip_force)
269 22 : IF (force_env%eip_env%eip_model == use_lenosky_eip) THEN
270 0 : CALL eip_lenosky(force_env%eip_env)
271 22 : ELSE IF (force_env%eip_env%eip_model == use_bazant_eip) THEN
272 22 : CALL eip_bazant(force_env%eip_env)
273 : END IF
274 : CASE (use_qmmm)
275 : CALL qmmm_calc_energy_force(force_env%qmmm_env, &
276 3698 : calculate_forces, energy_consistency, linres=linres_run)
277 : CASE (use_qmmmx)
278 : CALL qmmmx_calc_energy_force(force_env%qmmmx_env, &
279 : calculate_forces, energy_consistency, linres=linres_run, &
280 52 : require_consistent_energy_force=require_consistent_energy_force)
281 : CASE (use_mixed_force)
282 524 : CALL mixed_energy_forces(force_env, calculate_forces)
283 : CASE (use_nnp_force)
284 : CALL nnp_calc_energy_force(force_env%nnp_env, &
285 308 : calculate_forces)
286 : CASE (use_embed)
287 24 : CALL embed_energy(force_env)
288 : CASE (use_ipi)
289 0 : CALL request_forces(force_env%ipi_env)
290 : CASE default
291 97930 : CPABORT("")
292 : END SELECT
293 : END IF
294 : ! In case it is requested, we evaluate the stress tensor numerically
295 98070 : IF (virial%pv_availability) THEN
296 20004 : IF (virial%pv_numer .AND. calculate_stress_tensor) THEN
297 : ! Compute the numerical stress tensor
298 34 : CALL force_env_calc_num_pressure(force_env)
299 : ELSE
300 19970 : IF (calculate_forces) THEN
301 : ! Symmetrize analytical stress tensor
302 17316 : CALL symmetrize_virial(virial)
303 : ELSE
304 2654 : IF (calculate_stress_tensor) THEN
305 : CALL cp_warn(__LOCATION__, "The calculation of the stress tensor "// &
306 0 : "requires the calculation of the forces")
307 : END IF
308 : END IF
309 : END IF
310 : END IF
311 :
312 : !sample peak memory
313 98070 : CALL m_memory()
314 :
315 : ! Some additional tasks..
316 98070 : IF (.NOT. my_skip) THEN
317 : ! Flexible Partitioning
318 97176 : IF (ASSOCIATED(force_env%fp_env)) THEN
319 97100 : IF (force_env%fp_env%use_fp) THEN
320 122 : CALL fp_eval(force_env%fp_env, subsys, cell)
321 : END IF
322 : END IF
323 : ! Constraints ONLY of Fixed Atom type
324 97176 : CALL fix_atom_control(force_env)
325 : ! All Restraints
326 97176 : CALL restraint_control(force_env)
327 : ! Virtual Sites
328 97176 : CALL vsite_force_control(force_env)
329 : ! External Potential
330 97176 : CALL add_external_potential(force_env)
331 : ! Rescale forces if requested
332 97176 : CALL rescale_forces(force_env)
333 : END IF
334 :
335 98070 : CALL force_env_get(force_env, potential_energy=e_pot)
336 :
337 : ! Print always Energy in the same format for all methods
338 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%PROGRAM_RUN_INFO", &
339 98070 : extension=".Log")
340 98070 : IF (output_unit > 0) THEN
341 : WRITE (output_unit, '(/,T2,"ENERGY| Total FORCE_EVAL ( ",A," ) energy [a.u.]: ",T55,F26.15)') &
342 48531 : ADJUSTR(TRIM(use_prog_name(force_env%in_use))), e_pot
343 48531 : IF (e_gap .GT. -.1_dp) THEN
344 : WRITE (output_unit, '(/,T2,"ENERGY| Total FORCE_EVAL ( ",A," ) gap [a.u.]: ",T55,F26.15)') &
345 7 : ADJUSTR(TRIM(use_prog_name(force_env%in_use))), e_gap
346 : END IF
347 48531 : IF (e_entropy .GT. -0.1_dp) THEN
348 : WRITE (output_unit, '(/,T2,"ENERGY| Total FORCE_EVAL ( ",A," ) free energy [a.u.]: ",T55,F26.15)') &
349 7 : ADJUSTR(TRIM(use_prog_name(force_env%in_use))), e_pot - e_entropy
350 : END IF
351 : END IF
352 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
353 98070 : "PRINT%PROGRAM_RUN_INFO")
354 :
355 : ! terminate the run if the value of the potential is abnormal
356 98070 : IF (abnormal_value(e_pot)) &
357 0 : CPABORT("Potential energy is an abnormal value (NaN/Inf).")
358 :
359 : ! Print forces, if requested
360 : print_forces = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%FORCES", &
361 98070 : extension=".xyz")
362 98070 : IF ((print_forces > 0) .AND. calculate_forces) THEN
363 1479 : CALL force_env_get(force_env, subsys=subsys)
364 : CALL cp_subsys_get(subsys, &
365 : core_particles=core_particles, &
366 : particles=particles, &
367 1479 : shell_particles=shell_particles)
368 : ! Variable precision output of the forces
369 : CALL section_vals_val_get(force_env%force_env_section, "PRINT%FORCES%NDIGITS", &
370 1479 : i_val=ndigits)
371 1479 : IF (ASSOCIATED(core_particles) .OR. ASSOCIATED(shell_particles)) THEN
372 : CALL write_forces(particles, print_forces, "ATOMIC", ndigits, total_force, &
373 167 : zero_force_core_shell_atom=.TRUE.)
374 167 : grand_total_force(1:3) = total_force(1:3)
375 167 : IF (ASSOCIATED(core_particles)) THEN
376 : CALL write_forces(core_particles, print_forces, "CORE", ndigits, total_force, &
377 167 : zero_force_core_shell_atom=.FALSE.)
378 668 : grand_total_force(:) = grand_total_force(:) + total_force(:)
379 : END IF
380 167 : IF (ASSOCIATED(shell_particles)) THEN
381 : CALL write_forces(shell_particles, print_forces, "SHELL", ndigits, total_force, &
382 : zero_force_core_shell_atom=.FALSE., &
383 167 : grand_total_force=grand_total_force)
384 : END IF
385 : ELSE
386 1312 : CALL write_forces(particles, print_forces, "ATOMIC", ndigits, total_force)
387 : END IF
388 : END IF
389 98070 : CALL cp_print_key_finished_output(print_forces, logger, force_env%force_env_section, "PRINT%FORCES")
390 :
391 : ! Write stress tensor
392 98070 : IF (virial%pv_availability) THEN
393 : ! If the virial is defined but we are not computing forces let's zero the
394 : ! virial for consistency
395 20004 : IF (calculate_forces .AND. calculate_stress_tensor) THEN
396 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%STRESS_TENSOR", &
397 17322 : extension=".stress_tensor")
398 17322 : IF (output_unit > 0) THEN
399 : CALL section_vals_val_get(force_env%force_env_section, "PRINT%STRESS_TENSOR%COMPONENTS", &
400 6057 : l_val=print_components)
401 6057 : IF (print_components) THEN
402 112 : IF ((.NOT. virial%pv_numer) .AND. (force_env%in_use == use_qs_force)) THEN
403 108 : CALL write_stress_tensor_components(virial, output_unit, cell)
404 : END IF
405 : END IF
406 6057 : CALL write_stress_tensor(virial%pv_virial, output_unit, cell, virial%pv_numer)
407 : END IF
408 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
409 17322 : "PRINT%STRESS_TENSOR")
410 : ELSE
411 2682 : CALL zero_virial(virial, reset=.FALSE.)
412 : END IF
413 : ELSE
414 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%STRESS_TENSOR", &
415 78066 : extension=".stress_tensor")
416 78066 : IF (output_unit > 0) THEN
417 : CALL cp_warn(__LOCATION__, "To print the stress tensor switch on the "// &
418 307 : "virial evaluation with the keyword: STRESS_TENSOR")
419 : END IF
420 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
421 78066 : "PRINT%STRESS_TENSOR")
422 : END IF
423 :
424 : ! Atomic energy
425 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%PROGRAM_RUN_INFO", &
426 98070 : extension=".Log")
427 98070 : IF (atprop_env%energy) THEN
428 70174 : CALL force_env%para_env%sum(atprop_env%atener)
429 978 : CALL force_env_get(force_env, potential_energy=e_pot)
430 978 : IF (output_unit > 0) THEN
431 489 : IF (logger%iter_info%print_level >= low_print_level) THEN
432 489 : CALL cp_subsys_get(subsys=subsys, particles=particles)
433 489 : CALL write_atener(output_unit, particles, atprop_env%atener, "Mulliken Atomic Energies")
434 : END IF
435 489 : sum_energy = accurate_sum(atprop_env%atener(:))
436 489 : checksum = ABS(e_pot - sum_energy)
437 : WRITE (UNIT=output_unit, FMT="(/,(T2,A,T56,F25.13))") &
438 489 : "Potential energy (Atomic):", sum_energy, &
439 489 : "Potential energy (Total) :", e_pot, &
440 978 : "Difference :", checksum
441 489 : CPASSERT((checksum < ateps*ABS(e_pot)))
442 : END IF
443 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
444 978 : "PRINT%PROGRAM_RUN_INFO")
445 : END IF
446 :
447 : ! Print GRMM interface file
448 : print_grrm = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%GRRM", &
449 98070 : file_position="REWIND", extension=".rrm")
450 98070 : IF (print_grrm > 0) THEN
451 38 : CALL force_env_get(force_env, subsys=subsys)
452 : CALL cp_subsys_get(subsys=subsys, particles=particles, &
453 38 : molecule_kinds=molecule_kinds)
454 : ! Count the number of fixed atoms
455 38 : nfixed_atoms_total = 0
456 38 : nkind = molecule_kinds%n_els
457 38 : molecule_kind_set => molecule_kinds%els
458 158 : DO ikind = 1, nkind
459 120 : molecule_kind => molecule_kind_set(ikind)
460 120 : CALL get_molecule_kind(molecule_kind, nfixd=nfixed_atoms)
461 158 : nfixed_atoms_total = nfixed_atoms_total + nfixed_atoms
462 : END DO
463 : !
464 38 : CALL write_grrm(print_grrm, force_env, particles%els, e_pot, fixed_atoms=nfixed_atoms_total)
465 : END IF
466 98070 : CALL cp_print_key_finished_output(print_grrm, logger, force_env%force_env_section, "PRINT%GRRM")
467 :
468 : print_scine = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%SCINE", &
469 98070 : file_position="REWIND", extension=".scine")
470 98070 : IF (print_scine > 0) THEN
471 23 : CALL force_env_get(force_env, subsys=subsys)
472 23 : CALL cp_subsys_get(subsys=subsys, particles=particles)
473 : !
474 23 : CALL write_scine(print_scine, force_env, particles%els, e_pot)
475 : END IF
476 98070 : CALL cp_print_key_finished_output(print_scine, logger, force_env%force_env_section, "PRINT%SCINE")
477 :
478 : ! Atomic stress
479 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%PROGRAM_RUN_INFO", &
480 98070 : extension=".Log")
481 :
482 98070 : IF (atprop_env%stress) THEN
483 746392 : CALL force_env%para_env%sum(atprop_env%atstress)
484 : ! symmetrize (same as pv_virial)
485 29542 : DO i = 1, SIZE(atprop_env%atstress, 3)
486 : atprop_env%atstress(:, :, i) = 0.5_dp*(atprop_env%atstress(:, :, i) &
487 717718 : + TRANSPOSE(atprop_env%atstress(:, :, i)))
488 : END DO
489 868 : IF (output_unit > 0) THEN
490 434 : IF (logger%iter_info%print_level > low_print_level) THEN
491 12512 : DO i = 1, SIZE(atprop_env%atstress, 3)
492 12105 : WRITE (UNIT=output_unit, FMT="(/,T2,I0,T16,A1,2(19X,A1))") i, "X", "Y", "Z"
493 48420 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "X", (atprop_env%atstress(1, j, i), j=1, 3)
494 48420 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Y", (atprop_env%atstress(2, j, i), j=1, 3)
495 48420 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Z", (atprop_env%atstress(3, j, i), j=1, 3)
496 12105 : WRITE (UNIT=output_unit, FMT="(T2,A,F20.13)") "1/3 Trace(Atomic stress tensor):", &
497 24617 : (atprop_env%atstress(1, 1, i) + atprop_env%atstress(2, 2, i) + atprop_env%atstress(3, 3, i))/3.0_dp
498 : END DO
499 : END IF
500 434 : atomic_stress_tensor(:, :) = 0.0_dp
501 1736 : DO i = 1, 3
502 1302 : atomic_stress_tensor(i, i) = accurate_sum(atprop_env%atstress(i, i, :))
503 3038 : DO j = i + 1, 3
504 1302 : atomic_stress_tensor(i, j) = accurate_sum(atprop_env%atstress(i, j, :))
505 2604 : atomic_stress_tensor(j, i) = atomic_stress_tensor(i, j)
506 : END DO
507 : END DO
508 434 : WRITE (UNIT=output_unit, FMT="(/,T2,A,T15,A1,2(19X,A1))") "Atomic", "X", "Y", "Z"
509 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "X", (atomic_stress_tensor(1, i), i=1, 3)
510 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Y", (atomic_stress_tensor(2, i), i=1, 3)
511 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Z", (atomic_stress_tensor(3, i), i=1, 3)
512 434 : WRITE (UNIT=output_unit, FMT="(T2,A,10X,F20.13)") "1/3 Trace(Atomic stress tensor):", &
513 868 : (atomic_stress_tensor(1, 1) + atomic_stress_tensor(2, 2) + atomic_stress_tensor(3, 3))/3.0_dp
514 434 : sum_stress_tensor = accurate_sum(atomic_stress_tensor(:, :))
515 434 : IF (virial%pv_availability .AND. calculate_forces) THEN
516 434 : WRITE (UNIT=output_unit, FMT="(/,T2,A,T16,A1,2(19X,A1))") "Total", "X", "Y", "Z"
517 1736 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "X", (virial%pv_virial(1, i), i=1, 3)
518 1736 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Y", (virial%pv_virial(2, i), i=1, 3)
519 1736 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Z", (virial%pv_virial(3, i), i=1, 3)
520 434 : WRITE (UNIT=output_unit, FMT="(T2,A,10X,F20.13)") "1/3 Trace(Total stress tensor): ", &
521 868 : (virial%pv_virial(1, 1) + virial%pv_virial(2, 2) + virial%pv_virial(3, 3))/3.0_dp
522 5642 : sum_pv_virial = SUM(virial%pv_virial(:, :))
523 5642 : diff_stress_tensor(:, :) = ABS(virial%pv_virial(:, :) - atomic_stress_tensor(:, :))
524 434 : WRITE (UNIT=output_unit, FMT="(/,T2,A,T16,A1,2(19X,A1))") "Diff", "X", "Y", "Z"
525 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "X", (diff_stress_tensor(1, i), i=1, 3)
526 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Y", (diff_stress_tensor(2, i), i=1, 3)
527 434 : WRITE (UNIT=output_unit, FMT="(A3,3F20.13)") "Z", (diff_stress_tensor(3, i), i=1, 3)
528 434 : WRITE (UNIT=output_unit, FMT="(T2,A,10X,F20.13)") "1/3 Trace(Diff) : ", &
529 868 : (diff_stress_tensor(1, 1) + diff_stress_tensor(2, 2) + diff_stress_tensor(3, 3))/3.0_dp
530 434 : checksum = accurate_sum(diff_stress_tensor(:, :))
531 : WRITE (UNIT=output_unit, FMT="(/,(T2,A,11X,F25.13))") &
532 434 : "Checksum stress (Atomic) :", sum_stress_tensor, &
533 434 : "Checksum stress (Total) :", sum_pv_virial, &
534 868 : "Difference :", checksum
535 434 : CPASSERT(checksum < ateps)
536 : END IF
537 : END IF
538 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
539 868 : "PRINT%PROGRAM_RUN_INFO")
540 : END IF
541 :
542 98070 : END SUBROUTINE force_env_calc_energy_force
543 :
544 : ! **************************************************************************************************
545 : !> \brief Evaluates the stress tensor and pressure numerically
546 : !> \param force_env ...
547 : !> \param dx ...
548 : !> \par History
549 : !> 10.2005 created [JCS]
550 : !> 05.2009 Teodoro Laino [tlaino] - rewriting for general force_env
551 : !>
552 : !> \author JCS
553 : ! **************************************************************************************************
554 86 : SUBROUTINE force_env_calc_num_pressure(force_env, dx)
555 :
556 : TYPE(force_env_type), POINTER :: force_env
557 : REAL(KIND=dp), INTENT(IN), OPTIONAL :: dx
558 :
559 : REAL(kind=dp), PARAMETER :: default_dx = 0.001_dp
560 :
561 : INTEGER :: i, ip, iq, j, k, natom, ncore, nshell, &
562 : output_unit, symmetry_id
563 : REAL(KIND=dp) :: dx_w
564 : REAL(KIND=dp), DIMENSION(2) :: numer_energy
565 : REAL(KIND=dp), DIMENSION(3) :: s
566 : REAL(KIND=dp), DIMENSION(3, 3) :: numer_stress
567 86 : REAL(KIND=dp), DIMENSION(:, :), POINTER :: ref_pos_atom, ref_pos_core, ref_pos_shell
568 : TYPE(cell_type), POINTER :: cell, cell_local
569 : TYPE(cp_logger_type), POINTER :: logger
570 : TYPE(cp_subsys_type), POINTER :: subsys
571 : TYPE(global_environment_type), POINTER :: globenv
572 : TYPE(particle_list_type), POINTER :: core_particles, particles, &
573 : shell_particles
574 : TYPE(virial_type), POINTER :: virial
575 :
576 86 : NULLIFY (cell_local)
577 86 : NULLIFY (core_particles)
578 86 : NULLIFY (particles)
579 86 : NULLIFY (shell_particles)
580 86 : NULLIFY (ref_pos_atom)
581 86 : NULLIFY (ref_pos_core)
582 86 : NULLIFY (ref_pos_shell)
583 86 : natom = 0
584 86 : ncore = 0
585 86 : nshell = 0
586 86 : numer_stress = 0.0_dp
587 :
588 172 : logger => cp_get_default_logger()
589 :
590 86 : dx_w = default_dx
591 86 : IF (PRESENT(dx)) dx_w = dx
592 86 : CALL force_env_get(force_env, subsys=subsys, globenv=globenv)
593 : CALL cp_subsys_get(subsys, &
594 : core_particles=core_particles, &
595 : particles=particles, &
596 : shell_particles=shell_particles, &
597 86 : virial=virial)
598 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%STRESS_TENSOR", &
599 86 : extension=".stress_tensor")
600 86 : IF (output_unit > 0) THEN
601 12 : WRITE (output_unit, '(/A,A/)') ' **************************** ', &
602 24 : 'NUMERICAL STRESS ********************************'
603 : END IF
604 :
605 : ! Save all original particle positions
606 86 : natom = particles%n_els
607 258 : ALLOCATE (ref_pos_atom(natom, 3))
608 6732 : DO i = 1, natom
609 26670 : ref_pos_atom(i, :) = particles%els(i)%r
610 : END DO
611 86 : IF (ASSOCIATED(core_particles)) THEN
612 6 : ncore = core_particles%n_els
613 18 : ALLOCATE (ref_pos_core(ncore, 3))
614 1550 : DO i = 1, ncore
615 6182 : ref_pos_core(i, :) = core_particles%els(i)%r
616 : END DO
617 : END IF
618 86 : IF (ASSOCIATED(shell_particles)) THEN
619 6 : nshell = shell_particles%n_els
620 18 : ALLOCATE (ref_pos_shell(nshell, 3))
621 1550 : DO i = 1, nshell
622 6182 : ref_pos_shell(i, :) = shell_particles%els(i)%r
623 : END DO
624 : END IF
625 86 : CALL force_env_get(force_env, cell=cell)
626 : ! Save cell symmetry (distorted cell has no symmetry)
627 86 : symmetry_id = cell%symmetry_id
628 86 : cell%symmetry_id = cell_sym_triclinic
629 : !
630 86 : CALL cell_create(cell_local)
631 86 : CALL cell_clone(cell, cell_local)
632 : ! First change box
633 344 : DO ip = 1, 3
634 1118 : DO iq = 1, 3
635 774 : IF (virial%pv_diagonal .AND. (ip /= iq)) CYCLE
636 1746 : DO k = 1, 2
637 1164 : cell%hmat(ip, iq) = cell_local%hmat(ip, iq) - (-1.0_dp)**k*dx_w
638 1164 : CALL init_cell(cell)
639 : ! Scale positions
640 65304 : DO i = 1, natom
641 64140 : CALL real_to_scaled(s, ref_pos_atom(i, 1:3), cell_local)
642 65304 : CALL scaled_to_real(particles%els(i)%r, s, cell)
643 : END DO
644 28956 : DO i = 1, ncore
645 27792 : CALL real_to_scaled(s, ref_pos_core(i, 1:3), cell_local)
646 28956 : CALL scaled_to_real(core_particles%els(i)%r, s, cell)
647 : END DO
648 28956 : DO i = 1, nshell
649 27792 : CALL real_to_scaled(s, ref_pos_shell(i, 1:3), cell_local)
650 28956 : CALL scaled_to_real(shell_particles%els(i)%r, s, cell)
651 : END DO
652 : ! Compute energies
653 : CALL force_env_calc_energy_force(force_env, &
654 : calc_force=.FALSE., &
655 : consistent_energies=.TRUE., &
656 1164 : calc_stress_tensor=.FALSE.)
657 1164 : CALL force_env_get(force_env, potential_energy=numer_energy(k))
658 : ! Reset cell
659 1746 : cell%hmat(ip, iq) = cell_local%hmat(ip, iq)
660 : END DO
661 582 : CALL init_cell(cell)
662 582 : numer_stress(ip, iq) = 0.5_dp*(numer_energy(1) - numer_energy(2))/dx_w
663 840 : IF (output_unit > 0) THEN
664 90 : IF (globenv%run_type_id == debug_run) THEN
665 : WRITE (UNIT=output_unit, FMT="(/,T2,A,T19,A,F7.4,A,T44,A,F7.4,A,T69,A)") &
666 72 : "DEBUG|", "E("//ACHAR(119 + ip)//ACHAR(119 + iq)//" +", dx_w, ")", &
667 72 : "E("//ACHAR(119 + ip)//ACHAR(119 + iq)//" -", dx_w, ")", &
668 144 : "f(numerical)"
669 : WRITE (UNIT=output_unit, FMT="(T2,A,2(1X,F24.8),1X,F22.8)") &
670 72 : "DEBUG|", numer_energy(1:2), numer_stress(ip, iq)
671 : ELSE
672 : WRITE (UNIT=output_unit, FMT="(/,T7,A,F7.4,A,T27,A,F7.4,A,T49,A)") &
673 18 : "E("//ACHAR(119 + ip)//ACHAR(119 + iq)//" +", dx_w, ")", &
674 18 : "E("//ACHAR(119 + ip)//ACHAR(119 + iq)//" -", dx_w, ")", &
675 36 : "f(numerical)"
676 : WRITE (UNIT=output_unit, FMT="(3(1X,F19.8))") &
677 18 : numer_energy(1:2), numer_stress(ip, iq)
678 : END IF
679 : END IF
680 : END DO
681 : END DO
682 :
683 : ! Reset positions and rebuild original environment
684 86 : cell%symmetry_id = symmetry_id
685 86 : CALL init_cell(cell)
686 6732 : DO i = 1, natom
687 46608 : particles%els(i)%r = ref_pos_atom(i, :)
688 : END DO
689 1630 : DO i = 1, ncore
690 10894 : core_particles%els(i)%r = ref_pos_core(i, :)
691 : END DO
692 1630 : DO i = 1, nshell
693 10894 : shell_particles%els(i)%r = ref_pos_shell(i, :)
694 : END DO
695 : CALL force_env_calc_energy_force(force_env, &
696 : calc_force=.FALSE., &
697 : consistent_energies=.TRUE., &
698 86 : calc_stress_tensor=.FALSE.)
699 :
700 : ! Computing pv_test
701 1118 : virial%pv_virial = 0.0_dp
702 344 : DO i = 1, 3
703 1118 : DO j = 1, 3
704 3354 : DO k = 1, 3
705 : virial%pv_virial(i, j) = virial%pv_virial(i, j) - &
706 : 0.5_dp*(numer_stress(i, k)*cell_local%hmat(j, k) + &
707 3096 : numer_stress(j, k)*cell_local%hmat(i, k))
708 : END DO
709 : END DO
710 : END DO
711 :
712 86 : IF (output_unit > 0) THEN
713 12 : IF (globenv%run_type_id == debug_run) THEN
714 8 : CALL write_stress_tensor(virial%pv_virial, output_unit, cell, virial%pv_numer)
715 : END IF
716 : WRITE (output_unit, '(/,A,/)') ' **************************** '// &
717 12 : 'NUMERICAL STRESS END *****************************'
718 : END IF
719 :
720 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
721 86 : "PRINT%STRESS_TENSOR")
722 :
723 : ! Release storage
724 86 : IF (ASSOCIATED(ref_pos_atom)) THEN
725 86 : DEALLOCATE (ref_pos_atom)
726 : END IF
727 86 : IF (ASSOCIATED(ref_pos_core)) THEN
728 6 : DEALLOCATE (ref_pos_core)
729 : END IF
730 86 : IF (ASSOCIATED(ref_pos_shell)) THEN
731 6 : DEALLOCATE (ref_pos_shell)
732 : END IF
733 86 : IF (ASSOCIATED(cell_local)) CALL cell_release(cell_local)
734 :
735 86 : END SUBROUTINE force_env_calc_num_pressure
736 :
737 : ! **************************************************************************************************
738 : !> \brief creates and initializes a force environment
739 : !> \param force_env the force env to create
740 : !> \param root_section ...
741 : !> \param para_env ...
742 : !> \param globenv ...
743 : !> \param fist_env , qs_env: exactly one of these should be
744 : !> associated, the one that is active
745 : !> \param qs_env ...
746 : !> \param meta_env ...
747 : !> \param sub_force_env ...
748 : !> \param qmmm_env ...
749 : !> \param qmmmx_env ...
750 : !> \param eip_env ...
751 : !> \param pwdft_env ...
752 : !> \param force_env_section ...
753 : !> \param mixed_env ...
754 : !> \param embed_env ...
755 : !> \param nnp_env ...
756 : !> \param ipi_env ...
757 : !> \par History
758 : !> 04.2003 created [fawzi]
759 : !> \author fawzi
760 : ! **************************************************************************************************
761 8819 : SUBROUTINE force_env_create(force_env, root_section, para_env, globenv, fist_env, &
762 : qs_env, meta_env, sub_force_env, qmmm_env, qmmmx_env, eip_env, pwdft_env, force_env_section, &
763 : mixed_env, embed_env, nnp_env, ipi_env)
764 :
765 : TYPE(force_env_type), POINTER :: force_env
766 : TYPE(section_vals_type), POINTER :: root_section
767 : TYPE(mp_para_env_type), POINTER :: para_env
768 : TYPE(global_environment_type), POINTER :: globenv
769 : TYPE(fist_environment_type), OPTIONAL, POINTER :: fist_env
770 : TYPE(qs_environment_type), OPTIONAL, POINTER :: qs_env
771 : TYPE(meta_env_type), OPTIONAL, POINTER :: meta_env
772 : TYPE(force_env_p_type), DIMENSION(:), OPTIONAL, &
773 : POINTER :: sub_force_env
774 : TYPE(qmmm_env_type), OPTIONAL, POINTER :: qmmm_env
775 : TYPE(qmmmx_env_type), OPTIONAL, POINTER :: qmmmx_env
776 : TYPE(eip_environment_type), OPTIONAL, POINTER :: eip_env
777 : TYPE(pwdft_environment_type), OPTIONAL, POINTER :: pwdft_env
778 : TYPE(section_vals_type), POINTER :: force_env_section
779 : TYPE(mixed_environment_type), OPTIONAL, POINTER :: mixed_env
780 : TYPE(embed_env_type), OPTIONAL, POINTER :: embed_env
781 : TYPE(nnp_type), OPTIONAL, POINTER :: nnp_env
782 : TYPE(ipi_environment_type), OPTIONAL, POINTER :: ipi_env
783 :
784 8819 : ALLOCATE (force_env)
785 : NULLIFY (force_env%fist_env, force_env%qs_env, &
786 : force_env%para_env, force_env%globenv, &
787 : force_env%meta_env, force_env%sub_force_env, &
788 : force_env%qmmm_env, force_env%qmmmx_env, force_env%fp_env, &
789 : force_env%force_env_section, force_env%eip_env, force_env%mixed_env, &
790 : force_env%embed_env, force_env%pwdft_env, force_env%nnp_env, &
791 : force_env%root_section)
792 8819 : last_force_env_id = last_force_env_id + 1
793 8819 : force_env%ref_count = 1
794 : force_env%in_use = 0
795 : force_env%additional_potential = 0.0_dp
796 :
797 8819 : force_env%globenv => globenv
798 8819 : CALL globenv_retain(force_env%globenv)
799 :
800 8819 : force_env%root_section => root_section
801 8819 : CALL section_vals_retain(root_section)
802 :
803 8819 : force_env%para_env => para_env
804 8819 : CALL force_env%para_env%retain()
805 :
806 8819 : CALL section_vals_retain(force_env_section)
807 8819 : force_env%force_env_section => force_env_section
808 :
809 8819 : IF (PRESENT(fist_env)) THEN
810 2245 : CPASSERT(ASSOCIATED(fist_env))
811 2245 : CPASSERT(force_env%in_use == 0)
812 2245 : force_env%in_use = use_fist_force
813 2245 : force_env%fist_env => fist_env
814 : END IF
815 8819 : IF (PRESENT(eip_env)) THEN
816 2 : CPASSERT(ASSOCIATED(eip_env))
817 2 : CPASSERT(force_env%in_use == 0)
818 2 : force_env%in_use = use_eip_force
819 2 : force_env%eip_env => eip_env
820 : END IF
821 8819 : IF (PRESENT(pwdft_env)) THEN
822 14 : CPASSERT(ASSOCIATED(pwdft_env))
823 14 : CPASSERT(force_env%in_use == 0)
824 14 : force_env%in_use = use_pwdft_force
825 14 : force_env%pwdft_env => pwdft_env
826 : END IF
827 8819 : IF (PRESENT(qs_env)) THEN
828 6056 : CPASSERT(ASSOCIATED(qs_env))
829 6056 : CPASSERT(force_env%in_use == 0)
830 6056 : force_env%in_use = use_qs_force
831 6056 : force_env%qs_env => qs_env
832 : END IF
833 8819 : IF (PRESENT(qmmm_env)) THEN
834 326 : CPASSERT(ASSOCIATED(qmmm_env))
835 326 : CPASSERT(force_env%in_use == 0)
836 326 : force_env%in_use = use_qmmm
837 326 : force_env%qmmm_env => qmmm_env
838 : END IF
839 8819 : IF (PRESENT(qmmmx_env)) THEN
840 8 : CPASSERT(ASSOCIATED(qmmmx_env))
841 8 : CPASSERT(force_env%in_use == 0)
842 8 : force_env%in_use = use_qmmmx
843 8 : force_env%qmmmx_env => qmmmx_env
844 : END IF
845 8819 : IF (PRESENT(mixed_env)) THEN
846 130 : CPASSERT(ASSOCIATED(mixed_env))
847 130 : CPASSERT(force_env%in_use == 0)
848 130 : force_env%in_use = use_mixed_force
849 130 : force_env%mixed_env => mixed_env
850 : END IF
851 8819 : IF (PRESENT(embed_env)) THEN
852 24 : CPASSERT(ASSOCIATED(embed_env))
853 24 : CPASSERT(force_env%in_use == 0)
854 24 : force_env%in_use = use_embed
855 24 : force_env%embed_env => embed_env
856 : END IF
857 8819 : IF (PRESENT(nnp_env)) THEN
858 14 : CPASSERT(ASSOCIATED(nnp_env))
859 14 : CPASSERT(force_env%in_use == 0)
860 14 : force_env%in_use = use_nnp_force
861 14 : force_env%nnp_env => nnp_env
862 : END IF
863 8819 : IF (PRESENT(ipi_env)) THEN
864 0 : CPASSERT(ASSOCIATED(ipi_env))
865 0 : CPASSERT(force_env%in_use == 0)
866 0 : force_env%in_use = use_ipi
867 0 : force_env%ipi_env => ipi_env
868 : END IF
869 8819 : CPASSERT(force_env%in_use /= 0)
870 :
871 8819 : IF (PRESENT(sub_force_env)) THEN
872 0 : force_env%sub_force_env => sub_force_env
873 : END IF
874 :
875 8819 : IF (PRESENT(meta_env)) THEN
876 0 : force_env%meta_env => meta_env
877 : ELSE
878 8819 : NULLIFY (force_env%meta_env)
879 : END IF
880 :
881 8819 : END SUBROUTINE force_env_create
882 :
883 : ! **************************************************************************************************
884 : !> \brief ****f* force_env_methods/mixed_energy_forces [1.0]
885 : !>
886 : !> Computes energy and forces for a mixed force_env type
887 : !> \param force_env the force_env that holds the mixed_env type
888 : !> \param calculate_forces decides if forces should be calculated
889 : !> \par History
890 : !> 11.06 created [fschiff]
891 : !> 04.07 generalization to an illimited number of force_eval [tlaino]
892 : !> 04.07 further generalization to force_eval with different geometrical
893 : !> structures [tlaino]
894 : !> 04.08 reorganizing the genmix structure (collecting common code)
895 : !> 01.16 added CDFT [Nico Holmberg]
896 : !> 08.17 added DFT embedding [Vladimir Rybkin]
897 : !> \author Florian Schiffmann
898 : ! **************************************************************************************************
899 524 : SUBROUTINE mixed_energy_forces(force_env, calculate_forces)
900 :
901 : TYPE(force_env_type), POINTER :: force_env
902 : LOGICAL, INTENT(IN) :: calculate_forces
903 :
904 : CHARACTER(LEN=default_path_length) :: coupling_function
905 : CHARACTER(LEN=default_string_length) :: def_error, description, this_error
906 : INTEGER :: iforce_eval, iparticle, istate(2), &
907 : jparticle, mixing_type, my_group, &
908 : natom, nforce_eval, source, unit_nr
909 524 : INTEGER, DIMENSION(:), POINTER :: glob_natoms, itmplist, map_index
910 : LOGICAL :: dip_exists
911 : REAL(KIND=dp) :: coupling_parameter, dedf, der_1, der_2, &
912 : dx, energy, err, lambda, lerr, &
913 : restraint_strength, restraint_target, &
914 : sd
915 : REAL(KIND=dp), DIMENSION(3) :: dip_mix
916 524 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
917 : TYPE(cell_type), POINTER :: cell_mix
918 : TYPE(cp_logger_type), POINTER :: logger, my_logger
919 524 : TYPE(cp_result_p_type), DIMENSION(:), POINTER :: results
920 : TYPE(cp_result_type), POINTER :: loc_results, results_mix
921 524 : TYPE(cp_subsys_p_type), DIMENSION(:), POINTER :: subsystems
922 : TYPE(cp_subsys_type), POINTER :: subsys_mix
923 : TYPE(mixed_energy_type), POINTER :: mixed_energy
924 524 : TYPE(mixed_force_type), DIMENSION(:), POINTER :: global_forces
925 : TYPE(particle_list_p_type), DIMENSION(:), POINTER :: particles
926 : TYPE(particle_list_type), POINTER :: particles_mix
927 : TYPE(section_vals_type), POINTER :: force_env_section, gen_section, &
928 : mapping_section, mixed_section, &
929 : root_section
930 524 : TYPE(virial_p_type), DIMENSION(:), POINTER :: virials
931 : TYPE(virial_type), POINTER :: loc_virial, virial_mix
932 :
933 1048 : logger => cp_get_default_logger()
934 524 : CPASSERT(ASSOCIATED(force_env))
935 : ! Get infos about the mixed subsys
936 : CALL force_env_get(force_env=force_env, &
937 : subsys=subsys_mix, &
938 : force_env_section=force_env_section, &
939 : root_section=root_section, &
940 524 : cell=cell_mix)
941 : CALL cp_subsys_get(subsys=subsys_mix, &
942 : particles=particles_mix, &
943 : virial=virial_mix, &
944 524 : results=results_mix)
945 524 : NULLIFY (map_index, glob_natoms, global_forces, itmplist)
946 :
947 524 : nforce_eval = SIZE(force_env%sub_force_env)
948 524 : mixed_section => section_vals_get_subs_vals(force_env_section, "MIXED")
949 524 : mapping_section => section_vals_get_subs_vals(mixed_section, "MAPPING")
950 : ! Global Info
951 2712 : ALLOCATE (subsystems(nforce_eval))
952 2188 : ALLOCATE (particles(nforce_eval))
953 : ! Local Info to sync
954 2712 : ALLOCATE (global_forces(nforce_eval))
955 1048 : ALLOCATE (energies(nforce_eval))
956 1572 : ALLOCATE (glob_natoms(nforce_eval))
957 2188 : ALLOCATE (virials(nforce_eval))
958 2188 : ALLOCATE (results(nforce_eval))
959 1664 : energies = 0.0_dp
960 1664 : glob_natoms = 0
961 : ! Check if mixed CDFT calculation is requested and initialize
962 524 : CALL mixed_cdft_init(force_env, calculate_forces)
963 :
964 : !
965 524 : IF (.NOT. force_env%mixed_env%do_mixed_cdft) THEN
966 1358 : DO iforce_eval = 1, nforce_eval
967 928 : NULLIFY (subsystems(iforce_eval)%subsys, particles(iforce_eval)%list)
968 928 : NULLIFY (results(iforce_eval)%results, virials(iforce_eval)%virial)
969 212512 : ALLOCATE (virials(iforce_eval)%virial)
970 928 : CALL cp_result_create(results(iforce_eval)%results)
971 928 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
972 : ! From this point on the error is the sub_error
973 466 : my_group = force_env%mixed_env%group_distribution(force_env%para_env%mepos)
974 466 : my_logger => force_env%mixed_env%sub_logger(my_group + 1)%p
975 : ! Copy iterations info (they are updated only in the main mixed_env)
976 466 : CALL cp_iteration_info_copy_iter(logger%iter_info, my_logger%iter_info)
977 466 : CALL cp_add_default_logger(my_logger)
978 :
979 : ! Get all available subsys
980 : CALL force_env_get(force_env=force_env%sub_force_env(iforce_eval)%force_env, &
981 466 : subsys=subsystems(iforce_eval)%subsys)
982 :
983 : ! all force_env share the same cell
984 466 : CALL cp_subsys_set(subsystems(iforce_eval)%subsys, cell=cell_mix)
985 :
986 : ! Get available particles
987 : CALL cp_subsys_get(subsys=subsystems(iforce_eval)%subsys, &
988 466 : particles=particles(iforce_eval)%list)
989 :
990 : ! Get Mapping index array
991 466 : natom = SIZE(particles(iforce_eval)%list%els)
992 :
993 : CALL get_subsys_map_index(mapping_section, natom, iforce_eval, nforce_eval, &
994 466 : map_index)
995 :
996 : ! Mapping particles from iforce_eval environment to the mixed env
997 439077 : DO iparticle = 1, natom
998 438611 : jparticle = map_index(iparticle)
999 3070743 : particles(iforce_eval)%list%els(iparticle)%r = particles_mix%els(jparticle)%r
1000 : END DO
1001 :
1002 : ! Calculate energy and forces for each sub_force_env
1003 : CALL force_env_calc_energy_force(force_env%sub_force_env(iforce_eval)%force_env, &
1004 : calc_force=calculate_forces, &
1005 466 : skip_external_control=.TRUE.)
1006 :
1007 : ! Only the rank 0 process collect info for each computation
1008 466 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1009 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, &
1010 464 : potential_energy=energy)
1011 : CALL cp_subsys_get(subsystems(iforce_eval)%subsys, &
1012 464 : virial=loc_virial, results=loc_results)
1013 464 : energies(iforce_eval) = energy
1014 464 : glob_natoms(iforce_eval) = natom
1015 464 : virials(iforce_eval)%virial = loc_virial
1016 464 : CALL cp_result_copy(loc_results, results(iforce_eval)%results)
1017 : END IF
1018 : ! Deallocate map_index array
1019 466 : IF (ASSOCIATED(map_index)) THEN
1020 466 : DEALLOCATE (map_index)
1021 : END IF
1022 1358 : CALL cp_rm_default_logger()
1023 : END DO
1024 : ELSE
1025 : CALL mixed_cdft_energy_forces(force_env, calculate_forces, particles, energies, &
1026 94 : glob_natoms, virials, results)
1027 : END IF
1028 : ! Handling Parallel execution
1029 524 : CALL force_env%para_env%sync()
1030 : ! Post CDFT operations
1031 524 : CALL mixed_cdft_post_energy_forces(force_env)
1032 : ! Let's transfer energy, natom, forces, virials
1033 2804 : CALL force_env%para_env%sum(energies)
1034 2804 : CALL force_env%para_env%sum(glob_natoms)
1035 : ! Transfer forces
1036 1664 : DO iforce_eval = 1, nforce_eval
1037 3420 : ALLOCATE (global_forces(iforce_eval)%forces(3, glob_natoms(iforce_eval)))
1038 3512100 : global_forces(iforce_eval)%forces = 0.0_dp
1039 1140 : IF (ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) THEN
1040 642 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1041 : ! Forces
1042 439440 : DO iparticle = 1, glob_natoms(iforce_eval)
1043 : global_forces(iforce_eval)%forces(:, iparticle) = &
1044 3072660 : particles(iforce_eval)%list%els(iparticle)%f
1045 : END DO
1046 : END IF
1047 : END IF
1048 7023060 : CALL force_env%para_env%sum(global_forces(iforce_eval)%forces)
1049 : !Transfer only the relevant part of the virial..
1050 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_total)
1051 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_kinetic)
1052 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_virial)
1053 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_xc)
1054 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_fock_4c)
1055 1140 : CALL force_env%para_env%sum(virials(iforce_eval)%virial%pv_constraint)
1056 : !Transfer results
1057 1140 : source = 0
1058 1140 : IF (ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) THEN
1059 642 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) &
1060 570 : source = force_env%para_env%mepos
1061 : END IF
1062 1140 : CALL force_env%para_env%sum(source)
1063 1664 : CALL cp_results_mp_bcast(results(iforce_eval)%results, source, force_env%para_env)
1064 : END DO
1065 :
1066 2804 : force_env%mixed_env%energies = energies
1067 : ! Start combining the different sub_force_env
1068 : CALL get_mixed_env(mixed_env=force_env%mixed_env, &
1069 524 : mixed_energy=mixed_energy)
1070 :
1071 : !NB: do this for all MIXING_TYPE values, since some need it (e.g. linear mixing
1072 : !NB if the first system has fewer atoms than the second)
1073 440682 : DO iparticle = 1, SIZE(particles_mix%els)
1074 1761156 : particles_mix%els(iparticle)%f(:) = 0.0_dp
1075 : END DO
1076 :
1077 524 : CALL section_vals_val_get(mixed_section, "MIXING_TYPE", i_val=mixing_type)
1078 42 : SELECT CASE (mixing_type)
1079 : CASE (mix_linear_combination)
1080 : ! Support offered only 2 force_eval
1081 42 : CPASSERT(nforce_eval == 2)
1082 42 : CALL section_vals_val_get(mixed_section, "LINEAR%LAMBDA", r_val=lambda)
1083 42 : mixed_energy%pot = lambda*energies(1) + (1.0_dp - lambda)*energies(2)
1084 : ! General Mapping of forces...
1085 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1086 42 : lambda, 1, nforce_eval, map_index, mapping_section, .TRUE.)
1087 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1088 42 : (1.0_dp - lambda), 2, nforce_eval, map_index, mapping_section, .FALSE.)
1089 : CASE (mix_minimum)
1090 : ! Support offered only 2 force_eval
1091 0 : CPASSERT(nforce_eval == 2)
1092 0 : IF (energies(1) < energies(2)) THEN
1093 0 : mixed_energy%pot = energies(1)
1094 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1095 0 : 1.0_dp, 1, nforce_eval, map_index, mapping_section, .TRUE.)
1096 : ELSE
1097 0 : mixed_energy%pot = energies(2)
1098 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1099 0 : 1.0_dp, 2, nforce_eval, map_index, mapping_section, .TRUE.)
1100 : END IF
1101 : CASE (mix_coupled)
1102 : ! Support offered only 2 force_eval
1103 12 : CPASSERT(nforce_eval == 2)
1104 : CALL section_vals_val_get(mixed_section, "COUPLING%COUPLING_PARAMETER", &
1105 12 : r_val=coupling_parameter)
1106 12 : sd = SQRT((energies(1) - energies(2))**2 + 4.0_dp*coupling_parameter**2)
1107 12 : der_1 = (1.0_dp - (1.0_dp/(2.0_dp*sd))*2.0_dp*(energies(1) - energies(2)))/2.0_dp
1108 12 : der_2 = (1.0_dp + (1.0_dp/(2.0_dp*sd))*2.0_dp*(energies(1) - energies(2)))/2.0_dp
1109 12 : mixed_energy%pot = (energies(1) + energies(2) - sd)/2.0_dp
1110 : ! General Mapping of forces...
1111 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1112 12 : der_1, 1, nforce_eval, map_index, mapping_section, .TRUE.)
1113 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1114 12 : der_2, 2, nforce_eval, map_index, mapping_section, .FALSE.)
1115 : CASE (mix_restrained)
1116 : ! Support offered only 2 force_eval
1117 12 : CPASSERT(nforce_eval == 2)
1118 : CALL section_vals_val_get(mixed_section, "RESTRAINT%RESTRAINT_TARGET", &
1119 12 : r_val=restraint_target)
1120 : CALL section_vals_val_get(mixed_section, "RESTRAINT%RESTRAINT_STRENGTH", &
1121 12 : r_val=restraint_strength)
1122 12 : mixed_energy%pot = energies(1) + restraint_strength*(energies(1) - energies(2) - restraint_target)**2
1123 12 : der_2 = -2.0_dp*restraint_strength*(energies(1) - energies(2) - restraint_target)
1124 12 : der_1 = 1.0_dp - der_2
1125 : ! General Mapping of forces...
1126 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1127 12 : der_1, 1, nforce_eval, map_index, mapping_section, .TRUE.)
1128 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1129 12 : der_2, 2, nforce_eval, map_index, mapping_section, .FALSE.)
1130 : CASE (mix_generic)
1131 : ! Support any number of force_eval sections
1132 364 : gen_section => section_vals_get_subs_vals(mixed_section, "GENERIC")
1133 : CALL get_generic_info(gen_section, "MIXING_FUNCTION", coupling_function, force_env%mixed_env%par, &
1134 364 : force_env%mixed_env%val, energies)
1135 364 : CALL initf(1)
1136 364 : CALL parsef(1, TRIM(coupling_function), force_env%mixed_env%par)
1137 : ! Now the hardest part.. map energy with corresponding force_eval
1138 364 : mixed_energy%pot = evalf(1, force_env%mixed_env%val)
1139 364 : CPASSERT(EvalErrType <= 0)
1140 364 : CALL zero_virial(virial_mix, reset=.FALSE.)
1141 364 : CALL cp_results_erase(results_mix)
1142 1160 : DO iforce_eval = 1, nforce_eval
1143 796 : CALL section_vals_val_get(gen_section, "DX", r_val=dx)
1144 796 : CALL section_vals_val_get(gen_section, "ERROR_LIMIT", r_val=lerr)
1145 796 : dedf = evalfd(1, iforce_eval, force_env%mixed_env%val, dx, err)
1146 796 : IF (ABS(err) > lerr) THEN
1147 0 : WRITE (this_error, "(A,G12.6,A)") "(", err, ")"
1148 0 : WRITE (def_error, "(A,G12.6,A)") "(", lerr, ")"
1149 0 : CALL compress(this_error, .TRUE.)
1150 0 : CALL compress(def_error, .TRUE.)
1151 : CALL cp_warn(__LOCATION__, &
1152 : 'ASSERTION (cond) failed at line '//cp_to_string(__LINE__)// &
1153 : ' Error '//TRIM(this_error)//' in computing numerical derivatives larger then'// &
1154 0 : TRIM(def_error)//' .')
1155 : END IF
1156 : ! General Mapping of forces...
1157 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1158 796 : dedf, iforce_eval, nforce_eval, map_index, mapping_section, .FALSE.)
1159 1956 : force_env%mixed_env%val(iforce_eval) = energies(iforce_eval)
1160 : END DO
1161 : ! Let's store the needed information..
1162 364 : force_env%mixed_env%dx = dx
1163 364 : force_env%mixed_env%lerr = lerr
1164 364 : force_env%mixed_env%coupling_function = TRIM(coupling_function)
1165 364 : CALL finalizef()
1166 : CASE (mix_cdft)
1167 : ! Supports any number of force_evals for calculation of CDFT properties, but forces only from two
1168 94 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%LAMBDA", r_val=lambda)
1169 : ! Get the states which determine the forces
1170 94 : CALL section_vals_val_get(mixed_section, "MIXED_CDFT%FORCE_STATES", i_vals=itmplist)
1171 94 : IF (SIZE(itmplist) /= 2) &
1172 : CALL cp_abort(__LOCATION__, &
1173 0 : "Keyword FORCE_STATES takes exactly two input values.")
1174 282 : IF (ANY(itmplist .LT. 0)) &
1175 0 : CPABORT("Invalid force_eval index.")
1176 282 : istate = itmplist
1177 94 : IF (istate(1) > nforce_eval .OR. istate(2) > nforce_eval) &
1178 0 : CPABORT("Invalid force_eval index.")
1179 94 : mixed_energy%pot = lambda*energies(istate(1)) + (1.0_dp - lambda)*energies(istate(2))
1180 : ! General Mapping of forces...
1181 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1182 94 : lambda, istate(1), nforce_eval, map_index, mapping_section, .TRUE.)
1183 : CALL mixed_map_forces(particles_mix, virial_mix, results_mix, global_forces, virials, results, &
1184 94 : (1.0_dp - lambda), istate(2), nforce_eval, map_index, mapping_section, .FALSE.)
1185 : CASE DEFAULT
1186 590 : CPABORT("")
1187 : END SELECT
1188 : !Simply deallocate and loose the pointer references..
1189 1664 : DO iforce_eval = 1, nforce_eval
1190 1140 : DEALLOCATE (global_forces(iforce_eval)%forces)
1191 1140 : IF (ASSOCIATED(virials(iforce_eval)%virial)) DEALLOCATE (virials(iforce_eval)%virial)
1192 1664 : CALL cp_result_release(results(iforce_eval)%results)
1193 : END DO
1194 524 : DEALLOCATE (global_forces)
1195 524 : DEALLOCATE (subsystems)
1196 524 : DEALLOCATE (particles)
1197 524 : DEALLOCATE (energies)
1198 524 : DEALLOCATE (glob_natoms)
1199 524 : DEALLOCATE (virials)
1200 524 : DEALLOCATE (results)
1201 : ! Print Section
1202 : unit_nr = cp_print_key_unit_nr(logger, mixed_section, "PRINT%DIPOLE", &
1203 524 : extension=".data", middle_name="MIXED_DIPOLE", log_filename=.FALSE.)
1204 524 : IF (unit_nr > 0) THEN
1205 105 : description = '[DIPOLE]'
1206 105 : dip_exists = test_for_result(results=results_mix, description=description)
1207 105 : IF (dip_exists) THEN
1208 66 : CALL get_results(results=results_mix, description=description, values=dip_mix)
1209 66 : WRITE (unit_nr, '(/,1X,A,T48,3F21.16)') "MIXED ENV| DIPOLE ( A.U.)|", dip_mix
1210 264 : WRITE (unit_nr, '( 1X,A,T48,3F21.16)') "MIXED ENV| DIPOLE (Debye)|", dip_mix*debye
1211 : ELSE
1212 39 : WRITE (unit_nr, *) "NO FORCE_EVAL section calculated the dipole"
1213 : END IF
1214 : END IF
1215 524 : CALL cp_print_key_finished_output(unit_nr, logger, mixed_section, "PRINT%DIPOLE")
1216 1048 : END SUBROUTINE mixed_energy_forces
1217 :
1218 : ! **************************************************************************************************
1219 : !> \brief Driver routine for mixed CDFT energy and force calculations
1220 : !> \param force_env the force_env that holds the mixed_env
1221 : !> \param calculate_forces if forces should be calculated
1222 : !> \param particles system particles
1223 : !> \param energies the energies of the CDFT states
1224 : !> \param glob_natoms the total number of particles
1225 : !> \param virials the virials stored in subsys
1226 : !> \param results results stored in subsys
1227 : !> \par History
1228 : !> 01.17 created [Nico Holmberg]
1229 : !> \author Nico Holmberg
1230 : ! **************************************************************************************************
1231 94 : SUBROUTINE mixed_cdft_energy_forces(force_env, calculate_forces, particles, energies, &
1232 : glob_natoms, virials, results)
1233 : TYPE(force_env_type), POINTER :: force_env
1234 : LOGICAL, INTENT(IN) :: calculate_forces
1235 : TYPE(particle_list_p_type), DIMENSION(:), POINTER :: particles
1236 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
1237 : INTEGER, DIMENSION(:), POINTER :: glob_natoms
1238 : TYPE(virial_p_type), DIMENSION(:), POINTER :: virials
1239 : TYPE(cp_result_p_type), DIMENSION(:), POINTER :: results
1240 :
1241 : INTEGER :: iforce_eval, iparticle, jparticle, &
1242 : my_group, natom, nforce_eval
1243 94 : INTEGER, DIMENSION(:), POINTER :: map_index
1244 : REAL(KIND=dp) :: energy
1245 : TYPE(cell_type), POINTER :: cell_mix
1246 : TYPE(cp_logger_type), POINTER :: logger, my_logger
1247 : TYPE(cp_result_type), POINTER :: loc_results, results_mix
1248 94 : TYPE(cp_subsys_p_type), DIMENSION(:), POINTER :: subsystems
1249 : TYPE(cp_subsys_type), POINTER :: subsys_mix
1250 : TYPE(particle_list_type), POINTER :: particles_mix
1251 : TYPE(section_vals_type), POINTER :: force_env_section, mapping_section, &
1252 : mixed_section, root_section
1253 : TYPE(virial_type), POINTER :: loc_virial, virial_mix
1254 :
1255 188 : logger => cp_get_default_logger()
1256 94 : CPASSERT(ASSOCIATED(force_env))
1257 : ! Get infos about the mixed subsys
1258 : CALL force_env_get(force_env=force_env, &
1259 : subsys=subsys_mix, &
1260 : force_env_section=force_env_section, &
1261 : root_section=root_section, &
1262 94 : cell=cell_mix)
1263 : CALL cp_subsys_get(subsys=subsys_mix, &
1264 : particles=particles_mix, &
1265 : virial=virial_mix, &
1266 94 : results=results_mix)
1267 94 : NULLIFY (map_index)
1268 94 : nforce_eval = SIZE(force_env%sub_force_env)
1269 94 : mixed_section => section_vals_get_subs_vals(force_env_section, "MIXED")
1270 94 : mapping_section => section_vals_get_subs_vals(mixed_section, "MAPPING")
1271 494 : ALLOCATE (subsystems(nforce_eval))
1272 306 : DO iforce_eval = 1, nforce_eval
1273 212 : NULLIFY (subsystems(iforce_eval)%subsys, particles(iforce_eval)%list)
1274 212 : NULLIFY (results(iforce_eval)%results, virials(iforce_eval)%virial)
1275 48548 : ALLOCATE (virials(iforce_eval)%virial)
1276 212 : CALL cp_result_create(results(iforce_eval)%results)
1277 212 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1278 : ! Get all available subsys
1279 : CALL force_env_get(force_env=force_env%sub_force_env(iforce_eval)%force_env, &
1280 176 : subsys=subsystems(iforce_eval)%subsys)
1281 :
1282 : ! all force_env share the same cell
1283 176 : CALL cp_subsys_set(subsystems(iforce_eval)%subsys, cell=cell_mix)
1284 :
1285 : ! Get available particles
1286 : CALL cp_subsys_get(subsys=subsystems(iforce_eval)%subsys, &
1287 176 : particles=particles(iforce_eval)%list)
1288 :
1289 : ! Get Mapping index array
1290 176 : natom = SIZE(particles(iforce_eval)%list%els)
1291 : ! Serial mode need to deallocate first
1292 176 : IF (ASSOCIATED(map_index)) &
1293 82 : DEALLOCATE (map_index)
1294 : CALL get_subsys_map_index(mapping_section, natom, iforce_eval, nforce_eval, &
1295 176 : map_index)
1296 :
1297 : ! Mapping particles from iforce_eval environment to the mixed env
1298 638 : DO iparticle = 1, natom
1299 462 : jparticle = map_index(iparticle)
1300 3410 : particles(iforce_eval)%list%els(iparticle)%r = particles_mix%els(jparticle)%r
1301 : END DO
1302 : ! Mixed CDFT + QMMM: Need to translate now
1303 176 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) &
1304 118 : CALL apply_qmmm_translate(force_env%sub_force_env(iforce_eval)%force_env%qmmm_env)
1305 : END DO
1306 : ! For mixed CDFT calculations parallelized over CDFT states
1307 : ! build weight and gradient on all processors before splitting into groups and
1308 : ! starting energy calculation
1309 94 : CALL mixed_cdft_build_weight(force_env, calculate_forces)
1310 306 : DO iforce_eval = 1, nforce_eval
1311 212 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1312 : ! From this point on the error is the sub_error
1313 176 : IF (force_env%mixed_env%cdft_control%run_type == mixed_cdft_serial .AND. iforce_eval .GE. 2) THEN
1314 82 : my_logger => force_env%mixed_env%cdft_control%sub_logger(iforce_eval - 1)%p
1315 : ELSE
1316 94 : my_group = force_env%mixed_env%group_distribution(force_env%para_env%mepos)
1317 94 : my_logger => force_env%mixed_env%sub_logger(my_group + 1)%p
1318 : END IF
1319 : ! Copy iterations info (they are updated only in the main mixed_env)
1320 176 : CALL cp_iteration_info_copy_iter(logger%iter_info, my_logger%iter_info)
1321 176 : CALL cp_add_default_logger(my_logger)
1322 : ! Serial CDFT calculation: transfer weight/gradient
1323 176 : CALL mixed_cdft_build_weight(force_env, calculate_forces, iforce_eval)
1324 : ! Calculate energy and forces for each sub_force_env
1325 : CALL force_env_calc_energy_force(force_env%sub_force_env(iforce_eval)%force_env, &
1326 : calc_force=calculate_forces, &
1327 176 : skip_external_control=.TRUE.)
1328 : ! Only the rank 0 process collect info for each computation
1329 176 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1330 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, &
1331 106 : potential_energy=energy)
1332 : CALL cp_subsys_get(subsystems(iforce_eval)%subsys, &
1333 106 : virial=loc_virial, results=loc_results)
1334 106 : energies(iforce_eval) = energy
1335 106 : glob_natoms(iforce_eval) = natom
1336 106 : virials(iforce_eval)%virial = loc_virial
1337 106 : CALL cp_result_copy(loc_results, results(iforce_eval)%results)
1338 : END IF
1339 : ! Deallocate map_index array
1340 176 : IF (ASSOCIATED(map_index)) THEN
1341 94 : DEALLOCATE (map_index)
1342 : END IF
1343 306 : CALL cp_rm_default_logger()
1344 : END DO
1345 94 : DEALLOCATE (subsystems)
1346 :
1347 94 : END SUBROUTINE mixed_cdft_energy_forces
1348 :
1349 : ! **************************************************************************************************
1350 : !> \brief Perform additional tasks for mixed CDFT calculations after solving the electronic structure
1351 : !> of both CDFT states
1352 : !> \param force_env the force_env that holds the CDFT states
1353 : !> \par History
1354 : !> 01.17 created [Nico Holmberg]
1355 : !> \author Nico Holmberg
1356 : ! **************************************************************************************************
1357 524 : SUBROUTINE mixed_cdft_post_energy_forces(force_env)
1358 : TYPE(force_env_type), POINTER :: force_env
1359 :
1360 : INTEGER :: iforce_eval, nforce_eval, nvar
1361 : TYPE(dft_control_type), POINTER :: dft_control
1362 : TYPE(qs_environment_type), POINTER :: qs_env
1363 :
1364 524 : CPASSERT(ASSOCIATED(force_env))
1365 524 : NULLIFY (qs_env, dft_control)
1366 524 : IF (force_env%mixed_env%do_mixed_cdft) THEN
1367 94 : nforce_eval = SIZE(force_env%sub_force_env)
1368 94 : nvar = force_env%mixed_env%cdft_control%nconstraint
1369 : ! Transfer cdft strengths for writing restart
1370 94 : IF (.NOT. ASSOCIATED(force_env%mixed_env%strength)) &
1371 288 : ALLOCATE (force_env%mixed_env%strength(nforce_eval, nvar))
1372 406 : force_env%mixed_env%strength = 0.0_dp
1373 306 : DO iforce_eval = 1, nforce_eval
1374 212 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1375 176 : IF (force_env%mixed_env%do_mixed_qmmm_cdft) THEN
1376 24 : qs_env => force_env%sub_force_env(iforce_eval)%force_env%qmmm_env%qs_env
1377 : ELSE
1378 152 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, qs_env=qs_env)
1379 : END IF
1380 176 : CALL get_qs_env(qs_env, dft_control=dft_control)
1381 176 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) &
1382 452 : force_env%mixed_env%strength(iforce_eval, :) = dft_control%qs_control%cdft_control%strength(:)
1383 : END DO
1384 718 : CALL force_env%para_env%sum(force_env%mixed_env%strength)
1385 : ! Mixed CDFT: calculate ET coupling
1386 94 : IF (force_env%mixed_env%do_mixed_et) THEN
1387 94 : IF (MODULO(force_env%mixed_env%cdft_control%sim_step, force_env%mixed_env%et_freq) == 0) &
1388 94 : CALL mixed_cdft_calculate_coupling(force_env)
1389 : END IF
1390 : END IF
1391 :
1392 524 : END SUBROUTINE mixed_cdft_post_energy_forces
1393 :
1394 : ! **************************************************************************************************
1395 : !> \brief Computes the total energy for an embedded calculation
1396 : !> \param force_env ...
1397 : !> \author Vladimir Rybkin
1398 : ! **************************************************************************************************
1399 24 : SUBROUTINE embed_energy(force_env)
1400 :
1401 : TYPE(force_env_type), POINTER :: force_env
1402 :
1403 : INTEGER :: iforce_eval, iparticle, jparticle, &
1404 : my_group, natom, nforce_eval
1405 24 : INTEGER, DIMENSION(:), POINTER :: glob_natoms, map_index
1406 : LOGICAL :: converged_embed
1407 : REAL(KIND=dp) :: energy
1408 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
1409 : TYPE(cell_type), POINTER :: cell_embed
1410 : TYPE(cp_logger_type), POINTER :: logger, my_logger
1411 24 : TYPE(cp_result_p_type), DIMENSION(:), POINTER :: results
1412 : TYPE(cp_result_type), POINTER :: loc_results, results_embed
1413 24 : TYPE(cp_subsys_p_type), DIMENSION(:), POINTER :: subsystems
1414 : TYPE(cp_subsys_type), POINTER :: subsys_embed
1415 : TYPE(dft_control_type), POINTER :: dft_control
1416 24 : TYPE(particle_list_p_type), DIMENSION(:), POINTER :: particles
1417 : TYPE(particle_list_type), POINTER :: particles_embed
1418 : TYPE(pw_env_type), POINTER :: pw_env
1419 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1420 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot, spin_embed_pot
1421 : TYPE(section_vals_type), POINTER :: embed_section, force_env_section, &
1422 : mapping_section, root_section
1423 :
1424 48 : logger => cp_get_default_logger()
1425 24 : CPASSERT(ASSOCIATED(force_env))
1426 : ! Get infos about the embedding subsys
1427 : CALL force_env_get(force_env=force_env, &
1428 : subsys=subsys_embed, &
1429 : force_env_section=force_env_section, &
1430 : root_section=root_section, &
1431 24 : cell=cell_embed)
1432 : CALL cp_subsys_get(subsys=subsys_embed, &
1433 : particles=particles_embed, &
1434 24 : results=results_embed)
1435 24 : NULLIFY (map_index, glob_natoms)
1436 :
1437 24 : nforce_eval = SIZE(force_env%sub_force_env)
1438 24 : embed_section => section_vals_get_subs_vals(force_env_section, "EMBED")
1439 24 : mapping_section => section_vals_get_subs_vals(embed_section, "MAPPING")
1440 : ! Global Info
1441 168 : ALLOCATE (subsystems(nforce_eval))
1442 144 : ALLOCATE (particles(nforce_eval))
1443 : ! Local Info to sync
1444 48 : ALLOCATE (energies(nforce_eval))
1445 72 : ALLOCATE (glob_natoms(nforce_eval))
1446 144 : ALLOCATE (results(nforce_eval))
1447 120 : energies = 0.0_dp
1448 120 : glob_natoms = 0
1449 :
1450 120 : DO iforce_eval = 1, nforce_eval
1451 96 : NULLIFY (subsystems(iforce_eval)%subsys, particles(iforce_eval)%list)
1452 96 : NULLIFY (results(iforce_eval)%results)
1453 96 : CALL cp_result_create(results(iforce_eval)%results)
1454 96 : IF (.NOT. ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env)) CYCLE
1455 : ! From this point on the error is the sub_error
1456 96 : my_group = force_env%embed_env%group_distribution(force_env%para_env%mepos)
1457 96 : my_logger => force_env%embed_env%sub_logger(my_group + 1)%p
1458 : ! Copy iterations info (they are updated only in the main embed_env)
1459 96 : CALL cp_iteration_info_copy_iter(logger%iter_info, my_logger%iter_info)
1460 96 : CALL cp_add_default_logger(my_logger)
1461 :
1462 : ! Get all available subsys
1463 : CALL force_env_get(force_env=force_env%sub_force_env(iforce_eval)%force_env, &
1464 96 : subsys=subsystems(iforce_eval)%subsys)
1465 :
1466 : ! Check if we import density from previous force calculations
1467 : ! Only for QUICKSTEP
1468 96 : IF (ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env%qs_env)) THEN
1469 96 : NULLIFY (dft_control)
1470 96 : CALL get_qs_env(force_env%sub_force_env(iforce_eval)%force_env%qs_env, dft_control=dft_control)
1471 96 : IF (dft_control%qs_control%ref_embed_subsys) THEN
1472 24 : IF (iforce_eval .EQ. 2) CPABORT("Density importing force_eval can't be the first.")
1473 : END IF
1474 : END IF
1475 :
1476 : ! all force_env share the same cell
1477 96 : CALL cp_subsys_set(subsystems(iforce_eval)%subsys, cell=cell_embed)
1478 :
1479 : ! Get available particles
1480 : CALL cp_subsys_get(subsys=subsystems(iforce_eval)%subsys, &
1481 96 : particles=particles(iforce_eval)%list)
1482 :
1483 : ! Get Mapping index array
1484 96 : natom = SIZE(particles(iforce_eval)%list%els)
1485 :
1486 : CALL get_subsys_map_index(mapping_section, natom, iforce_eval, nforce_eval, &
1487 96 : map_index, .TRUE.)
1488 :
1489 : ! Mapping particles from iforce_eval environment to the embed env
1490 310 : DO iparticle = 1, natom
1491 214 : jparticle = map_index(iparticle)
1492 1594 : particles(iforce_eval)%list%els(iparticle)%r = particles_embed%els(jparticle)%r
1493 : END DO
1494 :
1495 : ! Calculate energy and forces for each sub_force_env
1496 : CALL force_env_calc_energy_force(force_env%sub_force_env(iforce_eval)%force_env, &
1497 : calc_force=.FALSE., &
1498 96 : skip_external_control=.TRUE.)
1499 :
1500 : ! Call DFT embedding
1501 96 : IF (ASSOCIATED(force_env%sub_force_env(iforce_eval)%force_env%qs_env)) THEN
1502 96 : NULLIFY (dft_control)
1503 96 : CALL get_qs_env(force_env%sub_force_env(iforce_eval)%force_env%qs_env, dft_control=dft_control)
1504 96 : IF (dft_control%qs_control%ref_embed_subsys) THEN
1505 : ! Now we can optimize the embedding potential
1506 24 : CALL dft_embedding(force_env, iforce_eval, energies, converged_embed)
1507 24 : IF (.NOT. converged_embed) CPABORT("Embedding potential optimization not converged.")
1508 : END IF
1509 : ! Deallocate embedding potential on the high-level subsystem
1510 96 : IF (dft_control%qs_control%high_level_embed_subsys) THEN
1511 : CALL get_qs_env(qs_env=force_env%sub_force_env(iforce_eval)%force_env%qs_env, &
1512 24 : embed_pot=embed_pot, spin_embed_pot=spin_embed_pot, pw_env=pw_env)
1513 24 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1514 24 : CALL auxbas_pw_pool%give_back_pw(embed_pot)
1515 24 : IF (ASSOCIATED(embed_pot)) THEN
1516 24 : CALL embed_pot%release()
1517 24 : DEALLOCATE (embed_pot)
1518 : END IF
1519 24 : IF (ASSOCIATED(spin_embed_pot)) THEN
1520 12 : CALL auxbas_pw_pool%give_back_pw(spin_embed_pot)
1521 12 : CALL spin_embed_pot%release()
1522 12 : DEALLOCATE (spin_embed_pot)
1523 : END IF
1524 : END IF
1525 : END IF
1526 :
1527 : ! Only the rank 0 process collect info for each computation
1528 96 : IF (force_env%sub_force_env(iforce_eval)%force_env%para_env%is_source()) THEN
1529 : CALL force_env_get(force_env%sub_force_env(iforce_eval)%force_env, &
1530 48 : potential_energy=energy)
1531 : CALL cp_subsys_get(subsystems(iforce_eval)%subsys, &
1532 48 : results=loc_results)
1533 48 : energies(iforce_eval) = energy
1534 48 : glob_natoms(iforce_eval) = natom
1535 48 : CALL cp_result_copy(loc_results, results(iforce_eval)%results)
1536 : END IF
1537 : ! Deallocate map_index array
1538 96 : IF (ASSOCIATED(map_index)) THEN
1539 96 : DEALLOCATE (map_index)
1540 : END IF
1541 120 : CALL cp_rm_default_logger()
1542 : END DO
1543 :
1544 : ! Handling Parallel execution
1545 24 : CALL force_env%para_env%sync()
1546 : ! Let's transfer energy, natom
1547 216 : CALL force_env%para_env%sum(energies)
1548 216 : CALL force_env%para_env%sum(glob_natoms)
1549 :
1550 216 : force_env%embed_env%energies = energies
1551 :
1552 : !NB if the first system has fewer atoms than the second)
1553 112 : DO iparticle = 1, SIZE(particles_embed%els)
1554 376 : particles_embed%els(iparticle)%f(:) = 0.0_dp
1555 : END DO
1556 :
1557 : ! ONIOM type of mixing in embedding: E = E_total + E_cluster_high - E_cluster
1558 24 : force_env%embed_env%pot_energy = energies(3) + energies(4) - energies(2)
1559 :
1560 : !Simply deallocate and loose the pointer references..
1561 120 : DO iforce_eval = 1, nforce_eval
1562 120 : CALL cp_result_release(results(iforce_eval)%results)
1563 : END DO
1564 24 : DEALLOCATE (subsystems)
1565 24 : DEALLOCATE (particles)
1566 24 : DEALLOCATE (energies)
1567 24 : DEALLOCATE (glob_natoms)
1568 24 : DEALLOCATE (results)
1569 :
1570 24 : END SUBROUTINE embed_energy
1571 :
1572 : ! **************************************************************************************************
1573 : !> \brief ...
1574 : !> \param force_env ...
1575 : !> \param ref_subsys_number ...
1576 : !> \param energies ...
1577 : !> \param converged_embed ...
1578 : ! **************************************************************************************************
1579 48 : SUBROUTINE dft_embedding(force_env, ref_subsys_number, energies, converged_embed)
1580 : TYPE(force_env_type), POINTER :: force_env
1581 : INTEGER :: ref_subsys_number
1582 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
1583 : LOGICAL :: converged_embed
1584 :
1585 : INTEGER :: embed_method
1586 : TYPE(section_vals_type), POINTER :: embed_section, force_env_section
1587 :
1588 : ! Find out which embedding scheme is used
1589 : CALL force_env_get(force_env=force_env, &
1590 24 : force_env_section=force_env_section)
1591 24 : embed_section => section_vals_get_subs_vals(force_env_section, "EMBED")
1592 :
1593 24 : CALL section_vals_val_get(embed_section, "EMBED_METHOD", i_val=embed_method)
1594 24 : SELECT CASE (embed_method)
1595 : CASE (dfet)
1596 : ! Density functional embedding
1597 24 : CALL dfet_embedding(force_env, ref_subsys_number, energies, converged_embed)
1598 : CASE (dmfet)
1599 : ! Density matrix embedding theory
1600 24 : CALL dmfet_embedding(force_env, ref_subsys_number, energies, converged_embed)
1601 : END SELECT
1602 :
1603 24 : END SUBROUTINE dft_embedding
1604 : ! **************************************************************************************************
1605 : !> \brief ... Main driver for DFT embedding
1606 : !> \param force_env ...
1607 : !> \param ref_subsys_number ...
1608 : !> \param energies ...
1609 : !> \param converged_embed ...
1610 : !> \author Vladimir Rybkin
1611 : ! **************************************************************************************************
1612 24 : SUBROUTINE dfet_embedding(force_env, ref_subsys_number, energies, converged_embed)
1613 : TYPE(force_env_type), POINTER :: force_env
1614 : INTEGER :: ref_subsys_number
1615 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
1616 : LOGICAL :: converged_embed
1617 :
1618 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dfet_embedding'
1619 :
1620 : INTEGER :: cluster_subsys_num, handle, &
1621 : i_force_eval, i_iter, i_spin, &
1622 : nforce_eval, nspins, nspins_subsys, &
1623 : output_unit
1624 : REAL(KIND=dp) :: cluster_energy
1625 24 : REAL(KIND=dp), DIMENSION(:), POINTER :: rhs
1626 : TYPE(cp_logger_type), POINTER :: logger
1627 : TYPE(dft_control_type), POINTER :: dft_control
1628 24 : TYPE(opt_embed_pot_type) :: opt_embed
1629 : TYPE(pw_env_type), POINTER :: pw_env
1630 : TYPE(pw_pool_type), POINTER :: auxbas_pw_pool
1631 : TYPE(pw_r3d_rs_type) :: diff_rho_r, diff_rho_spin
1632 24 : TYPE(pw_r3d_rs_type), DIMENSION(:), POINTER :: rho_r_ref, rho_r_subsys
1633 : TYPE(pw_r3d_rs_type), POINTER :: embed_pot, embed_pot_subsys, &
1634 : spin_embed_pot, spin_embed_pot_subsys
1635 : TYPE(qs_energy_type), POINTER :: energy
1636 : TYPE(qs_rho_type), POINTER :: rho, subsys_rho
1637 : TYPE(section_vals_type), POINTER :: dft_section, embed_section, &
1638 : force_env_section, input, &
1639 : mapping_section, opt_embed_section
1640 :
1641 24 : CALL timeset(routineN, handle)
1642 :
1643 24 : CALL cite_reference(Huang2011)
1644 24 : CALL cite_reference(Heaton_Burgess2007)
1645 :
1646 24 : CALL get_qs_env(qs_env=force_env%sub_force_env(ref_subsys_number)%force_env%qs_env)
1647 :
1648 : ! Reveal input file
1649 24 : NULLIFY (logger)
1650 24 : logger => cp_get_default_logger()
1651 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%PROGRAM_RUN_INFO", &
1652 24 : extension=".Log")
1653 :
1654 24 : NULLIFY (dft_section, input, opt_embed_section)
1655 24 : NULLIFY (energy, dft_control)
1656 :
1657 : CALL get_qs_env(qs_env=force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1658 : pw_env=pw_env, dft_control=dft_control, rho=rho, energy=energy, &
1659 24 : input=input)
1660 24 : nspins = dft_control%nspins
1661 :
1662 24 : dft_section => section_vals_get_subs_vals(input, "DFT")
1663 : opt_embed_section => section_vals_get_subs_vals(input, &
1664 24 : "DFT%QS%OPT_EMBED")
1665 : ! Rho_r is the reference
1666 24 : CALL qs_rho_get(rho_struct=rho, rho_r=rho_r_ref)
1667 :
1668 : ! We need to understand how to treat spins states
1669 : CALL understand_spin_states(force_env, ref_subsys_number, opt_embed%change_spin, opt_embed%open_shell_embed, &
1670 24 : opt_embed%all_nspins)
1671 :
1672 : ! Prepare everything for the potential maximization
1673 : CALL prepare_embed_opt(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, opt_embed, &
1674 24 : opt_embed_section)
1675 :
1676 : ! Initialize embedding potential
1677 : CALL init_embed_pot(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, embed_pot, &
1678 : opt_embed%add_const_pot, opt_embed%Fermi_Amaldi, opt_embed%const_pot, &
1679 : opt_embed%open_shell_embed, spin_embed_pot, &
1680 24 : opt_embed%pot_diff, opt_embed%Coulomb_guess, opt_embed%grid_opt)
1681 :
1682 : ! Read embedding potential vector from the file
1683 24 : IF (opt_embed%read_embed_pot .OR. opt_embed%read_embed_pot_cube) CALL read_embed_pot( &
1684 : force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, embed_pot, spin_embed_pot, &
1685 6 : opt_embed_section, opt_embed)
1686 :
1687 : ! Prepare the pw object to store density differences
1688 24 : CALL pw_env_get(pw_env, auxbas_pw_pool=auxbas_pw_pool)
1689 24 : CALL auxbas_pw_pool%create_pw(diff_rho_r)
1690 24 : CALL pw_zero(diff_rho_r)
1691 24 : IF (opt_embed%open_shell_embed) THEN
1692 12 : CALL auxbas_pw_pool%create_pw(diff_rho_spin)
1693 12 : CALL pw_zero(diff_rho_spin)
1694 : END IF
1695 :
1696 : ! Check the preliminary density differences
1697 58 : DO i_spin = 1, nspins
1698 58 : CALL pw_axpy(rho_r_ref(i_spin), diff_rho_r, -1.0_dp)
1699 : END DO
1700 24 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1701 12 : IF (nspins .EQ. 2) THEN ! Reference systems has an open shell, else the reference diff_rho_spin is zero
1702 10 : CALL pw_axpy(rho_r_ref(1), diff_rho_spin, -1.0_dp)
1703 10 : CALL pw_axpy(rho_r_ref(2), diff_rho_spin, 1.0_dp)
1704 : END IF
1705 : END IF
1706 :
1707 72 : DO i_force_eval = 1, ref_subsys_number - 1
1708 48 : NULLIFY (subsys_rho, rho_r_subsys, dft_control)
1709 : CALL get_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, rho=subsys_rho, energy=energy, &
1710 48 : dft_control=dft_control)
1711 48 : nspins_subsys = dft_control%nspins
1712 : ! Add subsystem densities
1713 48 : CALL qs_rho_get(rho_struct=subsys_rho, rho_r=rho_r_subsys)
1714 120 : DO i_spin = 1, nspins_subsys
1715 120 : CALL pw_axpy(rho_r_subsys(i_spin), diff_rho_r, allow_noncompatible_grids=.TRUE.)
1716 : END DO
1717 72 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1718 24 : IF (nspins_subsys .EQ. 2) THEN ! The subsystem makes contribution if it is spin-polarized
1719 : ! We may need to change spin ONLY FOR THE SECOND SUBSYSTEM: that's the internal convention
1720 24 : IF ((i_force_eval .EQ. 2) .AND. (opt_embed%change_spin)) THEN
1721 2 : CALL pw_axpy(rho_r_subsys(1), diff_rho_spin, -1.0_dp, allow_noncompatible_grids=.TRUE.)
1722 2 : CALL pw_axpy(rho_r_subsys(2), diff_rho_spin, 1.0_dp, allow_noncompatible_grids=.TRUE.)
1723 : ELSE
1724 : ! First subsystem (always) and second subsystem (without spin change)
1725 22 : CALL pw_axpy(rho_r_subsys(1), diff_rho_spin, 1.0_dp, allow_noncompatible_grids=.TRUE.)
1726 22 : CALL pw_axpy(rho_r_subsys(2), diff_rho_spin, -1.0_dp, allow_noncompatible_grids=.TRUE.)
1727 : END IF
1728 : END IF
1729 : END IF
1730 : END DO
1731 :
1732 : ! Print density difference
1733 24 : CALL print_rho_diff(diff_rho_r, 0, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .FALSE.)
1734 24 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1735 12 : CALL print_rho_spin_diff(diff_rho_spin, 0, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .FALSE.)
1736 : END IF
1737 :
1738 : ! Construct electrostatic guess if needed
1739 24 : IF (opt_embed%Coulomb_guess) THEN
1740 : ! Reveal resp charges for total system
1741 2 : nforce_eval = SIZE(force_env%sub_force_env)
1742 2 : NULLIFY (rhs)
1743 2 : CALL get_qs_env(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, rhs=rhs)
1744 : ! Get the mapping
1745 : CALL force_env_get(force_env=force_env, &
1746 2 : force_env_section=force_env_section)
1747 2 : embed_section => section_vals_get_subs_vals(force_env_section, "EMBED")
1748 2 : mapping_section => section_vals_get_subs_vals(embed_section, "MAPPING")
1749 :
1750 6 : DO i_force_eval = 1, ref_subsys_number - 1
1751 6 : IF (i_force_eval .EQ. 1) THEN
1752 : CALL Coulomb_guess(embed_pot, rhs, mapping_section, &
1753 2 : force_env%sub_force_env(i_force_eval)%force_env%qs_env, nforce_eval, i_force_eval, opt_embed%eta)
1754 : ELSE
1755 : CALL Coulomb_guess(opt_embed%pot_diff, rhs, mapping_section, &
1756 2 : force_env%sub_force_env(i_force_eval)%force_env%qs_env, nforce_eval, i_force_eval, opt_embed%eta)
1757 : END IF
1758 : END DO
1759 2 : CALL pw_axpy(opt_embed%pot_diff, embed_pot)
1760 2 : IF (.NOT. opt_embed%grid_opt) CALL pw_copy(embed_pot, opt_embed%const_pot)
1761 :
1762 : END IF
1763 :
1764 : ! Difference guess
1765 24 : IF (opt_embed%diff_guess) THEN
1766 2 : CALL pw_copy(diff_rho_r, embed_pot)
1767 2 : IF (.NOT. opt_embed%grid_opt) CALL pw_copy(embed_pot, opt_embed%const_pot)
1768 : ! Open shell
1769 2 : IF (opt_embed%open_shell_embed) CALL pw_copy(diff_rho_spin, spin_embed_pot)
1770 : END IF
1771 :
1772 : ! Calculate subsystems with trial embedding potential
1773 48 : DO i_iter = 1, opt_embed%n_iter
1774 48 : opt_embed%i_iter = i_iter
1775 :
1776 : ! Set the density difference as the negative reference one
1777 48 : CALL pw_zero(diff_rho_r)
1778 48 : CALL get_qs_env(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, dft_control=dft_control)
1779 48 : nspins = dft_control%nspins
1780 116 : DO i_spin = 1, nspins
1781 116 : CALL pw_axpy(rho_r_ref(i_spin), diff_rho_r, -1.0_dp)
1782 : END DO
1783 48 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1784 26 : CALL pw_zero(diff_rho_spin)
1785 26 : IF (nspins .EQ. 2) THEN ! Reference systems has an open shell, else the reference diff_rho_spin is zero
1786 20 : CALL pw_axpy(rho_r_ref(1), diff_rho_spin, -1.0_dp)
1787 20 : CALL pw_axpy(rho_r_ref(2), diff_rho_spin, 1.0_dp)
1788 : END IF
1789 : END IF
1790 :
1791 144 : DO i_force_eval = 1, ref_subsys_number - 1
1792 96 : NULLIFY (dft_control)
1793 96 : CALL get_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, dft_control=dft_control)
1794 96 : nspins_subsys = dft_control%nspins
1795 :
1796 96 : IF ((i_force_eval .EQ. 2) .AND. (opt_embed%change_spin)) THEN
1797 : ! Here we change the sign of the spin embedding potential due to spin change:
1798 : ! only in spin_embed_subsys
1799 : CALL make_subsys_embed_pot(force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
1800 : embed_pot, embed_pot_subsys, spin_embed_pot, spin_embed_pot_subsys, &
1801 6 : opt_embed%open_shell_embed, .TRUE.)
1802 : ELSE ! Regular case
1803 : CALL make_subsys_embed_pot(force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
1804 : embed_pot, embed_pot_subsys, spin_embed_pot, spin_embed_pot_subsys, &
1805 90 : opt_embed%open_shell_embed, .FALSE.)
1806 : END IF
1807 :
1808 : ! Switch on external potential in the subsystems
1809 96 : dft_control%apply_embed_pot = .TRUE.
1810 :
1811 : ! Add the embedding potential
1812 96 : CALL set_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, embed_pot=embed_pot_subsys)
1813 96 : IF ((opt_embed%open_shell_embed) .AND. (nspins_subsys .EQ. 2)) THEN ! Spin part
1814 : CALL set_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
1815 52 : spin_embed_pot=spin_embed_pot_subsys)
1816 : END IF
1817 :
1818 : ! Get the previous subsystem densities
1819 96 : CALL get_prev_density(opt_embed, force_env%sub_force_env(i_force_eval)%force_env, i_force_eval)
1820 :
1821 : ! Calculate the new density
1822 : CALL force_env_calc_energy_force(force_env=force_env%sub_force_env(i_force_eval)%force_env, &
1823 : calc_force=.FALSE., &
1824 96 : skip_external_control=.TRUE.)
1825 :
1826 96 : CALL get_max_subsys_diff(opt_embed, force_env%sub_force_env(i_force_eval)%force_env, i_force_eval)
1827 :
1828 : ! Extract subsystem density and energy
1829 96 : NULLIFY (rho_r_subsys, energy)
1830 :
1831 : CALL get_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, rho=subsys_rho, &
1832 96 : energy=energy)
1833 96 : opt_embed%w_func(i_iter) = opt_embed%w_func(i_iter) + energy%total
1834 :
1835 : ! Find out which subsystem is the cluster
1836 96 : IF (dft_control%qs_control%cluster_embed_subsys) THEN
1837 48 : cluster_subsys_num = i_force_eval
1838 48 : cluster_energy = energy%total
1839 : END IF
1840 :
1841 : ! Add subsystem densities
1842 96 : CALL qs_rho_get(rho_struct=subsys_rho, rho_r=rho_r_subsys)
1843 244 : DO i_spin = 1, nspins_subsys
1844 244 : CALL pw_axpy(rho_r_subsys(i_spin), diff_rho_r, allow_noncompatible_grids=.TRUE.)
1845 : END DO
1846 96 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1847 52 : IF (nspins_subsys .EQ. 2) THEN ! The subsystem makes contribution if it is spin-polarized
1848 : ! We may need to change spin ONLY FOR THE SECOND SUBSYSTEM: that's the internal convention
1849 52 : IF ((i_force_eval .EQ. 2) .AND. (opt_embed%change_spin)) THEN
1850 6 : CALL pw_axpy(rho_r_subsys(1), diff_rho_spin, -1.0_dp, allow_noncompatible_grids=.TRUE.)
1851 6 : CALL pw_axpy(rho_r_subsys(2), diff_rho_spin, 1.0_dp, allow_noncompatible_grids=.TRUE.)
1852 : ELSE
1853 : ! First subsystem (always) and second subsystem (without spin change)
1854 46 : CALL pw_axpy(rho_r_subsys(1), diff_rho_spin, 1.0_dp, allow_noncompatible_grids=.TRUE.)
1855 46 : CALL pw_axpy(rho_r_subsys(2), diff_rho_spin, -1.0_dp, allow_noncompatible_grids=.TRUE.)
1856 : END IF
1857 : END IF
1858 : END IF
1859 :
1860 : ! Release embedding potential for subsystem
1861 96 : CALL embed_pot_subsys%release()
1862 96 : DEALLOCATE (embed_pot_subsys)
1863 144 : IF (opt_embed%open_shell_embed) THEN
1864 52 : CALL spin_embed_pot_subsys%release()
1865 52 : DEALLOCATE (spin_embed_pot_subsys)
1866 : END IF
1867 :
1868 : END DO ! i_force_eval
1869 :
1870 : ! Print embedding potential for restart
1871 : CALL print_embed_restart(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1872 : opt_embed%dimen_aux, opt_embed%embed_pot_coef, embed_pot, i_iter, &
1873 48 : spin_embed_pot, opt_embed%open_shell_embed, opt_embed%grid_opt, .FALSE.)
1874 : CALL print_pot_simple_grid(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1875 : embed_pot, spin_embed_pot, i_iter, opt_embed%open_shell_embed, .FALSE., &
1876 48 : force_env%sub_force_env(cluster_subsys_num)%force_env%qs_env)
1877 :
1878 : ! Integrate the potential over density differences and add to w functional; also add regularization contribution
1879 116 : DO i_spin = 1, nspins ! Sum over nspins for the reference system, not subsystem!
1880 116 : opt_embed%w_func(i_iter) = opt_embed%w_func(i_iter) - pw_integral_ab(embed_pot, rho_r_ref(i_spin))
1881 : END DO
1882 : ! Spin part
1883 48 : IF (opt_embed%open_shell_embed) THEN
1884 : ! If reference system is not spin-polarized then it does not make a contribution to W functional
1885 26 : IF (nspins .EQ. 2) THEN
1886 : opt_embed%w_func(i_iter) = opt_embed%w_func(i_iter) &
1887 : - pw_integral_ab(spin_embed_pot, rho_r_ref(1)) &
1888 20 : + pw_integral_ab(spin_embed_pot, rho_r_ref(2))
1889 : END IF
1890 : END IF
1891 : ! Finally, add the regularization term
1892 48 : opt_embed%w_func(i_iter) = opt_embed%w_func(i_iter) + opt_embed%reg_term
1893 :
1894 : ! Print information and check convergence
1895 48 : CALL print_emb_opt_info(output_unit, i_iter, opt_embed)
1896 48 : CALL conv_check_embed(opt_embed, diff_rho_r, diff_rho_spin, output_unit)
1897 48 : IF (opt_embed%converged) EXIT
1898 :
1899 : ! Update the trust radius and control the step
1900 24 : IF ((i_iter .GT. 1) .AND. (.NOT. opt_embed%steep_desc)) CALL step_control(opt_embed)
1901 :
1902 : ! Print density difference
1903 24 : CALL print_rho_diff(diff_rho_r, i_iter, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .FALSE.)
1904 24 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1905 14 : CALL print_rho_spin_diff(diff_rho_spin, i_iter, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .FALSE.)
1906 : END IF
1907 :
1908 : ! Calculate potential gradient if the step has been accepted. Otherwise, we reuse the previous one
1909 :
1910 24 : IF (opt_embed%accept_step .AND. (.NOT. opt_embed%grid_opt)) &
1911 : CALL calculate_embed_pot_grad(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1912 16 : diff_rho_r, diff_rho_spin, opt_embed)
1913 : ! Take the embedding step
1914 : CALL opt_embed_step(diff_rho_r, diff_rho_spin, opt_embed, embed_pot, spin_embed_pot, rho_r_ref, &
1915 48 : force_env%sub_force_env(ref_subsys_number)%force_env%qs_env)
1916 :
1917 : END DO ! i_iter
1918 :
1919 : ! Print final embedding potential for restart
1920 : CALL print_embed_restart(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1921 : opt_embed%dimen_aux, opt_embed%embed_pot_coef, embed_pot, i_iter, &
1922 24 : spin_embed_pot, opt_embed%open_shell_embed, opt_embed%grid_opt, .TRUE.)
1923 : CALL print_pot_simple_grid(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
1924 : embed_pot, spin_embed_pot, i_iter, opt_embed%open_shell_embed, .TRUE., &
1925 24 : force_env%sub_force_env(cluster_subsys_num)%force_env%qs_env)
1926 :
1927 : ! Print final density difference
1928 : !CALL print_rho_diff(diff_rho_r, i_iter, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .TRUE.)
1929 24 : IF (opt_embed%open_shell_embed) THEN ! Spin part
1930 12 : CALL print_rho_spin_diff(diff_rho_spin, i_iter, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, .TRUE.)
1931 : END IF
1932 :
1933 : ! Give away plane waves pools
1934 24 : CALL diff_rho_r%release()
1935 24 : IF (opt_embed%open_shell_embed) THEN
1936 12 : CALL diff_rho_spin%release()
1937 : END IF
1938 :
1939 : CALL cp_print_key_finished_output(output_unit, logger, force_env%force_env_section, &
1940 24 : "PRINT%PROGRAM_RUN_INFO")
1941 :
1942 : ! If converged send the embedding potential to the higher-level calculation.
1943 24 : IF (opt_embed%converged) THEN
1944 : CALL get_qs_env(force_env%sub_force_env(ref_subsys_number + 1)%force_env%qs_env, dft_control=dft_control, &
1945 24 : pw_env=pw_env)
1946 24 : nspins_subsys = dft_control%nspins
1947 24 : dft_control%apply_embed_pot = .TRUE.
1948 : ! The embedded subsystem corresponds to subsystem #2, where spin change is possible
1949 : CALL make_subsys_embed_pot(force_env%sub_force_env(ref_subsys_number + 1)%force_env%qs_env, &
1950 : embed_pot, embed_pot_subsys, spin_embed_pot, spin_embed_pot_subsys, &
1951 24 : opt_embed%open_shell_embed, opt_embed%change_spin)
1952 :
1953 24 : IF (opt_embed%Coulomb_guess) THEN
1954 2 : CALL pw_axpy(opt_embed%pot_diff, embed_pot_subsys, -1.0_dp, allow_noncompatible_grids=.TRUE.)
1955 : END IF
1956 :
1957 24 : CALL set_qs_env(force_env%sub_force_env(ref_subsys_number + 1)%force_env%qs_env, embed_pot=embed_pot_subsys)
1958 :
1959 24 : IF ((opt_embed%open_shell_embed) .AND. (nspins_subsys .EQ. 2)) THEN
1960 : CALL set_qs_env(force_env%sub_force_env(ref_subsys_number + 1)%force_env%qs_env, &
1961 12 : spin_embed_pot=spin_embed_pot_subsys)
1962 : END IF
1963 :
1964 : ! Substitute the correct energy in energies: only on rank 0
1965 24 : IF (force_env%sub_force_env(cluster_subsys_num)%force_env%para_env%is_source()) THEN
1966 12 : energies(cluster_subsys_num) = cluster_energy
1967 : END IF
1968 : END IF
1969 :
1970 : ! Deallocate and release opt_embed content
1971 24 : CALL release_opt_embed(opt_embed)
1972 :
1973 : ! Deallocate embedding potential
1974 24 : CALL embed_pot%release()
1975 24 : DEALLOCATE (embed_pot)
1976 24 : IF (opt_embed%open_shell_embed) THEN
1977 12 : CALL spin_embed_pot%release()
1978 12 : DEALLOCATE (spin_embed_pot)
1979 : END IF
1980 :
1981 24 : converged_embed = opt_embed%converged
1982 :
1983 24 : CALL timestop(handle)
1984 :
1985 48 : END SUBROUTINE dfet_embedding
1986 :
1987 : ! **************************************************************************************************
1988 : !> \brief Main driver for the DMFET embedding
1989 : !> \param force_env ...
1990 : !> \param ref_subsys_number ...
1991 : !> \param energies ...
1992 : !> \param converged_embed ...
1993 : !> \author Vladimir Rybkin
1994 : ! **************************************************************************************************
1995 0 : SUBROUTINE dmfet_embedding(force_env, ref_subsys_number, energies, converged_embed)
1996 : TYPE(force_env_type), POINTER :: force_env
1997 : INTEGER :: ref_subsys_number
1998 : REAL(KIND=dp), DIMENSION(:), POINTER :: energies
1999 : LOGICAL :: converged_embed
2000 :
2001 : CHARACTER(LEN=*), PARAMETER :: routineN = 'dmfet_embedding'
2002 :
2003 : INTEGER :: cluster_subsys_num, handle, &
2004 : i_force_eval, i_iter, output_unit
2005 : LOGICAL :: subsys_open_shell
2006 : REAL(KIND=dp) :: cluster_energy
2007 : TYPE(cp_logger_type), POINTER :: logger
2008 : TYPE(dft_control_type), POINTER :: dft_control
2009 : TYPE(mp_para_env_type), POINTER :: para_env
2010 0 : TYPE(opt_dmfet_pot_type) :: opt_dmfet
2011 : TYPE(qs_energy_type), POINTER :: energy
2012 : TYPE(section_vals_type), POINTER :: dft_section, input, opt_dmfet_section
2013 :
2014 0 : CALL timeset(routineN, handle)
2015 :
2016 : CALL get_qs_env(qs_env=force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
2017 0 : para_env=para_env)
2018 :
2019 : ! Reveal input file
2020 0 : NULLIFY (logger)
2021 0 : logger => cp_get_default_logger()
2022 : output_unit = cp_print_key_unit_nr(logger, force_env%force_env_section, "PRINT%PROGRAM_RUN_INFO", &
2023 0 : extension=".Log")
2024 :
2025 0 : NULLIFY (dft_section, input, opt_dmfet_section)
2026 0 : NULLIFY (energy)
2027 :
2028 : CALL get_qs_env(qs_env=force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
2029 0 : energy=energy, input=input)
2030 :
2031 0 : dft_section => section_vals_get_subs_vals(input, "DFT")
2032 : opt_dmfet_section => section_vals_get_subs_vals(input, &
2033 0 : "DFT%QS%OPT_DMFET")
2034 :
2035 : ! We need to understand how to treat spins states
2036 : CALL understand_spin_states(force_env, ref_subsys_number, opt_dmfet%change_spin, opt_dmfet%open_shell_embed, &
2037 0 : opt_dmfet%all_nspins)
2038 :
2039 : ! Prepare for the potential optimization
2040 : CALL prepare_dmfet_opt(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
2041 0 : opt_dmfet, opt_dmfet_section)
2042 :
2043 : ! Get the reference density matrix/matrices
2044 0 : subsys_open_shell = subsys_spin(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env)
2045 : CALL build_full_dm(force_env%sub_force_env(ref_subsys_number)%force_env%qs_env, &
2046 0 : opt_dmfet%dm_total, subsys_open_shell, opt_dmfet%open_shell_embed, opt_dmfet%dm_total_beta)
2047 :
2048 : ! Check the preliminary DM difference
2049 0 : CALL cp_fm_copy_general(opt_dmfet%dm_total, opt_dmfet%dm_diff, para_env)
2050 0 : IF (opt_dmfet%open_shell_embed) CALL cp_fm_copy_general(opt_dmfet%dm_total_beta, &
2051 0 : opt_dmfet%dm_diff_beta, para_env)
2052 :
2053 0 : DO i_force_eval = 1, ref_subsys_number - 1
2054 :
2055 : ! Get the subsystem density matrix/matrices
2056 0 : subsys_open_shell = subsys_spin(force_env%sub_force_env(i_force_eval)%force_env%qs_env)
2057 :
2058 : CALL build_full_dm(force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
2059 : opt_dmfet%dm_subsys, subsys_open_shell, opt_dmfet%open_shell_embed, &
2060 0 : opt_dmfet%dm_subsys_beta)
2061 :
2062 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff, 1.0_dp, opt_dmfet%dm_subsys)
2063 :
2064 0 : IF (opt_dmfet%open_shell_embed) CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff_beta, &
2065 0 : 1.0_dp, opt_dmfet%dm_subsys_beta)
2066 :
2067 : END DO
2068 :
2069 : ! Main loop of iterative matrix potential optimization
2070 0 : DO i_iter = 1, opt_dmfet%n_iter
2071 :
2072 0 : opt_dmfet%i_iter = i_iter
2073 :
2074 : ! Set the dm difference as the reference one
2075 0 : CALL cp_fm_copy_general(opt_dmfet%dm_total, opt_dmfet%dm_diff, para_env)
2076 :
2077 0 : IF (opt_dmfet%open_shell_embed) CALL cp_fm_copy_general(opt_dmfet%dm_total_beta, &
2078 0 : opt_dmfet%dm_diff_beta, para_env)
2079 :
2080 : ! Loop over force evaluations
2081 0 : DO i_force_eval = 1, ref_subsys_number - 1
2082 :
2083 : ! Switch on external potential in the subsystems
2084 0 : NULLIFY (dft_control)
2085 0 : CALL get_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, dft_control=dft_control)
2086 0 : dft_control%apply_dmfet_pot = .TRUE.
2087 :
2088 : ! Calculate the new density
2089 : CALL force_env_calc_energy_force(force_env=force_env%sub_force_env(i_force_eval)%force_env, &
2090 : calc_force=.FALSE., &
2091 0 : skip_external_control=.TRUE.)
2092 :
2093 : ! Extract subsystem density matrix and energy
2094 0 : NULLIFY (energy)
2095 :
2096 0 : CALL get_qs_env(force_env%sub_force_env(i_force_eval)%force_env%qs_env, energy=energy)
2097 0 : opt_dmfet%w_func(i_iter) = opt_dmfet%w_func(i_iter) + energy%total
2098 :
2099 : ! Find out which subsystem is the cluster
2100 0 : IF (dft_control%qs_control%cluster_embed_subsys) THEN
2101 0 : cluster_subsys_num = i_force_eval
2102 0 : cluster_energy = energy%total
2103 : END IF
2104 :
2105 : ! Add subsystem density matrices
2106 0 : subsys_open_shell = subsys_spin(force_env%sub_force_env(i_force_eval)%force_env%qs_env)
2107 :
2108 : CALL build_full_dm(force_env%sub_force_env(i_force_eval)%force_env%qs_env, &
2109 : opt_dmfet%dm_subsys, subsys_open_shell, opt_dmfet%open_shell_embed, &
2110 0 : opt_dmfet%dm_subsys_beta)
2111 :
2112 0 : IF (opt_dmfet%open_shell_embed) THEN ! Open-shell embedding
2113 : ! We may need to change spin ONLY FOR THE SECOND SUBSYSTEM: that's the internal convention
2114 0 : IF ((i_force_eval .EQ. 2) .AND. (opt_dmfet%change_spin)) THEN
2115 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff_beta, 1.0_dp, opt_dmfet%dm_subsys)
2116 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff, 1.0_dp, opt_dmfet%dm_subsys_beta)
2117 : ELSE
2118 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff, 1.0_dp, opt_dmfet%dm_subsys)
2119 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff_beta, 1.0_dp, opt_dmfet%dm_subsys_beta)
2120 : END IF
2121 : ELSE ! Closed-shell embedding
2122 0 : CALL cp_fm_scale_and_add(-1.0_dp, opt_dmfet%dm_diff, 1.0_dp, opt_dmfet%dm_subsys)
2123 : END IF
2124 :
2125 : END DO ! i_force_eval
2126 :
2127 0 : CALL check_dmfet(opt_dmfet, force_env%sub_force_env(ref_subsys_number)%force_env%qs_env)
2128 :
2129 : END DO ! i_iter
2130 :
2131 : ! Substitute the correct energy in energies: only on rank 0
2132 0 : IF (force_env%sub_force_env(cluster_subsys_num)%force_env%para_env%is_source()) THEN
2133 0 : energies(cluster_subsys_num) = cluster_energy
2134 : END IF
2135 :
2136 0 : CALL release_dmfet_opt(opt_dmfet)
2137 :
2138 0 : converged_embed = .FALSE.
2139 :
2140 0 : END SUBROUTINE dmfet_embedding
2141 :
2142 : END MODULE force_env_methods
|