From cccd2f3934e493480bb4fa3e20ffad257d26b523 Mon Sep 17 00:00:00 2001 From: Dynamics of Condensed Matter <30792324+DCM-Uni-Paderborn@users.noreply.github.com> Date: Wed, 6 May 2026 00:47:46 +0200 Subject: [PATCH] Fix TB gradients, virials, and k-point symmetry # Fix TB gradients, virials, tblite reference checks, and k-point symmetry ## Summary This PR continues the CP2K/tblite interface work originally started by Johann Pototschnig (`jpoto`) and relies in part on Sebastian Ehlert's `tblite` library. It makes the CP2K tight binding paths substantially more consistent for nuclear gradients, virials/stress tensors, and k-point symmetry, especially for DFTB, CP2K-native GFN0/GFN1, and `&XTB &TBLITE` GFN1/GFN2/IPEA1. Main changes: - fix several CP2K/tblite force and virial terms for periodic systems, - add a native `tblite` CLI reference path under `&XTB &TBLITE &REFERENCE_CLI`, - enable and test k-point symmetry reduction for CP2K-native TB and CP2K/tblite TB paths, - improve DFTB SCC/Ewald virials and update affected DFTB references, - add/extend regtests for molecular and truly periodic systems, including force/stress DEBUG checks, - update the CP2K toolchain patches for `tblite`/embedded DFTD4 and standalone DFTD4. ## User-visible input changes - `&DFT &XTB` can now select the library implementation via `GFN_TYPE TBLITE`; in that case an `&XTB &TBLITE` section is required. - `&XTB &TBLITE` supports `METHOD GFN1`, `METHOD GFN2`, and `METHOD IPEA1`. - `&XTB &TBLITE` has an optional `REFERENCE_CLI` keyword and a lone `&REFERENCE_CLI` subsection. If present/enabled, CP2K writes a `.gen` geometry, runs native `tblite run --grad`, and compares energy, gradient, and virial. - `SCC_MIXER TBLITE` is documented as a modified Broyden mixer; the associated controls are named `TBLITE_MIXER_DAMPING` and `TBLITE_MIXER_MAX_SCF`. - `DO_EWALD` remains available as a deprecated/debug override; the manual now documents the required periodic `POISSON` setup for CP2K-native DFTB/xTB and the `TBLITE` exception. - CP2K warns if `CELL%PERIODIC` and `POISSON%PERIODIC` differ, but still runs. ## What was fixed ### CP2K/tblite GFN1/GFN2/IPEA1 - Periodic image-cell matrix construction now fills all image cells instead of only image cell 1. - H0, overlap/potential, GFN2 multipole, CN-chain-rule, and D4-related virial paths were checked term by term against finite differences. - Periodic self-image virial signs/factors were corrected in the CP2K/tblite interface. - The previously bad strongly distorted Si8/GFN2 Gamma stress case was traced to a hard D4 two-body cutoff discontinuity and fixed by adding a smooth switching region in the D4 path. - `RUN_TYPE DEBUG` force/stress checks now behave consistently for molecular and periodic CP2K/tblite GFN1/GFN2 cases; isolated stress is allowed for tblite with a warning because it is a diagnostic virial, not a physical isolated-system stress. ### Native tblite CLI reference The `REFERENCE_CLI` path initially showed good molecular agreement but poor periodic virials for Ar-fcc: - GFN1 periodic virial diff was about `1.15e-2`, - GFN2 periodic virial diff was about `2.95e-2`. The parser, units, row order, and sign convention were checked and were correct. The remaining error was in native `tblite`: periodic H0 self-image pairs (`iat == jat`, non-zero translation) used the normal pair sigma factor `0.5`. The correct symmetrized cell-derivative factor for these self-image pairs is `0.25`. Updated `REFERENCE_CLI` comparison after the native tblite H0 sigma fix: | Case | SCF | Energy diff | Gradient diff sum/max | Virial diff sum/max | | --- | ---: | ---: | ---: | ---: | | CH2O/GFN1, molecular | 12 | `6.775398020409e-10` | `3.296429618975e-08` / `1.577689361792e-08` | `2.884140131919e-08` / `2.625531908551e-08` | | CH2O/GFN2, molecular | 15 | `6.651852402229e-10` | `1.437665769393e-07` / `6.050656990025e-08` | `1.240845506761e-07` / `8.358997352631e-08` | | Ar-fcc/GFN1, periodic | 7 | `3.595097552989e-09` | `1.125627343711e-09` / `3.688615600028e-10` | `5.441065574157e-09` / `1.653417298474e-09` | | Ar-fcc/GFN2, periodic | 20 | `8.975906240494e-09` | `2.140900031075e-08` / `4.424293700931e-09` | `3.094086449720e-07` / `8.057020835922e-08` | `REFERENCE_CLI` is intentionally skipped/guarded for CP2K multi-k-point runs: native `tblite` CLI is a useful Gamma reference, but it is not a CP2K-equivalent k-point/symmetry implementation. ### DFTB and CP2K-native xTB/GFN0/GFN1 - DFTB SCC/Ewald background handling was fixed so the homogeneous background contributes to energy and atomic properties without entering the SCC overlap virial as a constant potential shift. - The TB real-space Ewald self-image virial prefactor was fixed. - CP2K-native DFTB/GFN0/GFN1 k-point symmetry support was extended and tested with the CP2K atomic backend and SPGLIB backend. - Full atomic k-point symmetry is used for high-symmetry production geometries; for displaced DEBUG geometries the reduced symmetry is recomputed instead of reusing an invalid high-symmetry map. - DFTB3 forces, Gamma stress, k-point forces, and k-point stress were tested and covered by new regtests. ## What was tried The debugging was deliberately systematic rather than a single-code-path patch: - molecular and truly periodic crystals were checked separately; large vacuum cells were not used as periodic substitutes, - GFN1 and GFN2 were tested with tight `EPS_DEFAULT`/`EPS_SCF`, DX scans, and high `MAX_SCF`, - CP2K/tblite results were compared to native `tblite` CLI for energy, gradient, and virial, - H0, overlap/potential, Coulomb/multipole, CN-chain-rule, D4, D3/s-D3, DFTD4 and SCC/Ewald pieces were isolated where practical and checked against finite differences, - CP2K-native DFTB, DFTB3, GFN0, GFN1, CP2K/tblite GFN1/GFN2/IPEA1, and native `tblite` CLI were tested separately, - k-point full grids, CP2K atomic symmetry, SPGLIB symmetry, displaced atoms, skew cells, and MPI-rank reproducibility were checked, - 1D/2D periodicity, charged systems, and open-shell/spin behavior were probed. What helped: - restoring periodic H0/CN self-image contributions, - fixing self-image virial signs/factors, - fixing the native tblite H0 self-image sigma factor, - fixing the DFTB SCC/Ewald background gauge contribution, - recomputing k-point symmetry for lowered-symmetry DEBUG geometries, - smoothing the hard D4 two-body cutoff in the stress-sensitive GFN2/Si8 case, - updating the external library toolchain patches and DFTB reference values. What did not help or was not the root cause: - simply tightening `EPS_SCF`, `EPS_DEFAULT`, `DX`, or `MAX_SCF`, - changing only SCC damping/mixer parameters for the hard GFN2 stress cases, - treating the native `tblite` CLI periodic virial as authoritative before fixing its own H0 sigma self-image term, - using large vacuum boxes as stand-ins for true periodic crystals, - assuming all heteronuclear crystals are good regtests: several are dominated by overlap conditioning/SCF-state sensitivity rather than a clean force/stress bug. ## What works now - CP2K/tblite GFN1/GFN2 molecular force DEBUG checks are at `~1e-8`. - CP2K/tblite GFN2 isolated diagnostic stress is `~4e-9`. - CP2K/tblite GFN1/GFN2 Ar-fcc k-point force/stress DEBUG runs with `64 -> 4` k-point reduction. - CP2K/tblite GFN2 `PERIODIC XZ` Ar-layer k-point stress DEBUG is reduced from the reproduced `5.83e-4` remainder to `2.66e-5`; forces are `2.29e-6`. - CP2K/tblite GFN1/GFN2 skew/asym Si8 Gamma stress is now in the `~1e-6` range rather than `~1e-3`. - CP2K/tblite IPEA1 runs with k-point reduction and force/stress DEBUG coverage. - CP2K-native DFTB non-SCC/SCC and GFN0/GFN1 k-point symmetry paths pass the new tests. - DFTB3 force, Gamma stress, k-point force, and k-point stress tests pass. - DFTD4/DFTD3/D3(BJ) CP2K tests pass with the updated build; external DFTD4/tblite patches are ready for the toolchain. Representative final regtest values: | Path | Representative result | | --- | ---: | | CP2K/tblite GFN2 CH2O force DEBUG | `M042 = 1e-8` | | CP2K/tblite GFN2 CH2O isolated stress DEBUG | `M042 = 4.067e-9` | | CP2K/tblite GFN2 Si8 Gamma stress DEBUG | `M042 = 4.76966e-7` | | CP2K/tblite GFN2 Ar-fcc k-point stress DEBUG | `M042 = 3.33e-7`, `N_special_kpoints = 4` | | CP2K/tblite GFN2 Ar-layer XZ k-point stress DEBUG | `M042 = 2.66e-5`, `N_special_kpoints = 2` | | CP2K/tblite GFN1 Ar-fcc k-point stress DEBUG | `M042 = 1.6417e-8`, `N_special_kpoints = 4` | | CP2K/tblite IPEA1 Ar-fcc k-point stress DEBUG | `M042 = 2.4656e-8`, `N_special_kpoints = 4` | | CP2K-native GFN0 Si k-point symmetry | `N_special_kpoints = 4`; displaced geometry `12` | | DFTB non-SCC Si k-point stress | `M042 = 3.807e-9`, `N_special_kpoints = 4` | | DFTB SCC C k-point stress | `M042 = 5.409e-9` | | DFTB SCC ZnS k-point stress | `M042 = 2.18113e-7`, `N_special_kpoints = 4` | | DFTB3 H2O k-point stress | `M042 = 6.89e-10`, `N_special_kpoints = 4` | ## Remaining limitations - The reproduced `PERIODIC XZ` CP2K/tblite GFN2 Ar-layer k-point virial remainder is now much smaller (`2.66e-5` instead of `5.83e-4`), but not yet in the `1e-6` range; forces are good. - `PERIODIC X` full stress DEBUG is limited by the general CP2K cell/Poisson/stress machinery, not by a TB-specific quick fix. - CP2K/tblite open-shell/LSD still aborts intentionally: `LSD option not compatible with tblite library`. - Native `tblite` CLI remains a serial external Gamma-reference path; it is not a k-point/symmetry reference implementation. - Some heteronuclear CP2K/tblite crystals with k-points are sensitive to overlap conditioning and SCF state; Ar/Si remain the robust PR regtest choices. ## Verification - formatting: - `tools/precommit/format_fortran.py` on changed Fortran files, - `tools/precommit/format_input_file.py` on changed/new CP2K inputs, - `tools/precommit/precommit.py -m` on non-Fortran/non-input files. - patch checks: - `tblite-0.5.0-gradient-fixes.patch`: `patch -p1 --dry-run` against fresh `tblite-0.5.0`, - `dftd4-4.1.0-gradient-fixes.patch`: `patch -p1 --dry-run` against fresh `dftd4-4.1.0`. - build: - `cmake --build build-tblite-mpi-check --target cp2k-bin -- -j 8` - regtests with `mpiranks=2`, `ompthreads=1`: - `xTB/regtest-tblite-gfn2`, `xTB/regtest-tblite-gfn1-grad`, `xTB/regtest-tblite-ipea1`, `DFTB/regtest-scc-2`: `49 / 49` correct, - `DFTB/regtest-scc`, `DFTB/regtest-nonscc`: after updating affected references, `89 / 89` correct, - additionally checked in the same PR-ready run: `xTB/regtest-1`, `xTB/regtest-3`, `xTB/regtest-gfn0`, `QS/regtest-dft-vdw-corr-4`; those were green, with only the old DFTB references requiring the follow-up update above. --- src/CMakeLists.txt | 1 + src/cp2k_debug.F | 6 + src/cp2k_info.F | 3 + src/cp_control_types.F | 22 + src/cp_control_utils.F | 109 +- src/cryssym.F | 10 +- src/eeq_method.F | 4 +- src/ewald_environment_types.F | 86 +- src/ewald_methods_tb.F | 10 +- src/force_env_methods.F | 95 + src/input_constants.F | 9 +- src/input_cp2k_poisson.F | 1 - src/input_cp2k_tb.F | 209 +- src/kpoint_types.F | 112 +- src/qs_charge_mixing.F | 182 +- src/qs_density_mixing_types.F | 61 +- src/qs_dftb_coulomb.F | 84 +- src/qs_dftb_matrices.F | 27 +- src/qs_dispersion_cnum.F | 7 +- src/qs_environment.F | 60 +- src/qs_environment_methods.F | 3 +- src/qs_force.F | 7 +- src/qs_mixing_utils.F | 14 +- src/qs_scf.F | 46 +- src/qs_scf_loop_utils.F | 23 +- src/qs_tddfpt2_stda_utils.F | 3 +- src/qs_wf_history_types.F | 28 +- src/tblite_interface.F | 2277 +++++++++++++++-- src/tblite_types.F | 5 + src/xtb_ks_matrix.F | 6 +- tests/DFTB/regtest-nonscc/TEST_FILES.toml | 32 +- tests/DFTB/regtest-nonscc/ch2o_force.inp | 55 + .../regtest-nonscc/si_kp1_kpsym_atomdisp.inp | 62 + tests/DFTB/regtest-nonscc/si_kp_stress.inp | 71 + tests/DFTB/regtest-scc-2/TEST_FILES.toml | 6 + tests/DFTB/regtest-scc-2/dftb3_h2o_force.inp | 68 + .../regtest-scc-2/dftb3_h2o_gamma_stress.inp | 79 + .../DFTB/regtest-scc-2/dftb3_h2o_kp_force.inp | 83 + .../regtest-scc-2/dftb3_h2o_kp_stress.inp | 85 + tests/DFTB/regtest-scc/TEST_FILES.toml | 40 +- tests/DFTB/regtest-scc/c_kp1_kpsym.inp | 3 +- .../regtest-scc/c_kp1_kpsym_debug_stress.inp | 76 + .../DFTB/regtest-scc/c_kp1_spglib_backend.inp | 72 + tests/DFTB/regtest-scc/c_kp2_stress.inp | 85 + tests/DFTB/regtest-scc/ch2o_force.inp | 67 + tests/DFTB/regtest-scc/ch2o_tblite_mixer.inp | 51 + tests/DFTB/regtest-scc/zns_kp2_stress.inp | 81 + tests/DFTB/regtest-vdw/TEST_FILES.toml | 8 +- .../QS/regtest-dft-vdw-corr-1/TEST_FILES.toml | 2 +- tests/QS/regtest-dm-ls-scf-1/TEST_FILES.toml | 6 +- tests/QS/regtest-dm-ls-scf-2/TEST_FILES.toml | 6 +- tests/QS/regtest-dm-ls-scf-3/TEST_FILES.toml | 8 +- tests/QS/regtest-gpw-9/TEST_FILES.toml | 8 +- tests/QS/regtest-rma-3D/TEST_FILES.toml | 4 +- tests/QS/regtest-rma/TEST_FILES.toml | 4 +- tests/QS/regtest-spgr-id/quartz.inp | 3 + tests/QS/regtest-spgr/quartz.inp | 3 + tests/QS/regtest-stda-force/TEST_FILES.toml | 2 +- tests/QS/regtest-stress/TEST_FILES.toml | 2 +- tests/QS/regtest-tddfpt-stda/TEST_FILES.toml | 2 +- tests/SE/regtest-2-2/TEST_FILES.toml | 2 +- tests/matchers.py | 40 +- tests/xTB/regtest-1/TEST_FILES.toml | 9 +- tests/xTB/regtest-1/ch2o_scc_mixer_tblite.inp | 43 + tests/xTB/regtest-1/si_kp.inp | 9 +- tests/xTB/regtest-2/TEST_FILES.toml | 4 +- tests/xTB/regtest-3/TEST_FILES.toml | 18 +- tests/xTB/regtest-3/si_band.inp | 14 +- tests/xTB/regtest-3/si_dos.inp | 14 +- tests/xTB/regtest-3/si_kp_kpsym.inp | 3 +- tests/xTB/regtest-3/si_kp_spglib_backend.inp | 3 +- tests/xTB/regtest-3/si_print.inp | 14 +- tests/xTB/regtest-4/TEST_FILES.toml | 4 +- tests/xTB/regtest-5/Ru_geo.inp | 3 +- tests/xTB/regtest-5/TEST_FILES.toml | 4 +- tests/xTB/regtest-debug/TEST_FILES.toml | 10 +- tests/xTB/regtest-gfn0/TEST_FILES.toml | 19 +- tests/xTB/regtest-gfn0/si_kp_kpsym.inp | 82 + .../xTB/regtest-gfn0/si_kp_kpsym_atomdisp.inp | 82 + .../regtest-gfn0/si_kp_kpsym_debug_stress.inp | 84 + .../xTB/regtest-gfn0/si_kp_spglib_backend.inp | 83 + .../si_kp_spglib_reduction_atomdisp.inp | 83 + tests/xTB/regtest-gfn1-d/TEST_FILES.toml | 1 + tests/xTB/regtest-gfn1-d/ch2o_cn_stress.inp | 53 + tests/xTB/regtest-stda-force/TEST_FILES.toml | 2 +- .../Ar_fcc_gfn1_kp_debug.inp | 61 + .../CH2O_gfn1_force.inp | 1 + .../COBe_gfn1_fd_force.inp | 1 + .../Si_gfn1_fd_force.inp | 1 + .../Si_gfn1_fd_stress.inp | 65 + .../regtest-tblite-gfn1-grad/TEST_FILES.toml | 4 + .../CH2O_gfn1.inp | 1 + .../COBe_gfn1_fd.inp | 1 + .../Si_gfn1_fd.inp | 1 + .../Si_gfn1_kp.inp | 61 + .../Si_gfn1_kp_kpsym.inp | 68 + .../TEST_FILES.toml | 5 +- tests/xTB/regtest-tblite-gfn1/CH2O_gfn1.inp | 1 + tests/xTB/regtest-tblite-gfn1/COBe_gfn1.inp | 1 + .../regtest-tblite-gfn1/COBe_gfn1_force.inp | 4 +- tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1.inp | 1 + .../regtest-tblite-gfn1/H2SO4_gfn1_force.inp | 4 +- tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1.inp | 1 + .../regtest-tblite-gfn1/Hg2Cl2_gfn1_force.inp | 4 +- .../regtest-tblite-gfn2/Ar_fcc_gfn2_force.inp | 54 + .../Ar_fcc_gfn2_kp_debug.inp | 61 + .../Ar_fcc_gfn2_stress.inp | 58 + .../Ar_layer_gfn2_xz_kp_debug.inp | 61 + tests/xTB/regtest-tblite-gfn2/CH2O_gfn2.inp | 1 + .../regtest-tblite-gfn2/CH2O_gfn2_force.inp | 4 +- .../CH2O_gfn2_force_cp2k_mixer.inp | 47 + .../CH2O_gfn2_reference_cli_lone.inp | 47 + .../regtest-tblite-gfn2/CH2O_gfn2_stress.inp | 50 + tests/xTB/regtest-tblite-gfn2/COBe_gfn2.inp | 1 + .../regtest-tblite-gfn2/COBe_gfn2_force.inp | 4 +- tests/xTB/regtest-tblite-gfn2/H2SO4_gfn2.inp | 1 + .../regtest-tblite-gfn2/Hg2Cl2_gfn2_force.inp | 2 +- tests/xTB/regtest-tblite-gfn2/NH3_gfn2.inp | 1 + .../regtest-tblite-gfn2/Si_gfn2_fd_force.inp | 73 + .../regtest-tblite-gfn2/Si_gfn2_fd_stress.inp | 66 + .../regtest-tblite-gfn2/Si_gfn2_kp_kpsym.inp | 68 + tests/xTB/regtest-tblite-gfn2/TEST_FILES.toml | 16 + .../Ar_fcc_ipea1_kp_debug.inp | 61 + tests/xTB/regtest-tblite-ipea1/CH2O_ipea1.inp | 1 + .../regtest-tblite-ipea1/CH2O_ipea1_force.inp | 4 +- tests/xTB/regtest-tblite-ipea1/COBe_ipea1.inp | 1 + .../regtest-tblite-ipea1/COBe_ipea1_force.inp | 4 +- .../xTB/regtest-tblite-ipea1/H2SO4_ipea1.inp | 1 + .../Si_ipea1_kp_kpsym.inp | 68 + .../xTB/regtest-tblite-ipea1/TEST_FILES.toml | 5 + .../stage8/dftd4-4.1.1-gradient-fixes.patch | 766 ++++++ .../toolchain/scripts/stage8/install_dftd4.sh | 34 +- .../scripts/stage8/install_tblite.sh | 67 +- .../simple-dftd3-1.3.2-gradient-fixes.patch | 1408 ++++++++++ .../stage8/tblite-0.5.0-gradient-fixes.patch | 521 ++++ 135 files changed, 8606 insertions(+), 503 deletions(-) create mode 100644 tests/DFTB/regtest-nonscc/ch2o_force.inp create mode 100644 tests/DFTB/regtest-nonscc/si_kp1_kpsym_atomdisp.inp create mode 100644 tests/DFTB/regtest-nonscc/si_kp_stress.inp create mode 100644 tests/DFTB/regtest-scc-2/dftb3_h2o_force.inp create mode 100644 tests/DFTB/regtest-scc-2/dftb3_h2o_gamma_stress.inp create mode 100644 tests/DFTB/regtest-scc-2/dftb3_h2o_kp_force.inp create mode 100644 tests/DFTB/regtest-scc-2/dftb3_h2o_kp_stress.inp create mode 100644 tests/DFTB/regtest-scc/c_kp1_kpsym_debug_stress.inp create mode 100644 tests/DFTB/regtest-scc/c_kp1_spglib_backend.inp create mode 100644 tests/DFTB/regtest-scc/c_kp2_stress.inp create mode 100644 tests/DFTB/regtest-scc/ch2o_force.inp create mode 100644 tests/DFTB/regtest-scc/ch2o_tblite_mixer.inp create mode 100644 tests/DFTB/regtest-scc/zns_kp2_stress.inp create mode 100644 tests/xTB/regtest-1/ch2o_scc_mixer_tblite.inp create mode 100644 tests/xTB/regtest-gfn0/si_kp_kpsym.inp create mode 100644 tests/xTB/regtest-gfn0/si_kp_kpsym_atomdisp.inp create mode 100644 tests/xTB/regtest-gfn0/si_kp_kpsym_debug_stress.inp create mode 100644 tests/xTB/regtest-gfn0/si_kp_spglib_backend.inp create mode 100644 tests/xTB/regtest-gfn0/si_kp_spglib_reduction_atomdisp.inp create mode 100644 tests/xTB/regtest-gfn1-d/ch2o_cn_stress.inp create mode 100644 tests/xTB/regtest-tblite-gfn1-grad/Ar_fcc_gfn1_kp_debug.inp create mode 100644 tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_stress.inp create mode 100644 tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp.inp create mode 100644 tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp_kpsym.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_force.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_kp_debug.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_stress.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Ar_layer_gfn2_xz_kp_debug.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force_cp2k_mixer.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_reference_cli_lone.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_stress.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_force.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_stress.inp create mode 100644 tests/xTB/regtest-tblite-gfn2/Si_gfn2_kp_kpsym.inp create mode 100644 tests/xTB/regtest-tblite-ipea1/Ar_fcc_ipea1_kp_debug.inp create mode 100644 tests/xTB/regtest-tblite-ipea1/Si_ipea1_kp_kpsym.inp create mode 100644 tools/toolchain/scripts/stage8/dftd4-4.1.1-gradient-fixes.patch create mode 100644 tools/toolchain/scripts/stage8/simple-dftd3-1.3.2-gradient-fixes.patch create mode 100644 tools/toolchain/scripts/stage8/tblite-0.5.0-gradient-fixes.patch diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f9624387b0..dfc5857633 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1792,6 +1792,7 @@ target_compile_definitions( $<$:__SPGLIB> $<$:__SMEAGOL> $<$:__TBLITE> + # Developer-only manual flag: __TBLITE_DEBUG_DIAGNOSTICS $<$:__DFTD4> $<$:__DFTD4> $<$:__DFTD4_V3> diff --git a/src/cp2k_debug.F b/src/cp2k_debug.F index 9080b34cab..856b32101e 100644 --- a/src/cp2k_debug.F +++ b/src/cp2k_debug.F @@ -170,6 +170,12 @@ CONTAINS iw = cp_print_key_unit_nr(logger, root_section, "DEBUG%PROGRAM_RUN_INFO", & extension=".log") IF (debug_stress_tensor) THEN + IF (SUM(cell%perd) == 0) THEN + CALL cp_warn(__LOCATION__, & + "DEBUG_STRESS_TENSOR requested for PERIODIC NONE. "// & + "The isolated-system virial is useful for finite-difference diagnostics, "// & + "but it is not a physically meaningful bulk stress.") + END IF ! To debug stress tensor the stress tensor calculation must be ! first enabled.. CALL section_vals_val_get(force_env%force_env_section, "STRESS_TENSOR", & diff --git a/src/cp2k_info.F b/src/cp2k_info.F index 4fba957b4d..eaa48e1581 100644 --- a/src/cp2k_info.F +++ b/src/cp2k_info.F @@ -200,6 +200,9 @@ CONTAINS flags = TRIM(flags)//" mctc-lib" flags = TRIM(flags)//" tblite" #endif +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + flags = TRIM(flags)//" tblite_debug_diagnostics" +#endif #if defined(__SIRIUS) flags = TRIM(flags)//" sirius" #endif diff --git a/src/cp_control_types.F b/src/cp_control_types.F index ef0ab9dbc1..b82292df1f 100644 --- a/src/cp_control_types.F +++ b/src/cp_control_types.F @@ -16,6 +16,7 @@ MODULE cp_control_types USE input_constants, ONLY: do_full_density,& rtp_bse_ham_G0W0,& rtp_method_tddft,& + tblite_scc_mixer_auto,& use_mom_ref_coac USE kinds, ONLY: default_path_length,& default_string_length,& @@ -149,10 +150,12 @@ MODULE cp_control_types LOGICAL :: self_consistent = .FALSE. LOGICAL :: orthogonal_basis = .FALSE. LOGICAL :: dispersion = .FALSE. + INTEGER :: tblite_scc_mixer = tblite_scc_mixer_auto INTEGER :: dispersion_type = 0 LOGICAL :: dftb3_diagonal = .FALSE. LOGICAL :: hb_sr_damp = .FALSE. REAL(KIND=dp) :: hb_sr_para = 0.0_dp + REAL(KIND=dp) :: tblite_mixer_damping = 0.4_dp REAL(KIND=dp) :: eps_disp = 0.0_dp REAL(KIND=dp) :: epscn = 0.0_dp REAL(KIND=dp) :: exp_pre = 0.0_dp @@ -172,6 +175,21 @@ MODULE cp_control_types ! ************************************************************************************************** ! \brief Control parameters for xTB calculations ! ************************************************************************************************** + TYPE xtb_reference_cli_type + LOGICAL :: enabled = .FALSE. + LOGICAL :: check_energy = .TRUE. + LOGICAL :: check_forces = .TRUE. + LOGICAL :: check_virial = .FALSE. + LOGICAL :: keep_files = .FALSE. + LOGICAL :: stop_on_error = .FALSE. + INTEGER :: iterations = 250 + REAL(KIND=dp) :: accuracy = 1.0_dp + REAL(KIND=dp) :: error_limit = 1.0E-8_dp + CHARACTER(LEN=default_path_length) :: program_name = "tblite" + CHARACTER(LEN=default_path_length) :: work_directory = "." + CHARACTER(LEN=default_path_length) :: prefix = "tblite-reference" + END TYPE xtb_reference_cli_type + TYPE xtb_control_type ! INTEGER :: gfn_type = 1 @@ -182,6 +200,8 @@ MODULE cp_control_types INTEGER :: sto_ng = 0 INTEGER :: h_sto_ng = 0 INTEGER :: tblite_method = 0 + INTEGER :: tblite_scc_mixer = tblite_scc_mixer_auto + REAL(KIND=dp) :: tblite_mixer_damping = 0.4_dp ! INTEGER :: vdw_type = -1 CHARACTER(LEN=default_path_length) :: parameter_file_path = "" @@ -232,6 +252,7 @@ MODULE cp_control_types ! EN shift in EEQ (molecular=1 or crystaline=2) INTEGER :: enshift_type = 1 TYPE(eeq_solver_type) :: eeq_sparam ! parameters for EEQ solver + TYPE(xtb_reference_cli_type) :: reference_cli END TYPE xtb_control_type ! ************************************************************************************************** @@ -714,6 +735,7 @@ MODULE cp_control_types ddapc_restraint_type, & dftb_control_type, & xtb_control_type, & + xtb_reference_cli_type, & semi_empirical_control_type, & s2_restraint_type, & admm_control_type, & diff --git a/src/cp_control_utils.F b/src/cp_control_utils.F index 2699e369fa..cf4df5a548 100644 --- a/src/cp_control_utils.F +++ b/src/cp_control_utils.F @@ -19,7 +19,7 @@ MODULE cp_control_utils admm_control_create, admm_control_type, ddapc_control_create, ddapc_restraint_type, & dft_control_create, dft_control_type, efield_type, expot_control_create, & maxwell_control_create, qs_control_type, rixs_control_type, tddfpt2_control_type, & - xtb_control_type + xtb_control_type, xtb_reference_cli_type USE cp_files, ONLY: close_file,& open_file USE cp_log_handling, ONLY: cp_get_default_logger,& @@ -53,12 +53,13 @@ MODULE cp_control_utils do_pwgrid_spherical, do_s2_constraint, do_s2_restraint, do_se_is_kdso, do_se_is_kdso_d, & do_se_is_slater, do_se_lr_ewald, do_se_lr_ewald_gks, do_se_lr_ewald_r3, do_se_lr_none, & gapw_1c_large, gapw_1c_medium, gapw_1c_orb, gapw_1c_small, gapw_1c_very_large, & - gaussian_env, kg_tnadd_embed, kg_tnadd_embed_ri, no_admm_type, numerical, ramp_env, & - real_time_propagation, rtp_method_bse, sccs_andreussi, sccs_derivative_cd3, & - sccs_derivative_cd5, sccs_derivative_cd7, sccs_derivative_fft, sccs_fattebert_gygi, & - sic_ad, sic_eo, sic_list_all, sic_list_unpaired, sic_mauri_spz, sic_mauri_us, sic_none, & - slater, tddfpt_dipole_length, tddfpt_kernel_stda, use_mom_ref_user, xtb_vdw_type_d3, & - xtb_vdw_type_d4, xtb_vdw_type_none + gaussian_env, gfn1xtb, gfn_tblite, kg_tnadd_embed, kg_tnadd_embed_ri, no_admm_type, & + numerical, ramp_env, real_time_propagation, rtp_method_bse, sccs_andreussi, & + sccs_derivative_cd3, sccs_derivative_cd5, sccs_derivative_cd7, sccs_derivative_fft, & + sccs_fattebert_gygi, sic_ad, sic_eo, sic_list_all, sic_list_unpaired, sic_mauri_spz, & + sic_mauri_us, sic_none, slater, tblite_scc_mixer_auto, tblite_scc_mixer_cp2k, & + tblite_scc_mixer_none, tblite_scc_mixer_tblite, tddfpt_dipole_length, tddfpt_kernel_stda, & + use_mom_ref_user, xtb_vdw_type_d3, xtb_vdw_type_d4, xtb_vdw_type_none USE input_cp2k_check, ONLY: xc_functionals_expand USE input_cp2k_dft, ONLY: create_dft_section USE input_enumeration_types, ONLY: enum_i2c,& @@ -870,20 +871,22 @@ CONTAINS INTEGER :: handle, itmp, j, jj, k, n_rep, n_var, & ngauss, ngp, nrep INTEGER, DIMENSION(:), POINTER :: tmplist - LOGICAL :: explicit, was_present + LOGICAL :: explicit, tblite_reference_cli, & + tblite_reference_cli_section, & + tblite_section_active, was_present REAL(dp) :: tmp, tmpsqrt, value REAL(dp), POINTER :: scal(:) TYPE(section_vals_type), POINTER :: cdft_control_section, ddapc_restraint_section, & dftb_parameter, dftb_section, eeq_section, genpot_section, lri_optbas_section, & mull_section, nonbonded_section, s2_restraint_section, se_section, xtb_parameter, & - xtb_section, xtb_tblite + xtb_section, xtb_tblite, xtb_tblite_ref_cli CALL timeset(routineN, handle) was_present = .FALSE. NULLIFY (mull_section, ddapc_restraint_section, s2_restraint_section, & se_section, dftb_section, xtb_section, dftb_parameter, xtb_parameter, lri_optbas_section, & - cdft_control_section, genpot_section, eeq_section) + cdft_control_section, genpot_section, eeq_section, xtb_tblite_ref_cli) mull_section => section_vals_get_subs_vals(qs_section, "MULLIKEN_RESTRAINT") ddapc_restraint_section => section_vals_get_subs_vals(qs_section, "DDAPC_RESTRAINT") @@ -899,6 +902,7 @@ CONTAINS nonbonded_section => section_vals_get_subs_vals(xtb_section, "NONBONDED") genpot_section => section_vals_get_subs_vals(nonbonded_section, "GENPOT") xtb_tblite => section_vals_get_subs_vals(xtb_section, "TBLITE") + xtb_tblite_ref_cli => section_vals_get_subs_vals(xtb_tblite, "REFERENCE_CLI") ! Setup all defaults values and overwrite input parameters ! EPS_DEFAULT should set the target accuracy in the total energy (~per electron) or a closely related value @@ -1290,6 +1294,10 @@ CONTAINS l_val=qs_control%dftb_control%dftb3_diagonal) CALL section_vals_val_get(dftb_section, "HB_SR_GAMMA", & l_val=qs_control%dftb_control%hb_sr_damp) + CALL section_vals_val_get(dftb_section, "SCC_MIXER", & + i_val=qs_control%dftb_control%tblite_scc_mixer) + CALL section_vals_val_get(dftb_section, "TBLITE_MIXER_DAMPING", & + r_val=qs_control%dftb_control%tblite_mixer_damping) CALL section_vals_val_get(dftb_section, "EPS_DISP", & r_val=qs_control%dftb_control%eps_disp) CALL section_vals_val_get(dftb_section, "DO_EWALD", explicit=explicit) @@ -1346,6 +1354,20 @@ CONTAINS ! xTB code IF (qs_control%xtb) THEN CALL section_vals_val_get(xtb_section, "GFN_TYPE", i_val=qs_control%xtb_control%gfn_type) + CALL section_vals_val_get(xtb_tblite, "_SECTION_PARAMETERS_", l_val=tblite_section_active) + qs_control%xtb_control%do_tblite = (qs_control%xtb_control%gfn_type == gfn_tblite) + IF (qs_control%xtb_control%do_tblite) THEN + IF (.NOT. tblite_section_active) & + CPABORT("XTB/GFN_TYPE TBLITE requires an XTB/TBLITE section") + ! The CP2K-internal GFN1 defaults are still used to initialize shared xTB fields. + qs_control%xtb_control%gfn_type = gfn1xtb + ELSE IF (tblite_section_active) THEN + CPABORT("The XTB/TBLITE section requires XTB/GFN_TYPE TBLITE") + END IF + CALL section_vals_val_get(xtb_section, "SCC_MIXER", & + i_val=qs_control%xtb_control%tblite_scc_mixer) + CALL section_vals_val_get(xtb_section, "TBLITE_MIXER_DAMPING", & + r_val=qs_control%xtb_control%tblite_mixer_damping) CALL section_vals_val_get(xtb_section, "DO_EWALD", explicit=explicit) IF (explicit) THEN CALL section_vals_val_get(xtb_section, "DO_EWALD", & @@ -1652,30 +1674,64 @@ CONTAINS ! EEQ solver params CALL read_eeq_param(eeq_section, qs_control%xtb_control%eeq_sparam) - END IF ! Optimize LRI basis set CALL section_vals_get(lri_optbas_section, explicit=qs_control%lri_optbas) - ! Use instead the tblite - CALL section_vals_val_get(xtb_tblite, "_SECTION_PARAMETERS_", & - l_val=qs_control%xtb_control%do_tblite) - CALL section_vals_val_get(xtb_tblite, "METHOD", & - i_val=qs_control%xtb_control%tblite_method) + ! Use tblite if selected through XTB/GFN_TYPE TBLITE. IF (qs_control%xtb_control%do_tblite) THEN + CALL section_vals_val_get(xtb_tblite, "METHOD", & + i_val=qs_control%xtb_control%tblite_method) + CALL section_vals_val_get(xtb_tblite, "SCC_MIXER", & + i_val=qs_control%xtb_control%tblite_scc_mixer) + CALL section_vals_val_get(xtb_tblite, "TBLITE_MIXER_DAMPING", & + r_val=qs_control%xtb_control%tblite_mixer_damping) + CALL section_vals_val_get(xtb_tblite, "REFERENCE_CLI", l_val=tblite_reference_cli) + CALL section_vals_get(xtb_tblite_ref_cli, explicit=tblite_reference_cli_section) + IF (tblite_reference_cli .AND. (.NOT. tblite_reference_cli_section)) & + CPABORT("XTB/TBLITE/REFERENCE_CLI keyword requires an XTB/TBLITE/REFERENCE_CLI section") + IF (tblite_reference_cli .OR. tblite_reference_cli_section) THEN + CALL read_xtb_reference_cli_section(xtb_tblite_ref_cli, qs_control%xtb_control%reference_cli) + qs_control%xtb_control%reference_cli%enabled = .TRUE. + END IF CALL cite_reference(Caldeweyher2017) CALL cite_reference(Caldeweyher2020) CALL cite_reference(Asgeirsson2017) CALL cite_reference(Grimme2017) CALL cite_reference(Bannwarth2019) - !Ewald sum included in tblite - qs_control%xtb_control%do_ewald = .FALSE. + ! tblite handles periodic long-range terms internally from the CP2K cell periodicity. + ! Keep xtb_control%do_ewald as read above from XTB/DO_EWALD or SUBSYS/CELL/PERIODIC, + ! matching the DFTB and CP2K-internal xTB setup. END IF CALL timestop(handle) END SUBROUTINE read_qs_section +! ************************************************************************************************** +!> \brief Read native tblite CLI reference options. +!> \param ref_cli_section input section +!> \param ref_cli reference CLI control data +! ************************************************************************************************** + SUBROUTINE read_xtb_reference_cli_section(ref_cli_section, ref_cli) + TYPE(section_vals_type), POINTER :: ref_cli_section + TYPE(xtb_reference_cli_type), INTENT(INOUT) :: ref_cli + + CALL section_vals_val_get(ref_cli_section, "_SECTION_PARAMETERS_", l_val=ref_cli%enabled) + CALL section_vals_val_get(ref_cli_section, "PROGRAM_NAME", c_val=ref_cli%program_name) + CALL section_vals_val_get(ref_cli_section, "WORK_DIRECTORY", c_val=ref_cli%work_directory) + CALL section_vals_val_get(ref_cli_section, "PREFIX", c_val=ref_cli%prefix) + CALL section_vals_val_get(ref_cli_section, "KEEP_FILES", l_val=ref_cli%keep_files) + CALL section_vals_val_get(ref_cli_section, "ERROR_LIMIT", r_val=ref_cli%error_limit) + CALL section_vals_val_get(ref_cli_section, "STOP_ON_ERROR", l_val=ref_cli%stop_on_error) + CALL section_vals_val_get(ref_cli_section, "CHECK_ENERGY", l_val=ref_cli%check_energy) + CALL section_vals_val_get(ref_cli_section, "CHECK_FORCES", l_val=ref_cli%check_forces) + CALL section_vals_val_get(ref_cli_section, "CHECK_VIRIAL", l_val=ref_cli%check_virial) + CALL section_vals_val_get(ref_cli_section, "ACCURACY", r_val=ref_cli%accuracy) + CALL section_vals_val_get(ref_cli_section, "ITERATIONS", i_val=ref_cli%iterations) + + END SUBROUTINE read_xtb_reference_cli_section + ! ************************************************************************************************** !> \brief Read TDDFPT-related input parameters. !> \param t_control TDDFPT control parameters @@ -2302,6 +2358,7 @@ CONTAINS CHARACTER(len=*), PARAMETER :: routineN = 'write_xtb_control' + CHARACTER(LEN=16) :: scc_mixer_name INTEGER :: handle, output_unit TYPE(cp_logger_type), POINTER :: logger @@ -2359,6 +2416,22 @@ CONTAINS "xTB| Electronegativity scaling", xtb_control%ken WRITE (UNIT=output_unit, FMT="(T2,A,T61,2F10.3)") & "xTB| Halogen potential scaling kxr kx2", xtb_control%kxr, xtb_control%kx2 + SELECT CASE (xtb_control%tblite_scc_mixer) + CASE (tblite_scc_mixer_auto) + scc_mixer_name = "AUTO" + CASE (tblite_scc_mixer_tblite) + scc_mixer_name = "TBLITE" + CASE (tblite_scc_mixer_cp2k) + scc_mixer_name = "CP2K" + CASE (tblite_scc_mixer_none) + scc_mixer_name = "NONE" + CASE DEFAULT + CPABORT("Unknown tblite SCC mixer") + END SELECT + WRITE (UNIT=output_unit, FMT="(T2,A,T72,A)") & + "xTB| SCC mixer:", TRIM(scc_mixer_name) + WRITE (UNIT=output_unit, FMT="(T2,A,T71,F10.3)") & + "xTB| tblite SCC mixer damping:", xtb_control%tblite_mixer_damping WRITE (UNIT=output_unit, FMT="(/)") END IF diff --git a/src/cryssym.F b/src/cryssym.F index 814895072a..f70259e00e 100644 --- a/src/cryssym.F +++ b/src/cryssym.F @@ -973,14 +973,16 @@ CONTAINS valid = .FALSE. DO iop = 1, csym%nrtot - kr = csym%ibrot(iop) - IF (kr < 1 .OR. kr > SIZE(csym%rt, 3)) CYCLE + IF (iop > SIZE(csym%rt, 3)) CYCLE + IF (csym%ibrot(iop) == 0) CYCLE DO ibsign = 1, 2 wcart(1:3) = alat*(xref(1)*b1(1:3) + xref(2)*b2(1:3) + xref(3)*b3(1:3)) - wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, kr)) + wcart(1:3) = kp_apply_operation(wcart(1:3), csym%rt(1:3, 1:3, iop)) IF (ibsign == 2) THEN wcart(1:3) = -wcart(1:3) - kr = -kr + kr = -csym%ibrot(iop) + ELSE + kr = csym%ibrot(iop) END IF rr(1) = DOT_PRODUCT(a1(1:3), wcart(1:3))/alat rr(2) = DOT_PRODUCT(a2(1:3), wcart(1:3))/alat diff --git a/src/eeq_method.F b/src/eeq_method.F index 5fdfc22ff0..7e86e08ea0 100644 --- a/src/eeq_method.F +++ b/src/eeq_method.F @@ -335,7 +335,7 @@ CONTAINS print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION") CALL get_qs_env(qs_env, cell_ref=cell_ref) CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & - silent=.TRUE., pset="EEQ") + silent=.TRUE., pset="EEQ", cell_periodic=cell%perd) ALLOCATE (ewald_pw) CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section) ! @@ -511,7 +511,7 @@ CONTAINS print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION") CALL get_qs_env(qs_env, cell_ref=cell_ref) CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & - silent=.TRUE., pset="EEQ") + silent=.TRUE., pset="EEQ", cell_periodic=cell%perd) ALLOCATE (ewald_pw) CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section) ! diff --git a/src/ewald_environment_types.F b/src/ewald_environment_types.F index d954a72abd..7baf299ddd 100644 --- a/src/ewald_environment_types.F +++ b/src/ewald_environment_types.F @@ -12,6 +12,14 @@ !> \author CJM NOV-30-2003 ! ************************************************************************************************** MODULE ewald_environment_types + USE cell_types, ONLY: use_perd_none,& + use_perd_x,& + use_perd_xy,& + use_perd_xyz,& + use_perd_xz,& + use_perd_y,& + use_perd_yz,& + use_perd_z USE cp_log_handling, ONLY: cp_get_default_logger,& cp_logger_type USE cp_output_handling, ONLY: cp_print_key_finished_output,& @@ -383,21 +391,25 @@ CONTAINS !> \param hmat ... !> \param silent ... !> \param pset ... +!> \param cell_periodic ... !> \author JGH ! ************************************************************************************************** - SUBROUTINE read_ewald_section_tb(ewald_env, ewald_section, hmat, silent, pset) + SUBROUTINE read_ewald_section_tb(ewald_env, ewald_section, hmat, silent, pset, cell_periodic) TYPE(ewald_environment_type), INTENT(INOUT) :: ewald_env TYPE(section_vals_type), POINTER :: ewald_section REAL(KIND=dp), DIMENSION(3, 3), INTENT(IN) :: hmat LOGICAL, INTENT(IN), OPTIONAL :: silent CHARACTER(LEN=*), OPTIONAL :: pset + INTEGER, DIMENSION(3), INTENT(IN), OPTIONAL :: cell_periodic CHARACTER(LEN=5) :: param - INTEGER :: i, iw, n(3) + INTEGER :: i, iw, n(3), poisson_key + INTEGER, DIMENSION(3) :: poisson_periodic INTEGER, DIMENSION(:), POINTER :: gmax_read LOGICAL :: do_print, explicit REAL(KIND=dp) :: alat, cutoff, dummy, omega TYPE(cp_logger_type), POINTER :: logger + TYPE(section_vals_type), POINTER :: poisson_section logger => cp_get_default_logger() do_print = .TRUE. @@ -405,6 +417,21 @@ CONTAINS param = "none" IF (PRESENT(pset)) param = pset + IF (PRESENT(cell_periodic)) THEN + poisson_section => ewald_env%poisson_section + IF (ASSOCIATED(poisson_section)) THEN + CALL section_vals_val_get(poisson_section, "PERIODIC", i_val=poisson_key) + CALL tb_decode_periodicity(poisson_key, poisson_periodic) + IF (ANY(cell_periodic /= poisson_periodic)) THEN + CALL cp_warn(__LOCATION__, & + "The selected periodicities in SUBSYS/CELL and DFT/POISSON do not match. "// & + "The TB Ewald electrostatics will use DFT/POISSON/PERIODIC="// & + TRIM(tb_periodicity_label(poisson_periodic))// & + " while SUBSYS/CELL/PERIODIC="//TRIM(tb_periodicity_label(cell_periodic))//".") + END IF + END IF + END IF + ewald_env%do_multipoles = .FALSE. ewald_env%do_ipol = 0 ewald_env%eps_pol = 1.e-12_dp @@ -429,7 +456,7 @@ CONTAINS ELSE SELECT CASE (param) CASE DEFAULT - ewald_env%alpha = 1.0_dp + CALL section_vals_val_get(ewald_section, "ALPHA", r_val=ewald_env%alpha) CASE ("EEQ") omega = ABS(det_3x3(hmat)) ewald_env%alpha = SQRT(twopi)/omega**(1./3.) @@ -511,6 +538,58 @@ CONTAINS END SUBROUTINE read_ewald_section_tb +! ************************************************************************************************** +!> \brief Decode CP2K PERIODIC enum into the 3-component periodicity mask. +!> \param periodic_key input enum value +!> \param periodic periodicity mask +! ************************************************************************************************** + SUBROUTINE tb_decode_periodicity(periodic_key, periodic) + INTEGER, INTENT(IN) :: periodic_key + INTEGER, DIMENSION(3), INTENT(OUT) :: periodic + + SELECT CASE (periodic_key) + CASE (use_perd_x) + periodic = [1, 0, 0] + CASE (use_perd_y) + periodic = [0, 1, 0] + CASE (use_perd_z) + periodic = [0, 0, 1] + CASE (use_perd_xy) + periodic = [1, 1, 0] + CASE (use_perd_xz) + periodic = [1, 0, 1] + CASE (use_perd_yz) + periodic = [0, 1, 1] + CASE (use_perd_xyz) + periodic = [1, 1, 1] + CASE (use_perd_none) + periodic = [0, 0, 0] + CASE DEFAULT + CPABORT("Invalid PERIODIC setting for TB Ewald") + END SELECT + + END SUBROUTINE tb_decode_periodicity + +! ************************************************************************************************** +!> \brief Return a compact label for a 3-component periodicity mask. +!> \param periodic periodicity mask +!> \return label +! ************************************************************************************************** + FUNCTION tb_periodicity_label(periodic) RESULT(label) + INTEGER, DIMENSION(3), INTENT(IN) :: periodic + CHARACTER(LEN=4) :: label + + label = "" + IF (ALL(periodic == 0)) THEN + label = "NONE" + ELSE + IF (periodic(1) == 1) label = TRIM(label)//"X" + IF (periodic(2) == 1) label = TRIM(label)//"Y" + IF (periodic(3) == 1) label = TRIM(label)//"Z" + END IF + + END FUNCTION tb_periodicity_label + ! ************************************************************************************************** !> \brief triggers (by bisection) the optimal value for EWALD parameter x !> EXP(-x^2)/x^2 = EWALD_ACCURACY @@ -551,4 +630,3 @@ CONTAINS END FUNCTION find_ewald_optimal_value END MODULE ewald_environment_types - diff --git a/src/ewald_methods_tb.F b/src/ewald_methods_tb.F index 95ae94ce01..a8e800573f 100644 --- a/src/ewald_methods_tb.F +++ b/src/ewald_methods_tb.F @@ -326,11 +326,10 @@ CONTAINS END DO END IF IF (use_virial) THEN - IF (iatom == jatom) THEN - pfr = -0.5_dp*dfr*mcharge(iatom)*mcharge(jatom) - ELSE - pfr = -dfr*mcharge(iatom)*mcharge(jatom) - END IF + ! The potential update above adds both sides of the pair before the + ! final 0.5 energy prefactor is applied. Self-image pairs therefore + ! need the same virial prefactor as interatomic pairs. + pfr = -dfr*mcharge(iatom)*mcharge(jatom) CALL virial_pair_force(virial%pv_virial, -pfr, rij, rij) END IF END IF @@ -513,4 +512,3 @@ CONTAINS END SUBROUTINE tb_spme_zforce END MODULE ewald_methods_tb - diff --git a/src/force_env_methods.F b/src/force_env_methods.F index 01bbd43802..f78b769860 100644 --- a/src/force_env_methods.F +++ b/src/force_env_methods.F @@ -30,6 +30,7 @@ MODULE force_env_methods scaled_to_real USE constraint_fxd, ONLY: fix_atom_control USE constraint_vsite, ONLY: vsite_force_control + USE cp_blacs_env, ONLY: cp_blacs_env_type USE cp_control_types, ONLY: dft_control_type USE cp_fm_basic_linalg, ONLY: cp_fm_scale_and_add USE cp_fm_types, ONLY: cp_fm_copy_general @@ -101,6 +102,13 @@ MODULE force_env_methods USE kinds, ONLY: default_path_length,& default_string_length,& dp + USE kpoint_methods, ONLY: kpoint_env_initialize,& + kpoint_initialize,& + kpoint_initialize_mos + USE kpoint_types, ONLY: get_kpoint_info,& + kpoint_reset_initialization,& + kpoint_type,& + set_kpoint_info USE machine, ONLY: m_memory USE mathlib, ONLY: abnormal_value USE message_passing, ONLY: mp_para_env_type @@ -132,6 +140,7 @@ MODULE force_env_methods understand_spin_states USE particle_list_types, ONLY: particle_list_p_type,& particle_list_type + USE particle_types, ONLY: particle_type USE physcon, ONLY: debye USE pw_env_types, ONLY: pw_env_get,& pw_env_type @@ -149,13 +158,17 @@ MODULE force_env_methods USE qmmmx_force, ONLY: qmmmx_calc_energy_force USE qmmmx_types, ONLY: qmmmx_env_type USE qs_apt_fdiff_methods, ONLY: apt_fdiff + USE qs_basis_rotation_methods, ONLY: qs_basis_rotation USE qs_energy_types, ONLY: qs_energy_type USE qs_environment_types, ONLY: get_qs_env,& qs_environment_type,& set_qs_env USE qs_force, ONLY: qs_calc_energy_force + USE qs_mo_types, ONLY: mo_set_type USE qs_rho_types, ONLY: qs_rho_get,& qs_rho_type + USE qs_wf_history_types, ONLY: qs_wf_history_type,& + wfi_clear USE restraint, ONLY: restraint_control USE scine_utils, ONLY: write_scine USE string_utilities, ONLY: compress @@ -264,6 +277,7 @@ CONTAINS CASE (use_fist_force) CALL fist_calc_energy_force(force_env%fist_env) CASE (use_qs_force) + CALL force_env_refresh_debug_kpoints(force_env, fd_energy=.NOT. calculate_forces) CALL qs_calc_energy_force(force_env%qs_env, calculate_forces, energy_consistency, linres_run) CASE (use_pwdft_force) IF (virial%pv_availability .AND. calculate_stress_tensor) THEN @@ -515,6 +529,87 @@ CONTAINS END SUBROUTINE force_env_calc_energy_force +! ************************************************************************************************** +!> \brief Rebuild k-point data for DEBUG finite-difference geometries. +!> Atomic k-point symmetry may change when a single atom or cell element is displaced. +!> \param force_env ... +!> \param fd_energy ... +! ************************************************************************************************** + SUBROUTINE force_env_refresh_debug_kpoints(force_env, fd_energy) + + TYPE(force_env_type), POINTER :: force_env + LOGICAL, INTENT(IN) :: fd_energy + + CHARACTER(LEN=default_string_length) :: kp_scheme + LOGICAL :: debug_inversion_only, do_kpoints, full_grid, input_full_grid, & + input_inversion_symmetry_only, inversion_symmetry_only, kpoint_symmetry, use_full_grid, & + use_inversion_symmetry_only + TYPE(cell_type), POINTER :: cell + TYPE(cp_blacs_env_type), POINTER :: blacs_env + TYPE(dft_control_type), POINTER :: dft_control + TYPE(global_environment_type), POINTER :: globenv + TYPE(kpoint_type), POINTER :: kpoints + TYPE(mo_set_type), DIMENSION(:), POINTER :: mos + TYPE(mp_para_env_type), POINTER :: para_env + TYPE(particle_type), DIMENSION(:), POINTER :: particle_set + TYPE(qs_wf_history_type), POINTER :: wf_history + TYPE(section_vals_type), POINTER :: input, kpoint_section + + IF (.NOT. ASSOCIATED(force_env)) RETURN + IF (force_env%in_use /= use_qs_force) RETURN + + NULLIFY (globenv) + CALL force_env_get(force_env, globenv=globenv) + IF (.NOT. ASSOCIATED(globenv)) RETURN + IF (globenv%run_type_id /= debug_run) RETURN + + NULLIFY (blacs_env, cell, dft_control, input, kpoint_section, kpoints, mos, para_env, & + particle_set, wf_history) + CALL get_qs_env(qs_env=force_env%qs_env, & + blacs_env=blacs_env, & + cell=cell, & + dft_control=dft_control, & + do_kpoints=do_kpoints, & + input=input, & + kpoints=kpoints, & + mos=mos, & + para_env=para_env, & + particle_set=particle_set, & + wf_history=wf_history) + IF (.NOT. do_kpoints) RETURN + + CALL get_kpoint_info(kpoints, kp_scheme=kp_scheme, symmetry=kpoint_symmetry, full_grid=full_grid, & + inversion_symmetry_only=inversion_symmetry_only) + IF (.NOT. kpoint_symmetry) RETURN + IF (TRIM(kp_scheme) /= "MONKHORST-PACK" .AND. TRIM(kp_scheme) /= "MACDONALD") RETURN + + input_full_grid = full_grid + input_inversion_symmetry_only = inversion_symmetry_only + IF (ASSOCIATED(input)) THEN + kpoint_section => section_vals_get_subs_vals(input, "DFT%KPOINTS") + CALL section_vals_val_get(kpoint_section, "FULL_GRID", l_val=input_full_grid) + CALL section_vals_val_get(kpoint_section, "INVERSION_SYMMETRY_ONLY", & + l_val=input_inversion_symmetry_only) + END IF + ! DEBUG finite differences must not reuse atomic symmetry from another geometry. + ! Keep only k-space inversion/time-reversal for numerical points and TB DEBUG. + debug_inversion_only = fd_energy .OR. dft_control%qs_control%dftb .OR. & + dft_control%qs_control%xtb + use_full_grid = input_full_grid + use_inversion_symmetry_only = (input_inversion_symmetry_only .OR. debug_inversion_only) .AND. & + (.NOT. use_full_grid) + CALL set_kpoint_info(kpoints, full_grid=use_full_grid, & + inversion_symmetry_only=use_inversion_symmetry_only) + + CALL kpoint_reset_initialization(kpoints) + CALL kpoint_initialize(kpoints, particle_set, cell) + CALL kpoint_env_initialize(kpoints, para_env, blacs_env, with_aux_fit=dft_control%do_admm) + CALL kpoint_initialize_mos(kpoints, mos) + CALL wfi_clear(wf_history) + CALL qs_basis_rotation(force_env%qs_env, kpoints) + + END SUBROUTINE force_env_refresh_debug_kpoints + ! ************************************************************************************************** !> \brief Evaluates the stress tensor and pressure numerically !> \param force_env ... diff --git a/src/input_constants.F b/src/input_constants.F index 0fd310ac8a..076cdd6721 100644 --- a/src/input_constants.F +++ b/src/input_constants.F @@ -1351,7 +1351,14 @@ MODULE input_constants ! tblite method selection INTEGER, PARAMETER, PUBLIC :: gfn1xtb = 1, & gfn2xtb = 2, & - ipea1xtb = 3 + ipea1xtb = 3, & + gfn_tblite = 4 + + ! tblite SCC mixer selection + INTEGER, PARAMETER, PUBLIC :: tblite_scc_mixer_auto = 0, & + tblite_scc_mixer_tblite = 1, & + tblite_scc_mixer_cp2k = 2, & + tblite_scc_mixer_none = 3 ! SMEAGOL interface INTEGER, PARAMETER, PUBLIC :: smeagol_bulklead_leftright = 1, & diff --git a/src/input_cp2k_poisson.F b/src/input_cp2k_poisson.F index 5a9496bf44..8cadede87f 100644 --- a/src/input_cp2k_poisson.F +++ b/src/input_cp2k_poisson.F @@ -337,7 +337,6 @@ CONTAINS CALL keyword_create(keyword, __LOCATION__, name="alpha", & description="alpha parameter associated with Ewald (EWALD|PME|SPME). "// & "Recommended for small systems is alpha = 3.5 / r_cut. "// & - "For Tight-binding application a recommended value is alpha = 1.0. "// & "Tuning alpha, r_cut and gmax is needed to obtain O(N**1.5) scaling for ewald.", & usage="alpha .30", & default_r_val=cp_unit_to_cp2k(value=0.35_dp, unit_str="angstrom^-1"), & diff --git a/src/input_cp2k_tb.F b/src/input_cp2k_tb.F index 6659ec2343..3c0ef8c6a1 100644 --- a/src/input_cp2k_tb.F +++ b/src/input_cp2k_tb.F @@ -16,14 +16,10 @@ MODULE input_cp2k_tb Asgeirsson2017, Bannwarth2019, Caldeweyher2017, Caldeweyher2020, Elstner1998, Grimme2017, & Hu2007, Porezag1995, Seifert1996, Zhechkov2005 USE eeq_input, ONLY: create_eeq_control_section - USE input_constants, ONLY: dispersion_d2,& - dispersion_d3,& - dispersion_d3bj,& - dispersion_uff,& - gfn1xtb,& - gfn2xtb,& - ipea1xtb,& - slater + USE input_constants, ONLY: & + dispersion_d2, dispersion_d3, dispersion_d3bj, dispersion_uff, gfn1xtb, gfn2xtb, & + gfn_tblite, ipea1xtb, slater, tblite_scc_mixer_auto, tblite_scc_mixer_cp2k, & + tblite_scc_mixer_none, tblite_scc_mixer_tblite USE input_cp2k_mm, ONLY: create_GENPOT_section USE input_keyword_types, ONLY: keyword_create,& keyword_release,& @@ -83,8 +79,12 @@ CONTAINS CALL keyword_release(keyword) CALL keyword_create(keyword, __LOCATION__, name="do_ewald", & - description="Use Ewald type method instead of direct sum for Coulomb interaction", & - usage="DO_EWALD", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + description="Deprecated debug override for the DFTB Ewald treatment. "// & + "By default the setting is inferred from SUBSYS/CELL/PERIODIC. "// & + "If set to TRUE, the DFT/POISSON section must use a periodic Poisson solver.", & + usage="DO_EWALD", default_l_val=.FALSE., lone_keyword_l_val=.TRUE., & + deprecation_notice="Use SUBSYS/CELL/PERIODIC to select periodicity. "// & + "DO_EWALD is retained only as a debug override for the DFTB Ewald path.") CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) @@ -116,6 +116,9 @@ CONTAINS CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) + CALL add_tb_scc_mixer_keywords(section, "CP2K-internal DFTB", & + "AUTO keeps the existing CP2K density/SCF mixing path for DFTB.") + END SUBROUTINE create_dftb_control_section ! ************************************************************************************************** @@ -153,14 +156,31 @@ CONTAINS NULLIFY (keyword) CALL keyword_create(keyword, __LOCATION__, name="GFN_TYPE", & - description="Which GFN xTB method should be used.", & - usage="GFN_TYPE 1", default_i_val=1) + description="Selects the xTB backend. GFN_TYPE 1 uses the CP2K-internal GFN1-xTB "// & + "implementation. GFN_TYPE TBLITE uses the tblite backend and requires an XTB/TBLITE "// & + "section, where the actual tblite method is selected.", & + usage="GFN_TYPE (0|1|TBLITE)", & + enum_c_vals=s2a("0", "1", "TBLITE"), & + enum_i_vals=[0, gfn1xtb, gfn_tblite], & + enum_desc=s2a("Use the CP2K-internal GFN0-xTB implementation.", & + "Use the CP2K-internal GFN1-xTB implementation.", & + "Use the CP2K/tblite backend; requires XTB/TBLITE."), & + default_i_val=gfn1xtb) CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) + CALL add_tb_scc_mixer_keywords(section, "CP2K-internal xTB", & + "AUTO keeps the CP2K charge mixer for CP2K-internal xTB.") + CALL keyword_create(keyword, __LOCATION__, name="DO_EWALD", & - description="Use Ewald type method instead of direct sum for Coulomb interaction", & - usage="DO_EWALD", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + description="Deprecated debug override for the xTB Ewald treatment. "// & + "By default the setting is inferred from SUBSYS/CELL/PERIODIC. "// & + "If set to TRUE for CP2K-internal xTB, the DFT/POISSON section must use a periodic "// & + "Poisson solver. For CP2K/tblite, the periodic long-range treatment is performed "// & + "inside tblite.", & + usage="DO_EWALD", default_l_val=.FALSE., lone_keyword_l_val=.TRUE., & + deprecation_notice="Use SUBSYS/CELL/PERIODIC to select periodicity. "// & + "DO_EWALD is retained only as a debug override for the CP2K-internal xTB Ewald path.") CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) @@ -552,16 +572,21 @@ CONTAINS TYPE(section_type), POINTER :: section TYPE(keyword_type), POINTER :: keyword + TYPE(section_type), POINTER :: subsection CPASSERT(.NOT. ASSOCIATED(section)) CALL section_create(section, __LOCATION__, name="TBLITE", & - description="Section used to specify options for an xTB computation using tblite.", & - n_keywords=1, n_subsections=0, repeats=.FALSE., citations=[Caldeweyher2017, Caldeweyher2020, & + description="Section used to specify options for an xTB computation using tblite. "// & + "This section is required when XTB/GFN_TYPE is set to TBLITE. "// & + "Periodicity follows SUBSYS/CELL/PERIODIC; the deprecated XTB/DO_EWALD keyword "// & + "is read consistently with CP2K-internal xTB for diagnostics/debugging.", & + n_keywords=1, n_subsections=1, repeats=.FALSE., citations=[Caldeweyher2017, Caldeweyher2020, & Asgeirsson2017, Grimme2017, Bannwarth2019]) NULLIFY (keyword) CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", & - description="activates the execution via tblite", & + description="Marks the tblite options section as present. The tblite backend is selected "// & + "with XTB/GFN_TYPE TBLITE.", & lone_keyword_l_val=.TRUE., default_l_val=.FALSE.) CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) @@ -579,6 +604,156 @@ CONTAINS CALL section_add_keyword(section, keyword) CALL keyword_release(keyword) + CALL add_tb_scc_mixer_keywords(section, "CP2K/tblite xTB", & + "AUTO uses tblite's internal SCC mixer.") + + NULLIFY (keyword) + CALL keyword_create(keyword, __LOCATION__, name="REFERENCE_CLI", & + description="Enable the native tblite CLI reference check. If true, the "// & + "XTB/TBLITE/REFERENCE_CLI section must be present. The reference check is also "// & + "enabled whenever that section is present. This diagnostic path is skipped for "// & + "CP2K multi-k-point calculations, because the native tblite CLI does not reproduce "// & + "CP2K KPOINTS sampling.", & + usage="REFERENCE_CLI", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + NULLIFY (subsection) + CALL create_xtb_reference_cli_section(subsection) + CALL section_add_subsection(section, subsection) + CALL section_release(subsection) + END SUBROUTINE create_xtb_tblite_section +! ************************************************************************************************** +!> \brief Adds common SCC-mixer keywords for TB methods. +!> \param section section receiving the keywords +!> \param TARGET method/path description for the manual text +!> \param auto_desc AUTO behavior for this section +! ************************************************************************************************** + SUBROUTINE add_tb_scc_mixer_keywords(section, TARGET, auto_desc) + TYPE(section_type), POINTER :: section + CHARACTER(LEN=*), INTENT(IN) :: target, auto_desc + + TYPE(keyword_type), POINTER :: keyword + + NULLIFY (keyword) + CALL keyword_create(keyword, __LOCATION__, name="SCC_MIXER", & + description="Selects the SCC variable mixer for "//TARGET//" calculations. "// & + auto_desc//" TBLITE forces the tblite modified Broyden SCC mixer, CP2K forces CP2K "// & + "charge mixing, and NONE updates SCC variables without mixing.", & + usage="SCC_MIXER (AUTO|TBLITE|CP2K|NONE)", & + enum_c_vals=s2a("AUTO", "TBLITE", "CP2K", "NONE"), & + enum_i_vals=[tblite_scc_mixer_auto, tblite_scc_mixer_tblite, & + tblite_scc_mixer_cp2k, tblite_scc_mixer_none], & + enum_desc=s2a("Default method-dependent choice.", & + "Use the tblite modified Broyden SCC mixer.", & + "Use CP2K charge mixing for SCC variables.", & + "Do not mix SCC variables; for debugging."), & + default_i_val=tblite_scc_mixer_auto) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="TBLITE_MIXER_DAMPING", & + description="Damping parameter for the tblite modified Broyden SCC mixer. "// & + "Only active when the effective SCC mixer is TBLITE, either explicitly or via AUTO. "// & + "The iteration limit is taken from DFT/SCF/MAX_SCF.", & + usage="TBLITE_MIXER_DAMPING 0.4", default_r_val=0.4_dp) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + END SUBROUTINE add_tb_scc_mixer_keywords + +! ************************************************************************************************** +!> \brief Creates the &REFERENCE_CLI section used to compare against native tblite. +!> \param section the section to create +! ************************************************************************************************** + SUBROUTINE create_xtb_reference_cli_section(section) + TYPE(section_type), POINTER :: section + + TYPE(keyword_type), POINTER :: keyword + + CPASSERT(.NOT. ASSOCIATED(section)) + CALL section_create(section, __LOCATION__, name="REFERENCE_CLI", & + description="Run the native tblite command line interface as a reference "// & + "for CP2K/tblite energies, nuclear gradients, and optionally virials. "// & + "The section is a lone section: if it is present, the reference check is enabled.", & + n_keywords=1, n_subsections=0, repeats=.FALSE.) + + NULLIFY (keyword) + CALL keyword_create(keyword, __LOCATION__, name="_SECTION_PARAMETERS_", & + description="Activates the native tblite CLI reference check when the section is present.", & + lone_keyword_l_val=.TRUE., default_l_val=.FALSE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="PROGRAM_NAME", & + description="Executable name or path for the native tblite command line program.", & + usage="PROGRAM_NAME tblite", n_var=1, type_of_var=char_t, default_c_val="tblite") + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="WORK_DIRECTORY", & + description="Directory used for temporary native tblite CLI input and output files.", & + usage="WORK_DIRECTORY .", n_var=1, type_of_var=char_t, default_c_val=".") + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="PREFIX", & + description="Prefix for temporary native tblite CLI input and output files.", & + usage="PREFIX tblite-reference", n_var=1, type_of_var=char_t, & + default_c_val="tblite-reference") + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="KEEP_FILES", & + description="Keep the temporary native tblite CLI input and output files.", & + usage="KEEP_FILES T", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="ERROR_LIMIT", & + description="Tolerance for reporting reference CLI deviations.", & + usage="ERROR_LIMIT 1.0E-8", default_r_val=1.0E-8_dp) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="STOP_ON_ERROR", & + description="Abort if a checked reference CLI deviation exceeds ERROR_LIMIT.", & + usage="STOP_ON_ERROR T", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="CHECK_ENERGY", & + description="Compare CP2K/tblite energy against the native tblite CLI energy.", & + usage="CHECK_ENERGY T", default_l_val=.TRUE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="CHECK_FORCES", & + description="Compare CP2K/tblite nuclear gradients against native tblite CLI gradients.", & + usage="CHECK_FORCES T", default_l_val=.TRUE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="CHECK_VIRIAL", & + description="Compare CP2K/tblite virial against the native tblite CLI virial.", & + usage="CHECK_VIRIAL T", default_l_val=.FALSE., lone_keyword_l_val=.TRUE.) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="ACCURACY", & + description="Value passed to native tblite as --acc.", & + usage="ACCURACY 1.0", default_r_val=1.0_dp) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + CALL keyword_create(keyword, __LOCATION__, name="ITERATIONS", & + description="Value passed to native tblite as --iterations.", & + usage="ITERATIONS 250", default_i_val=250) + CALL section_add_keyword(section, keyword) + CALL keyword_release(keyword) + + END SUBROUTINE create_xtb_reference_cli_section + END MODULE input_cp2k_tb diff --git a/src/kpoint_types.F b/src/kpoint_types.F index 7a5e9e14e2..a7ff99815e 100644 --- a/src/kpoint_types.F +++ b/src/kpoint_types.F @@ -56,7 +56,7 @@ MODULE kpoint_types CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'kpoint_types' PUBLIC :: kpoint_type - PUBLIC :: kpoint_create, kpoint_release, get_kpoint_info, set_kpoint_info + PUBLIC :: kpoint_create, kpoint_release, kpoint_reset_initialization, get_kpoint_info, set_kpoint_info PUBLIC :: read_kpoint_section, write_kpoint_info PUBLIC :: kpoint_env_type, kpoint_env_p_type PUBLIC :: kpoint_env_create, get_kpoint_env @@ -346,6 +346,116 @@ CONTAINS END SUBROUTINE kpoint_release +! ************************************************************************************************** +!> \brief Reset all data derived from a concrete k-point initialization. +!> Input options such as the scheme, grid, shifts and symmetry settings are kept. +!> \param kpoint The kpoint environment +! ************************************************************************************************** + SUBROUTINE kpoint_reset_initialization(kpoint) + TYPE(kpoint_type), INTENT(INOUT) :: kpoint + + INTEGER :: i, ik, j + + IF (ASSOCIATED(kpoint%xkp)) THEN + DEALLOCATE (kpoint%xkp) + NULLIFY (kpoint%xkp) + END IF + IF (ASSOCIATED(kpoint%wkp)) THEN + DEALLOCATE (kpoint%wkp) + NULLIFY (kpoint%wkp) + END IF + IF (ASSOCIATED(kpoint%kp_dist)) THEN + DEALLOCATE (kpoint%kp_dist) + NULLIFY (kpoint%kp_dist) + END IF + + CALL mpools_release(kpoint%mpools) + CALL mpools_release(kpoint%mpools_aux_fit) + + CALL cp_blacs_env_release(kpoint%blacs_env) + CALL cp_blacs_env_release(kpoint%blacs_env_all) + + CALL mp_para_env_release(kpoint%para_env) + CALL mp_para_env_release(kpoint%para_env_kp) + CALL mp_para_env_release(kpoint%para_env_inter_kp) + + IF (ASSOCIATED(kpoint%cell_to_index)) THEN + DEALLOCATE (kpoint%cell_to_index) + NULLIFY (kpoint%cell_to_index) + END IF + IF (ASSOCIATED(kpoint%index_to_cell)) THEN + DEALLOCATE (kpoint%index_to_cell) + NULLIFY (kpoint%index_to_cell) + END IF + + IF (ASSOCIATED(kpoint%kp_env)) THEN + DO ik = 1, SIZE(kpoint%kp_env) + CALL kpoint_env_release(kpoint%kp_env(ik)%kpoint_env) + END DO + DEALLOCATE (kpoint%kp_env) + NULLIFY (kpoint%kp_env) + END IF + + IF (ASSOCIATED(kpoint%kp_aux_env)) THEN + DO ik = 1, SIZE(kpoint%kp_aux_env) + CALL kpoint_env_release(kpoint%kp_aux_env(ik)%kpoint_env) + END DO + DEALLOCATE (kpoint%kp_aux_env) + NULLIFY (kpoint%kp_aux_env) + END IF + + IF (ASSOCIATED(kpoint%kp_sym)) THEN + DO ik = 1, SIZE(kpoint%kp_sym) + CALL kpoint_sym_release(kpoint%kp_sym(ik)%kpoint_sym) + END DO + DEALLOCATE (kpoint%kp_sym) + NULLIFY (kpoint%kp_sym) + END IF + + IF (ASSOCIATED(kpoint%atype)) THEN + DEALLOCATE (kpoint%atype) + NULLIFY (kpoint%atype) + END IF + IF (ASSOCIATED(kpoint%ibrot)) THEN + DEALLOCATE (kpoint%ibrot) + NULLIFY (kpoint%ibrot) + END IF + + IF (ASSOCIATED(kpoint%kind_rotmat)) THEN + DO i = 1, SIZE(kpoint%kind_rotmat, 1) + DO j = 1, SIZE(kpoint%kind_rotmat, 2) + IF (ASSOCIATED(kpoint%kind_rotmat(i, j)%rmat)) THEN + DEALLOCATE (kpoint%kind_rotmat(i, j)%rmat) + NULLIFY (kpoint%kind_rotmat(i, j)%rmat) + END IF + END DO + END DO + DEALLOCATE (kpoint%kind_rotmat) + NULLIFY (kpoint%kind_rotmat) + END IF + + IF (ASSOCIATED(kpoint%scf_diis_buffer)) THEN + CALL qs_diis_b_release_kp(kpoint%scf_diis_buffer) + DEALLOCATE (kpoint%scf_diis_buffer) + NULLIFY (kpoint%scf_diis_buffer) + END IF + + NULLIFY (kpoint%sab_nl) + NULLIFY (kpoint%sab_nl_nosym) + + ALLOCATE (kpoint%cell_to_index(0:0, 0:0, 0:0)) + kpoint%cell_to_index(:, :, :) = 1 + + ALLOCATE (kpoint%index_to_cell(0:0, 0:0)) + kpoint%index_to_cell(:, :) = 0 + + kpoint%nkp = 0 + kpoint%nkp_groups = 0 + kpoint%kp_range = 0 + kpoint%iogrp = .FALSE. + + END SUBROUTINE kpoint_reset_initialization + ! ************************************************************************************************** !> \brief Retrieve information from a kpoint environment !> \param kpoint The kpoint environment diff --git a/src/qs_charge_mixing.F b/src/qs_charge_mixing.F index 0ddf4847a0..92111c3c9a 100644 --- a/src/qs_charge_mixing.F +++ b/src/qs_charge_mixing.F @@ -8,14 +8,22 @@ ! ************************************************************************************************** MODULE qs_charge_mixing - USE kinds, ONLY: dp - USE mathlib, ONLY: get_pseudo_inverse_svd - USE message_passing, ONLY: mp_para_env_type - USE qs_density_mixing_types, ONLY: broyden_mixing_nr,& - gspace_mixing_nr,& - mixing_storage_type,& - multisecant_mixing_nr,& - pulay_mixing_nr +#if defined(__TBLITE) + USE mctc_env, ONLY: error_type + USE tblite_scf, ONLY: new_mixer +#endif + USE input_constants, ONLY: tblite_scc_mixer_auto, & + tblite_scc_mixer_cp2k, & + tblite_scc_mixer_none, & + tblite_scc_mixer_tblite + USE kinds, ONLY: dp + USE mathlib, ONLY: get_pseudo_inverse_svd + USE message_passing, ONLY: mp_para_env_type + USE qs_density_mixing_types, ONLY: broyden_mixing_nr, & + gspace_mixing_nr, & + mixing_storage_type, & + multisecant_mixing_nr, & + pulay_mixing_nr #include "./base/base_uses.f90" IMPLICIT NONE @@ -24,40 +32,77 @@ MODULE qs_charge_mixing CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_charge_mixing' - PUBLIC :: charge_mixing + PUBLIC :: charge_mixing, charge_mixing_scc_error + + REAL(KIND=dp), PARAMETER, PRIVATE :: tblite_scc_pconv = 2.0E-5_dp CONTAINS ! ************************************************************************************************** -!> \brief Driver for the charge mixing, calls the proper routine given the requested method +!> \brief Driver for TB SCC variable mixing, calls the requested method. !> \param mixing_method ... !> \param mixing_store ... !> \param charges ... !> \param para_env ... !> \param iter_count ... +!> \param scc_mixer ... +!> \param tblite_mixer_damping ... +!> \param tblite_mixer_memory ... !> \par History !> \author JGH ! ************************************************************************************************** - SUBROUTINE charge_mixing(mixing_method, mixing_store, charges, para_env, iter_count) + SUBROUTINE charge_mixing(mixing_method, mixing_store, charges, para_env, iter_count, & + scc_mixer, tblite_mixer_damping, tblite_mixer_memory) INTEGER, INTENT(IN) :: mixing_method TYPE(mixing_storage_type), POINTER :: mixing_store REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT) :: charges TYPE(mp_para_env_type), POINTER :: para_env INTEGER, INTENT(IN) :: iter_count + INTEGER, INTENT(IN), OPTIONAL :: scc_mixer + REAL(KIND=dp), INTENT(IN), OPTIONAL :: tblite_mixer_damping + INTEGER, INTENT(IN), OPTIONAL :: tblite_mixer_memory CHARACTER(len=*), PARAMETER :: routineN = 'charge_mixing' - INTEGER :: handle, ia, ii, imin, inow, nbuffer, ns, & + INTEGER :: effective_scc_mixer, handle, ia, ii, & + imin, inow, mixer_memory, nbuffer, ns, & nvec - REAL(dp) :: alpha + REAL(dp) :: alpha, mixer_damping CALL timeset(routineN, handle) + effective_scc_mixer = tblite_scc_mixer_cp2k + IF (PRESENT(scc_mixer)) effective_scc_mixer = scc_mixer + IF (ASSOCIATED(mixing_store)) mixing_store%tb_scc_mixer_error = 0.0_dp + + SELECT CASE (effective_scc_mixer) + CASE (tblite_scc_mixer_auto, tblite_scc_mixer_cp2k) + ! Use the regular CP2K SCC-variable mixing path below. + CASE (tblite_scc_mixer_tblite) + CPASSERT(ASSOCIATED(mixing_store)) + mixer_damping = 0.4_dp + IF (PRESENT(tblite_mixer_damping)) mixer_damping = tblite_mixer_damping + mixer_memory = MAX(1, mixing_store%nbuffer) + IF (PRESENT(tblite_mixer_memory)) mixer_memory = MAX(1, tblite_mixer_memory) + CALL tblite_charge_mixing(mixing_store, charges, para_env, iter_count, & + mixer_damping, mixer_memory) + CALL timestop(handle) + RETURN + CASE (tblite_scc_mixer_none) + IF (ASSOCIATED(mixing_store)) mixing_store%iter_method = "NoMix" + CALL timestop(handle) + RETURN + CASE DEFAULT + CPABORT("Unknown SCC mixer for TB charge mixing") + END SELECT + IF (mixing_method >= gspace_mixing_nr) THEN CPASSERT(ASSOCIATED(mixing_store)) mixing_store%ncall = mixing_store%ncall + 1 ns = SIZE(charges, 2) - ns = MIN(ns, mixing_store%max_shell) + IF (ns > mixing_store%max_shell) THEN + CPABORT("Mixing storage too small for TB SCC variables") + END IF alpha = mixing_store%alpha nbuffer = mixing_store%nbuffer inow = MOD(mixing_store%ncall - 1, nbuffer) + 1 @@ -104,6 +149,98 @@ CONTAINS END SUBROUTINE charge_mixing +! ************************************************************************************************** +!> \brief Return the tblite SCC-mixer residual on the CP2K EPS_SCF scale. +!> \param mixing_store ... +!> \param eps_scf ... +!> \return ... +! ************************************************************************************************** + FUNCTION charge_mixing_scc_error(mixing_store, eps_scf) RESULT(mixer_error) + TYPE(mixing_storage_type), POINTER :: mixing_store + REAL(KIND=dp), INTENT(IN) :: eps_scf + REAL(KIND=dp) :: mixer_error + + mixer_error = 0.0_dp + IF (.NOT. ASSOCIATED(mixing_store)) RETURN + IF (mixing_store%tb_scc_mixer_step <= 1) RETURN + + IF (eps_scf > 0.0_dp) THEN + mixer_error = eps_scf*mixing_store%tb_scc_mixer_error/tblite_scc_pconv + ELSE + mixer_error = mixing_store%tb_scc_mixer_error + END IF + + END FUNCTION charge_mixing_scc_error + +! ************************************************************************************************** +!> \brief TBLite modified-Broyden mixing for a complete TB SCC-variable vector. +!> \param mixing_store ... +!> \param charges ... +!> \param para_env ... +!> \param iter_count ... +!> \param damping ... +!> \param memory ... +! ************************************************************************************************** + SUBROUTINE tblite_charge_mixing(mixing_store, charges, para_env, iter_count, damping, memory) + TYPE(mixing_storage_type), POINTER :: mixing_store + REAL(KIND=dp), DIMENSION(:, :), INTENT(INOUT) :: charges + TYPE(mp_para_env_type), POINTER :: para_env + INTEGER, INTENT(IN) :: iter_count, memory + REAL(KIND=dp), INTENT(IN) :: damping + +#if defined(__TBLITE) + TYPE(error_type), ALLOCATABLE :: error +#endif + INTEGER :: natom, ndim, ns + LOGICAL :: reset_mixer + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: qvec + + MARK_USED(para_env) + + natom = SIZE(charges, 1) + ns = SIZE(charges, 2) + ndim = natom*ns + ALLOCATE (qvec(ndim)) + qvec(:) = RESHAPE(charges, [ndim]) + reset_mixer = (iter_count == 1) .OR. (mixing_store%tb_scc_mixer_step == 0) .OR. & + (mixing_store%tb_scc_mixer_natom /= natom) .OR. & + (mixing_store%tb_scc_mixer_ns /= ns) .OR. & + (mixing_store%tb_scc_mixer_memory /= memory) + mixing_store%tb_scc_mixer_error = 0.0_dp + +#if defined(__TBLITE) + IF (reset_mixer) THEN + IF (ALLOCATED(mixing_store%tb_scc_mixer)) DEALLOCATE (mixing_store%tb_scc_mixer) + CALL new_mixer(mixing_store%tb_scc_mixer, memory, ndim, damping) + CALL mixing_store%tb_scc_mixer%set(qvec) + mixing_store%tb_scc_mixer_natom = natom + mixing_store%tb_scc_mixer_ns = ns + mixing_store%tb_scc_mixer_memory = memory + mixing_store%tb_scc_mixer_step = 1 + mixing_store%iter_method = "NoMix" + RETURN + END IF + + CPASSERT(ALLOCATED(mixing_store%tb_scc_mixer)) + CALL mixing_store%tb_scc_mixer%diff(qvec) + mixing_store%tb_scc_mixer_error = REAL(mixing_store%tb_scc_mixer%get_error(), KIND=dp) + CALL mixing_store%tb_scc_mixer%next(error) + IF (ALLOCATED(error)) CPABORT("tblite SCC mixer failed") + CALL mixing_store%tb_scc_mixer%get(qvec) + charges = RESHAPE(qvec, SHAPE(charges)) + mixing_store%tb_scc_mixer_step = mixing_store%tb_scc_mixer_step + 1 + mixing_store%iter_method = "TBLITE" +#else + MARK_USED(mixing_store) + MARK_USED(charges) + MARK_USED(iter_count) + MARK_USED(damping) + MARK_USED(memory) + CPABORT("SCC_MIXER TBLITE requires CP2K to be built with tblite") +#endif + + END SUBROUTINE tblite_charge_mixing + ! ************************************************************************************************** !> \brief Simple charge mixing !> \param mixing_store ... @@ -190,7 +327,7 @@ CONTAINS maxw = 100000.0_dp wfac = 0.01_dp - mixing_store%wbroy(nv) = SUM(dq_now(:, :)**2) + mixing_store%wbroy(nv) = SUM(dq_now(:, 1:ns)**2) CALL para_env%sum(mixing_store%wbroy(nv)) mixing_store%wbroy(nv) = SQRT(mixing_store%wbroy(nv)) IF (mixing_store%wbroy(nv) > (wfac/maxw)) THEN @@ -201,15 +338,16 @@ CONTAINS IF (mixing_store%wbroy(nv) < minw) mixing_store%wbroy(nv) = minw ! dfbroy - mixing_store%dfbroy(:, :, nv) = dq_now(:, :) - dq_last(:, :) - wdf = SUM(mixing_store%dfbroy(:, :, nv)**2) + mixing_store%dfbroy(:, :, nv) = 0.0_dp + mixing_store%dfbroy(:, 1:ns, nv) = dq_now(:, 1:ns) - dq_last(:, 1:ns) + wdf = SUM(mixing_store%dfbroy(:, 1:ns, nv)**2) CALL para_env%sum(wdf) wdf = 1.0_dp/SQRT(wdf) - mixing_store%dfbroy(:, :, nv) = wdf*mixing_store%dfbroy(:, :, nv) + mixing_store%dfbroy(:, 1:ns, nv) = wdf*mixing_store%dfbroy(:, 1:ns, nv) ! abroy matrix DO i = 1, nv - wfac = SUM(mixing_store%dfbroy(:, :, i)*mixing_store%dfbroy(:, :, nv)) + wfac = SUM(mixing_store%dfbroy(:, 1:ns, i)*mixing_store%dfbroy(:, 1:ns, nv)) CALL para_env%sum(wfac) mixing_store%abroy(i, nv) = wfac mixing_store%abroy(nv, i) = wfac @@ -218,7 +356,7 @@ CONTAINS ! broyden matrices ALLOCATE (amat(nv, nv), beta(nv, nv), cvec(nv), gammab(nv)) DO i = 1, nv - wfac = SUM(mixing_store%dfbroy(:, :, i)*dq_now(:, :)) + wfac = SUM(mixing_store%dfbroy(:, 1:ns, i)*dq_now(:, 1:ns)) CALL para_env%sum(wfac) cvec(i) = mixing_store%wbroy(i)*wfac END DO @@ -235,7 +373,9 @@ CONTAINS gammab(1:nv) = MATMUL(cvec(1:nv), amat(1:nv, 1:nv)) ! build ubroy - mixing_store%ubroy(:, :, nv) = alpha*mixing_store%dfbroy(:, :, nv) + wdf*(q_now(:, :) - q_last(:, :)) + mixing_store%ubroy(:, :, nv) = 0.0_dp + mixing_store%ubroy(:, 1:ns, nv) = alpha*mixing_store%dfbroy(:, 1:ns, nv) + & + wdf*(q_now(:, 1:ns) - q_last(:, 1:ns)) charges = 0.0_dp DO ia = 1, mixing_store%nat_local diff --git a/src/qs_density_mixing_types.F b/src/qs_density_mixing_types.F index df01fb93dc..7718a4d565 100644 --- a/src/qs_density_mixing_types.F +++ b/src/qs_density_mixing_types.F @@ -12,27 +12,30 @@ !> \author fawzi ! ************************************************************************************************** MODULE qs_density_mixing_types - USE ao_util, ONLY: exp_radius - USE input_constants, ONLY: broy_mix,& - direct_p_mix,& - gaussian,& - kerker_mix,& - multisec_mix,& - no_mix,& - pulay_mix - USE input_keyword_types, ONLY: keyword_create,& - keyword_release,& - keyword_type - USE input_section_types, ONLY: section_add_keyword,& - section_create,& - section_type,& - section_vals_type,& - section_vals_val_get - USE input_val_types, ONLY: real_t - USE kinds, ONLY: default_string_length,& - dp - USE qs_rho_atom_types, ONLY: rho_atom_coeff - USE string_utilities, ONLY: s2a +#if defined(__TBLITE) + USE tblite_scf, ONLY: mixer_type +#endif + USE ao_util, ONLY: exp_radius + USE input_constants, ONLY: broy_mix, & + direct_p_mix, & + gaussian, & + kerker_mix, & + multisec_mix, & + no_mix, & + pulay_mix + USE input_keyword_types, ONLY: keyword_create, & + keyword_release, & + keyword_type + USE input_section_types, ONLY: section_add_keyword, & + section_create, & + section_type, & + section_vals_type, & + section_vals_val_get + USE input_val_types, ONLY: real_t + USE kinds, ONLY: default_string_length, & + dp + USE qs_rho_atom_types, ONLY: rho_atom_coeff + USE string_utilities, ONLY: s2a #include "./base/base_uses.f90" IMPLICIT NONE @@ -74,6 +77,9 @@ MODULE qs_density_mixing_types REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: fmat => NULL(), gmat => NULL(), pulay_matrix => NULL(), smat => NULL() ! INTEGER :: nat_local = -1, max_shell = -1 + INTEGER :: tb_scc_mixer_memory = 0, tb_scc_mixer_natom = 0, & + tb_scc_mixer_ns = 0, tb_scc_mixer_step = 0 + REAL(KIND=dp) :: tb_scc_mixer_error = 0.0_dp REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: acharge => NULL() REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: dacharge => NULL() REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: dfbroy => NULL() @@ -92,6 +98,9 @@ MODULE qs_density_mixing_types TYPE(rho_atom_coeff), DIMENSION(:, :, :), POINTER :: cpc_h_in_buffer => NULL(), cpc_s_in_buffer => NULL() TYPE(rho_atom_coeff), DIMENSION(:, :, :), POINTER :: cpc_h_res_buffer => NULL(), cpc_s_res_buffer => NULL() TYPE(rho_atom_coeff), DIMENSION(:, :, :), POINTER :: dcpc_h_in => NULL(), dcpc_s_in => NULL() +#if defined(__TBLITE) + CLASS(mixer_type), ALLOCATABLE :: tb_scc_mixer +#endif END TYPE mixing_storage_type CONTAINS @@ -126,6 +135,11 @@ CONTAINS mixing_store%iter_method = "NoMix" mixing_store%max_g2 = 2._dp*ecut mixing_store%gmix_p = .FALSE. + mixing_store%tb_scc_mixer_error = 0.0_dp + mixing_store%tb_scc_mixer_memory = 0 + mixing_store%tb_scc_mixer_natom = 0 + mixing_store%tb_scc_mixer_ns = 0 + mixing_store%tb_scc_mixer_step = 0 NULLIFY (mixing_store%p_metric) NULLIFY (mixing_store%kerker_factor) @@ -405,6 +419,11 @@ CONTAINS IF (ASSOCIATED(mixing_store%atlist)) THEN DEALLOCATE (mixing_store%atlist) END IF +#if defined(__TBLITE) + IF (ALLOCATED(mixing_store%tb_scc_mixer)) THEN + DEALLOCATE (mixing_store%tb_scc_mixer) + END IF +#endif IF (ASSOCIATED(mixing_store%delta_res)) THEN DO i = 1, SIZE(mixing_store%delta_res, 2) diff --git a/src/qs_dftb_coulomb.F b/src/qs_dftb_coulomb.F index f5680cb8b5..2ba570e5ec 100644 --- a/src/qs_dftb_coulomb.F +++ b/src/qs_dftb_coulomb.F @@ -82,6 +82,7 @@ MODULE qs_dftb_coulomb REAL(dp), PARAMETER :: tol_gamma = 1.e-4_dp ! small real number REAL(dp), PARAMETER :: rtiny = 1.e-10_dp + REAL(KIND=dp), PARAMETER, PRIVATE :: dftb_fd_deriv_step = 1.0e-3_dp PUBLIC :: build_dftb_coulomb, gamma_rab_sr @@ -110,19 +111,23 @@ CONTAINS CHARACTER(len=*), PARAMETER :: routineN = 'build_dftb_coulomb' INTEGER :: atom_i, atom_j, ewald_type, handle, i, ia, iac, iatom, ic, icol, ikind, img, & - irow, is, jatom, jkind, natom, natorb_a, natorb_b, nimg, nkind, nmat + irow, is, jatom, jkind, llm, lmaxi, lmaxj, n1, n2, natom, natorb_a, natorb_b, ngrd, & + ngrdcut, nimg, nkind, nmat INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of INTEGER, DIMENSION(3) :: cellind, periodic INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index - LOGICAL :: defined, do_ewald, do_gamma_stress, & - found, hb_sr_damp, use_virial - REAL(KIND=dp) :: alpha, ddr, deth, dgam, dr, drm, drp, & - fi, ga, gb, gmat, gmij, hb_para, zeff + LOGICAL :: defined, defined_a, defined_b, do_ewald, & + do_gamma_stress, found, hb_sr_damp, & + use_virial + REAL(KIND=dp) :: alpha, background, ddr, deth, dgam, & + dgrd, dr, drm, drp, fi, ga, gb, gmat, & + gmij, gmij_virial, hb_para, zeff REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: xgamma, zeffk REAL(KIND=dp), DIMENSION(0:3) :: eta_a, eta_b - REAL(KIND=dp), DIMENSION(3) :: fij, rij - REAL(KIND=dp), DIMENSION(:, :), POINTER :: dsblock, gmcharge, ksblock, pblock, & - sblock + REAL(KIND=dp), DIMENSION(3) :: drij, fij, rij + REAL(KIND=dp), DIMENSION(:, :), POINTER :: dsblock, dsblock_vir, dsblockm_vir, & + gmcharge, ksblock, pblock, sblock, & + smatij, smatji REAL(KIND=dp), DIMENSION(:, :, :), POINTER :: dsint TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set TYPE(atprop_type), POINTER :: atprop @@ -143,6 +148,7 @@ CONTAINS TYPE(qs_dftb_atom_type), POINTER :: dftb_kind, dftb_kind_a, dftb_kind_b TYPE(qs_dftb_pairpot_type), DIMENSION(:, :), & POINTER :: dftb_potential + TYPE(qs_dftb_pairpot_type), POINTER :: dftb_param_ij, dftb_param_ji TYPE(qs_force_type), DIMENSION(:), POINTER :: force TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set TYPE(sap_int_type), DIMENSION(:), POINTER :: sap_int @@ -217,7 +223,7 @@ CONTAINS gmcharge(iatom, 1) = gmcharge(iatom, 1) + gmat*mcharge(jatom) END IF IF (calculate_forces .AND. (iatom /= jatom .OR. dr > 0.001_dp)) THEN - ddr = 0.1_dp*dftb_potential(ikind, jkind)%dgrd + ddr = dftb_fd_deriv_step*dftb_potential(ikind, jkind)%dgrd drp = dr + ddr drm = dr - ddr dgam = 0.5_dp*(gamma_rab_sr(drp, ga, gb, hb_para) - gamma_rab_sr(drm, ga, gb, hb_para))/ddr @@ -294,15 +300,16 @@ CONTAINS CALL para_env%sum(gmcharge(:, 1)) + background = 0.0_dp IF (do_ewald) THEN ! add self charge interaction and background charge contribution gmcharge(:, 1) = gmcharge(:, 1) - 2._dp*alpha*oorootpi*mcharge(:) IF (ANY(periodic(:) == 1)) THEN - gmcharge(:, 1) = gmcharge(:, 1) - pi/alpha**2/deth + background = pi/alpha**2/deth END IF END IF - energy%hartree = energy%hartree + 0.5_dp*SUM(mcharge(:)*gmcharge(:, 1)) + energy%hartree = energy%hartree + 0.5_dp*SUM(mcharge(:)*(gmcharge(:, 1) - background)) IF (atprop%energy) THEN CALL get_qs_env(qs_env=qs_env, & local_particles=local_particles) @@ -485,9 +492,55 @@ CONTAINS fij(i) = fi END DO IF (use_virial) THEN - fi = 1.0_dp - IF (iatom == jatom) fi = 0.5_dp - CALL virial_pair_force(virial%pv_virial, fi, fij, rij) + ! The image-resolved overlap derivative blocks are matrix oriented. Rebuild the + ! atom-oriented derivative for the virial contraction, matching the Gamma path. + fij = 0.0_dp + CALL get_qs_kind(qs_kind_set(ikind), dftb_parameter=dftb_kind_a) + CALL get_dftb_atom_param(dftb_kind_a, & + defined=defined_a, lmax=lmaxi, natorb=natorb_a) + CALL get_qs_kind(qs_kind_set(jkind), dftb_parameter=dftb_kind_b) + CALL get_dftb_atom_param(dftb_kind_b, & + defined=defined_b, lmax=lmaxj, natorb=natorb_b) + IF (defined_a .AND. defined_b .AND. natorb_a > 0 .AND. natorb_b > 0) THEN + dftb_param_ij => dftb_potential(ikind, jkind) + dftb_param_ji => dftb_potential(jkind, ikind) + ngrd = dftb_param_ij%ngrd + ngrdcut = dftb_param_ij%ngrdcut + dgrd = dftb_param_ij%dgrd + ddr = dgrd*dftb_fd_deriv_step + CPASSERT(dftb_param_ij%llm == dftb_param_ji%llm) + llm = dftb_param_ij%llm + smatij => dftb_param_ij%smat + smatji => dftb_param_ji%smat + dr = SQRT(SUM(rij(:)**2)) + IF (NINT(dr/dgrd) <= ngrdcut .AND. dr > 1.e-6_dp) THEN + n1 = natorb_a + n2 = natorb_b + ALLOCATE (dsblock_vir(n1, n2), dsblockm_vir(n1, n2)) + gmij_virial = 0.5_dp*(gmcharge(iatom, 1) + gmcharge(jatom, 1)) + DO i = 1, 3 + dsblock_vir = 0._dp + dsblockm_vir = 0._dp + drij = rij + drij(i) = rij(i) - ddr + CALL compute_block_sk(dsblockm_vir, smatij, smatji, drij, ngrd, ngrdcut, dgrd, & + llm, lmaxi, lmaxj, iatom, iatom) + drij(i) = rij(i) + ddr + CALL compute_block_sk(dsblock_vir, smatij, smatji, drij, ngrd, ngrdcut, dgrd, & + llm, lmaxi, lmaxj, iatom, iatom) + dsblock_vir = (dsblock_vir - dsblockm_vir)/(2.0_dp*ddr) + IF (irow == iatom) THEN + fij(i) = 2.0_dp*gmij_virial*SUM(pblock*dsblock_vir) + ELSE + fij(i) = 2.0_dp*gmij_virial*SUM(TRANSPOSE(pblock)*dsblock_vir) + END IF + END DO + DEALLOCATE (dsblock_vir, dsblockm_vir) + fi = 1.0_dp + IF (iatom == jatom) fi = 0.5_dp + CALL virial_pair_force(virial%pv_virial, fi, fij, rij) + END IF + END IF END IF END IF END DO @@ -694,7 +747,7 @@ CONTAINS ngrd = dftb_param_ij%ngrd ngrdcut = dftb_param_ij%ngrdcut dgrd = dftb_param_ij%dgrd - ddr = dgrd*0.1_dp + ddr = dgrd*dftb_fd_deriv_step CPASSERT(dftb_param_ij%llm == dftb_param_ji%llm) llm = dftb_param_ij%llm smatij => dftb_param_ij%smat @@ -738,4 +791,3 @@ CONTAINS END SUBROUTINE dftb_dsint_list END MODULE qs_dftb_coulomb - diff --git a/src/qs_dftb_matrices.F b/src/qs_dftb_matrices.F index 9237d33540..b55060602b 100644 --- a/src/qs_dftb_matrices.F +++ b/src/qs_dftb_matrices.F @@ -33,6 +33,7 @@ MODULE qs_dftb_matrices cp_print_key_should_output,& cp_print_key_unit_nr USE efield_tb_methods, ONLY: efield_tb_matrix + USE input_constants, ONLY: tblite_scc_mixer_auto USE input_section_types, ONLY: section_vals_get_subs_vals,& section_vals_type,& section_vals_val_get @@ -44,6 +45,7 @@ MODULE qs_dftb_matrices USE mulliken, ONLY: mulliken_charges USE particle_methods, ONLY: get_particle_set USE particle_types, ONLY: particle_type + USE qs_charge_mixing, ONLY: charge_mixing USE qs_dftb_coulomb, ONLY: build_dftb_coulomb USE qs_dftb_types, ONLY: qs_dftb_atom_type,& qs_dftb_pairpot_type @@ -71,6 +73,7 @@ MODULE qs_dftb_matrices neighbor_list_set_p_type USE qs_rho_types, ONLY: qs_rho_get,& qs_rho_type + USE qs_scf_types, ONLY: qs_scf_env_type USE virial_methods, ONLY: virial_pair_force USE virial_types, ONLY: virial_type #include "./base/base_uses.f90" @@ -83,6 +86,7 @@ MODULE qs_dftb_matrices PRIVATE CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_dftb_matrices' + REAL(KIND=dp), PARAMETER, PRIVATE :: dftb_fd_deriv_step = 1.0e-3_dp PUBLIC :: build_dftb_matrices, build_dftb_ks_matrix, build_dftb_overlap @@ -250,7 +254,7 @@ CONTAINS ngrd = dftb_param_ij%ngrd ngrdcut = dftb_param_ij%ngrdcut dgrd = dftb_param_ij%dgrd - ddr = dgrd*0.1_dp + ddr = dgrd*dftb_fd_deriv_step CPASSERT(dftb_param_ij%llm == dftb_param_ji%llm) llm = dftb_param_ij%llm fmatij => dftb_param_ij%fmat @@ -496,6 +500,7 @@ CONTAINS ispin, natom, nkind, nspins, & output_unit REAL(KIND=dp) :: pc_ener, qmmm_el, zeff + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: mix_charge REAL(KIND=dp), DIMENSION(:), POINTER :: mcharge, occupation_numbers REAL(KIND=dp), DIMENSION(:, :), POINTER :: charges TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set @@ -511,11 +516,12 @@ CONTAINS TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set TYPE(qs_ks_env_type), POINTER :: ks_env TYPE(qs_rho_type), POINTER :: rho + TYPE(qs_scf_env_type), POINTER :: scf_env TYPE(section_vals_type), POINTER :: scf_section CALL timeset(routineN, handle) NULLIFY (dft_control, logger, scf_section, matrix_p, particle_set, ks_env, & - ks_matrix, rho, energy) + ks_matrix, rho, energy, scf_env) logger => cp_get_default_logger() CPASSERT(ASSOCIATED(qs_env)) @@ -569,6 +575,20 @@ CONTAINS END DO DEALLOCATE (charges) + IF ((.NOT. dft_control%qs_control%do_ls_scf) .AND. & + (dft_control%qs_control%dftb_control%tblite_scc_mixer /= tblite_scc_mixer_auto)) THEN + CALL get_qs_env(qs_env=qs_env, scf_env=scf_env) + ALLOCATE (mix_charge(SIZE(mcharge), 1)) + mix_charge(:, 1) = mcharge(:) + CALL charge_mixing(scf_env%mixing_method, scf_env%mixing_store, & + mix_charge, para_env, scf_env%iter_count, & + scc_mixer=dft_control%qs_control%dftb_control%tblite_scc_mixer, & + tblite_mixer_damping=dft_control%qs_control%dftb_control%tblite_mixer_damping, & + tblite_mixer_memory=qs_env%scf_control%max_scf) + mcharge(:) = mix_charge(:, 1) + DEALLOCATE (mix_charge) + END IF + CALL build_dftb_coulomb(qs_env, ks_matrix, rho, mcharge, energy, & calculate_forces, just_energy) @@ -747,7 +767,7 @@ CONTAINS ngrd = dftb_param_ij%ngrd ngrdcut = dftb_param_ij%ngrdcut dgrd = dftb_param_ij%dgrd - ddr = dgrd*0.1_dp + ddr = dgrd*dftb_fd_deriv_step CPASSERT(dftb_param_ij%llm == dftb_param_ji%llm) llm = dftb_param_ij%llm smatij => dftb_param_ij%smat @@ -1029,4 +1049,3 @@ CONTAINS END SUBROUTINE setup_matrices2 END MODULE qs_dftb_matrices - diff --git a/src/qs_dispersion_cnum.F b/src/qs_dispersion_cnum.F index 43a10c4f71..7a9be08889 100644 --- a/src/qs_dispersion_cnum.F +++ b/src/qs_dispersion_cnum.F @@ -983,7 +983,7 @@ CONTAINS REAL(KIND=dp), INTENT(IN) :: rab, rcovab, k1 REAL(KIND=dp), INTENT(OUT) :: cnab, dcnab - REAL(KIND=dp) :: dfz, ee, fz, rr + REAL(KIND=dp) :: dfz, ee, ff, fz, rr ! covalent distance in Bohr rr = rcovab/rab @@ -994,8 +994,9 @@ CONTAINS ! force the function to zero using a second step function fz = 0.5_dp*(1.0_dp - TANH(rab - 2.0_dp*rcovab)) dfz = 0.5_dp*((TANH(rab - 2.0_dp*rcovab))**2 - 1.0_dp) - cnab = 1.0_dp/(1.0_dp + ee)*fz - dcnab = -cnab*cnab*k1*rr/rab*ee + 1.0_dp/(1.0_dp + ee)*dfz + ff = 1.0_dp/(1.0_dp + ee) + cnab = ff*fz + dcnab = -fz*ff*ff*k1*rr/rab*ee + ff*dfz END SUBROUTINE cnparam_d3 diff --git a/src/qs_environment.F b/src/qs_environment.F index 3b78ab1e24..5d2df053cd 100644 --- a/src/qs_environment.F +++ b/src/qs_environment.F @@ -90,11 +90,11 @@ MODULE qs_environment USE hfx_types, ONLY: compare_hfx_sections,& hfx_create USE input_constants, ONLY: & - dispersion_d2, dispersion_d3, dispersion_d3bj, do_et_ddapc, do_method_am1, do_method_dftb, & - do_method_gapw, do_method_gapw_xc, do_method_gpw, do_method_lrigpw, do_method_mndo, & - do_method_mndod, do_method_ofgpw, do_method_pdg, do_method_pm3, do_method_pm6, & - do_method_pm6fm, do_method_pnnl, do_method_rigpw, do_method_rm1, do_method_xtb, & - do_qmmm_gauss, do_qmmm_swave, general_roks, hden_atomic, kg_tnadd_embed_ri, & + debug_run, dispersion_d2, dispersion_d3, dispersion_d3bj, do_et_ddapc, do_method_am1, & + do_method_dftb, do_method_gapw, do_method_gapw_xc, do_method_gpw, do_method_lrigpw, & + do_method_mndo, do_method_mndod, do_method_ofgpw, do_method_pdg, do_method_pm3, & + do_method_pm6, do_method_pm6fm, do_method_pnnl, do_method_rigpw, do_method_rm1, & + do_method_xtb, do_qmmm_gauss, do_qmmm_swave, general_roks, hden_atomic, kg_tnadd_embed_ri, & linear_response_run, rel_none, rel_trans_atom, smear_fermi_dirac, vdw_pairpot_dftd2, & vdw_pairpot_dftd3, vdw_pairpot_dftd3bj, vdw_pairpot_dftd4, wfi_gext_proj_nr, & wfi_gext_proj_qtr_nr, wfi_linear_ps_method_nr, wfi_linear_wf_method_nr, & @@ -268,8 +268,9 @@ CONTAINS CHARACTER(LEN=default_string_length) :: basis_type INTEGER :: ikind, method_id, nelectron_total, & nkind, nkp_grid(3) - LOGICAL :: do_active_space, do_admm_rpa, do_bse, do_ec_hfx, do_et, do_exx, do_gw, do_hfx, & - do_kpoints, do_linear_response, do_mp2, do_ri_mp2, do_ri_rpa, do_ri_sos_mp2, do_tddfpt, & + LOGICAL :: do_active_space, do_admm_rpa, do_bse, do_debug_fdiff, do_debug_forces, & + do_debug_stress_tensor, do_ec_hfx, do_et, do_exx, do_gw, do_hfx, do_kpoints, & + do_linear_response, do_mp2, do_ri_mp2, do_ri_rpa, do_ri_sos_mp2, do_tddfpt, & do_wfc_low_scaling, do_wfc_low_scaling_kpoints, do_xtb_tblite, is_identical, is_semi, & mp2_present, my_qmmm, qmmm_decoupl, same_except_frac, use_ref_cell REAL(KIND=dp), DIMENSION(:, :), POINTER :: rtmat @@ -411,6 +412,15 @@ CONTAINS END IF do_linear_response = .FALSE. IF (PRESENT(globenv)) do_linear_response = globenv%run_type_id == linear_response_run + do_debug_fdiff = .FALSE. + IF (PRESENT(globenv)) do_debug_fdiff = globenv%run_type_id == debug_run + IF (do_debug_fdiff .AND. PRESENT(root_section)) THEN + CALL section_vals_val_get(root_section, "DEBUG%DEBUG_FORCES", & + l_val=do_debug_forces) + CALL section_vals_val_get(root_section, "DEBUG%DEBUG_STRESS_TENSOR", & + l_val=do_debug_stress_tensor) + do_debug_fdiff = do_debug_forces .OR. do_debug_stress_tensor + END IF do_mp2 = .FALSE. do_ri_mp2 = .FALSE. do_ri_sos_mp2 = .FALSE. @@ -439,6 +449,7 @@ CONTAINS END IF CALL restrict_unsupported_atomic_kpoint_symmetry(kpoints, method_id, do_hfx, do_exx, do_gw, & do_tddfpt, do_active_space, do_linear_response, & + do_debug_fdiff, & do_mp2 .OR. do_ri_mp2 .OR. do_ri_sos_mp2, & do_ri_rpa .AND. .NOT. do_gw, do_bse, & do_wfc_low_scaling, do_wfc_low_scaling_kpoints, & @@ -659,6 +670,7 @@ CONTAINS !> \param do_tddfpt ... !> \param do_active_space ... !> \param do_linear_response ... +!> \param do_debug_fdiff ... !> \param do_mp2 ... !> \param do_rpa ... !> \param do_bse ... @@ -668,12 +680,13 @@ CONTAINS ! ************************************************************************************************** SUBROUTINE restrict_unsupported_atomic_kpoint_symmetry(kpoints, method_id, do_hfx, do_exx, do_gw, & do_tddfpt, do_active_space, do_linear_response, & + do_debug_fdiff, & do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & do_wfc_low_scaling_kpoints, do_xtb_tblite) TYPE(kpoint_type), POINTER :: kpoints INTEGER, INTENT(IN) :: method_id LOGICAL, INTENT(IN) :: do_hfx, do_exx, do_gw, do_tddfpt, do_active_space, & - do_linear_response, do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & + do_linear_response, do_debug_fdiff, do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & do_wfc_low_scaling_kpoints, do_xtb_tblite CHARACTER(LEN=default_string_length) :: kp_scheme, reason @@ -713,6 +726,7 @@ CONTAINS reason = unsupported_atomic_kpoint_symmetry_reason(method_id, do_hfx, do_exx, do_gw, & do_tddfpt, do_active_space, do_linear_response, & + do_debug_fdiff, & do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & do_wfc_low_scaling_kpoints, do_xtb_tblite) IF (LEN_TRIM(reason) == 0) RETURN @@ -745,6 +759,7 @@ CONTAINS reason = "" MARK_USED(do_gw) MARK_USED(do_mp2) + MARK_USED(do_xtb_tblite) IF (do_bse) THEN reason = "BSE" @@ -758,11 +773,6 @@ CONTAINS reason = "LINEAR_RESPONSE/DFPT" RETURN END IF - IF (do_xtb_tblite) THEN - reason = "tblite xTB" - RETURN - END IF - SELECT CASE (method_id) CASE (do_method_rigpw) reason = "RIGPW" @@ -786,6 +796,7 @@ CONTAINS !> \param do_tddfpt ... !> \param do_active_space ... !> \param do_linear_response ... +!> \param do_debug_fdiff ... !> \param do_mp2 ... !> \param do_rpa ... !> \param do_bse ... @@ -795,26 +806,24 @@ CONTAINS !> \return reason ! ************************************************************************************************** FUNCTION unsupported_atomic_kpoint_symmetry_reason(method_id, do_hfx, do_exx, do_gw, do_tddfpt, & - do_active_space, do_linear_response, do_mp2, do_rpa, & - do_bse, do_wfc_low_scaling, do_wfc_low_scaling_kpoints, & - do_xtb_tblite) RESULT(reason) + do_active_space, do_linear_response, do_debug_fdiff, & + do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & + do_wfc_low_scaling_kpoints, do_xtb_tblite) RESULT(reason) INTEGER, INTENT(IN) :: method_id LOGICAL, INTENT(IN) :: do_hfx, do_exx, do_gw, do_tddfpt, do_active_space, & - do_linear_response, do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & + do_linear_response, do_debug_fdiff, do_mp2, do_rpa, do_bse, do_wfc_low_scaling, & do_wfc_low_scaling_kpoints, do_xtb_tblite CHARACTER(LEN=default_string_length) :: reason reason = "" + MARK_USED(do_debug_fdiff) + MARK_USED(do_xtb_tblite) SELECT CASE (method_id) - CASE (do_method_dftb) - reason = "DFTB" CASE (do_method_lrigpw) reason = "LRIGPW" CASE (do_method_rigpw) reason = "RIGPW" - CASE (do_method_xtb) - reason = "xTB" CASE (do_method_mndo, do_method_mndod, do_method_am1, do_method_pm3, & do_method_pm6, do_method_pm6fm, do_method_pdg, do_method_rm1, do_method_pnnl) reason = "semiempirical methods" @@ -829,8 +838,6 @@ CONTAINS reason = "GW" ELSE IF (do_hfx .OR. do_exx) THEN reason = "HFX/HF" - ELSE IF (do_xtb_tblite) THEN - reason = "tblite xTB" ELSE IF (do_tddfpt) THEN reason = "TDDFPT/TDDFT" ELSE IF (do_active_space) THEN @@ -1062,7 +1069,8 @@ CONTAINS ewald_section => section_vals_get_subs_vals(poisson_section, "EWALD") print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION") CALL get_qs_kind_set(qs_kind_set, basis_rcut=ewald_rcut) - CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat) + CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & + cell_periodic=cell%perd) ALLOCATE (ewald_pw) CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section) CALL set_qs_env(qs_env, ewald_env=ewald_env, ewald_pw=ewald_pw) @@ -1156,10 +1164,10 @@ CONTAINS print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION") IF (gfn_type == 0) THEN CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & - silent=silent, pset="EEQ") + silent=silent, pset="EEQ", cell_periodic=cell%perd) ELSE CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & - silent=silent) + silent=silent, cell_periodic=cell%perd) END IF ALLOCATE (ewald_pw) CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section) diff --git a/src/qs_environment_methods.F b/src/qs_environment_methods.F index 918af5f6a5..eb0da3d6e8 100644 --- a/src/qs_environment_methods.F +++ b/src/qs_environment_methods.F @@ -261,7 +261,8 @@ CONTAINS CALL get_qs_env(qs_env=qs_env, ewald_env=ewald_env, ewald_pw=ewald_pw) CALL ewald_pw_grid_update(ewald_pw, ewald_env, cell%hmat) END IF - ELSE IF (dft_control%qs_control%xtb) THEN + ELSE IF (dft_control%qs_control%xtb .AND. & + (.NOT. dft_control%qs_control%xtb_control%do_tblite)) THEN IF (dft_control%qs_control%xtb_control%do_ewald) THEN ! rebuild Ewald environment CALL get_qs_env(qs_env=qs_env, ewald_env=ewald_env, ewald_pw=ewald_pw) diff --git a/src/qs_force.F b/src/qs_force.F index 1bf376709e..e8c3fb6733 100644 --- a/src/qs_force.F +++ b/src/qs_force.F @@ -77,7 +77,8 @@ MODULE qs_force velocity_gauge_nl_force USE se_core_core, ONLY: se_core_core_interaction USE se_core_matrix, ONLY: build_se_core_matrix - USE tblite_interface, ONLY: build_tblite_matrices + USE tblite_interface, ONLY: build_tblite_matrices,& + tb_reference_cli_compare USE virial_types, ONLY: symmetrize_virial,& virial_type USE xtb_matrices, ONLY: build_xtb_matrices @@ -448,6 +449,10 @@ CONTAINS END IF END IF + IF (dft_control%qs_control%xtb .AND. dft_control%qs_control%xtb_control%do_tblite) THEN + CALL tb_reference_cli_compare(qs_env) + END IF + output_unit = cp_print_key_unit_nr(logger, qs_env%input, "DFT%PRINT%DERIVATIVES", & extension=".Log") print_section => section_vals_get_subs_vals(qs_env%input, "DFT%PRINT%DERIVATIVES") diff --git a/src/qs_mixing_utils.F b/src/qs_mixing_utils.F index b13eba1f3a..695378696e 100644 --- a/src/qs_mixing_utils.F +++ b/src/qs_mixing_utils.F @@ -39,6 +39,8 @@ MODULE qs_mixing_utils PRIVATE CHARACTER(len=*), PARAMETER, PRIVATE :: moduleN = 'qs_mixing_utils' + INTEGER, PARAMETER, PRIVATE :: max_dftb_scc_vars = 1, & + max_xtb_scc_vars = 14 PUBLIC :: mixing_allocate, mixing_init, charge_mixing_init, & self_consistency_check @@ -177,13 +179,13 @@ CONTAINS END IF IF (charge_mixing) THEN - ! *** allocate buffer for charge mixing *** + ! *** allocate buffer for TB SCC variable mixing *** IF (mixing_method >= gspace_mixing_nr) THEN CPASSERT(.NOT. mixing_store%gmix_p) IF (dft_control%qs_control%dftb) THEN - max_shell = 1 + max_shell = max_dftb_scc_vars ELSEIF (dft_control%qs_control%xtb) THEN - max_shell = 5 + max_shell = max_xtb_scc_vars ELSE CPABORT('UNKNOWN METHOD') END IF @@ -652,7 +654,11 @@ CONTAINS ELEMENTAL SUBROUTINE charge_mixing_init(mixing_store) TYPE(mixing_storage_type), INTENT(INOUT) :: mixing_store - mixing_store%acharge = 0.0_dp + mixing_store%ncall = 0 + mixing_store%tb_scc_mixer_error = 0.0_dp + mixing_store%tb_scc_mixer_step = 0 + IF (ASSOCIATED(mixing_store%acharge)) mixing_store%acharge = 0.0_dp + IF (ASSOCIATED(mixing_store%dacharge)) mixing_store%dacharge = 0.0_dp END SUBROUTINE charge_mixing_init diff --git a/src/qs_scf.F b/src/qs_scf.F index b1d46bed08..36fec79c26 100644 --- a/src/qs_scf.F +++ b/src/qs_scf.F @@ -83,7 +83,7 @@ MODULE qs_scf cdft2ot, history_guess, ot2cdft, ot_precond_full_all, ot_precond_full_single, & ot_precond_full_single_inverse, ot_precond_none, ot_precond_s_inverse, & outer_scf_becke_constraint, outer_scf_hirshfeld_constraint, outer_scf_optimizer_broyden, & - outer_scf_optimizer_newton_ls + outer_scf_optimizer_newton_ls, tblite_scc_mixer_tblite USE input_section_types, ONLY: section_vals_get_subs_vals,& section_vals_type USE kinds, ONLY: default_path_length,& @@ -110,6 +110,7 @@ MODULE qs_scf print_inverse_jacobian,& restart_inverse_jacobian USE qs_cdft_types, ONLY: cdft_control_type + USE qs_charge_mixing, ONLY: charge_mixing_scc_error USE qs_charges_types, ONLY: qs_charges_type USE qs_density_matrices, ONLY: calculate_density_matrix USE qs_density_mixing_types, ONLY: gspace_mixing_nr @@ -174,6 +175,8 @@ MODULE qs_scf USE smeagol_interface, ONLY: run_smeagol_bulktrans,& run_smeagol_emtrans USE tblite_interface, ONLY: tb_get_energy,& + tb_native_scc_mixer_active,& + tb_scf_mixer_error,& tb_update_charges #include "./base/base_uses.f90" @@ -357,8 +360,9 @@ CONTAINS INTEGER :: ext_master_id, handle, handle2, i_tmp, & ic, ispin, iter_count, output_unit, & scf_energy_message_tag, total_steps - LOGICAL :: diis_step, do_kpoints, energy_only, exit_inner_loop, exit_outer_loop, & - inner_loop_converged, just_energy, outer_loop_converged + LOGICAL :: density_full_step, diis_step, do_kpoints, energy_only, exit_inner_loop, & + exit_outer_loop, inner_loop_converged, internal_tblite_density_full_step, & + internal_tblite_mixer, just_energy, outer_loop_converged, tblite_native_mixer REAL(KIND=dp) :: t1, t2 REAL(KIND=dp), DIMENSION(3) :: res_val_3 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set @@ -410,6 +414,16 @@ CONTAINS results=results, & pw_env=pw_env, & para_env=para_env) + tblite_native_mixer = dft_control%qs_control%xtb_control%do_tblite .AND. & + tb_native_scc_mixer_active(dft_control) + internal_tblite_mixer = (dft_control%qs_control%dftb .AND. & + dft_control%qs_control%dftb_control%tblite_scc_mixer == tblite_scc_mixer_tblite) .OR. & + (dft_control%qs_control%xtb .AND. & + .NOT. dft_control%qs_control%xtb_control%do_tblite .AND. & + dft_control%qs_control%xtb_control%tblite_scc_mixer == tblite_scc_mixer_tblite) + internal_tblite_density_full_step = dft_control%qs_control%xtb .AND. & + .NOT. dft_control%qs_control%xtb_control%do_tblite .AND. & + dft_control%qs_control%xtb_control%tblite_scc_mixer == tblite_scc_mixer_tblite CALL qs_rho_get(rho, rho_ao_kp=rho_ao_kp) @@ -530,7 +544,29 @@ CONTAINS CALL tb_get_energy(qs_env, qs_env%tb_tblite, energy) END IF - CALL qs_scf_density_mixing(scf_env, rho, para_env, diis_step) + density_full_step = diis_step .OR. tblite_native_mixer .OR. internal_tblite_density_full_step + CALL qs_scf_density_mixing(scf_env, rho, para_env, density_full_step) + IF (dft_control%qs_control%xtb_control%do_tblite) THEN + scf_env%iter_delta = MAX(scf_env%iter_delta, & + tb_scf_mixer_error(dft_control, qs_env%tb_tblite, & + scf_control%eps_scf)) + END IF + IF (dft_control%qs_control%dftb .OR. & + (dft_control%qs_control%xtb .AND. .NOT. dft_control%qs_control%xtb_control%do_tblite)) THEN + scf_env%iter_delta = MAX(scf_env%iter_delta, & + charge_mixing_scc_error(scf_env%mixing_store, scf_control%eps_scf)) + END IF + IF (tblite_native_mixer) THEN + scf_env%iter_param = dft_control%qs_control%xtb_control%tblite_mixer_damping + scf_env%iter_method = "TBLite/Diag" + ELSEIF (internal_tblite_mixer) THEN + scf_env%iter_method = "TBLite/Diag" + IF (dft_control%qs_control%dftb) THEN + scf_env%iter_param = dft_control%qs_control%dftb_control%tblite_mixer_damping + ELSE + scf_env%iter_param = dft_control%qs_control%xtb_control%tblite_mixer_damping + END IF + END IF t2 = m_walltime() @@ -550,7 +586,7 @@ CONTAINS ! is really the last SCF step IF (exit_inner_loop) THEN - CALL qs_scf_inner_finalize(scf_env, qs_env, diis_step, output_unit) + CALL qs_scf_inner_finalize(scf_env, qs_env, density_full_step, output_unit) CALL qs_scf_check_outer_exit(qs_env, scf_env, scf_control, should_stop, & outer_loop_converged, exit_outer_loop) diff --git a/src/qs_scf_loop_utils.F b/src/qs_scf_loop_utils.F index 5d7cdf86ea..9a2b8f6e20 100644 --- a/src/qs_scf_loop_utils.F +++ b/src/qs_scf_loop_utils.F @@ -62,6 +62,7 @@ MODULE qs_scf_loop_utils USE scf_control_types, ONLY: scf_control_type,& smear_type USE smeagol_interface, ONLY: run_smeagol_emtrans + USE tblite_interface, ONLY: tb_native_scc_mixer_active #include "./base/base_uses.f90" IMPLICIT NONE @@ -130,7 +131,9 @@ CONTAINS CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_new_mos' INTEGER :: handle, ispin - LOGICAL :: has_unit_metric, skip_diag_sub + LOGICAL :: disable_diis, has_unit_metric, & + skip_diag_sub + REAL(KIND=dp) :: saved_eps_diis TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: matrix_ks, matrix_s TYPE(dft_control_type), POINTER :: dft_control TYPE(mo_set_type), DIMENSION(:), POINTER :: mos @@ -149,6 +152,12 @@ CONTAINS dft_control=dft_control, & has_unit_metric=has_unit_metric) scf_env%iter_param = 0.0_dp + disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. & + tb_native_scc_mixer_active(dft_control) + IF (disable_diis) THEN + saved_eps_diis = scf_control%eps_diis + scf_control%eps_diis = 0.0_dp + END IF ! transfer total_zeff_corr from qs_env to scf_env only if ! correct_el_density_dip is switched on [SGh] @@ -275,6 +284,7 @@ CONTAINS qs_env%mo_derivs, energy%total, & matrix_s, energy_only=energy_only, has_unit_metric=has_unit_metric) END SELECT + IF (disable_diis) scf_control%eps_diis = saved_eps_diis energy%kTS = 0.0_dp energy%efermi = 0.0_dp @@ -309,8 +319,8 @@ CONTAINS CHARACTER(LEN=*), PARAMETER :: routineN = 'qs_scf_new_mos_kp' INTEGER :: handle, ispin - LOGICAL :: has_unit_metric - REAL(dp) :: diis_error + LOGICAL :: disable_diis, has_unit_metric + REAL(dp) :: diis_error, saved_eps_diis TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_ks, matrix_s TYPE(dft_control_type), POINTER :: dft_control TYPE(kpoint_type), POINTER :: kpoints @@ -323,6 +333,12 @@ CONTAINS CALL get_qs_env(qs_env=qs_env, dft_control=dft_control, kpoints=kpoints) scf_env%iter_param = 0.0_dp + disable_diis = dft_control%qs_control%xtb_control%do_tblite .AND. & + tb_native_scc_mixer_active(dft_control) + IF (disable_diis) THEN + saved_eps_diis = scf_control%eps_diis + scf_control%eps_diis = 0.0_dp + END IF IF (dft_control%roks) & CPABORT("KP code: ROKS method not available: ") @@ -385,6 +401,7 @@ CONTAINS END IF CALL run_smeagol_emtrans(qs_env, last=.FALSE., iter=scf_env%iter_count, rho_ao_kp=scf_env%p_mix_new) END SELECT + IF (disable_diis) scf_control%eps_diis = saved_eps_diis CALL get_qs_env(qs_env=qs_env, energy=energy) energy%kTS = 0.0_dp diff --git a/src/qs_tddfpt2_stda_utils.F b/src/qs_tddfpt2_stda_utils.F index a729824d8e..68840bfd85 100644 --- a/src/qs_tddfpt2_stda_utils.F +++ b/src/qs_tddfpt2_stda_utils.F @@ -138,7 +138,8 @@ CONTAINS ewald_section => section_vals_get_subs_vals(poisson_section, "EWALD") print_section => section_vals_get_subs_vals(qs_env%input, "PRINT%GRID_INFORMATION") CALL get_qs_env(qs_env, cell=cell, cell_ref=cell_ref) - CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat) + CALL read_ewald_section_tb(ewald_env, ewald_section, cell_ref%hmat, & + cell_periodic=cell%perd) ALLOCATE (ewald_pw) CALL ewald_pw_create(ewald_pw, ewald_env, cell, cell_ref, print_section=print_section) work%ewald_env => ewald_env diff --git a/src/qs_wf_history_types.F b/src/qs_wf_history_types.F index 0a669ec7be..5bfa39f9d5 100644 --- a/src/qs_wf_history_types.F +++ b/src/qs_wf_history_types.F @@ -37,7 +37,7 @@ MODULE qs_wf_history_types PUBLIC :: qs_wf_snapshot_type, & qs_wf_history_type, qs_wf_history_p_type - PUBLIC :: wfi_retain, wfi_release, wfi_get_snapshot + PUBLIC :: wfi_retain, wfi_release, wfi_clear, wfi_get_snapshot ! ************************************************************************************************** !> \brief represent a past snapshot of the wavefunction. @@ -215,6 +215,32 @@ CONTAINS NULLIFY (wf_history) END SUBROUTINE wfi_release +! ************************************************************************************************** +!> \brief Clear stored wavefunction snapshots while preserving history settings. +!> \param wf_history the wf_history to clear +! ************************************************************************************************** + SUBROUTINE wfi_clear(wf_history) + TYPE(qs_wf_history_type), POINTER :: wf_history + + INTEGER :: i + + IF (ASSOCIATED(wf_history)) THEN + CPASSERT(wf_history%ref_count > 0) + IF (ASSOCIATED(wf_history%past_states)) THEN + DO i = 1, SIZE(wf_history%past_states) + IF (ASSOCIATED(wf_history%past_states(i)%snapshot)) THEN + CALL wfs_release(wf_history%past_states(i)%snapshot) + DEALLOCATE (wf_history%past_states(i)%snapshot) + NULLIFY (wf_history%past_states(i)%snapshot) + END IF + END DO + END IF + wf_history%snapshot_count = 0 + wf_history%last_state_index = 1 + END IF + + END SUBROUTINE wfi_clear + ! ************************************************************************************************** !> \brief returns a snapshot, the first being the latest snapshot !> \param wf_history the plage where to get the snapshot diff --git a/src/tblite_interface.F b/src/tblite_interface.F index c49dcd9865..60ddb3abe7 100644 --- a/src/tblite_interface.F +++ b/src/tblite_interface.F @@ -17,12 +17,16 @@ MODULE tblite_interface USE mctc_env, ONLY: error_type USE mctc_io, ONLY: structure_type, new USE mctc_io_symbols, ONLY: symbol_to_number + USE tblite_adjlist, ONLY: adjacency_list, new_adjacency_list USE tblite_basis_type, ONLY: get_cutoff USE tblite_container, ONLY: container_cache + USE tblite_cutoff, ONLY: get_lattice_points USE tblite_integral_multipole, ONLY: multipole_cgto, multipole_grad_cgto, maxl, msao + USE tblite_integral_type, ONLY: integral_type, new_integral + USE tblite_scf, ONLY: get_mixer_dimension, new_mixer USE tblite_scf_info, ONLY: scf_info, atom_resolved, shell_resolved, & orbital_resolved, not_used - USE tblite_scf_potential, ONLY: potential_type, new_potential + USE tblite_scf_potential, ONLY: potential_type, new_potential, add_pot_to_h1 USE tblite_wavefunction_type, ONLY: wavefunction_type, new_wavefunction USE tblite_xtb_calculator, ONLY: xtb_calculator, new_xtb_calculator USE tblite_xtb_gfn1, ONLY: new_gfn1_calculator @@ -40,7 +44,7 @@ MODULE tblite_interface & allocate_gto_basis_set, write_gto_basis_set, process_gto_basis USE cell_types, ONLY: cell_type, get_cell USE cp_blacs_env, ONLY: cp_blacs_env_type - USE cp_control_types, ONLY: dft_control_type + USE cp_control_types, ONLY: dft_control_type, xtb_reference_cli_type USE cp_dbcsr_api, ONLY: dbcsr_type, dbcsr_p_type, dbcsr_create, dbcsr_add, & dbcsr_get_block_p, dbcsr_finalize, & dbcsr_iterator_type, dbcsr_iterator_blocks_left, & @@ -53,9 +57,12 @@ MODULE tblite_interface cp_logger_type, cp_logger_get_default_io_unit USE cp_output_handling, ONLY: cp_print_key_should_output, & cp_print_key_unit_nr, cp_print_key_finished_output - USE input_constants, ONLY: gfn1xtb, gfn2xtb, ipea1xtb + USE cp_units, ONLY: cp_unit_from_cp2k + USE input_constants, ONLY: gfn1xtb, gfn2xtb, ipea1xtb, & + tblite_scc_mixer_auto, tblite_scc_mixer_cp2k, & + tblite_scc_mixer_none, tblite_scc_mixer_tblite USE input_section_types, ONLY: section_vals_val_get - USE kinds, ONLY: dp, default_string_length + USE kinds, ONLY: default_path_length, default_string_length, dp USE kpoint_types, ONLY: get_kpoint_info, kpoint_type USE memory_utilities, ONLY: reallocate USE message_passing, ONLY: mp_para_env_type @@ -66,10 +73,10 @@ MODULE tblite_interface USE qs_condnum, ONLY: overlap_condnum USE qs_energy_types, ONLY: qs_energy_type USE qs_environment_types, ONLY: get_qs_env, qs_environment_type - USE qs_force_types, ONLY: qs_force_type + USE qs_force_types, ONLY: qs_force_type, total_qs_force USE qs_integral_utils, ONLY: basis_set_list_setup, get_memory_usage USE qs_kind_types, ONLY: get_qs_kind, qs_kind_type, get_qs_kind_set - USE qs_ks_types, ONLY: qs_ks_env_type, set_ks_env + USE qs_ks_types, ONLY: get_ks_env, qs_ks_env_type, set_ks_env USE qs_neighbor_list_types, ONLY: neighbor_list_iterator_create, neighbor_list_iterate, & get_iterator_info, neighbor_list_set_p_type, & neighbor_list_iterator_p_type, neighbor_list_iterator_release @@ -77,6 +84,7 @@ MODULE tblite_interface USE cp_dbcsr_output, ONLY: cp_dbcsr_write_sparse_matrix USE qs_rho_types, ONLY: qs_rho_get, qs_rho_type USE qs_scf_types, ONLY: qs_scf_env_type + USE scf_control_types, ONLY: scf_control_type USE input_section_types, ONLY: section_vals_get_subs_vals, section_vals_type USE string_utilities, ONLY: integer_to_string USE tblite_types, ONLY: tblite_type, deallocate_tblite_type, allocate_tblite_type @@ -94,12 +102,16 @@ MODULE tblite_interface INTEGER, PARAMETER :: dip_n = 3 INTEGER, PARAMETER :: quad_n = 6 REAL(KIND=dp), PARAMETER :: same_atom = 0.00001_dp + REAL(KIND=dp), PARAMETER :: tblite_scc_pconv = 2.0E-5_dp PUBLIC :: tb_set_calculator, tb_init_geometry, tb_init_wf PUBLIC :: tb_get_basis, build_tblite_matrices PUBLIC :: tb_get_energy, tb_update_charges, tb_ham_add_coulomb + PUBLIC :: tb_native_scc_mixer_active + PUBLIC :: tb_scf_mixer_error PUBLIC :: tb_get_multipole PUBLIC :: tb_derive_dH_diag, tb_derive_dH_off + PUBLIC :: tb_reference_cli_compare CONTAINS @@ -181,6 +193,7 @@ CONTAINS CHARACTER(LEN=*), PARAMETER :: routineN = 'tblite_update_geometry' + TYPE(cell_type), POINTER :: cell TYPE(particle_type), DIMENSION(:), POINTER :: particle_set INTEGER :: iatom, natom REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: xyz @@ -189,7 +202,8 @@ CONTAINS CALL timeset(routineN, handle) !get info from environment vaiarable - CALL get_qs_env(qs_env=qs_env, particle_set=particle_set) + NULLIFY (cell) + CALL get_qs_env(qs_env=qs_env, particle_set=particle_set, cell=cell) !get information about particles natom = SIZE(particle_set) @@ -198,6 +212,7 @@ CONTAINS xyz(:, iatom) = particle_set(iatom)%r(:) END DO tb%mol%xyz(:, :) = xyz + tb%mol%lattice(:, :) = cell%hmat DEALLOCATE (xyz) @@ -232,6 +247,7 @@ CONTAINS CPABORT("tblite: no support shell resolved quadrupole moment") CALL new_wavefunction(tb%wfn, tb%mol%nat, tb%calc%bas%nsh, tb%calc%bas%nao, nSpin, 0.0_dp) + CALL tb_reset_mixer(tb) CALL new_potential(tb%pot, tb%mol, tb%calc%bas, tb%wfn%nspin) @@ -248,6 +264,123 @@ CONTAINS END SUBROUTINE tb_init_wf +! ************************************************************************************************** +!> \brief Reset tblite's internal SCC mixer for a new CP2K SCF cycle. +!> \param tb ... +! ************************************************************************************************** + SUBROUTINE tb_reset_mixer(tb) + + TYPE(tblite_type), POINTER :: tb + +#if defined(__TBLITE) + + TYPE(scf_info) :: info + + info = tb%calc%variable_info() + IF (ALLOCATED(tb%mixer)) DEALLOCATE (tb%mixer) + CALL new_mixer(tb%mixer, tb%calc%max_iter, & + tb%wfn%nspin*get_mixer_dimension(tb%mol, tb%calc%bas, info), & + tb%calc%mixer_damping) + +#else + MARK_USED(tb) + CPABORT("Built without TBLITE") +#endif + + END SUBROUTINE tb_reset_mixer + +! ************************************************************************************************** +!> \brief Configure tblite's internal SCC mixer from CP2K input. +!> \param tb ... +!> \param max_scf ... +!> \param damping ... +! ************************************************************************************************** + SUBROUTINE tb_configure_mixer(tb, max_scf, damping) + + TYPE(tblite_type), POINTER :: tb + INTEGER, INTENT(IN) :: max_scf + REAL(KIND=dp), INTENT(IN) :: damping + +#if defined(__TBLITE) + + IF (max_scf < 1) CPABORT("tblite SCC mixer MAX_SCF must be positive") + IF (damping <= 0.0_dp) CPABORT("tblite SCC mixer damping must be positive") + + tb%calc%max_iter = max_scf + tb%calc%mixer_damping = damping + +#else + MARK_USED(tb) + MARK_USED(max_scf) + MARK_USED(damping) + CPABORT("Built without TBLITE") +#endif + + END SUBROUTINE tb_configure_mixer + +! ************************************************************************************************** +!> \brief Return whether the tblite native SCC mixer is active for this run. +!> \param dft_control ... +!> \return ... +! ************************************************************************************************** + FUNCTION tb_native_scc_mixer_active(dft_control) RESULT(use_native_mixer) + + TYPE(dft_control_type), POINTER :: dft_control + LOGICAL :: use_native_mixer + + use_native_mixer = .FALSE. + IF (.NOT. ASSOCIATED(dft_control)) RETURN + + SELECT CASE (dft_control%qs_control%xtb_control%tblite_scc_mixer) + CASE (tblite_scc_mixer_auto) + use_native_mixer = .TRUE. + CASE (tblite_scc_mixer_tblite) + use_native_mixer = .TRUE. + CASE (tblite_scc_mixer_cp2k, tblite_scc_mixer_none) + use_native_mixer = .FALSE. + CASE DEFAULT + CPABORT("Unknown tblite SCC mixer") + END SELECT + + END FUNCTION tb_native_scc_mixer_active + +! ************************************************************************************************** +!> \brief Return the native tblite SCC mixer residual for CP2K SCF convergence. +!> \param dft_control ... +!> \param tb ... +!> \param eps_scf ... +!> \return ... +! ************************************************************************************************** + FUNCTION tb_scf_mixer_error(dft_control, tb, eps_scf) RESULT(mixer_error) + + TYPE(dft_control_type), POINTER :: dft_control + TYPE(tblite_type), POINTER :: tb + REAL(KIND=dp), INTENT(IN) :: eps_scf + REAL(KIND=dp) :: mixer_error + + REAL(KIND=dp) :: raw_error + + mixer_error = 0.0_dp + +#if defined(__TBLITE) + IF (.NOT. ASSOCIATED(tb)) RETURN + IF (.NOT. tb_native_scc_mixer_active(dft_control)) RETURN + IF (ALLOCATED(tb%mixer)) THEN + raw_error = REAL(tb%mixer%get_error(), KIND=dp) + IF (eps_scf > 0.0_dp) THEN + mixer_error = eps_scf*raw_error/tblite_scc_pconv + ELSE + mixer_error = raw_error + END IF + END IF +#else + MARK_USED(dft_control) + MARK_USED(tb) + MARK_USED(eps_scf) +#endif + + END FUNCTION tb_scf_mixer_error + ! ************************************************************************************************** !> \brief ... !> \param tb ... @@ -312,6 +445,7 @@ CONTAINS tb%grad = 0.0_dp CALL tb%calc%halogen%get_engrad(tb%mol, hcache, tb%e_hal, & & tb%grad, tb%sigma) + CALL tb_dump_sigma_component("after_halogen", tb%sigma, para_env) CALL tb_grad2force(qs_env, tb, para_env, 0) ELSE CALL tb%calc%halogen%get_engrad(tb%mol, hcache, tb%e_hal) @@ -324,6 +458,7 @@ CONTAINS tb%grad = 0.0_dp CALL tb%calc%repulsion%get_engrad(tb%mol, rcache, tb%e_rep, & & tb%grad, tb%sigma) + CALL tb_dump_sigma_component("after_repulsion", tb%sigma, para_env) CALL tb_grad2force(qs_env, tb, para_env, 1) ELSE CALL tb%calc%repulsion%get_engrad(tb%mol, rcache, tb%e_rep) @@ -336,6 +471,7 @@ CONTAINS tb%grad = 0.0_dp CALL tb%calc%dispersion%get_engrad(tb%mol, tb%dcache, tb%e_disp, & & tb%grad, tb%sigma) + CALL tb_dump_sigma_component("after_dispersion_static", tb%sigma, para_env) CALL tb_grad2force(qs_env, tb, para_env, 2) ELSE CALL tb%calc%dispersion%get_engrad(tb%mol, tb%dcache, tb%e_disp) @@ -568,19 +704,24 @@ CONTAINS CHARACTER(LEN=*), PARAMETER :: routineN = 'build_tblite_matrices' - INTEGER :: handle, maxder, nderivatives, nimg, img, nkind, i, ic, iw, & - iatom, jatom, ikind, jkind, iset, jset, n1, n2, icol, irow, & - ia, ib, sgfa, sgfb, atom_a, atom_b, & - ldsab, nseta, nsetb, natorb_a, natorb_b, sgfa0 + INTEGER :: handle, maxder, nderivatives, nimg, img, nkind, i, j, & + ic, iw, iatom, jatom, ikind, jkind, iset, jset, n1, n2, icol, & + irow, ia, ib, sgfa, sgfb, atom_a, atom_b, ldsab, nseta, nsetb, & + natorb_a, natorb_b, sgfa0, mp_test_mode, i0, j0 LOGICAL :: found, norml1, norml2, use_arnoldi REAL(KIND=dp) :: dr, rr INTEGER, DIMENSION(3) :: cell REAL(KIND=dp) :: hij, shpoly REAL(KIND=dp), DIMENSION(2) :: condnum REAL(KIND=dp), DIMENSION(3) :: rij +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value +#endif INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind - REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: owork - REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: oint, sint, hint + INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: owork, native_s, native_h, native_lattr + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: oint, sint, hint, native_dip, native_quad INTEGER, DIMENSION(:), POINTER :: la_max, la_min, lb_max, lb_min INTEGER, DIMENSION(:), POINTER :: npgfa, npgfb, nsgfa, nsgfb INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb @@ -589,6 +730,7 @@ CONTAINS REAL(KIND=dp), DIMENSION(:, :), POINTER :: sblock, fblock TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set + TYPE(adjacency_list) :: native_list TYPE(atprop_type), POINTER :: atprop TYPE(cp_blacs_env_type), POINTER :: blacs_env TYPE(cp_logger_type), POINTER :: logger @@ -597,6 +739,7 @@ CONTAINS TYPE(qs_force_type), DIMENSION(:), POINTER :: force TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list + TYPE(kpoint_type), POINTER :: kpoints TYPE(neighbor_list_set_p_type), DIMENSION(:), POINTER :: sab_orb TYPE(neighbor_list_iterator_p_type), & DIMENSION(:), POINTER :: nl_iterator @@ -611,9 +754,15 @@ CONTAINS CALL timeset(routineN, handle) + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif + NULLIFY (ks_env, energy, atomic_kind_set, qs_kind_set) NULLIFY (matrix_h, matrix_s, atprop, dft_control) - NULLIFY (sab_orb, rho, tb) + NULLIFY (sab_orb, rho, tb, kpoints, cell_to_index) CALL get_qs_env(qs_env=qs_env, & ks_env=ks_env, para_env=para_env, & @@ -645,9 +794,17 @@ CONTAINS IF (ALLOCATED(tb%dcndL)) DEALLOCATE (tb%dcndL) ALLOCATE (tb%dcndL(3, 3, tb%mol%nat)) END IF + ELSE + IF (ALLOCATED(tb%grad)) DEALLOCATE (tb%grad) + IF (ALLOCATED(tb%dcndr)) DEALLOCATE (tb%dcndr) + IF (ALLOCATED(tb%dcndL)) DEALLOCATE (tb%dcndL) END IF maxder = ncoset(nderivatives) nimg = dft_control%nimages + IF (nimg > 1) THEN + CALL get_ks_env(ks_env=ks_env, kpoints=kpoints) + CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index) + END IF !intialise hamiltonian CALL tb_init_ham(qs_env, tb, para_env) @@ -689,12 +846,66 @@ CONTAINS CALL dbcsr_allocate_matrix_set(matrix_h, 1, nimg) DO img = 1, nimg ALLOCATE (matrix_h(1, img)%matrix) - CALL dbcsr_create(matrix_h(1, img)%matrix, template=matrix_s(1, 1)%matrix, & + CALL dbcsr_create(matrix_h(1, img)%matrix, template=matrix_s(1, img)%matrix, & name="HAMILTONIAN MATRIX") CALL cp_dbcsr_alloc_block_from_nbl(matrix_h(1, img)%matrix, sab_orb) END DO CALL set_ks_env(ks_env, matrix_h_kp=matrix_h) + IF (mp_test_mode == 81 .OR. mp_test_mode == 82 .OR. & + mp_test_mode == 232 .OR. mp_test_mode == 233) THEN + IF (nimg > 1) CPABORT("Native tblite matrix test with k-points not implemented") + ALLOCATE (native_s(tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_h(tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_dip(dip_n, tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_quad(quad_n, tb%calc%bas%nao, tb%calc%bas%nao)) + CALL get_lattice_points(tb%mol%periodic, tb%mol%lattice, get_cutoff(tb%calc%bas, 1.0_dp), native_lattr) + CALL new_adjacency_list(native_list, tb%mol, native_lattr, get_cutoff(tb%calc%bas, 1.0_dp)) + CALL get_hamiltonian(tb%mol, native_lattr, native_list, tb%calc%bas, tb%calc%h0, tb%selfenergy, & + native_s, native_dip, native_quad, native_h) + + NULLIFY (nl_iterator) + CALL neighbor_list_iterator_create(nl_iterator, sab_orb) + DO WHILE (neighbor_list_iterate(nl_iterator) == 0) + CALL get_iterator_info(nl_iterator, iatom=iatom, jatom=jatom) + icol = MAX(iatom, jatom) + irow = MIN(iatom, jatom) + i0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(irow) + 1) + j0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(icol) + 1) + + NULLIFY (sblock, fblock) + CALL dbcsr_get_block_p(matrix=matrix_s(1, 1)%matrix, row=irow, col=icol, BLOCK=sblock, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=matrix_h(1, 1)%matrix, row=irow, col=icol, BLOCK=fblock, found=found) + CPASSERT(found) + + DO j = 1, SIZE(sblock, 1) + DO i = 1, SIZE(sblock, 2) + sblock(j, i) = native_s(i0 + j, j0 + i) + fblock(j, i) = native_h(i0 + j, j0 + i) + END DO + END DO + END DO + CALL neighbor_list_iterator_release(nl_iterator) + + DO img = 1, nimg + DO i = 1, SIZE(matrix_s, 1) + CALL dbcsr_finalize(matrix_s(i, img)%matrix) + END DO + DO i = 1, SIZE(matrix_h, 1) + CALL dbcsr_finalize(matrix_h(i, img)%matrix) + END DO + END DO + + IF (dft_control%qs_control%xtb_control%tblite_method == gfn2xtb) & + CALL tb_get_multipole(qs_env, tb) + + DEALLOCATE (native_s, native_h, native_dip, native_quad, native_lattr) + DEALLOCATE (basis_set_list) + CALL timestop(handle) + RETURN + END IF + ! loop over all atom pairs with a non-zero overlap (sab_orb) NULLIFY (nl_iterator) CALL neighbor_list_iterator_create(nl_iterator, sab_orb) @@ -713,7 +924,12 @@ CONTAINS dr = NORM2(rij(:)) - ic = 1 + IF (nimg == 1) THEN + ic = 1 + ELSE + ic = cell_to_index(cell(1), cell(2), cell(3)) + CPASSERT(ic > 0) + END IF NULLIFY (sblock) CALL dbcsr_get_block_p(matrix=matrix_s(1, ic)%matrix, & row=irow, col=icol, BLOCK=sblock, found=found) @@ -913,44 +1129,115 @@ CONTAINS #if defined(__TBLITE) - INTEGER :: iatom, ikind, is, ns, atom_a, ii, im - INTEGER :: nimg, nkind, nsgf, natorb, na + INTEGER :: iatom, ikind, is, ns, atom_a, ii, im, irow, icol, i, j + INTEGER :: iao, jao, ish, ispin, i0, j0, nspin + INTEGER :: nimg, nkind, nsgf, natorb, na, n_mix_cols, mix_offset INTEGER :: n_atom, max_orb, max_shell - LOGICAL :: do_dipole, do_quadrupole - REAL(KIND=dp) :: norm + INTEGER :: mp_test_mode, raw_state_status, raw_state_unit, & + state_status, state_unit, last_mix_slot, ia_local, ns_mix + LOGICAL :: discard_mixed_output, do_combined_mixing, do_dipole, do_quadrupole, & + native_sign_mixing, phased_combined_mixing, skip_charge_mixing, & + reuse_native_input, skip_scf_dispersion, skip_scf_dispersion_energy, & + skip_scf_dispersion_gradient, skip_scf_dispersion_potential, & + use_native_mixer, use_no_mixer + REAL(KIND=dp) :: mix_alpha, norm, moment_alpha, new_charge, new_moment, pao +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value +#endif + CHARACTER(LEN=default_path_length) :: raw_state_file, state_file INTEGER, DIMENSION(5) :: occ INTEGER, DIMENSION(25) :: lao INTEGER, DIMENSION(25) :: nao - REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ch_atom, ch_shell, ch_ref, ch_orb - REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: aocg, ao_dip, ao_quad + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ch_atom, ch_shell, ch_ref, ch_orb, mix_vars, prev_vars + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: aocg, ao_dip, ao_quad, native_lattr + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: native_p TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set + TYPE(adjacency_list) :: native_list + TYPE(dbcsr_iterator_type) :: iter TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s, matrix_p TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: p_matrix TYPE(dbcsr_type), POINTER :: s_matrix + TYPE(error_type), ALLOCATABLE :: error + TYPE(integral_type) :: native_ints TYPE(mp_para_env_type), POINTER :: para_env TYPE(particle_type), DIMENSION(:), POINTER :: particle_set + REAL(KIND=dp), DIMENSION(:, :), POINTER :: p_block TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set TYPE(qs_rho_type), POINTER :: rho TYPE(qs_scf_env_type), POINTER :: scf_env + TYPE(scf_control_type), POINTER :: scf_control TYPE(xtb_atom_type), POINTER :: xtb_kind ! also compute multipoles needed by GFN2 do_dipole = .FALSE. do_quadrupole = .FALSE. + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif + skip_scf_dispersion = .FALSE. +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DEBUG_SKIP_SCF_DISPERSION", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) skip_scf_dispersion +#endif + skip_scf_dispersion_energy = skip_scf_dispersion + skip_scf_dispersion_gradient = skip_scf_dispersion + skip_scf_dispersion_potential = skip_scf_dispersion +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DEBUG_SKIP_SCF_DISPERSION_ENERGY", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) skip_scf_dispersion_energy + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DEBUG_SKIP_SCF_DISPERSION_GRADIENT", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) skip_scf_dispersion_gradient + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DEBUG_SKIP_SCF_DISPERSION_POTENTIAL", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) skip_scf_dispersion_potential +#endif + SELECT CASE (dft_control%qs_control%xtb_control%tblite_scc_mixer) + CASE (tblite_scc_mixer_auto) + use_native_mixer = tb_native_scc_mixer_active(dft_control) + use_no_mixer = .FALSE. + CASE (tblite_scc_mixer_tblite) + use_native_mixer = .TRUE. + use_no_mixer = .FALSE. + CASE (tblite_scc_mixer_cp2k) + use_native_mixer = .FALSE. + use_no_mixer = .FALSE. + CASE (tblite_scc_mixer_none) + use_native_mixer = .FALSE. + use_no_mixer = .TRUE. + CASE DEFAULT + CPABORT("Unknown tblite SCC mixer") + END SELECT ! compute mulliken charges required for charge update - NULLIFY (particle_set, qs_kind_set, atomic_kind_set) + NULLIFY (particle_set, qs_kind_set, atomic_kind_set, scf_control) CALL get_qs_env(qs_env=qs_env, scf_env=scf_env, particle_set=particle_set, qs_kind_set=qs_kind_set, & - atomic_kind_set=atomic_kind_set, matrix_s_kp=matrix_s, rho=rho, para_env=para_env) + atomic_kind_set=atomic_kind_set, matrix_s_kp=matrix_s, rho=rho, para_env=para_env, & + scf_control=scf_control) + IF (use_native_mixer .AND. use_rho .AND. (.NOT. calculate_forces) .AND. & + scf_env%iter_count == 1) THEN + CALL tb_configure_mixer(tb, scf_control%max_scf, & + dft_control%qs_control%xtb_control%tblite_mixer_damping) + CALL tb_reset_mixer(tb) + END IF NULLIFY (matrix_p) IF (use_rho) THEN CALL qs_rho_get(rho, rho_ao_kp=matrix_p) - IF (ASSOCIATED(tb%dipbra)) do_dipole = .TRUE. - IF (ASSOCIATED(tb%quadbra)) do_quadrupole = .TRUE. ELSE matrix_p => scf_env%p_mix_new END IF + IF (ASSOCIATED(tb%dipbra)) do_dipole = .TRUE. + IF (ASSOCIATED(tb%quadbra)) do_quadrupole = .TRUE. + reuse_native_input = .FALSE. + IF (use_native_mixer .AND. scf_env%iter_count == 1) THEN + reuse_native_input = ANY(ABS(tb%wfn%qsh) > 1.0E-14_dp) + IF (do_dipole) reuse_native_input = reuse_native_input .OR. & + ANY(ABS(tb%wfn%dpat) > 1.0E-14_dp) + IF (do_quadrupole) reuse_native_input = reuse_native_input .OR. & + ANY(ABS(tb%wfn%qpat) > 1.0E-14_dp) + END IF n_atom = SIZE(particle_set) nkind = SIZE(atomic_kind_set) nimg = dft_control%nimages @@ -977,8 +1264,15 @@ CONTAINS ch_ref = 0.0_dp IF (nimg > 1) THEN CALL ao_charges(matrix_p, matrix_s, aocg, para_env) - IF (do_dipole .OR. do_quadrupole) THEN - CPABORT("missing contraction with density matrix for multiple k-points") + IF (do_dipole) THEN + DO im = 1, dip_n + CALL contract_dens_kp(matrix_p, tb%dipbra, tb%dipket, im, dip_n, ao_dip(:, im), para_env) + END DO + END IF + IF (do_quadrupole) THEN + DO im = 1, quad_n + CALL contract_dens_kp(matrix_p, tb%quadbra, tb%quadket, im, quad_n, ao_quad(:, im), para_env) + END DO END IF ELSE NULLIFY (p_matrix, s_matrix) @@ -1015,62 +1309,501 @@ CONTAINS END DO DEALLOCATE (aocg) - ! charge mixing - IF (dft_control%qs_control%do_ls_scf) THEN - ! - ELSE - CALL charge_mixing(scf_env%mixing_method, scf_env%mixing_store, & - ch_shell, para_env, scf_env%iter_count) + raw_state_status = 1 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_RAW_STATE_DUMP", raw_state_file, STATUS=raw_state_status) +#endif + IF (raw_state_status == 0) THEN + OPEN (NEWUNIT=raw_state_unit, FILE=TRIM(raw_state_file), STATUS="REPLACE", ACTION="WRITE") + WRITE (raw_state_unit, *) "qat" + DO iatom = 1, n_atom + WRITE (raw_state_unit, "(I0,1X,ES24.16)") iatom, -ch_atom(iatom, 1) + END DO + WRITE (raw_state_unit, *) "qsh" + DO iatom = 1, n_atom + DO is = 1, tb%calc%bas%nsh_at(iatom) + WRITE (raw_state_unit, "(I0,1X,ES24.16)") tb%calc%bas%ish_at(iatom) + is, -ch_shell(iatom, is) + END DO + END DO + IF (do_dipole) THEN + WRITE (raw_state_unit, *) "dpat" + DO iatom = 1, n_atom + WRITE (raw_state_unit, "(I0,3(1X,ES24.16))") iatom, -ao_dip(iatom, :) + END DO + END IF + IF (do_quadrupole) THEN + WRITE (raw_state_unit, *) "qpat" + DO iatom = 1, n_atom + WRITE (raw_state_unit, "(I0,6(1X,ES24.16))") iatom, -ao_quad(iatom, :) + END DO + END IF + CLOSE (raw_state_unit) + END IF + + IF (mp_test_mode == 150) THEN + n_mix_cols = max_shell + IF (do_dipole) n_mix_cols = n_mix_cols + dip_n + IF (do_quadrupole) n_mix_cols = n_mix_cols + quad_n + ALLOCATE (mix_vars(n_atom, n_mix_cols)) + mix_vars = 0.0_dp + + mix_vars(:, 1:max_shell) = -ch_shell(:, 1:max_shell) + mix_offset = max_shell + IF (do_dipole) THEN + mix_vars(:, mix_offset + 1:mix_offset + dip_n) = -ao_dip(:, 1:dip_n) + mix_offset = mix_offset + dip_n + END IF + IF (do_quadrupole) THEN + mix_vars(:, mix_offset + 1:mix_offset + quad_n) = -ao_quad(:, 1:quad_n) + END IF + + IF (use_rho .AND. (.NOT. calculate_forces) .AND. scf_env%mixing_store%ncall > 0) THEN + mix_vars = 0.0_dp + ns_mix = MIN(n_mix_cols, scf_env%mixing_store%max_shell) + last_mix_slot = MOD(scf_env%mixing_store%ncall - 1, scf_env%mixing_store%nbuffer) + 1 + DO ia_local = 1, scf_env%mixing_store%nat_local + iatom = scf_env%mixing_store%atlist(ia_local) + mix_vars(iatom, 1:ns_mix) = scf_env%mixing_store%acharge(ia_local, 1:ns_mix, last_mix_slot) + END DO + CALL para_env%sum(mix_vars) + ELSEIF ((.NOT. use_rho) .AND. (.NOT. calculate_forces)) THEN + ALLOCATE (prev_vars(n_atom, n_mix_cols)) + prev_vars(:, :) = mix_vars + IF (scf_env%mixing_store%ncall > 0) THEN + prev_vars = 0.0_dp + ns_mix = MIN(n_mix_cols, scf_env%mixing_store%max_shell) + last_mix_slot = MOD(scf_env%mixing_store%ncall - 1, scf_env%mixing_store%nbuffer) + 1 + DO ia_local = 1, scf_env%mixing_store%nat_local + iatom = scf_env%mixing_store%atlist(ia_local) + prev_vars(iatom, 1:ns_mix) = scf_env%mixing_store%acharge(ia_local, 1:ns_mix, last_mix_slot) + END DO + CALL para_env%sum(prev_vars) + END IF + mix_alpha = scf_env%mixing_store%alpha + prev_vars(:, :) = (1.0_dp - mix_alpha)*prev_vars + mix_alpha*mix_vars + scf_env%mixing_store%ncall = scf_env%mixing_store%ncall + 1 + ns_mix = MIN(n_mix_cols, scf_env%mixing_store%max_shell) + last_mix_slot = MOD(scf_env%mixing_store%ncall - 1, scf_env%mixing_store%nbuffer) + 1 + DO ia_local = 1, scf_env%mixing_store%nat_local + iatom = scf_env%mixing_store%atlist(ia_local) + scf_env%mixing_store%acharge(ia_local, 1:ns_mix, last_mix_slot) = prev_vars(iatom, 1:ns_mix) + END DO + DEALLOCATE (prev_vars) + END IF + + DO iatom = 1, n_atom + ii = tb%calc%bas%ish_at(iatom) + DO is = 1, tb%calc%bas%nsh_at(iatom) + tb%wfn%qsh(ii + is, 1) = mix_vars(iatom, is) + END DO + tb%wfn%qat(iatom, 1) = SUM(tb%wfn%qsh(ii + 1:ii + tb%calc%bas%nsh_at(iatom), 1)) + END DO + mix_offset = max_shell + IF (do_dipole) THEN + DO iatom = 1, n_atom + tb%wfn%dpat(:, iatom, 1) = mix_vars(iatom, mix_offset + 1:mix_offset + dip_n) + END DO + mix_offset = mix_offset + dip_n + DEALLOCATE (ao_dip) + END IF + IF (do_quadrupole) THEN + DO iatom = 1, n_atom + tb%wfn%qpat(:, iatom, 1) = mix_vars(iatom, mix_offset + 1:mix_offset + quad_n) + END DO + DEALLOCATE (ao_quad) + END IF + DEALLOCATE (mix_vars) + ELSEIF (use_native_mixer .OR. mp_test_mode == 120 .OR. mp_test_mode == 220 .OR. & + mp_test_mode == 230 .OR. mp_test_mode == 231 .OR. & + mp_test_mode == 232 .OR. mp_test_mode == 233) THEN + IF (.NOT. ALLOCATED(tb%mixer)) CPABORT("tblite mixer not initialized") + IF (use_rho .AND. (.NOT. calculate_forces) .AND. scf_env%iter_count > 1) THEN + CALL tb%mixer%next(error) + IF (ALLOCATED(error)) CPABORT("tblite native mixer failed") + CALL tb%mixer%get(tb%wfn%qsh) + tb%wfn%qat(:, 1) = 0.0_dp + DO iatom = 1, n_atom + ii = tb%calc%bas%ish_at(iatom) + tb%wfn%qat(iatom, 1) = SUM(tb%wfn%qsh(ii + 1:ii + tb%calc%bas%nsh_at(iatom), 1)) + END DO + IF (do_dipole) THEN + CALL tb%mixer%get(tb%wfn%dpat) + DEALLOCATE (ao_dip) + END IF + IF (do_quadrupole) THEN + CALL tb%mixer%get(tb%wfn%qpat) + DEALLOCATE (ao_quad) + END IF + ELSE + IF ((use_native_mixer .OR. mp_test_mode == 230 .OR. mp_test_mode == 231 .OR. & + mp_test_mode == 232 .OR. mp_test_mode == 233) .AND. & + use_rho .AND. (.NOT. calculate_forces)) THEN + IF (.NOT. reuse_native_input) THEN + tb%wfn%qsh(:, :) = 0.0_dp + tb%wfn%qat(:, :) = 0.0_dp + IF (do_dipole) tb%wfn%dpat(:, :, :) = 0.0_dp + IF (do_quadrupole) tb%wfn%qpat(:, :, :) = 0.0_dp + END IF + IF (do_dipole) DEALLOCATE (ao_dip) + IF (do_quadrupole) DEALLOCATE (ao_quad) + ELSE + IF ((.NOT. use_rho) .AND. (.NOT. calculate_forces)) THEN + CALL tb%mixer%set(tb%wfn%qsh) + IF (do_dipole) CALL tb%mixer%set(tb%wfn%dpat) + IF (do_quadrupole) CALL tb%mixer%set(tb%wfn%qpat) + END IF + DO iatom = 1, n_atom + ii = tb%calc%bas%ish_at(iatom) + DO is = 1, tb%calc%bas%nsh_at(iatom) + tb%wfn%qsh(ii + is, 1) = -ch_shell(iatom, is) + END DO + tb%wfn%qat(iatom, 1) = SUM(tb%wfn%qsh(ii + 1:ii + tb%calc%bas%nsh_at(iatom), 1)) + END DO + IF (do_dipole) THEN + DO iatom = 1, n_atom + tb%wfn%dpat(:, iatom, 1) = -ao_dip(iatom, :) + END DO + DEALLOCATE (ao_dip) + END IF + IF (do_quadrupole) THEN + DO iatom = 1, n_atom + tb%wfn%qpat(:, iatom, 1) = -ao_quad(iatom, :) + END DO + DEALLOCATE (ao_quad) + END IF + IF ((.NOT. use_rho) .AND. (.NOT. calculate_forces)) THEN + CALL tb%mixer%diff(tb%wfn%qsh) + IF (do_dipole) CALL tb%mixer%diff(tb%wfn%dpat) + IF (do_quadrupole) CALL tb%mixer%diff(tb%wfn%qpat) + END IF + END IF + END IF + ELSE + ! charge mixing + IF (dft_control%qs_control%do_ls_scf) THEN + ! + ELSE + ! CP2K SCC mixing has to see all tblite SCC variables, not only shell charges. + do_combined_mixing = do_dipole .OR. do_quadrupole .OR. & + (mp_test_mode == 110 .OR. mp_test_mode == 111 .OR. & + mp_test_mode == 112 .OR. mp_test_mode == 114 .OR. & + mp_test_mode == 115 .OR. & + mp_test_mode == 116 .OR. mp_test_mode == 117 .OR. & + mp_test_mode == 118 .OR. mp_test_mode == 122 .OR. & + mp_test_mode == 130 .OR. mp_test_mode == 131 .OR. & + mp_test_mode == 140 .OR. mp_test_mode == 141 .OR. & + mp_test_mode == 142 .OR. mp_test_mode == 183) + native_sign_mixing = ((do_dipole .OR. do_quadrupole) .AND. mp_test_mode == 0) .OR. & + (mp_test_mode == 116 .OR. mp_test_mode == 117 .OR. & + mp_test_mode == 118) + phased_combined_mixing = (mp_test_mode == 130 .OR. mp_test_mode == 131) + discard_mixed_output = (mp_test_mode == 114 .AND. .NOT. use_rho) .OR. & + (mp_test_mode == 115 .AND. (.NOT. use_rho .OR. calculate_forces)) .OR. & + (mp_test_mode == 117 .AND. .NOT. use_rho) .OR. & + (mp_test_mode == 118 .AND. (.NOT. use_rho .OR. calculate_forces)) .OR. & + (mp_test_mode == 131 .AND. (.NOT. use_rho .OR. calculate_forces)) + skip_charge_mixing = use_no_mixer .OR. & + (mp_test_mode == 111 .AND. use_rho) .OR. & + (mp_test_mode == 112 .AND. .NOT. use_rho) .OR. & + (phased_combined_mixing .AND. use_rho) + IF (phased_combined_mixing .AND. use_rho .AND. scf_env%mixing_store%ncall > 0 .AND. & + (mp_test_mode /= 131 .OR. .NOT. calculate_forces)) THEN + n_mix_cols = max_shell + IF (do_dipole) n_mix_cols = n_mix_cols + dip_n + IF (do_quadrupole) n_mix_cols = n_mix_cols + quad_n + ALLOCATE (mix_vars(n_atom, n_mix_cols)) + mix_vars = 0.0_dp + ns_mix = MIN(n_mix_cols, scf_env%mixing_store%max_shell) + last_mix_slot = MOD(scf_env%mixing_store%ncall - 1, scf_env%mixing_store%nbuffer) + 1 + DO ia_local = 1, scf_env%mixing_store%nat_local + iatom = scf_env%mixing_store%atlist(ia_local) + mix_vars(iatom, 1:ns_mix) = scf_env%mixing_store%acharge(ia_local, 1:ns_mix, last_mix_slot) + END DO + CALL para_env%sum(mix_vars) + ch_shell(:, 1:max_shell) = mix_vars(:, 1:max_shell) + mix_offset = max_shell + IF (do_dipole) THEN + ao_dip(:, 1:dip_n) = mix_vars(:, mix_offset + 1:mix_offset + dip_n) + mix_offset = mix_offset + dip_n + END IF + IF (do_quadrupole) THEN + ao_quad(:, 1:quad_n) = mix_vars(:, mix_offset + 1:mix_offset + quad_n) + END IF + DEALLOCATE (mix_vars) + END IF + IF (skip_charge_mixing) THEN + ! + ELSEIF (do_combined_mixing) THEN + n_mix_cols = max_shell + IF (do_dipole) n_mix_cols = n_mix_cols + dip_n + IF (do_quadrupole) n_mix_cols = n_mix_cols + quad_n + ALLOCATE (mix_vars(n_atom, n_mix_cols)) + IF (native_sign_mixing) THEN + mix_vars(:, 1:max_shell) = -ch_shell(:, 1:max_shell) + ELSE + mix_vars(:, 1:max_shell) = ch_shell(:, 1:max_shell) + END IF + mix_offset = max_shell + IF (do_dipole) THEN + IF (native_sign_mixing) THEN + mix_vars(:, mix_offset + 1:mix_offset + dip_n) = -ao_dip(:, 1:dip_n) + ELSE + mix_vars(:, mix_offset + 1:mix_offset + dip_n) = ao_dip(:, 1:dip_n) + END IF + mix_offset = mix_offset + dip_n + END IF + IF (do_quadrupole) THEN + IF (native_sign_mixing) THEN + mix_vars(:, mix_offset + 1:mix_offset + quad_n) = -ao_quad(:, 1:quad_n) + ELSE + mix_vars(:, mix_offset + 1:mix_offset + quad_n) = ao_quad(:, 1:quad_n) + END IF + END IF + CALL charge_mixing(scf_env%mixing_method, scf_env%mixing_store, & + mix_vars, para_env, scf_env%iter_count) + IF (.NOT. discard_mixed_output) THEN + IF (native_sign_mixing) THEN + ch_shell(:, 1:max_shell) = -mix_vars(:, 1:max_shell) + ELSE + ch_shell(:, 1:max_shell) = mix_vars(:, 1:max_shell) + END IF + mix_offset = max_shell + IF (do_dipole) THEN + IF (native_sign_mixing) THEN + ao_dip(:, 1:dip_n) = -mix_vars(:, mix_offset + 1:mix_offset + dip_n) + ELSE + ao_dip(:, 1:dip_n) = mix_vars(:, mix_offset + 1:mix_offset + dip_n) + END IF + mix_offset = mix_offset + dip_n + END IF + IF (do_quadrupole) THEN + IF (native_sign_mixing) THEN + ao_quad(:, 1:quad_n) = -mix_vars(:, mix_offset + 1:mix_offset + quad_n) + ELSE + ao_quad(:, 1:quad_n) = mix_vars(:, mix_offset + 1:mix_offset + quad_n) + END IF + END IF + END IF + DEALLOCATE (mix_vars) + ELSE + CALL charge_mixing(scf_env%mixing_method, scf_env%mixing_store, & + ch_shell, para_env, scf_env%iter_count) + END IF + END IF + + !setting new wave function + CALL tb%pot%reset + tb%e_es = 0.0_dp + tb%e_scd = 0.0_dp + moment_alpha = scf_env%p_mix_alpha + IF (mp_test_mode == 61 .OR. mp_test_mode == 91) moment_alpha = 0.05_dp + IF (mp_test_mode == 62 .OR. mp_test_mode == 92) moment_alpha = 0.5_dp + DO iatom = 1, n_atom + ii = tb%calc%bas%ish_at(iatom) + DO is = 1, tb%calc%bas%nsh_at(iatom) + new_charge = -ch_shell(iatom, is) + IF ((mp_test_mode == 90 .OR. mp_test_mode == 91 .OR. mp_test_mode == 92) .AND. & + scf_env%iter_count > 1) THEN + new_charge = moment_alpha*new_charge + (1.0_dp - moment_alpha)*tb%wfn%qsh(ii + is, 1) + END IF + tb%wfn%qsh(ii + is, 1) = new_charge + END DO + IF (native_sign_mixing .OR. mp_test_mode == 122) THEN + tb%wfn%qat(iatom, 1) = SUM(tb%wfn%qsh(ii + 1:ii + tb%calc%bas%nsh_at(iatom), 1)) + ELSE + new_charge = -ch_atom(iatom, 1) + IF ((mp_test_mode == 90 .OR. mp_test_mode == 91 .OR. mp_test_mode == 92) .AND. & + scf_env%iter_count > 1) THEN + new_charge = moment_alpha*new_charge + (1.0_dp - moment_alpha)*tb%wfn%qat(iatom, 1) + END IF + tb%wfn%qat(iatom, 1) = new_charge + END IF + END DO + + IF (do_dipole) THEN + DO iatom = 1, n_atom + DO im = 1, dip_n + new_moment = -ao_dip(iatom, im) + IF ((mp_test_mode == 60 .OR. mp_test_mode == 61 .OR. mp_test_mode == 62 .OR. & + mp_test_mode == 90 .OR. mp_test_mode == 91 .OR. mp_test_mode == 92) .AND. & + scf_env%iter_count > 1) THEN + new_moment = moment_alpha*new_moment + (1.0_dp - moment_alpha)*tb%wfn%dpat(im, iatom, 1) + END IF + tb%wfn%dpat(im, iatom, 1) = new_moment + END DO + END DO + DEALLOCATE (ao_dip) + END IF + IF (do_quadrupole) THEN + DO iatom = 1, n_atom + DO im = 1, quad_n + new_moment = -ao_quad(iatom, im) + IF ((mp_test_mode == 60 .OR. mp_test_mode == 61 .OR. mp_test_mode == 62 .OR. & + mp_test_mode == 90 .OR. mp_test_mode == 91 .OR. mp_test_mode == 92) .AND. & + scf_env%iter_count > 1) THEN + new_moment = moment_alpha*new_moment + (1.0_dp - moment_alpha)*tb%wfn%qpat(im, iatom, 1) + END IF + tb%wfn%qpat(im, iatom, 1) = new_moment + END DO + END DO + DEALLOCATE (ao_quad) + END IF + END IF + IF (mp_test_mode == 2 .OR. mp_test_mode == 7 .OR. mp_test_mode == 8 .OR. & + mp_test_mode == 13 .OR. mp_test_mode == 14 .OR. mp_test_mode == 15 .OR. & + mp_test_mode == 16 .OR. mp_test_mode == 17 .OR. mp_test_mode == 18 .OR. & + mp_test_mode == 20 .OR. mp_test_mode == 21 .OR. & + mp_test_mode == 32 .OR. mp_test_mode == 33 .OR. & + mp_test_mode == 34 .OR. mp_test_mode == 35 .OR. & + mp_test_mode == 36 .OR. mp_test_mode == 37 .OR. & + mp_test_mode == 10 .OR. mp_test_mode == 11 .OR. mp_test_mode == 12) THEN + tb%wfn%dpat(:, :, :) = -tb%wfn%dpat(:, :, :) + tb%wfn%qpat(:, :, :) = -tb%wfn%qpat(:, :, :) + ELSEIF (mp_test_mode == 4) THEN + tb%wfn%dpat(:, :, :) = 0.0_dp + tb%wfn%qpat(:, :, :) = 0.0_dp + END IF + + IF (mp_test_mode == 100 .OR. mp_test_mode == 101 .OR. mp_test_mode == 102) THEN + nspin = SIZE(p_matrix) + CALL new_integral(native_ints, tb%calc%bas%nao) + CALL get_lattice_points(tb%mol%periodic, tb%mol%lattice, get_cutoff(tb%calc%bas, 1.0_dp), native_lattr) + CALL new_adjacency_list(native_list, tb%mol, native_lattr, get_cutoff(tb%calc%bas, 1.0_dp)) + CALL get_hamiltonian(tb%mol, native_lattr, native_list, tb%calc%bas, tb%calc%h0, tb%selfenergy, & + native_ints%overlap, native_ints%dipole, native_ints%quadrupole, & + native_ints%hamiltonian) + ALLOCATE (native_p(tb%calc%bas%nao, tb%calc%bas%nao, nspin)) + native_p = 0.0_dp + DO ispin = 1, nspin + CALL dbcsr_iterator_start(iter, p_matrix(ispin)%matrix) + DO WHILE (dbcsr_iterator_blocks_left(iter)) + NULLIFY (p_block) + CALL dbcsr_iterator_next_block(iter, irow, icol, p_block) + i0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(irow) + 1) + j0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(icol) + 1) + DO j = 1, SIZE(p_block, 1) + DO i = 1, SIZE(p_block, 2) + IF (mp_test_mode == 102 .AND. irow /= icol) THEN + native_p(i0 + j, j0 + i, ispin) = 0.5_dp*p_block(j, i) + native_p(j0 + i, i0 + j, ispin) = 0.5_dp*p_block(j, i) + ELSE + native_p(i0 + j, j0 + i, ispin) = p_block(j, i) + IF (mp_test_mode == 100 .AND. irow /= icol) & + native_p(j0 + i, i0 + j, ispin) = p_block(j, i) + END IF + END DO + END DO + END DO + CALL dbcsr_iterator_stop(iter) + END DO + + tb%wfn%qsh(:, :) = 0.0_dp + DO ispin = 1, nspin + DO iao = 1, tb%calc%bas%nao + pao = 0.0_dp + DO jao = 1, tb%calc%bas%nao + pao = pao + native_p(jao, iao, ispin)*native_ints%overlap(jao, iao) + END DO + ish = tb%calc%bas%ao2sh(iao) + tb%wfn%qsh(ish, ispin) = tb%wfn%qsh(ish, ispin) - pao + END DO + END DO + tb%wfn%qsh(:, 1) = tb%wfn%qsh(:, 1) + tb%wfn%n0sh(:) + + tb%wfn%qat(:, :) = 0.0_dp + DO ispin = 1, nspin + DO ish = 1, tb%calc%bas%nsh + tb%wfn%qat(tb%calc%bas%sh2at(ish), ispin) = & + tb%wfn%qat(tb%calc%bas%sh2at(ish), ispin) + tb%wfn%qsh(ish, ispin) + END DO + END DO + + IF (do_dipole) THEN + tb%wfn%dpat(:, :, :) = 0.0_dp + DO ispin = 1, nspin + DO iao = 1, tb%calc%bas%nao + atom_a = tb%calc%bas%ao2at(iao) + DO jao = 1, tb%calc%bas%nao + DO im = 1, dip_n + tb%wfn%dpat(im, atom_a, ispin) = tb%wfn%dpat(im, atom_a, ispin) & + - native_p(jao, iao, ispin)*native_ints%dipole(im, jao, iao) + END DO + END DO + END DO + END DO + END IF + IF (do_quadrupole) THEN + tb%wfn%qpat(:, :, :) = 0.0_dp + DO ispin = 1, nspin + DO iao = 1, tb%calc%bas%nao + atom_a = tb%calc%bas%ao2at(iao) + DO jao = 1, tb%calc%bas%nao + DO im = 1, quad_n + tb%wfn%qpat(im, atom_a, ispin) = tb%wfn%qpat(im, atom_a, ispin) & + - native_p(jao, iao, ispin)*native_ints%quadrupole(im, jao, iao) + END DO + END DO + END DO + END DO + END IF + DEALLOCATE (native_p, native_lattr) END IF - !setting new wave function CALL tb%pot%reset tb%e_es = 0.0_dp tb%e_scd = 0.0_dp - DO iatom = 1, n_atom - ii = tb%calc%bas%ish_at(iatom) - DO is = 1, tb%calc%bas%nsh_at(iatom) - tb%wfn%qsh(ii + is, 1) = -ch_shell(iatom, is) - END DO - tb%wfn%qat(iatom, 1) = -ch_atom(iatom, 1) - END DO - - IF (do_dipole) THEN - DO iatom = 1, n_atom - DO im = 1, dip_n - tb%wfn%dpat(im, iatom, 1) = -ao_dip(iatom, im) - END DO - END DO - DEALLOCATE (ao_dip) - END IF - IF (do_quadrupole) THEN - DO iatom = 1, n_atom - DO im = 1, quad_n - tb%wfn%qpat(im, iatom, 1) = -ao_quad(iatom, im) - END DO - END DO - DEALLOCATE (ao_quad) - END IF - IF (ALLOCATED(tb%calc%coulomb)) THEN CALL tb%calc%coulomb%get_potential(tb%mol, tb%cache, tb%wfn, tb%pot) CALL tb%calc%coulomb%get_energy(tb%mol, tb%cache, tb%wfn, tb%e_es) END IF IF (ALLOCATED(tb%calc%dispersion)) THEN - CALL tb%calc%dispersion%get_potential(tb%mol, tb%dcache, tb%wfn, tb%pot) - CALL tb%calc%dispersion%get_energy(tb%mol, tb%dcache, tb%wfn, tb%e_scd) + IF (.NOT. skip_scf_dispersion_potential) & + CALL tb%calc%dispersion%get_potential(tb%mol, tb%dcache, tb%wfn, tb%pot) + IF (.NOT. skip_scf_dispersion_energy) & + CALL tb%calc%dispersion%get_energy(tb%mol, tb%dcache, tb%wfn, tb%e_scd) + END IF + + state_status = 1 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_STATE_DUMP", state_file, STATUS=state_status) +#endif + IF (state_status == 0) THEN + OPEN (NEWUNIT=state_unit, FILE=TRIM(state_file), STATUS="REPLACE", ACTION="WRITE") + WRITE (state_unit, *) "qat" + DO iatom = 1, n_atom + WRITE (state_unit, "(I0,1X,ES24.16)") iatom, tb%wfn%qat(iatom, 1) + END DO + WRITE (state_unit, *) "qsh" + DO iatom = 1, SIZE(tb%wfn%qsh, 1) + WRITE (state_unit, "(I0,1X,ES24.16)") iatom, tb%wfn%qsh(iatom, 1) + END DO + IF (do_dipole) THEN + WRITE (state_unit, *) "dpat" + DO iatom = 1, n_atom + WRITE (state_unit, "(I0,3(1X,ES24.16))") iatom, tb%wfn%dpat(:, iatom, 1) + END DO + END IF + IF (do_quadrupole) THEN + WRITE (state_unit, *) "qpat" + DO iatom = 1, n_atom + WRITE (state_unit, "(I0,6(1X,ES24.16))") iatom, tb%wfn%qpat(:, iatom, 1) + END DO + END IF + CLOSE (state_unit) END IF IF (calculate_forces) THEN IF (ALLOCATED(tb%calc%coulomb)) THEN tb%grad = 0.0_dp CALL tb%calc%coulomb%get_gradient(tb%mol, tb%cache, tb%wfn, tb%grad, tb%sigma) + CALL tb_dump_sigma_component("after_coulomb", tb%sigma, para_env) CALL tb_grad2force(qs_env, tb, para_env, 3) END IF - IF (ALLOCATED(tb%calc%dispersion)) THEN + IF (ALLOCATED(tb%calc%dispersion) .AND. .NOT. skip_scf_dispersion_gradient) THEN tb%grad = 0.0_dp CALL tb%calc%dispersion%get_gradient(tb%mol, tb%dcache, tb%wfn, tb%grad, tb%sigma) + CALL tb_dump_sigma_component("after_dispersion_scf", tb%sigma, para_env) CALL tb_grad2force(qs_env, tb, para_env, 2) END IF END IF @@ -1103,14 +1836,22 @@ CONTAINS #if defined(__TBLITE) INTEGER :: ikind, jkind, iatom, jatom, icol, irow - INTEGER :: ic, is, nimg, ni, nj, i, j + INTEGER :: ic, id1, id2, id3, iq1, iq2, iq3, iq4, iq5, iq6, & + is, nimg, ni, nj, i, j, i0, j0 INTEGER :: la, lb, za, zb + INTEGER :: mp_test_mode LOGICAL :: found INTEGER, DIMENSION(3) :: cellind INTEGER, DIMENSION(25) :: naoa, naob REAL(KIND=dp), DIMENSION(3) :: rij + REAL(KIND=dp) :: mpfac +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value +#endif INTEGER, ALLOCATABLE, DIMENSION(:) :: kind_of, sum_shell - REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ashift, bshift + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: ashift, bshift, native_lattr + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :, :) :: native_h1 REAL(KIND=dp), DIMENSION(:, :), POINTER :: ksblock, sblock INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index REAL(KIND=dp), DIMENSION(:, :), POINTER :: dip_ket1, dip_ket2, dip_ket3, & @@ -1121,7 +1862,9 @@ CONTAINS quad_bra4, quad_bra5, quad_bra6 TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set + TYPE(adjacency_list) :: native_list TYPE(dbcsr_iterator_type) :: iter + TYPE(integral_type) :: native_ints TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: ks_matrix TYPE(kpoint_type), POINTER :: kpoints @@ -1130,13 +1873,53 @@ CONTAINS TYPE(neighbor_list_set_p_type), DIMENSION(:), & POINTER :: n_list TYPE(qs_kind_type), DIMENSION(:), POINTER :: qs_kind_set + TYPE(potential_type) :: native_pot TYPE(xtb_atom_type), POINTER :: xtb_atom_a, xtb_atom_b nimg = dft_control%nimages + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif + mpfac = -0.5_dp + IF (mp_test_mode == 3 .OR. mp_test_mode == 10 .OR. mp_test_mode == 11 .OR. & + mp_test_mode == 12) mpfac = 0.5_dp + IF (mp_test_mode == 5) mpfac = 0.0_dp NULLIFY (matrix_s, ks_matrix, n_list, qs_kind_set) CALL get_qs_env(qs_env=qs_env, sab_orb=n_list, matrix_s_kp=matrix_s, matrix_ks_kp=ks_matrix, qs_kind_set=qs_kind_set) + IF (mp_test_mode == 83 .OR. mp_test_mode == 183 .OR. & + mp_test_mode == 220 .OR. mp_test_mode == 231 .OR. & + mp_test_mode == 233) THEN + IF (nimg > 1) CPABORT("Native tblite Hamiltonian test with k-points not implemented") + CALL new_integral(native_ints, tb%calc%bas%nao) + CALL get_lattice_points(tb%mol%periodic, tb%mol%lattice, get_cutoff(tb%calc%bas, 1.0_dp), native_lattr) + CALL new_adjacency_list(native_list, tb%mol, native_lattr, get_cutoff(tb%calc%bas, 1.0_dp)) + CALL get_hamiltonian(tb%mol, native_lattr, native_list, tb%calc%bas, tb%calc%h0, tb%selfenergy, & + native_ints%overlap, native_ints%dipole, native_ints%quadrupole, & + native_ints%hamiltonian) + ALLOCATE (native_h1(tb%calc%bas%nao, tb%calc%bas%nao, 1)) + native_pot = tb%pot + CALL add_pot_to_h1(tb%calc%bas, native_ints, native_pot, native_h1) + + CALL dbcsr_iterator_start(iter, ks_matrix(1, 1)%matrix) + DO WHILE (dbcsr_iterator_blocks_left(iter)) + CALL dbcsr_iterator_next_block(iter, irow, icol, ksblock) + i0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(irow) + 1) + j0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(icol) + 1) + DO j = 1, SIZE(ksblock, 1) + DO i = 1, SIZE(ksblock, 2) + ksblock(j, i) = native_h1(i0 + j, j0 + i, 1) + END DO + END DO + END DO + CALL dbcsr_iterator_stop(iter) + DEALLOCATE (native_h1, native_lattr) + RETURN + END IF + !creating sum of shell lists ALLOCATE (sum_shell(tb%mol%nat)) i = 0 @@ -1224,12 +2007,12 @@ CONTAINS CALL dbcsr_get_block_p(matrix=ks_matrix(is, 1)%matrix, & row=irow, col=icol, block=ksblock, found=found) CPASSERT(found) - ksblock = ksblock - 0.5_dp*(dip_ket1*tb%pot%vdp(1, irow, 1) & - + dip_ket2*tb%pot%vdp(2, irow, 1) & - + dip_ket3*tb%pot%vdp(3, irow, 1) & - + dip_bra1*tb%pot%vdp(1, icol, 1) & - + dip_bra2*tb%pot%vdp(2, icol, 1) & - + dip_bra3*tb%pot%vdp(3, icol, 1)) + ksblock = ksblock + mpfac*(dip_ket1*tb%pot%vdp(1, irow, 1) & + + dip_ket2*tb%pot%vdp(2, irow, 1) & + + dip_ket3*tb%pot%vdp(3, irow, 1) & + + dip_bra1*tb%pot%vdp(1, icol, 1) & + + dip_bra2*tb%pot%vdp(2, icol, 1) & + + dip_bra3*tb%pot%vdp(3, icol, 1)) END DO END DO CALL dbcsr_iterator_stop(iter) @@ -1286,25 +2069,24 @@ CONTAINS row=irow, col=icol, block=ksblock, found=found) CPASSERT(found) - ksblock = ksblock - 0.5_dp*(quad_ket1*tb%pot%vqp(1, irow, 1) & - + quad_ket2*tb%pot%vqp(2, irow, 1) & - + quad_ket3*tb%pot%vqp(3, irow, 1) & - + quad_ket4*tb%pot%vqp(4, irow, 1) & - + quad_ket5*tb%pot%vqp(5, irow, 1) & - + quad_ket6*tb%pot%vqp(6, irow, 1) & - + quad_bra1*tb%pot%vqp(1, icol, 1) & - + quad_bra2*tb%pot%vqp(2, icol, 1) & - + quad_bra3*tb%pot%vqp(3, icol, 1) & - + quad_bra4*tb%pot%vqp(4, icol, 1) & - + quad_bra5*tb%pot%vqp(5, icol, 1) & - + quad_bra6*tb%pot%vqp(6, icol, 1)) + ksblock = ksblock + mpfac*(quad_ket1*tb%pot%vqp(1, irow, 1) & + + quad_ket2*tb%pot%vqp(2, irow, 1) & + + quad_ket3*tb%pot%vqp(3, irow, 1) & + + quad_ket4*tb%pot%vqp(4, irow, 1) & + + quad_ket5*tb%pot%vqp(5, irow, 1) & + + quad_ket6*tb%pot%vqp(6, irow, 1) & + + quad_bra1*tb%pot%vqp(1, icol, 1) & + + quad_bra2*tb%pot%vqp(2, icol, 1) & + + quad_bra3*tb%pot%vqp(3, icol, 1) & + + quad_bra4*tb%pot%vqp(4, icol, 1) & + + quad_bra5*tb%pot%vqp(5, icol, 1) & + + quad_bra6*tb%pot%vqp(6, icol, 1)) END DO END DO CALL dbcsr_iterator_stop(iter) END IF ELSE - CPABORT("GFN methods with k-points not tested") NULLIFY (kpoints) CALL get_qs_env(qs_env=qs_env, kpoints=kpoints) NULLIFY (cell_to_index) @@ -1366,6 +2148,7 @@ CONTAINS ksblock = ksblock - 0.5_dp*(tb%pot%vat(irow, 1) & + tb%pot%vat(icol, 1))*sblock END DO + DEALLOCATE (ashift, bshift) END DO CALL neighbor_list_iterator_release(nl_iterator) @@ -1377,39 +2160,44 @@ CONTAINS iatom=iatom, jatom=jatom, cell=cellind) icol = MAX(iatom, jatom) irow = MIN(iatom, jatom) + ic = cell_to_index(cellind(1), cellind(2), cellind(3)) + CPASSERT(ic > 0) + id1 = 1 + dip_n*(ic - 1) + id2 = 2 + dip_n*(ic - 1) + id3 = 3 + dip_n*(ic - 1) NULLIFY (dip_bra1, dip_bra2, dip_bra3) - CALL dbcsr_get_block_p(matrix=tb%dipbra(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id1)%matrix, & row=irow, col=icol, BLOCK=dip_bra1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipbra(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id2)%matrix, & row=irow, col=icol, BLOCK=dip_bra2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipbra(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id3)%matrix, & row=irow, col=icol, BLOCK=dip_bra3, found=found) CPASSERT(found) NULLIFY (dip_ket1, dip_ket2, dip_ket3) - CALL dbcsr_get_block_p(matrix=tb%dipket(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id1)%matrix, & row=irow, col=icol, BLOCK=dip_ket1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipket(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id2)%matrix, & row=irow, col=icol, BLOCK=dip_ket2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipket(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id3)%matrix, & row=irow, col=icol, BLOCK=dip_ket3, found=found) CPASSERT(found) DO is = 1, SIZE(ks_matrix, 1) NULLIFY (ksblock) - CALL dbcsr_get_block_p(matrix=ks_matrix(is, 1)%matrix, & + CALL dbcsr_get_block_p(matrix=ks_matrix(is, ic)%matrix, & row=irow, col=icol, block=ksblock, found=found) CPASSERT(found) - ksblock = ksblock - 0.5_dp*(dip_ket1*tb%pot%vdp(1, irow, 1) & - + dip_ket2*tb%pot%vdp(2, irow, 1) & - + dip_ket3*tb%pot%vdp(3, irow, 1) & - + dip_bra1*tb%pot%vdp(1, icol, 1) & - + dip_bra2*tb%pot%vdp(2, icol, 1) & - + dip_bra3*tb%pot%vdp(3, icol, 1)) + ksblock = ksblock + mpfac*(dip_ket1*tb%pot%vdp(1, irow, 1) & + + dip_ket2*tb%pot%vdp(2, irow, 1) & + + dip_ket3*tb%pot%vdp(3, irow, 1) & + + dip_bra1*tb%pot%vdp(1, icol, 1) & + + dip_bra2*tb%pot%vdp(2, icol, 1) & + + dip_bra3*tb%pot%vdp(3, icol, 1)) END DO END DO CALL neighbor_list_iterator_release(nl_iterator) @@ -1423,65 +2211,73 @@ CONTAINS iatom=iatom, jatom=jatom, cell=cellind) icol = MAX(iatom, jatom) irow = MIN(iatom, jatom) + ic = cell_to_index(cellind(1), cellind(2), cellind(3)) + CPASSERT(ic > 0) + iq1 = 1 + quad_n*(ic - 1) + iq2 = 2 + quad_n*(ic - 1) + iq3 = 3 + quad_n*(ic - 1) + iq4 = 4 + quad_n*(ic - 1) + iq5 = 5 + quad_n*(ic - 1) + iq6 = 6 + quad_n*(ic - 1) NULLIFY (quad_bra1, quad_bra2, quad_bra3, quad_bra4, quad_bra5, quad_bra6) - CALL dbcsr_get_block_p(matrix=tb%quadbra(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq1)%matrix, & row=irow, col=icol, BLOCK=quad_bra1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq2)%matrix, & row=irow, col=icol, BLOCK=quad_bra2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq3)%matrix, & row=irow, col=icol, BLOCK=quad_bra3, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(4)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq4)%matrix, & row=irow, col=icol, BLOCK=quad_bra4, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(5)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq5)%matrix, & row=irow, col=icol, BLOCK=quad_bra5, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(6)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq6)%matrix, & row=irow, col=icol, BLOCK=quad_bra6, found=found) CPASSERT(found) NULLIFY (quad_ket1, quad_ket2, quad_ket3, quad_ket4, quad_ket5, quad_ket6) - CALL dbcsr_get_block_p(matrix=tb%quadket(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq1)%matrix, & row=irow, col=icol, BLOCK=quad_ket1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq2)%matrix, & row=irow, col=icol, BLOCK=quad_ket2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq3)%matrix, & row=irow, col=icol, BLOCK=quad_ket3, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(4)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq4)%matrix, & row=irow, col=icol, BLOCK=quad_ket4, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(5)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq5)%matrix, & row=irow, col=icol, BLOCK=quad_ket5, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(6)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq6)%matrix, & row=irow, col=icol, BLOCK=quad_ket6, found=found) CPASSERT(found) DO is = 1, SIZE(ks_matrix, 1) NULLIFY (ksblock) - CALL dbcsr_get_block_p(matrix=ks_matrix(is, 1)%matrix, & + CALL dbcsr_get_block_p(matrix=ks_matrix(is, ic)%matrix, & row=irow, col=icol, block=ksblock, found=found) CPASSERT(found) - ksblock = ksblock - 0.5_dp*(quad_ket1*tb%pot%vqp(1, irow, 1) & - + quad_ket2*tb%pot%vqp(2, irow, 1) & - + quad_ket3*tb%pot%vqp(3, irow, 1) & - + quad_ket4*tb%pot%vqp(4, irow, 1) & - + quad_ket5*tb%pot%vqp(5, irow, 1) & - + quad_ket6*tb%pot%vqp(6, irow, 1) & - + quad_bra1*tb%pot%vqp(1, icol, 1) & - + quad_bra2*tb%pot%vqp(2, icol, 1) & - + quad_bra3*tb%pot%vqp(3, icol, 1) & - + quad_bra4*tb%pot%vqp(4, icol, 1) & - + quad_bra5*tb%pot%vqp(5, icol, 1) & - + quad_bra6*tb%pot%vqp(6, icol, 1)) + ksblock = ksblock + mpfac*(quad_ket1*tb%pot%vqp(1, irow, 1) & + + quad_ket2*tb%pot%vqp(2, irow, 1) & + + quad_ket3*tb%pot%vqp(3, irow, 1) & + + quad_ket4*tb%pot%vqp(4, irow, 1) & + + quad_ket5*tb%pot%vqp(5, irow, 1) & + + quad_ket6*tb%pot%vqp(6, irow, 1) & + + quad_bra1*tb%pot%vqp(1, icol, 1) & + + quad_bra2*tb%pot%vqp(2, icol, 1) & + + quad_bra3*tb%pot%vqp(3, icol, 1) & + + quad_bra4*tb%pot%vqp(4, icol, 1) & + + quad_bra5*tb%pot%vqp(5, icol, 1) & + + quad_bra6*tb%pot%vqp(6, icol, 1)) END DO END DO CALL neighbor_list_iterator_release(nl_iterator) @@ -1513,17 +2309,26 @@ CONTAINS CHARACTER(LEN=*), PARAMETER :: routineN = 'tb_get_multipole' INTEGER :: ikind, jkind, iatom, jatom, icol, irow, iset, jset, ityp, jtyp - INTEGER :: nkind, natom, handle, nimg, i, inda, indb - INTEGER :: atom_a, atom_b, nseta, nsetb, ia, ib, ij + INTEGER :: ic, idx, id1, id2, id3, img, iq1, iq2, iq3, iq4, iq5, iq6 + INTEGER :: nkind, natom, handle, nimg, i, j, inda, indb + INTEGER :: mp_test_mode + INTEGER :: atom_a, atom_b, nseta, nsetb, ia, ib, ij, i0, j0 LOGICAL :: found REAL(KIND=dp) :: r2 - REAL(KIND=dp), DIMENSION(3) :: rij + INTEGER, DIMENSION(3) :: cell + INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index + REAL(KIND=dp), DIMENSION(3) :: rij, mp_int_vec, mp_shift_vec +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value +#endif INTEGER, DIMENSION(:), POINTER :: la_max, lb_max INTEGER, DIMENSION(:), POINTER :: nsgfa, nsgfb INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb INTEGER, ALLOCATABLE :: atom_of_kind(:) - REAL(KIND=dp), ALLOCATABLE :: stmp(:) + REAL(KIND=dp), ALLOCATABLE :: stmp(:), native_s(:, :), native_h(:, :), native_lattr(:, :) REAL(KIND=dp), ALLOCATABLE :: dtmp(:, :), qtmp(:, :), dtmpj(:, :), qtmpj(:, :) + REAL(KIND=dp), ALLOCATABLE :: native_dip(:, :, :), native_quad(:, :, :) REAL(KIND=dp), DIMENSION(:, :), POINTER :: dip_ket1, dip_ket2, dip_ket3, & dip_bra1, dip_bra2, dip_bra3 REAL(KIND=dp), DIMENSION(:, :), POINTER :: quad_ket1, quad_ket2, quad_ket3, & @@ -1534,8 +2339,11 @@ CONTAINS TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: matrix_s TYPE(dft_control_type), POINTER :: dft_control + TYPE(dbcsr_iterator_type) :: iter TYPE(gto_basis_set_type), POINTER :: basis_set_a, basis_set_b TYPE(gto_basis_set_p_type), DIMENSION(:), POINTER :: basis_set_list + TYPE(adjacency_list) :: native_list + TYPE(kpoint_type), POINTER :: kpoints TYPE(neighbor_list_set_p_type), DIMENSION(:), POINTER :: sab_orb TYPE(neighbor_list_iterator_p_type), & DIMENSION(:), POINTER :: nl_iterator @@ -1546,16 +2354,25 @@ CONTAINS !get info from environment vaiarable NULLIFY (atomic_kind_set, qs_kind_set, sab_orb, particle_set) - NULLIFY (dft_control, matrix_s) + NULLIFY (dft_control, matrix_s, kpoints, cell_to_index) CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, & qs_kind_set=qs_kind_set, & sab_orb=sab_orb, & particle_set=particle_set, & dft_control=dft_control, & + kpoints=kpoints, & matrix_s_kp=matrix_s) natom = SIZE(particle_set) nkind = SIZE(atomic_kind_set) nimg = dft_control%nimages + IF (nimg > 1) THEN + CALL get_kpoint_info(kpoint=kpoints, cell_to_index=cell_to_index) + END IF + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif CALL get_atomic_kind_set(atomic_kind_set=atomic_kind_set, atom_of_kind=atom_of_kind) @@ -1570,37 +2387,133 @@ CONTAINS ALLOCATE (qtmpj(quad_n, msao(tb%calc%bas%maxl)**2)) ! allocate dipole/quadrupole moment matrix elemnts - CALL dbcsr_allocate_matrix_set(tb%dipbra, dip_n) - CALL dbcsr_allocate_matrix_set(tb%dipket, dip_n) - CALL dbcsr_allocate_matrix_set(tb%quadbra, quad_n) - CALL dbcsr_allocate_matrix_set(tb%quadket, quad_n) - DO i = 1, dip_n - ALLOCATE (tb%dipbra(i)%matrix) - ALLOCATE (tb%dipket(i)%matrix) - CALL dbcsr_create(tb%dipbra(i)%matrix, template=matrix_s(1, 1)%matrix, & - name="DIPOLE BRAMATRIX") - CALL dbcsr_create(tb%dipket(i)%matrix, template=matrix_s(1, 1)%matrix, & - name="DIPOLE KETMATRIX") - CALL cp_dbcsr_alloc_block_from_nbl(tb%dipbra(i)%matrix, sab_orb) - CALL cp_dbcsr_alloc_block_from_nbl(tb%dipket(i)%matrix, sab_orb) - END DO - DO i = 1, quad_n - ALLOCATE (tb%quadbra(i)%matrix) - ALLOCATE (tb%quadket(i)%matrix) - CALL dbcsr_create(tb%quadbra(i)%matrix, template=matrix_s(1, 1)%matrix, & - name="QUADRUPOLE BRAMATRIX") - CALL dbcsr_create(tb%quadket(i)%matrix, template=matrix_s(1, 1)%matrix, & - name="QUADRUPOLE KETMATRIX") - CALL cp_dbcsr_alloc_block_from_nbl(tb%quadbra(i)%matrix, sab_orb) - CALL cp_dbcsr_alloc_block_from_nbl(tb%quadket(i)%matrix, sab_orb) + CALL dbcsr_allocate_matrix_set(tb%dipbra, dip_n*nimg) + CALL dbcsr_allocate_matrix_set(tb%dipket, dip_n*nimg) + CALL dbcsr_allocate_matrix_set(tb%quadbra, quad_n*nimg) + CALL dbcsr_allocate_matrix_set(tb%quadket, quad_n*nimg) + DO img = 1, nimg + DO i = 1, dip_n + idx = i + dip_n*(img - 1) + ALLOCATE (tb%dipbra(idx)%matrix) + ALLOCATE (tb%dipket(idx)%matrix) + CALL dbcsr_create(tb%dipbra(idx)%matrix, template=matrix_s(1, img)%matrix, & + name="DIPOLE BRAMATRIX") + CALL dbcsr_create(tb%dipket(idx)%matrix, template=matrix_s(1, img)%matrix, & + name="DIPOLE KETMATRIX") + CALL cp_dbcsr_alloc_block_from_nbl(tb%dipbra(idx)%matrix, sab_orb) + CALL cp_dbcsr_alloc_block_from_nbl(tb%dipket(idx)%matrix, sab_orb) + END DO + DO i = 1, quad_n + idx = i + quad_n*(img - 1) + ALLOCATE (tb%quadbra(idx)%matrix) + ALLOCATE (tb%quadket(idx)%matrix) + CALL dbcsr_create(tb%quadbra(idx)%matrix, template=matrix_s(1, img)%matrix, & + name="QUADRUPOLE BRAMATRIX") + CALL dbcsr_create(tb%quadket(idx)%matrix, template=matrix_s(1, img)%matrix, & + name="QUADRUPOLE KETMATRIX") + CALL cp_dbcsr_alloc_block_from_nbl(tb%quadbra(idx)%matrix, sab_orb) + CALL cp_dbcsr_alloc_block_from_nbl(tb%quadket(idx)%matrix, sab_orb) + END DO END DO + IF (mp_test_mode == 80 .OR. mp_test_mode == 82) THEN + IF (nimg > 1) CPABORT("Native tblite multipole test with k-points not implemented") + ALLOCATE (native_s(tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_h(tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_dip(dip_n, tb%calc%bas%nao, tb%calc%bas%nao)) + ALLOCATE (native_quad(quad_n, tb%calc%bas%nao, tb%calc%bas%nao)) + CALL get_lattice_points(tb%mol%periodic, tb%mol%lattice, get_cutoff(tb%calc%bas, 1.0_dp), native_lattr) + CALL new_adjacency_list(native_list, tb%mol, native_lattr, get_cutoff(tb%calc%bas, 1.0_dp)) + CALL get_hamiltonian(tb%mol, native_lattr, native_list, tb%calc%bas, tb%calc%h0, tb%selfenergy, & + native_s, native_dip, native_quad, native_h) + + CALL dbcsr_iterator_start(iter, tb%dipbra(1)%matrix) + DO WHILE (dbcsr_iterator_blocks_left(iter)) + CALL dbcsr_iterator_next_block(iter, irow, icol, dip_bra1) + CALL dbcsr_get_block_p(matrix=tb%dipbra(2)%matrix, row=irow, col=icol, BLOCK=dip_bra2, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%dipbra(3)%matrix, row=irow, col=icol, BLOCK=dip_bra3, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%dipket(1)%matrix, row=irow, col=icol, BLOCK=dip_ket1, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%dipket(2)%matrix, row=irow, col=icol, BLOCK=dip_ket2, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%dipket(3)%matrix, row=irow, col=icol, BLOCK=dip_ket3, found=found) + CPASSERT(found) + + CALL dbcsr_get_block_p(matrix=tb%quadbra(1)%matrix, row=irow, col=icol, BLOCK=quad_bra1, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadbra(2)%matrix, row=irow, col=icol, BLOCK=quad_bra2, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadbra(3)%matrix, row=irow, col=icol, BLOCK=quad_bra3, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadbra(4)%matrix, row=irow, col=icol, BLOCK=quad_bra4, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadbra(5)%matrix, row=irow, col=icol, BLOCK=quad_bra5, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadbra(6)%matrix, row=irow, col=icol, BLOCK=quad_bra6, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(1)%matrix, row=irow, col=icol, BLOCK=quad_ket1, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(2)%matrix, row=irow, col=icol, BLOCK=quad_ket2, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(3)%matrix, row=irow, col=icol, BLOCK=quad_ket3, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(4)%matrix, row=irow, col=icol, BLOCK=quad_ket4, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(5)%matrix, row=irow, col=icol, BLOCK=quad_ket5, found=found) + CPASSERT(found) + CALL dbcsr_get_block_p(matrix=tb%quadket(6)%matrix, row=irow, col=icol, BLOCK=quad_ket6, found=found) + CPASSERT(found) + + i0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(irow) + 1) + j0 = tb%calc%bas%iao_sh(tb%calc%bas%ish_at(icol) + 1) + DO j = 1, SIZE(dip_bra1, 1) + DO i = 1, SIZE(dip_bra1, 2) + dip_bra1(j, i) = native_dip(1, i0 + j, j0 + i) + dip_bra2(j, i) = native_dip(2, i0 + j, j0 + i) + dip_bra3(j, i) = native_dip(3, i0 + j, j0 + i) + dip_ket1(j, i) = native_dip(1, j0 + i, i0 + j) + dip_ket2(j, i) = native_dip(2, j0 + i, i0 + j) + dip_ket3(j, i) = native_dip(3, j0 + i, i0 + j) + + quad_bra1(j, i) = native_quad(1, i0 + j, j0 + i) + quad_bra2(j, i) = native_quad(2, i0 + j, j0 + i) + quad_bra3(j, i) = native_quad(3, i0 + j, j0 + i) + quad_bra4(j, i) = native_quad(4, i0 + j, j0 + i) + quad_bra5(j, i) = native_quad(5, i0 + j, j0 + i) + quad_bra6(j, i) = native_quad(6, i0 + j, j0 + i) + quad_ket1(j, i) = native_quad(1, j0 + i, i0 + j) + quad_ket2(j, i) = native_quad(2, j0 + i, i0 + j) + quad_ket3(j, i) = native_quad(3, j0 + i, i0 + j) + quad_ket4(j, i) = native_quad(4, j0 + i, i0 + j) + quad_ket5(j, i) = native_quad(5, j0 + i, i0 + j) + quad_ket6(j, i) = native_quad(6, j0 + i, i0 + j) + END DO + END DO + END DO + CALL dbcsr_iterator_stop(iter) + + DO i = 1, dip_n + CALL dbcsr_finalize(tb%dipbra(i)%matrix) + CALL dbcsr_finalize(tb%dipket(i)%matrix) + END DO + DO i = 1, quad_n + CALL dbcsr_finalize(tb%quadbra(i)%matrix) + CALL dbcsr_finalize(tb%quadket(i)%matrix) + END DO + + DEALLOCATE (native_s, native_h, native_dip, native_quad, native_lattr, basis_set_list) + CALL timestop(handle) + RETURN + END IF + !loop over all atom pairs with a non-zero overlap (sab_orb) NULLIFY (nl_iterator) CALL neighbor_list_iterator_create(nl_iterator, sab_orb) DO WHILE (neighbor_list_iterate(nl_iterator) == 0) CALL get_iterator_info(nl_iterator, ikind=ikind, jkind=jkind, & - iatom=iatom, jatom=jatom, r=rij) + iatom=iatom, jatom=jatom, r=rij, cell=cell) r2 = NORM2(rij(:))**2 @@ -1614,68 +2527,84 @@ CONTAINS jkind = i END IF + IF (nimg == 1) THEN + ic = 1 + ELSE + ic = cell_to_index(cell(1), cell(2), cell(3)) + CPASSERT(ic > 0) + END IF + id1 = 1 + dip_n*(ic - 1) + id2 = 2 + dip_n*(ic - 1) + id3 = 3 + dip_n*(ic - 1) + iq1 = 1 + quad_n*(ic - 1) + iq2 = 2 + quad_n*(ic - 1) + iq3 = 3 + quad_n*(ic - 1) + iq4 = 4 + quad_n*(ic - 1) + iq5 = 5 + quad_n*(ic - 1) + iq6 = 6 + quad_n*(ic - 1) + ityp = tb%mol%id(icol) jtyp = tb%mol%id(irow) NULLIFY (dip_bra1, dip_bra2, dip_bra3) - CALL dbcsr_get_block_p(matrix=tb%dipbra(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id1)%matrix, & row=irow, col=icol, BLOCK=dip_bra1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipbra(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id2)%matrix, & row=irow, col=icol, BLOCK=dip_bra2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipbra(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipbra(id3)%matrix, & row=irow, col=icol, BLOCK=dip_bra3, found=found) CPASSERT(found) NULLIFY (dip_ket1, dip_ket2, dip_ket3) - CALL dbcsr_get_block_p(matrix=tb%dipket(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id1)%matrix, & row=irow, col=icol, BLOCK=dip_ket1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipket(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id2)%matrix, & row=irow, col=icol, BLOCK=dip_ket2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%dipket(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%dipket(id3)%matrix, & row=irow, col=icol, BLOCK=dip_ket3, found=found) CPASSERT(found) NULLIFY (quad_bra1, quad_bra2, quad_bra3, quad_bra4, quad_bra5, quad_bra6) - CALL dbcsr_get_block_p(matrix=tb%quadbra(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq1)%matrix, & row=irow, col=icol, BLOCK=quad_bra1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq2)%matrix, & row=irow, col=icol, BLOCK=quad_bra2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq3)%matrix, & row=irow, col=icol, BLOCK=quad_bra3, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(4)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq4)%matrix, & row=irow, col=icol, BLOCK=quad_bra4, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(5)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq5)%matrix, & row=irow, col=icol, BLOCK=quad_bra5, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadbra(6)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadbra(iq6)%matrix, & row=irow, col=icol, BLOCK=quad_bra6, found=found) CPASSERT(found) NULLIFY (quad_ket1, quad_ket2, quad_ket3, quad_ket4, quad_ket5, quad_ket6) - CALL dbcsr_get_block_p(matrix=tb%quadket(1)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq1)%matrix, & row=irow, col=icol, BLOCK=quad_ket1, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(2)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq2)%matrix, & row=irow, col=icol, BLOCK=quad_ket2, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(3)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq3)%matrix, & row=irow, col=icol, BLOCK=quad_ket3, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(4)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq4)%matrix, & row=irow, col=icol, BLOCK=quad_ket4, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(5)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq5)%matrix, & row=irow, col=icol, BLOCK=quad_ket5, found=found) CPASSERT(found) - CALL dbcsr_get_block_p(matrix=tb%quadket(6)%matrix, & + CALL dbcsr_get_block_p(matrix=tb%quadket(iq6)%matrix, & row=irow, col=icol, BLOCK=quad_ket6, found=found) CPASSERT(found) @@ -1698,7 +2627,8 @@ CONTAINS nsgfb => basis_set_b%nsgf_set ! --------- Hamiltonian - IF (icol == irow) THEN + ! Periodic self-images are off-diagonal lattice contributions, not the on-site block. + IF (icol == irow .AND. r2 < same_atom**2) THEN DO iset = 1, nseta DO jset = 1, nsetb CALL multipole_cgto(tb%calc%bas%cgto(jset, ityp), tb%calc%bas%cgto(iset, ityp), & @@ -1738,10 +2668,18 @@ CONTAINS ELSE DO iset = 1, nseta DO jset = 1, nsetb + mp_int_vec = -rij + mp_shift_vec = -rij + IF (mp_test_mode == 14) THEN + mp_int_vec = rij + mp_shift_vec = rij + ELSEIF (mp_test_mode == 15) THEN + mp_shift_vec = rij + ELSEIF (mp_test_mode == 16) THEN + mp_int_vec = rij + END IF CALL multipole_cgto(tb%calc%bas%cgto(jset, jtyp), tb%calc%bas%cgto(iset, ityp), & - & r2, -rij, tb%calc%bas%intcut, stmp, dtmp, qtmp) - CALL multipole_cgto(tb%calc%bas%cgto(iset, ityp), tb%calc%bas%cgto(jset, jtyp), & - & r2, rij, tb%calc%bas%intcut, stmp, dtmpj, qtmpj) + & r2, mp_int_vec, tb%calc%bas%intcut, stmp, dtmp, qtmp) DO inda = 1, nsgfa(iset) ia = first_sgfa(1, iset) - first_sgfa(1, 1) + inda @@ -1749,6 +2687,87 @@ CONTAINS ib = first_sgfb(1, jset) - first_sgfb(1, 1) + indb ij = indb + nsgfb(jset)*(inda - 1) + CALL tb_shift_multipole(mp_shift_vec, stmp(ij), dtmp(:, ij), qtmp(:, ij), & + dtmpj(:, ij), qtmpj(:, ij)) + IF (icol == irow .AND. r2 >= same_atom**2) THEN + IF (nimg > 1) THEN + ! Match the k-point image block orientation used for self-image quadrupoles. + qtmp(:, ij) = -qtmp(:, ij) + qtmpj(:, ij) = -qtmpj(:, ij) + END IF + IF (mp_test_mode == 30 .OR. mp_test_mode == 32 .OR. mp_test_mode == 33) THEN + dtmpj(:, ij) = dtmp(:, ij) + qtmpj(:, ij) = qtmp(:, ij) + ELSEIF (mp_test_mode == 31) THEN + CALL tb_shift_multipole(-mp_shift_vec, stmp(ij), dtmp(:, ij), qtmp(:, ij), & + dtmpj(:, ij), qtmpj(:, ij)) + END IF + IF (mp_test_mode == 40 .OR. mp_test_mode == 41 .OR. mp_test_mode == 44) THEN + dtmp(:, ij) = -dtmp(:, ij) + END IF + IF (mp_test_mode == 40 .OR. mp_test_mode == 42 .OR. mp_test_mode == 44) THEN + dtmpj(:, ij) = -dtmpj(:, ij) + END IF + IF (mp_test_mode == 40 .OR. mp_test_mode == 41 .OR. mp_test_mode == 45) THEN + qtmp(:, ij) = -qtmp(:, ij) + END IF + IF (mp_test_mode == 40 .OR. mp_test_mode == 42 .OR. mp_test_mode == 45) THEN + qtmpj(:, ij) = -qtmpj(:, ij) + END IF + IF (mp_test_mode == 43) THEN + dtmp(:, ij) = 0.0_dp + qtmp(:, ij) = 0.0_dp + dtmpj(:, ij) = 0.0_dp + qtmpj(:, ij) = 0.0_dp + END IF + END IF + IF (r2 >= same_atom**2) THEN + IF (mp_test_mode == 46 .OR. mp_test_mode == 48) THEN + dtmp(:, ij) = -dtmp(:, ij) + dtmpj(:, ij) = -dtmpj(:, ij) + END IF + IF (mp_test_mode == 46 .OR. mp_test_mode == 49) THEN + qtmp(:, ij) = -qtmp(:, ij) + qtmpj(:, ij) = -qtmpj(:, ij) + END IF + IF (mp_test_mode == 47) THEN + dtmp(:, ij) = 0.0_dp + qtmp(:, ij) = 0.0_dp + dtmpj(:, ij) = 0.0_dp + qtmpj(:, ij) = 0.0_dp + END IF + IF (mp_test_mode == 50) THEN + dtmp(:, ij) = 0.25_dp*dtmp(:, ij) + qtmp(:, ij) = 0.25_dp*qtmp(:, ij) + dtmpj(:, ij) = 0.25_dp*dtmpj(:, ij) + qtmpj(:, ij) = 0.25_dp*qtmpj(:, ij) + ELSEIF (mp_test_mode == 51) THEN + dtmp(:, ij) = 0.5_dp*dtmp(:, ij) + qtmp(:, ij) = 0.5_dp*qtmp(:, ij) + dtmpj(:, ij) = 0.5_dp*dtmpj(:, ij) + qtmpj(:, ij) = 0.5_dp*qtmpj(:, ij) + ELSEIF (mp_test_mode == 52) THEN + dtmp(:, ij) = 0.75_dp*dtmp(:, ij) + qtmp(:, ij) = 0.75_dp*qtmp(:, ij) + dtmpj(:, ij) = 0.75_dp*dtmpj(:, ij) + qtmpj(:, ij) = 0.75_dp*qtmpj(:, ij) + ELSEIF (mp_test_mode == 53) THEN + dtmp(:, ij) = -0.25_dp*dtmp(:, ij) + qtmp(:, ij) = -0.25_dp*qtmp(:, ij) + dtmpj(:, ij) = -0.25_dp*dtmpj(:, ij) + qtmpj(:, ij) = -0.25_dp*qtmpj(:, ij) + ELSEIF (mp_test_mode == 54) THEN + dtmp(:, ij) = -0.5_dp*dtmp(:, ij) + qtmp(:, ij) = -0.5_dp*qtmp(:, ij) + dtmpj(:, ij) = -0.5_dp*dtmpj(:, ij) + qtmpj(:, ij) = -0.5_dp*qtmpj(:, ij) + ELSEIF (mp_test_mode == 55) THEN + dtmp(:, ij) = -0.75_dp*dtmp(:, ij) + qtmp(:, ij) = -0.75_dp*qtmp(:, ij) + dtmpj(:, ij) = -0.75_dp*dtmpj(:, ij) + qtmpj(:, ij) = -0.75_dp*qtmpj(:, ij) + END IF + END IF dip_bra1(ib, ia) = dip_bra1(ib, ia) + dtmp(1, ij) dip_bra2(ib, ia) = dip_bra2(ib, ia) + dtmp(2, ij) @@ -1761,8 +2780,6 @@ CONTAINS quad_bra5(ib, ia) = quad_bra5(ib, ia) + qtmp(5, ij) quad_bra6(ib, ia) = quad_bra6(ib, ia) + qtmp(6, ij) - ij = inda + nsgfa(iset)*(indb - 1) - dip_ket1(ib, ia) = dip_ket1(ib, ia) + dtmpj(1, ij) dip_ket2(ib, ia) = dip_ket2(ib, ia) + dtmpj(2, ij) dip_ket3(ib, ia) = dip_ket3(ib, ia) + dtmpj(3, ij) @@ -1781,11 +2798,11 @@ CONTAINS END DO CALL neighbor_list_iterator_release(nl_iterator) - DO i = 1, dip_n + DO i = 1, SIZE(tb%dipbra) CALL dbcsr_finalize(tb%dipbra(i)%matrix) CALL dbcsr_finalize(tb%dipket(i)%matrix) END DO - DO i = 1, quad_n + DO i = 1, SIZE(tb%quadbra) CALL dbcsr_finalize(tb%quadbra(i)%matrix) CALL dbcsr_finalize(tb%quadket(i)%matrix) END DO @@ -1802,6 +2819,45 @@ CONTAINS END SUBROUTINE tb_get_multipole +! ************************************************************************************************** +!> \brief Shift a multipole operator from one center to the other. +!> \param vec displacement vector between the two centers +!> \param s overlap integral +!> \param di dipole integral on the original center +!> \param qi quadrupole integral on the original center +!> \param dj dipole integral on the shifted center +!> \param qj quadrupole integral on the shifted center +! ************************************************************************************************** + PURE SUBROUTINE tb_shift_multipole(vec, s, di, qi, dj, qj) + + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: vec + REAL(KIND=dp), INTENT(IN) :: s + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: di, qi + REAL(KIND=dp), DIMENSION(:), INTENT(OUT) :: dj, qj + + REAL(KIND=dp) :: tr + + dj(1) = di(1) + vec(1)*s + dj(2) = di(2) + vec(2)*s + dj(3) = di(3) + vec(3)*s + + qj(1) = 2*vec(1)*di(1) + vec(1)**2*s + qj(3) = 2*vec(2)*di(2) + vec(2)**2*s + qj(6) = 2*vec(3)*di(3) + vec(3)**2*s + qj(2) = vec(1)*di(2) + vec(2)*di(1) + vec(1)*vec(2)*s + qj(4) = vec(1)*di(3) + vec(3)*di(1) + vec(1)*vec(3)*s + qj(5) = vec(2)*di(3) + vec(3)*di(2) + vec(2)*vec(3)*s + tr = 0.5_dp*(qj(1) + qj(3) + qj(6)) + + qj(1) = qi(1) + 1.5_dp*qj(1) - tr + qj(2) = qi(2) + 1.5_dp*qj(2) + qj(3) = qi(3) + 1.5_dp*qj(3) - tr + qj(4) = qi(4) + 1.5_dp*qj(4) + qj(5) = qi(5) + 1.5_dp*qj(5) + qj(6) = qi(6) + 1.5_dp*qj(6) - tr + + END SUBROUTINE tb_shift_multipole + ! ************************************************************************************************** !> \brief compute the mulliken properties (AO resolved) !> \param p_matrix ... @@ -1821,14 +2877,25 @@ CONTAINS CHARACTER(len=*), PARAMETER :: routineN = 'contract_dens' - INTEGER :: handle, i, iblock_col, iblock_row, & - ispin, j, nspin + INTEGER :: handle, i, iblock_col, & + iblock_row, ispin, j, mp_test_mode, & + nspin +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value +#endif LOGICAL :: found REAL(KIND=dp), DIMENSION(:, :), POINTER :: bra, ket, p_block TYPE(dbcsr_iterator_type) :: iter CALL timeset(routineN, handle) + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif + nspin = SIZE(p_matrix) output = 0.0_dp DO ispin = 1, nspin @@ -1845,12 +2912,32 @@ CONTAINS IF (.NOT. found) CPABORT("missing block") IF (.NOT. (ASSOCIATED(bra) .AND. ASSOCIATED(p_block))) CYCLE - DO j = 1, SIZE(p_block, 1) - DO i = 1, SIZE(p_block, 2) - output(iblock_row) = output(iblock_row) + p_block(j, i)*ket(j, i) + IF (iblock_col == iblock_row) THEN + IF (mp_test_mode == 70) THEN + DO j = 1, SIZE(p_block, 1) + DO i = 1, SIZE(p_block, 2) + output(iblock_row) = output(iblock_row) + p_block(j, i)*ket(j, i) + END DO + END DO + ELSEIF (mp_test_mode == 71) THEN + DO j = 1, SIZE(p_block, 1) + DO i = 1, SIZE(p_block, 2) + output(iblock_row) = output(iblock_row) + 0.5_dp*p_block(j, i)*(bra(j, i) + ket(j, i)) + END DO + END DO + ELSE + DO j = 1, SIZE(p_block, 1) + DO i = 1, SIZE(p_block, 2) + output(iblock_row) = output(iblock_row) + p_block(j, i)*bra(j, i) + END DO + END DO + END IF + ELSE + DO j = 1, SIZE(p_block, 1) + DO i = 1, SIZE(p_block, 2) + output(iblock_row) = output(iblock_row) + p_block(j, i)*ket(j, i) + END DO END DO - END DO - IF (iblock_col /= iblock_row) THEN DO j = 1, SIZE(p_block, 1) DO i = 1, SIZE(p_block, 2) output(iblock_col) = output(iblock_col) + p_block(j, i)*bra(j, i) @@ -1866,6 +2953,44 @@ CONTAINS END SUBROUTINE contract_dens +! ************************************************************************************************** +!> \brief compute the AO-resolved density contraction for real-space k-point image matrices +!> \param p_matrix ... +!> \param bra_mat ... +!> \param ket_mat ... +!> \param iop ... +!> \param nops ... +!> \param output ... +!> \param para_env ... +! ************************************************************************************************** + SUBROUTINE contract_dens_kp(p_matrix, bra_mat, ket_mat, iop, nops, output, para_env) + TYPE(dbcsr_p_type), DIMENSION(:, :), POINTER :: p_matrix + TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: bra_mat, ket_mat + INTEGER, INTENT(IN) :: iop, nops + REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: output + TYPE(mp_para_env_type), POINTER :: para_env + + INTEGER :: ic, idx, nimg + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: image_output + TYPE(dbcsr_p_type), DIMENSION(:), POINTER :: p_image + + nimg = SIZE(p_matrix, 2) + output = 0.0_dp + ALLOCATE (image_output(SIZE(output))) + DO ic = 1, nimg + idx = iop + nops*(ic - 1) + CPASSERT(idx <= SIZE(bra_mat)) + CPASSERT(idx <= SIZE(ket_mat)) + NULLIFY (p_image) + p_image => p_matrix(:, ic) + image_output = 0.0_dp + CALL contract_dens(p_image, bra_mat(idx)%matrix, ket_mat(idx)%matrix, image_output, para_env) + output = output + image_output + END DO + DEALLOCATE (image_output) + + END SUBROUTINE contract_dens_kp + ! ************************************************************************************************** !> \brief save gradient to force !> \param qs_env ... @@ -1883,7 +3008,9 @@ CONTAINS CHARACTER(len=*), PARAMETER :: routineN = 'tb_grad2force' - INTEGER :: atoma, handle, iatom, ikind, natom + CHARACTER(LEN=default_path_length) :: dump_file + INTEGER :: atoma, dump_status, dump_unit, handle, & + iatom, ikind, natom INTEGER, ALLOCATABLE, DIMENSION(:) :: atom_of_kind, kind_of TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set TYPE(particle_type), DIMENSION(:), POINTER :: particle_set @@ -1899,6 +3026,20 @@ CONTAINS natom = SIZE(particle_set) + dump_status = 1 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_FORCE_DUMP", dump_file, STATUS=dump_status) +#endif + IF (dump_status == 0) THEN + OPEN (NEWUNIT=dump_unit, FILE=TRIM(dump_file), STATUS="UNKNOWN", & + POSITION="APPEND", ACTION="WRITE") + WRITE (dump_unit, "(A,1X,I0)") "component", ityp + DO iatom = 1, natom + WRITE (dump_unit, "(I0,3(1X,ES24.16))") iatom, tb%grad(:, iatom)/para_env%num_pe + END DO + CLOSE (dump_unit) + END IF + SELECT CASE (ityp) CASE DEFAULT CPABORT("unknown force type") @@ -2111,9 +3252,23 @@ CONTAINS INTEGER, DIMENSION(:), POINTER :: nsgfa, nsgfb INTEGER, DIMENSION(:, :), POINTER :: first_sgfa, first_sgfb INTEGER, DIMENSION(:, :, :), POINTER :: cell_to_index - LOGICAL :: found + LOGICAL :: found, image_pair REAL(KIND=dp) :: r2, dr, itemp, jtemp, rr, hij, shpoly, dshpoly, idHdc, jdHdc, & - scal, hp, i_a_shift, j_a_shift, ishift, jshift + scal, hp, i_a_shift, j_a_shift, ishift, jshift, & + dip_deriv_fac, quad_deriv_fac, dip_deriv_fac_pair, & + quad_deriv_fac_pair, overlap_deriv_fac, pot_deriv_scale, & + w_deriv_scale, h0_deriv_scale, mp_deriv_scale, & + pot_image_deriv_scale, w_image_deriv_scale, & + h0_image_deriv_scale, mp_image_deriv_scale, & + pot_pair_scale, w_pair_scale, h0_pair_scale, mp_pair_scale, & + pot_self_image_deriv_scale, w_self_image_deriv_scale, & + h0_self_image_deriv_scale, mp_self_image_deriv_scale, & + cn_image_scale + INTEGER :: mp_test_mode +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + INTEGER :: debug_status + CHARACTER(LEN=32) :: debug_value, scale_value +#endif REAL(KIND=dp), DIMENSION(3) :: rij, dgrad REAL(KIND=dp), DIMENSION(3, 3) :: hsigma REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: dE, t_ov, idip, jdip, iquad, jquad @@ -2156,6 +3311,82 @@ CONTAINS END IF h0 => tb%calc%h0 + mp_test_mode = 0 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_MULTIPOLE_TEST", debug_value, STATUS=debug_status) + IF (debug_status == 0) READ (debug_value, *, IOSTAT=debug_status) mp_test_mode +#endif + dip_deriv_fac = -1.0_dp + quad_deriv_fac = -1.0_dp + IF (mp_test_mode == 7 .OR. mp_test_mode == 11) THEN + dip_deriv_fac = 1.0_dp + quad_deriv_fac = 1.0_dp + END IF + IF (mp_test_mode == 8 .OR. mp_test_mode == 12) THEN + dip_deriv_fac = 0.0_dp + quad_deriv_fac = 0.0_dp + END IF + IF (mp_test_mode == 13 .OR. mp_test_mode == 14 .OR. mp_test_mode == 15 .OR. & + mp_test_mode == 16 .OR. mp_test_mode == 21 .OR. mp_test_mode == 33 .OR. & + mp_test_mode == 34 .OR. mp_test_mode == 37) THEN + dip_deriv_fac = -0.5_dp + quad_deriv_fac = -0.5_dp + END IF + IF (mp_test_mode == 17) THEN + dip_deriv_fac = -1.0_dp + quad_deriv_fac = 0.0_dp + END IF + IF (mp_test_mode == 18) THEN + dip_deriv_fac = 0.0_dp + quad_deriv_fac = -1.0_dp + END IF + pot_deriv_scale = 1.0_dp + w_deriv_scale = 1.0_dp + h0_deriv_scale = 1.0_dp + mp_deriv_scale = 1.0_dp +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_POT_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) pot_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_W_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) w_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_H0_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) h0_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_MP_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) mp_deriv_scale +#endif + pot_image_deriv_scale = pot_deriv_scale + w_image_deriv_scale = w_deriv_scale + h0_image_deriv_scale = h0_deriv_scale + mp_image_deriv_scale = mp_deriv_scale +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_POT_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) pot_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_W_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) w_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_H0_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) h0_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_MP_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) mp_image_deriv_scale +#endif + pot_self_image_deriv_scale = pot_image_deriv_scale + w_self_image_deriv_scale = w_image_deriv_scale + h0_self_image_deriv_scale = h0_image_deriv_scale + mp_self_image_deriv_scale = mp_image_deriv_scale +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_POT_SELF_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) pot_self_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_W_SELF_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) w_self_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_H0_SELF_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) h0_self_image_deriv_scale + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_MP_SELF_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) mp_self_image_deriv_scale +#endif + cn_image_scale = 1.0_dp +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_DH_CN_IMAGE_SCALE", scale_value, STATUS=debug_status) + IF (debug_status == 0) READ (scale_value, *, IOSTAT=debug_status) cn_image_scale +#endif NULLIFY (matrix_p) IF (use_rho) THEN @@ -2208,6 +3439,7 @@ CONTAINS r2 = DOT_PRODUCT(rij, rij) dr = SQRT(r2) IF (icol == jrow .AND. dr < same_atom) CYCLE + IF (mp_test_mode == 140 .AND. icol == jrow) CYCLE rr = SQRT(dr/(h0%rad(ikind) + h0%rad(jkind))) !get basis information @@ -2228,6 +3460,17 @@ CONTAINS ic = cell_to_index(cellind(1), cellind(2), cellind(3)) CPASSERT(ic > 0) END IF + image_pair = (cellind(1) /= 0 .OR. cellind(2) /= 0 .OR. cellind(3) /= 0) + pot_pair_scale = MERGE(pot_image_deriv_scale, pot_deriv_scale, image_pair) + w_pair_scale = MERGE(w_image_deriv_scale, w_deriv_scale, image_pair) + h0_pair_scale = MERGE(h0_image_deriv_scale, h0_deriv_scale, image_pair) + mp_pair_scale = MERGE(mp_image_deriv_scale, mp_deriv_scale, image_pair) + IF (icol == jrow .AND. image_pair) THEN + pot_pair_scale = pot_self_image_deriv_scale + w_pair_scale = w_self_image_deriv_scale + h0_pair_scale = h0_self_image_deriv_scale + mp_pair_scale = mp_self_image_deriv_scale + END IF NULLIFY (pblock) CALL dbcsr_get_block_p(matrix=matrix_p(1, ic)%matrix, & @@ -2245,6 +3488,17 @@ CONTAINS jdip(:) = tb%pot%vdp(:, jrow, 1) iquad(:) = tb%pot%vqp(:, icol, 1) jquad(:) = tb%pot%vqp(:, jrow, 1) + dip_deriv_fac_pair = dip_deriv_fac + quad_deriv_fac_pair = quad_deriv_fac + overlap_deriv_fac = 1.0_dp + IF (icol == jrow) THEN + IF (mp_test_mode == 141) THEN + dip_deriv_fac_pair = 0.0_dp + quad_deriv_fac_pair = 0.0_dp + ELSEIF (mp_test_mode == 142) THEN + overlap_deriv_fac = 0.0_dp + END IF + END IF ni = tb%calc%bas%ish_at(icol) DO iset = 1, nseti @@ -2256,9 +3510,23 @@ CONTAINS jshift = j_a_shift + tb%pot%vsh(nj + jset, 1) !get integrals and derivatives - CALL multipole_grad_cgto(tb%calc%bas%cgto(iset, ityp), tb%calc%bas%cgto(jset, jtyp), & - & r2, rij, tb%calc%bas%intcut, t_ov, t_dip, t_quad, t_d_ov, t_i_dip, t_i_quad, & - & t_j_dip, t_j_quad) + IF (mp_test_mode == 20 .OR. mp_test_mode == 21) THEN + CALL multipole_grad_cgto(tb%calc%bas%cgto(jset, jtyp), tb%calc%bas%cgto(iset, ityp), & + & r2, rij, tb%calc%bas%intcut, t_ov, t_dip, t_quad, t_d_ov, t_j_dip, t_j_quad, & + & t_i_dip, t_i_quad) + ELSEIF (mp_test_mode == 34 .OR. mp_test_mode == 35) THEN + CALL multipole_grad_cgto(tb%calc%bas%cgto(jset, jtyp), tb%calc%bas%cgto(iset, ityp), & + & r2, -rij, tb%calc%bas%intcut, t_ov, t_dip, t_quad, t_d_ov, t_j_dip, t_j_quad, & + & t_i_dip, t_i_quad) + ELSEIF (mp_test_mode == 36 .OR. mp_test_mode == 37) THEN + CALL multipole_grad_cgto(tb%calc%bas%cgto(iset, ityp), tb%calc%bas%cgto(jset, jtyp), & + & r2, -rij, tb%calc%bas%intcut, t_ov, t_dip, t_quad, t_d_ov, t_i_dip, t_i_quad, & + & t_j_dip, t_j_quad) + ELSE + CALL multipole_grad_cgto(tb%calc%bas%cgto(iset, ityp), tb%calc%bas%cgto(jset, jtyp), & + & r2, rij, tb%calc%bas%intcut, t_ov, t_dip, t_quad, t_d_ov, t_i_dip, t_i_quad, & + & t_j_dip, t_j_quad) + END IF shpoly = (1.0_dp + h0%shpoly(iset, ikind)*rr) & *(1.0_dp + h0%shpoly(jset, jkind)*rr) @@ -2279,34 +3547,52 @@ CONTAINS DO indb = 1, nsgfb(jset) ib = first_sgfb(1, jset) - first_sgfb(1, 1) + indb - ij = inda + nsgfa(iset)*(indb - 1) + IF (mp_test_mode == 20 .OR. mp_test_mode == 21 .OR. & + mp_test_mode == 34 .OR. mp_test_mode == 35) THEN + ij = indb + nsgfb(jset)*(inda - 1) + ELSE + ij = inda + nsgfa(iset)*(indb - 1) + END IF - itemp = itemp + idHdc*pblock(ib, ia)*t_ov(ij) - jtemp = jtemp + jdHdc*pblock(ib, ia)*t_ov(ij) + itemp = itemp + overlap_deriv_fac*idHdc*pblock(ib, ia)*t_ov(ij) + jtemp = jtemp + overlap_deriv_fac*jdHdc*pblock(ib, ia)*t_ov(ij) hp = 2*hij*pblock(ib, ia) dgrad(:) = dgrad(:) & - - (ishift + jshift)*pblock(ib, ia)*t_d_ov(:, ij) & - - 2*wblock(ib, ia)*t_d_ov(:, ij) & - + hp*shpoly*t_d_ov(:, ij) & - + hp*dshpoly*t_ov(ij)*rij & - - pblock(ib, ia)*( & - MATMUL(t_i_dip(:, :, ij), idip) & - + MATMUL(t_j_dip(:, :, ij), jdip) & - + MATMUL(t_i_quad(:, :, ij), iquad) & - + MATMUL(t_j_quad(:, :, ij), jquad)) + + overlap_deriv_fac*(-pot_pair_scale*(ishift + jshift)*pblock(ib, ia)*t_d_ov(:, ij) & + - 2*w_pair_scale*wblock(ib, ia)*t_d_ov(:, ij) & + + h0_pair_scale*(hp*shpoly*t_d_ov(:, ij) & + + hp*dshpoly*t_ov(ij)*rij)) & + + mp_pair_scale*pblock(ib, ia)*( & + dip_deriv_fac_pair*(MATMUL(t_i_dip(:, :, ij), idip) & + + MATMUL(t_j_dip(:, :, ij), jdip)) & + + quad_deriv_fac_pair*(MATMUL(t_i_quad(:, :, ij), iquad) & + + MATMUL(t_j_quad(:, :, ij), jquad))) END DO END DO - dE(icol) = dE(icol) + itemp - dE(jrow) = dE(jrow) + jtemp + ! Periodic self-image pairs share one atom in the sorted CP2K block representation. + IF (icol == jrow) THEN + IF (image_pair) THEN + dE(icol) = dE(icol) + cn_image_scale*0.5_dp*(itemp + jtemp) + ELSE + dE(icol) = dE(icol) + 0.5_dp*(itemp + jtemp) + END IF + ELSE + dE(icol) = dE(icol) + itemp + dE(jrow) = dE(jrow) + jtemp + END IF tb%grad(:, icol) = tb%grad(:, icol) - dgrad tb%grad(:, jrow) = tb%grad(:, jrow) + dgrad IF (tb%use_virial) THEN IF (icol == jrow) THEN DO ia = 1, 3 DO ib = 1, 3 - hsigma(ia, ib) = hsigma(ia, ib) + 0.25_dp*(rij(ia)*dgrad(ib) + rij(ib)*dgrad(ia)) + IF (image_pair .AND. nimg > 1) THEN + hsigma(ia, ib) = hsigma(ia, ib) - 0.25_dp*(rij(ia)*dgrad(ib) + rij(ib)*dgrad(ia)) + ELSE + hsigma(ia, ib) = hsigma(ia, ib) + 0.25_dp*(rij(ia)*dgrad(ib) + rij(ib)*dgrad(ia)) + END IF END DO END DO ELSE @@ -2329,8 +3615,13 @@ CONTAINS CALL tb_add_grad(tb%grad, tb%dcndr, dE, tb%mol%nat) CALL tb_grad2force(qs_env, tb, para_env, 4) + CALL tb_dump_sigma_component("before_h0_off", tb%sigma, para_env) tb%sigma = tb%sigma + hsigma - IF (tb%use_virial) CALL tb_add_sig(tb%sigma, tb%dcndL, dE, tb%mol%nat) + CALL tb_dump_sigma_component("after_h0_off_direct", tb%sigma, para_env) + IF (tb%use_virial) THEN + CALL tb_add_sig(tb%sigma, tb%dcndL, dE, tb%mol%nat) + CALL tb_dump_sigma_component("after_h0_off_cn", tb%sigma, para_env) + END IF DEALLOCATE (dE) DEALLOCATE (basis_set_list) @@ -2350,6 +3641,554 @@ CONTAINS END SUBROUTINE tb_derive_dH_off +! ************************************************************************************************** +!> \brief Run native tblite CLI and compare against CP2K/tblite. +!> \param qs_env ... +! ************************************************************************************************** + SUBROUTINE tb_reference_cli_compare(qs_env) + + TYPE(qs_environment_type), POINTER :: qs_env + + CHARACTER(LEN=*), PARAMETER :: routineN = 'tb_reference_cli_compare' + + CHARACTER(LEN=32) :: acc_str, charge_str, iter_str, spin_str + CHARACTER(LEN=8) :: method + CHARACTER(LEN=8*default_path_length) :: command + CHARACTER(LEN=default_path_length) :: file_base, gen_file, grad_file, & + json_file, log_file + INTEGER :: cmdstat, exitstat, handle, iounit, & + natom, nkp, spin + LOGICAL :: do_kpoints, have_energy, have_gradient, & + have_virial, too_large, & + unsupported_kpoints + REAL(KIND=dp) :: cli_energy, cp_energy, ediff, fmax, & + fsum, vmax, vsum + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:, :) :: cli_gradient, cli_virial, cp_gradient + REAL(KIND=dp), DIMENSION(:, :), POINTER :: xkp + TYPE(atomic_kind_type), DIMENSION(:), POINTER :: atomic_kind_set + TYPE(cp_logger_type), POINTER :: logger + TYPE(dft_control_type), POINTER :: dft_control + TYPE(kpoint_type), POINTER :: kpoints + TYPE(mp_para_env_type), POINTER :: para_env + TYPE(particle_type), DIMENSION(:), POINTER :: particle_set + TYPE(qs_energy_type), POINTER :: energy + TYPE(qs_force_type), DIMENSION(:), POINTER :: force + TYPE(virial_type), POINTER :: virial + TYPE(xtb_reference_cli_type) :: ref + + CALL timeset(routineN, handle) + + NULLIFY (atomic_kind_set, dft_control, energy, force, kpoints, logger, para_env, particle_set, & + virial, xkp) + CALL get_qs_env(qs_env=qs_env, atomic_kind_set=atomic_kind_set, & + dft_control=dft_control, energy=energy, force=force, & + para_env=para_env, particle_set=particle_set, virial=virial, & + do_kpoints=do_kpoints, kpoints=kpoints) + + ref = dft_control%qs_control%xtb_control%reference_cli + IF (.NOT. ref%enabled) THEN + CALL timestop(handle) + RETURN + END IF + IF (.NOT. para_env%is_source()) THEN + CALL timestop(handle) + RETURN + END IF + + logger => cp_get_default_logger() + iounit = cp_logger_get_default_io_unit(logger) + unsupported_kpoints = .FALSE. + IF (do_kpoints .AND. ASSOCIATED(kpoints)) THEN + nkp = 0 + CALL get_kpoint_info(kpoint=kpoints, nkp=nkp, xkp=xkp) + unsupported_kpoints = nkp > 1 + IF (nkp == 1 .AND. ASSOCIATED(xkp)) unsupported_kpoints = ANY(ABS(xkp(:, 1)) > 1.0E-12_dp) + END IF + IF (unsupported_kpoints) THEN + WRITE (UNIT=iounit, FMT="(/,T2,A)") & + "tblite reference CLI check skipped: CP2K KPOINTS are active." + WRITE (UNIT=iounit, FMT="(T2,A)") & + "The native tblite CLI reference path does not reproduce CP2K multi-k-point sampling." + IF (ref%stop_on_error) CPABORT("tblite reference CLI cannot check CP2K k-point calculations") + CALL timestop(handle) + RETURN + END IF + natom = SIZE(particle_set) + method = tb_reference_method_name(dft_control%qs_control%xtb_control%tblite_method) + file_base = tb_join_path(ref%work_directory, ref%prefix) + gen_file = TRIM(file_base)//".gen" + grad_file = TRIM(file_base)//".grad" + json_file = TRIM(file_base)//".json" + log_file = TRIM(file_base)//".log" + + WRITE (charge_str, "(I0)") dft_control%charge + spin = MAX(0, dft_control%multiplicity - 1) + WRITE (spin_str, "(I0)") spin + WRITE (acc_str, "(ES16.8)") ref%accuracy + WRITE (iter_str, "(I0)") ref%iterations + + CALL tb_write_reference_gen(qs_env, TRIM(gen_file)) + + command = TRIM(tb_shell_quote(ref%program_name))//" run --method "//TRIM(method)// & + " --charge "//TRIM(ADJUSTL(charge_str))// & + " --spin "//TRIM(ADJUSTL(spin_str))// & + " --acc "//TRIM(ADJUSTL(acc_str))// & + " --iterations "//TRIM(ADJUSTL(iter_str))// & + " --no-restart --input gen --grad "//TRIM(tb_shell_quote(grad_file))// & + " --json "//TRIM(tb_shell_quote(json_file))//" "//TRIM(tb_shell_quote(gen_file))// & + " > "//TRIM(tb_shell_quote(log_file))//" 2>&1" + + cmdstat = 0 + exitstat = 0 + CALL execute_command_line(TRIM(command), exitstat=exitstat, cmdstat=cmdstat) + IF (cmdstat /= 0 .OR. exitstat /= 0) THEN + WRITE (UNIT=iounit, FMT="(/,T2,A)") "tblite reference CLI check failed to run." + WRITE (UNIT=iounit, FMT="(T2,A,A)") "Command: ", TRIM(command) + WRITE (UNIT=iounit, FMT="(T2,A,I0,T32,A,I0)") "cmdstat:", cmdstat, "exitstat:", exitstat + IF (ref%stop_on_error) CPABORT("tblite reference CLI command failed") + CALL tb_reference_cleanup(ref, gen_file, grad_file, json_file, log_file) + CALL timestop(handle) + RETURN + END IF + + ALLOCATE (cli_gradient(3, natom), cli_virial(3, 3)) + CALL tb_read_reference_grad(TRIM(grad_file), natom, cli_energy, cli_gradient, cli_virial, & + have_energy, have_gradient, have_virial) + + WRITE (UNIT=iounit, FMT="(/,T2,A)") "tblite reference CLI check" + WRITE (UNIT=iounit, FMT="(T2,A,A)") "Executable: ", TRIM(ref%program_name) + WRITE (UNIT=iounit, FMT="(T2,A,A)") "Method: ", TRIM(method) + WRITE (UNIT=iounit, FMT="(T2,A,A)") "Log file: ", TRIM(log_file) + + too_large = .FALSE. + IF (ref%check_energy) THEN + IF (have_energy) THEN + cp_energy = energy%total + ediff = ABS(cp_energy - cli_energy) + WRITE (UNIT=iounit, FMT="(T2,A,3ES22.12)") & + "Energy CP2K/CLI/absdiff:", cp_energy, cli_energy, ediff + too_large = too_large .OR. ediff > ref%error_limit + ELSE + WRITE (UNIT=iounit, FMT="(T2,A)") "Energy check skipped: no CLI energy found." + END IF + END IF + + IF (ref%check_forces) THEN + IF (have_gradient .AND. ASSOCIATED(force)) THEN + ALLOCATE (cp_gradient(3, natom)) + CALL total_qs_force(cp_gradient, force, atomic_kind_set) + fsum = SUM(ABS(cp_gradient - cli_gradient)) + fmax = MAXVAL(ABS(cp_gradient - cli_gradient)) + WRITE (UNIT=iounit, FMT="(T2,A,2ES22.12)") "Gradient diff sum/max:", fsum, fmax + too_large = too_large .OR. fmax > ref%error_limit + DEALLOCATE (cp_gradient) + ELSE + WRITE (UNIT=iounit, FMT="(T2,A)") "Gradient check skipped: no CLI gradient or CP2K force found." + END IF + END IF + + IF (ref%check_virial) THEN + IF (have_virial .AND. ASSOCIATED(virial)) THEN + ! Native tblite prints the positive cell derivative; CP2K stores the PV virial + ! with the opposite sign. + vsum = SUM(ABS(-virial%pv_virial - cli_virial)) + vmax = MAXVAL(ABS(-virial%pv_virial - cli_virial)) + WRITE (UNIT=iounit, FMT="(T2,A,2ES22.12)") "Virial diff sum/max:", vsum, vmax + too_large = too_large .OR. vmax > ref%error_limit + ELSE + WRITE (UNIT=iounit, FMT="(T2,A)") "Virial check skipped: no CLI virial or CP2K virial found." + END IF + END IF + + IF (too_large) THEN + WRITE (UNIT=iounit, FMT="(T2,A,ES12.4)") & + "tblite reference CLI deviation exceeded ERROR_LIMIT = ", ref%error_limit + IF (ref%stop_on_error) CPABORT("tblite reference CLI deviation exceeded ERROR_LIMIT") + END IF + + CALL tb_reference_cleanup(ref, gen_file, grad_file, json_file, log_file) + DEALLOCATE (cli_gradient, cli_virial) + + CALL timestop(handle) + + END SUBROUTINE tb_reference_cli_compare + +! ************************************************************************************************** +!> \brief Map CP2K tblite method id to native tblite CLI method name. +!> \param method_id ... +!> \return ... +! ************************************************************************************************** + FUNCTION tb_reference_method_name(method_id) RESULT(method) + INTEGER, INTENT(IN) :: method_id + CHARACTER(LEN=8) :: method + + SELECT CASE (method_id) + CASE (gfn1xtb) + method = "gfn1" + CASE (gfn2xtb) + method = "gfn2" + CASE (ipea1xtb) + method = "ipea1" + CASE DEFAULT + CPABORT("Unknown tblite reference CLI method") + END SELECT + + END FUNCTION tb_reference_method_name + +! ************************************************************************************************** +!> \brief Join directory and filename. +!> \param directory ... +!> \param filename ... +!> \return ... +! ************************************************************************************************** + FUNCTION tb_join_path(directory, filename) RESULT(path) + CHARACTER(LEN=*), INTENT(IN) :: directory, filename + CHARACTER(LEN=default_path_length) :: path + + IF (LEN_TRIM(directory) == 0 .OR. TRIM(directory) == ".") THEN + path = TRIM(filename) + ELSE IF (directory(LEN_TRIM(directory):LEN_TRIM(directory)) == "/") THEN + path = TRIM(directory)//TRIM(filename) + ELSE + path = TRIM(directory)//"/"//TRIM(filename) + END IF + + END FUNCTION tb_join_path + +! ************************************************************************************************** +!> \brief Shell-quote a filename or executable path. +!> \param text ... +!> \return ... +! ************************************************************************************************** + FUNCTION tb_shell_quote(text) RESULT(quoted) + CHARACTER(LEN=*), INTENT(IN) :: text + CHARACTER(LEN=4*default_path_length) :: quoted + + INTEGER :: i + + quoted = "'" + DO i = 1, LEN_TRIM(text) + IF (text(i:i) == "'") THEN + quoted = TRIM(quoted)//"'\\''" + ELSE + quoted = TRIM(quoted)//text(i:i) + END IF + END DO + quoted = TRIM(quoted)//"'" + + END FUNCTION tb_shell_quote + +! ************************************************************************************************** +!> \brief Write current CP2K geometry as DFTB+ gen format for native tblite. +!> \param qs_env ... +!> \param filename ... +! ************************************************************************************************** + SUBROUTINE tb_write_reference_gen(qs_env, filename) + + TYPE(qs_environment_type), POINTER :: qs_env + CHARACTER(LEN=*), INTENT(IN) :: filename + + CHARACTER(LEN=2), ALLOCATABLE, DIMENSION(:) :: symbols, unique_symbols + INTEGER :: iatom, ikind, ios, natom, nuniq, unit_nr + INTEGER, ALLOCATABLE, DIMENSION(:) :: species + INTEGER, DIMENSION(3) :: periodic + LOGICAL :: found + REAL(KIND=dp) :: to_angstrom + TYPE(cell_type), POINTER :: cell + TYPE(particle_type), DIMENSION(:), POINTER :: particle_set + + NULLIFY (cell, particle_set) + CALL get_qs_env(qs_env=qs_env, cell=cell, particle_set=particle_set) + + natom = SIZE(particle_set) + to_angstrom = cp_unit_from_cp2k(1.0_dp, "angstrom") + ALLOCATE (symbols(natom), unique_symbols(natom), species(natom)) + nuniq = 0 + DO iatom = 1, natom + CALL get_atomic_kind(particle_set(iatom)%atomic_kind, element_symbol=symbols(iatom)) + found = .FALSE. + DO ikind = 1, nuniq + IF (TRIM(unique_symbols(ikind)) == TRIM(symbols(iatom))) THEN + found = .TRUE. + EXIT + END IF + END DO + IF (.NOT. found) THEN + nuniq = nuniq + 1 + unique_symbols(nuniq) = symbols(iatom) + ikind = nuniq + END IF + species(iatom) = ikind + END DO + + OPEN (NEWUNIT=unit_nr, FILE=TRIM(filename), STATUS="REPLACE", ACTION="WRITE", & + FORM="FORMATTED", IOSTAT=ios) + IF (ios /= 0) CPABORT("Could not open tblite reference CLI geometry file") + + CALL get_cell(cell=cell, periodic=periodic) + IF (ANY(periodic == 1)) THEN + WRITE (UNIT=unit_nr, FMT="(I0,1X,A)") natom, "S" + ELSE + WRITE (UNIT=unit_nr, FMT="(I0,1X,A)") natom, "C" + END IF + WRITE (UNIT=unit_nr, FMT="(*(A,1X))") (TRIM(unique_symbols(ikind)), ikind=1, nuniq) + DO iatom = 1, natom + WRITE (UNIT=unit_nr, FMT="(I0,1X,I0,3(1X,ES24.16))") & + iatom, species(iatom), particle_set(iatom)%r(:)*to_angstrom + END DO + IF (ANY(periodic == 1)) THEN + WRITE (UNIT=unit_nr, FMT="(3(1X,ES24.16))") 0.0_dp, 0.0_dp, 0.0_dp + DO ikind = 1, 3 + WRITE (UNIT=unit_nr, FMT="(3(1X,ES24.16))") cell%hmat(:, ikind)*to_angstrom + END DO + END IF + CLOSE (unit_nr) + + DEALLOCATE (symbols, unique_symbols, species) + + END SUBROUTINE tb_write_reference_gen + +! ************************************************************************************************** +!> \brief Read native tblite gradient file. +!> \param filename ... +!> \param natom ... +!> \param energy ... +!> \param gradient ... +!> \param virial ... +!> \param have_energy ... +!> \param have_gradient ... +!> \param have_virial ... +! ************************************************************************************************** + SUBROUTINE tb_read_reference_grad(filename, natom, energy, gradient, virial, & + have_energy, have_gradient, have_virial) + + CHARACTER(LEN=*), INTENT(IN) :: filename + INTEGER, INTENT(IN) :: natom + REAL(KIND=dp), INTENT(OUT) :: energy + REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: gradient, virial + LOGICAL, INTENT(OUT) :: have_energy, have_gradient, have_virial + + CHARACTER(LEN=1024) :: line + INTEGER :: ios, nread, unit_nr + LOGICAL :: exists + REAL(KIND=dp), ALLOCATABLE, DIMENSION(:) :: values + + have_energy = .FALSE. + have_gradient = .FALSE. + have_virial = .FALSE. + energy = 0.0_dp + gradient = 0.0_dp + virial = 0.0_dp + + INQUIRE (FILE=TRIM(filename), EXIST=exists) + IF (.NOT. exists) RETURN + + OPEN (NEWUNIT=unit_nr, FILE=TRIM(filename), STATUS="OLD", ACTION="READ", & + FORM="FORMATTED", IOSTAT=ios) + IF (ios /= 0) RETURN + + DO + READ (UNIT=unit_nr, FMT="(A)", IOSTAT=ios) line + IF (ios /= 0) EXIT + IF (INDEX(line, "energy :real:0:") > 0) THEN + READ (UNIT=unit_nr, FMT="(A)", IOSTAT=ios) line + IF (ios == 0) THEN + READ (line, *, IOSTAT=ios) energy + have_energy = ios == 0 + END IF + ELSE IF (INDEX(line, "gradient :real:2:3,") > 0) THEN + ALLOCATE (values(3*natom)) + CALL tb_read_real_values(unit_nr, values, nread) + IF (nread == 3*natom) THEN + CALL tb_values_to_matrix(values, gradient) + have_gradient = .TRUE. + END IF + DEALLOCATE (values) + ELSE IF (INDEX(line, "virial :real:2:3,3") > 0) THEN + ALLOCATE (values(9)) + CALL tb_read_real_values(unit_nr, values, nread) + IF (nread == 9) THEN + CALL tb_values_to_matrix_rowmajor(values, virial) + have_virial = .TRUE. + END IF + DEALLOCATE (values) + END IF + END DO + CLOSE (unit_nr) + + END SUBROUTINE tb_read_reference_grad + +! ************************************************************************************************** +!> \brief Read a fixed number of real values from following lines. +!> \param unit_nr ... +!> \param values ... +!> \param nread ... +! ************************************************************************************************** + SUBROUTINE tb_read_real_values(unit_nr, values, nread) + + INTEGER, INTENT(IN) :: unit_nr + REAL(KIND=dp), DIMENSION(:), INTENT(OUT) :: values + INTEGER, INTENT(OUT) :: nread + + CHARACTER(LEN=1024) :: line + INTEGER :: ios + + nread = 0 + DO WHILE (nread < SIZE(values)) + READ (UNIT=unit_nr, FMT="(A)", IOSTAT=ios) line + IF (ios /= 0) EXIT + CALL tb_parse_real_line(line, values, nread) + END DO + + END SUBROUTINE tb_read_real_values + +! ************************************************************************************************** +!> \brief Parse real values from one text line. +!> \param line ... +!> \param values ... +!> \param nread ... +! ************************************************************************************************** + SUBROUTINE tb_parse_real_line(line, values, nread) + + CHARACTER(LEN=*), INTENT(IN) :: line + REAL(KIND=dp), DIMENSION(:), INTENT(INOUT) :: values + INTEGER, INTENT(INOUT) :: nread + + CHARACTER(LEN=128) :: token + INTEGER :: first, ios, last, pos + + pos = 1 + DO WHILE (pos <= LEN_TRIM(line) .AND. nread < SIZE(values)) + DO WHILE (pos <= LEN_TRIM(line) .AND. INDEX(" ,[]", line(pos:pos)) > 0) + pos = pos + 1 + END DO + IF (pos > LEN_TRIM(line)) EXIT + first = pos + DO WHILE (pos <= LEN_TRIM(line) .AND. INDEX(" ,[]", line(pos:pos)) == 0) + pos = pos + 1 + END DO + last = pos - 1 + token = line(first:last) + READ (token, *, IOSTAT=ios) values(nread + 1) + IF (ios == 0) nread = nread + 1 + END DO + + END SUBROUTINE tb_parse_real_line + +! ************************************************************************************************** +!> \brief Convert flat native tblite values to CP2K atom-major matrix layout. +!> \param values ... +!> \param matrix ... +! ************************************************************************************************** + SUBROUTINE tb_values_to_matrix(values, matrix) + + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: values + REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: matrix + + INTEGER :: i, j, n + + n = 0 + DO j = 1, SIZE(matrix, 2) + DO i = 1, SIZE(matrix, 1) + n = n + 1 + matrix(i, j) = values(n) + END DO + END DO + + END SUBROUTINE tb_values_to_matrix + +! ************************************************************************************************** +!> \brief Convert flat native tblite row-major values to a 2D matrix. +!> \param values ... +!> \param matrix ... +! ************************************************************************************************** + SUBROUTINE tb_values_to_matrix_rowmajor(values, matrix) + + REAL(KIND=dp), DIMENSION(:), INTENT(IN) :: values + REAL(KIND=dp), DIMENSION(:, :), INTENT(OUT) :: matrix + + INTEGER :: i, j, n + + n = 0 + DO i = 1, SIZE(matrix, 1) + DO j = 1, SIZE(matrix, 2) + n = n + 1 + matrix(i, j) = values(n) + END DO + END DO + + END SUBROUTINE tb_values_to_matrix_rowmajor + +! ************************************************************************************************** +!> \brief Delete temporary files unless requested otherwise. +!> \param ref ... +!> \param gen_file ... +!> \param grad_file ... +!> \param json_file ... +!> \param log_file ... +! ************************************************************************************************** + SUBROUTINE tb_reference_cleanup(ref, gen_file, grad_file, json_file, log_file) + + TYPE(xtb_reference_cli_type), INTENT(IN) :: ref + CHARACTER(LEN=*), INTENT(IN) :: gen_file, grad_file, json_file, log_file + + IF (ref%keep_files) RETURN + CALL tb_delete_file(gen_file) + CALL tb_delete_file(grad_file) + CALL tb_delete_file(json_file) + CALL tb_delete_file(log_file) + + END SUBROUTINE tb_reference_cleanup + +! ************************************************************************************************** +!> \brief Delete a file if it exists. +!> \param filename ... +! ************************************************************************************************** + SUBROUTINE tb_delete_file(filename) + + CHARACTER(LEN=*), INTENT(IN) :: filename + + INTEGER :: ios, unit_nr + LOGICAL :: exists + + INQUIRE (FILE=TRIM(filename), EXIST=exists) + IF (.NOT. exists) RETURN + OPEN (NEWUNIT=unit_nr, FILE=TRIM(filename), STATUS="OLD", IOSTAT=ios) + IF (ios == 0) CLOSE (unit_nr, STATUS="DELETE") + + END SUBROUTINE tb_delete_file + +! ************************************************************************************************** +!> \brief Dump cumulative tblite virial pieces for local debugging. +!> \param label ... +!> \param sigma ... +!> \param para_env ... +! ************************************************************************************************** + SUBROUTINE tb_dump_sigma_component(label, sigma, para_env) + + CHARACTER(LEN=*), INTENT(IN) :: label + REAL(KIND=dp), DIMENSION(:, :), INTENT(IN) :: sigma + TYPE(mp_para_env_type), INTENT(IN) :: para_env + + CHARACTER(LEN=default_path_length) :: dump_file + INTEGER :: dump_status, dump_unit, i + + dump_status = 1 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_SIGMA_COMPONENT_DUMP", dump_file, STATUS=dump_status) +#endif + IF (dump_status /= 0) RETURN + + OPEN (NEWUNIT=dump_unit, FILE=TRIM(dump_file), STATUS="UNKNOWN", & + POSITION="APPEND", ACTION="WRITE") + WRITE (dump_unit, "(A)") TRIM(label) + DO i = 1, 3 + WRITE (dump_unit, "(3(1X,ES24.16))") sigma(i, :)/para_env%num_pe + END DO + CLOSE (dump_unit) + + END SUBROUTINE tb_dump_sigma_component + ! ************************************************************************************************** !> \brief save stress tensor !> \param qs_env ... @@ -2362,11 +4201,36 @@ CONTAINS TYPE(tblite_type) :: tb TYPE(mp_para_env_type) :: para_env + CHARACTER(LEN=default_path_length) :: dump_file + INTEGER :: dump_status, dump_unit, i + INTEGER, DIMENSION(3) :: periodic TYPE(cell_type), POINTER :: cell TYPE(virial_type), POINTER :: virial NULLIFY (virial, cell) CALL get_qs_env(qs_env=qs_env, virial=virial, cell=cell) + CALL get_cell(cell=cell, periodic=periodic) + + IF (ALL(periodic == 0)) THEN + CALL cp_warn(__LOCATION__, & + "tblite stress tensor requested for an isolated system. "// & + "The reported virial is useful for finite-difference checks, "// & + "but it is not a physically meaningful bulk stress for an isolated molecule.") + END IF + + dump_status = 1 +#if defined(__TBLITE_DEBUG_DIAGNOSTICS) + CALL GET_ENVIRONMENT_VARIABLE("CP2K_TBLITE_VIRIAL_DUMP", dump_file, STATUS=dump_status) +#endif + IF (dump_status == 0) THEN + OPEN (NEWUNIT=dump_unit, FILE=TRIM(dump_file), STATUS="UNKNOWN", & + POSITION="APPEND", ACTION="WRITE") + WRITE (dump_unit, "(A)") "sigma" + DO i = 1, 3 + WRITE (dump_unit, "(3(1X,ES24.16))") tb%sigma(i, :)/para_env%num_pe + END DO + CLOSE (dump_unit) + END IF virial%pv_virial = virial%pv_virial - tb%sigma/para_env%num_pe @@ -2421,4 +4285,3 @@ CONTAINS END SUBROUTINE tb_add_sig END MODULE tblite_interface - diff --git a/src/tblite_types.F b/src/tblite_types.F index 3faad6d76a..39b4ecd40b 100644 --- a/src/tblite_types.F +++ b/src/tblite_types.F @@ -17,6 +17,7 @@ MODULE tblite_types USE mctc_io, ONLY: structure_type, new USE tblite_xtb_calculator, ONLY: xtb_calculator USE tblite_container, ONLY: container_cache + USE tblite_scf_mixer, ONLY: mixer_type USE tblite_wavefunction_type, ONLY: wavefunction_type USE tblite_scf_potential, ONLY: potential_type #endif @@ -66,6 +67,7 @@ MODULE tblite_types TYPE(container_cache) :: dcache = container_cache() TYPE(wavefunction_type) :: wfn = wavefunction_type() TYPE(potential_type) :: pot = potential_type() + CLASS(mixer_type), ALLOCATABLE :: mixer #endif END TYPE tblite_type @@ -118,6 +120,9 @@ CONTAINS CALL dbcsr_deallocate_matrix_set(tb_tblite%quadbra) IF (ASSOCIATED(tb_tblite%quadket)) & CALL dbcsr_deallocate_matrix_set(tb_tblite%quadket) +#if defined(__TBLITE) + IF (ALLOCATED(tb_tblite%mixer)) DEALLOCATE (tb_tblite%mixer) +#endif DEALLOCATE (tb_tblite) END IF diff --git a/src/xtb_ks_matrix.F b/src/xtb_ks_matrix.F index f905157aab..beb30d6f30 100644 --- a/src/xtb_ks_matrix.F +++ b/src/xtb_ks_matrix.F @@ -355,7 +355,10 @@ CONTAINS ELSE CALL get_qs_env(qs_env=qs_env, scf_env=scf_env) CALL charge_mixing(scf_env%mixing_method, scf_env%mixing_store, & - charges, para_env, scf_env%iter_count) + charges, para_env, scf_env%iter_count, & + scc_mixer=dft_control%qs_control%xtb_control%tblite_scc_mixer, & + tblite_mixer_damping=dft_control%qs_control%xtb_control%tblite_mixer_damping, & + tblite_mixer_memory=qs_env%scf_control%max_scf) END IF DO iatom = 1, natom @@ -472,4 +475,3 @@ CONTAINS END SUBROUTINE build_gfn1_xtb_ks_matrix END MODULE xtb_ks_matrix - diff --git a/tests/DFTB/regtest-nonscc/TEST_FILES.toml b/tests/DFTB/regtest-nonscc/TEST_FILES.toml index 4f08344111..8b48eb185d 100644 --- a/tests/DFTB/regtest-nonscc/TEST_FILES.toml +++ b/tests/DFTB/regtest-nonscc/TEST_FILES.toml @@ -2,24 +2,25 @@ # the second field tells which test should be run in order to compare with the last available output # see regtest/TEST_FILES "ch2o-1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.82072731467941}] -"ch2o-2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.82159061359821}] -"ch2o-3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.81373413468792}] -"ch2o-r.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.81373413468792}] +"ch2o-2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.8215906135489996}] +"ch2o-3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.8137341344748501}] +"ch2o-r.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.8137341344748501}] +"ch2o_force.inp" = [{matcher="M042", tol=1.0E-06, ref=0.0}] "h2-1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-0.70875565358819}] "h2-2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-0.70875565358819}] "h2-3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-0.70875565358819}] -"h2-4.inp" = [{matcher="E_total", tol=3e-14, ref=-0.71042952969308004}] -"h2o-32_1.inp" = [{matcher="E_total", tol=6e-13, ref=-131.08636939008761}] -"h2o-32_2.inp" = [{matcher="E_total", tol=4e-13, ref=-131.07999691054360}] -"h2o-32_3.inp" = [{matcher="E_total", tol=9e-14, ref=-131.07520911566399}] -"h2o-32_4.inp" = [{matcher="E_total", tol=2e-13, ref=-131.07520911521166}] +"h2-4.inp" = [{matcher="E_total", tol=3e-14, ref=-0.71042953396467}] +"h2o-32_1.inp" = [{matcher="E_total", tol=6e-13, ref=-131.08636943050718}] +"h2o-32_2.inp" = [{matcher="E_total", tol=4e-13, ref=-131.07999694042778}] +"h2o-32_3.inp" = [{matcher="E_total", tol=9e-14, ref=-131.07520912214508}] +"h2o-32_4.inp" = [{matcher="E_total", tol=2e-13, ref=-131.07520912214875}] "MoS.inp" = [{matcher="E_total", tol=1.0E-14, ref=-2.99616182900092}] -"n2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-4.86560729574766}] -"s2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-4.83731808711857}] +"n2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-4.8656072957458099}] +"s2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-4.8373181011770399}] # atomic properties "ch2o_atprop.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.81281420275335}] "MoS_atprop.inp" = [{matcher="E_total", tol=1.0E-14, ref=-2.99616182900092}] -"h2o-32_atprop.inp" = [{matcher="E_total", tol=6e-13, ref=-131.08636939008761}] +"h2o-32_atprop.inp" = [{matcher="E_total", tol=6e-13, ref=-131.08636943050718}] # "co2_1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-8.55586246566686}] "co2_2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-8.55586246566686}] @@ -27,8 +28,13 @@ # "si_kp1.inp" = [{matcher="E_total", tol=1.0E-13, ref=-10.06358203475393}] "si_kp1_kpsym.inp" = [{matcher="E_total", tol=1.0E-13, ref=-10.06358203475393}, - {matcher="N_special_kpoints", tol=0.0, ref=32}] + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"si_kp1_kpsym_atomdisp.inp" = [{matcher="E_total", tol=1.0E-13, ref=-10.06358201165233}, + {matcher="N_special_kpoints", tol=0.0, ref=12}] "si_kp1_spglib_backend.inp" = [{matcher="E_total", tol=1.0E-13, ref=-10.06358203475393}, - {matcher="N_special_kpoints", tol=0.0, ref=32}] + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"si_kp_stress.inp" = [{matcher="E_total", tol=1.0E-12, ref=-10.05636443824252}, + {matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M042", tol=1.0E-06, ref=0.0}] "si_kp2.inp" = [] #EOF diff --git a/tests/DFTB/regtest-nonscc/ch2o_force.inp b/tests/DFTB/regtest-nonscc/ch2o_force.inp new file mode 100644 index 0000000000..35370e1e1d --- /dev/null +++ b/tests/DFTB/regtest-nonscc/ch2o_force.inp @@ -0,0 +1,55 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT ch2o_nonscc_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 0.0001 + EPS_NO_ERROR_CHECK 1.0e-6 + STOP_ON_MISMATCH F +&END DEBUG + +#CPQA INCLUDE DFTB/nonscc/ch.spl +#CPQA INCLUDE DFTB/nonscc/hc.spl +#CPQA INCLUDE DFTB/nonscc/co.spl +#CPQA INCLUDE DFTB/nonscc/oc.spl +#CPQA INCLUDE DFTB/nonscc/oh.spl +#CPQA INCLUDE DFTB/nonscc/ho.spl +#CPQA INCLUDE DFTB/nonscc/hh.spl +#CPQA INCLUDE DFTB/nonscc/oo.spl +#CPQA INCLUDE DFTB/nonscc/nonscc_parameter +&FORCE_EVAL + &DFT + &QS + METHOD DFTB + &DFTB + DISPERSION F + ORTHOGONAL_BASIS F + SELF_CONSISTENT F + &PARAMETER + PARAM_FILE_NAME nonscc_parameter + PARAM_FILE_PATH DFTB/nonscc + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + SCF_GUESS NONE + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-nonscc/si_kp1_kpsym_atomdisp.inp b/tests/DFTB/regtest-nonscc/si_kp1_kpsym_atomdisp.inp new file mode 100644 index 0000000000..0bf137966c --- /dev/null +++ b/tests/DFTB/regtest-nonscc/si_kp1_kpsym_atomdisp.inp @@ -0,0 +1,62 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DISPERSION T + ORTHOGONAL_BASIS F + SELF_CONSISTENT F + &PARAMETER + PARAM_FILE_NAME nonscc_parameter + PARAM_FILE_PATH DFTB/nonscc + SK_FILE Si Si sisi-d + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + SCF_GUESS NONE + &MIXING + ALPHA 1. + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000050 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL HIGH + PROJECT Si_kpsym_atomdisp + RUN_TYPE ENERGY +&END GLOBAL diff --git a/tests/DFTB/regtest-nonscc/si_kp_stress.inp b/tests/DFTB/regtest-nonscc/si_kp_stress.inp new file mode 100644 index 0000000000..9f7b4f18d8 --- /dev/null +++ b/tests/DFTB/regtest-nonscc/si_kp_stress.inp @@ -0,0 +1,71 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DISPERSION T + ORTHOGONAL_BASIS F + SELF_CONSISTENT F + &PARAMETER + PARAM_FILE_NAME nonscc_parameter + PARAM_FILE_PATH DFTB/nonscc + SK_FILE Si Si sisi-d + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + SCF_GUESS NONE + &MIXING + ALPHA 1.0 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_nonscc_kp_stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0001 + EPS_NO_ERROR_CHECK 1.0e-6 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG diff --git a/tests/DFTB/regtest-scc-2/TEST_FILES.toml b/tests/DFTB/regtest-scc-2/TEST_FILES.toml index 61e02cf512..9e7c809dd2 100644 --- a/tests/DFTB/regtest-scc-2/TEST_FILES.toml +++ b/tests/DFTB/regtest-scc-2/TEST_FILES.toml @@ -4,6 +4,12 @@ "base1.inp" = [{matcher="E_total", tol=5e-12, ref=-4.08612338013299}] "base2.inp" = [{matcher="E_total", tol=5e-12, ref=-4.08612338013299}] "base3.inp" = [{matcher="E_total", tol=5e-12, ref=-4.08520460432732}] +"dftb3_h2o_force.inp" = [{matcher="M042", tol=1.0E-6, ref=0.0}] +"dftb3_h2o_gamma_stress.inp" = [{matcher="M042", tol=1.0E-6, ref=0.0}] +"dftb3_h2o_kp_force.inp" = [{matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M042", tol=1.0E-6, ref=0.0}] +"dftb3_h2o_kp_stress.inp" = [{matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M042", tol=1.0E-6, ref=0.0}] "str1.inp" = [{matcher="E_total", tol=5e-12, ref=-4.08612900850098}] "str2.inp" = [{matcher="E_total", tol=5e-12, ref=-32.67545045484238}] "str3.inp" = [{matcher="E_total", tol=5e-12, ref=-4.08521609759106}] diff --git a/tests/DFTB/regtest-scc-2/dftb3_h2o_force.inp b/tests/DFTB/regtest-scc-2/dftb3_h2o_force.inp new file mode 100644 index 0000000000..ca2967ef79 --- /dev/null +++ b/tests/DFTB/regtest-scc-2/dftb3_h2o_force.inp @@ -0,0 +1,68 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT dftb3_h2o_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 1.0e-4 + EPS_NO_ERROR_CHECK 1.0e-6 + STOP_ON_MISMATCH F +&END DEBUG + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + &DFT + &QS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 T + DISPERSION F + DO_EWALD F + HB_SR_GAMMA T + SELF_CONSISTENT T + &PARAMETER + HB_SR_PARAM 4.0 + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.000000 0.000000 0.000000 + H 0.758602 0.000000 0.504284 + H -0.758602 0.000000 0.504284 + &END COORD + &KIND O + DFTB3_PARAM -0.14 + &END KIND + &KIND H + DFTB3_PARAM -0.05 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc-2/dftb3_h2o_gamma_stress.inp b/tests/DFTB/regtest-scc-2/dftb3_h2o_gamma_stress.inp new file mode 100644 index 0000000000..5e94c89d2f --- /dev/null +++ b/tests/DFTB/regtest-scc-2/dftb3_h2o_gamma_stress.inp @@ -0,0 +1,79 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT dftb3_h2o_gamma_stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 1.0e-4 + EPS_NO_ERROR_CHECK 1.0e-6 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 T + DISPERSION F + DO_EWALD T + HB_SR_GAMMA T + SELF_CONSISTENT T + &PARAMETER + HB_SR_PARAM 4.0 + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 4.0 4.0 4.0 + PERIODIC XYZ + &END CELL + &COORD + O 0.000000 0.000000 0.000000 + H 0.758602 0.000000 0.504284 + H -0.758602 0.000000 0.504284 + &END COORD + &KIND O + DFTB3_PARAM -0.14 + &END KIND + &KIND H + DFTB3_PARAM -0.05 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_force.inp b/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_force.inp new file mode 100644 index 0000000000..e3ee63b6dd --- /dev/null +++ b/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_force.inp @@ -0,0 +1,83 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT dftb3_h2o_kp_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 1.0e-4 + EPS_NO_ERROR_CHECK 1.0e-6 + STOP_ON_MISMATCH F +&END DEBUG + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 T + DISPERSION F + DO_EWALD T + HB_SR_GAMMA T + SELF_CONSISTENT T + &PARAMETER + HB_SR_PARAM 4.0 + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 4.0 4.0 4.0 + PERIODIC XYZ + &END CELL + &COORD + O 0.000000 0.000000 0.000000 + H 0.758602 0.000000 0.504284 + H -0.758602 0.000000 0.504284 + &END COORD + &KIND O + DFTB3_PARAM -0.14 + &END KIND + &KIND H + DFTB3_PARAM -0.05 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_stress.inp b/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_stress.inp new file mode 100644 index 0000000000..ac262fca3b --- /dev/null +++ b/tests/DFTB/regtest-scc-2/dftb3_h2o_kp_stress.inp @@ -0,0 +1,85 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT dftb3_h2o_kp_stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 1.0e-4 + EPS_NO_ERROR_CHECK 1.0e-6 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 T + DISPERSION F + DO_EWALD T + HB_SR_GAMMA T + SELF_CONSISTENT T + &PARAMETER + HB_SR_PARAM 4.0 + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 4.0 4.0 4.0 + PERIODIC XYZ + &END CELL + &COORD + O 0.000000 0.000000 0.000000 + H 0.758602 0.000000 0.504284 + H -0.758602 0.000000 0.504284 + &END COORD + &KIND O + DFTB3_PARAM -0.14 + &END KIND + &KIND H + DFTB3_PARAM -0.05 + &END KIND + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc/TEST_FILES.toml b/tests/DFTB/regtest-scc/TEST_FILES.toml index d5bcfa1c4a..6ef34eacac 100644 --- a/tests/DFTB/regtest-scc/TEST_FILES.toml +++ b/tests/DFTB/regtest-scc/TEST_FILES.toml @@ -1,41 +1,43 @@ # runs are executed in the same order as in this file # the second field tells which test should be run in order to compare with the last available output # see regtest/TEST_FILES -"ch2o-1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.76250962732554}] +"ch2o-1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.7625096274801404}] +"ch2o_tblite_mixer.inp" = [{matcher="E_total", tol=1.0E-09, ref=-5.75878702944325}] # not yet implemented # isolated system.. "ch2o-2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75087368892706}] -"ch2o-3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75463060809440}] +"ch2o-3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.7546306080948604}] "H+.inp" = [{matcher="E_total", tol=1.0E-14, ref=0.23499952945092}] "ch2o-4.inp" = [{matcher="E_total", tol=3e-14, ref=-5.75087391612954}] -"ch2o-5.inp" = [{matcher="E_total", tol=6e-14, ref=-5.75463073168421}] +"ch2o-5.inp" = [{matcher="E_total", tol=6e-14, ref=-5.7546307316870697}] "ch2o.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75087391754637}] "ch2o-r.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75087391754637}] "ch2o-p.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75087391754637}] +"ch2o_force.inp" = [{matcher="M042", tol=1.0E-06, ref=0.0}] "co.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.04980895105760}] "h2o-1.inp" = [{matcher="E_total", tol=4e-09, ref=-130.55701170331295}] -"h2o-2.inp" = [{matcher="E_total", tol=3e-09, ref=-130.54671457542995}] -"h2o-3.inp" = [{matcher="E_total", tol=1e-08, ref=-130.54250004205457}] -"h2o-4.inp" = [{matcher="E_total", tol=3e-09, ref=-130.55701202522684}] +"h2o-2.inp" = [{matcher="E_total", tol=3e-09, ref=-130.54671568595433}] +"h2o-3.inp" = [{matcher="E_total", tol=1e-08, ref=-130.54245923459086}] +"h2o-4.inp" = [{matcher="E_total", tol=3e-09, ref=-130.55701254220213}] "h2o.inp" = [{matcher="E_total", tol=4e-09, ref=-130.41378146312945}] "h2o_hb_corr.inp" = [{matcher="E_total", tol=1.0E-14, ref=-12.22019537999129}] "ch2o-ot1.inp" = [{matcher="E_total", tol=2e-14, ref=-5.7581776065727297}] "ch2o-ot2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75313936188209}] "ch2o-ot3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.74238713882779}] "ch2o-ot4.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.71482283252281}] -"ch2o-ot6.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75734496336594}] +"ch2o-ot6.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.7573449633658802}] # bug fix for neighborlists "h2o-5.inp" = [{matcher="E_total", tol=4e-09, ref=-130.55701170331295}] # first check for LSD "test-lsd.inp" = [{matcher="E_total", tol=4e-14, ref=-5.75878702495205}] # atomic properties -"fa_atprop.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75463073188988}] +"fa_atprop.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.7546307318903498}] "fa2_atprop.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75087391754637}] -"h2o_atprop.inp" = [{matcher="E_total", tol=5e-09, ref=-130.55609410509899}] +"h2o_atprop.inp" = [{matcher="E_total", tol=5e-09, ref=-130.55609077057122}] # MD properties -"h2o_md.inp" = [{matcher="E_total", tol=5e-09, ref=-130.43511524831297}] +"h2o_md.inp" = [{matcher="E_total", tol=5e-09, ref=-130.43512095384048}] # Ehrenfest and RTP -"h2o_emd.inp" = [{matcher="E_total", tol=1.0E-11, ref=-4.06522754240490}] +"h2o_emd.inp" = [{matcher="E_total", tol=1.0E-11, ref=-4.0652275476139899}] "h2o_rtp.inp" = [{matcher="E_total", tol=1.0E-14, ref=-4.06552855730937}] "c2h2_emd_mix.inp" = [{matcher="E_total", tol=5e-11, ref=-3.91584441819893}] # HB correction parameter @@ -44,17 +46,27 @@ # Dispersion "h2o_disp1.inp" = [{matcher="E_total", tol=4e-09, ref=-130.41378146312945}] "h2o_disp2.inp" = [{matcher="E_total", tol=4e-09, ref=-130.75835628011220}] -"h2o_disp3.inp" = [{matcher="E_total", tol=3e-09, ref=-130.76542980403056}] +"h2o_disp3.inp" = [{matcher="E_total", tol=3e-09, ref=-130.76542890762238}] # DFTB3 "h2o-6.inp" = [{matcher="E_total", tol=4e-09, ref=-131.25337238175840}] "h2o-7.inp" = [{matcher="E_total", tol=2e-08, ref=-131.26536755467674}] # Properties stress -"h2o-atprop1.inp" = [{matcher="E_total", tol=4e-09, ref=-130.77763673429416}] +"h2o-atprop1.inp" = [{matcher="E_total", tol=4e-09, ref=-130.77766397611819}] "h2o-atprop2.inp" = [{matcher="E_total", tol=2e-08, ref=-131.68099550861825}] "h2o-atprop3.inp" = [{matcher="E_total", tol=2e-08, ref=-131.33465894123017}] # "c_kp1.inp" = [{matcher="E_total", tol=1.0E-14, ref=-13.76936385283589}] "c_kp1_kpsym.inp" = [{matcher="E_total", tol=1.0E-14, ref=-13.76936385283589}, - {matcher="N_special_kpoints", tol=0.0, ref=32}] + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"c_kp1_spglib_backend.inp" = [{matcher="E_total", tol=1.0E-14, ref=-13.76936385283589}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"c_kp1_kpsym_debug_stress.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.76936385283589}, + {matcher="N_special_kpoints", tol=0.0, ref=32}, + {matcher="M042", tol=1.0E-5, ref=0.0}] "c_kp2.inp" = [{matcher="E_total", tol=7e-14, ref=-13.76786045921772}] +"c_kp2_stress.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.76771748328116}, + {matcher="M042", tol=2.0E-06, ref=0.0000000}] +"zns_kp2_stress.inp" = [{matcher="E_total", tol=1.0E-12, ref=-27.54559977921195}, + {matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M042", tol=2.0E-06, ref=0.0000000}] #EOF diff --git a/tests/DFTB/regtest-scc/c_kp1_kpsym.inp b/tests/DFTB/regtest-scc/c_kp1_kpsym.inp index 1ba78bd63e..02b9910de4 100644 --- a/tests/DFTB/regtest-scc/c_kp1_kpsym.inp +++ b/tests/DFTB/regtest-scc/c_kp1_kpsym.inp @@ -10,6 +10,8 @@ VERBOSE T &END KPOINTS &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC &EWALD ALPHA 0.35 EWALD_TYPE SPME @@ -22,7 +24,6 @@ &DFTB DIAGONAL_DFTB3 F DISPERSION T - DO_EWALD T HB_SR_GAMMA F SELF_CONSISTENT T &PARAMETER diff --git a/tests/DFTB/regtest-scc/c_kp1_kpsym_debug_stress.inp b/tests/DFTB/regtest-scc/c_kp1_kpsym_debug_stress.inp new file mode 100644 index 0000000000..86b5f72779 --- /dev/null +++ b/tests/DFTB/regtest-scc/c_kp1_kpsym_debug_stress.inp @@ -0,0 +1,76 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR DIAGONAL_ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 F + DISPERSION T + HB_SR_GAMMA F + SELF_CONSISTENT T + &PARAMETER + PARAM_FILE_PATH ./DFTB/scc + SK_FILE C C cc.spl + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-8 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.35 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + C 0.000000 0.000000 0.000000 + C 0.500000 0.500000 0.000000 + C 0.500000 0.000000 0.500000 + C 0.000000 0.500000 0.500000 + C 0.250000 0.250000 0.250000 + C 0.250000 0.750000 0.750000 + C 0.750000 0.250000 0.750000 + C 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT C_kpsym_debug + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T +&END DEBUG diff --git a/tests/DFTB/regtest-scc/c_kp1_spglib_backend.inp b/tests/DFTB/regtest-scc/c_kp1_spglib_backend.inp new file mode 100644 index 0000000000..25bfe0ae7b --- /dev/null +++ b/tests/DFTB/regtest-scc/c_kp1_spglib_backend.inp @@ -0,0 +1,72 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 F + DISPERSION T + HB_SR_GAMMA F + SELF_CONSISTENT T + &PARAMETER + PARAM_FILE_PATH ./DFTB/scc + SK_FILE C C cc.spl + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-8 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.35 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + C 0.000000 0.000000 0.000000 + C 0.500000 0.500000 0.000000 + C 0.500000 0.000000 0.500000 + C 0.000000 0.500000 0.500000 + C 0.250000 0.250000 0.250000 + C 0.250000 0.750000 0.750000 + C 0.750000 0.250000 0.750000 + C 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT C_spglib_backend + RUN_TYPE ENERGY +&END GLOBAL diff --git a/tests/DFTB/regtest-scc/c_kp2_stress.inp b/tests/DFTB/regtest-scc/c_kp2_stress.inp new file mode 100644 index 0000000000..ba6c95da13 --- /dev/null +++ b/tests/DFTB/regtest-scc/c_kp2_stress.inp @@ -0,0 +1,85 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_GEO 1.e-8 + FULL_GRID ON + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE F + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DIAGONAL_DFTB3 F + DISPERSION T + HB_SR_GAMMA F + SCC_MIXER CP2K + SELF_CONSISTENT T + &PARAMETER + PARAM_FILE_PATH ./DFTB/scc + SK_FILE C C cc.spl + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.50 + METHOD BROYDEN_MIXING + NBUFFER 8 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 3.56683 3.56683 3.56683 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + C 0.000000 0.000000 0.000000 + C 0.502000 0.502000 0.002000 + C 0.500000 0.000000 0.500000 + C 0.000000 0.500000 0.500000 + C 0.250000 0.250000 0.250000 + C 0.250000 0.750000 0.750000 + C 0.750000 0.250000 0.750000 + C 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT C + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 1.0e-4 + STOP_ON_MISMATCH F +&END DEBUG diff --git a/tests/DFTB/regtest-scc/ch2o_force.inp b/tests/DFTB/regtest-scc/ch2o_force.inp new file mode 100644 index 0000000000..167f8b17f5 --- /dev/null +++ b/tests/DFTB/regtest-scc/ch2o_force.inp @@ -0,0 +1,67 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT CH2O_dftb_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 1.0e-4 + EPS_NO_ERROR_CHECK 1.0e-5 +&END DEBUG + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE ../uff_table +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oc.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/co.spl +#CPQA INCLUDE DFTB/scc/cc.spl +#CPQA INCLUDE DFTB/scc/ch.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hc.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + &DFT + &QS + METHOD DFTB + &DFTB + DISPERSION T + DO_EWALD F + ORTHOGONAL_BASIS F + SELF_CONSISTENT T + &PARAMETER + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + UFF_FORCE_FIELD ../uff_table + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-9 + MAX_SCF 1000 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.05 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc/ch2o_tblite_mixer.inp b/tests/DFTB/regtest-scc/ch2o_tblite_mixer.inp new file mode 100644 index 0000000000..7800e96e3a --- /dev/null +++ b/tests/DFTB/regtest-scc/ch2o_tblite_mixer.inp @@ -0,0 +1,51 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT ch2o_tblite_mixer + RUN_TYPE ENERGY_FORCE +&END GLOBAL + +#CPQA INCLUDE DFTB/scc/scc_parameter +#CPQA INCLUDE DFTB/scc/oo.spl +#CPQA INCLUDE DFTB/scc/oc.spl +#CPQA INCLUDE DFTB/scc/oh.spl +#CPQA INCLUDE DFTB/scc/co.spl +#CPQA INCLUDE DFTB/scc/cc.spl +#CPQA INCLUDE DFTB/scc/ch.spl +#CPQA INCLUDE DFTB/scc/ho.spl +#CPQA INCLUDE DFTB/scc/hc.spl +#CPQA INCLUDE DFTB/scc/hh.spl +&FORCE_EVAL + &DFT + &QS + METHOD DFTB + &DFTB + DISPERSION F + ORTHOGONAL_BASIS F + SCC_MIXER TBLITE + SELF_CONSISTENT T + TBLITE_MIXER_DAMPING 0.005 + &PARAMETER + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH DFTB/scc + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0E-10 + MAX_SCF 500 + SCF_GUESS CORE + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-scc/zns_kp2_stress.inp b/tests/DFTB/regtest-scc/zns_kp2_stress.inp new file mode 100644 index 0000000000..08f9d378a2 --- /dev/null +++ b/tests/DFTB/regtest-scc/zns_kp2_stress.inp @@ -0,0 +1,81 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT ZnS + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 1.0e-4 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_GEO 1.e-8 + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 25 + &END EWALD + &END POISSON + &QS + EXTRAPOLATION USE_GUESS + METHOD DFTB + &DFTB + DISPERSION F + ORTHOGONAL_BASIS F + SCC_MIXER CP2K + SELF_CONSISTENT T + &PARAMETER + PARAM_FILE_NAME scc_parameter + PARAM_FILE_PATH ./DFTB/scc + SK_FILE Zn Zn znzn.spl + SK_FILE Zn S zns.spl + SK_FILE S Zn szn.spl + SK_FILE S S ss.spl + &END PARAMETER + &END DFTB + &END QS + &SCF + EPS_SCF 1.0e-10 + MAX_SCF 500 + SCF_GUESS ATOMIC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.409 5.409 5.409 + &END CELL + &COORD + SCALED + Zn 0.000000 0.000000 0.000000 + Zn 0.000000 0.500000 0.500000 + Zn 0.500000 0.000000 0.500000 + Zn 0.500000 0.500000 0.000000 + S 0.255000 0.250000 0.250000 + S 0.250000 0.750000 0.750000 + S 0.750000 0.250000 0.750000 + S 0.750000 0.750000 0.250000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/DFTB/regtest-vdw/TEST_FILES.toml b/tests/DFTB/regtest-vdw/TEST_FILES.toml index d84d7c5159..989553e01a 100644 --- a/tests/DFTB/regtest-vdw/TEST_FILES.toml +++ b/tests/DFTB/regtest-vdw/TEST_FILES.toml @@ -1,8 +1,8 @@ # runs are executed in the same order as in this file # the second field tells which test should be run in order to compare with the last available output # see regtest/TEST_FILES -"tb_uff.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75463073188988}] -"tb_d3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.76288772623661}] -"tb_d3bj.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.76508211988679}] -"tb_d2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.85163052938608}] +"tb_uff.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.75463073189035}] +"tb_d3.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.76288772639609}] +"tb_d3bj.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.76508212004095}] +"tb_d2.inp" = [{matcher="E_total", tol=1.0E-14, ref=-5.85163052938979}] #EOF diff --git a/tests/QS/regtest-dft-vdw-corr-1/TEST_FILES.toml b/tests/QS/regtest-dft-vdw-corr-1/TEST_FILES.toml index 4d42d7cefd..63a7f65bd0 100644 --- a/tests/QS/regtest-dft-vdw-corr-1/TEST_FILES.toml +++ b/tests/QS/regtest-dft-vdw-corr-1/TEST_FILES.toml @@ -14,5 +14,5 @@ "dftd3_t3.inp" = [{matcher="M033", tol=1.0E-14, ref=-0.00021588485204}] # "dftd3src1.inp" = [{matcher="M033", tol=1.0E-14, ref=-0.02610167828267}] -"dftd3src2.inp" = [{matcher="M033", tol=1.0E-12, ref=-0.01190472610032}] +"dftd3src2.inp" = [{matcher="M033", tol=1.0E-12, ref=-0.01190472345638}] #EOF diff --git a/tests/QS/regtest-dm-ls-scf-1/TEST_FILES.toml b/tests/QS/regtest-dm-ls-scf-1/TEST_FILES.toml index 3c21366b0a..403aa1a446 100644 --- a/tests/QS/regtest-dm-ls-scf-1/TEST_FILES.toml +++ b/tests/QS/regtest-dm-ls-scf-1/TEST_FILES.toml @@ -12,7 +12,7 @@ "H2-big-12.inp" = [{matcher="M011", tol=2e-13, ref=-27.808422055041142}] "H2O-32-se-ls-2.inp" = [{matcher="M011", tol=2e-12, ref=-91.844809918052079}] "H2-big-nimages.inp" = [{matcher="M011", tol=2e-13, ref=-27.808422055041149}] -"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-14, ref=-32.574187281046839}] -"H2O-32-dftb-ls-2-2.inp" = [{matcher="M011", tol=1e-14, ref=-32.566467816537354}] -"H2O-32-dftb-ls-3.inp" = [{matcher="M011", tol=1e-14, ref=-65.156508566365304}] +"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-14, ref=-32.574187449191}] +"H2O-32-dftb-ls-2-2.inp" = [{matcher="M011", tol=1e-14, ref=-32.56646782062275}] +"H2O-32-dftb-ls-3.inp" = [{matcher="M011", tol=1e-14, ref=-65.1565085666187}] #EOF diff --git a/tests/QS/regtest-dm-ls-scf-2/TEST_FILES.toml b/tests/QS/regtest-dm-ls-scf-2/TEST_FILES.toml index 084b0a3755..dea6bff8ae 100644 --- a/tests/QS/regtest-dm-ls-scf-2/TEST_FILES.toml +++ b/tests/QS/regtest-dm-ls-scf-2/TEST_FILES.toml @@ -1,4 +1,4 @@ -"H2O-32-dftb-ls-4.inp" = [{matcher="M011", tol=1e-14, ref=-65.156509160977791}] +"H2O-32-dftb-ls-4.inp" = [{matcher="M011", tol=1e-14, ref=-65.156509277266}] "ace_ala_nme_pm6_01.inp" = [{matcher="M011", tol=2e-13, ref=-67.527159993652958}] "ace_ala_nme_pm6_02.inp" = [{matcher="M011", tol=1e-13, ref=-67.527159993652958}] "ace_ala_nme_pm6_03.inp" = [{matcher="M011", tol=1e-13, ref=-67.527159993652731}] @@ -6,6 +6,6 @@ "ace_ala_nme_pm6_05.inp" = [{matcher="M011", tol=1e-13, ref=-67.52716001935687}] "ace_ala_nme_pm6_06.inp" = [{matcher="M011", tol=1e-13, ref=-67.52716001935687}] "H2O-32-dftb-trs4.inp" = [{matcher="M011", tol=1e-14, ref=-32.574186126112359}] -"H2O-32-dftb-ls-5.inp" = [{matcher="M011", tol=1e-14, ref=-65.156508922082025}] -"H2O-32-dftb-ls-6.inp" = [{matcher="M011", tol=1e-14, ref=-65.156509160977791}] +"H2O-32-dftb-ls-5.inp" = [{matcher="M011", tol=1e-14, ref=-65.15650903836215}] +"H2O-32-dftb-ls-6.inp" = [{matcher="M011", tol=1e-14, ref=-65.156509277266}] #EOF diff --git a/tests/QS/regtest-dm-ls-scf-3/TEST_FILES.toml b/tests/QS/regtest-dm-ls-scf-3/TEST_FILES.toml index e108eb87e0..135b152101 100644 --- a/tests/QS/regtest-dm-ls-scf-3/TEST_FILES.toml +++ b/tests/QS/regtest-dm-ls-scf-3/TEST_FILES.toml @@ -1,10 +1,10 @@ -"H2O-32-dftb-ls-7.inp" = [{matcher="M011", tol=1e-14, ref=-65.156508767453730}] -"H2O-32-dftb-ls-8.inp" = [{matcher="M011", tol=1e-14, ref=-65.156509052448342}] +"H2O-32-dftb-ls-7.inp" = [{matcher="M011", tol=1e-14, ref=-65.15650888373142}] +"H2O-32-dftb-ls-8.inp" = [{matcher="M011", tol=1e-14, ref=-65.15650916873452}] "H2O-32-dftb-trs4-dyn.inp" = [{matcher="M011", tol=1e-14, ref=-32.574186126112359}] "H2_curvy-1.inp" = [{matcher="M011", tol=2e-13, ref=-27.808687287777047}] "H2_curvy-2.inp" = [{matcher="M011", tol=2e-13, ref=-27.808687287777051}] "H2_curvy-3.inp" = [{matcher="M011", tol=2e-13, ref=-27.808687287777047}] -"H2O-chebyshev-01.inp" = [{matcher="M011", tol=1e-14, ref=-32.574187281046839}] +"H2O-chebyshev-01.inp" = [{matcher="M011", tol=1e-14, ref=-32.574187449191}] "H2O-ewindow-01.inp" = [{matcher="M011", tol=2e-13, ref=-17.178459065026125}] "H2O-dft-ecube.inp" = [{matcher="M011", tol=1e-13, ref=-51.496123149381503}] "H2O-dipole.inp" = [{matcher="M039", tol=1.0E-14, ref=0.4862112}] @@ -13,7 +13,7 @@ "H2O-restart-read-curvy.inp" = [{matcher="M011", tol=2e-13, ref=-51.496124073690879}] "H2O-curvy-prop.inp" = [{matcher="M011", tol=1e-13, ref=-17.163926787927892}] "H2O-dftb-tc2-1.inp" = [{matcher="M011", tol=1e-10, ref=-65.156509353902877}] -"H2O-dftb-tc2-2.inp" = [{matcher="M011", tol=1e-13, ref=-65.156509348964946}] +"H2O-dftb-tc2-2.inp" = [{matcher="M011", tol=1e-13, ref=-65.15650934894896}] "ch4_DIIS-TRS4.inp" = [{matcher="M011", tol=2e-14, ref=-7.995026750654139}] "cho_DIIS-TRS4.inp" = [{matcher="M011", tol=2e-14, ref=-22.137028020221496}] "C_TRS4.inp" = [{matcher="M011", tol=2e-04, ref=-5.308503835702582}] diff --git a/tests/QS/regtest-gpw-9/TEST_FILES.toml b/tests/QS/regtest-gpw-9/TEST_FILES.toml index 5b14806897..572b9291ab 100644 --- a/tests/QS/regtest-gpw-9/TEST_FILES.toml +++ b/tests/QS/regtest-gpw-9/TEST_FILES.toml @@ -1,15 +1,15 @@ # "nlcc-mix.inp" = [{matcher="E_total", tol=1.0E-12, ref=-18.10530459905852}] "C2H4_GRRM.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.93037233386821}] -"h2o_GRRM.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.672}, +"h2o_GRRM.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.6104041}, {matcher="Vib_frc_const", tol=1.0E-04, ref=0.087928}] "C2H4_frozen_GRRM.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.93037233386821}] -"h2o_frozen_GRRM.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=872.278}] +"h2o_frozen_GRRM.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=872.26594122}] # "C2H4_SCINE.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.14346149279209}] -"h2o_SCINE.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.672}, +"h2o_SCINE.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.6104041}, {matcher="Vib_frc_const", tol=1.0E-04, ref=0.087928}] -"h2o_NEWTONX.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1447.380}, +"h2o_NEWTONX.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1447.326016}, {matcher="Vib_frc_const", tol=1.0E-04, ref=0.085778}] # "cif_symbol_1st_column.inp" = [{matcher="E_total", tol=1.0E-14, ref=-13.41107059145742}] diff --git a/tests/QS/regtest-rma-3D/TEST_FILES.toml b/tests/QS/regtest-rma-3D/TEST_FILES.toml index 476d2c75e2..fab829a333 100644 --- a/tests/QS/regtest-rma-3D/TEST_FILES.toml +++ b/tests/QS/regtest-rma-3D/TEST_FILES.toml @@ -1,5 +1,5 @@ -"H2O-32-dftb-ls-2_mult.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187281046811}] -"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187281046811}] +"H2O-32-dftb-ls-2_mult.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187449191}] +"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187449191}] "H2O-OT-ASPC-1.inp" = [{matcher="E_total", tol=4e-14, ref=-17.13993294752105}] "H2-big-nimages.inp" = [{matcher="M011", tol=2e-13, ref=-27.808422055041138}] "H2O_grad_gpw.inp" = [{matcher="M011", tol=7e-08, ref=-16.990049367524865}] diff --git a/tests/QS/regtest-rma/TEST_FILES.toml b/tests/QS/regtest-rma/TEST_FILES.toml index 2875ca2349..1a4530750e 100644 --- a/tests/QS/regtest-rma/TEST_FILES.toml +++ b/tests/QS/regtest-rma/TEST_FILES.toml @@ -1,5 +1,5 @@ -"H2O-32-dftb-ls-2_mult.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187281046811}] -"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187281046811}] +"H2O-32-dftb-ls-2_mult.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187449191}] +"H2O-32-dftb-ls-2.inp" = [{matcher="M011", tol=1e-12, ref=-32.574187449191}] "H2O-OT-ASPC-1.inp" = [{matcher="E_total", tol=4e-14, ref=-17.13993294752105}] "H2O-OT-ASPC-1_clusters.inp" = [{matcher="E_total", tol=4e-14, ref=-17.13993294752105}] "H2-big-nimages.inp" = [{matcher="M011", tol=2e-13, ref=-27.808422055041138}] diff --git a/tests/QS/regtest-spgr-id/quartz.inp b/tests/QS/regtest-spgr-id/quartz.inp index 8afb8709c1..64ff94305c 100644 --- a/tests/QS/regtest-spgr-id/quartz.inp +++ b/tests/QS/regtest-spgr-id/quartz.inp @@ -27,6 +27,9 @@ &POISSON PERIODIC XYZ POISSON_SOLVER PERIODIC + &EWALD + ALPHA 1.0 + &END EWALD &END POISSON &QS METHOD XTB diff --git a/tests/QS/regtest-spgr/quartz.inp b/tests/QS/regtest-spgr/quartz.inp index be97fd5299..db872682a6 100644 --- a/tests/QS/regtest-spgr/quartz.inp +++ b/tests/QS/regtest-spgr/quartz.inp @@ -24,6 +24,9 @@ &POISSON PERIODIC XYZ POISSON_SOLVER PERIODIC + &EWALD + ALPHA 1.0 + &END EWALD &END POISSON &QS METHOD XTB diff --git a/tests/QS/regtest-stda-force/TEST_FILES.toml b/tests/QS/regtest-stda-force/TEST_FILES.toml index 9743e4e4d4..d0a455360f 100644 --- a/tests/QS/regtest-stda-force/TEST_FILES.toml +++ b/tests/QS/regtest-stda-force/TEST_FILES.toml @@ -14,5 +14,5 @@ "h2o_f08a.inp" = [{matcher="E_total", tol=1.0E-12, ref=-17.23033099140069}] "h2o_f08b.inp" = [{matcher="E_total", tol=1.0E-12, ref=-17.23207213802078}] "CH2O_stda-xtb-s_virtual_shift.inp" = [{matcher="M037", tol=1.0E-06, ref=0.779158E-01}] -"water_xTB_virtual_shift.inp" = [{matcher="M037", tol=1.0E-06, ref=0.236164E+00}] +"water_xTB_virtual_shift.inp" = [{matcher="M037", tol=1.0E-06, ref=0.236163E+00}] #EOF diff --git a/tests/QS/regtest-stress/TEST_FILES.toml b/tests/QS/regtest-stress/TEST_FILES.toml index e1fcddd54d..f763280879 100644 --- a/tests/QS/regtest-stress/TEST_FILES.toml +++ b/tests/QS/regtest-stress/TEST_FILES.toml @@ -5,5 +5,5 @@ "SiC-stress-pbe-nlcc.inp" = [{matcher="M031", tol=1.0E-09, ref=-1.84632367133E+05}] "SiC-stress-tpss.inp" = [{matcher="M031", tol=1.0E-09, ref=1.33145056114E+04}] "SiC-stress-br89.inp" = [{matcher="M031", tol=1.0E-09, ref=-5.12223409624E+04}] -"LiH-stress-pbe-uks-vdW.inp" = [{matcher="M031", tol=1.0E-09, ref=-2.66548358795E+03}] +"LiH-stress-pbe-uks-vdW.inp" = [{matcher="M031", tol=1.0E-09, ref=-2.61376786609E+03}] #EOF diff --git a/tests/QS/regtest-tddfpt-stda/TEST_FILES.toml b/tests/QS/regtest-tddfpt-stda/TEST_FILES.toml index 68b1d6b1dc..65e3c28e58 100644 --- a/tests/QS/regtest-tddfpt-stda/TEST_FILES.toml +++ b/tests/QS/regtest-tddfpt-stda/TEST_FILES.toml @@ -15,7 +15,7 @@ "H2O_tddfpt_stda-pbe-t.inp" = [{matcher="M037", tol=1.0E-05, ref=0.595565E+00}] "H2O_tddfpt_stda-pbe0-s.inp" = [{matcher="M037", tol=1.0E-05, ref=0.637391E+00}] "H2O_tddfpt_stda-pbe0-t.inp" = [{matcher="M037", tol=1.0E-05, ref=0.633489E+00}] -"H2O_tddfpt_stda-s-1.inp" = [{matcher="M037", tol=1.0E-05, ref=0.173021E+00}] +"H2O_tddfpt_stda-s-1.inp" = [{matcher="M037", tol=1.0E-05, ref=0.173147E+00}] "NO_tddfpt_stda-s-1.inp" = [{matcher="M037", tol=1.0E-05, ref=0.375613E+00}] "water_xTB.inp" = [{matcher="M037", tol=2.0E-05, ref=0.125917E+00}] "water_xTBi_NTO.inp" = [{matcher="M037", tol=2.0E-05, ref=0.125917E+00}] diff --git a/tests/SE/regtest-2-2/TEST_FILES.toml b/tests/SE/regtest-2-2/TEST_FILES.toml index 95c76f80cb..e0c012c482 100644 --- a/tests/SE/regtest-2-2/TEST_FILES.toml +++ b/tests/SE/regtest-2-2/TEST_FILES.toml @@ -38,5 +38,5 @@ # dispersion "2h2o_disp1.inp" = [{matcher="M003", tol=1.0E-14, ref=-649.05174548613479}] "2h2o_disp2.inp" = [{matcher="M003", tol=1.0E-14, ref=-649.05174548613479}] -"2h2o_disp3.inp" = [{matcher="M003", tol=1.0E-14, ref=-649.14047694554415}] +"2h2o_disp3.inp" = [{matcher="M003", tol=1.0E-14, ref=-649.1404770436569}] #EOF diff --git a/tests/matchers.py b/tests/matchers.py index 7e1d12f329..3f8c44f2e9 100644 --- a/tests/matchers.py +++ b/tests/matchers.py @@ -35,10 +35,12 @@ class Matcher(Protocol): # ====================================================================================== class GenericMatcher(Matcher): - def __init__(self, pattern: str, col: int): + def __init__(self, pattern: str, col: int, regex: bool = False): self.pattern = pattern - for c in r"[]()|+*?": - pattern = pattern.replace(c, f"\\{c}") # escape special chars + self.regex_mode = regex + if not regex: + for c in r"[]()|+*?": + pattern = pattern.replace(c, f"\\{c}") # escape special chars self.regex = re.compile(pattern) self.col = col @@ -48,8 +50,12 @@ class GenericMatcher(Matcher): assert isinstance(ref, float) or isinstance(ref, int) # grep result for line in reversed(output.split("\n")): - if self.regex.search(line): - value_str = line.split()[self.col - 1] + match = self.regex.search(line) + if match: + if self.regex_mode and match.groups(): + value_str = match.group(1) + else: + value_str = line.split()[self.col - 1] break else: error = f"Result not found: '{self.pattern}'.\n" @@ -57,7 +63,7 @@ class GenericMatcher(Matcher): # parse result try: - value = float(value_str) + value = float(value_str.replace("D", "E")) except: error = f"Could not parse result as float: '{value_str}'.\n" return MatchResult("WRONG RESULT", error, value=None) @@ -72,6 +78,19 @@ class GenericMatcher(Matcher): return MatchResult("OK", error=None, value=value) # passed +# ====================================================================================== +class TextPresenceMatcher(Matcher): + def __init__(self, text: str): + self.text = text + + def run(self, output: str, **kwargs: Any) -> MatchResult: + if self.text not in output: + return MatchResult( + "WRONG RESULT", f"Text not found: '{self.text}'.\n", value=None + ) + return MatchResult("OK", error=None, value=None) + + # ====================================================================================== class MatcherRegistry(Dict[str, Matcher]): def __setitem__(self, key: str, value: Matcher) -> None: @@ -179,6 +198,15 @@ registry["IC_gap"] = GenericMatcher(r"IC HOMO-LUMO gap (eV)", col=5) registry["M081"] = GenericMatcher(r"HOMO SCF Cycle: 4", col=9) registry["M082"] = GenericMatcher(r"DEBUG| Sum of differences:", col=5) +registry["DEBUG_stress_sum"] = GenericMatcher( + r"DEBUG\|\s+Sum of differences\s+([-+0-9.EeDd]+)$", col=5, regex=True +) +registry["DEBUG_force_sum"] = GenericMatcher( + r"DEBUG\|\s+Sum of differences:\s+([-+0-9.EeDd]+)", col=5, regex=True +) +registry["XTB_reference_cli_failed"] = TextPresenceMatcher( + "tblite reference CLI check failed to run." +) registry["M083"] = GenericMatcher(r"1[ 1] - 2[ 1]", col=7) registry["M084"] = GenericMatcher(r"Ionization potential of the excited atom:", col=7) registry["M085"] = GenericMatcher(r"Total FORCE_EVAL ( SIRIUS ) energy", col=9) diff --git a/tests/xTB/regtest-1/TEST_FILES.toml b/tests/xTB/regtest-1/TEST_FILES.toml index dc3c0813d0..3a918b00b0 100644 --- a/tests/xTB/regtest-1/TEST_FILES.toml +++ b/tests/xTB/regtest-1/TEST_FILES.toml @@ -4,19 +4,20 @@ # 1 compares the last total energy in the file # for details see cp2k/tools/do_regtest "ch2o.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84456570296343}] -"ch2o_geo.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84652942485169}] +"ch2o_scc_mixer_tblite.inp" = [{matcher="E_total", tol=1.0E-08, ref=-7.84456570570919}] +"ch2o_geo.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84652942195117}] "ch2o_lsd.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.19650182424155}] "ch2o_smear.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.19753850357134}] "tmol.inp" = [{matcher="E_total", tol=1.0E-12, ref=-41.90845660778482}] "h2.inp" = [{matcher="E_total", tol=1.0E-12, ref=-1.03458223634251}] "h2_kab.inp" = [{matcher="E_total", tol=1.0E-12, ref=-0.99816707611986}] -"h2o-md.inp" = [{matcher="E_total", tol=1.0E-12, ref=-185.14385714438652}] +"h2o-md.inp" = [{matcher="E_total", tol=1.0E-12, ref=-185.14383606866977}] "h2o_str.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76524673249110}] "h2o_strsym.inp" = [] -"h2o-atprop.inp" = [{matcher="E_total", tol=1.0E-10, ref=-185.16262201741714}] +"h2o-atprop.inp" = [{matcher="E_total", tol=1.0E-10, ref=-185.16260010725958}] "h2o-atprop0.inp" = [{matcher="E_total", tol=1.0E-12, ref=-187.45499307126425}] "si_geo.inp" = [{matcher="E_total", tol=1.0E-11, ref=-14.51194886943525}] -"si_kp.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73191471087850}] +"si_kp.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73191475194472}] "h2o_dimer.inp" = [{matcher="E_total", tol=1.0E-12, ref=-11.54506384435821}] "ghost.inp" = [{matcher="E_total", tol=1.0E-12, ref=-1.03458221876736}] "tcif.inp" = [{matcher="E_total", tol=1.0E-12, ref=-27.71649842848894}] diff --git a/tests/xTB/regtest-1/ch2o_scc_mixer_tblite.inp b/tests/xTB/regtest-1/ch2o_scc_mixer_tblite.inp new file mode 100644 index 0000000000..6e9b3f0849 --- /dev/null +++ b/tests/xTB/regtest-1/ch2o_scc_mixer_tblite.inp @@ -0,0 +1,43 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT ch2o_scc_mixer_tblite + RUN_TYPE ENERGY_FORCE +&END GLOBAL + +&FORCE_EVAL + &DFT + &QS + METHOD xTB + &XTB + COULOMB_INTERACTION T + GFN_TYPE 1 + SCC_MIXER TBLITE + TBLITE_MIXER_DAMPING 0.002 + &PARAMETER + DISPERSION_PARAMETER_FILE dftd3.dat + &END PARAMETER + &END XTB + &END QS + &SCF + EPS_SCF 1.0E-10 + MAX_SCF 500 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-1/si_kp.inp b/tests/xTB/regtest-1/si_kp.inp index e3a450ca17..7d252fd712 100644 --- a/tests/xTB/regtest-1/si_kp.inp +++ b/tests/xTB/regtest-1/si_kp.inp @@ -6,7 +6,10 @@ SCHEME MONKHORST-PACK 2 2 2 &END KPOINTS &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC &EWALD + ALPHA [bohr^-1] 1.0 EWALD_TYPE SPME &END EWALD &END POISSON @@ -27,19 +30,17 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF ADDED_MOS 100 EPS_SCF 1.e-6 IGNORE_CONVERGENCE_FAILURE - MAX_SCF 100 + MAX_SCF 500 SCF_GUESS MOPAC &MIXING ALPHA 0.15 - METHOD BROYDEN_MIXING - NBROYDEN 12 + METHOD DIRECT_P_MIXING &END MIXING &PRINT &RESTART off diff --git a/tests/xTB/regtest-2/TEST_FILES.toml b/tests/xTB/regtest-2/TEST_FILES.toml index 06c8853879..173f7738dd 100644 --- a/tests/xTB/regtest-2/TEST_FILES.toml +++ b/tests/xTB/regtest-2/TEST_FILES.toml @@ -5,7 +5,7 @@ # for details see cp2k/tools/do_regtest # test mulliken constraints "H2O-field-gopt.inp" = [{matcher="E_total", tol=4e-10, ref=-5.76970818700878}] -"H2O-field-gopt-lsd.inp" = [{matcher="E_total", tol=4e-12, ref=-5.76970797174834}] +"H2O-field-gopt-lsd.inp" = [{matcher="E_total", tol=4e-12, ref=-5.76970797200779}] "H2O-field.inp" = [] "H2O-field-lsd.inp" = [{matcher="E_total", tol=4e-14, ref=-5.76959233315201}] "HF-field.inp" = [{matcher="E_total", tol=1e-12, ref=-5.70162277773935}] @@ -16,6 +16,6 @@ "HF-dfield.inp" = [{matcher="E_total", tol=1e-12, ref=-5.66052242442153}] "HF-dfield-debug.inp" = [] "HF-loc-field.inp" = [{matcher="E_total", tol=1e-12, ref=-5.65286303322644}] -"HF-loc-field-gopt.inp" = [{matcher="E_total", tol=2e-08, ref=-5.65791503021294}] +"HF-loc-field-gopt.inp" = [{matcher="E_total", tol=2e-08, ref=-5.65759961599548}] "HF-loc-field-debug.inp" = [] #EOF diff --git a/tests/xTB/regtest-3/TEST_FILES.toml b/tests/xTB/regtest-3/TEST_FILES.toml index 6cf3412af7..0a04c60aec 100644 --- a/tests/xTB/regtest-3/TEST_FILES.toml +++ b/tests/xTB/regtest-3/TEST_FILES.toml @@ -4,14 +4,14 @@ # 1 compares the last total energy in the file # for details see cp2k/tools/do_regtest "NdF3.inp" = [{matcher="E_total", tol=1.0E-12, ref=-16.30904020314352}] -"h2o_rtp.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76539152285971}] -"h2o_emd.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76621483534992}] +"h2o_rtp.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76539102399686}] +"h2o_emd.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76569266115801}] "si8_wan.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.36588818966667}] "si_kp.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123294306}] "si_kp_kpsym.inp" = [{matcher="E_total", tol=1.0E-11, ref=-14.74208554207339}, - {matcher="N_special_kpoints", tol=0.0, ref=32}] + {matcher="N_special_kpoints", tol=0.0, ref=4}] "si_kp_spglib_backend.inp" = [{matcher="E_total", tol=1.0E-11, ref=-14.74208554207337}, - {matcher="N_special_kpoints", tol=0.0, ref=32}] + {matcher="N_special_kpoints", tol=0.0, ref=4}] "tmol.inp" = [{matcher="E_total", tol=1.0E-12, ref=-41.90845660778482}] "ch2o.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84456570305608}] "ch2o_print.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84456570305608}] @@ -19,9 +19,9 @@ "ch2o_dens.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84456570305607}] "ch2o_loc.inp" = [{matcher="E_total", tol=1.0E-12, ref=-13.55045387785839}] "ch2o_mos.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.84456570305607}] -"si_print.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123294387}] -"si_band.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123294387}] -"H2O-geo-pdos.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76872484344198}] -"graphite-stm.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.91403228336802}] -"si_dos.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123294387}] +"si_print.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123463482}] +"si_band.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123463482}] +"H2O-geo-pdos.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76872484352614}] +"graphite-stm.inp" = [{matcher="E_total", tol=1.0E-12, ref=-7.91403223193017}] +"si_dos.inp" = [{matcher="E_total", tol=1.0E-12, ref=-14.73033123463482}] #EOF diff --git a/tests/xTB/regtest-3/si_band.inp b/tests/xTB/regtest-3/si_band.inp index 25fb274776..b54233cea2 100644 --- a/tests/xTB/regtest-3/si_band.inp +++ b/tests/xTB/regtest-3/si_band.inp @@ -5,6 +5,14 @@ &KPOINTS SCHEME MONKHORST-PACK 2 2 2 &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA [bohr^-1] 1.0 + EWALD_TYPE SPME + &END EWALD + &END POISSON &PRINT &BAND_STRUCTURE &KPOINT_SET @@ -15,18 +23,16 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF ADDED_MOS 100 EPS_SCF 1.e-6 - MAX_SCF 100 + MAX_SCF 500 SCF_GUESS MOPAC &MIXING ALPHA 0.40 - METHOD BROYDEN_MIXING - NBUFFER 10 + METHOD DIRECT_P_MIXING &END MIXING &PRINT &RESTART OFF diff --git a/tests/xTB/regtest-3/si_dos.inp b/tests/xTB/regtest-3/si_dos.inp index 2b37f23bd0..5cbd4c6c6e 100644 --- a/tests/xTB/regtest-3/si_dos.inp +++ b/tests/xTB/regtest-3/si_dos.inp @@ -4,6 +4,14 @@ &KPOINTS SCHEME MONKHORST-PACK 2 2 2 &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA [bohr^-1] 1.0 + EWALD_TYPE SPME + &END EWALD + &END POISSON &PRINT &DOS &END DOS @@ -11,18 +19,16 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF ADDED_MOS 100 EPS_SCF 1.e-6 - MAX_SCF 100 + MAX_SCF 500 SCF_GUESS MOPAC &MIXING ALPHA 0.40 - METHOD BROYDEN_MIXING - NBUFFER 10 + METHOD DIRECT_P_MIXING &END MIXING &PRINT &RESTART OFF diff --git a/tests/xTB/regtest-3/si_kp_kpsym.inp b/tests/xTB/regtest-3/si_kp_kpsym.inp index a04dca8c92..14c2384fd9 100644 --- a/tests/xTB/regtest-3/si_kp_kpsym.inp +++ b/tests/xTB/regtest-3/si_kp_kpsym.inp @@ -11,6 +11,8 @@ VERBOSE T &END KPOINTS &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC &EWALD ALPHA 1.0 EWALD_TYPE SPME @@ -20,7 +22,6 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF diff --git a/tests/xTB/regtest-3/si_kp_spglib_backend.inp b/tests/xTB/regtest-3/si_kp_spglib_backend.inp index d34ea49d4b..779216eb56 100644 --- a/tests/xTB/regtest-3/si_kp_spglib_backend.inp +++ b/tests/xTB/regtest-3/si_kp_spglib_backend.inp @@ -12,6 +12,8 @@ VERBOSE T &END KPOINTS &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC &EWALD ALPHA 1.0 EWALD_TYPE SPME @@ -21,7 +23,6 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF diff --git a/tests/xTB/regtest-3/si_print.inp b/tests/xTB/regtest-3/si_print.inp index 2ba1918efd..3113ecd929 100644 --- a/tests/xTB/regtest-3/si_print.inp +++ b/tests/xTB/regtest-3/si_print.inp @@ -5,6 +5,14 @@ &KPOINTS SCHEME MONKHORST-PACK 2 2 2 &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA [bohr^-1] 1.0 + EWALD_TYPE SPME + &END EWALD + &END POISSON &PRINT &ENERGY_WINDOWS N_WINDOWS 10 @@ -40,18 +48,16 @@ &QS METHOD xTB &XTB - DO_EWALD T &END XTB &END QS &SCF ADDED_MOS 100 EPS_SCF 1.e-6 - MAX_SCF 100 + MAX_SCF 500 SCF_GUESS MOPAC &MIXING ALPHA 0.40 - METHOD BROYDEN_MIXING - NBUFFER 10 + METHOD DIRECT_P_MIXING &END MIXING &PRINT &RESTART OFF diff --git a/tests/xTB/regtest-4/TEST_FILES.toml b/tests/xTB/regtest-4/TEST_FILES.toml index 613abb4521..3c7f3a47cc 100644 --- a/tests/xTB/regtest-4/TEST_FILES.toml +++ b/tests/xTB/regtest-4/TEST_FILES.toml @@ -3,7 +3,7 @@ # e.g. 0 means do not compare anything, running is enough # 1 compares the last total energy in the file # for details see cp2k/tools/do_regtest -"H2O-32-xtb-ls-1.inp" = [{matcher="M011", tol=1.0E-12, ref=-46.140441340701784}] +"H2O-32-xtb-ls-1.inp" = [{matcher="M011", tol=1.0E-12, ref=-46.14044075497412}] "H2O-32-xtb-ls-2.inp" = [{matcher="M011", tol=1.0E-12, ref=-46.149897222623842}] "H2O-32-xtb-ls-3.inp" = [{matcher="M011", tol=1.0E-12, ref=-92.314662149041851}] "H2O-32-xtb-ls-4.inp" = [{matcher="M011", tol=1.0E-12, ref=-92.314660970750793}] @@ -15,7 +15,7 @@ "H2O-xtb-tc2-2.inp" = [{matcher="M011", tol=1.0E-12, ref=-92.314663104135690}] "H2O-32-xtb-trs4.inp" = [{matcher="M011", tol=1.0E-12, ref=-46.149897253047165}] "H2O-32-xtb-trs4-dyn.inp" = [{matcher="M011", tol=1.0E-12, ref=-46.149897253047165}] -"h2o_vib.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.672}, +"h2o_vib.inp" = [{matcher="Vib_freq", tol=8.0E-06, ref=1465.6104041}, {matcher="Vib_frc_const", tol=1.0E-04, ref=0.087927}] "tmol.inp" = [{matcher="M011", tol=1.0E-12, ref=-41.908456607784821}] #EOF diff --git a/tests/xTB/regtest-5/Ru_geo.inp b/tests/xTB/regtest-5/Ru_geo.inp index 811688c31a..386a68a690 100644 --- a/tests/xTB/regtest-5/Ru_geo.inp +++ b/tests/xTB/regtest-5/Ru_geo.inp @@ -12,6 +12,7 @@ &END KPOINTS &POISSON &EWALD + ALPHA [bohr^-1] 1.0 EWALD_TYPE SPME &END EWALD &END POISSON @@ -36,7 +37,7 @@ &SCF ADDED_MOS 400 EPS_SCF 1.0E-7 - MAX_SCF 500 + MAX_SCF 1000 SCF_GUESS MOPAC &DIAGONALIZATION ALGORITHM STANDARD diff --git a/tests/xTB/regtest-5/TEST_FILES.toml b/tests/xTB/regtest-5/TEST_FILES.toml index f6b395bb4c..7a3bdc8c2d 100644 --- a/tests/xTB/regtest-5/TEST_FILES.toml +++ b/tests/xTB/regtest-5/TEST_FILES.toml @@ -4,9 +4,9 @@ # 1 compares the last total energy in the file # for details see cp2k/tools/do_regtest "AdeThyvdW.inp" = [{matcher="E_total", tol=1.0E-12, ref=-58.89501835809043}] -"ice.inp" = [{matcher="E_total", tol=1.0E-10, ref=-46.30708081122568}] -"ice2.inp" = [{matcher="E_total", tol=1.0E-10, ref=-46.30708081091197}] "Ru_geo.inp" = [{matcher="E_total", tol=5.0E-09, ref=-7.01272555836003}] +"ice.inp" = [{matcher="E_total", tol=1.0E-10, ref=-46.30445554804503}] +"ice2.inp" = [{matcher="E_total", tol=1.0E-10, ref=-46.30445554772967}] "ef_stress1.inp" = [] "ef_stress2.inp" = [] "ef_stress3.inp" = [] diff --git a/tests/xTB/regtest-debug/TEST_FILES.toml b/tests/xTB/regtest-debug/TEST_FILES.toml index 5dc54e40df..1b287bbf26 100644 --- a/tests/xTB/regtest-debug/TEST_FILES.toml +++ b/tests/xTB/regtest-debug/TEST_FILES.toml @@ -5,13 +5,13 @@ # for details see cp2k/tools/do_regtest "ch2o_t01.inp" = [{matcher="M086", tol=1.0E-12, ref=0.108915750509E+01}] "ch2o_t02.inp" = [{matcher="M086", tol=1.0E-12, ref=0.108915750509E+01}] -"ch2o_t03.inp" = [{matcher="M086", tol=1.0E-12, ref=0.114819181828E+01}] -"ch2o_t04.inp" = [{matcher="M086", tol=1.0E-12, ref=0.109829662200E+01}] +"ch2o_t03.inp" = [{matcher="M086", tol=1.0E-12, ref=0.112728364233E+01}] +"ch2o_t04.inp" = [{matcher="M086", tol=1.0E-12, ref=0.109828925085E+01}] "ch2o_t05.inp" = [{matcher="M087", tol=1.0E-12, ref=0.226843652140E+02}] -"ch2o_t06.inp" = [{matcher="M087", tol=1.0E-12, ref=0.229761888713E+02}] +"ch2o_t06.inp" = [{matcher="M087", tol=1.0E-12, ref=0.229748436012E+02}] "ch2o_t07.inp" = [{matcher="M086", tol=1.0E-12, ref=0.954101834865E+00}] -"ch2o_t08.inp" = [{matcher="M086", tol=1.0E-12, ref=0.963128388956E+00}] +"ch2o_t08.inp" = [{matcher="M086", tol=1.0E-12, ref=0.963121521347E+00}] "ch3br_nonbond_2.inp" = [{matcher="E_total", tol=1.0E-12, ref=-11.78062819229165}] "ch3br_nonbond.inp" = [{matcher="E_total", tol=1.0E-12, ref=-11.78062802267188}] -"ch3br_atprop_nonbond.inp" = [{matcher="E_total", tol=1.0E-10, ref=-11.78112909303997}] +"ch3br_atprop_nonbond.inp" = [{matcher="E_total", tol=1.0E-10, ref=-11.78112904495693}] #EOF diff --git a/tests/xTB/regtest-gfn0/TEST_FILES.toml b/tests/xTB/regtest-gfn0/TEST_FILES.toml index 24f0832fcb..a987b49efc 100644 --- a/tests/xTB/regtest-gfn0/TEST_FILES.toml +++ b/tests/xTB/regtest-gfn0/TEST_FILES.toml @@ -13,10 +13,25 @@ "ch2o_8.inp" = [] "ch2o_9.inp" = [] "si_kp.inp" = [] +"si_kp_kpsym.inp" = [{matcher="E_total", tol=1.0E-11, ref=-13.92586350112312}, + {matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M072", tol=1.0E-12, ref=0.0}, + {matcher="M031", tol=1.0E-5, ref=2.61113942316E+04}] +"si_kp_kpsym_atomdisp.inp" = [{matcher="E_total", tol=1.0E-11, ref=-13.92586348551223}, + {matcher="N_special_kpoints", tol=0.0, ref=12}] +"si_kp_spglib_backend.inp" = [{matcher="E_total", tol=1.0E-11, ref=-13.92586350112312}, + {matcher="N_special_kpoints", tol=0.0, ref=4}, + {matcher="M072", tol=1.0E-12, ref=0.0}, + {matcher="M031", tol=1.0E-5, ref=2.61113942316E+04}] +"si_kp_spglib_reduction_atomdisp.inp" = [{matcher="E_total", tol=1.0E-11, ref=-13.92586348551223}, + {matcher="N_special_kpoints", tol=0.0, ref=12}] +"si_kp_kpsym_debug_stress.inp" = [{matcher="E_total", tol=1.0E-11, ref=-13.92597057189198}, + {matcher="N_special_kpoints", tol=0.0, ref=32}, + {matcher="M042", tol=1.0E-5, ref=0.0}] "si_smear.inp" = [] "SiC_virial.inp" = [] -"SiC-stress.inp" = [] -"ch2o_eeq.inp" = [{matcher="E_total", tol=1.0E-11, ref=-7.84498782090161}] +"SiC-stress.inp" = [{matcher="M042", tol=1.0E-04, ref=0.0}] +"ch2o_eeq.inp" = [{matcher="E_total", tol=1.0E-11, ref=-7.84498764689590}] "ch2o_eloc.inp" = [] "ch2o_eper.inp" = [] "ch2o_ls1.inp" = [{matcher="E_total", tol=1.0E-12, ref=-6.46515972056537}] diff --git a/tests/xTB/regtest-gfn0/si_kp_kpsym.inp b/tests/xTB/regtest-gfn0/si_kp_kpsym.inp new file mode 100644 index 0000000000..bed92d36f1 --- /dev/null +++ b/tests/xTB/regtest-gfn0/si_kp_kpsym.inp @@ -0,0 +1,82 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 50 + &END EWALD + &END POISSON + &QS + METHOD xTB + &XTB + GFN_TYPE 0 + VDW_POTENTIAL DFTD3 + &END XTB + &END QS + &SCF + ADDED_MOS 100 + EPS_SCF 1.e-6 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.40 + METHOD BROYDEN_MIXING + NBUFFER 10 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR + ELECTRONIC_TEMPERATURE 1000 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &PRINT + &FORCES ON + &END FORCES + &STRESS_TENSOR + COMPONENTS + &END STRESS_TENSOR + &END PRINT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn0_kpsym + RUN_TYPE ENERGY_FORCE +&END GLOBAL diff --git a/tests/xTB/regtest-gfn0/si_kp_kpsym_atomdisp.inp b/tests/xTB/regtest-gfn0/si_kp_kpsym_atomdisp.inp new file mode 100644 index 0000000000..ae25c9922d --- /dev/null +++ b/tests/xTB/regtest-gfn0/si_kp_kpsym_atomdisp.inp @@ -0,0 +1,82 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 50 + &END EWALD + &END POISSON + &QS + METHOD xTB + &XTB + GFN_TYPE 0 + VDW_POTENTIAL DFTD3 + &END XTB + &END QS + &SCF + ADDED_MOS 100 + EPS_SCF 1.e-6 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.40 + METHOD BROYDEN_MIXING + NBUFFER 10 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR + ELECTRONIC_TEMPERATURE 1000 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &PRINT + &FORCES ON + &END FORCES + &STRESS_TENSOR + COMPONENTS + &END STRESS_TENSOR + &END PRINT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000050 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn0_kpsym_atomdisp + RUN_TYPE ENERGY_FORCE +&END GLOBAL diff --git a/tests/xTB/regtest-gfn0/si_kp_kpsym_debug_stress.inp b/tests/xTB/regtest-gfn0/si_kp_kpsym_debug_stress.inp new file mode 100644 index 0000000000..5e96b4f947 --- /dev/null +++ b/tests/xTB/regtest-gfn0/si_kp_kpsym_debug_stress.inp @@ -0,0 +1,84 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR DIAGONAL_ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 50 + &END EWALD + &END POISSON + &QS + METHOD xTB + &XTB + GFN_TYPE 0 + VDW_POTENTIAL DFTD3 + &END XTB + &END QS + &SCF + ADDED_MOS 100 + EPS_SCF 1.e-6 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.40 + METHOD BROYDEN_MIXING + NBUFFER 10 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR + ELECTRONIC_TEMPERATURE 1000 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn0_kpsym_debug + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0005 + EPS_NO_ERROR_CHECK 0.000001 + MAX_RELATIVE_ERROR 0.3 + STOP_ON_MISMATCH F +&END DEBUG diff --git a/tests/xTB/regtest-gfn0/si_kp_spglib_backend.inp b/tests/xTB/regtest-gfn0/si_kp_spglib_backend.inp new file mode 100644 index 0000000000..bbf834645b --- /dev/null +++ b/tests/xTB/regtest-gfn0/si_kp_spglib_backend.inp @@ -0,0 +1,83 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + SYMMETRY_BACKEND SPGLIB + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 50 + &END EWALD + &END POISSON + &QS + METHOD xTB + &XTB + GFN_TYPE 0 + VDW_POTENTIAL DFTD3 + &END XTB + &END QS + &SCF + ADDED_MOS 100 + EPS_SCF 1.e-6 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.40 + METHOD BROYDEN_MIXING + NBUFFER 10 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR + ELECTRONIC_TEMPERATURE 1000 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &PRINT + &FORCES ON + &END FORCES + &STRESS_TENSOR + COMPONENTS + &END STRESS_TENSOR + &END PRINT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn0_spglib_backend + RUN_TYPE ENERGY_FORCE +&END GLOBAL diff --git a/tests/xTB/regtest-gfn0/si_kp_spglib_reduction_atomdisp.inp b/tests/xTB/regtest-gfn0/si_kp_spglib_reduction_atomdisp.inp new file mode 100644 index 0000000000..1ff427e9ff --- /dev/null +++ b/tests/xTB/regtest-gfn0/si_kp_spglib_reduction_atomdisp.inp @@ -0,0 +1,83 @@ +@SET NREP 1 +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + SYMMETRY_REDUCTION_METHOD SPGLIB + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &EWALD + ALPHA 0.35 + EWALD_TYPE SPME + GMAX 50 + &END EWALD + &END POISSON + &QS + METHOD xTB + &XTB + GFN_TYPE 0 + VDW_POTENTIAL DFTD3 + &END XTB + &END QS + &SCF + ADDED_MOS 100 + EPS_SCF 1.e-6 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.40 + METHOD BROYDEN_MIXING + NBUFFER 10 + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR + ELECTRONIC_TEMPERATURE 1000 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &PRINT + &FORCES ON + &END FORCES + &STRESS_TENSOR + COMPONENTS + &END STRESS_TENSOR + &END PRINT + &SUBSYS + &CELL + ABC 5.431 5.431 5.431 + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END CELL + &COORD + SCALED + Si 0.000050 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &TOPOLOGY + MULTIPLE_UNIT_CELL ${NREP} ${NREP} ${NREP} + &END TOPOLOGY + &END SUBSYS +&END FORCE_EVAL + +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn0_spglib_reduction_atomdisp + RUN_TYPE ENERGY_FORCE +&END GLOBAL diff --git a/tests/xTB/regtest-gfn1-d/TEST_FILES.toml b/tests/xTB/regtest-gfn1-d/TEST_FILES.toml index 14395fdae5..20113434b8 100644 --- a/tests/xTB/regtest-gfn1-d/TEST_FILES.toml +++ b/tests/xTB/regtest-gfn1-d/TEST_FILES.toml @@ -13,6 +13,7 @@ # "ch2o_t07.inp" = [] "ch2o_t08.inp" = [] +"ch2o_cn_stress.inp" = [] # #ch2o_t09.inp 0 #ch2o_t10.inp 0 diff --git a/tests/xTB/regtest-gfn1-d/ch2o_cn_stress.inp b/tests/xTB/regtest-gfn1-d/ch2o_cn_stress.inp new file mode 100644 index 0000000000..33f81c49c2 --- /dev/null +++ b/tests/xTB/regtest-gfn1-d/ch2o_cn_stress.inp @@ -0,0 +1,53 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT CH2O-cn-stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DE 0.0002 + DEBUG_DIPOLE F + DEBUG_FORCES F + DEBUG_POLARIZABILITY F + DEBUG_STRESS_TENSOR T + DX 0.0005 + EPS_NO_ERROR_CHECK 1.0E-7 + STOP_ON_MISMATCH T +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &QS + METHOD xTB + &XTB + COULOMB_INTERACTION F + DO_EWALD T + DO_NONBONDED F + GFN_TYPE 1 + USE_HALOGEN_CORRECTION F + VDW_POTENTIAL NONE + &END XTB + &END QS + &SCF + EPS_SCF 1.0E-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.0 5.0 5.0 + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-stda-force/TEST_FILES.toml b/tests/xTB/regtest-stda-force/TEST_FILES.toml index d2ee6f4b36..0d12f0d51c 100644 --- a/tests/xTB/regtest-stda-force/TEST_FILES.toml +++ b/tests/xTB/regtest-stda-force/TEST_FILES.toml @@ -10,6 +10,6 @@ #h2o_f15.inp 1 1.0E-12 0.000000E+00 #h2o_f16.inp 1 1.0E-12 0.000000E+00 #h2o_f17.inp 1 1.0E-12 0.000000E+00 -"h2o_f18.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76959310723082}] +"h2o_f18.inp" = [{matcher="E_total", tol=1.0E-12, ref=-5.76904757361574}] #h2o_f19.inp 1 1.0E-12 0.000000E+00 #EOF diff --git a/tests/xTB/regtest-tblite-gfn1-grad/Ar_fcc_gfn1_kp_debug.inp b/tests/xTB/regtest-tblite-gfn1-grad/Ar_fcc_gfn1_kp_debug.inp new file mode 100644 index 0000000000..ffe2abd4c5 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn1-grad/Ar_fcc_gfn1_kp_debug.inp @@ -0,0 +1,61 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_fcc_gfn1_kp + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN1 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 5.2600000000 5.2600000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.021000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.032000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn1-grad/CH2O_gfn1_force.inp b/tests/xTB/regtest-tblite-gfn1-grad/CH2O_gfn1_force.inp index b605edcc11..ca3b38adc1 100644 --- a/tests/xTB/regtest-tblite-gfn1-grad/CH2O_gfn1_force.inp +++ b/tests/xTB/regtest-tblite-gfn1-grad/CH2O_gfn1_force.inp @@ -29,6 +29,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-grad/COBe_gfn1_fd_force.inp b/tests/xTB/regtest-tblite-gfn1-grad/COBe_gfn1_fd_force.inp index 98ac295023..9b3513a36f 100644 --- a/tests/xTB/regtest-tblite-gfn1-grad/COBe_gfn1_fd_force.inp +++ b/tests/xTB/regtest-tblite-gfn1-grad/COBe_gfn1_fd_force.inp @@ -29,6 +29,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_force.inp b/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_force.inp index 0c773781f7..eb601f9b1e 100644 --- a/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_force.inp +++ b/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_force.inp @@ -29,6 +29,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_stress.inp b/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_stress.inp new file mode 100644 index 0000000000..5e6ea2c30a --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn1-grad/Si_gfn1_fd_stress.inp @@ -0,0 +1,65 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT dat_Si + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + SCHEME NONE + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN1 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-8 + MAX_SCF 100 + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD Fermi_Dirac + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + Si 0.00000000 0.00000000 0.00000000 + Si 2.71550000 2.71550000 0.00000000 + Si 2.71550000 0.00000000 2.71550000 + Si 0.00000000 2.71550000 2.71550000 + Si 1.35775000 1.35775000 1.35775000 + Si 1.35775000 4.10040500 4.10040500 + Si 4.10040500 1.35775000 4.10040500 + Si 4.10040500 4.10040500 1.35775000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn1-grad/TEST_FILES.toml b/tests/xTB/regtest-tblite-gfn1-grad/TEST_FILES.toml index 26e9ff0fd1..fd248c54c7 100644 --- a/tests/xTB/regtest-tblite-gfn1-grad/TEST_FILES.toml +++ b/tests/xTB/regtest-tblite-gfn1-grad/TEST_FILES.toml @@ -6,4 +6,8 @@ "CH2O_gfn1_force.inp" = [{matcher="M082", tol=1.0E-5, ref=0.0000000}] "COBe_gfn1_fd_force.inp" = [{matcher="M082", tol=1.0E-5, ref=0.0000000}] "Si_gfn1_fd_force.inp" = [{matcher="M082", tol=2.0E-4, ref=0.0000000}] +"Si_gfn1_fd_stress.inp" = [{matcher="M042", tol=1.0E-5, ref=0.0000000}] +"Ar_fcc_gfn1_kp_debug.inp" = [{matcher="DEBUG_stress_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="DEBUG_force_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] #EOF diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/CH2O_gfn1.inp b/tests/xTB/regtest-tblite-gfn1-periodic/CH2O_gfn1.inp index 821dabc276..1844ffca7c 100644 --- a/tests/xTB/regtest-tblite-gfn1-periodic/CH2O_gfn1.inp +++ b/tests/xTB/regtest-tblite-gfn1-periodic/CH2O_gfn1.inp @@ -17,6 +17,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/COBe_gfn1_fd.inp b/tests/xTB/regtest-tblite-gfn1-periodic/COBe_gfn1_fd.inp index 7662b17393..a64412e3d1 100644 --- a/tests/xTB/regtest-tblite-gfn1-periodic/COBe_gfn1_fd.inp +++ b/tests/xTB/regtest-tblite-gfn1-periodic/COBe_gfn1_fd.inp @@ -17,6 +17,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_fd.inp b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_fd.inp index 0e428b5142..21bb84c69b 100644 --- a/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_fd.inp +++ b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_fd.inp @@ -18,6 +18,7 @@ EPS_DEFAULT 1.00E-12 METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp.inp b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp.inp new file mode 100644 index 0000000000..fd4483aa1e --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp.inp @@ -0,0 +1,61 @@ +&GLOBAL + PRINT_LEVEL LOW + PROJECT Si_gfn1_kp + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + METHOD QS + &DFT + &KPOINTS + SCHEME MONKHORST-PACK 2 2 2 + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN1 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-8 + MAX_SCF 100 + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + Si 0.00000000 0.00000000 0.00000000 + Si 2.71550000 2.71550000 0.00000000 + Si 2.71550000 0.00000000 2.71550000 + Si 0.00000000 2.71550000 2.71550000 + Si 1.35775000 1.35775000 1.35775000 + Si 1.35775000 4.10040500 4.10040500 + Si 4.10040500 1.35775000 4.10040500 + Si 4.10040500 4.10040500 1.35775000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp_kpsym.inp b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp_kpsym.inp new file mode 100644 index 0000000000..869e0911e9 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn1-periodic/Si_gfn1_kp_kpsym.inp @@ -0,0 +1,68 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Si_gfn1_kp_kpsym + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + METHOD QS + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN1 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn1-periodic/TEST_FILES.toml b/tests/xTB/regtest-tblite-gfn1-periodic/TEST_FILES.toml index 112ba96fb3..73bf1d079d 100644 --- a/tests/xTB/regtest-tblite-gfn1-periodic/TEST_FILES.toml +++ b/tests/xTB/regtest-tblite-gfn1-periodic/TEST_FILES.toml @@ -5,5 +5,8 @@ # for details see cp2k/tools/do_regtest "COBe_gfn1_fd.inp" = [{matcher="E_total", tol=1.0E-8, ref=-7.4283186205}] "CH2O_gfn1.inp" = [{matcher="E_total", tol=1.0E-8, ref=-7.8503584297}] -"Si_gfn1_fd.inp" = [{matcher="E_total", tol=1.0E-8, ref=-14.452117500}] +"Si_gfn1_fd.inp" = [{matcher="E_total", tol=1.0E-8, ref=-14.45211729669823}] +"Si_gfn1_kp.inp" = [{matcher="E_total", tol=1.0E-8, ref=-14.71883978952347}] +"Si_gfn1_kp_kpsym.inp" = [{matcher="E_total", tol=1.0E-8, ref=-14.7262344001}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] #EOF diff --git a/tests/xTB/regtest-tblite-gfn1/CH2O_gfn1.inp b/tests/xTB/regtest-tblite-gfn1/CH2O_gfn1.inp index 44efd39f26..3b19f7fbdf 100644 --- a/tests/xTB/regtest-tblite-gfn1/CH2O_gfn1.inp +++ b/tests/xTB/regtest-tblite-gfn1/CH2O_gfn1.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/COBe_gfn1.inp b/tests/xTB/regtest-tblite-gfn1/COBe_gfn1.inp index 0544d11b01..02c6b200c5 100644 --- a/tests/xTB/regtest-tblite-gfn1/COBe_gfn1.inp +++ b/tests/xTB/regtest-tblite-gfn1/COBe_gfn1.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/COBe_gfn1_force.inp b/tests/xTB/regtest-tblite-gfn1/COBe_gfn1_force.inp index 266b7357ed..2bc05e2a7f 100644 --- a/tests/xTB/regtest-tblite-gfn1/COBe_gfn1_force.inp +++ b/tests/xTB/regtest-tblite-gfn1/COBe_gfn1_force.inp @@ -6,12 +6,11 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT &PRINT &DERIVATIVES ON @@ -20,6 +19,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1.inp b/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1.inp index 1b73f6f29d..e509e4a0d4 100644 --- a/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1.inp +++ b/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1.inp @@ -11,6 +11,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1_force.inp b/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1_force.inp index 993fdbca55..6000117812 100644 --- a/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1_force.inp +++ b/tests/xTB/regtest-tblite-gfn1/H2SO4_gfn1_force.inp @@ -6,18 +6,18 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT CHARGE 0 MULTIPLICITY 1 &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1.inp b/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1.inp index 21913dbbb7..ca4b38a1a0 100644 --- a/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1.inp +++ b/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1.inp @@ -11,6 +11,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1_force.inp b/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1_force.inp index bb92bfe134..ccc859e773 100644 --- a/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1_force.inp +++ b/tests/xTB/regtest-tblite-gfn1/Hg2Cl2_gfn1_force.inp @@ -6,18 +6,18 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT CHARGE 0 MULTIPLICITY 1 &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_force.inp b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_force.inp new file mode 100644 index 0000000000..57a7017545 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_force.inp @@ -0,0 +1,54 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_fcc_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + SCHEME NONE + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 5.2600000000 5.2600000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.021000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.032000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_kp_debug.inp b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_kp_debug.inp new file mode 100644 index 0000000000..2cff92aca1 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_kp_debug.inp @@ -0,0 +1,61 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_fcc_gfn2_kp + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 5.2600000000 5.2600000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.021000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.032000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_stress.inp b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_stress.inp new file mode 100644 index 0000000000..8dbb529e3a --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Ar_fcc_gfn2_stress.inp @@ -0,0 +1,58 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_fcc + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + SCHEME MONKHORST-PACK 2 2 2 + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 5.2600000000 5.2600000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.021000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.032000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/Ar_layer_gfn2_xz_kp_debug.inp b/tests/xTB/regtest-tblite-gfn2/Ar_layer_gfn2_xz_kp_debug.inp new file mode 100644 index 0000000000..b6bc32b0b0 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Ar_layer_gfn2_xz_kp_debug.inp @@ -0,0 +1,61 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_layer_gfn2_xz_kp + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 1 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 18.0000000000 5.2600000000 + PERIODIC XZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.501000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.532000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2.inp b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2.inp index 34d939a408..f2e772219f 100644 --- a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2.inp +++ b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force.inp b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force.inp index 65895b4dc9..ed68ded9b2 100644 --- a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force.inp +++ b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force.inp @@ -6,16 +6,16 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force_cp2k_mixer.inp b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force_cp2k_mixer.inp new file mode 100644 index 0000000000..ea5f547233 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_force_cp2k_mixer.inp @@ -0,0 +1,47 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT CH2O + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 0.0001 +&END DEBUG + +&FORCE_EVAL + &DFT + &QS + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + SCC_MIXER CP2K + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-8 + MAX_SCF 100 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_reference_cli_lone.inp b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_reference_cli_lone.inp new file mode 100644 index 0000000000..cf3d49efdc --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_reference_cli_lone.inp @@ -0,0 +1,47 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT CH2O_gfn2_reference_cli_lone + RUN_TYPE ENERGY_FORCE +&END GLOBAL + +&FORCE_EVAL + &DFT + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &REFERENCE_CLI + CHECK_FORCES F + CHECK_VIRIAL F + PROGRAM_NAME /bin/false + STOP_ON_ERROR F + &END REFERENCE_CLI + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_stress.inp b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_stress.inp new file mode 100644 index 0000000000..bfb014903b --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/CH2O_gfn2_stress.inp @@ -0,0 +1,50 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT CH2O_gfn2_stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 20.0 20.0 20.0 + PERIODIC NONE + &END CELL + &COORD + O 0.051368 0.000000 0.000000 + C 1.278612 0.000000 0.000000 + H 1.870460 0.939607 0.000000 + H 1.870460 -0.939607 0.000000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/COBe_gfn2.inp b/tests/xTB/regtest-tblite-gfn2/COBe_gfn2.inp index a83fbc3902..51d5f8f184 100644 --- a/tests/xTB/regtest-tblite-gfn2/COBe_gfn2.inp +++ b/tests/xTB/regtest-tblite-gfn2/COBe_gfn2.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/COBe_gfn2_force.inp b/tests/xTB/regtest-tblite-gfn2/COBe_gfn2_force.inp index e73b289cd0..010b4d828b 100644 --- a/tests/xTB/regtest-tblite-gfn2/COBe_gfn2_force.inp +++ b/tests/xTB/regtest-tblite-gfn2/COBe_gfn2_force.inp @@ -6,16 +6,16 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/H2SO4_gfn2.inp b/tests/xTB/regtest-tblite-gfn2/H2SO4_gfn2.inp index f63ad241ef..1620e6ec41 100644 --- a/tests/xTB/regtest-tblite-gfn2/H2SO4_gfn2.inp +++ b/tests/xTB/regtest-tblite-gfn2/H2SO4_gfn2.inp @@ -11,6 +11,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/Hg2Cl2_gfn2_force.inp b/tests/xTB/regtest-tblite-gfn2/Hg2Cl2_gfn2_force.inp index 65f7971015..2644124d42 100644 --- a/tests/xTB/regtest-tblite-gfn2/Hg2Cl2_gfn2_force.inp +++ b/tests/xTB/regtest-tblite-gfn2/Hg2Cl2_gfn2_force.inp @@ -11,7 +11,6 @@ &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT CHARGE 0 MULTIPLICITY 1 @@ -22,6 +21,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/NH3_gfn2.inp b/tests/xTB/regtest-tblite-gfn2/NH3_gfn2.inp index f7cbc3af4f..023b75f439 100644 --- a/tests/xTB/regtest-tblite-gfn2/NH3_gfn2.inp +++ b/tests/xTB/regtest-tblite-gfn2/NH3_gfn2.inp @@ -13,6 +13,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD GFN2 &END TBLITE diff --git a/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_force.inp b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_force.inp new file mode 100644 index 0000000000..0bcad929e5 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_force.inp @@ -0,0 +1,73 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Si_gfn2_fd_force + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR F + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + SCHEME NONE + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &PRINT + &DERIVATIVES ON + &END DERIVATIVES + &END PRINT + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &PRINT + &FORCES ON + &END FORCES + &END PRINT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + Si 0.00000000 0.00000000 0.00000000 + Si 2.71550000 2.71550000 0.00000000 + Si 2.71550000 0.00000000 2.71550000 + Si 0.00000000 2.71550000 2.71550000 + Si 1.35775000 1.35775000 1.35775000 + Si 1.35775000 4.10040500 4.10040500 + Si 4.10040500 1.35775000 4.10040500 + Si 4.10040500 4.10040500 1.35775000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_stress.inp b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_stress.inp new file mode 100644 index 0000000000..2c9374b87a --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_fd_stress.inp @@ -0,0 +1,66 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Si_gfn2_fd_stress + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES F + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + SCHEME NONE + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + Si 0.00000000 0.00000000 0.00000000 + Si 2.71550000 2.71550000 0.00000000 + Si 2.71550000 0.00000000 2.71550000 + Si 0.00000000 2.71550000 2.71550000 + Si 1.35775000 1.35775000 1.35775000 + Si 1.35775000 4.10040500 4.10040500 + Si 4.10040500 1.35775000 4.10040500 + Si 4.10040500 4.10040500 1.35775000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/Si_gfn2_kp_kpsym.inp b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_kp_kpsym.inp new file mode 100644 index 0000000000..760583e602 --- /dev/null +++ b/tests/xTB/regtest-tblite-gfn2/Si_gfn2_kp_kpsym.inp @@ -0,0 +1,68 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Si_gfn2_kp_kpsym + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + METHOD QS + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD GFN2 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-gfn2/TEST_FILES.toml b/tests/xTB/regtest-tblite-gfn2/TEST_FILES.toml index df25bd81eb..68f4fc1f84 100644 --- a/tests/xTB/regtest-tblite-gfn2/TEST_FILES.toml +++ b/tests/xTB/regtest-tblite-gfn2/TEST_FILES.toml @@ -8,6 +8,22 @@ "H2SO4_gfn2.inp" = [{matcher="E_total", tol=1.0E-8, ref=-20.535208593}] "NH3_gfn2.inp" = [{matcher="E_total", tol=1.0E-8, ref=-4.4259996366}] "CH2O_gfn2_force.inp" = [{matcher="M082", tol=5.0E-6, ref=0.0000000}] +"CH2O_gfn2_force_cp2k_mixer.inp" = [{matcher="M082", tol=5.0E-6, ref=0.0000000}] +"CH2O_gfn2_stress.inp" = [{matcher="M042", tol=1.0E-7, ref=0.0000000}] +"CH2O_gfn2_reference_cli_lone.inp" = [{matcher="E_total", tol=1.0E-8, ref=-7.1737299847}, + {matcher="XTB_reference_cli_failed"}] "COBe_gfn2_force.inp" = [{matcher="M082", tol=5.0E-6, ref=0.0000000}] "Hg2Cl2_gfn2_force.inp" = [{matcher="M082", tol=1.0E-5, ref=0.0000000}] +"Si_gfn2_fd_force.inp" = [{matcher="M082", tol=1.0E-5, ref=0.0000000}] +"Si_gfn2_fd_stress.inp" = [{matcher="M042", tol=1.0E-5, ref=0.0000000}] +"Si_gfn2_kp_kpsym.inp" = [{matcher="E_total", tol=1.0E-8, ref=-13.6562404472}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"Ar_fcc_gfn2_force.inp" = [{matcher="M082", tol=1.0E-5, ref=0.0000000}] +"Ar_fcc_gfn2_stress.inp" = [{matcher="M042", tol=1.0E-5, ref=0.0000000}] +"Ar_fcc_gfn2_kp_debug.inp" = [{matcher="DEBUG_stress_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="DEBUG_force_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"Ar_layer_gfn2_xz_kp_debug.inp" = [{matcher="DEBUG_stress_sum", tol=5.0E-5, ref=0.0000000}, + {matcher="DEBUG_force_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="N_special_kpoints", tol=0.0, ref=2}] #EOF diff --git a/tests/xTB/regtest-tblite-ipea1/Ar_fcc_ipea1_kp_debug.inp b/tests/xTB/regtest-tblite-ipea1/Ar_fcc_ipea1_kp_debug.inp new file mode 100644 index 0000000000..7abfef4513 --- /dev/null +++ b/tests/xTB/regtest-tblite-ipea1/Ar_fcc_ipea1_kp_debug.inp @@ -0,0 +1,61 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Ar_fcc_ipea1_kp + RUN_TYPE DEBUG +&END GLOBAL + +&DEBUG + DEBUG_FORCES T + DEBUG_STRESS_TENSOR T + DX 0.0001 + MAX_RELATIVE_ERROR 0.5 + STOP_ON_MISMATCH F +&END DEBUG + +&FORCE_EVAL + STRESS_TENSOR ANALYTICAL + &DFT + &KPOINTS + FULL_GRID OFF + SCHEME MONKHORST-PACK 2 2 2 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD IPEA1 + &END TBLITE + &END XTB + &END QS + &SCF + EPS_SCF 1.e-10 + MAX_SCF 200 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.2600000000 5.2600000000 5.2600000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Ar 0.113000 0.021000 0.037000 + Ar 0.486000 0.523000 0.014000 + Ar 0.517000 0.032000 0.491000 + Ar 0.029000 0.468000 0.546000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1.inp b/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1.inp index 329dfa25fc..37ccab462a 100644 --- a/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1.inp +++ b/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD IPEA1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1_force.inp b/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1_force.inp index 4cb879b506..a3247fb570 100644 --- a/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1_force.inp +++ b/tests/xTB/regtest-tblite-ipea1/CH2O_ipea1_force.inp @@ -6,16 +6,16 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD IPEA1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-ipea1/COBe_ipea1.inp b/tests/xTB/regtest-tblite-ipea1/COBe_ipea1.inp index 759ef9dbf3..e56206099a 100644 --- a/tests/xTB/regtest-tblite-ipea1/COBe_ipea1.inp +++ b/tests/xTB/regtest-tblite-ipea1/COBe_ipea1.inp @@ -15,6 +15,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD IPEA1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-ipea1/COBe_ipea1_force.inp b/tests/xTB/regtest-tblite-ipea1/COBe_ipea1_force.inp index d19d7f9e18..d7f7074b1f 100644 --- a/tests/xTB/regtest-tblite-ipea1/COBe_ipea1_force.inp +++ b/tests/xTB/regtest-tblite-ipea1/COBe_ipea1_force.inp @@ -6,18 +6,18 @@ &DEBUG DEBUG_FORCES T - DEBUG_STRESS_TENSOR T + DEBUG_STRESS_TENSOR F DX 0.0001 &END DEBUG &FORCE_EVAL - STRESS_TENSOR ANALYTICAL &DFT &PRINT &END PRINT &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD IPEA1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-ipea1/H2SO4_ipea1.inp b/tests/xTB/regtest-tblite-ipea1/H2SO4_ipea1.inp index 4d443d6629..596192fa15 100644 --- a/tests/xTB/regtest-tblite-ipea1/H2SO4_ipea1.inp +++ b/tests/xTB/regtest-tblite-ipea1/H2SO4_ipea1.inp @@ -11,6 +11,7 @@ &QS METHOD xTB &XTB + GFN_TYPE TBLITE &TBLITE METHOD IPEA1 &END TBLITE diff --git a/tests/xTB/regtest-tblite-ipea1/Si_ipea1_kp_kpsym.inp b/tests/xTB/regtest-tblite-ipea1/Si_ipea1_kp_kpsym.inp new file mode 100644 index 0000000000..f1e5de3ea3 --- /dev/null +++ b/tests/xTB/regtest-tblite-ipea1/Si_ipea1_kp_kpsym.inp @@ -0,0 +1,68 @@ +&GLOBAL + PRINT_LEVEL MEDIUM + PROJECT Si_ipea1_kp_kpsym + RUN_TYPE ENERGY +&END GLOBAL + +&FORCE_EVAL + METHOD QS + &DFT + &KPOINTS + EPS_SYMMETRY 1.e-8 + FULL_GRID OFF + PARALLEL_GROUP_SIZE -1 + SCHEME MONKHORST-PACK 4 4 4 + SYMMETRY ON + VERBOSE T + &END KPOINTS + &POISSON + PERIODIC XYZ + POISSON_SOLVER PERIODIC + &END POISSON + &QS + EPS_DEFAULT 1.00E-12 + METHOD xTB + &XTB + GFN_TYPE TBLITE + &TBLITE + METHOD IPEA1 + &END TBLITE + &END XTB + &END QS + &SCF + ADDED_MOS -1 -1 + EPS_SCF 1.e-10 + MAX_SCF 300 + SCF_GUESS MOPAC + &MIXING + ALPHA 0.2 + METHOD DIRECT_P_MIXING + &END MIXING + &PRINT + &RESTART OFF + &END RESTART + &END PRINT + &SMEAR ON + ELECTRONIC_TEMPERATURE 300 + METHOD FERMI_DIRAC + &END SMEAR + &END SCF + &END DFT + &SUBSYS + &CELL + ABC 5.4310000000 5.4310000000000 5.431000000000 + PERIODIC XYZ + &END CELL + &COORD + SCALED + Si 0.000000 0.000000 0.000000 + Si 0.500000 0.500000 0.000000 + Si 0.500000 0.000000 0.500000 + Si 0.000000 0.500000 0.500000 + Si 0.250000 0.250000 0.250000 + Si 0.250000 0.750000 0.750000 + Si 0.750000 0.250000 0.750000 + Si 0.750000 0.750000 0.250000 + &END COORD + &END SUBSYS +&END FORCE_EVAL diff --git a/tests/xTB/regtest-tblite-ipea1/TEST_FILES.toml b/tests/xTB/regtest-tblite-ipea1/TEST_FILES.toml index 00465709d9..3fabea9939 100644 --- a/tests/xTB/regtest-tblite-ipea1/TEST_FILES.toml +++ b/tests/xTB/regtest-tblite-ipea1/TEST_FILES.toml @@ -8,4 +8,9 @@ "H2SO4_ipea1.inp" = [{matcher="E_total", tol=1.0E-8, ref=-23.686361850}] "CH2O_ipea1_force.inp" = [{matcher="M082", tol=1.0E-6, ref=0.0000000}] "COBe_ipea1_force.inp" = [{matcher="M082", tol=1.0E-6, ref=0.0000000}] +"Si_ipea1_kp_kpsym.inp" = [{matcher="E_total", tol=1.0E-8, ref=-15.1833211806}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] +"Ar_fcc_ipea1_kp_debug.inp" = [{matcher="DEBUG_stress_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="DEBUG_force_sum", tol=1.0E-5, ref=0.0000000}, + {matcher="N_special_kpoints", tol=0.0, ref=4}] #EOF diff --git a/tools/toolchain/scripts/stage8/dftd4-4.1.1-gradient-fixes.patch b/tools/toolchain/scripts/stage8/dftd4-4.1.1-gradient-fixes.patch new file mode 100644 index 0000000000..5c8b13c280 --- /dev/null +++ b/tools/toolchain/scripts/stage8/dftd4-4.1.1-gradient-fixes.patch @@ -0,0 +1,766 @@ +diff --git a/src/dftd4/damping/atm.f90 b/src/dftd4/damping/atm.f90 +index 2ea6307..62b9b9c 100644 +--- a/src/dftd4/damping/atm.f90 ++++ b/src/dftd4/damping/atm.f90 +@@ -29,6 +29,58 @@ module dftd4_damping_atm + contains + + ++subroutine get_disp3_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ active = .false. ++ ++ call get_environment_variable("DFTD4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0) then ++ call get_environment_variable("TBLITE_D4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0) then ++ read(env, *, iostat=io) width ++ if (io == 0 .and. width > 0.0_wp .and. width < cutoff) then ++ inner = cutoff - width ++ active = .true. ++ end if ++ end if ++ ++end subroutine get_disp3_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: width, x ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp * x**2 * (1.0_wp - x)**2 / width ++ end if ++ ++end subroutine smooth_cutoff ++ ++ + !> Evaluation of the dispersion energy expression + subroutine get_atm_dispersion(mol, trans, cutoff, s9, a1, a2, alp, r4r2, & + & c6, dc6dcn, dc6dq, energy, dEdcn, dEdq, gradient, sigma) +@@ -133,26 +185,23 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + real(wp), intent(inout) :: energy(:) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang +- real(wp) :: cutoff2, c9, dE, alp3 +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, alp3, swij, swjk, swik, dswdr, sw + + cutoff2 = cutoff*cutoff + alp3 = alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, s9, a1, a2, alp3, r4r2, cutoff2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, trans, c6, s9, a1, a2, alp3, r4r2, cutoff2, cutoff, & ++ !$omp& cutoff_inner, use_switch) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, ang, c9, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(dynamic) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang, c9, dE, & ++ !$omp& swij, swjk, swik, dswdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -163,6 +212,8 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -176,12 +227,17 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswdr) + + ! vjk(:) = mol%xyz(:, kat) + trans(:, ktr) + ! - mol%xyz(:, jat) - trans(:, jtr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswdr) ++ sw = swij * swik * swjk + + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) +@@ -194,21 +250,15 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + + rr = ang*fdmp + +- dE = rr * c9 * triple * third +- energy_local(iat) = energy_local(iat) - dE +- energy_local(jat) = energy_local(jat) - dE +- energy_local(kat) = energy_local(kat) - dE ++ dE = rr * c9 * triple * third * sw ++ energy(iat) = energy(iat) - dE ++ energy(jat) = energy(jat) - dE ++ energy(kat) = energy(kat) - dE + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_atm_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_atm_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_atm_dispersion_energy + +@@ -266,37 +316,27 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + real(wp), intent(inout) :: sigma(:, :) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang +- real(wp) :: cutoff2, alp3, c9, dE, dE_third, dGij(3), dGjk(3), dGik(3), dS(3, 3) +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: dEdq_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) ++ real(wp) :: cutoff2, cutoff_inner, alp3, c9, dE, dE0, dE_third ++ real(wp) :: dGij(3), dGjk(3), dGik(3), dS(3, 3) ++ real(wp) :: swij, swjk, swik, dswijdr, dswjkdr, dswikdr, sw + + cutoff2 = cutoff*cutoff + alp3 = alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, s9, a1, a2, alp, alp3, r4r2, cutoff2, & +- !$omp& dc6dcn, dc6dq) & ++ !$omp parallel do schedule(runtime) default(none) & ++ !$omp reduction(+:energy, gradient, sigma, dEdcn, dEdq) & ++ !$omp shared(mol, trans, c6, s9, a1, a2, alp, alp3, r4r2, cutoff2, cutoff, & ++ !$omp& cutoff_inner, use_switch, dc6dcn, dc6dq) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang, c9, dE, dE_third, dGij, & +- !$omp& dGjk, dGik, dS) & +- !$omp shared(energy, gradient, sigma, dEdcn, dEdq) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local, & +- !$omp& dEdq_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(dEdq_local(size(dEdq, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(dynamic) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang, & ++ !$omp& c9, dE, dE0, dE_third, dGij, dGjk, dGik, dS, swij, swjk, swik, & ++ !$omp& dswijdr, dswjkdr, dswikdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -307,6 +347,8 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswijdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -320,12 +362,17 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswikdr) + + ! vjk(:) = mol%xyz(:, kat) + trans(:, ktr) + ! - mol%xyz(:, jat) - trans(:, jtr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswjkdr) ++ sw = swij * swik * swjk + + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) +@@ -345,73 +392,63 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, a1, a2, alp, r4r2, + & + r2ij * (3.0_wp * r2jk**2 + 2.0_wp * r2jk*r2ik& + & + 3.0_wp * r2ik**2)& + & - 5.0_wp * (r2jk - r2ik)**2 * (r2jk + r2ik)) / r5 +- dGij(:) = c9 * (-dang*fdmp + ang*dfdmp) / r2ij * vij ++ dE0 = rr * c9 ++ dGij(:) = sw * c9 * (-dang*fdmp + ang*dfdmp) / r2ij * vij & ++ & - dE0 * dswijdr / rij * swik * swjk * vij + + ! d/drik + dang = -0.375_wp * (r2ik**3 + r2ik**2 * (r2jk + r2ij)& + & + r2ik * (3.0_wp * r2jk**2 + 2.0_wp * r2jk * r2ij& + & + 3.0_wp * r2ij**2)& + & - 5.0_wp * (r2jk - r2ij)**2 * (r2jk + r2ij)) / r5 +- dGik(:) = c9 * (-dang * fdmp + ang * dfdmp) / r2ik * vik ++ dGik(:) = sw * c9 * (-dang * fdmp + ang * dfdmp) / r2ik * vik & ++ & - dE0 * dswikdr / rik * swij * swjk * vik + + ! d/drjk + dang = -0.375_wp * (r2jk**3 + r2jk**2*(r2ik + r2ij)& + & + r2jk * (3.0_wp * r2ik**2 + 2.0_wp * r2ik * r2ij& + & + 3.0_wp * r2ij**2)& + & - 5.0_wp * (r2ik - r2ij)**2 * (r2ik + r2ij)) / r5 +- dGjk(:) = c9 * (-dang * fdmp + ang * dfdmp) / r2jk * vjk ++ dGjk(:) = sw * c9 * (-dang * fdmp + ang * dfdmp) / r2jk * vjk & ++ & - dE0 * dswjkdr / rjk * swij * swik * vjk + +- dE = rr * c9 * triple ++ dE = dE0 * triple * sw + dE_third = dE * third +- energy_local(iat) = energy_local(iat) - dE_third +- energy_local(jat) = energy_local(jat) - dE_third +- energy_local(kat) = energy_local(kat) - dE_third ++ energy(iat) = energy(iat) - dE_third ++ energy(jat) = energy(jat) - dE_third ++ energy(kat) = energy(kat) - dE_third + +- gradient_local(:, iat) = gradient_local(:, iat) & ++ gradient(:, iat) = gradient(:, iat) & + & - (dGij + dGik) * triple +- gradient_local(:, jat) = gradient_local(:, jat) & ++ gradient(:, jat) = gradient(:, jat) & + & + (dGij - dGjk) * triple +- gradient_local(:, kat) = gradient_local(:, kat) & ++ gradient(:, kat) = gradient(:, kat) & + & + (dGik + dGjk) * triple + + dS(:, :) = spread(dGij, 1, 3) * spread(vij, 2, 3)& + & + spread(dGik, 1, 3) * spread(vik, 2, 3)& + & + spread(dGjk, 1, 3) * spread(vjk, 2, 3) + +- sigma_local(:, :) = sigma_local + dS * triple ++ sigma(:, :) = sigma(:, :) + dS * triple + +- dEdcn_local(iat) = dEdcn_local(iat) - dE * 0.5_wp & ++ dEdcn(iat) = dEdcn(iat) - dE * 0.5_wp & + & * (dc6dcn(iat, jat) / c6ij + dc6dcn(iat, kat) / c6ik) +- dEdcn_local(jat) = dEdcn_local(jat) - dE * 0.5_wp & ++ dEdcn(jat) = dEdcn(jat) - dE * 0.5_wp & + & * (dc6dcn(jat, iat) / c6ij + dc6dcn(jat, kat) / c6jk) +- dEdcn_local(kat) = dEdcn_local(kat) - dE * 0.5_wp & ++ dEdcn(kat) = dEdcn(kat) - dE * 0.5_wp & + & * (dc6dcn(kat, iat) / c6ik + dc6dcn(kat, jat) / c6jk) + +- dEdq_local(iat) = dEdq_local(iat) - dE * 0.5_wp & ++ dEdq(iat) = dEdq(iat) - dE * 0.5_wp & + & * (dc6dq(iat, jat) / c6ij + dc6dq(iat, kat) / c6ik) +- dEdq_local(jat) = dEdq_local(jat) - dE * 0.5_wp & ++ dEdq(jat) = dEdq(jat) - dE * 0.5_wp & + & * (dc6dq(jat, iat) / c6ij + dc6dq(jat, kat) / c6jk) +- dEdq_local(kat) = dEdq_local(kat) - dE * 0.5_wp & ++ dEdq(kat) = dEdq(kat) - dE * 0.5_wp & + & * (dc6dq(kat, iat) / c6ik + dc6dq(kat, jat) / c6jk) + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_atm_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- dEdq(:) = dEdq(:) + dEdq_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_atm_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(dEdq_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_atm_dispersion_derivs + +diff --git a/src/dftd4/damping/rational.f90 b/src/dftd4/damping/rational.f90 +index 04e9241..4fbb790 100644 +--- a/src/dftd4/damping/rational.f90 ++++ b/src/dftd4/damping/rational.f90 +@@ -57,6 +57,84 @@ module dftd4_damping_rational + contains + + ++subroutine get_disp2_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ width = 0.05_wp ++ ++ call get_environment_variable("DFTD4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("TBLITE_D4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ end if ++ active = width > 0.0_wp .and. width < cutoff ++ if (active) inner = cutoff - width ++ ++end subroutine get_disp2_switch ++ ++ ++subroutine get_disp3_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ active = .false. ++ ++ call get_environment_variable("DFTD4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0) then ++ call get_environment_variable("TBLITE_D4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0) then ++ read(env, *, iostat=io) width ++ if (io == 0 .and. width > 0.0_wp .and. width < cutoff) then ++ inner = cutoff - width ++ active = .true. ++ end if ++ end if ++ ++end subroutine get_disp3_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: x, width ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp*x**2*(1.0_wp - x)**2 / width ++ end if ++ ++end subroutine smooth_cutoff ++ ++ + !> Evaluation of the dispersion energy expression + subroutine get_dispersion2(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6dq, & + & energy, dEdcn, dEdq, gradient, sigma) +@@ -142,22 +220,17 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, r4r2, c6, energy) + real(wp), intent(inout) :: energy(:) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE +- +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, & +- !$omp& t6, t8, edisp, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t6, t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -169,27 +242,28 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, r4r2, c6, energy) + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -238,32 +312,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6 + real(wp), intent(inout) :: sigma(:, :) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, d6, d8, edisp, gdisp ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: d6, d8, edisp0, gdisp0, edisp, gdisp, sw, dswdr + real(wp) :: dE, dG(3), dS(3, 3) + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: dEdq_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) +- + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, dc6dcn, dc6dq, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) & ++ !$omp reduction(+:energy, gradient, sigma, dEdcn, dEdq) & ++ !$omp shared(mol, self, c6, dc6dcn, dc6dq, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, t8, & +- !$omp& d6, d8, edisp, gdisp, dE, dG, dS) & +- !$omp shared(energy, gradient, sigma, dEdcn, dEdq) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local, & +- !$omp& dEdq_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(dEdq_local(size(dEdq, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& d6, d8, edisp0, gdisp0, edisp, gdisp, dE, dG, dS, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -275,6 +336,15 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6 + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ r = 1.0_wp ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) +@@ -282,42 +352,30 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6 + d6 = -6*r2**2*t6**2 + d8 = -8*r2**3*t8**2 + +- edisp = self%s6*t6 + self%s8*rrij*t8 +- gdisp = self%s6*d6 + self%s8*rrij*d8 ++ edisp0 = self%s6*t6 + self%s8*rrij*t8 ++ gdisp0 = self%s6*d6 + self%s8*rrij*d8 ++ edisp = sw * edisp0 ++ gdisp = sw * gdisp0 + dswdr * edisp0 / r + + dE = -c6ij*edisp * 0.5_wp + dG(:) = -c6ij*gdisp*vec + dS(:, :) = spread(dG, 1, 3) * spread(vec, 2, 3) * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- dEdq_local(iat) = dEdq_local(iat) - dc6dq(iat, jat) * edisp +- sigma_local(:, :) = sigma_local + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ dEdq(iat) = dEdq(iat) - dc6dq(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- dEdq_local(jat) = dEdq_local(jat) - dc6dq(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ dEdq(jat) = dEdq(jat) - dc6dq(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- dEdq(:) = dEdq(:) + dEdq_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(dEdq_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -399,23 +457,18 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, r4r2, c6, energy) + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE +- +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + if (abs(self%s6) < epsilon(1.0_wp) .and. abs(self%s8) < epsilon(1.0_wp)) return + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, & +- !$omp& t6, t8, edisp, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t6, t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -427,27 +480,28 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, r4r2, c6, energy) + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 + +@@ -478,27 +532,24 @@ subroutine get_pairwise_dispersion3(self, mol, trans, cutoff, r4r2, c6, energy) + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang +- real(wp) :: cutoff2, c9, dE, alp3 +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, alp3, swij, swjk, swik, dswdr, sw + + if (abs(self%s9) < epsilon(1.0_wp)) return + cutoff2 = cutoff*cutoff + alp3 = self%alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, r4r2, cutoff2, alp3, self) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, trans, c6, r4r2, cutoff2, cutoff, cutoff_inner, & ++ !$omp& use_switch, alp3, self) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, ang, c9, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang, c9, dE, & ++ !$omp& swij, swjk, swik, dswdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -509,6 +560,8 @@ subroutine get_pairwise_dispersion3(self, mol, trans, cutoff, r4r2, c6, energy) + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -522,12 +575,17 @@ subroutine get_pairwise_dispersion3(self, mol, trans, cutoff, r4r2, c6, energy) + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswdr) + + ! vjk(:) = mol%xyz(:, kat) + trans(:, ktr) + ! - mol%xyz(:, jat) - trans(:, jtr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswdr) ++ sw = swij * swik * swjk + + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) +@@ -540,24 +598,18 @@ subroutine get_pairwise_dispersion3(self, mol, trans, cutoff, r4r2, c6, energy) + + rr = ang*fdmp + +- dE = rr * c9 * triple * sixth +- energy_local(jat, iat) = energy_local(jat, iat) - dE +- energy_local(kat, iat) = energy_local(kat, iat) - dE +- energy_local(iat, jat) = energy_local(iat, jat) - dE +- energy_local(kat, jat) = energy_local(kat, jat) - dE +- energy_local(iat, kat) = energy_local(iat, kat) - dE +- energy_local(jat, kat) = energy_local(jat, kat) - dE ++ dE = rr * c9 * triple * sixth * sw ++ energy(jat, iat) = energy(jat, iat) - dE ++ energy(kat, iat) = energy(kat, iat) - dE ++ energy(iat, jat) = energy(iat, jat) - dE ++ energy(kat, jat) = energy(kat, jat) - dE ++ energy(iat, kat) = energy(iat, kat) - dE ++ energy(jat, kat) = energy(jat, kat) - dE + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion3_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion3_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion3 diff --git a/tools/toolchain/scripts/stage8/install_dftd4.sh b/tools/toolchain/scripts/stage8/install_dftd4.sh index 4f94bbb985..68b3757db7 100755 --- a/tools/toolchain/scripts/stage8/install_dftd4.sh +++ b/tools/toolchain/scripts/stage8/install_dftd4.sh @@ -6,8 +6,8 @@ [ "${BASH_SOURCE[0]}" ] && SCRIPT_NAME="${BASH_SOURCE[0]}" || SCRIPT_NAME=$0 SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_NAME")/.." && pwd -P)" -dftd4_ver="4.0.2" -dftd4_sha256="ed4a6a3ba0a89b8d6825bf11724dee647fd8ee6272e7822e0cbd9847994eb872" +dftd4_ver="4.1.1" +dftd4_sha256="c8e6388d7d7d748dbcf91117f35aa50108492d4fd2266d60782cf85a16651887" source "${SCRIPT_DIR}"/common_vars.sh source "${SCRIPT_DIR}"/tool_kit.sh @@ -34,24 +34,46 @@ case "$with_dftd4" in if verify_checksums "${install_lock_file}"; then echo "dftd4-${dftd4_ver} is already installed, skipping it." else - retrieve_package "${dftd4_sha256}" "dftd4-${dftd4_ver}-source.tar.xz" + if ! [ -f "dftd4-${dftd4_ver}.tar.xz" ]; then + if ! download_pkg_from_cp2k_org "${dftd4_sha256}" "dftd4-${dftd4_ver}.tar.xz"; then + download_pkg_from_urlpath "${dftd4_sha256}" "dftd4-${dftd4_ver}.tar.xz" \ + "https://github.com/dftd4/dftd4/releases/download/v${dftd4_ver}" + fi + elif ! checksum "${dftd4_sha256}" "dftd4-${dftd4_ver}.tar.xz"; then + echo "dftd4-${dftd4_ver}.tar.xz is found but checksum is wrong; delete and re-download" + rm -vf "dftd4-${dftd4_ver}.tar.xz" + if ! download_pkg_from_cp2k_org "${dftd4_sha256}" "dftd4-${dftd4_ver}.tar.xz"; then + download_pkg_from_urlpath "${dftd4_sha256}" "dftd4-${dftd4_ver}.tar.xz" \ + "https://github.com/dftd4/dftd4/releases/download/v${dftd4_ver}" + fi + else + echo "dftd4-${dftd4_ver}.tar.xz is found and checksum is right" + fi echo "Installing from scratch into ${pkg_install_dir}" [ -d dftd4-${dftd4_ver} ] && rm -rf dftd4-${dftd4_ver} - tar -xJf dftd4-${dftd4_ver}-source.tar.xz + tar -xJf dftd4-${dftd4_ver}.tar.xz cd dftd4-${dftd4_ver} + patch -l -p1 < "${SCRIPT_DIR}/stage8/dftd4-${dftd4_ver}-gradient-fixes.patch" \ + > dftd4_gradient_fixes.patch.log 2>&1 || tail_excerpt dftd4_gradient_fixes.patch.log mkdir build && cd build CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:${OPENBLAS_ROOT}" cmake \ -DCMAKE_INSTALL_PREFIX="${pkg_install_dir}" \ -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_VERBOSE_MAKEFILE=ON \ + -Ddftd4-dependency-method=subproject \ + -DMCTC-LIB_FIND_METHOD=subproject \ + -DMULTICHARGE_FIND_METHOD=subproject \ .. \ > cmake.log 2>&1 || tail_excerpt cmake.log - make install -j $(get_nprocs) >> make.log 2>&1 || tail_excerpt build.log + cmake --build . --target mctc-convert mstore-fortranize mstore-info multicharge-exe dftd4-exe \ + -- -j $(get_nprocs) > make.log 2>&1 || tail_excerpt make.log + cmake --install . >> make.log 2>&1 || tail_excerpt make.log cd .. fi - write_checksums "${install_lock_file}" "${SCRIPT_DIR}/stage8/$(basename ${SCRIPT_NAME})" + write_checksums "${install_lock_file}" "${SCRIPT_DIR}/stage8/$(basename ${SCRIPT_NAME})" \ + "${SCRIPT_DIR}/stage8/dftd4-${dftd4_ver}-gradient-fixes.patch" ;; __SYSTEM__) diff --git a/tools/toolchain/scripts/stage8/install_tblite.sh b/tools/toolchain/scripts/stage8/install_tblite.sh index 7f1df89471..94414faac4 100755 --- a/tools/toolchain/scripts/stage8/install_tblite.sh +++ b/tools/toolchain/scripts/stage8/install_tblite.sh @@ -8,6 +8,14 @@ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT_NAME")/.." && pwd -P)" tblite_ver="0.5.0" tblite_sha256="e8a70b72ed0a0db0621c7958c63667a9cd008c97c868a4a417ff1bc262052ea8" +tblite_dftd4_ver="3.7.0" +tblite_multicharge_ver="0.3.0" +tblite_sdftd3_ver="1.3.2" +tblite_sdftd3_sha256="bbf6aaa23332a7217a6dfc5c3ca8dc74f949c4cb6e4dccbadf32fa21fe8bb0d7" +tblite_mctc_ver="0.5.1" +tblite_mctc_sha256="c0b3ed75546ca6382f18b5569ce3f80c916537aaf02b208662bce6eb53338350" +tblite_tomlf_ver="0.5.0" +tblite_tomlf_sha256="a9e546221d788416fa6ca8d8550a79d1adf983a2a67b5c9ef57ae79fb02c9df0" source "${SCRIPT_DIR}"/common_vars.sh source "${SCRIPT_DIR}"/tool_kit.sh @@ -20,6 +28,22 @@ source "${INSTALLDIR}"/toolchain.env ! [ -d "${BUILDDIR}" ] && mkdir -p "${BUILDDIR}" cd "${BUILDDIR}" +retrieve_github_archive() { + local __sha256="$1" + local __filename="$2" + local __urlpath="$3" + local __outfile="$4" + if ! [ -f "${__outfile}" ]; then + download_pkg_from_urlpath "${__sha256}" "${__filename}" "${__urlpath}" "${__outfile}" + elif ! checksum "${__sha256}" "${__outfile}"; then + echo "${__outfile} is found but checksum is wrong; delete and re-download" + rm -vf "${__outfile}" + download_pkg_from_urlpath "${__sha256}" "${__filename}" "${__urlpath}" "${__outfile}" + else + echo "${__outfile} is found and checksum is right" + fi +} + case "$with_tblite" in __DONTUSE__) ;; @@ -35,19 +59,40 @@ case "$with_tblite" in echo "tblite-${tblite_ver} is already installed, skipping it." else retrieve_package "${tblite_sha256}" "tblite-${tblite_ver}.tar.xz" + retrieve_github_archive "${tblite_sdftd3_sha256}" "v${tblite_sdftd3_ver}.tar.gz" \ + "https://github.com/dftd3/simple-dftd3/archive/refs/tags" \ + "simple-dftd3-${tblite_sdftd3_ver}.tar.gz" + retrieve_github_archive "${tblite_mctc_sha256}" "v${tblite_mctc_ver}.tar.gz" \ + "https://github.com/grimme-lab/mctc-lib/archive/refs/tags" \ + "mctc-lib-${tblite_mctc_ver}.tar.gz" + retrieve_github_archive "${tblite_tomlf_sha256}" "v${tblite_tomlf_ver}.tar.gz" \ + "https://github.com/toml-f/toml-f/archive/refs/tags" \ + "toml-f-${tblite_tomlf_ver}.tar.gz" echo "Installing from scratch into ${pkg_install_dir}" [ -d tblite-${tblite_ver} ] && rm -rf tblite-${tblite_ver} tar -xJf tblite-${tblite_ver}.tar.xz cd tblite-${tblite_ver} + # tblite 0.5.0 is still the latest release, but newer compatible + # subprojects can be used for s-D3, mctc-lib, and toml-f. + rm -rf subprojects/s-dftd3 subprojects/mctc-lib subprojects/toml-f + mkdir -p subprojects/s-dftd3 subprojects/mctc-lib subprojects/toml-f + tar -xzf ../simple-dftd3-${tblite_sdftd3_ver}.tar.gz -C subprojects/s-dftd3 --strip-components=1 + tar -xzf ../mctc-lib-${tblite_mctc_ver}.tar.gz -C subprojects/mctc-lib --strip-components=1 + tar -xzf ../toml-f-${tblite_tomlf_ver}.tar.gz -C subprojects/toml-f --strip-components=1 + patch -l -d subprojects/s-dftd3 -p1 < "${SCRIPT_DIR}/stage8/simple-dftd3-${tblite_sdftd3_ver}-gradient-fixes.patch" \ + > simple_dftd3_gradient_fixes.patch.log 2>&1 || tail_excerpt simple_dftd3_gradient_fixes.patch.log # Interim fix for tblite-0.5.0.tar.xz: the subprojects are found in order # specified by tblite-0.5.0/CMakeLists.txt as # mctc-lib, mstore, toml-f (, test-drive), dft-d4 (, multicharge), s-dftd3. # Despite all subprojects already included in the package, test-drive and # multicharge cannot be located, necessitating separate downloads from # github repositories. Two soft links are created to resolve this issue. - ln -s ${PWD}/subprojects/test-drive ${PWD}/subprojects/toml-f/subprojects/test-drive - ln -s ${PWD}/subprojects/multicharge ${PWD}/subprojects/dftd4/subprojects/multicharge + mkdir -p ${PWD}/subprojects/toml-f/subprojects ${PWD}/subprojects/dftd4/subprojects + ln -sfn ${PWD}/subprojects/test-drive ${PWD}/subprojects/toml-f/subprojects/test-drive + ln -sfn ${PWD}/subprojects/multicharge ${PWD}/subprojects/dftd4/subprojects/multicharge # See https://github.com/tblite/tblite/issues/313 for the full story. + patch -p1 < "${SCRIPT_DIR}/stage8/tblite-0.5.0-gradient-fixes.patch" \ + > tblite_gradient_fixes.patch.log 2>&1 || tail_excerpt tblite_gradient_fixes.patch.log rm -Rf build mkdir build @@ -57,13 +102,22 @@ case "$with_tblite" in -DCMAKE_INSTALL_PREFIX="${pkg_install_dir}" \ -DCMAKE_INSTALL_LIBDIR=lib \ -DCMAKE_VERBOSE_MAKEFILE=ON \ + -DBUILD_TESTING=OFF \ + -DWITH_TESTS=OFF \ + -Dtblite-dependency-method=subproject \ + -DDFTD4_FIND_METHOD=subproject \ + -DMULTICHARGE_FIND_METHOD=subproject \ .. \ > cmake.log 2>&1 || tail_excerpt cmake.log - make install -j $(get_nprocs) > make.log 2>&1 || tail_excerpt make.log + cmake --build . --target mctc-convert mstore-fortranize mstore-info multicharge-exe dftd4-exe s-dftd3-exe tblite-exe \ + -- -j $(get_nprocs) > make.log 2>&1 || tail_excerpt make.log + cmake --install . >> make.log 2>&1 || tail_excerpt make.log cd .. fi - write_checksums "${install_lock_file}" "${SCRIPT_DIR}/stage8/$(basename ${SCRIPT_NAME})" + write_checksums "${install_lock_file}" "${SCRIPT_DIR}/stage8/$(basename ${SCRIPT_NAME})" \ + "${SCRIPT_DIR}/stage8/simple-dftd3-${tblite_sdftd3_ver}-gradient-fixes.patch" \ + "${SCRIPT_DIR}/stage8/tblite-0.5.0-gradient-fixes.patch" ;; __SYSTEM__) @@ -95,6 +149,11 @@ if [ "$with_tblite" != "__DONTUSE__" ]; then cat << EOF > "${BUILDDIR}/setup_tblite" export TBLITE_VER="${tblite_ver}" +export TBLITE_DFTD4_VER="${tblite_dftd4_ver}" +export TBLITE_MULTICHARGE_VER="${tblite_multicharge_ver}" +export TBLITE_SDFTD3_VER="${tblite_sdftd3_ver}" +export TBLITE_MCTC_VER="${tblite_mctc_ver}" +export TBLITE_TOMLF_VER="${tblite_tomlf_ver}" EOF TEMP_LOC=$(find ${pkg_install_dir}/include -name "tomlf.mod") diff --git a/tools/toolchain/scripts/stage8/simple-dftd3-1.3.2-gradient-fixes.patch b/tools/toolchain/scripts/stage8/simple-dftd3-1.3.2-gradient-fixes.patch new file mode 100644 index 0000000000..d01c492da9 --- /dev/null +++ b/tools/toolchain/scripts/stage8/simple-dftd3-1.3.2-gradient-fixes.patch @@ -0,0 +1,1408 @@ +diff --git a/src/dftd3/damping/atm.f90 b/src/dftd3/damping/atm.f90 +index b412ecc..6c5256b 100644 +--- a/src/dftd3/damping/atm.f90 ++++ b/src/dftd3/damping/atm.f90 +@@ -25,6 +25,61 @@ module dftd3_damping_atm + contains + + ++subroutine get_disp3_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ active = .false. ++ ++ call get_environment_variable("SDFTD3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("DFTD3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("TBLITE_D3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ if (io == 0 .and. width > 0.0_wp .and. width < cutoff) then ++ inner = cutoff - width ++ active = .true. ++ end if ++ end if ++ ++end subroutine get_disp3_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: width, x ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp * x**2 * (1.0_wp - x)**2 / width ++ end if ++ ++end subroutine smooth_cutoff ++ ++ + !> Evaluation of the dispersion energy expression + subroutine get_atm_dispersion(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, dc6dcn, & + & energy, dEdcn, gradient, sigma) +@@ -115,26 +170,23 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + real(wp), intent(inout) :: energy(:) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang +- real(wp) :: cutoff2, c9, dE, alp3 +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, alp3, swij, swjk, swik, dswdr, sw + + cutoff2 = cutoff*cutoff + alp3 = alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, s9, rs9, alp3, rvdw, cutoff2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, trans, c6, s9, rs9, alp3, rvdw, cutoff2, cutoff, & ++ !$omp& cutoff_inner, use_switch) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, ang, c9, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang, c9, dE, & ++ !$omp& swij, swjk, swik, dswdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -145,6 +197,8 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -158,9 +212,14 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswdr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswdr) ++ sw = swij * swik * swjk + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) + r3 = r2 * r1 +@@ -172,21 +231,15 @@ subroutine get_atm_dispersion_energy(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + + rr = ang*fdmp + +- dE = rr * c9 * triple / 3.0_wp +- energy_local(iat) = energy_local(iat) - dE +- energy_local(jat) = energy_local(jat) - dE +- energy_local(kat) = energy_local(kat) - dE ++ dE = rr * c9 * triple * sw / 3.0_wp ++ energy(iat) = energy(iat) - dE ++ energy(jat) = energy(jat) - dE ++ energy(kat) = energy(kat) - dE + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_atm_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_atm_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_atm_dispersion_energy + +@@ -235,34 +288,26 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + real(wp), intent(inout) :: sigma(:, :) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr, ic, jc +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang +- real(wp) :: cutoff2, c9, dE, dGij(3), dGjk(3), dGik(3), dS(3, 3) ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, dE0, dGij(3), dGjk(3), dGik(3), dS(3, 3) + real(wp) :: alp3, r0r1alp3 +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) ++ real(wp) :: swij, swjk, swik, dswijdr, dswjkdr, dswikdr, sw + + cutoff2 = cutoff*cutoff + alp3 = alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, s9, rs9, alp, alp3, rvdw, cutoff2, dc6dcn) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & ++ !$omp shared(mol, trans, c6, s9, rs9, alp, alp3, rvdw, cutoff2, cutoff, & ++ !$omp& cutoff_inner, use_switch, dc6dcn) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, ic, jc, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang, c9, dE, dGij, dGjk, & +- !$omp& dGik, dS, r0r1alp3) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, dfdmp, ang, dang, & ++ !$omp& c9, dE, dE0, dGij, dGjk, dGik, dS, r0r1alp3, swij, swjk, swik, & ++ !$omp& dswijdr, dswjkdr, dswikdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -273,6 +318,8 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswijdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -286,9 +333,14 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswikdr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswjkdr) ++ sw = swij * swik * swjk + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) + r3 = r2 * r1 +@@ -308,30 +360,34 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + & + r2ij * (3.0_wp * r2jk**2 + 2.0_wp * r2jk*r2ik& + & + 3.0_wp * r2ik**2)& + & - 5.0_wp * (r2jk - r2ik)**2 * (r2jk + r2ik)) / r5 +- dGij(:) = c9 * (-dang*fdmp + ang*dfdmp) / r2ij * vij ++ dE0 = rr * c9 ++ dGij(:) = sw * c9 * (-dang*fdmp + ang*dfdmp) / r2ij * vij & ++ & - dE0 * dswijdr / rij * swik * swjk * vij + + ! d/drik + dang = -0.375_wp * (r2ik**3 + r2ik**2 * (r2jk + r2ij)& + & + r2ik * (3.0_wp * r2jk**2 + 2.0_wp * r2jk * r2ij& + & + 3.0_wp * r2ij**2)& + & - 5.0_wp * (r2jk - r2ij)**2 * (r2jk + r2ij)) / r5 +- dGik(:) = c9 * (-dang * fdmp + ang * dfdmp) / r2ik * vik ++ dGik(:) = sw * c9 * (-dang * fdmp + ang * dfdmp) / r2ik * vik & ++ & - dE0 * dswikdr / rik * swij * swjk * vik + + ! d/drjk + dang = -0.375_wp * (r2jk**3 + r2jk**2*(r2ik + r2ij)& + & + r2jk * (3.0_wp * r2ik**2 + 2.0_wp * r2ik * r2ij& + & + 3.0_wp * r2ij**2)& + & - 5.0_wp * (r2ik - r2ij)**2 * (r2ik + r2ij)) / r5 +- dGjk(:) = c9 * (-dang * fdmp + ang * dfdmp) / r2jk * vjk ++ dGjk(:) = sw * c9 * (-dang * fdmp + ang * dfdmp) / r2jk * vjk & ++ & - dE0 * dswjkdr / rjk * swij * swik * vjk + +- dE = rr * c9 * triple +- energy_local(iat) = energy_local(iat) - dE/3.0_wp +- energy_local(jat) = energy_local(jat) - dE/3.0_wp +- energy_local(kat) = energy_local(kat) - dE/3.0_wp ++ dE = dE0 * triple * sw ++ energy(iat) = energy(iat) - dE/3.0_wp ++ energy(jat) = energy(jat) - dE/3.0_wp ++ energy(kat) = energy(kat) - dE/3.0_wp + +- gradient_local(:, iat) = gradient_local(:, iat) - (dGij + dGik) * triple +- gradient_local(:, jat) = gradient_local(:, jat) + (dGij - dGjk) * triple +- gradient_local(:, kat) = gradient_local(:, kat) + (dGik + dGjk) * triple ++ gradient(:, iat) = gradient(:, iat) - (dGij + dGik) * triple ++ gradient(:, jat) = gradient(:, jat) + (dGij - dGjk) * triple ++ gradient(:, kat) = gradient(:, kat) + (dGik + dGjk) * triple + + do ic = 1, 3 + do jc = 1, 3 +@@ -340,31 +396,19 @@ subroutine get_atm_dispersion_derivs(mol, trans, cutoff, s9, rs9, alp, rvdw, c6, + end do + end do + +- sigma_local(:, :) = sigma_local + dS * triple ++ sigma(:, :) = sigma(:, :) + dS * triple + +- dEdcn_local(iat) = dEdcn_local(iat) - dE * 0.5_wp & ++ dEdcn(iat) = dEdcn(iat) - dE * 0.5_wp & + & * (dc6dcn(iat, jat) / c6ij + dc6dcn(iat, kat) / c6ik) +- dEdcn_local(jat) = dEdcn_local(jat) - dE * 0.5_wp & ++ dEdcn(jat) = dEdcn(jat) - dE * 0.5_wp & + & * (dc6dcn(jat, iat) / c6ij + dc6dcn(jat, kat) / c6jk) +- dEdcn_local(kat) = dEdcn_local(kat) - dE * 0.5_wp & ++ dEdcn(kat) = dEdcn(kat) - dE * 0.5_wp & + & * (dc6dcn(kat, iat) / c6ik + dc6dcn(kat, jat) / c6jk) + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_atm_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_atm_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_atm_dispersion_derivs + +@@ -401,27 +445,24 @@ subroutine get_atm_pairwise_dispersion(mol, trans, cutoff, s9, rs9, alp, rvdw, c + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ logical :: use_switch ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang +- real(wp) :: cutoff2, c9, dE, alp3 +- +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, alp3, swij, swjk, swik, dswdr, sw + + if (abs(s9) < epsilon(1.0_wp)) return + cutoff2 = cutoff*cutoff + alp3 = alp / 3.0_wp ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, trans, c6, cutoff2, s9, rs9, alp3, rvdw) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, trans, c6, cutoff2, cutoff, cutoff_inner, use_switch, & ++ !$omp& s9, rs9, alp3, rvdw) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, ang, c9, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang, c9, dE, & ++ !$omp& swij, swjk, swik, dswdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -432,6 +473,8 @@ subroutine get_atm_pairwise_dispersion(mol, trans, cutoff, s9, rs9, alp, rvdw, c + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -445,9 +488,14 @@ subroutine get_atm_pairwise_dispersion(mol, trans, cutoff, s9, rs9, alp, rvdw, c + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswdr) + vjk(:) = vik(:) - vij(:) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswdr) ++ sw = swij * swik * swjk + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) + r3 = r2 * r1 +@@ -459,24 +507,18 @@ subroutine get_atm_pairwise_dispersion(mol, trans, cutoff, s9, rs9, alp, rvdw, c + + rr = ang*fdmp + +- dE = rr * c9 * triple / 6.0_wp +- energy_local(jat, iat) = energy_local(jat, iat) - dE +- energy_local(kat, iat) = energy_local(kat, iat) - dE +- energy_local(iat, jat) = energy_local(iat, jat) - dE +- energy_local(kat, jat) = energy_local(kat, jat) - dE +- energy_local(iat, kat) = energy_local(iat, kat) - dE +- energy_local(jat, kat) = energy_local(jat, kat) - dE ++ dE = rr * c9 * triple * sw / 6.0_wp ++ energy(jat, iat) = energy(jat, iat) - dE ++ energy(kat, iat) = energy(kat, iat) - dE ++ energy(iat, jat) = energy(iat, jat) - dE ++ energy(kat, jat) = energy(kat, jat) - dE ++ energy(iat, kat) = energy(iat, kat) - dE ++ energy(jat, kat) = energy(jat, kat) - dE + end do + end do + end do + end do + end do +- !$omp end do +- !$omp critical (get_atm_pairwise_dispersion_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_atm_pairwise_dispersion_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_atm_pairwise_dispersion + +diff --git a/src/dftd3/damping/cso.f90 b/src/dftd3/damping/cso.f90 +index 046cdf2..189aad5 100644 +--- a/src/dftd3/damping/cso.f90 ++++ b/src/dftd3/damping/cso.f90 +@@ -165,20 +165,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + real(wp) :: c6ij, edisp, dE + real(wp) :: d6_6, a2r0ij, r4 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, rrij, r0ij, rij, d6, ef, & +- !$omp& sf, sig, t6, c6ij, edisp, dE, d6_6, a2r0ij, r4) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& sf, sig, t6, c6ij, edisp, dE, d6_6, a2r0ij, r4) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -205,19 +198,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_cso_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_cso_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -268,26 +255,13 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + real(wp) :: dE, dG(3), dS(3, 3) + real(wp) :: d6_6, a2r0ij, r4 + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & + !$omp shared(mol, self, c6, dc6dcn, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, ic, jc, vec, r2, rrij, r0ij, rij, d6, ef, & +- !$omp& sf, sig, t6, c6ij, dsig, dt6, edisp, gdisp, dE, dG, dS, d6_6, a2r0ij, r4) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& sf, sig, t6, c6ij, dsig, dt6, edisp, gdisp, dE, dG, dS, d6_6, a2r0ij, r4) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -324,31 +298,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + end do + end do + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- sigma_local(:, :) = sigma_local(:, :) + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local(:, :) + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_cso_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_cso_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -431,20 +393,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + real(wp) :: c6ij, edisp, dE + real(wp) :: d6_6, a2r0ij, r4 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, rrij, r0ij, rij, d6, ef, & +- !$omp& sf, sig, t6, c6ij, edisp, dE, d6_6, a2r0ij, r4) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& sf, sig, t6, c6ij, edisp, dE, d6_6, a2r0ij, r4) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -471,19 +426,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_cso_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_cso_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 + +diff --git a/src/dftd3/damping/mzero.f90 b/src/dftd3/damping/mzero.f90 +index d38a3a8..83ff770 100644 +--- a/src/dftd3/damping/mzero.f90 ++++ b/src/dftd3/damping/mzero.f90 +@@ -165,22 +165,15 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + real(wp) :: edisp, cutoff2, r0ij, rrij, c6ij, dE + real(wp) :: irs6r0, irs8r0, betr0 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, alp6, alp8, rvdw, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r1, r6, r8, t6, t8, f6, & +- !$omp& f8, edisp, r0ij, rrij, c6ij, dE, irs6r0, irs8r0, betr0) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& f8, edisp, r0ij, rrij, c6ij, dE, irs6r0, irs8r0, betr0) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -210,19 +203,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -272,29 +259,16 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + real(wp) :: edisp, gdisp, cutoff2, r0ij, rrij, c6ij, dE, dG(3), dS(3, 3) + real(wp) :: irs6r0, irs8r0, betr0, betr02rs6, betr02rs8 + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & + !$omp shared(mol, self, c6, dc6dcn, trans, cutoff2, alp6, alp8, rvdw, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, ic, jc, vec, r2, r1, r6, r8, t6, t8, d6, & + !$omp& d8, f6, f8, edisp, gdisp, r0ij, rrij, c6ij, dE, dG, dS, & +- !$omp& irs6r0, irs8r0, betr0, betr02rs6, betr02rs8) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& irs6r0, irs8r0, betr0, betr02rs6, betr02rs8) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -338,31 +312,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + end do + end do + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- sigma_local(:, :) = sigma_local + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -444,22 +406,15 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + real(wp) :: vec(3), r2, r1, r6, r8, t6, t8, f6, f8, alp6, alp8 + real(wp) :: edisp, cutoff2, r0ij, rrij, c6ij, dE + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, alp6, alp8, rvdw, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r1, r6, r8, t6, t8, f6, & +- !$omp& f8, edisp, r0ij, rrij, c6ij, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& f8, edisp, r0ij, rrij, c6ij, dE) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -486,19 +441,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 + +diff --git a/src/dftd3/damping/optimizedpower.f90 b/src/dftd3/damping/optimizedpower.f90 +index 6ef5c0b..2c6a797 100644 +--- a/src/dftd3/damping/optimizedpower.f90 ++++ b/src/dftd3/damping/optimizedpower.f90 +@@ -164,20 +164,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE, rb, ab + real(wp) :: r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, & +- !$omp& t8, edisp, dE, rb, ab, r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t8, edisp, dE, rb, ab, r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -205,19 +198,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -267,27 +254,14 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + real(wp) :: dE, dG(3), dS(3, 3), rb, ab + real(wp) :: r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4 + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & + !$omp shared(mol, self, c6, dc6dcn, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, ic, jc, vec, r2, r0ij, rrij, c6ij, t6, t8, & + !$omp& d6, d8, edisp, gdisp, dE, dG, dS, rb, ab, & +- !$omp& r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& r0ij2, r0ij6, r0ij8, abr0ij6, abr0ij8, r4) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -325,31 +299,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + end do + end do + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- sigma_local(:, :) = sigma_local + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -430,20 +392,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + integer :: iat, jat, izp, jzp, jtr + real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE, rb, ab + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) + + cutoff2 = cutoff*cutoff + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, & +- !$omp& t8, edisp, dE, rb, ab) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t8, edisp, dE, rb, ab) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -465,19 +420,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 + +diff --git a/src/dftd3/damping/rational.f90 b/src/dftd3/damping/rational.f90 +index 09fa105..c56396f 100644 +--- a/src/dftd3/damping/rational.f90 ++++ b/src/dftd3/damping/rational.f90 +@@ -56,6 +56,90 @@ module dftd3_damping_rational + contains + + ++subroutine get_disp2_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ width = 0.05_wp ++ ++ call get_environment_variable("SDFTD3_DISP2_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("DFTD3_DISP2_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("TBLITE_D3_DISP2_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ end if ++ active = width > 0.0_wp .and. width < cutoff ++ if (active) inner = cutoff - width ++ ++end subroutine get_disp2_switch ++ ++ ++subroutine get_disp3_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ active = .false. ++ ++ call get_environment_variable("SDFTD3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("DFTD3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("TBLITE_D3_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ if (io == 0 .and. width > 0.0_wp .and. width < cutoff) then ++ inner = cutoff - width ++ active = .true. ++ end if ++ end if ++ ++end subroutine get_disp3_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: width, x ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp * x**2 * (1.0_wp - x)**2 / width ++ end if ++ ++end subroutine smooth_cutoff ++ ++ + !> Create new rational damping model + subroutine new_rational_damping(self, param) + +@@ -159,23 +243,18 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + real(wp), intent(inout) :: energy(:) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + real(wp) :: r0ij2, r0ij6, r0ij8, r4 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, & +- !$omp& t8, edisp, dE, r0ij2, r0ij6, r0ij8, r4) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t8, edisp, dE, r0ij2, r0ij6, r0ij8, r4, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -190,28 +269,29 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + r4 = r2 * r2 + t6 = 1.0_wp/(r4 * r2 + r0ij6) + t8 = 1.0_wp/(r4 * r4 + r0ij8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -257,30 +337,20 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + real(wp), intent(inout) :: sigma(:, :) + + integer :: iat, jat, izp, jzp, jtr, ic, jc +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, d6, d8, edisp, gdisp ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: d6, d8, edisp0, gdisp0, edisp, gdisp, sw, dswdr + real(wp) :: dE, dG(3), dS(3, 3) + real(wp) :: r0ij2, r0ij6, r0ij8, r4 + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) +- + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, dc6dcn, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & ++ !$omp shared(mol, self, c6, dc6dcn, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, ic, jc, vec, r2, r0ij, rrij, c6ij, t6, t8, & +- !$omp& d6, d8, edisp, gdisp, dE, dG, dS, r0ij2, r0ij6, r0ij8, r4) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& d6, d8, edisp0, gdisp0, edisp, gdisp, dE, dG, dS, r0ij2, r0ij6, & ++ !$omp& r0ij8, r4, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -295,6 +365,15 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ r = 1.0_wp ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ end if + + r4 = r2 * r2 + t6 = 1.0_wp/(r4 * r2 + r0ij6) +@@ -303,8 +382,10 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + d6 = -6*r4*t6*t6 + d8 = -8*r4*r2*t8*t8 + +- edisp = self%s6*t6 + self%s8*rrij*t8 +- gdisp = self%s6*d6 + self%s8*rrij*d8 ++ edisp0 = self%s6*t6 + self%s8*rrij*t8 ++ gdisp0 = self%s6*d6 + self%s8*rrij*d8 ++ edisp = sw * edisp0 ++ gdisp = sw * gdisp0 + dswdr * edisp0 / r + + dE = -c6ij*edisp * 0.5_wp + dG(:) = -c6ij*gdisp*vec +@@ -314,31 +395,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + end do + end do + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- sigma_local(:, :) = sigma_local + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -417,22 +486,17 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE +- +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + +- !$omp parallel default(none) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, & +- !$omp& t8, edisp, dE) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -444,27 +508,28 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 + +diff --git a/src/dftd3/damping/zero.f90 b/src/dftd3/damping/zero.f90 +index 684506f..5d7eebf 100644 +--- a/src/dftd3/damping/zero.f90 ++++ b/src/dftd3/damping/zero.f90 +@@ -163,22 +163,15 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + real(wp) :: edisp, cutoff2, r0ij, rrij, c6ij, dE + real(wp) :: rs6r0, rs8r0 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, alp6, alp8, rvdw, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r1, r6, r8, t6, t8, f6, & +- !$omp& f8, edisp, r0ij, rrij, c6ij, dE, rs6r0, rs8r0) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& f8, edisp, r0ij, rrij, c6ij, dE, rs6r0, rs8r0) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -207,19 +200,13 @@ subroutine get_dispersion_energy(self, mol, trans, cutoff, rvdw, r4r2, c6, energ + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(iat) = energy_local(iat) + dE ++ energy(iat) = energy(iat) + dE + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE ++ energy(jat) = energy(jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_energy_) +- energy(:) = energy(:) + energy_local(:) +- !$omp end critical (get_dispersion_energy_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_dispersion_energy + +@@ -269,28 +256,15 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + real(wp) :: edisp, gdisp, cutoff2, r0ij, rrij, c6ij, dE, dG(3), dS(3, 3) + real(wp) :: rs6r0, rs8r0 + +- ! Thread-private arrays for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:) +- real(wp), allocatable :: dEdcn_local(:) +- real(wp), allocatable :: gradient_local(:, :) +- real(wp), allocatable :: sigma_local(:, :) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy, gradient, sigma, dEdcn) & + !$omp shared(mol, self, c6, dc6dcn, trans, cutoff2, alp6, alp8, r4r2, rvdw) & + !$omp private(iat, jat, izp, jzp, jtr, ic, jc, vec, r2, r1, r6, r8, t6, t8, d6, & +- !$omp& d8, f6, f8, edisp, gdisp, r0ij, rrij, c6ij, dE, dG, dS, rs6r0, rs8r0) & +- !$omp shared(energy, gradient, sigma, dEdcn) & +- !$omp private(energy_local, gradient_local, sigma_local, dEdcn_local) +- allocate(energy_local(size(energy, 1)), source=0.0_wp) +- allocate(dEdcn_local(size(dEdcn, 1)), source=0.0_wp) +- allocate(gradient_local(size(gradient, 1), size(gradient, 2)), source=0.0_wp) +- allocate(sigma_local(size(sigma, 1), size(sigma, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& d8, f6, f8, edisp, gdisp, r0ij, rrij, c6ij, dE, dG, dS, rs6r0, rs8r0) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -331,31 +305,19 @@ subroutine get_dispersion_derivs(self, mol, trans, cutoff, rvdw, r4r2, c6, dc6dc + end do + end do + +- energy_local(iat) = energy_local(iat) + dE +- dEdcn_local(iat) = dEdcn_local(iat) - dc6dcn(iat, jat) * edisp +- sigma_local(:, :) = sigma_local + dS ++ energy(iat) = energy(iat) + dE ++ dEdcn(iat) = dEdcn(iat) - dc6dcn(iat, jat) * edisp ++ sigma(:, :) = sigma(:, :) + dS + if (iat /= jat) then +- energy_local(jat) = energy_local(jat) + dE +- dEdcn_local(jat) = dEdcn_local(jat) - dc6dcn(jat, iat) * edisp +- gradient_local(:, iat) = gradient_local(:, iat) + dG +- gradient_local(:, jat) = gradient_local(:, jat) - dG +- sigma_local(:, :) = sigma_local + dS ++ energy(jat) = energy(jat) + dE ++ dEdcn(jat) = dEdcn(jat) - dc6dcn(jat, iat) * edisp ++ gradient(:, iat) = gradient(:, iat) + dG ++ gradient(:, jat) = gradient(:, jat) - dG ++ sigma(:, :) = sigma(:, :) + dS + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_dispersion_derivs_) +- energy(:) = energy(:) + energy_local(:) +- dEdcn(:) = dEdcn(:) + dEdcn_local(:) +- gradient(:, :) = gradient(:, :) + gradient_local(:, :) +- sigma(:, :) = sigma(:, :) + sigma_local(:, :) +- !$omp end critical (get_dispersion_derivs_) +- deallocate(energy_local) +- deallocate(dEdcn_local) +- deallocate(gradient_local) +- deallocate(sigma_local) +- !$omp end parallel + + end subroutine get_dispersion_derivs + +@@ -438,22 +400,15 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + real(wp) :: edisp, cutoff2, r0ij, rrij, c6ij, dE + real(wp) :: rs6r0, rs8r0 + +- ! Thread-private array for reduction +- ! Set to 0 explicitly as the shared variants are potentially non-zero (inout) +- real(wp), allocatable :: energy_local(:, :) + + cutoff2 = cutoff*cutoff + alp6 = self%alp + alp8 = self%alp + 2.0_wp + +- !$omp parallel default(none) & ++ !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & + !$omp shared(mol, self, c6, trans, cutoff2, alp6, alp8, rvdw, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r1, r6, r8, t6, t8, f6, & +- !$omp& f8, edisp, r0ij, rrij, c6ij, dE, rs6r0, rs8r0) & +- !$omp shared(energy) & +- !$omp private(energy_local) +- allocate(energy_local(size(energy, 1), size(energy, 2)), source=0.0_wp) +- !$omp do schedule(runtime) ++ !$omp& f8, edisp, r0ij, rrij, c6ij, dE, rs6r0, rs8r0) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -482,19 +437,13 @@ subroutine get_pairwise_dispersion2(self, mol, trans, cutoff, rvdw, r4r2, c6, en + + dE = -c6ij*edisp * 0.5_wp + +- energy_local(jat, iat) = energy_local(jat, iat) + dE ++ energy(jat, iat) = energy(jat, iat) + dE + if (iat /= jat) then +- energy_local(iat, jat) = energy_local(iat, jat) + dE ++ energy(iat, jat) = energy(iat, jat) + dE + end if + end do + end do + end do +- !$omp end do +- !$omp critical (get_pairwise_dispersion2_) +- energy(:, :) = energy(:, :) + energy_local(:, :) +- !$omp end critical (get_pairwise_dispersion2_) +- deallocate(energy_local) +- !$omp end parallel + + end subroutine get_pairwise_dispersion2 diff --git a/tools/toolchain/scripts/stage8/tblite-0.5.0-gradient-fixes.patch b/tools/toolchain/scripts/stage8/tblite-0.5.0-gradient-fixes.patch new file mode 100644 index 0000000000..c0e5715ba1 --- /dev/null +++ b/tools/toolchain/scripts/stage8/tblite-0.5.0-gradient-fixes.patch @@ -0,0 +1,521 @@ +--- a/src/tblite/xtb/h0.f90 2025-07-30 13:36:17 ++++ b/src/tblite/xtb/h0.f90 2026-05-05 12:29:02 +@@ -391,9 +391,9 @@ + itr = list%nltr(img+inl) + jzp = mol%id(jat) + js = bas%ish_at(jat) +- if (iat == jat) cycle + vec(:) = mol%xyz(:, iat) - mol%xyz(:, jat) - trans(:, itr) + r2 = vec(1)**2 + vec(2)**2 + vec(3)**2 ++ if (r2 <= epsilon(1.0_wp)) cycle + rr = sqrt(sqrt(r2) / (h0%rad(jzp) + h0%rad(izp))) + do ish = 1, bas%nsh_id(izp) + ii = bas%iao_sh(is+ish) +@@ -445,12 +445,22 @@ + dcnj = dcnj + dhdcnj * pmat(jj+jao, ii+iao, 1) * stmp(ij) + end do + end do +- dEdcn(iat) = dEdcn(iat) + dcni +- dEdcn(jat) = dEdcn(jat) + dcnj ++ if (iat == jat) then ++ dEdcn(iat) = dEdcn(iat) + 0.5_wp * (dcni + dcnj) ++ else ++ dEdcn(iat) = dEdcn(iat) + dcni ++ dEdcn(jat) = dEdcn(jat) + dcnj ++ end if + gradient(:, iat) = gradient(:, iat) + dG + gradient(:, jat) = gradient(:, jat) - dG +- sigma(:, :) = sigma + 0.5_wp * (spread(vec, 1, 3) * spread(dG, 2, 3) & +- + spread(dG, 1, 3) * spread(vec, 2, 3)) ++ if (iat == jat) then ++ sigma(:, :) = sigma + 0.25_wp * & ++ & (spread(vec, 1, 3) * spread(dG, 2, 3) & ++ & + spread(dG, 1, 3) * spread(vec, 2, 3)) ++ else ++ sigma(:, :) = sigma + 0.5_wp * (spread(vec, 1, 3) * spread(dG, 2, 3) & ++ & + spread(dG, 1, 3) * spread(vec, 2, 3)) ++ end if + + end do + end do +--- a/src/tblite/coulomb/multipole.f90 2025-07-30 13:36:17 ++++ b/src/tblite/coulomb/multipole.f90 2026-05-05 12:29:02 +@@ -931,9 +931,9 @@ + real(wp), intent(out) :: dg(3) + real(wp), intent(out) :: ds(3, 3) + +- integer :: itr ++ integer :: itr, a, b + real(wp) :: fac, vec(3), g2, gv, expk, alp2, sink, cosk, dpiqj, qidpj +- real(wp) :: qpiqj, qiqpj, dpiv, dpjv ++ real(wp) :: qpiqj, qiqpj, dpiv, dpjv, tiv(3), tjv(3) + + dg(:) = 0.0_wp + ds(:, :) = 0.0_wp +@@ -955,6 +955,12 @@ + dg(:) = dg - 2*vec*cosk * (dpiqj - qidpj) + ds(:, :) = ds + 2 * sink * (dpiqj - qidpj) & + & * ((2.0_wp/g2 + 0.5_wp/alp2) * spread(vec, 1, 3)*spread(vec, 2, 3) - unity) ++ do b = 1, 3 ++ do a = 1, 3 ++ ds(a, b) = ds(a, b) - sink*( & ++ & vec(a)*(qj*mi(b) - qi*mj(b)) + vec(b)*(qj*mi(a) - qi*mj(a))) ++ end do ++ end do + + dpiv = dot_product(mi, vec) + dpjv = dot_product(mj, vec) +@@ -962,15 +968,33 @@ + dg(:) = dg + vec*sink*dpiv*dpjv + ds(:, :) = ds + cosk * dpiv*dpjv & + & * ((2.0_wp/g2 + 0.5_wp/alp2) * spread(vec, 1, 3)*spread(vec, 2, 3) - unity) ++ do b = 1, 3 ++ do a = 1, 3 ++ ds(a, b) = ds(a, b) - 0.5_wp*cosk*( & ++ & vec(a)*(mi(b)*dpjv + mj(b)*dpiv) + vec(b)*(mi(a)*dpjv + mj(a)*dpiv)) ++ end do ++ end do + + qiqpj = qi*(tj(1)*vec(1)*vec(1) + tj(3)*vec(2)*vec(2) + tj(6)*vec(3)*vec(3) & + & + 2*tj(2)*vec(1)*vec(2) + 2*tj(4)*vec(1)*vec(3) + 2*tj(5)*vec(2)*vec(3)) + qpiqj = qj*(ti(1)*vec(1)*vec(1) + ti(3)*vec(2)*vec(2) + ti(6)*vec(3)*vec(3) & + & + 2*ti(2)*vec(1)*vec(2) + 2*ti(4)*vec(1)*vec(3) + 2*ti(5)*vec(2)*vec(3)) ++ tiv = [ti(1)*vec(1) + ti(2)*vec(2) + ti(4)*vec(3), & ++ & ti(2)*vec(1) + ti(3)*vec(2) + ti(5)*vec(3), & ++ & ti(4)*vec(1) + ti(5)*vec(2) + ti(6)*vec(3)] ++ tjv = [tj(1)*vec(1) + tj(2)*vec(2) + tj(4)*vec(3), & ++ & tj(2)*vec(1) + tj(3)*vec(2) + tj(5)*vec(3), & ++ & tj(4)*vec(1) + tj(5)*vec(2) + tj(6)*vec(3)] + + dg(:) = dg + vec * sink * (qiqpj + qpiqj) + ds(:, :) = ds + cosk * (qiqpj + qpiqj) & + & * ((2.0_wp/g2 + 0.5_wp/alp2) * spread(vec, 1, 3)*spread(vec, 2, 3) - unity) ++ do b = 1, 3 ++ do a = 1, 3 ++ ds(a, b) = ds(a, b) - cosk*( & ++ & vec(a)*(qi*tjv(b) + qj*tiv(b)) + vec(b)*(qi*tjv(a) + qj*tiv(a))) ++ end do ++ end do + end do + + end subroutine get_damat_sdq_rec_3d +@@ -1054,7 +1078,7 @@ + + de = de + 3.0_wp*(dpiqj - qidpj)*kdmp3*fdmp3*g3*(fdmp3/rr)*(rr*g1)**kdmp3 + dg(:) = dg + g_sd +- ds(:, :) = - 0.5_wp * (spread(vec, 1, 3) * spread(g_sd, 2, 3) & ++ ds(:, :) = ds - 0.5_wp * (spread(vec, 1, 3) * spread(g_sd, 2, 3) & + & + spread(g_sd, 1, 3) * spread(vec, 2, 3)) + + ! Dipole - dipole +@@ -1093,7 +1117,7 @@ + + de = de + 3.0_wp*edd*kdmp5*fdmp5*g5*(fdmp5/rr)*(rr*g1)**kdmp5 + dg(:) = dg + g_dd +- ds(:, :) = - 0.5_wp * (spread(vec, 1, 3) * spread(g_dd, 2, 3) & ++ ds(:, :) = ds - 0.5_wp * (spread(vec, 1, 3) * spread(g_dd, 2, 3) & + & + spread(g_dd, 1, 3) * spread(vec, 2, 3)) + + ! Charge - quadrupole +--- a/subprojects/dftd4/src/dftd4/damping/atm.f90 2024-08-29 15:40:10 ++++ b/subprojects/dftd4/src/dftd4/damping/atm.f90 2026-05-05 12:29:02 +@@ -326,9 +326,9 @@ + energy(jat) = energy(jat) - dE/3 + energy(kat) = energy(kat) - dE/3 + +- gradient(:, iat) = gradient(:, iat) - dGij - dGik +- gradient(:, jat) = gradient(:, jat) + dGij - dGjk +- gradient(:, kat) = gradient(:, kat) + dGik + dGjk ++ gradient(:, iat) = gradient(:, iat) + (-dGij - dGik) * triple ++ gradient(:, jat) = gradient(:, jat) + (+dGij - dGjk) * triple ++ gradient(:, kat) = gradient(:, kat) + (+dGik + dGjk) * triple + + dS(:, :) = spread(dGij, 1, 3) * spread(vij, 2, 3)& + & + spread(dGik, 1, 3) * spread(vik, 2, 3)& +--- a/subprojects/dftd4/src/dftd4/damping/rational.f90 2024-08-29 15:40:10 ++++ b/subprojects/dftd4/src/dftd4/damping/rational.f90 2026-05-05 12:29:02 +@@ -55,6 +55,84 @@ + contains + + ++subroutine get_disp2_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ width = 0.05_wp ++ ++ call get_environment_variable("DFTD4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("TBLITE_D4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ end if ++ active = width > 0.0_wp .and. width < cutoff ++ if (active) inner = cutoff - width ++ ++end subroutine get_disp2_switch ++ ++ ++subroutine get_disp3_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ active = .false. ++ ++ call get_environment_variable("DFTD4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0) then ++ call get_environment_variable("TBLITE_D4_DISP3_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0) then ++ read(env, *, iostat=io) width ++ if (io == 0 .and. width > 0.0_wp .and. width < cutoff) then ++ inner = cutoff - width ++ active = .true. ++ end if ++ end if ++ ++end subroutine get_disp3_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: x, width ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp*x**2*(1.0_wp - x)**2 / width ++ end if ++ ++end subroutine smooth_cutoff ++ ++ + !> Evaluation of the dispersion energy expression + subroutine get_dispersion2(self, mol, trans, cutoff, r4r2, c6, dc6dcn, dc6dq, & + & energy, dEdcn, dEdq, gradient, sigma) +@@ -140,14 +218,17 @@ + real(wp), intent(inout) :: energy(:) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + + !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, & +- !$omp& t6, t8, edisp, dE) ++ !$omp& t6, t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -159,11 +240,18 @@ + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +@@ -222,16 +310,19 @@ + real(wp), intent(inout) :: sigma(:, :) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, d6, d8, edisp, gdisp ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: d6, d8, edisp0, gdisp0, edisp, gdisp, sw, dswdr + real(wp) :: dE, dG(3), dS(3, 3) + + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + + !$omp parallel do schedule(runtime) default(none) & + !$omp reduction(+:energy, gradient, sigma, dEdcn, dEdq) & +- !$omp shared(mol, self, c6, dc6dcn, dc6dq, trans, cutoff2, r4r2) & ++ !$omp shared(mol, self, c6, dc6dcn, dc6dq, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, t6, t8, & +- !$omp& d6, d8, edisp, gdisp, dE, dG, dS) ++ !$omp& d6, d8, edisp0, gdisp0, edisp, gdisp, dE, dG, dS, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -243,6 +334,15 @@ + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ r = 1.0_wp ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) +@@ -250,8 +350,10 @@ + d6 = -6*r2**2*t6**2 + d8 = -8*r2**3*t8**2 + +- edisp = self%s6*t6 + self%s8*rrij*t8 +- gdisp = self%s6*d6 + self%s8*rrij*d8 ++ edisp0 = self%s6*t6 + self%s8*rrij*t8 ++ gdisp0 = self%s6*d6 + self%s8*rrij*d8 ++ edisp = sw * edisp0 ++ gdisp = sw * gdisp0 + dswdr * edisp0 / r + + dE = -c6ij*edisp * 0.5_wp + dG(:) = -c6ij*gdisp*vec +@@ -353,15 +455,18 @@ + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, izp, jzp, jtr +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, c6ij, t6, t8, edisp, dE ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, c6ij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + if (abs(self%s6) < epsilon(1.0_wp) .and. abs(self%s8) < epsilon(1.0_wp)) return + cutoff2 = cutoff*cutoff ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + + !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & +- !$omp shared(mol, self, c6, trans, cutoff2, r4r2) & ++ !$omp shared(mol, self, c6, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, c6ij, & +- !$omp& t6, t8, edisp, dE) ++ !$omp& t6, t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -373,11 +478,18 @@ + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = self%s6*t6 + self%s8*rrij*t8 ++ edisp = sw * (self%s6*t6 + self%s8*rrij*t8) + + dE = -c6ij*edisp * 0.5_wp + +@@ -418,18 +530,22 @@ + real(wp), intent(inout) :: energy(:, :) + + integer :: iat, jat, kat, izp, jzp, kzp, jtr, ktr +- real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple ++ real(wp) :: vij(3), vjk(3), vik(3), r2ij, r2jk, r2ik, rij, rjk, rik ++ real(wp) :: c6ij, c6jk, c6ik, triple + real(wp) :: r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang +- real(wp) :: cutoff2, c9, dE ++ real(wp) :: cutoff2, cutoff_inner, c9, dE, swij, swjk, swik, dswdr, sw ++ logical :: use_switch + + if (abs(self%s9) < epsilon(1.0_wp)) return + cutoff2 = cutoff*cutoff ++ call get_disp3_switch(cutoff, cutoff_inner, use_switch) + + !$omp parallel do schedule(runtime) default(none) reduction(+:energy) & +- !$omp shared(mol, trans, c6, r4r2, cutoff2, self) & ++ !$omp shared(mol, trans, c6, r4r2, cutoff2, cutoff, cutoff_inner, use_switch, self) & + !$omp private(iat, jat, kat, izp, jzp, kzp, jtr, ktr, vij, vjk, vik, & +- !$omp& r2ij, r2jk, r2ik, c6ij, c6jk, c6ik, triple, r0ij, r0jk, r0ik, r0, & +- !$omp& r1, r2, r3, r5, rr, fdmp, ang, c9, dE) ++ !$omp& r2ij, r2jk, r2ik, rij, rjk, rik, c6ij, c6jk, c6ik, triple, & ++ !$omp& r0ij, r0jk, r0ik, r0, r1, r2, r3, r5, rr, fdmp, ang, c9, dE, & ++ !$omp& swij, swjk, swik, dswdr, sw) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -440,6 +556,8 @@ + vij(:) = mol%xyz(:, jat) + trans(:, jtr) - mol%xyz(:, iat) + r2ij = vij(1)*vij(1) + vij(2)*vij(2) + vij(3)*vij(3) + if (r2ij > cutoff2 .or. r2ij < epsilon(1.0_wp)) cycle ++ rij = sqrt(r2ij) ++ call smooth_cutoff(rij, cutoff, cutoff_inner, use_switch, swij, dswdr) + do kat = 1, jat + kzp = mol%id(kat) + c6ik = c6(kat, iat) +@@ -453,10 +571,15 @@ + vik(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, iat) + r2ik = vik(1)*vik(1) + vik(2)*vik(2) + vik(3)*vik(3) + if (r2ik > cutoff2 .or. r2ik < epsilon(1.0_wp)) cycle ++ rik = sqrt(r2ik) ++ call smooth_cutoff(rik, cutoff, cutoff_inner, use_switch, swik, dswdr) + vjk(:) = mol%xyz(:, kat) + trans(:, ktr) - mol%xyz(:, jat) & + & - trans(:, jtr) + r2jk = vjk(1)*vjk(1) + vjk(2)*vjk(2) + vjk(3)*vjk(3) + if (r2jk > cutoff2 .or. r2jk < epsilon(1.0_wp)) cycle ++ rjk = sqrt(r2jk) ++ call smooth_cutoff(rjk, cutoff, cutoff_inner, use_switch, swjk, dswdr) ++ sw = swij * swik * swjk + r2 = r2ij*r2ik*r2jk + r1 = sqrt(r2) + r3 = r2 * r1 +@@ -468,7 +591,7 @@ + + rr = ang*fdmp + +- dE = rr * c9 * triple/6 ++ dE = rr * c9 * triple * sw/6 + energy(jat, iat) = energy(jat, iat) - dE + energy(kat, iat) = energy(kat, iat) - dE + energy(iat, jat) = energy(iat, jat) - dE +--- a/src/tblite/disp/d4.f90 2025-07-30 13:36:17 ++++ b/src/tblite/disp/d4.f90 2026-05-05 12:29:02 +@@ -66,8 +66,58 @@ + + + contains ++ ++ ++subroutine get_disp2_switch(cutoff, inner, active) ++ ++ real(wp), intent(in) :: cutoff ++ real(wp), intent(out) :: inner ++ logical, intent(out) :: active ++ ++ character(len=64) :: env ++ integer :: stat, io ++ real(wp) :: width ++ ++ inner = cutoff ++ width = 0.05_wp ++ ++ call get_environment_variable("TBLITE_D4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ if (stat /= 0 .or. len_trim(env) == 0) then ++ call get_environment_variable("DFTD4_DISP2_SMOOTH_WIDTH", env, status=stat) ++ end if ++ if (stat == 0 .and. len_trim(env) > 0) then ++ read(env, *, iostat=io) width ++ end if ++ active = width > 0.0_wp .and. width < cutoff ++ if (active) inner = cutoff - width ++ ++end subroutine get_disp2_switch ++ ++ ++pure subroutine smooth_cutoff(r, cutoff, inner, active, sw, dswdr) ++ ++ real(wp), intent(in) :: r, cutoff, inner ++ logical, intent(in) :: active ++ real(wp), intent(out) :: sw, dswdr ++ ++ real(wp) :: x, width ++ ++ if (.not. active .or. r <= inner) then ++ sw = 1.0_wp ++ dswdr = 0.0_wp ++ else if (r >= cutoff) then ++ sw = 0.0_wp ++ dswdr = 0.0_wp ++ else ++ width = cutoff - inner ++ x = (cutoff - r) / width ++ sw = x**3 * (10.0_wp + x*(-15.0_wp + 6.0_wp*x)) ++ dswdr = -30.0_wp*x**2*(1.0_wp - x)**2 / width ++ end if + ++end subroutine smooth_cutoff + ++ + !> Create a new instance of a self-consistent D4 dispersion correction + subroutine new_d4_dispersion(self, mol, s6, s8, a1, a2, s9) + !> Instance of the dispersion correction +@@ -252,15 +302,18 @@ + real(wp), intent(out) :: dispmat(:, :, :, :) + + integer :: iat, jat, izp, jzp, jtr, iref, jref +- real(wp) :: vec(3), r2, cutoff2, r0ij, rrij, t6, t8, edisp, dE ++ logical :: use_switch ++ real(wp) :: vec(3), r2, r, cutoff2, cutoff_inner, r0ij, rrij, t6, t8 ++ real(wp) :: edisp, dE, sw, dswdr + + dispmat(:, :, :, :) = 0.0_wp + cutoff2 = cutoff**2 ++ call get_disp2_switch(cutoff, cutoff_inner, use_switch) + + !$omp parallel do schedule(runtime) default(none) & +- !$omp shared(mol, param, disp, trans, cutoff2, r4r2, dispmat) & ++ !$omp shared(mol, param, disp, trans, cutoff, cutoff2, cutoff_inner, use_switch, r4r2, dispmat) & + !$omp private(iat, jat, izp, jzp, jtr, vec, r2, r0ij, rrij, & +- !$omp& t6, t8, edisp, dE) ++ !$omp& t6, t8, edisp, dE, r, sw, dswdr) + do iat = 1, mol%nat + izp = mol%id(iat) + do jat = 1, iat +@@ -272,11 +325,18 @@ + vec(:) = mol%xyz(:, iat) - (mol%xyz(:, jat) + trans(:, jtr)) + r2 = vec(1)*vec(1) + vec(2)*vec(2) + vec(3)*vec(3) + if (r2 > cutoff2 .or. r2 < epsilon(1.0_wp)) cycle ++ if (use_switch) then ++ r = sqrt(r2) ++ call smooth_cutoff(r, cutoff, cutoff_inner, use_switch, sw, dswdr) ++ if (sw <= 0.0_wp) cycle ++ else ++ sw = 1.0_wp ++ end if + + t6 = 1.0_wp/(r2**3 + r0ij**6) + t8 = 1.0_wp/(r2**4 + r0ij**8) + +- edisp = param%s6*t6 + param%s8*rrij*t8 ++ edisp = sw * (param%s6*t6 + param%s8*rrij*t8) + + dE = dE - edisp + end do