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 Methods dealing with Neural Network potentials
10 : !> \author Christoph Schran (christoph.schran@rub.de)
11 : !> \date 2020-10-10
12 : ! **************************************************************************************************
13 : MODULE nnp_force
14 :
15 : USE atomic_kind_types, ONLY: atomic_kind_type
16 : USE cp_log_handling, ONLY: cp_get_default_logger,&
17 : cp_logger_type
18 : USE cp_output_handling, ONLY: cp_p_file,&
19 : cp_print_key_finished_output,&
20 : cp_print_key_should_output,&
21 : cp_print_key_unit_nr
22 : USE cp_subsys_types, ONLY: cp_subsys_get,&
23 : cp_subsys_type
24 : USE cp_units, ONLY: cp_unit_from_cp2k
25 : USE distribution_1d_types, ONLY: distribution_1d_type
26 : USE input_section_types, ONLY: section_vals_get_subs_vals,&
27 : section_vals_type,&
28 : section_vals_val_get
29 : USE kinds, ONLY: default_path_length,&
30 : default_string_length,&
31 : dp
32 : USE nnp_acsf, ONLY: nnp_calc_acsf
33 : USE nnp_environment_types, ONLY: nnp_env_get,&
34 : nnp_type
35 : USE nnp_model, ONLY: nnp_gradients,&
36 : nnp_predict
37 : USE particle_types, ONLY: particle_type
38 : USE periodic_table, ONLY: get_ptable_info
39 : USE physcon, ONLY: angstrom
40 : USE virial_types, ONLY: virial_type
41 : #include "./base/base_uses.f90"
42 :
43 : IMPLICIT NONE
44 :
45 : PRIVATE
46 :
47 : LOGICAL, PARAMETER, PRIVATE :: debug_this_module = .TRUE.
48 : CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'nnp_force'
49 :
50 : PUBLIC :: nnp_calc_energy_force
51 :
52 : CONTAINS
53 :
54 : ! **************************************************************************************************
55 : !> \brief Calculate the energy and force for a given configuration with the NNP
56 : !> \param nnp ...
57 : !> \param calc_forces ...
58 : !> \date 2020-10-10
59 : !> \author Christoph Schran (christoph.schran@rub.de)
60 : ! **************************************************************************************************
61 308 : SUBROUTINE nnp_calc_energy_force(nnp, calc_forces)
62 : TYPE(nnp_type), INTENT(INOUT), POINTER :: nnp
63 : LOGICAL, INTENT(IN) :: calc_forces
64 :
65 : CHARACTER(len=*), PARAMETER :: routineN = 'nnp_calc_energy_force'
66 :
67 : INTEGER :: handle, i, i_com, ig, ind, istart, j, k, &
68 : m, mecalc
69 308 : INTEGER, ALLOCATABLE, DIMENSION(:) :: allcalc
70 : LOGICAL :: calc_stress
71 308 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: denergydsym
72 308 : REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: dsymdxyz, stress
73 308 : TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set
74 : TYPE(cp_logger_type), POINTER :: logger
75 : TYPE(cp_subsys_type), POINTER :: subsys
76 : TYPE(distribution_1d_type), POINTER :: local_particles
77 308 : TYPE(particle_type), DIMENSION(:), POINTER :: particle_set
78 : TYPE(section_vals_type), POINTER :: print_section
79 : TYPE(virial_type), POINTER :: virial
80 :
81 308 : CALL timeset(routineN, handle)
82 :
83 308 : NULLIFY (particle_set, logger, local_particles, subsys, &
84 308 : atomic_kind_set)
85 308 : logger => cp_get_default_logger()
86 :
87 308 : CPASSERT(ASSOCIATED(nnp))
88 : CALL nnp_env_get(nnp_env=nnp, particle_set=particle_set, &
89 : subsys=subsys, local_particles=local_particles, &
90 308 : atomic_kind_set=atomic_kind_set)
91 :
92 : CALL cp_subsys_get(subsys, &
93 308 : virial=virial)
94 :
95 308 : calc_stress = virial%pv_availability .AND. (.NOT. virial%pv_numer)
96 22 : IF (calc_stress .AND. .NOT. calc_forces) CPABORT('Stress cannot be calculated without forces')
97 :
98 : ! Initialize energy and gradient:
99 412874 : nnp%atomic_energy(:, :) = 0.0_dp
100 696234 : IF (calc_forces) nnp%myforce(:, :, :) = 0.0_dp
101 696234 : IF (calc_forces) nnp%committee_forces(:, :, :) = 0.0_dp
102 2596 : IF (calc_stress) nnp%committee_stress(:, :, :) = 0.0_dp
103 :
104 : !fill coord array
105 308 : ig = 1
106 924 : DO i = 1, nnp%n_ele
107 110880 : DO j = 1, nnp%num_atoms
108 110572 : IF (nnp%ele(i) == particle_set(j)%atomic_kind%element_symbol) THEN
109 219912 : DO m = 1, 3
110 219912 : nnp%coord(m, ig) = particle_set(j)%r(m)
111 : END DO
112 54978 : nnp%atoms(ig) = nnp%ele(i)
113 54978 : CALL get_ptable_info(nnp%atoms(ig), number=nnp%nuc_atoms(ig))
114 54978 : nnp%ele_ind(ig) = i
115 54978 : nnp%sort(ig) = j
116 54978 : nnp%sort_inv(j) = ig
117 54978 : ig = ig + 1
118 : END IF
119 : END DO
120 : END DO
121 :
122 : ! parallization:
123 : mecalc = nnp%num_atoms/logger%para_env%num_pe + &
124 : MIN(MOD(nnp%num_atoms, logger%para_env%num_pe)/ &
125 308 : (logger%para_env%mepos + 1), 1)
126 924 : ALLOCATE (allcalc(logger%para_env%num_pe))
127 924 : allcalc(:) = 0
128 308 : CALL logger%para_env%allgather(mecalc, allcalc)
129 308 : istart = 1
130 462 : DO i = 2, logger%para_env%mepos + 1
131 462 : istart = istart + allcalc(i - 1)
132 : END DO
133 :
134 : ! reset extrapolation status
135 308 : nnp%output_expol = .FALSE.
136 :
137 : ! calc atomic contribution to energy and force
138 27797 : DO i = istart, istart + mecalc - 1
139 :
140 : ! determine index of atom type and offset
141 27489 : ind = nnp%ele_ind(i)
142 :
143 : ! reset input nodes of ele(ind):
144 797181 : nnp%arc(ind)%layer(1)%node(:) = 0.0_dp
145 :
146 : ! compute sym fnct values
147 27489 : IF (calc_forces) THEN
148 : !reset input grads of ele(ind):
149 368445 : nnp%arc(ind)%layer(1)%node_grad(:) = 0.0_dp
150 50820 : ALLOCATE (dsymdxyz(3, nnp%arc(ind)%n_nodes(1), nnp%num_atoms))
151 274955604 : dsymdxyz(:, :, :) = 0.0_dp
152 12705 : IF (calc_stress) THEN
153 6336 : ALLOCATE (stress(3, 3, nnp%arc(ind)%n_nodes(1)))
154 770880 : stress(:, :, :) = 0.0_dp
155 2112 : CALL nnp_calc_acsf(nnp, i, dsymdxyz, stress)
156 : ELSE
157 10593 : CALL nnp_calc_acsf(nnp, i, dsymdxyz)
158 : END IF
159 : ELSE
160 14784 : CALL nnp_calc_acsf(nnp, i)
161 : END IF
162 :
163 232617 : DO i_com = 1, nnp%n_committee
164 : ! predict energy
165 205128 : CALL nnp_predict(nnp%arc(ind), nnp, i_com)
166 : nnp%atomic_energy(i, i_com) = nnp%arc(ind)%layer(nnp%n_layer)%node(1) + &
167 205128 : nnp%atom_energies(ind)
168 :
169 : ! predict forces
170 232617 : IF (calc_forces) THEN
171 260568 : ALLOCATE (denergydsym(nnp%arc(ind)%n_nodes(1)))
172 2518824 : denergydsym(:) = 0.0_dp
173 86856 : CALL nnp_gradients(nnp%arc(ind), nnp, i_com, denergydsym)
174 2518824 : DO j = 1, nnp%arc(ind)%n_nodes(1)
175 467972736 : DO k = 1, nnp%num_atoms
176 1864595040 : DO m = 1, 3
177 1862163072 : nnp%myforce(m, k, i_com) = nnp%myforce(m, k, i_com) - denergydsym(j)*dsymdxyz(m, j, k)
178 : END DO
179 : END DO
180 2518824 : IF (calc_stress) THEN
181 : nnp%committee_stress(:, :, i_com) = nnp%committee_stress(:, :, i_com) - &
182 6150144 : denergydsym(j)*stress(:, :, j)
183 : END IF
184 : END DO
185 86856 : DEALLOCATE (denergydsym)
186 : END IF
187 : END DO
188 :
189 : !deallocate memory
190 27797 : IF (calc_forces) THEN
191 12705 : DEALLOCATE (dsymdxyz)
192 12705 : IF (calc_stress) THEN
193 2112 : DEALLOCATE (stress)
194 : END IF
195 : END IF
196 :
197 : END DO ! loop over num_atoms
198 :
199 : ! calculate energy:
200 308 : CALL logger%para_env%sum(nnp%atomic_energy(:, :))
201 412874 : nnp%committee_energy(:) = SUM(nnp%atomic_energy, 1)
202 2618 : nnp%nnp_potential_energy = SUM(nnp%committee_energy)/REAL(nnp%n_committee, dp)
203 :
204 308 : IF (calc_forces) THEN
205 : ! bring myforce to force array
206 25564 : DO j = 1, nnp%num_atoms
207 101794 : DO k = 1, 3
208 622776 : nnp%committee_forces(k, (nnp%sort(j)), :) = nnp%myforce(k, j, :)
209 : END DO
210 : END DO
211 154 : CALL logger%para_env%sum(nnp%committee_forces)
212 622930 : nnp%nnp_forces(:, :) = SUM(nnp%committee_forces, DIM=3)/REAL(nnp%n_committee, dp)
213 25564 : DO j = 1, nnp%num_atoms
214 178024 : particle_set(j)%f(:) = nnp%nnp_forces(:, j)
215 : END DO
216 : END IF
217 :
218 308 : IF (calc_stress) THEN
219 22 : CALL logger%para_env%sum(nnp%committee_stress)
220 2134 : virial%pv_virial = SUM(nnp%committee_stress, DIM=3)/REAL(nnp%n_committee, dp)
221 : END IF
222 :
223 : ! Bias the standard deviation of committee disagreement
224 308 : IF (nnp%bias) THEN
225 44 : CALL nnp_bias_sigma(nnp, calc_forces)
226 44 : nnp%nnp_potential_energy = nnp%nnp_potential_energy + nnp%bias_energy
227 44 : IF (calc_forces) THEN
228 8492 : DO j = 1, nnp%num_atoms
229 59180 : particle_set(j)%f(:) = particle_set(j)%f(:) + nnp%bias_forces(:, j)
230 : END DO
231 : END IF
232 : ! print properties if requested
233 44 : print_section => section_vals_get_subs_vals(nnp%nnp_input, "BIAS%PRINT")
234 44 : CALL nnp_print_bias(nnp, print_section)
235 : END IF
236 :
237 : ! print properties if requested
238 308 : print_section => section_vals_get_subs_vals(nnp%nnp_input, "PRINT")
239 308 : CALL nnp_print(nnp, print_section)
240 :
241 308 : DEALLOCATE (allcalc)
242 :
243 308 : CALL timestop(handle)
244 :
245 616 : END SUBROUTINE nnp_calc_energy_force
246 :
247 : ! **************************************************************************************************
248 : !> \brief Calculate bias potential and force based on standard deviation of committee disagreement
249 : !> \param nnp ...
250 : !> \param calc_forces ...
251 : !> \date 2020-10-10
252 : !> \author Christoph Schran (christoph.schran@rub.de)
253 : ! **************************************************************************************************
254 44 : SUBROUTINE nnp_bias_sigma(nnp, calc_forces)
255 : TYPE(nnp_type), INTENT(INOUT) :: nnp
256 : LOGICAL, INTENT(IN) :: calc_forces
257 :
258 : CHARACTER(len=*), PARAMETER :: routineN = 'nnp_bias_sigma'
259 :
260 : INTEGER :: handle, i
261 : REAL(KIND=dp) :: avrg, pref, sigma
262 :
263 44 : CALL timeset(routineN, handle)
264 :
265 : ! init
266 44 : sigma = 0.0_dp
267 44 : nnp%bias_energy = 0.0_dp
268 33836 : IF (calc_forces) nnp%bias_forces = 0.0_dp
269 :
270 : ! Subtract reference energy of each committee member, if requested
271 44 : IF (nnp%bias_align) THEN
272 : ! committee energy not used afterward, therefore overwritten
273 396 : nnp%committee_energy(:) = nnp%committee_energy(:) - nnp%bias_e_avrg(:)
274 : END IF
275 :
276 : ! <E> = 1/n sum(E_i)
277 : ! sigma = sqrt(1/n sum((E_i - <E>)**2))
278 : ! = sqrt(1/n sum(dE_i**2))
279 396 : avrg = SUM(nnp%committee_energy)/REAL(nnp%n_committee, dp)
280 396 : DO i = 1, nnp%n_committee
281 396 : sigma = sigma + (nnp%committee_energy(i) - avrg)**2
282 : END DO
283 44 : sigma = SQRT(sigma/REAL(nnp%n_committee, dp))
284 44 : nnp%bias_sigma = sigma
285 :
286 44 : IF (sigma > nnp%bias_sigma0) THEN
287 : ! E_b = 0.5 * kb * (sigma - sigma_0)**2
288 44 : nnp%bias_energy = 0.5_dp*nnp%bias_kb*(sigma - nnp%bias_sigma0)**2
289 :
290 44 : IF (calc_forces) THEN
291 : ! nabla(E_b) = kb*(sigma - sigma_0)*nabla(sigma)
292 : ! nabla(sigma) = 1/sigma * 1/n sum(dE_i* nabla(dE_i))
293 : ! nabla(dE_i) = nabla(E_i) - nabla(<E>)
294 44 : pref = nnp%bias_kb*(1.0_dp - nnp%bias_sigma0/sigma)
295 396 : DO i = 1, nnp%n_committee
296 : nnp%bias_forces(:, :) = nnp%bias_forces(:, :) + &
297 : (nnp%committee_energy(i) - avrg)* &
298 270732 : (nnp%committee_forces(:, :, i) - nnp%nnp_forces(:, :))
299 : END DO
300 44 : pref = pref/REAL(nnp%n_committee, dp)
301 33836 : nnp%bias_forces(:, :) = nnp%bias_forces(:, :)*pref
302 : END IF
303 : END IF
304 :
305 44 : CALL timestop(handle)
306 :
307 44 : END SUBROUTINE nnp_bias_sigma
308 :
309 : ! **************************************************************************************************
310 : !> \brief Print properties according to the requests in input file
311 : !> \param nnp ...
312 : !> \param print_section ...
313 : !> \date 2020-10-10
314 : !> \author Christoph Schran (christoph.schran@rub.de)
315 : ! **************************************************************************************************
316 616 : SUBROUTINE nnp_print(nnp, print_section)
317 : TYPE(nnp_type), INTENT(INOUT) :: nnp
318 : TYPE(section_vals_type), INTENT(IN), POINTER :: print_section
319 :
320 : INTEGER :: unit_nr
321 : LOGICAL :: explicit, file_is_new
322 : TYPE(cp_logger_type), POINTER :: logger
323 : TYPE(section_vals_type), POINTER :: print_key
324 :
325 308 : NULLIFY (logger, print_key)
326 308 : logger => cp_get_default_logger()
327 :
328 308 : print_key => section_vals_get_subs_vals(print_section, "ENERGIES")
329 308 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
330 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".data", &
331 308 : middle_name="nnp-energies", is_new_file=file_is_new)
332 308 : IF (unit_nr > 0) CALL nnp_print_energies(nnp, unit_nr, file_is_new)
333 308 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
334 : END IF
335 :
336 308 : print_key => section_vals_get_subs_vals(print_section, "FORCES")
337 308 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
338 286 : IF (unit_nr > 0) CALL nnp_print_forces(nnp, print_key)
339 : END IF
340 :
341 308 : print_key => section_vals_get_subs_vals(print_section, "FORCES_SIGMA")
342 308 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
343 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".xyz", &
344 264 : middle_name="nnp-forces-std")
345 264 : IF (unit_nr > 0) CALL nnp_print_force_sigma(nnp, unit_nr)
346 264 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
347 : END IF
348 :
349 : ! Output structures with extrapolation warning on any processor
350 308 : CALL logger%para_env%sum(nnp%output_expol)
351 308 : IF (nnp%output_expol) THEN
352 22 : print_key => section_vals_get_subs_vals(print_section, "EXTRAPOLATION")
353 22 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
354 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".xyz", &
355 22 : middle_name="nnp-extrapolation")
356 22 : IF (unit_nr > 0) CALL nnp_print_expol(nnp, unit_nr)
357 22 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
358 : END IF
359 : END IF
360 :
361 308 : print_key => section_vals_get_subs_vals(print_section, "SUM_FORCE")
362 :
363 : CALL section_vals_val_get(print_section, "SUM_FORCE%ATOM_LIST", &
364 308 : explicit=explicit)
365 308 : IF (explicit) THEN
366 0 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
367 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".dat", &
368 0 : middle_name="nnp-sumforce", is_new_file=file_is_new)
369 0 : IF (unit_nr > 0) CALL nnp_print_sumforces(nnp, print_section, unit_nr, file_is_new)
370 0 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
371 : END IF
372 : END IF
373 :
374 308 : END SUBROUTINE nnp_print
375 :
376 : ! **************************************************************************************************
377 : !> \brief Print NNP energies and standard deviation sigma
378 : !> \param nnp ...
379 : !> \param unit_nr ...
380 : !> \param file_is_new ...
381 : !> \date 2020-10-10
382 : !> \author Christoph Schran (christoph.schran@rub.de)
383 : ! **************************************************************************************************
384 154 : SUBROUTINE nnp_print_energies(nnp, unit_nr, file_is_new)
385 : TYPE(nnp_type), INTENT(INOUT) :: nnp
386 : INTEGER, INTENT(IN) :: unit_nr
387 : LOGICAL, INTENT(IN) :: file_is_new
388 :
389 : CHARACTER(len=default_path_length) :: fmt_string
390 : INTEGER :: i
391 : REAL(KIND=dp) :: std
392 :
393 154 : IF (file_is_new) THEN
394 6 : WRITE (unit_nr, "(A1,1X,A20)", ADVANCE='no') "#", "NNP Average [a.u.],"
395 6 : WRITE (unit_nr, "(A20)", ADVANCE='no') "NNP sigma [a.u.]"
396 47 : DO i = 1, nnp%n_committee
397 47 : WRITE (unit_nr, "(A17,I3)", ADVANCE='no') "NNP", i
398 : END DO
399 6 : WRITE (unit_nr, "(A)") ""
400 : END IF
401 :
402 154 : fmt_string = "(2X,2(F20.9))"
403 154 : WRITE (fmt_string, "(A,I3,A)") "(2X", nnp%n_committee + 2, "(F20.9))"
404 206437 : std = SUM((SUM(nnp%atomic_energy, 1) - nnp%nnp_potential_energy)**2)
405 154 : std = std/REAL(nnp%n_committee, dp)
406 154 : std = SQRT(std)
407 206437 : WRITE (unit_nr, fmt_string) nnp%nnp_potential_energy, std, SUM(nnp%atomic_energy, 1)
408 :
409 154 : END SUBROUTINE nnp_print_energies
410 :
411 : ! **************************************************************************************************
412 : !> \brief Print nnp forces
413 : !> \param nnp ...
414 : !> \param print_key ...
415 : !> \date 2020-10-10
416 : !> \author Christoph Schran (christoph.schran@rub.de)
417 : ! **************************************************************************************************
418 0 : SUBROUTINE nnp_print_forces(nnp, print_key)
419 : TYPE(nnp_type), INTENT(INOUT) :: nnp
420 : TYPE(section_vals_type), INTENT(IN), POINTER :: print_key
421 :
422 : CHARACTER(len=default_path_length) :: fmt_string, middle_name
423 : INTEGER :: i, j, unit_nr
424 : TYPE(cp_logger_type), POINTER :: logger
425 :
426 0 : NULLIFY (logger)
427 0 : logger => cp_get_default_logger()
428 :
429 : ! TODO use write_particle_coordinates from particle_methods.F
430 0 : DO i = 1, nnp%n_committee
431 0 : WRITE (fmt_string, *) i
432 0 : WRITE (middle_name, "(A,A)") "nnp-forces-", ADJUSTL(TRIM(fmt_string))
433 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".xyz", &
434 0 : middle_name=TRIM(middle_name))
435 0 : IF (unit_nr > 0) THEN
436 0 : WRITE (unit_nr, *) nnp%num_atoms
437 0 : WRITE (unit_nr, "(A,1X,A,A,F20.9)") "NNP forces [a.u.] of committee member", &
438 0 : ADJUSTL(TRIM(fmt_string)), "energy [a.u.]=", nnp%committee_energy(i)
439 :
440 0 : fmt_string = "(A4,1X,3F20.10)"
441 0 : DO j = 1, nnp%num_atoms
442 0 : WRITE (unit_nr, fmt_string) nnp%atoms(nnp%sort_inv(j)), nnp%committee_forces(:, j, i)
443 : END DO
444 : END IF
445 0 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
446 : END DO
447 :
448 0 : END SUBROUTINE nnp_print_forces
449 :
450 : ! **************************************************************************************************
451 : !> \brief Print standard deviation sigma of NNP forces
452 : !> \param nnp ...
453 : !> \param unit_nr ...
454 : !> \date 2020-10-10
455 : !> \author Christoph Schran (christoph.schran@rub.de)
456 : ! **************************************************************************************************
457 132 : SUBROUTINE nnp_print_force_sigma(nnp, unit_nr)
458 : TYPE(nnp_type), INTENT(INOUT) :: nnp
459 : INTEGER, INTENT(IN) :: unit_nr
460 :
461 : INTEGER :: i, j
462 : REAL(KIND=dp), DIMENSION(3) :: var
463 :
464 132 : IF (unit_nr > 0) THEN
465 132 : WRITE (unit_nr, *) nnp%num_atoms
466 132 : WRITE (unit_nr, "(A,1X,A)") "NNP sigma of forces [a.u.]"
467 :
468 25476 : DO i = 1, nnp%num_atoms
469 25344 : var = 0.0_dp
470 228096 : DO j = 1, nnp%n_committee
471 836352 : var = var + (nnp%committee_forces(:, i, j) - nnp%nnp_forces(:, i))**2
472 : END DO
473 101376 : var = var/REAL(nnp%n_committee, dp)
474 101376 : var = SQRT(var)
475 25476 : WRITE (unit_nr, "(A4,1X,3F20.10)") nnp%atoms(nnp%sort_inv(i)), var
476 : END DO
477 : END IF
478 :
479 132 : END SUBROUTINE nnp_print_force_sigma
480 :
481 : ! **************************************************************************************************
482 : !> \brief Print structures with extrapolation warning
483 : !> \param nnp ...
484 : !> \param unit_nr ...
485 : !> \date 2020-10-10
486 : !> \author Christoph Schran (christoph.schran@rub.de)
487 : ! **************************************************************************************************
488 11 : SUBROUTINE nnp_print_expol(nnp, unit_nr)
489 : TYPE(nnp_type), INTENT(INOUT) :: nnp
490 : INTEGER, INTENT(IN) :: unit_nr
491 :
492 : CHARACTER(len=default_path_length) :: fmt_string
493 : INTEGER :: i
494 : REAL(KIND=dp) :: mass, unit_conv
495 : REAL(KIND=dp), DIMENSION(3) :: com
496 :
497 11 : nnp%expol = nnp%expol + 1
498 11 : WRITE (unit_nr, *) nnp%num_atoms
499 11 : WRITE (unit_nr, "(A,1X,I6)") "NNP extrapolation point N =", nnp%expol
500 :
501 : ! move to COM of solute and wrap the box
502 : ! coord not needed afterwards, therefore manipulation ok
503 11 : com = 0.0_dp
504 11 : mass = 0.0_dp
505 44 : DO i = 1, nnp%num_atoms
506 33 : CALL get_ptable_info(nnp%atoms(i), amass=unit_conv)
507 132 : com(:) = com(:) + nnp%coord(:, i)*unit_conv
508 77 : mass = mass + unit_conv
509 : END DO
510 44 : com(:) = com(:)/mass
511 :
512 44 : DO i = 1, nnp%num_atoms
513 143 : nnp%coord(:, i) = nnp%coord(:, i) - com(:)
514 : END DO
515 :
516 : ! write out coordinates
517 11 : unit_conv = cp_unit_from_cp2k(1.0_dp, TRIM("angstrom"))
518 11 : fmt_string = "(A4,1X,3F20.10)"
519 44 : DO i = 1, nnp%num_atoms
520 : WRITE (unit_nr, fmt_string) &
521 33 : nnp%atoms(nnp%sort_inv(i)), &
522 33 : nnp%coord(1, nnp%sort_inv(i))*unit_conv, &
523 33 : nnp%coord(2, nnp%sort_inv(i))*unit_conv, &
524 77 : nnp%coord(3, nnp%sort_inv(i))*unit_conv
525 : END DO
526 :
527 11 : END SUBROUTINE nnp_print_expol
528 :
529 : ! **************************************************************************************************
530 : !> \brief Print properties number according the requests in input file
531 : !> \param nnp ...
532 : !> \param print_section ...
533 : !> \date 2020-10-10
534 : !> \author Christoph Schran (christoph.schran@rub.de)
535 : ! **************************************************************************************************
536 44 : SUBROUTINE nnp_print_bias(nnp, print_section)
537 : TYPE(nnp_type), INTENT(INOUT) :: nnp
538 : TYPE(section_vals_type), INTENT(IN), POINTER :: print_section
539 :
540 : INTEGER :: unit_nr
541 : LOGICAL :: file_is_new
542 : TYPE(cp_logger_type), POINTER :: logger
543 : TYPE(section_vals_type), POINTER :: print_key
544 :
545 44 : NULLIFY (logger, print_key)
546 44 : logger => cp_get_default_logger()
547 :
548 44 : print_key => section_vals_get_subs_vals(print_section, "BIAS_ENERGY")
549 44 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
550 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".data", &
551 44 : middle_name="nnp-bias-energy", is_new_file=file_is_new)
552 44 : IF (unit_nr > 0) CALL nnp_print_bias_energy(nnp, unit_nr, file_is_new)
553 44 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
554 : END IF
555 :
556 44 : print_key => section_vals_get_subs_vals(print_section, "BIAS_FORCES")
557 44 : IF (BTEST(cp_print_key_should_output(logger%iter_info, print_key), cp_p_file)) THEN
558 : unit_nr = cp_print_key_unit_nr(logger, print_key, extension=".xyz", &
559 0 : middle_name="nnp-bias-forces")
560 0 : IF (unit_nr > 0) CALL nnp_print_bias_forces(nnp, unit_nr)
561 0 : CALL cp_print_key_finished_output(unit_nr, logger, print_key)
562 : END IF
563 :
564 44 : END SUBROUTINE nnp_print_bias
565 :
566 : ! **************************************************************************************************
567 : !> \brief Print NNP bias energies
568 : !> \param nnp ...
569 : !> \param unit_nr ...
570 : !> \param file_is_new ...
571 : !> \date 2020-10-10
572 : !> \author Christoph Schran (christoph.schran@rub.de)
573 : ! **************************************************************************************************
574 22 : SUBROUTINE nnp_print_bias_energy(nnp, unit_nr, file_is_new)
575 : TYPE(nnp_type), INTENT(INOUT) :: nnp
576 : INTEGER, INTENT(IN) :: unit_nr
577 : LOGICAL, INTENT(IN) :: file_is_new
578 :
579 : CHARACTER(len=default_path_length) :: fmt_string
580 : INTEGER :: i
581 :
582 22 : IF (file_is_new) THEN
583 1 : WRITE (unit_nr, "(A1)", ADVANCE='no') "#"
584 1 : WRITE (unit_nr, "(2(2X,A19))", ADVANCE='no') "Sigma [a.u.]", "Bias energy [a.u.]"
585 9 : DO i = 1, nnp%n_committee
586 9 : IF (nnp%bias_align) THEN
587 8 : WRITE (unit_nr, "(2X,A16,I3)", ADVANCE='no') "shifted E_NNP", i
588 : ELSE
589 0 : WRITE (unit_nr, "(2X,A16,I3)", ADVANCE='no') "E_NNP", i
590 : END IF
591 : END DO
592 1 : WRITE (unit_nr, "(A)") ""
593 :
594 : END IF
595 :
596 22 : WRITE (fmt_string, "(A,I3,A)") "(2X,", nnp%n_committee + 2, "(F20.9,1X))"
597 22 : WRITE (unit_nr, fmt_string) nnp%bias_sigma, nnp%bias_energy, nnp%committee_energy
598 :
599 22 : END SUBROUTINE nnp_print_bias_energy
600 :
601 : ! **************************************************************************************************
602 : !> \brief Print NNP bias forces
603 : !> \param nnp ...
604 : !> \param unit_nr ...
605 : !> \date 2020-10-10
606 : !> \author Christoph Schran (christoph.schran@rub.de)
607 : ! **************************************************************************************************
608 0 : SUBROUTINE nnp_print_bias_forces(nnp, unit_nr)
609 : TYPE(nnp_type), INTENT(INOUT) :: nnp
610 : INTEGER, INTENT(IN) :: unit_nr
611 :
612 : CHARACTER(len=default_path_length) :: fmt_string
613 : INTEGER :: i
614 :
615 : ! TODO use write_particle_coordinates from particle_methods.F
616 0 : WRITE (unit_nr, *) nnp%num_atoms
617 0 : WRITE (unit_nr, "(A,F20.9)") "NNP bias forces [a.u.] for bias energy [a.u]=", nnp%bias_energy
618 :
619 0 : fmt_string = "(A4,1X,3F20.10)"
620 0 : DO i = 1, nnp%num_atoms
621 0 : WRITE (unit_nr, fmt_string) nnp%atoms(nnp%sort_inv(i)), nnp%bias_forces(:, i)
622 : END DO
623 :
624 0 : END SUBROUTINE nnp_print_bias_forces
625 :
626 : ! **************************************************************************************************
627 : !> \brief Print NNP summed forces
628 : !> \param nnp ...
629 : !> \param print_section ...
630 : !> \param unit_nr ...
631 : !> \param file_is_new ...
632 : !> \date 2020-10-10
633 : !> \author Christoph Schran (christoph.schran@rub.de)
634 : ! **************************************************************************************************
635 0 : SUBROUTINE nnp_print_sumforces(nnp, print_section, unit_nr, file_is_new)
636 : TYPE(nnp_type), INTENT(INOUT) :: nnp
637 : TYPE(section_vals_type), INTENT(IN), POINTER :: print_section
638 : INTEGER, INTENT(IN) :: unit_nr
639 : LOGICAL, INTENT(IN) :: file_is_new
640 :
641 : CHARACTER(len=default_path_length) :: fmt_string
642 : CHARACTER(LEN=default_string_length), &
643 0 : DIMENSION(:), POINTER :: atomlist
644 : INTEGER :: i, ig, j, n
645 : REAL(KIND=dp), DIMENSION(3) :: rvec
646 :
647 0 : NULLIFY (atomlist)
648 0 : IF (file_is_new) THEN
649 0 : WRITE (unit_nr, "(A)") "# Summed forces [a.u.]"
650 : END IF
651 :
652 0 : rvec = 0.0_dp
653 :
654 : ! get atoms to sum over:
655 : CALL section_vals_val_get(print_section, "SUM_FORCE%ATOM_LIST", &
656 0 : c_vals=atomlist)
657 0 : IF (ASSOCIATED(atomlist)) THEN
658 0 : n = SIZE(atomlist)
659 0 : DO i = 1, nnp%num_atoms
660 0 : DO j = 1, n
661 0 : ig = nnp%sort_inv(i)
662 0 : IF (TRIM(ADJUSTL(atomlist(j))) == TRIM(ADJUSTL(nnp%atoms(ig)))) THEN
663 0 : rvec(:) = rvec(:) + nnp%nnp_forces(:, i)
664 : END IF
665 : END DO
666 : END DO
667 : END IF
668 :
669 0 : fmt_string = "(3(F20.10,1X))"
670 0 : WRITE (unit_nr, fmt_string) rvec
671 :
672 0 : END SUBROUTINE nnp_print_sumforces
673 :
674 : END MODULE nnp_force
|