(git:871dbd5)
Loading...
Searching...
No Matches
cp2k_debug.F
Go to the documentation of this file.
1!--------------------------------------------------------------------------------------------------!
2! CP2K: A general program to perform molecular dynamics simulations !
3! Copyright 2000-2026 CP2K developers group <https://cp2k.org> !
4! !
5! SPDX-License-Identifier: GPL-2.0-or-later !
6!--------------------------------------------------------------------------------------------------!
7
8! **************************************************************************************************
9!> \brief Debug energy and derivatives w.r.t. finite differences
10!> \note
11!> Use INTERPOLATION USE_GUESS, in order to perform force and energy
12!> calculations with the same density. This is not compulsory when iterating
13!> to selfconsistency, but essential in the non-selfconsistent case [08.2005,TdK].
14!> \par History
15!> 12.2004 created [tlaino]
16!> 08.2005 consistent_energies option added, to allow FD calculations
17!> with the correct energies in the non-selfconsistent case, but
18!> keep in mind, that the QS energies and forces are then NOT
19!> consistent to each other [TdK].
20!> 08.2005 In case the Harris functional is used, consistent_energies is
21!> et to .FALSE., otherwise the QS energies are spuriously used [TdK].
22!> 01.2015 Remove Harris functional option
23!> - Revised (20.11.2013,MK)
24!> \author Teodoro Laino
25! **************************************************************************************************
27 USE cell_types, ONLY: cell_type,&
51 USE kinds, ONLY: default_string_length,&
52 dp
60 USE virial_types, ONLY: virial_set,&
62#include "./base/base_uses.f90"
63
64 IMPLICIT NONE
65 PRIVATE
66 CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'cp2k_debug'
67
69
70CONTAINS
71
72! **************************************************************************************************
73!> \brief ...
74!> \param force_env ...
75! **************************************************************************************************
76 SUBROUTINE cp2k_debug_energy_and_forces(force_env)
77
78 TYPE(force_env_type), POINTER :: force_env
79
80 CHARACTER(LEN=3) :: cval1
81 CHARACTER(LEN=3*default_string_length) :: message
82 CHARACTER(LEN=60) :: line
83 CHARACTER(LEN=80), DIMENSION(:), POINTER :: cval2
84 CHARACTER(LEN=default_string_length) :: description
85 INTEGER :: i, ip, irep, iw, j, k, n_periodic, np, &
86 nrep, stress_tensor
87 INTEGER, DIMENSION(3) :: periodic
88 LOGICAL :: check_failed, debug_dipole, &
89 debug_forces, debug_polar, &
90 debug_stress_tensor, skip, &
91 stop_on_mismatch
92 LOGICAL, ALLOCATABLE, DIMENSION(:, :) :: do_dof_atom_coor
93 LOGICAL, DIMENSION(3) :: do_dof_dipole
94 LOGICAL, DIMENSION(3, 3) :: check_stress_element
95 REAL(kind=dp) :: amplitude, dd, de, derr, difference, dx, eps_no_error_check, errmax, &
96 maxerr, periodic_stress_sum, std_value, sum_of_differences
97 REAL(kind=dp), DIMENSION(2) :: numer_energy
98 REAL(kind=dp), DIMENSION(3) :: dipole_moment, dipole_numer, err, &
99 my_maxerr, poldir
100 REAL(kind=dp), DIMENSION(3, 2) :: dipn
101 REAL(kind=dp), DIMENSION(3, 3) :: polar_analytic, polar_numeric
102 REAL(kind=dp), DIMENSION(9) :: pvals
103 REAL(kind=dp), DIMENSION(:, :), POINTER :: analyt_forces, numer_forces
104 TYPE(cell_type), POINTER :: cell
105 TYPE(cp_logger_type), POINTER :: logger
106 TYPE(cp_result_type), POINTER :: results
107 TYPE(cp_subsys_type), POINTER :: subsys
108 TYPE(dft_control_type), POINTER :: dft_control
109 TYPE(mp_para_env_type), POINTER :: para_env
110 TYPE(particle_type), DIMENSION(:), POINTER :: particles
111 TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set
112 TYPE(section_vals_type), POINTER :: root_section, subsys_section
113
114 NULLIFY (analyt_forces, numer_forces, subsys, particles)
115
116 root_section => force_env%root_section
117
118 CALL force_env_get(force_env, para_env=para_env, subsys=subsys, cell=cell)
119 subsys_section => section_vals_get_subs_vals(force_env%force_env_section, &
120 "SUBSYS")
121
122 CALL section_vals_val_get(root_section, "DEBUG%DEBUG_STRESS_TENSOR", &
123 l_val=debug_stress_tensor)
124 CALL section_vals_val_get(root_section, "DEBUG%DEBUG_FORCES", &
125 l_val=debug_forces)
126 CALL section_vals_val_get(root_section, "DEBUG%DEBUG_DIPOLE", &
127 l_val=debug_dipole)
128 CALL section_vals_val_get(root_section, "DEBUG%DEBUG_POLARIZABILITY", &
129 l_val=debug_polar)
130 CALL section_vals_val_get(root_section, "DEBUG%DX", &
131 r_val=dx)
132 CALL section_vals_val_get(root_section, "DEBUG%DE", &
133 r_val=de)
134 CALL section_vals_val_get(root_section, "DEBUG%CHECK_DIPOLE_DIRS", &
135 c_val=cval1)
136 dx = abs(dx)
137 CALL section_vals_val_get(root_section, "DEBUG%MAX_RELATIVE_ERROR", &
138 r_val=maxerr)
139 CALL section_vals_val_get(root_section, "DEBUG%EPS_NO_ERROR_CHECK", &
140 r_val=eps_no_error_check)
141 eps_no_error_check = max(eps_no_error_check, epsilon(0.0_dp))
142 CALL section_vals_val_get(root_section, "DEBUG%STOP_ON_MISMATCH", &
143 l_val=stop_on_mismatch)
144
145 ! set active DOF
146 CALL uppercase(cval1)
147 do_dof_dipole(1) = (index(cval1, "X") /= 0)
148 do_dof_dipole(2) = (index(cval1, "Y") /= 0)
149 do_dof_dipole(3) = (index(cval1, "Z") /= 0)
150 NULLIFY (cval2)
151 IF (debug_forces) THEN
152 np = subsys%particles%n_els
153 ALLOCATE (do_dof_atom_coor(3, np))
154 CALL section_vals_val_get(root_section, "DEBUG%CHECK_ATOM_FORCE", n_rep_val=nrep)
155 IF (nrep > 0) THEN
156 do_dof_atom_coor = .false.
157 DO irep = 1, nrep
158 CALL section_vals_val_get(root_section, "DEBUG%CHECK_ATOM_FORCE", i_rep_val=irep, &
159 c_vals=cval2)
160 READ (cval2(1), fmt="(I10)") k
161 CALL uppercase(cval2(2))
162 do_dof_atom_coor(1, k) = (index(cval2(2), "X") /= 0)
163 do_dof_atom_coor(2, k) = (index(cval2(2), "Y") /= 0)
164 do_dof_atom_coor(3, k) = (index(cval2(2), "Z") /= 0)
165 END DO
166 ELSE
167 do_dof_atom_coor = .true.
168 END IF
169 END IF
170
171 logger => cp_get_default_logger()
172 iw = cp_print_key_unit_nr(logger, root_section, "DEBUG%PROGRAM_RUN_INFO", &
173 extension=".log")
174 IF (debug_stress_tensor) THEN
175 IF (sum(cell%perd) == 0) THEN
176 CALL cp_warn(__location__, &
177 "DEBUG_STRESS_TENSOR requested for PERIODIC NONE. "// &
178 "The isolated-system virial is useful for finite-difference diagnostics, "// &
179 "but it is not a physically meaningful bulk stress.")
180 END IF
181 ! To debug stress tensor the stress tensor calculation must be
182 ! first enabled..
183 CALL section_vals_val_get(force_env%force_env_section, "STRESS_TENSOR", &
184 i_val=stress_tensor)
185 skip = .false.
186 SELECT CASE (stress_tensor)
188 ! OK
190 ! Nothing to check
191 CALL cp_warn(__location__, "Numerical stress tensor was requested in "// &
192 "the FORCE_EVAL section. Nothing to debug!")
193 skip = .true.
194 CASE DEFAULT
195 CALL cp_warn(__location__, "Stress tensor calculation was not enabled in "// &
196 "the FORCE_EVAL section. Nothing to debug!")
197 skip = .true.
198 END SELECT
199
200 IF (.NOT. skip) THEN
201
202 block
203 TYPE(virial_type) :: virial_analytical, virial_numerical
204 TYPE(virial_type), POINTER :: virial
205
206 ! Compute the analytical stress tensor
207 CALL cp_subsys_get(subsys, virial=virial)
208 CALL virial_set(virial, pv_numer=.false.)
209 CALL force_env_calc_energy_force(force_env, &
210 calc_force=.true., &
211 calc_stress_tensor=.true.)
212
213 ! Retrieve the analytical virial
214 virial_analytical = virial
215
216 ! Debug stress tensor (numerical vs analytical)
217 CALL virial_set(virial, pv_numer=.true.)
218 CALL force_env_calc_num_pressure(force_env, dx=dx)
219
220 ! Retrieve the numerical virial
221 CALL cp_subsys_get(subsys, virial=virial)
222 virial_numerical = virial
223
224 ! Numerical diagonal stress checks only perturb diagonal cell elements.
225 IF (virial_analytical%pv_diagonal .OR. virial_numerical%pv_diagonal) THEN
226 DO i = 1, 3
227 DO k = 1, 3
228 IF (i /= k) THEN
229 virial_analytical%pv_virial(i, k) = 0.0_dp
230 virial_numerical%pv_virial(i, k) = 0.0_dp
231 END IF
232 END DO
233 END DO
234 END IF
235
236 CALL get_cell(cell=cell, periodic=periodic)
237 n_periodic = count(periodic /= 0)
238 check_stress_element = .true.
239 IF (n_periodic > 0 .AND. n_periodic < 3) THEN
240 check_stress_element = .false.
241 DO i = 1, 3
242 DO k = 1, 3
243 check_stress_element(i, k) = periodic(i) /= 0 .AND. periodic(k) /= 0
244 END DO
245 END DO
246 END IF
247
248 ! Print results
249 IF (iw > 0) THEN
250 WRITE (unit=iw, fmt="((T2,A))") &
251 "DEBUG| Numerical pv_virial [a.u.]"
252 WRITE (unit=iw, fmt="((T2,A,T21,3(1X,F19.12)))") &
253 ("DEBUG|", virial_numerical%pv_virial(i, 1:3), i=1, 3)
254 WRITE (unit=iw, fmt="(/,(T2,A))") &
255 "DEBUG| Analytical pv_virial [a.u.]"
256 WRITE (unit=iw, fmt="((T2,A,T21,3(1X,F19.12)))") &
257 ("DEBUG|", virial_analytical%pv_virial(i, 1:3), i=1, 3)
258 WRITE (unit=iw, fmt="(/,(T2,A))") &
259 "DEBUG| Difference pv_virial [a.u.]"
260 WRITE (unit=iw, fmt="((T2,A,T21,3(1X,F19.12)))") &
261 ("DEBUG|", virial_numerical%pv_virial(i, 1:3) - virial_analytical%pv_virial(i, 1:3), i=1, 3)
262 WRITE (unit=iw, fmt="(T2,A,T61,F20.12)") &
263 "DEBUG| Sum of differences", &
264 sum(abs(virial_numerical%pv_virial(:, :) - virial_analytical%pv_virial(:, :)))
265 IF (n_periodic > 0 .AND. n_periodic < 3) THEN
266 periodic_stress_sum = 0.0_dp
267 DO i = 1, 3
268 DO k = 1, 3
269 IF (periodic(i) /= 0 .AND. periodic(k) /= 0) THEN
270 periodic_stress_sum = periodic_stress_sum + &
271 abs(virial_numerical%pv_virial(i, k) - &
272 virial_analytical%pv_virial(i, k))
273 END IF
274 END DO
275 END DO
276 WRITE (unit=iw, fmt="(T2,A,T61,F20.12)") &
277 "DEBUG| Periodic-subspace sum of differences", periodic_stress_sum
278 END IF
279 END IF
280
281 ! Check and abort on failure
282 check_failed = .false.
283 IF (iw > 0) THEN
284 WRITE (unit=iw, fmt="(/T2,A)") &
285 "DEBUG| Relative error pv_virial"
286 WRITE (unit=iw, fmt="(T2,A,T61,ES20.8)") &
287 "DEBUG| Threshold value for error check [a.u.]", eps_no_error_check
288 END IF
289 DO i = 1, 3
290 err(:) = 0.0_dp
291 DO k = 1, 3
292 IF (check_stress_element(i, k) .AND. &
293 abs(virial_analytical%pv_virial(i, k)) >= eps_no_error_check) THEN
294 err(k) = 100.0_dp*(virial_numerical%pv_virial(i, k) - virial_analytical%pv_virial(i, k))/ &
295 virial_analytical%pv_virial(i, k)
296 WRITE (unit=line(20*(k - 1) + 1:20*k), fmt="(1X,F17.2,A2)") err(k), " %"
297 ELSE
298 WRITE (unit=line(20*(k - 1) + 1:20*k), fmt="(17X,A3)") "- %"
299 END IF
300 END DO
301 IF (iw > 0) THEN
302 WRITE (unit=iw, fmt="(T2,A,T21,A60)") &
303 "DEBUG|", line
304 END IF
305 IF (any(abs(err(1:3)) > maxerr)) check_failed = .true.
306 END DO
307 IF (iw > 0) THEN
308 WRITE (unit=iw, fmt="(T2,A,T61,F18.2,A2)") &
309 "DEBUG| Maximum accepted error", maxerr, " %"
310 END IF
311 IF (check_failed) THEN
312 message = "A mismatch between the analytical and the numerical "// &
313 "stress tensor has been detected. Check the implementation "// &
314 "of the stress tensor"
315 IF (stop_on_mismatch) THEN
316 cpabort(trim(message))
317 ELSE
318 cpwarn(trim(message))
319 END IF
320 END IF
321 END block
322 END IF
323 END IF
324
325 IF (debug_forces) THEN
326 ! Debug forces (numerical vs analytical)
327 particles => subsys%particles%els
328 SELECT CASE (force_env%in_use)
329 CASE (use_qs_force)
330 CALL get_qs_env(force_env%qs_env, qs_kind_set=qs_kind_set)
331 CALL write_qs_particle_coordinates(particles, qs_kind_set, subsys_section, "DEBUG")
332 CASE DEFAULT
333 CALL write_fist_particle_coordinates(particles, subsys_section)
334 END SELECT
335 ! First evaluate energy and forces
336 CALL force_env_calc_energy_force(force_env, &
337 calc_force=.true., &
338 calc_stress_tensor=.false.)
339 ! Copy forces in array and start the numerical calculation
340 IF (ASSOCIATED(analyt_forces)) DEALLOCATE (analyt_forces)
341 np = subsys%particles%n_els
342 ALLOCATE (analyt_forces(np, 3))
343 DO ip = 1, np
344 analyt_forces(ip, 1:3) = particles(ip)%f(1:3)
345 END DO
346 ! Loop on atoms and coordinates
347 IF (ASSOCIATED(numer_forces)) DEALLOCATE (numer_forces)
348 ALLOCATE (numer_forces(subsys%particles%n_els, 3))
349 atom: DO ip = 1, np
350 coord: DO k = 1, 3
351 IF (do_dof_atom_coor(k, ip)) THEN
352 numer_energy = 0.0_dp
353 std_value = particles(ip)%r(k)
354 DO j = 1, 2
355 particles(ip)%r(k) = std_value - (-1.0_dp)**j*dx
356 SELECT CASE (force_env%in_use)
357 CASE (use_qs_force)
358 CALL get_qs_env(force_env%qs_env, qs_kind_set=qs_kind_set)
359 CALL write_qs_particle_coordinates(particles, qs_kind_set, subsys_section, "DEBUG")
360 CASE DEFAULT
361 CALL write_fist_particle_coordinates(particles, subsys_section)
362 END SELECT
363 ! Compute energy
364 CALL force_env_calc_energy_force(force_env, &
365 calc_force=.false., &
366 calc_stress_tensor=.false., &
367 consistent_energies=.true.)
368 CALL force_env_get(force_env, potential_energy=numer_energy(j))
369 END DO
370 particles(ip)%r(k) = std_value
371 numer_forces(ip, k) = -0.5_dp*(numer_energy(1) - numer_energy(2))/dx
372 IF (iw > 0) THEN
373 WRITE (unit=iw, fmt="(/,T2,A,T17,A,F7.4,A,T34,A,F7.4,A,T52,A,T68,A)") &
374 "DEBUG| Atom", "E("//achar(119 + k)//" +", dx, ")", &
375 "E("//achar(119 + k)//" -", dx, ")", &
376 "f(numerical)", "f(analytical)"
377 WRITE (unit=iw, fmt="(T2,A,I5,4(1X,F16.8))") &
378 "DEBUG|", ip, numer_energy(1:2), numer_forces(ip, k), analyt_forces(ip, k)
379 END IF
380 ELSE
381 numer_forces(ip, k) = 0.0_dp
382 END IF
383 END DO coord
384 ! Check analytical forces using the numerical forces as reference
385 my_maxerr = maxerr
386 err(1:3) = 0.0_dp
387 DO k = 1, 3
388 IF (do_dof_atom_coor(k, ip)) THEN
389 ! Calculate percentage but ignore very small force values
390 IF (abs(analyt_forces(ip, k)) >= eps_no_error_check) THEN
391 err(k) = 100.0_dp*(numer_forces(ip, k) - analyt_forces(ip, k))/analyt_forces(ip, k)
392 END IF
393 ! Increase error tolerance for small force values
394 IF (abs(analyt_forces(ip, k)) <= 0.0001_dp) my_maxerr(k) = 5.0_dp*my_maxerr(k)
395 ELSE
396 err(k) = 0.0_dp
397 END IF
398 END DO
399 IF (iw > 0) THEN
400 IF (any(do_dof_atom_coor(1:3, ip))) THEN
401 WRITE (unit=iw, fmt="(/,T2,A)") &
402 "DEBUG| Atom Coordinate f(numerical) f(analytical) Difference Error [%]"
403 END IF
404 DO k = 1, 3
405 IF (do_dof_atom_coor(k, ip)) THEN
406 difference = analyt_forces(ip, k) - numer_forces(ip, k)
407 IF (abs(analyt_forces(ip, k)) >= eps_no_error_check) THEN
408 WRITE (unit=iw, fmt="(T2,A,I5,T19,A1,T26,F14.8,T42,F14.8,T57,F12.8,T71,F10.2)") &
409 "DEBUG|", ip, achar(119 + k), numer_forces(ip, k), analyt_forces(ip, k), difference, err(k)
410 ELSE
411 WRITE (unit=iw, fmt="(T2,A,I5,T19,A1,T26,F14.8,T42,F14.8,T57,F12.8,T80,A1)") &
412 "DEBUG|", ip, achar(119 + k), numer_forces(ip, k), analyt_forces(ip, k), difference, "-"
413 END IF
414 END IF
415 END DO
416 END IF
417 IF (any(abs(err(1:3)) > my_maxerr(1:3))) THEN
418 message = "A mismatch between analytical and numerical forces "// &
419 "has been detected. Check the implementation of the "// &
420 "analytical force calculation"
421 IF (stop_on_mismatch) THEN
422 cpabort(message)
423 ELSE
424 cpwarn(message)
425 END IF
426 END IF
427 END DO atom
428 ! Print summary
429 IF (iw > 0) THEN
430 WRITE (unit=iw, fmt="(/,(T2,A))") &
431 "DEBUG|======================== BEGIN OF SUMMARY ===============================", &
432 "DEBUG| Atom Coordinate f(numerical) f(analytical) Difference Error [%]"
433 sum_of_differences = 0.0_dp
434 errmax = 0.0_dp
435 DO ip = 1, np
436 err(1:3) = 0.0_dp
437 DO k = 1, 3
438 IF (do_dof_atom_coor(k, ip)) THEN
439 difference = analyt_forces(ip, k) - numer_forces(ip, k)
440 IF (abs(analyt_forces(ip, k)) >= eps_no_error_check) THEN
441 err(k) = 100_dp*(numer_forces(ip, k) - analyt_forces(ip, k))/analyt_forces(ip, k)
442 errmax = max(errmax, abs(err(k)))
443 WRITE (unit=iw, fmt="(T2,A,I5,T19,A1,T26,F14.8,T42,F14.8,T57,F12.8,T71,F10.2)") &
444 "DEBUG|", ip, achar(119 + k), numer_forces(ip, k), analyt_forces(ip, k), difference, err(k)
445 ELSE
446 WRITE (unit=iw, fmt="(T2,A,I5,T19,A1,T26,F14.8,T42,F14.8,T57,F12.8,T80,A1)") &
447 "DEBUG|", ip, achar(119 + k), numer_forces(ip, k), analyt_forces(ip, k), difference, "-"
448 END IF
449 sum_of_differences = sum_of_differences + abs(difference)
450 END IF
451 END DO
452 END DO
453 WRITE (unit=iw, fmt="(T2,A,T57,F12.8,T71,F10.2)") &
454 "DEBUG| Sum of differences:", sum_of_differences, errmax
455 WRITE (unit=iw, fmt="(T2,A)") &
456 "DEBUG|======================== END OF SUMMARY ================================="
457 END IF
458 ! Release work storage
459 IF (ASSOCIATED(analyt_forces)) DEALLOCATE (analyt_forces)
460 IF (ASSOCIATED(numer_forces)) DEALLOCATE (numer_forces)
461 DEALLOCATE (do_dof_atom_coor)
462 END IF
463
464 IF (debug_dipole) THEN
465 IF (force_env%in_use == use_qs_force) THEN
466 CALL get_qs_env(force_env%qs_env, dft_control=dft_control)
467 poldir = [0.0_dp, 0.0_dp, 1.0_dp]
468 amplitude = 0.0_dp
469 CALL set_efield(dft_control, amplitude, poldir)
470 CALL force_env_calc_energy_force(force_env, calc_force=.true.)
471 CALL get_qs_env(force_env%qs_env, results=results)
472 description = "[DIPOLE]"
473 IF (test_for_result(results, description=description)) THEN
474 CALL get_results(results, description=description, values=dipole_moment)
475 ELSE
476 CALL cp_warn(__location__, "Debug of dipole moments needs DFT/PRINT/MOMENTS section enabled")
477 cpabort("DEBUG")
478 END IF
479 amplitude = de
480 DO k = 1, 3
481 IF (do_dof_dipole(k)) THEN
482 poldir = 0.0_dp
483 poldir(k) = 1.0_dp
484 DO j = 1, 2
485 poldir = -1.0_dp*poldir
486 CALL set_efield(dft_control, amplitude, poldir)
487 CALL force_env_calc_energy_force(force_env, calc_force=.false.)
488 CALL force_env_get(force_env, potential_energy=numer_energy(j))
489 END DO
490 dipole_numer(k) = 0.5_dp*(numer_energy(1) - numer_energy(2))/de
491 ELSE
492 dipole_numer(k) = 0.0_dp
493 END IF
494 END DO
495 IF (iw > 0) THEN
496 WRITE (unit=iw, fmt="(/,(T2,A))") &
497 "DEBUG|========================= DIPOLE MOMENTS ================================", &
498 "DEBUG| Coordinate D(numerical) D(analytical) Difference Error [%]"
499 err(1:3) = 0.0_dp
500 DO k = 1, 3
501 IF (do_dof_dipole(k)) THEN
502 dd = dipole_moment(k) - dipole_numer(k)
503 IF (abs(dipole_moment(k)) > eps_no_error_check) THEN
504 derr = 100._dp*dd/dipole_moment(k)
505 WRITE (unit=iw, fmt="(T2,A,T13,A1,T21,F16.8,T38,F16.8,T56,G12.3,T72,F9.3)") &
506 "DEBUG|", achar(119 + k), dipole_numer(k), dipole_moment(k), dd, derr
507 ELSE
508 derr = 0.0_dp
509 WRITE (unit=iw, fmt="(T2,A,T13,A1,T21,F16.8,T38,F16.8,T56,G12.3)") &
510 "DEBUG|", achar(119 + k), dipole_numer(k), dipole_moment(k), dd
511 END IF
512 err(k) = derr
513 ELSE
514 WRITE (unit=iw, fmt="(T2,A,T13,A1,T21,A16,T38,F16.8)") &
515 "DEBUG|", achar(119 + k), " skipped", dipole_moment(k)
516 END IF
517 END DO
518 WRITE (unit=iw, fmt="((T2,A))") &
519 "DEBUG|========================================================================="
520 WRITE (unit=iw, fmt="(T2,A,T61,E20.12)") 'DIPOLE : CheckSum =', sum(dipole_moment)
521 IF (any(abs(err(1:3)) > maxerr)) THEN
522 message = "A mismatch between analytical and numerical dipoles "// &
523 "has been detected. Check the implementation of the "// &
524 "analytical dipole calculation"
525 IF (stop_on_mismatch) THEN
526 cpabort(message)
527 ELSE
528 cpwarn(message)
529 END IF
530 END IF
531 END IF
532
533 ELSE
534 CALL cp_warn(__location__, "Debug of dipole moments only for Quickstep code available")
535 END IF
536 END IF
537
538 IF (debug_polar) THEN
539 IF (force_env%in_use == use_qs_force) THEN
540 CALL get_qs_env(force_env%qs_env, dft_control=dft_control)
541 poldir = [0.0_dp, 0.0_dp, 1.0_dp]
542 amplitude = 0.0_dp
543 CALL set_efield(dft_control, amplitude, poldir)
544 CALL force_env_calc_energy_force(force_env, calc_force=.false.)
545 CALL get_qs_env(force_env%qs_env, results=results)
546 description = "[POLAR]"
547 IF (test_for_result(results, description=description)) THEN
548 CALL get_results(results, description=description, values=pvals)
549 polar_analytic(1:3, 1:3) = reshape(pvals(1:9), [3, 3])
550 ELSE
551 CALL cp_warn(__location__, "Debug of polarizabilities needs PROPERTIES/LINRES/POLAR section enabled")
552 cpabort("DEBUG")
553 END IF
554 description = "[DIPOLE]"
555 IF (.NOT. test_for_result(results, description=description)) THEN
556 CALL cp_warn(__location__, "Debug of polarizabilities need DFT/PRINT/MOMENTS section enabled")
557 cpabort("DEBUG")
558 END IF
559 amplitude = de
560 DO k = 1, 3
561 poldir = 0.0_dp
562 poldir(k) = 1.0_dp
563 DO j = 1, 2
564 poldir = -1.0_dp*poldir
565 CALL set_efield(dft_control, amplitude, poldir)
566 CALL force_env_calc_energy_force(force_env, calc_force=.false., linres=.true.)
567 CALL get_results(results, description=description, values=dipn(1:3, j))
568 END DO
569 polar_numeric(1:3, k) = 0.5_dp*(dipn(1:3, 2) - dipn(1:3, 1))/de
570 END DO
571 IF (iw > 0) THEN
572 WRITE (unit=iw, fmt="(/,(T2,A))") &
573 "DEBUG|========================= POLARIZABILITY ================================", &
574 "DEBUG| Coordinates P(numerical) P(analytical) Difference Error [%]"
575 DO k = 1, 3
576 DO j = 1, 3
577 dd = polar_analytic(k, j) - polar_numeric(k, j)
578 IF (abs(polar_analytic(k, j)) > eps_no_error_check) THEN
579 derr = 100._dp*dd/polar_analytic(k, j)
580 WRITE (unit=iw, fmt="(T2,A,T12,A1,A1,T21,F16.8,T38,F16.8,T56,G12.3,T72,F9.3)") &
581 "DEBUG|", achar(119 + k), achar(119 + j), polar_numeric(k, j), polar_analytic(k, j), dd, derr
582 ELSE
583 WRITE (unit=iw, fmt="(T2,A,T12,A1,A1,T21,F16.8,T38,F16.8,T56,G12.3)") &
584 "DEBUG|", achar(119 + k), achar(119 + j), polar_numeric(k, j), polar_analytic(k, j), dd
585 END IF
586 END DO
587 END DO
588 WRITE (unit=iw, fmt="((T2,A))") &
589 "DEBUG|========================================================================="
590 WRITE (unit=iw, fmt="(T2,A,T61,E20.12)") ' POLAR : CheckSum =', sum(polar_analytic)
591 END IF
592 ELSE
593 CALL cp_warn(__location__, "Debug of polarizabilities only for Quickstep code available")
594 END IF
595 END IF
596
597 CALL cp_print_key_finished_output(iw, logger, root_section, "DEBUG%PROGRAM_RUN_INFO")
598
599 END SUBROUTINE cp2k_debug_energy_and_forces
600
601! **************************************************************************************************
602!> \brief ...
603!> \param dft_control ...
604!> \param amplitude ...
605!> \param poldir ...
606! **************************************************************************************************
607 SUBROUTINE set_efield(dft_control, amplitude, poldir)
608 TYPE(dft_control_type), POINTER :: dft_control
609 REAL(kind=dp), INTENT(IN) :: amplitude
610 REAL(kind=dp), DIMENSION(3), INTENT(IN) :: poldir
611
612 IF (dft_control%apply_efield) THEN
613 dft_control%efield_fields(1)%efield%strength = amplitude
614 dft_control%efield_fields(1)%efield%polarisation(1:3) = poldir(1:3)
615 ELSEIF (dft_control%apply_period_efield) THEN
616 dft_control%period_efield%strength = amplitude
617 dft_control%period_efield%polarisation(1:3) = poldir(1:3)
618 ELSE
619 cpabort("No EFIELD definition available")
620 END IF
621
622 END SUBROUTINE set_efield
623
624END MODULE cp2k_debug
Definition atom.F:9
Handles all functions related to the CELL.
Definition cell_types.F:15
subroutine, public get_cell(cell, alpha, beta, gamma, deth, orthorhombic, abc, periodic, h, h_inv, symmetry_id, tag)
Get informations about a simulation cell.
Definition cell_types.F:210
Debug energy and derivatives w.r.t. finite differences.
Definition cp2k_debug.F:26
subroutine, public cp2k_debug_energy_and_forces(force_env)
...
Definition cp2k_debug.F:77
Defines control structures, which contain the parameters and the settings for the DFT-based calculati...
various routines to log and control the output. The idea is that decisions about where to log should ...
type(cp_logger_type) function, pointer, public cp_get_default_logger()
returns the default logger
routines to handle the output, The idea is to remove the decision of wheter to output and what to out...
integer function, public cp_print_key_unit_nr(logger, basis_section, print_key_path, extension, middle_name, local, log_filename, ignore_should_output, file_form, file_position, file_action, file_status, do_backup, on_file, is_new_file, mpi_io, fout)
...
subroutine, public cp_print_key_finished_output(unit_nr, logger, basis_section, print_key_path, local, ignore_should_output, on_file, mpi_io)
should be called after you finish working with a unit obtained with cp_print_key_unit_nr,...
set of type/routines to handle the storage of results in force_envs
logical function, public test_for_result(results, description)
test for a certain result in the result_list
set of type/routines to handle the storage of results in force_envs
types that represent a subsys, i.e. a part of the system
subroutine, public cp_subsys_get(subsys, ref_count, atomic_kinds, atomic_kind_set, particles, particle_set, local_particles, molecules, molecule_set, molecule_kinds, molecule_kind_set, local_molecules, para_env, colvar_p, shell_particles, core_particles, gci, multipoles, natom, nparticle, ncore, nshell, nkind, atprop, virial, results, cell, cell_ref, use_ref_cell)
returns information about various attributes of the given subsys
Interface for the force calculations.
recursive subroutine, public force_env_calc_energy_force(force_env, calc_force, consistent_energies, skip_external_control, eval_energy_forces, require_consistent_energy_force, linres, calc_stress_tensor)
Interface routine for force and energy calculations.
subroutine, public force_env_calc_num_pressure(force_env, dx)
Evaluates the stress tensor and pressure numerically.
Interface for the force calculations.
recursive subroutine, public force_env_get(force_env, in_use, fist_env, qs_env, meta_env, fp_env, subsys, para_env, potential_energy, additional_potential, kinetic_energy, harmonic_shell, kinetic_shell, cell, sub_force_env, qmmm_env, qmmmx_env, eip_env, pwdft_env, globenv, input, force_env_section, method_name_id, root_section, mixed_env, nnp_env, embed_env, ipi_env)
returns various attributes about the force environment
integer, parameter, public use_qs_force
collects all constants needed in input so that they can be used without circular dependencies
integer, parameter, public do_stress_analytical
integer, parameter, public do_stress_diagonal_anal
integer, parameter, public do_stress_diagonal_numer
integer, parameter, public do_stress_numerical
objects that represent the structure of input sections and the data contained in an input section
recursive type(section_vals_type) function, pointer, public section_vals_get_subs_vals(section_vals, subsection_name, i_rep_section, can_return_null)
returns the values of the requested subsection
subroutine, public section_vals_val_get(section_vals, keyword_name, i_rep_section, i_rep_val, n_rep_val, val, l_val, i_val, r_val, c_val, l_vals, i_vals, r_vals, c_vals, explicit)
returns the requested value
Defines the basic variable types.
Definition kinds.F:23
integer, parameter, public dp
Definition kinds.F:34
integer, parameter, public default_string_length
Definition kinds.F:57
Interface to the message passing library MPI.
Define methods related to particle_type.
subroutine, public write_qs_particle_coordinates(particle_set, qs_kind_set, subsys_section, label)
Write the atomic coordinates to the output unit.
subroutine, public write_fist_particle_coordinates(particle_set, subsys_section, charges)
Write the atomic coordinates to the output unit.
Define the data structure for the particle information.
subroutine, public get_qs_env(qs_env, atomic_kind_set, qs_kind_set, cell, super_cell, cell_ref, use_ref_cell, kpoints, dft_control, mos, sab_orb, sab_all, qmmm, qmmm_periodic, mimic, sac_ae, sac_ppl, sac_lri, sap_ppnl, sab_vdw, sab_scp, sap_oce, sab_lrc, sab_se, sab_xtbe, sab_tbe, sab_core, sab_xb, sab_xtb_pp, sab_xtb_nonbond, sab_almo, sab_kp, sab_kp_nosym, sab_cneo, particle_set, energy, force, matrix_h, matrix_h_im, matrix_ks, matrix_ks_im, matrix_vxc, run_rtp, rtp, matrix_h_kp, matrix_h_im_kp, matrix_ks_kp, matrix_ks_im_kp, matrix_vxc_kp, kinetic_kp, matrix_s_kp, matrix_w_kp, matrix_s_ri_aux_kp, matrix_s, matrix_s_ri_aux, matrix_w, matrix_p_mp2, matrix_p_mp2_admm, rho, rho_xc, pw_env, ewald_env, ewald_pw, active_space, mpools, input, para_env, blacs_env, scf_control, rel_control, kinetic, qs_charges, vppl, xcint_weights, rho_core, rho_nlcc, rho_nlcc_g, ks_env, ks_qmmm_env, wf_history, scf_env, local_particles, local_molecules, distribution_2d, dbcsr_dist, molecule_kind_set, molecule_set, subsys, cp_subsys, oce, local_rho_set, rho_atom_set, task_list, task_list_soft, rho0_atom_set, rho0_mpole, rhoz_set, rhoz_cneo_set, ecoul_1c, rho0_s_rs, rho0_s_gs, rhoz_cneo_s_rs, rhoz_cneo_s_gs, do_kpoints, has_unit_metric, requires_mo_derivs, mo_derivs, mo_loc_history, nkind, natom, nelectron_total, nelectron_spin, efield, neighbor_list_id, linres_control, xas_env, virial, cp_ddapc_env, cp_ddapc_ewald, outer_scf_history, outer_scf_ihistory, x_data, et_coupling, dftb_potential, results, se_taper, se_store_int_env, se_nddo_mpole, se_nonbond_env, admm_env, lri_env, lri_density, exstate_env, ec_env, harris_env, dispersion_env, gcp_env, vee, rho_external, external_vxc, mask, mp2_env, bs_env, kg_env, wanniercentres, atprop, ls_scf_env, do_transport, transport_env, v_hartree_rspace, s_mstruct_changed, rho_changed, potential_changed, forces_up_to_date, mscfg_env, almo_scf_env, gradient_history, variable_history, embed_pot, spin_embed_pot, polar_env, mos_last_converged, eeq, rhs, do_rixs, tb_tblite)
Get the QUICKSTEP environment.
Define the quickstep kind type and their sub types.
Utilities for string manipulations.
elemental subroutine, public uppercase(string)
Convert all lower case characters in a string to upper case.
subroutine, public virial_set(virial, pv_total, pv_kinetic, pv_virial, pv_xc, pv_fock_4c, pv_constraint, pv_overlap, pv_ekinetic, pv_ppl, pv_ppnl, pv_ecore_overlap, pv_ehartree, pv_exc, pv_exx, pv_vdw, pv_mp2, pv_nlcc, pv_gapw, pv_lrigpw, pv_availability, pv_calculate, pv_numer, pv_diagonal)
...
Type defining parameters related to the simulation cell.
Definition cell_types.F:60
type of a logger, at the moment it contains just a print level starting at which level it should be l...
contains arbitrary information which need to be stored
represents a system: atoms, molecules, their pos,vel,...
wrapper to abstract the force evaluation of the various methods
stores all the informations relevant to an mpi environment
Provides all information about a quickstep kind.