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, &
87 INTEGER,
DIMENSION(3) :: periodic
88 LOGICAL :: check_failed, debug_dipole, &
89 debug_forces, debug_polar, &
90 debug_stress_tensor, skip, &
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, &
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
111 TYPE(
qs_kind_type),
DIMENSION(:),
POINTER :: qs_kind_set
114 NULLIFY (analyt_forces, numer_forces, subsys, particles)
116 root_section => force_env%root_section
118 CALL force_env_get(force_env, para_env=para_env, subsys=subsys, cell=cell)
123 l_val=debug_stress_tensor)
140 r_val=eps_no_error_check)
141 eps_no_error_check = max(eps_no_error_check, epsilon(0.0_dp))
143 l_val=stop_on_mismatch)
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)
151 IF (debug_forces)
THEN
152 np = subsys%particles%n_els
153 ALLOCATE (do_dof_atom_coor(3, np))
156 do_dof_atom_coor = .false.
160 READ (cval2(1), fmt=
"(I10)") k
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)
167 do_dof_atom_coor = .true.
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.")
186 SELECT CASE (stress_tensor)
191 CALL cp_warn(__location__,
"Numerical stress tensor was requested in "// &
192 "the FORCE_EVAL section. Nothing to debug!")
195 CALL cp_warn(__location__,
"Stress tensor calculation was not enabled in "// &
196 "the FORCE_EVAL section. Nothing to debug!")
203 TYPE(
virial_type) :: virial_analytical, virial_numerical
211 calc_stress_tensor=.true.)
214 virial_analytical = virial
222 virial_numerical = virial
225 IF (virial_analytical%pv_diagonal .OR. virial_numerical%pv_diagonal)
THEN
229 virial_analytical%pv_virial(i, k) = 0.0_dp
230 virial_numerical%pv_virial(i, k) = 0.0_dp
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.
243 check_stress_element(i, k) = periodic(i) /= 0 .AND. periodic(k) /= 0
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
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))
276 WRITE (unit=iw, fmt=
"(T2,A,T61,F20.12)") &
277 "DEBUG| Periodic-subspace sum of differences", periodic_stress_sum
282 check_failed = .false.
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
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),
" %"
298 WRITE (unit=line(20*(k - 1) + 1:20*k), fmt=
"(17X,A3)")
"- %"
302 WRITE (unit=iw, fmt=
"(T2,A,T21,A60)") &
305 IF (any(abs(err(1:3)) > maxerr)) check_failed = .true.
308 WRITE (unit=iw, fmt=
"(T2,A,T61,F18.2,A2)") &
309 "DEBUG| Maximum accepted error", maxerr,
" %"
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))
318 cpwarn(trim(message))
325 IF (debug_forces)
THEN
327 particles => subsys%particles%els
328 SELECT CASE (force_env%in_use)
330 CALL get_qs_env(force_env%qs_env, qs_kind_set=qs_kind_set)
338 calc_stress_tensor=.false.)
340 IF (
ASSOCIATED(analyt_forces))
DEALLOCATE (analyt_forces)
341 np = subsys%particles%n_els
342 ALLOCATE (analyt_forces(np, 3))
344 analyt_forces(ip, 1:3) = particles(ip)%f(1:3)
347 IF (
ASSOCIATED(numer_forces))
DEALLOCATE (numer_forces)
348 ALLOCATE (numer_forces(subsys%particles%n_els, 3))
351 IF (do_dof_atom_coor(k, ip))
THEN
352 numer_energy = 0.0_dp
353 std_value = particles(ip)%r(k)
355 particles(ip)%r(k) = std_value - (-1.0_dp)**j*dx
356 SELECT CASE (force_env%in_use)
358 CALL get_qs_env(force_env%qs_env, qs_kind_set=qs_kind_set)
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))
370 particles(ip)%r(k) = std_value
371 numer_forces(ip, k) = -0.5_dp*(numer_energy(1) - numer_energy(2))/dx
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)
381 numer_forces(ip, k) = 0.0_dp
388 IF (do_dof_atom_coor(k, ip))
THEN
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)
394 IF (abs(analyt_forces(ip, k)) <= 0.0001_dp) my_maxerr(k) = 5.0_dp*my_maxerr(k)
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 [%]"
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)
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,
"-"
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
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
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)
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,
"-"
449 sum_of_differences = sum_of_differences + abs(difference)
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 ================================="
459 IF (
ASSOCIATED(analyt_forces))
DEALLOCATE (analyt_forces)
460 IF (
ASSOCIATED(numer_forces))
DEALLOCATE (numer_forces)
461 DEALLOCATE (do_dof_atom_coor)
464 IF (debug_dipole)
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]
469 CALL set_efield(dft_control, amplitude, poldir)
471 CALL get_qs_env(force_env%qs_env, results=results)
472 description =
"[DIPOLE]"
474 CALL get_results(results, description=description, values=dipole_moment)
476 CALL cp_warn(__location__,
"Debug of dipole moments needs DFT/PRINT/MOMENTS section enabled")
481 IF (do_dof_dipole(k))
THEN
485 poldir = -1.0_dp*poldir
486 CALL set_efield(dft_control, amplitude, poldir)
488 CALL force_env_get(force_env, potential_energy=numer_energy(j))
490 dipole_numer(k) = 0.5_dp*(numer_energy(1) - numer_energy(2))/de
492 dipole_numer(k) = 0.0_dp
496 WRITE (unit=iw, fmt=
"(/,(T2,A))") &
497 "DEBUG|========================= DIPOLE MOMENTS ================================", &
498 "DEBUG| Coordinate D(numerical) D(analytical) Difference Error [%]"
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
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
514 WRITE (unit=iw, fmt=
"(T2,A,T13,A1,T21,A16,T38,F16.8)") &
515 "DEBUG|", achar(119 + k),
" skipped", dipole_moment(k)
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
534 CALL cp_warn(__location__,
"Debug of dipole moments only for Quickstep code available")
538 IF (debug_polar)
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]
543 CALL set_efield(dft_control, amplitude, poldir)
545 CALL get_qs_env(force_env%qs_env, results=results)
546 description =
"[POLAR]"
548 CALL get_results(results, description=description, values=pvals)
549 polar_analytic(1:3, 1:3) = reshape(pvals(1:9), [3, 3])
551 CALL cp_warn(__location__,
"Debug of polarizabilities needs PROPERTIES/LINRES/POLAR section enabled")
554 description =
"[DIPOLE]"
556 CALL cp_warn(__location__,
"Debug of polarizabilities need DFT/PRINT/MOMENTS section enabled")
564 poldir = -1.0_dp*poldir
565 CALL set_efield(dft_control, amplitude, poldir)
567 CALL get_results(results, description=description, values=dipn(1:3, j))
569 polar_numeric(1:3, k) = 0.5_dp*(dipn(1:3, 2) - dipn(1:3, 1))/de
572 WRITE (unit=iw, fmt=
"(/,(T2,A))") &
573 "DEBUG|========================= POLARIZABILITY ================================", &
574 "DEBUG| Coordinates P(numerical) P(analytical) Difference Error [%]"
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
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
588 WRITE (unit=iw, fmt=
"((T2,A))") &
589 "DEBUG|========================================================================="
590 WRITE (unit=iw, fmt=
"(T2,A,T61,E20.12)")
' POLAR : CheckSum =', sum(polar_analytic)
593 CALL cp_warn(__location__,
"Debug of polarizabilities only for Quickstep code available")
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.