From 6747ae7caf388e71b21bf3cbc186f85500fc1016 Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Wed, 13 Mar 2024 19:56:26 +0000 Subject: [PATCH 1/6] Update git submodules --- .gitmodules | 13 +++++++------ README.md | 12 ++++++------ subprojects/.gitignore | 2 +- subprojects/README.md | 17 +++++++++-------- subprojects/tblite | 2 +- subprojects/tblite.wrap | 4 ++-- subprojects/test-drive | 1 + 7 files changed, 27 insertions(+), 24 deletions(-) create mode 160000 subprojects/test-drive diff --git a/.gitmodules b/.gitmodules index a7ced99f..30a29d29 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,13 +10,14 @@ path = subprojects/gfnff url = https://github.com/pprcht/gfnff.git branch = master -[submodule "subprojects/tblite"] - path = subprojects/tblite -# url = https://github.com/tblite/tblite.git -# branch = main - url = https://github.com/pprcht/tblite.git - branch = ompleak [submodule "subprojects/lwoniom"] path = subprojects/lwoniom url = https://github.com/crest-lab/lwoniom branch = main +[submodule "subprojects/test-drive"] + path = subprojects/test-drive + url = https://github.com/fortran-lang/test-drive.git +[submodule "subprojects/tblite"] + path = subprojects/tblite + url = https://github.com/tblite/tblite.git + branch = main diff --git a/README.md b/README.md index 07ad9188..5a770b4c 100644 --- a/README.md +++ b/README.md @@ -61,12 +61,12 @@ Working and tested builds of CREST (mostly on Ubuntu 20.04 LTS): | Build System | Compiler | Linear Algebra Backend | Build type | Status | |--------------|----------|------------------------|:--------------:|:----------:| -| CMake | GNU (gcc 10.3.0) | [OpenBLAS](https://github.com/xianyi/OpenBLAS) (with OpenMP) | dynamic | ✅ | -| CMake | GNU (gcc 10.3.0) | [MKL shared (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | -| CMake | GNU (gcc 9.5.0) | [MKL shared (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | -| CMake | [Intel (`ifort`/`icc` 2021.9.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | -| Meson | [Intel (`ifort`/`icc` 2021.9.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | static | ✅ | -| Meson | [Intel (`ifort` 2021.9.0/`icx` 2023.1.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | static | ✅ | +| CMake 3.28.3 | GNU (gcc 10.3.0) | [OpenBLAS](https://github.com/xianyi/OpenBLAS) (with OpenMP) | dynamic | ✅ | +| CMake 3.28.3 | GNU (gcc 10.3.0) | [MKL shared (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | +| CMake 3.28.3 | GNU (gcc 9.5.0) | [MKL shared (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | +| CMake 3.28.3 | [Intel (`ifort`/`icc` 2021.9.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | dynamic | ✅ | +| Meson 1.2.0 | [Intel (`ifort`/`icc` 2021.9.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | static | ✅ | +| Meson 1.2.0 | [Intel (`ifort` 2021.9.0/`icx` 2023.1.0)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/toolkits.html) | [MKL static (oneAPI 2023.1)](https://www.intel.com/content/www/us/en/developer/tools/oneapi/onemkl.html) | static | ✅ | diff --git a/subprojects/.gitignore b/subprojects/.gitignore index 145e0523..f05ba005 100644 --- a/subprojects/.gitignore +++ b/subprojects/.gitignore @@ -4,7 +4,6 @@ dftd4.wrap mstore.wrap multicharge.wrap s-dftd3.wrap -test-drive.wrap mctc-lib.wrap xhcff lammps* @@ -14,6 +13,7 @@ lammps* !toml-f !gfnff !tblite +!test-drive !packagefiles !packagefiles/tblite diff --git a/subprojects/README.md b/subprojects/README.md index 3a95d033..8b88f765 100644 --- a/subprojects/README.md +++ b/subprojects/README.md @@ -2,15 +2,15 @@ Newer versions of CREST use external projects: -| Library | Description | Build Option | git submodule | -| ------- | ----------- | ------------ | :-----------: | -| [`toml-f`](https://github.com/toml-f/toml-f) | A TOML parser for Fortran | `-DWITH_TOMLF=true` (default) | ✅ | -| [`gfn0`](https://github.com/pprcht/gfn0) | A GFN0-xTB standalone library | `-DWITH_GFN0=true` (default) | ✅ | -| [`gfnff`](https://github.com/pprcht/gfnff) | A GFN-FF standalone library | `-DWITH_GFNFF=true` (default) | ✅ | -| [`tblite`](https://github.com/tblite/tblite) | A lightweight implementation of the GFN1 and GFN2-xTB Hamiltonians | `-DWITH_TBLITE=true` (default) | ✅ | -| [`lwoniom`](https://github.com/crest-lab/lwoniom) | A lightweight ONIOM implementation | `-DWITH_LWONIOM=true` (default) | ✅ | +| Library | Description | Build Option | git submodule | CMake build | `meson` build | +| ------- | ----------- | ------------ | :-----------: | :---------: | :-----------: | +| [`toml-f`](https://github.com/toml-f/toml-f) | A TOML parser for Fortran | `-DWITH_TOMLF=true` (default) | ✅ | ✅ | ✅ | +| [`gfn0`](https://github.com/pprcht/gfn0) | A GFN0-xTB standalone library | `-DWITH_GFN0=true` (default) | ✅ | ✅ | ✅ | +| [`gfnff`](https://github.com/pprcht/gfnff) | A GFN-FF standalone library | `-DWITH_GFNFF=true` (default) | ✅ | ✅ | ✅ | +| [`tblite`](https://github.com/tblite/tblite) | A lightweight implementation of the GFN1 and GFN2-xTB Hamiltonians | `-DWITH_TBLITE=true` (default) | ✅ | ✅ | ✅ | +| [`lwoniom`](https://github.com/crest-lab/lwoniom) | A lightweight ONIOM implementation | `-DWITH_LWONIOM=true` (default) | ✅ | ✅ | ✅ | @@ -30,3 +30,4 @@ git submodule update --remote ``` can be used. +Alternatively, a source directory of the respective project can be placed in the subprojects directory, or a symbolic link can be set. diff --git a/subprojects/tblite b/subprojects/tblite index 59d37429..82c3dcb9 160000 --- a/subprojects/tblite +++ b/subprojects/tblite @@ -1 +1 @@ -Subproject commit 59d3742917aec41e28237d632a0f43afc5b2dac5 +Subproject commit 82c3dcb9f76f1b45639b7a17c27e7ba40fffe472 diff --git a/subprojects/tblite.wrap b/subprojects/tblite.wrap index a864bf48..261920a9 100644 --- a/subprojects/tblite.wrap +++ b/subprojects/tblite.wrap @@ -1,4 +1,4 @@ [wrap-git] directory = tblite -url = https://github.com/pprcht/tblite -revision = ompleak +url = https://github.com/tblite/tblite +revision = main diff --git a/subprojects/test-drive b/subprojects/test-drive new file mode 160000 index 00000000..a78870c8 --- /dev/null +++ b/subprojects/test-drive @@ -0,0 +1 @@ +Subproject commit a78870c8028168a8270a853b8aa9ef922f198718 From d0054018db5dd48e71dd1bdd5f6ee19295eaa995 Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Thu, 14 Mar 2024 16:18:20 +0000 Subject: [PATCH 2/6] CMake build with unit tests Signed-off-by: Philipp Pracht --- CMakeLists.txt | 11 +- config/CMakeLists.txt | 1 + config/modules/Findtblite.cmake | 5 + config/modules/Findtest-drive.cmake | 38 +++ test/CMakeLists.txt | 32 ++ test/main.f90 | 62 ++++ test/test_gfn0.F90 | 395 ++++++++++++++++++++++++ test/test_gfn0occ.F90 | 258 ++++++++++++++++ test/test_gfnff.F90 | 325 ++++++++++++++++++++ test/test_tblite.F90 | 454 ++++++++++++++++++++++++++++ test/testmol.f90 | 60 ++++ 11 files changed, 1640 insertions(+), 1 deletion(-) create mode 100644 config/modules/Findtest-drive.cmake create mode 100644 test/CMakeLists.txt create mode 100644 test/main.f90 create mode 100644 test/test_gfn0.F90 create mode 100644 test/test_gfn0occ.F90 create mode 100644 test/test_gfnff.F90 create mode 100644 test/test_tblite.F90 create mode 100644 test/testmol.f90 diff --git a/CMakeLists.txt b/CMakeLists.txt index ad0fa883..b0cd4269 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,11 @@ if(NOT TARGET "OpenMP::OpenMP_Fortran" AND WITH_OpenMP) find_package("OpenMP" REQUIRED) endif() +# Fortran unit test interface (also used by other subprojects) +if(NOT TARGET "test-drive::test-drive" AND WITH_TESTS) + find_package("test-drive" REQUIRED) +endif() + # TOML-F (needs to be imported before tblite) if(NOT TARGET "toml-f::toml-f" AND WITH_TOMLF) find_package("toml-f" REQUIRED) @@ -334,6 +339,10 @@ install( ) ############################################################################## -################################ Testing ##################################### +############################# Unit Tests ##################################### ############################################################################## +if (WITH_TESTS) + enable_testing() + add_subdirectory("test") +endif() diff --git a/config/CMakeLists.txt b/config/CMakeLists.txt index e6a7e09d..95a79c63 100644 --- a/config/CMakeLists.txt +++ b/config/CMakeLists.txt @@ -36,6 +36,7 @@ option(WITH_GFN0 "Enable support for GFN0-xTB" TRUE) option(WITH_GFNFF "Enable support for GFN-FF" TRUE) option(WITH_XHCFF "Enable support for XHCFF" FALSE) option(WITH_LWONIOM "Enable support for lwONIOM" TRUE) +option(WITH_TESTS "Enable unit tests" TRUE) option(STATICBUILD "Attempt to link everything statically" FALSE) # doesn't work yet diff --git a/config/modules/Findtblite.cmake b/config/modules/Findtblite.cmake index 9ca3cfc3..f8fbf600 100644 --- a/config/modules/Findtblite.cmake +++ b/config/modules/Findtblite.cmake @@ -24,6 +24,9 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/crest-utils.cmake") +set(temp_with_tests ${WITH_TESTS}) # Save the current value of WITH_TESTS +set(WITH_TESTS FALSE CACHE BOOL "Temporarily disable tests for the tblite subproject" FORCE) +set(WITH_API FALSE) crest_find_package("${_lib}" "${${_pkg}_FIND_METHOD}" "${_url}") set(found FALSE) @@ -32,6 +35,8 @@ if(TARGET "tblite::tblite") endif() message(STATUS "Found tblite: ${found}") +set(WITH_TESTS ${temp_with_tests} CACHE BOOL "Enable tests for the main project" FORCE) + unset(_lib) unset(_pkg) unset(_url) diff --git a/config/modules/Findtest-drive.cmake b/config/modules/Findtest-drive.cmake new file mode 100644 index 00000000..ed96bae6 --- /dev/null +++ b/config/modules/Findtest-drive.cmake @@ -0,0 +1,38 @@ +# This file is part of crest. +# SPDX-Identifier: LGPL-3.0-or-later +# +# crest is free software: you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# crest is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with crest. If not, see . + +set(_lib "test-drive") +set(_pkg "TEST-DRIVE") +set(_url "https://github.com/fortran-lang/test-drive") + +if(NOT DEFINED "${_pkg}_FIND_METHOD") + set("${_pkg}_FIND_METHOD" "subproject" "cmake" "fetch" "pkgconf") +endif() + +include("${CMAKE_CURRENT_LIST_DIR}/crest-utils.cmake") + +crest_find_package("${_lib}" "${${_pkg}_FIND_METHOD}" "${_url}") + +if(TARGET "${_lib}::${_lib}") + set (found TRUE) +else() + set (found FALSE) +endif() +message(STATUS "Found test-drive: ${found}") + +unset(_lib) +unset(_pkg) +unset(_url) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 00000000..7d2aee54 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,32 @@ +# Unit testing +set( + tests + "tblite" + "gfnff" + "gfn0" + "gfn0occ" +) +set( + test-srcs + "testmol.f90" + "main.f90" +) +foreach(t IN LISTS tests) + string(MAKE_C_IDENTIFIER ${t} t) + list(APPEND test-srcs "test_${t}.F90") +endforeach() + +add_executable( + "${PROJECT_NAME}-tester" + "${test-srcs}" +) +target_link_libraries( + "${PROJECT_NAME}-tester" + PRIVATE + "lib-${PROJECT_NAME}-static" + "test-drive::test-drive" +) + +foreach(t IN LISTS tests) + add_test("${PROJECT_NAME}/${t}" "${PROJECT_NAME}-tester" "${t}") +endforeach() diff --git a/test/main.f90 b/test/main.f90 new file mode 100644 index 00000000..69b8dbd8 --- /dev/null +++ b/test/main.f90 @@ -0,0 +1,62 @@ +!> Driver for unit testing +program tester + use, intrinsic :: iso_fortran_env, only : error_unit + use testdrive, only : run_testsuite, new_testsuite, testsuite_type, & + & select_suite, run_selected, get_argument + use test_tblite, only : collect_tblite + use test_gfnff, only : collect_gfnff + use test_gfn0, only: collect_gfn0 + use test_gfn0occ, only: collect_gfn0occ + implicit none + integer :: stat, is + character(len=:), allocatable :: suite_name, test_name + type(testsuite_type), allocatable :: testsuites(:) + character(len=*), parameter :: fmt = '("#", *(1x, a))' + + stat = 0 + +!&< + testsuites = [ & + new_testsuite("tblite", collect_tblite), & + new_testsuite("gfnff", collect_gfnff), & + new_testsuite("gfn0", collect_gfn0), & + new_testsuite("gfn0occ", collect_gfn0occ) & + ] +!&> + + call get_argument(1, suite_name) + call get_argument(2, test_name) + + if (allocated(suite_name)) then + is = select_suite(testsuites, suite_name) + if (is > 0 .and. is <= size(testsuites)) then + if (allocated(test_name)) then + write(error_unit, fmt) "Suite:", testsuites(is)%name + call run_selected(testsuites(is)%collect, test_name, error_unit, stat) + if (stat < 0) then + error stop 1 + end if + else + write(error_unit, fmt) "Testing:", testsuites(is)%name + call run_testsuite(testsuites(is)%collect, error_unit, stat) + end if + else + write(error_unit, fmt) "Available testsuites" + do is = 1, size(testsuites) + write(error_unit, fmt) "-", testsuites(is)%name + end do + error stop 1 + end if + else + do is = 1, size(testsuites) + write(error_unit, fmt) "Testing:", testsuites(is)%name + call run_testsuite(testsuites(is)%collect, error_unit, stat) + end do + end if + + if (stat > 0) then + write(error_unit, '(i0, 1x, a)') stat, "test(s) failed!" + error stop 1 + end if + +end program tester diff --git a/test/test_gfn0.F90 b/test/test_gfn0.F90 new file mode 100644 index 00000000..cff5e503 --- /dev/null +++ b/test/test_gfn0.F90 @@ -0,0 +1,395 @@ +module test_gfn0 + use testdrive,only:new_unittest,unittest_type,error_type,check,test_failed + use crest_parameters + use crest_calculator + use strucrd + use testmol + implicit none + private + + public :: collect_gfn0 + + real(wp),parameter :: thr = 5e+6_wp*epsilon(1.0_wp) + real(wp),parameter :: thr2 = 10*sqrt(epsilon(1.0_wp)) + +!========================================================================================! +!========================================================================================! +contains !> Unit tests for using gfn0 in crest +!========================================================================================! +!========================================================================================! + +!> Collect all exported unit tests + subroutine collect_gfn0(testsuite) + !> Collection of tests + type(unittest_type),allocatable,intent(out) :: testsuite(:) + +!&< + testsuite = [ & +#ifdef WITH_GFN0 + new_unittest("Compiled gfn0 subproject ",test_compiled_gfn0), & + new_unittest("GFN0-xTB singlepoint ",test_gfn0_sp), & + new_unittest("GFN0-xTB singlepoint (cation) ",test_gfn0_sp_cation), & + new_unittest("GFN0-xTB singlepoint (anion) ",test_gfn0_sp_anion), & + new_unittest("GFN0-xTB singlepoint (S1) ",test_gfn0_sp_uhf), & + new_unittest("GFN0-xTB singlepoint (ALPB) ",test_gfn0_sp_alpb) & +#else + new_unittest("Compiled gfn0 subproject",test_compiled_gfn0,should_fail=.true.) & +#endif + ] +!&> + end subroutine collect_gfn0 + + subroutine test_compiled_gfn0(error) + type(error_type),allocatable,intent(out) :: error +#ifndef WITH_GFN0 + write (*,'(" ...")') 'gfn0 not compiled, expecting fail.' + allocate (error) +#endif + end subroutine test_compiled_gfn0 + + subroutine test_gfn0_sp(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.908850360158375_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.008276000880612_wp, 0.000674981651598_wp, 0.000004847527110_wp, & + & 0.000668264513185_wp, -0.042047718526109_wp, -0.000053634043553_wp, & + & 0.029870640452823_wp, 0.018041726002428_wp, 0.000047108740385_wp, & + & -0.014397691809728_wp, -0.000783036074432_wp, -0.000025116661451_wp, & + & -0.025652094129182_wp, 0.001170992902634_wp, -0.000039879097860_wp, & + & -0.005414581736854_wp, 0.019478157220852_wp, 0.000025849983768_wp, & + & 0.002171994638264_wp, 0.002763826717346_wp, -0.000027761994727_wp, & + & -0.006339371025545_wp, 0.009614108548993_wp, -0.000095144233133_wp, & + & -0.007195087486222_wp, -0.023395259838885_wp, 0.000142400425061_wp, & + & -0.003510117314291_wp, 0.001640619882830_wp, -0.000054834076982_wp, & + & 0.022508811615001_wp, -0.018116741176823_wp, -0.000038916654210_wp, & + & 0.010845831057935_wp, 0.023727337503019_wp, -0.000033624275410_wp, & + & 0.009140006411910_wp, 0.001070150449043_wp, -0.000005140577297_wp, & + & -0.008520164815828_wp, -0.003504121840219_wp, 0.000001694971373_wp, & + & -0.001910960997009_wp, 0.002489353607793_wp, 0.000004185369847_wp, & + & 0.001243151419495_wp, 0.000934470115371_wp, 0.001848577600329_wp, & + & 0.001245637087981_wp, 0.000931685537315_wp, -0.001851704582091_wp, & + & -0.002704195204404_wp, 0.009583395574317_wp, 0.000027163737872_wp, & + & 0.005501417797794_wp, 0.002334158463011_wp, 0.000002931622293_wp, & + & 0.000100709327854_wp, -0.000135677302777_wp, 0.001510921694029_wp, & + & 0.000119765751454_wp, -0.000116613513992_wp, -0.001513953698281_wp, & + & -0.000586838167009_wp, -0.006799931661327_wp, 0.000077003603818_wp, & + & 0.000543218118930_wp, 0.000226162233238_wp, 0.000696572111601_wp, & + & 0.000547655374056_wp, 0.000217973524777_wp, -0.000649547492491_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn0') + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp + +!=======================================================================================! + + subroutine test_gfn0_sp_cation(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -39.184258118641779_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.007842230338035_wp, -0.000716107768510_wp, 0.000006027708001_wp, & + & -0.002549502219587_wp, -0.006712715165025_wp, -0.000063584928083_wp, & + & 0.007492657772969_wp, 0.010735993410871_wp, 0.000043822832430_wp, & + & -0.004701920582963_wp, -0.008992393110043_wp, -0.000016900999295_wp, & + & -0.065308643658280_wp, 0.014998387461506_wp, -0.000025263603064_wp, & + & 0.026348051443162_wp, 0.000695960584767_wp, 0.000036422163237_wp, & + & 0.011552078545256_wp, 0.013928105520511_wp, -0.000015015405495_wp, & + & -0.016301123411167_wp, 0.004407346436043_wp, -0.000110455543716_wp, & + & -0.007000882328314_wp, -0.023249527069618_wp, 0.000116829671479_wp, & + & -0.008894681217503_wp, 0.018490096056011_wp, -0.000046417895620_wp, & + & 0.031760376572335_wp, -0.027586600027256_wp, -0.000037169135464_wp, & + & 0.027470215463378_wp, -0.007606885366080_wp, -0.000031542739820_wp, & + & 0.010038999410521_wp, 0.003472278445810_wp, -0.000001309295826_wp, & + & -0.007885663618776_wp, -0.000845723166647_wp, -0.000014835557759_wp, & + & -0.001742861631250_wp, 0.000967263497864_wp, 0.000003516663274_wp, & + & 0.000834212167689_wp, 0.002093154209008_wp, 0.000668398641072_wp, & + & 0.000835357962140_wp, 0.002088629391442_wp, -0.000667079195056_wp, & + & -0.002684468315013_wp, 0.007905570755284_wp, 0.000020202284591_wp, & + & 0.004694468163203_wp, 0.004647604594929_wp, 0.000001966682944_wp, & + & 0.001739391942329_wp, -0.000902814088036_wp, 0.000582413882469_wp, & + & 0.001758162748149_wp, -0.000892066810248_wp, -0.000586310681465_wp, & + & 0.001826353796634_wp, -0.007288556920403_wp, 0.000080112644597_wp, & + & -0.000722574033665_wp, 0.000176063546670_wp, -0.001079601340131_wp, & + & -0.000715774633213_wp, 0.000186935581150_wp, 0.001135773146697_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn0') + sett%chrg = 1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_cation + +!========================================================================================! + + subroutine test_gfn0_sp_anion(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -42.344166332135032_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.010426382020451_wp, 0.001628829595313_wp, 0.000007210312846_wp, & + & 0.033181572393851_wp, -0.019170218624431_wp, -0.000019048355272_wp, & + & 0.023154208212837_wp, -0.027018852959561_wp, 0.000030204155402_wp, & + & -0.033913203181934_wp, 0.011899345317063_wp, -0.000034930531440_wp, & + & -0.026343002344950_wp, -0.024284354151725_wp, -0.000034684043749_wp, & + & 0.001672756331309_wp, 0.052826607173373_wp, -0.000034110755900_wp, & + & -0.036523532541808_wp, -0.051427567776587_wp, -0.000040815831358_wp, & + & 0.056448934120884_wp, 0.034347894252949_wp, 0.000037020902616_wp, & + & -0.034867985005472_wp, -0.008497410919343_wp, 0.000082164597833_wp, & + & 0.004376880255650_wp, 0.008002069192913_wp, -0.000057248113415_wp, & + & 0.018129870164541_wp, -0.014929003125888_wp, -0.000042026145794_wp, & + & -0.004008388700057_wp, 0.029821884580246_wp, -0.000000204657431_wp, & + & 0.012333625323093_wp, 0.002013273343179_wp, -0.000015895752098_wp, & + & -0.009301577149329_wp, -0.006375597665755_wp, 0.000002449135366_wp, & + & -0.000738347066971_wp, 0.002524191851042_wp, 0.000004389653171_wp, & + & 0.003476207329027_wp, 0.000273988079977_wp, 0.001398873626651_wp, & + & 0.003481545977019_wp, 0.000270469106296_wp, -0.001403512318146_wp, & + & -0.002469087328290_wp, 0.009366488704670_wp, 0.000032438663601_wp, & + & 0.004640209194904_wp, 0.000420047295936_wp, 0.000003914960794_wp, & + & -0.001789731838366_wp, -0.000233566591710_wp, 0.001663848929359_wp, & + & -0.001768091322568_wp, -0.000209591676999_wp, -0.001667189552238_wp, & + & -0.001887028684596_wp, -0.005039986652338_wp, 0.000064725306285_wp, & + & 0.001567359989035_wp, 0.001904232833389_wp, 0.000932148271364_wp, & + & 0.001573187892642_wp, 0.001886828817991_wp, -0.000909722458446_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn0') + sett%chrg = -1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_anion + +!========================================================================================! + + subroutine test_gfn0_sp_uhf(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.794220208842034_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.009683192083122_wp, 0.000062096462778_wp, 0.000008503079162_wp, & + & 0.029950134754847_wp, 0.016154999834677_wp, -0.000029559358726_wp, & + & 0.001026094788509_wp, -0.034289045648831_wp, 0.000026746432153_wp, & + & -0.023692035047363_wp, 0.004808003969286_wp, -0.000027757841729_wp, & + & -0.066059837811864_wp, -0.010598998081046_wp, -0.000020112909173_wp, & + & 0.033469390804893_wp, 0.034069110547216_wp, -0.000024058369133_wp, & + & -0.027158226668960_wp, -0.040298394690399_wp, -0.000028307867095_wp, & + & 0.045267701500952_wp, 0.028495521163272_wp, 0.000015296720032_wp, & + & -0.034731876264284_wp, -0.008324613000098_wp, 0.000055864206958_wp, & + & -0.000950977413604_wp, 0.024709825590934_wp, -0.000048981080232_wp, & + & 0.028639632796385_wp, -0.025444838911568_wp, -0.000043224546602_wp, & + & 0.012588974124660_wp, -0.001417380069055_wp, 0.000000603696102_wp, & + & 0.012881941138038_wp, 0.004366453541656_wp, -0.000011028577992_wp, & + & -0.008496043097398_wp, -0.003373490964412_wp, -0.000015764466586_wp, & + & -0.001893487311906_wp, 0.002489088628558_wp, 0.000004520971875_wp, & + & 0.001977504303537_wp, 0.001276443128655_wp, 0.001493591257119_wp, & + & 0.001981343921494_wp, 0.001271441117791_wp, -0.001496582541107_wp, & + & -0.002698130179752_wp, 0.009632226603761_wp, 0.000025851813993_wp, & + & 0.005515249124662_wp, 0.002334826380529_wp, 0.000000147972166_wp, & + & 0.000780537496596_wp, -0.000202638555834_wp, 0.002005623023644_wp, & + & 0.000801617743338_wp, -0.000186719577198_wp, -0.002010886741046_wp, & + & -0.000586042185047_wp, -0.006771411480583_wp, 0.000076716303119_wp, & + & 0.000532419821636_wp, 0.000625485053760_wp, 0.000482264816859_wp, & + & 0.000537305743752_wp, 0.000612008956153_wp, -0.000439465993761_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn0') + sett%uhf = 2 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_uhf + +!========================================================================================! + + subroutine test_gfn0_sp_alpb(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.914343794671524_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.008898560311789_wp, 0.000892429056758_wp, 0.000004556059972_wp, & + & -0.000468776166310_wp, -0.043191973189122_wp, -0.000054862901428_wp, & + & 0.024663000326671_wp, 0.019360907908987_wp, 0.000047913413987_wp, & + & -0.010385602759747_wp, 0.000142625634889_wp, -0.000026453191079_wp, & + & -0.025619391962604_wp, -0.002551430389827_wp, -0.000033834302670_wp, & + & -0.005774090861161_wp, 0.019454186312275_wp, 0.000023090583090_wp, & + & 0.007253376564080_wp, 0.005876146709966_wp, -0.000007350539307_wp, & + & -0.010672008807614_wp, 0.007463393391104_wp, -0.000107883944900_wp, & + & -0.007498735532863_wp, -0.026202194147258_wp, 0.000176804338630_wp, & + & -0.009300643359264_wp, 0.006178344563789_wp, -0.000051191689584_wp, & + & 0.026956312467136_wp, -0.021882994536491_wp, -0.000046452481884_wp, & + & 0.013312947174854_wp, 0.024105982533520_wp, -0.000039072228588_wp, & + & 0.010195763973726_wp, 0.002279939496888_wp, -0.000004593954548_wp, & + & -0.008623042956319_wp, -0.005290515866303_wp, -0.000002934904397_wp, & + & -0.001195830395235_wp, 0.000342647459422_wp, 0.000002968426401_wp, & + & 0.001562132758955_wp, 0.002094592384456_wp, 0.000349004075247_wp, & + & 0.001563163374063_wp, 0.002090581886295_wp, -0.000349436798086_wp, & + & -0.001603073760636_wp, 0.011233732948092_wp, 0.000027699940260_wp, & + & 0.004037613498852_wp, 0.004181512677995_wp, 0.000002534288046_wp, & + & -0.000126245919963_wp, -0.001310141049523_wp, -0.000127946288841_wp, & + & -0.000105213385149_wp, -0.001291320273641_wp, 0.000123231121617_wp, & + & 0.001658673162282_wp, -0.006431790301682_wp, 0.000072326100654_wp, & + & -0.000461422151234_wp, 0.001213582872177_wp, -0.000877981885269_wp, & + & -0.000470344970731_wp, 0.001241753917236_wp, 0.000899866762676_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn0') + sett%solvmodel = 'alpb' + sett%solvent = 'water' + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_alpb + +!========================================================================================! +!========================================================================================! +end module test_gfn0 diff --git a/test/test_gfn0occ.F90 b/test/test_gfn0occ.F90 new file mode 100644 index 00000000..e4c5c635 --- /dev/null +++ b/test/test_gfn0occ.F90 @@ -0,0 +1,258 @@ +module test_gfn0occ + use testdrive,only:new_unittest,unittest_type,error_type,check,test_failed + use crest_parameters + use crest_calculator + use strucrd + use testmol + implicit none + private + + public :: collect_gfn0occ + + real(wp),parameter :: thr = 5e+6_wp*epsilon(1.0_wp) + real(wp),parameter :: thr2 = 10*sqrt(epsilon(1.0_wp)) + +!========================================================================================! +!========================================================================================! +contains !> Unit tests for using gfn0 in crest +!========================================================================================! +!========================================================================================! + +!> Collect all exported unit tests + subroutine collect_gfn0occ(testsuite) + !> Collection of tests + type(unittest_type),allocatable,intent(out) :: testsuite(:) + +!&< + testsuite = [ & +#ifdef WITH_GFN0 + new_unittest("Compiled gfn0 subproject ",test_compiled_gfn0), & + new_unittest("GFN0*-xTB singlepoint (S0) ",test_gfn0_sp_s0), & + new_unittest("GFN0*-xTB singlepoint (S1) ",test_gfn0_sp_s1), & + new_unittest("GFN0*-xTB singlepoint (S2) ",test_gfn0_sp_s2) & +#else + new_unittest("Compiled gfn0 subproject",test_compiled_gfn0,should_fail=.true.) & +#endif + ] +!&> + end subroutine collect_gfn0occ + + subroutine test_compiled_gfn0(error) + type(error_type),allocatable,intent(out) :: error +#ifndef WITH_GFN0 + write (*,'(" ...")') 'gfn0 not compiled, expecting fail.' + allocate (error) +#endif + end subroutine test_compiled_gfn0 + + subroutine test_gfn0_sp_s0(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.908850360158375_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.008276000880612_wp, 0.000674981651598_wp, 0.000004847527110_wp, & + & 0.000668264513185_wp, -0.042047718526109_wp, -0.000053634043553_wp, & + & 0.029870640452823_wp, 0.018041726002428_wp, 0.000047108740385_wp, & + & -0.014397691809728_wp, -0.000783036074432_wp, -0.000025116661451_wp, & + & -0.025652094129182_wp, 0.001170992902634_wp, -0.000039879097860_wp, & + & -0.005414581736854_wp, 0.019478157220852_wp, 0.000025849983768_wp, & + & 0.002171994638264_wp, 0.002763826717346_wp, -0.000027761994727_wp, & + & -0.006339371025545_wp, 0.009614108548993_wp, -0.000095144233133_wp, & + & -0.007195087486222_wp, -0.023395259838885_wp, 0.000142400425061_wp, & + & -0.003510117314291_wp, 0.001640619882830_wp, -0.000054834076982_wp, & + & 0.022508811615001_wp, -0.018116741176823_wp, -0.000038916654210_wp, & + & 0.010845831057935_wp, 0.023727337503019_wp, -0.000033624275410_wp, & + & 0.009140006411910_wp, 0.001070150449043_wp, -0.000005140577297_wp, & + & -0.008520164815828_wp, -0.003504121840219_wp, 0.000001694971373_wp, & + & -0.001910960997009_wp, 0.002489353607793_wp, 0.000004185369847_wp, & + & 0.001243151419495_wp, 0.000934470115371_wp, 0.001848577600329_wp, & + & 0.001245637087981_wp, 0.000931685537315_wp, -0.001851704582091_wp, & + & -0.002704195204404_wp, 0.009583395574317_wp, 0.000027163737872_wp, & + & 0.005501417797794_wp, 0.002334158463011_wp, 0.000002931622293_wp, & + & 0.000100709327854_wp, -0.000135677302777_wp, 0.001510921694029_wp, & + & 0.000119765751454_wp, -0.000116613513992_wp, -0.001513953698281_wp, & + & -0.000586838167009_wp, -0.006799931661327_wp, 0.000077003603818_wp, & + & 0.000543218118930_wp, 0.000226162233238_wp, 0.000696572111601_wp, & + & 0.000547655374056_wp, 0.000217973524777_wp, -0.000649547492491_wp & + & ], shape(g_ref)) +!&> + + !> setup + sett%id = jobtype%gfn0occ + allocate(sett%config(2)) + sett%config = (/ 2, 0 /) + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_s0 + +!=======================================================================================! + + subroutine test_gfn0_sp_s1(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.794220064299274_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.009683192083122_wp, 0.000062096462778_wp, 0.000008503079162_wp, & + & 0.029950134754846_wp, 0.016154999834677_wp, -0.000029559358726_wp, & + & 0.001026094788509_wp, -0.034289045648831_wp, 0.000026746432153_wp, & + & -0.023692035047362_wp, 0.004808003969285_wp, -0.000027757841729_wp, & + & -0.066059837811864_wp, -0.010598998081046_wp, -0.000020112909173_wp, & + & 0.033469390804894_wp, 0.034069110547217_wp, -0.000024058369133_wp, & + & -0.027158226668960_wp, -0.040298394690399_wp, -0.000028307867095_wp, & + & 0.045267701500953_wp, 0.028495521163272_wp, 0.000015296720032_wp, & + & -0.034731876264285_wp, -0.008324613000097_wp, 0.000055864206958_wp, & + & -0.000950977413603_wp, 0.024709825590934_wp, -0.000048981080232_wp, & + & 0.028639632796385_wp, -0.025444838911568_wp, -0.000043224546602_wp, & + & 0.012588974124660_wp, -0.001417380069055_wp, 0.000000603696102_wp, & + & 0.012881941138038_wp, 0.004366453541656_wp, -0.000011028577992_wp, & + & -0.008496043097398_wp, -0.003373490964412_wp, -0.000015764466586_wp, & + & -0.001893487311906_wp, 0.002489088628558_wp, 0.000004520971875_wp, & + & 0.001977504303537_wp, 0.001276443128655_wp, 0.001493591257119_wp, & + & 0.001981343921494_wp, 0.001271441117791_wp, -0.001496582541107_wp, & + & -0.002698130179752_wp, 0.009632226603760_wp, 0.000025851813993_wp, & + & 0.005515249124662_wp, 0.002334826380529_wp, 0.000000147972166_wp, & + & 0.000780537496596_wp, -0.000202638555834_wp, 0.002005623023643_wp, & + & 0.000801617743338_wp, -0.000186719577198_wp, -0.002010886741046_wp, & + & -0.000586042185047_wp, -0.006771411480583_wp, 0.000076716303119_wp, & + & 0.000532419821636_wp, 0.000625485053760_wp, 0.000482264816859_wp, & + & 0.000537305743752_wp, 0.000612008956153_wp, -0.000439465993761_wp & + & ], shape(g_ref)) +!&> + + !> setup + sett%id = jobtype%gfn0occ + allocate(sett%config(2)) + sett%config = (/ 1, 1 /) + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_s1 + +!========================================================================================! + + subroutine test_gfn0_sp_s2(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -40.679590034280530_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.011090400703265_wp, -0.000550797248329_wp, 0.000012158644771_wp, & + & 0.059231969368526_wp, 0.074358105923631_wp, -0.000005484741059_wp, & + & -0.027818712379222_wp, -0.086619905186659_wp, 0.000006384034335_wp, & + & -0.032986301433234_wp, 0.010398875688673_wp, -0.000030398873745_wp, & + & -0.106468035839301_wp, -0.022368853570731_wp, -0.000000346685034_wp, & + & 0.072353687766465_wp, 0.048659928733743_wp, -0.000073966588130_wp, & + & -0.056488580529763_wp, -0.083360755297732_wp, -0.000028853791246_wp, & + & 0.096875046218719_wp, 0.047377108381327_wp, 0.000125738042617_wp, & + & -0.062268657067894_wp, 0.006746080150362_wp, -0.000030672823990_wp, & + & 0.001608123526999_wp, 0.047779250424054_wp, -0.000043128177393_wp, & + & 0.034770487416331_wp, -0.032773029038149_wp, -0.000047532282769_wp, & + & 0.014332308826253_wp, -0.026562470871541_wp, 0.000034831823648_wp, & + & 0.016623917102329_wp, 0.007662792461814_wp, -0.000016916559234_wp, & + & -0.008471949368056_wp, -0.003242862418837_wp, -0.000033223734021_wp, & + & -0.001876014175256_wp, 0.002488823075292_wp, 0.000004856576058_wp, & + & 0.002711853392059_wp, 0.001618417904629_wp, 0.001138609703103_wp, & + & 0.002717046952465_wp, 0.001611198450635_wp, -0.001141465289808_wp, & + & -0.002692066285949_wp, 0.009681054218680_wp, 0.000024539819171_wp, & + & 0.005529080674439_wp, 0.002335495633181_wp, -0.000002635712312_wp, & + & 0.001460375790183_wp, -0.000269596453729_wp, 0.002500333777585_wp, & + & 0.001483479833311_wp, -0.000256822352583_wp, -0.002507829221423_wp, & + & -0.000585237202597_wp, -0.006742898208140_wp, 0.000076429068566_wp, & + & 0.000521621763150_wp, 0.001024811502812_wp, 0.000267958165803_wp, & + & 0.000526956353308_wp, 0.001006048097595_wp, -0.000229385175492_wp & + & ], shape(g_ref)) +!&> + + !> setup + sett%id = jobtype%gfn0occ + allocate(sett%config(2)) + sett%config = (/ 0, 2 /) + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) +! write (*,'(F25.15)') energy +! write (*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn0_sp_s2 + +!========================================================================================! +!========================================================================================! +end module test_gfn0occ diff --git a/test/test_gfnff.F90 b/test/test_gfnff.F90 new file mode 100644 index 00000000..273147aa --- /dev/null +++ b/test/test_gfnff.F90 @@ -0,0 +1,325 @@ +module test_gfnff + use testdrive,only:new_unittest,unittest_type,error_type,check,test_failed + use crest_parameters + use crest_calculator + use strucrd + use testmol + implicit none + private + + public :: collect_gfnff + + real(wp),parameter :: thr = 5e+6_wp*epsilon(1.0_wp) + real(wp),parameter :: thr2 = 10*sqrt(epsilon(1.0_wp)) + +!========================================================================================! +!========================================================================================! +contains !> Unit tests for using gfnff in crest +!========================================================================================! +!========================================================================================! + +!> Collect all exported unit tests + subroutine collect_gfnff(testsuite) + !> Collection of tests + type(unittest_type),allocatable,intent(out) :: testsuite(:) + +!&< + testsuite = [ & +#ifdef WITH_GFNFF + new_unittest("Compiled gfnff subproject ",test_compiled_gfnff), & + new_unittest("GFN-FF singlepoint ",test_gfnff_sp), & + new_unittest("GFN-FF singlepoint (cation) ",test_gfnff_sp_cation), & + new_unittest("GFN-FF singlepoint (anion) ",test_gfnff_sp_anion), & + new_unittest("GFN-FF singlepoint (ALPB) ",test_gfnff_sp_alpb) & +#else + new_unittest("Compiled gfnff subproject",test_compiled_gfnff,should_fail=.true.) & +#endif + ] +!&> + end subroutine collect_gfnff + + subroutine test_compiled_gfnff(error) + type(error_type),allocatable,intent(out) :: error +#ifndef WITH_GFNFF + write(*,'(" ...")') 'gfnff not compiled, expecting fail.' + allocate (error) +#endif + end subroutine test_compiled_gfnff + + subroutine test_gfnff_sp(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -4.672792615407980_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & 0.005301577528380_wp, 0.000273969963676_wp, 0.000002235966901_wp, & + & 0.008166049302148_wp, -0.008220839652479_wp, -0.000025577423357_wp, & + & -0.003078315962938_wp, -0.009433015660225_wp, 0.000033248957362_wp, & + & 0.009919813036231_wp, 0.008086621308606_wp, -0.000022035638450_wp, & + & -0.015632607591379_wp, -0.026672383478048_wp, 0.000004837609574_wp, & + & 0.014525647437915_wp, -0.001976836648137_wp, 0.000067168707615_wp, & + & 0.006146656755674_wp, 0.009561079703764_wp, -0.000017505319062_wp, & + & -0.008820848527167_wp, -0.001068632036479_wp, -0.000078000869434_wp, & + & -0.000983352637051_wp, 0.014873587850193_wp, 0.000032976002056_wp, & + & -0.006683050923820_wp, 0.007422835964584_wp, -0.000019221292477_wp, & + & 0.012839290444322_wp, -0.012743002931932_wp, -0.000039643202321_wp, & + & -0.023422684595081_wp, 0.021005864224867_wp, -0.000002459565985_wp, & + & -0.001884047168835_wp, -0.003906629596872_wp, -0.000013746283758_wp, & + & -0.003754971577627_wp, 0.003730231633401_wp, -0.000073759305057_wp, & + & 0.000742834486661_wp, 0.003621860437988_wp, 0.000003807409655_wp, & + & 0.001069305640750_wp, -0.000350573335716_wp, 0.003705264819091_wp, & + & 0.001070928608593_wp, -0.000349783768115_wp, -0.003711454166132_wp, & + & -0.002984448998131_wp, 0.000421235644680_wp, 0.000013800906585_wp, & + & 0.004499275275005_wp, 0.000660471751639_wp, 0.000002343070942_wp, & + & 0.000371387054650_wp, 0.001498977490928_wp, 0.003776574488090_wp, & + & 0.000381320992120_wp, 0.001507606004227_wp, -0.003766956258310_wp, & + & -0.001010470679296_wp, -0.004606701841933_wp, 0.000057155046565_wp, & + & 0.001617337942360_wp, -0.001636909416951_wp, 0.003219098019704_wp, & + & 0.001603374156518_wp, -0.001699033611664_wp, -0.003148151679798_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfnff') + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfnff_sp + +!=======================================================================================! + + subroutine test_gfnff_sp_cation(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -3.329316204948430_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & 0.006025113616110_wp, -0.000476041539293_wp, 0.000002594729221_wp, & + & 0.002976419911185_wp, 0.000679240987425_wp, -0.000027434135534_wp, & + & -0.007741249228758_wp, -0.010698615223025_wp, 0.000033493626850_wp, & + & 0.015675798394840_wp, 0.001864038271447_wp, -0.000014511182788_wp, & + & -0.034151774354292_wp, -0.007653966260220_wp, 0.000003680323479_wp, & + & 0.022999436444320_wp, -0.004730111785708_wp, 0.000060519347357_wp, & + & 0.006126360638611_wp, 0.009306188454984_wp, -0.000009596058284_wp, & + & -0.013550831209723_wp, -0.002922580821436_wp, -0.000095354457018_wp, & + & -0.002031960041829_wp, 0.013328804263952_wp, 0.000044228493753_wp, & + & -0.007664605104266_wp, 0.014627940401588_wp, -0.000016489263802_wp, & + & 0.018754969893106_wp, -0.017773375742745_wp, -0.000041517059516_wp, & + & -0.007820308319431_wp, 0.003713980391848_wp, -0.000001085232997_wp, & + & -0.003458102422879_wp, -0.003295384699656_wp, -0.000018978176550_wp, & + & -0.003546064904121_wp, 0.005171739411741_wp, -0.000084843666171_wp, & + & 0.001188602766869_wp, 0.002934130726579_wp, 0.000003784320013_wp, & + & 0.001506247126530_wp, 0.000290262093640_wp, 0.002739113228752_wp, & + & 0.001506604239896_wp, 0.000291343554975_wp, -0.002741664315015_wp, & + & -0.003214661896317_wp, -0.001822644901899_wp, 0.000012841210822_wp, & + & 0.003609901458510_wp, 0.002382972247914_wp, 0.000004307221005_wp, & + & 0.000282820078859_wp, 0.001032394332879_wp, 0.002665731125889_wp, & + & 0.000293959715940_wp, 0.001040386594915_wp, -0.002655070180927_wp, & + & 0.000911301550457_wp, -0.004660465773164_wp, 0.000059733158755_wp, & + & 0.000667168759801_wp, -0.001290577497866_wp, 0.001915244081988_wp, & + & 0.000654852886582_wp, -0.001339657488875_wp, -0.001838727139279_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfnff') + sett%chrg = 1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfnff_sp_cation + +!========================================================================================! + + subroutine test_gfnff_sp_anion(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -5.722199796041350_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & 0.004468921480142_wp, -0.000083123134016_wp, 0.000001151477114_wp, & + & 0.026784240021401_wp, -0.003317301163864_wp, 0.000007330730819_wp, & + & -0.004004820272010_wp, -0.030509909771367_wp, 0.000021392716860_wp, & + & -0.000751769525558_wp, 0.005889324801531_wp, -0.000022156837684_wp, & + & -0.027788611671027_wp, -0.033864525810969_wp, -0.000006636279691_wp, & + & 0.026412943164910_wp, 0.030830470039288_wp, 0.000033495772036_wp, & + & -0.017689873797001_wp, -0.023514680185829_wp, -0.000029972119517_wp, & + & 0.025299322245125_wp, 0.011384898053826_wp, 0.000001507574957_wp, & + & -0.009184660893020_wp, 0.023372121393537_wp, -0.000006131704134_wp, & + & -0.001241048489363_wp, 0.005561107788044_wp, -0.000016875281359_wp, & + & 0.002544027763531_wp, -0.004003045629465_wp, -0.000031756330103_wp, & + & -0.029084734620249_wp, 0.020333106964323_wp, 0.000017800756382_wp, & + & -0.000069352904917_wp, -0.003305508039344_wp, -0.000014616855913_wp, & + & -0.003685271682472_wp, 0.001732297413329_wp, -0.000073775627784_wp, & + & 0.001715180720526_wp, 0.002427255238024_wp, 0.000002864449221_wp, & + & 0.001895835509322_wp, -0.000518306207627_wp, 0.003050902872775_wp, & + & 0.001898766998976_wp, -0.000518624553391_wp, -0.003057577541061_wp, & + & -0.002685446613991_wp, 0.000991558499999_wp, 0.000012103424716_wp, & + & 0.003434143710645_wp, -0.000161577974365_wp, 0.000003107935122_wp, & + & -0.000493795408284_wp, 0.000908332349694_wp, 0.003287812553032_wp, & + & -0.000484391594052_wp, 0.000916710811928_wp, -0.003278674680856_wp, & + & -0.001252234734786_wp, -0.003284602467482_wp, 0.000045301985594_wp, & + & 0.001987099764679_wp, -0.000604716538950_wp, 0.002853130443235_wp, & + & 0.001975530827471_wp, -0.000661261876856_wp, -0.002799729433761_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfnff') + sett%chrg = -1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfnff_sp_anion + +!========================================================================================! + + subroutine test_gfnff_sp_alpb(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -4.689906438468960_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & 0.005946318956743_wp, 0.000224845414918_wp, 0.000002359259418_wp, & + & 0.008276028708202_wp, -0.008052841871053_wp, -0.000024497556066_wp, & + & -0.002933422656266_wp, -0.008965806356044_wp, 0.000032565115728_wp, & + & 0.009327430055380_wp, 0.007163077799008_wp, -0.000020616233726_wp, & + & -0.015612398376933_wp, -0.026601046126910_wp, 0.000003393882782_wp, & + & 0.014224603776207_wp, -0.002328340250813_wp, 0.000066592790248_wp, & + & 0.006359125001507_wp, 0.009728710502539_wp, -0.000012692526671_wp, & + & -0.008060303189818_wp, -0.001017324006654_wp, -0.000067764705906_wp, & + & -0.000928875315221_wp, 0.014721274585459_wp, 0.000064282322941_wp, & + & -0.007032637800329_wp, 0.007686466080511_wp, -0.000018779454375_wp, & + & 0.012172269349249_wp, -0.012198147638366_wp, -0.000031535160939_wp, & + & -0.023075283175922_wp, 0.020590486278622_wp, 0.000000950293160_wp, & + & -0.002527752580930_wp, -0.004378687256113_wp, -0.000014408178734_wp, & + & -0.003644475629980_wp, 0.004533754258488_wp, -0.000098967058627_wp, & + & 0.000763589312794_wp, 0.003493537197421_wp, 0.000003659958242_wp, & + & 0.001177972834069_wp, -0.000489791575692_wp, 0.003518465980525_wp, & + & 0.001179451150639_wp, -0.000489262746804_wp, -0.003525390673803_wp, & + & -0.002858204604008_wp, -0.000053706012265_wp, 0.000013389518933_wp, & + & 0.004179436123396_wp, 0.000474457663764_wp, 0.000002349459544_wp, & + & 0.000262934613792_wp, 0.001522201563008_wp, 0.003711712203599_wp, & + & 0.000272333461465_wp, 0.001531295083315_wp, -0.003702175465263_wp, & + & -0.001005498943326_wp, -0.004218548273957_wp, 0.000052754696087_wp, & + & 0.001779350047276_wp, -0.001420257920538_wp, 0.003106515658900_wp, & + & 0.001758008882015_wp, -0.001456346391844_wp, -0.003062164125997_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfnff') + sett%solvmodel = 'alpb' + sett%solvent = 'water' + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfnff_sp_alpb + +!========================================================================================! +!========================================================================================! +end module test_gfnff diff --git a/test/test_tblite.F90 b/test/test_tblite.F90 new file mode 100644 index 00000000..d04030d4 --- /dev/null +++ b/test/test_tblite.F90 @@ -0,0 +1,454 @@ +module test_tblite + use testdrive,only:new_unittest,unittest_type,error_type,check,test_failed + use crest_parameters + use crest_calculator + use strucrd + use testmol + implicit none + private + + public :: collect_tblite + + real(wp),parameter :: thr = 5e+6_wp*epsilon(1.0_wp) + real(wp),parameter :: thr2 = 10*sqrt(epsilon(1.0_wp)) + +!========================================================================================! +!========================================================================================! +contains !> Unit tests for using tblite in crest +!========================================================================================! +!========================================================================================! + +!> Collect all exported unit tests + subroutine collect_tblite(testsuite) + !> Collection of tests + type(unittest_type),allocatable,intent(out) :: testsuite(:) + +!&< + testsuite = [ & +#ifdef WITH_TBLITE + new_unittest("Compiled tblite subproject ",test_compiled_tblite), & + new_unittest("GFN2-xTB singlepoint ",test_gfn2_sp), & + new_unittest("GFN2-xTB singlepoint (cation) ",test_gfn2_sp_cation), & + new_unittest("GFN2-xTB singlepoint (anion) ",test_gfn2_sp_anion), & + new_unittest("GFN2-xTB singlepoint (S1) ",test_gfn2_sp_uhf), & + new_unittest("GFN2-xTB singlepoint (ALPB) ",test_gfn2_sp_alpb), & + new_unittest("GFN1-xTB singlepoint ",test_gfn1_sp) & +#else + new_unittest("Compiled tblite subproject",test_compiled_tblite,should_fail=.true.) & +#endif + ] +!&> + end subroutine collect_tblite + + subroutine test_compiled_tblite(error) + type(error_type),allocatable,intent(out) :: error +#ifndef WITH_TBLITE + write(*,'(" ...")') 'tblite not compiled, expecting fail.' + allocate (error) +#endif + end subroutine test_compiled_tblite + + subroutine test_gfn2_sp(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -42.147463158380759_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.004487752242140_wp, -0.000711346240072_wp, 0.000004422164841_wp, & + & 0.005634362546189_wp, -0.026328061332228_wp, -0.000054754510167_wp, & + & 0.004946048801527_wp, 0.019170217873591_wp, 0.000052031097841_wp, & + & 0.004141916834604_wp, 0.003789795457963_wp, -0.000032613472094_wp, & + & -0.034492420000772_wp, -0.008306534022261_wp, -0.000038549844651_wp, & + & 0.006099034314247_wp, -0.004026436591110_wp, 0.000034614598904_wp, & + & 0.017464391491536_wp, 0.007913720841403_wp, 0.000037512385299_wp, & + & -0.014424186416761_wp, 0.007079404110621_wp, -0.000112173010722_wp, & + & -0.000507487343595_wp, -0.011316409953097_wp, 0.000072913115165_wp, & + & -0.015572958723902_wp, 0.012695690090090_wp, -0.000028265341194_wp, & + & 0.028409899406550_wp, -0.023838232143263_wp, -0.000039688080918_wp, & + & 0.002527690133545_wp, 0.013657975721102_wp, -0.000010799050903_wp, & + & -0.001619011135134_wp, -0.002968794206681_wp, 0.000002893676649_wp, & + & -0.006515329457992_wp, 0.007906403753381_wp, -0.000058364122249_wp, & + & -0.001453539200851_wp, 0.002783638728611_wp, 0.000004398794037_wp, & + & 0.002596908343625_wp, 0.000907279408505_wp, 0.003981683485842_wp, & + & 0.002598744285592_wp, 0.000908311001962_wp, -0.003984457648426_wp, & + & -0.003774165613087_wp, 0.008367958950496_wp, 0.000028978030648_wp, & + & 0.007868100320925_wp, 0.002139539119133_wp, 0.000000731417166_wp, & + & 0.000932101707044_wp, -0.000165802818748_wp, 0.003249098830930_wp, & + & 0.000957167451635_wp, -0.000141981017010_wp, -0.003253611423897_wp, & + & -0.002069570321846_wp, -0.009289127414772_wp, 0.000103587670973_wp, & + & 0.000358684569710_wp, -0.000098291491328_wp, 0.002383904434443_wp, & + & 0.000381370249352_wp, -0.000128917826287_wp, -0.002343493197516_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn2') + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn2_sp + +!=======================================================================================! + + subroutine test_gfn2_sp_cation(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -41.662902644562010_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.008680441178755_wp, -0.003805585932997_wp, 0.000003833547822_wp, & + & 0.008556211724477_wp, 0.007298329032302_wp, -0.000060715808107_wp, & + & -0.017210129653521_wp, 0.008000848866626_wp, 0.000045675030514_wp, & + & 0.014180937675588_wp, -0.003569605927023_wp, -0.000026595098533_wp, & + & -0.065969546794406_wp, -0.001431750313422_wp, -0.000024664910677_wp, & + & 0.035369189836543_wp, -0.022587142672832_wp, 0.000057299230498_wp, & + & 0.027217881045369_wp, 0.025975982754290_wp, 0.000020410444564_wp, & + & -0.024543524792713_wp, -0.000639673261627_wp, -0.000111734218168_wp, & + & -0.002428707956668_wp, -0.010444903854503_wp, 0.000058564290422_wp, & + & -0.016364194518134_wp, 0.044172268722857_wp, -0.000063262605340_wp, & + & 0.037221292516429_wp, -0.035587227765337_wp, -0.000030296425373_wp, & + & 0.004976226192841_wp, -0.023995007612999_wp, 0.000028348988032_wp, & + & 0.005579294937249_wp, 0.005081360488652_wp, 0.000017005851806_wp, & + & -0.004901080903271_wp, 0.007389912260113_wp, -0.000058731488109_wp, & + & -0.001138968489320_wp, 0.003005596945492_wp, 0.000006328264437_wp, & + & 0.003099117352777_wp, 0.001897847123878_wp, 0.003761878500882_wp, & + & 0.003099436103951_wp, 0.001894452000258_wp, -0.003760475465119_wp, & + & -0.004253493889487_wp, 0.006389910199458_wp, 0.000023261411435_wp, & + & 0.006392948917928_wp, 0.002861653171794_wp, -0.000007274304368_wp, & + & 0.001014741765200_wp, -0.002193018249538_wp, 0.003407479151927_wp, & + & 0.001044587604884_wp, -0.002181552984101_wp, -0.003420727645756_wp, & + & -0.002157293947451_wp, -0.008075804379714_wp, 0.000093116929524_wp, & + & -0.000060141992576_wp, 0.000289154141166_wp, 0.002614714491853_wp, & + & -0.000044341556934_wp, 0.000253957247207_wp, -0.002573438164165_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn2') + sett%chrg = 1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn2_sp_cation + +!========================================================================================! + + subroutine test_gfn2_sp_anion(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -42.311955686578870_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.011470105970055_wp, 0.000454323102443_wp, 0.000004025088780_wp, & + & 0.035872697562889_wp, -0.008460078242858_wp, -0.000021111515370_wp, & + & 0.003692743414081_wp, -0.020258524834661_wp, 0.000037721453388_wp, & + & -0.019087091757337_wp, 0.017138450608344_wp, -0.000045771350144_wp, & + & -0.020213616463304_wp, -0.039924769953061_wp, -0.000028414555700_wp, & + & 0.009408652907122_wp, 0.033864938287135_wp, -0.000033430463173_wp, & + & -0.016485709515356_wp, -0.051197854678100_wp, 0.000036590001373_wp, & + & 0.045058407382885_wp, 0.033979204637975_wp, -0.000005048366790_wp, & + & -0.036758692818602_wp, 0.001990415645982_wp, 0.000018141382464_wp, & + & 0.021925167453428_wp, 0.005846953244880_wp, -0.000041044406011_wp, & + & 0.003436690227325_wp, -0.004233961986466_wp, -0.000060952000306_wp, & + & -0.023154168166028_wp, 0.024946658253272_wp, 0.000030358110993_wp, & + & 0.004916230569813_wp, 0.001138591313257_wp, -0.000009402454000_wp, & + & -0.008313799516116_wp, 0.002428139980713_wp, -0.000040049501514_wp, & + & -0.001208556228635_wp, 0.000961400750060_wp, 0.000003367872204_wp, & + & 0.004124763613055_wp, 0.001669700587915_wp, 0.003007813202271_wp, & + & 0.004131893302950_wp, 0.001670334153738_wp, -0.003008973034920_wp, & + & -0.002632048440229_wp, 0.006629738397082_wp, 0.000032670619566_wp, & + & 0.007424243930173_wp, 0.002858491363991_wp, -0.000000133946349_wp, & + & 0.000371778457024_wp, -0.001850778398136_wp, 0.002001649485315_wp, & + & 0.000408679516879_wp, -0.001820688458466_wp, -0.002012504665727_wp, & + & -0.001161553361651_wp, -0.010738152646510_wp, 0.000113042740553_wp, & + & -0.000156331938699_wp, 0.001465258504155_wp, 0.001088496060505_wp, & + & -0.000130274161610_wp, 0.001442210367316_wp, -0.001067039757407_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn2') + sett%chrg = -1 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn2_sp_anion + +!========================================================================================! + + subroutine test_gfn2_sp_uhf(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -42.015481983629080_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.008640563198637_wp, -0.001276731011454_wp, 0.000007958615032_wp, & + & 0.037512683660300_wp, 0.023726123308498_wp, -0.000011120132727_wp, & + & -0.023304344662829_wp, -0.030936043041433_wp, 0.000027310525144_wp, & + & -0.003125727457313_wp, 0.011153715001891_wp, -0.000039680963846_wp, & + & -0.071897035549331_wp, -0.035684240793218_wp, -0.000021364112392_wp, & + & 0.053937213287434_wp, 0.027607622002516_wp, -0.000019246037097_wp, & + & -0.015752681349571_wp, -0.038841382300575_wp, 0.000004645104546_wp, & + & 0.035638413983781_wp, 0.024134341589115_wp, 0.000001459196707_wp, & + & -0.037275602976986_wp, -0.000596375689797_wp, 0.000022849188633_wp, & + & 0.011882587422559_wp, 0.038230111262650_wp, -0.000064502857749_wp, & + & 0.022686028312851_wp, -0.023788517748961_wp, -0.000048189366831_wp, & + & -0.006326790373970_wp, -0.007705697383338_wp, 0.000050970659367_wp, & + & 0.002507168942608_wp, 0.000804113685594_wp, -0.000002670812276_wp, & + & -0.007100255305176_wp, 0.007182777740523_wp, -0.000064268848580_wp, & + & -0.002073508104906_wp, 0.002718196006540_wp, 0.000005207667148_wp, & + & 0.003175843964289_wp, 0.001471376588308_wp, 0.003688753934759_wp, & + & 0.003180536309837_wp, 0.001468559650412_wp, -0.003691578785923_wp, & + & -0.004351450534000_wp, 0.008596740689697_wp, 0.000025895635956_wp, & + & 0.007700374408025_wp, 0.002614064547437_wp, -0.000002553113761_wp, & + & 0.001391017646603_wp, -0.000983369331829_wp, 0.003331940615500_wp, & + & 0.001421163490921_wp, -0.000962246268976_wp, -0.003341342331401_wp, & + & -0.002160782577365_wp, -0.009722835050767_wp, 0.000104945398812_wp, & + & 0.000477407267670_wp, 0.000411637518681_wp, 0.002100726847295_wp, & + & 0.000498303393207_wp, 0.000378059028485_wp, -0.002066146026319_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn2') + sett%uhf = 2 + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn2_sp_uhf + +!========================================================================================! + + subroutine test_gfn2_sp_alpb(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -42.150818113966622_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & -0.004041852805369_wp, -0.001459116937018_wp, 0.000004212952013_wp, & + & 0.005431782185647_wp, -0.026769409144275_wp, -0.000053933849249_wp, & + & 0.005232547908947_wp, 0.019316152153876_wp, 0.000051828956087_wp, & + & 0.003984299183311_wp, 0.004654018323578_wp, -0.000031672641741_wp, & + & -0.034791239964625_wp, -0.009664440508457_wp, -0.000039268100546_wp, & + & 0.006792385075909_wp, -0.003127178836761_wp, 0.000032791144117_wp, & + & 0.015306198183764_wp, 0.005195424722641_wp, 0.000035383591075_wp, & + & -0.011644038936970_wp, 0.009526167376125_wp, -0.000103656945404_wp, & + & -0.001073718470205_wp, -0.010467260905049_wp, 0.000071170633309_wp, & + & -0.012208257598543_wp, 0.007792225857756_wp, -0.000026835529946_wp, & + & 0.024297093142032_wp, -0.020057317289964_wp, -0.000036190038701_wp, & + & 0.002288207714506_wp, 0.015784323612706_wp, -0.000015109378387_wp, & + & -0.001839503827186_wp, -0.003557956433963_wp, 0.000003971003294_wp, & + & -0.006475695156935_wp, 0.007869132396390_wp, -0.000061014145496_wp, & + & -0.001323378271276_wp, 0.002797437673167_wp, 0.000004384755727_wp, & + & 0.002794743156382_wp, 0.000752555767144_wp, 0.003757718239733_wp, & + & 0.002796550406646_wp, 0.000753562108628_wp, -0.003760695667456_wp, & + & -0.003950802127381_wp, 0.008247313874474_wp, 0.000028580331243_wp, & + & 0.007699255283409_wp, 0.001924889526582_wp, 0.000000878165662_wp, & + & 0.000911988480912_wp, -0.000170582007313_wp, 0.003208806647171_wp, & + & 0.000936315963916_wp, -0.000147196304551_wp, -0.003212846696159_wp, & + & -0.002208060498652_wp, -0.009259192346010_wp, 0.000102993956974_wp, & + & 0.000531577240056_wp, 0.000047927691044_wp, 0.002360617394228_wp, & + & 0.000553603731705_wp, 0.000018519629250_wp, -0.002322114777547_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn2') + sett%solvmodel = 'alpb' + sett%solvent = 'water' + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + !write(*,'(F25.15)') energy + !write(*,'(3F25.15)') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn2_sp_alpb + +!========================================================================================! + + subroutine test_gfn1_sp(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io +!&< + real(wp),parameter :: e_ref = -44.509702451339784_wp + real(wp),parameter :: g_ref(3,24) = reshape([& + & 0.003874633213987_wp, 0.001058841664050_wp, 0.000004010132495_wp, & + & -0.006820697815903_wp, -0.025467667208147_wp, -0.000047472704275_wp, & + & 0.010650204538643_wp, 0.008835966788566_wp, 0.000047997051770_wp, & + & 0.000318472512888_wp, 0.007424576243087_wp, -0.000028497241728_wp, & + & -0.026207800400472_wp, -0.009013375235391_wp, -0.000038669187497_wp, & + & -0.001750473728420_wp, 0.003668870753592_wp, 0.000034119493952_wp, & + & 0.019485861483131_wp, 0.004742782186204_wp, 0.000040473978448_wp, & + & -0.011724493022376_wp, 0.007481847734935_wp, -0.000116124549323_wp, & + & -0.001224423088802_wp, -0.019133403500940_wp, 0.000124617291725_wp, & + & -0.016766618899760_wp, 0.012104298176132_wp, -0.000034576323330_wp, & + & 0.024844625147691_wp, -0.019287644128199_wp, -0.000049197092067_wp, & + & 0.011083811277529_wp, 0.017004904025028_wp, -0.000003221055588_wp, & + & -0.006459232625454_wp, -0.004286162846774_wp, -0.000004086343732_wp, & + & -0.006590040129048_wp, 0.013220910391538_wp, -0.000090165069414_wp, & + & -0.001326880708616_wp, 0.002124670840594_wp, 0.000004093024610_wp, & + & 0.001722713105321_wp, 0.001171656543542_wp, 0.002684536818471_wp, & + & 0.001725380313342_wp, 0.001170987522855_wp, -0.002688028482816_wp, & + & -0.001550167832156_wp, 0.003931581737480_wp, 0.000025224933007_wp, & + & 0.006357182837352_wp, 0.002289813675783_wp, 0.000003480620835_wp, & + & 0.000517412225517_wp, -0.000506087340212_wp, 0.001942472921733_wp, & + & 0.000540625438461_wp, -0.000485737254273_wp, -0.001945673784378_wp, & + & -0.001267730219018_wp, -0.007658771744659_wp, 0.000084917355339_wp, & + & 0.000277986074076_wp, -0.000182942929362_wp, 0.001400429395618_wp, & + & 0.000289650302091_wp, -0.000209916095429_wp, -0.001350661183856_wp & + & ], shape(g_ref)) +!&> + + !> setup + call sett%create('gfn1') + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + call engrad(mol,calc,energy,grad,io) + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-7_wp) + if (allocated(error)) return + + if (any(abs(grad-g_ref) > thr2)) then + call test_failed(error,"Gradient of energy does not match") + print'(3es21.14)',grad + print'("---")' + print'(3es21.14)',g_ref + print'("---")' + print'(3es21.14)',grad-g_ref + end if + + deallocate (grad) + end subroutine test_gfn1_sp + +!========================================================================================! +!========================================================================================! +end module test_tblite diff --git a/test/testmol.f90 b/test/testmol.f90 new file mode 100644 index 00000000..7fc1a718 --- /dev/null +++ b/test/testmol.f90 @@ -0,0 +1,60 @@ +module testmol +!> coffeine + use iso_fortran_env,only:wp => real64 + use strucrd + implicit none + private +!&< + integer,parameter :: caffeine_nat = 24 + integer, parameter :: caffeine_at(caffeine_nat) = [6,7,6,7,6,6,6,8,7,6,8,7,6,6, & + & 1,1,1,1,1,1,1,1,1,1] + real(wp),parameter :: caffeine_xyz(3,caffeine_nat) = reshape(& + &[ 2.02799738646442_wp, 0.09231312124713_wp, -0.14310895950963_wp, & + & 4.75011007621000_wp, 0.02373496014051_wp, -0.14324124033844_wp, & + & 6.33434307654413_wp, 2.07098865582721_wp, -0.14235306905930_wp, & + & 8.72860718071825_wp, 1.38002919517619_wp, -0.14265542523943_wp, & + & 8.65318821103610_wp, -1.19324866489847_wp, -0.14231527453678_wp, & + & 6.23857175648671_wp, -2.08353643730276_wp, -0.14218299370797_wp, & + & 5.63266886875962_wp, -4.69950321056008_wp, -0.13940509630299_wp, & + & 3.44931709749015_wp, -5.48092386085491_wp, -0.14318454855466_wp, & + & 7.77508917214346_wp, -6.24427872938674_wp, -0.13107140408805_wp, & + & 10.30229550927022_wp, -5.39739796609292_wp, -0.13672168520430_wp, & + & 12.07410272485492_wp, -6.91573621641911_wp, -0.13666499342053_wp, & + & 10.70038521493902_wp, -2.79078533715849_wp, -0.14148379504141_wp, & + & 13.24597858727017_wp, -1.76969072232377_wp, -0.14218299370797_wp, & + & 7.40891694074004_wp, -8.95905928176407_wp, -0.11636933482904_wp, & + & 1.38702118184179_wp, 2.05575746325296_wp, -0.14178615122154_wp, & + & 1.34622199478497_wp, -0.86356704498496_wp, 1.55590600570783_wp, & + & 1.34624089204623_wp, -0.86133716815647_wp, -1.84340893849267_wp, & + & 5.65596919189118_wp, 4.00172183859480_wp, -0.14131371969009_wp, & + & 14.67430918222276_wp, -3.26230980007732_wp, -0.14344911021228_wp, & + & 13.50897177220290_wp, -0.60815166181684_wp, 1.54898960808727_wp, & + & 13.50780014200488_wp, -0.60614855212345_wp, -1.83214617078268_wp, & + & 5.41408424778406_wp, -9.49239668625902_wp, -0.11022772492007_wp, & + & 8.31919801555568_wp, -9.74947502841788_wp, 1.56539243085954_wp, & + & 8.31511620712388_wp, -9.76854236502758_wp, -1.79108242206824_wp], & + & shape(caffeine_xyz)) +!&> + + public :: get_testmol + +contains + + subroutine get_testmol(name,mol) + character(len=*),intent(in) :: name + type(coord),intent(out) :: mol + select case(name) + + case default + !> caffeine + mol%nat = caffeine_nat + allocate(mol%at(mol%nat)) + mol%at(:) = caffeine_at(:) + allocate(mol%xyz(3,mol%nat)) + mol%xyz(:,:) = caffeine_xyz(:,:) + mol%chrg = 0 + mol%uhf = 0 + end select + end subroutine get_testmol + +end module testmol From b4888fd89ca289c83e204b4a2f1743431a5654c6 Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Thu, 14 Mar 2024 16:28:20 +0000 Subject: [PATCH 3/6] Add CMake GitHub workflow --- .github/workflows/cmake-build.yml | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/workflows/cmake-build.yml diff --git a/.github/workflows/cmake-build.yml b/.github/workflows/cmake-build.yml new file mode 100644 index 00000000..1739ece4 --- /dev/null +++ b/.github/workflows/cmake-build.yml @@ -0,0 +1,46 @@ +name: CI +on: [push, pull_request] + +env: + BUILD_DIR: _build + +jobs: + gcc-cmake-build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest] + fc: [gfortran-10] + cc: [gcc-10] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: 3.x + + - name: Install CMake + run: pip3 install ninja cmake + + - name: Git Sumbodules Setup + run: | + git submodule update --init + + - name: Configure build + run: cmake -B ${{ env.BUILD_DIR }} + env: + FC: ${{ matrix.fc }} + CC: ${{ matrix.cc }} + + - name: Build project + run: cmake --build ${{ env.BUILD_DIR }} + + - name: Run unit tests + run: make test + working-directory: ${{ env.BUILD_DIR }} + env: + OMP_NUM_THREADS: 2,1 From 7f2448fbc7bd455d9acafbfb18ea380140304c8f Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Thu, 14 Mar 2024 18:27:45 +0000 Subject: [PATCH 4/6] Unit tests for geometry optimization Signed-off-by: Philipp Pracht --- .github/workflows/build.yml | 7 +- .github/workflows/cmake-build.yml | 4 +- src/optimize/gd.f90 | 4 +- test/CMakeLists.txt | 1 + test/main.f90 | 5 +- test/test_optimization.F90 | 159 ++++++++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 11 deletions(-) create mode 100644 test/test_optimization.F90 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9e76cbd0..ec5bf37c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -100,11 +100,6 @@ jobs: tar xvf xtb-*.tar.xz echo ${{ env.PWD }}/xtb-${{ env.XTB_VERSION }}/bin >> $GITHUB_PATH -# - name: Run example 0 -# run: | -# bash run.sh -# working-directory: examples/expl-0 - continuous-delivery: if: github.event_name == 'push' @@ -118,7 +113,7 @@ jobs: OUTPUT_INTEL: crest-latest.tar.xz steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Install github-release run: | diff --git a/.github/workflows/cmake-build.yml b/.github/workflows/cmake-build.yml index 1739ece4..193a5130 100644 --- a/.github/workflows/cmake-build.yml +++ b/.github/workflows/cmake-build.yml @@ -1,4 +1,4 @@ -name: CI +name: CMake build and unit tests on: [push, pull_request] env: @@ -24,7 +24,7 @@ jobs: python-version: 3.x - name: Install CMake - run: pip3 install ninja cmake + run: pip3 install cmake - name: Git Sumbodules Setup run: | diff --git a/src/optimize/gd.f90 b/src/optimize/gd.f90 index dec91301..00c57bfe 100644 --- a/src/optimize/gd.f90 +++ b/src/optimize/gd.f90 @@ -238,9 +238,9 @@ subroutine gradientdescent(mol,calc,etot,grd,pr,wr,iostatus) !>--- for too large energy rise, rewind step. otherwise go to next iteration if (.not.lowered) then - write (*,'(" * ENERGY RISE detected. Rewind and try again with smaller step ...")') + if(pr) write (*,'(" * ENERGY RISE detected. Rewind and try again with smaller step ...")') molopt%xyz = molopt%xyz-displ - write (*,*) jjj,maxmicro + !write (*,*) jjj,maxmicro if (jjj == maxmicro) then write (*,'(" * FAILED to perform gradient descent! Something is very wrong ...")') converged = .false. diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 7d2aee54..3086735c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -5,6 +5,7 @@ set( "gfnff" "gfn0" "gfn0occ" + "optimization" ) set( test-srcs diff --git a/test/main.f90 b/test/main.f90 index 69b8dbd8..291940af 100644 --- a/test/main.f90 +++ b/test/main.f90 @@ -7,6 +7,7 @@ program tester use test_gfnff, only : collect_gfnff use test_gfn0, only: collect_gfn0 use test_gfn0occ, only: collect_gfn0occ + use test_optimization, only: collect_optimization implicit none integer :: stat, is character(len=:), allocatable :: suite_name, test_name @@ -16,11 +17,13 @@ program tester stat = 0 !&< +!> note: these must have the same name as in CMakeLists.txt testsuites = [ & new_testsuite("tblite", collect_tblite), & new_testsuite("gfnff", collect_gfnff), & new_testsuite("gfn0", collect_gfn0), & - new_testsuite("gfn0occ", collect_gfn0occ) & + new_testsuite("gfn0occ", collect_gfn0occ), & + new_testsuite("optimization", collect_optimization) & ] !&> diff --git a/test/test_optimization.F90 b/test/test_optimization.F90 new file mode 100644 index 00000000..57b31638 --- /dev/null +++ b/test/test_optimization.F90 @@ -0,0 +1,159 @@ +module test_optimization + use testdrive,only:new_unittest,unittest_type,error_type,check,test_failed + use crest_parameters + use crest_calculator + use strucrd + use testmol + use optimize_module + implicit none + private + + public :: collect_optimization + + real(wp),parameter :: thr = 5e+6_wp*epsilon(1.0_wp) + real(wp),parameter :: thr2 = 10*sqrt(epsilon(1.0_wp)) + +!========================================================================================! +!========================================================================================! +contains !> Unit tests for using gfnff in crest +!========================================================================================! +!========================================================================================! + +!> Collect all exported unit tests + subroutine collect_optimization(testsuite) + !> Collection of tests + type(unittest_type),allocatable,intent(out) :: testsuite(:) + +!&< + testsuite = [ & +#ifdef WITH_GFNFF + new_unittest("Compiled gfnff subproject ",test_compiled_gfnff), & + new_unittest("optimization (ANCOPT) ",test_ancopt), & + new_unittest("optimization (grad. descent) ",test_gradientdescent), & + new_unittest("optimization (RFO) ",test_rfo) & +#else + new_unittest("Compiled gfnff subproject",test_compiled_gfnff,should_fail=.true.) & +#endif + ] +!&> + end subroutine collect_optimization + + subroutine test_compiled_gfnff(error) + type(error_type),allocatable,intent(out) :: error +#ifndef WITH_GFNFF + write(*,'(" ...")') 'gfnff not compiled, expecting fail.' + allocate (error) +#endif + end subroutine test_compiled_gfnff + +!========================================================================================! + + subroutine test_ancopt(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol,molnew + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io + logical :: wr,pr +!&< + real(wp),parameter :: e_ref = -4.677663337455959_wp +!&> + + !> setup + call sett%create('gfnff') + call calc%add(sett) + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + wr = .false. + pr = .false. + call optimize_geometry(mol,molnew,calc,energy,grad,pr,wr,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-6_wp) + if (allocated(error)) return + + deallocate (grad) + end subroutine test_ancopt + +!========================================================================================! + subroutine test_gradientdescent(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol,molnew + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io + logical :: wr,pr +!&< + real(wp),parameter :: e_ref = -4.677587929227879_wp +!&> + + !> setup + call sett%create('gfnff') + call calc%add(sett) + calc%opt_engine = -1 + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + wr = .false. + pr = .false. + call optimize_geometry(mol,molnew,calc,energy,grad,pr,wr,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-6_wp) + if (allocated(error)) return + + deallocate (grad) + end subroutine test_gradientdescent + +!========================================================================================! + subroutine test_rfo(error) + type(error_type),allocatable,intent(out) :: error + type(calcdata) :: calc + type(calculation_settings) :: sett + type(coord) :: mol,molnew + real(wp) :: energy + real(wp),allocatable :: grad(:,:) + integer :: io + logical :: wr,pr +!&< + real(wp),parameter :: e_ref = -4.677662006957390_wp +!&> + + !> setup + call sett%create('gfnff') + call calc%add(sett) + calc%opt_engine = 2 + call get_testmol('caffeine',mol) + allocate (grad(3,mol%nat)) + + !> calculation + wr = .false. + pr = .false. + call optimize_geometry(mol,molnew,calc,energy,grad,pr,wr,io) + !write(*,'(F25.15)') energy + !write(*,'(3(F20.15,"_wp,")," &")') grad + call check(error,io,0) + if (allocated(error)) return + + call check(error,energy,e_ref,thr=1e-6_wp) + if (allocated(error)) return + + deallocate (grad) + end subroutine test_rfo + +!========================================================================================! +!========================================================================================! +end module test_optimization From 4ea0deada10397467b72879c0657d66bfb7fe744 Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Tue, 19 Mar 2024 13:24:33 +0000 Subject: [PATCH 5/6] Restore old behaviour of --mdopt output ensemble --- src/algos/optimization.f90 | 16 ++++++++++++++++ src/algos/parallel.f90 | 2 +- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/algos/optimization.f90 b/src/algos/optimization.f90 index 6158f97d..25967626 100644 --- a/src/algos/optimization.f90 +++ b/src/algos/optimization.f90 @@ -193,6 +193,7 @@ subroutine crest_ensemble_optimization(env,tim) real(wp),allocatable :: eread(:) real(wp),allocatable :: xyz(:,:,:) integer,allocatable :: at(:) + character(len=10),allocatable :: comments(:) character(len=80) :: atmp real(wp) :: percent character(len=52) :: bar @@ -237,6 +238,21 @@ subroutine crest_ensemble_optimization(env,tim) !>--- call the loop call crest_oloop(env,nat,nall,at,xyz,eread,.true.) +!========================================================================================! +!>--- output + write(stdout,'(/,a,a,a)') 'Rewriting ',ensemblefile,' in the correct order'// & + & ' (failed optimizations are assigned an energy of +1.0)' +!>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<--- Back to Angstroem + xyz = xyz * bohr +!>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<< 0.0_wp) comments(i) = '!failed' + enddo + call wrensemble(ensemblefile,nat,nall,at,xyz,eread,comments) + deallocate (eread,at,xyz) write(stdout,'(/,a,a,a)') 'Optimized ensemble written to <',ensemblefile,'>' diff --git a/src/algos/parallel.f90 b/src/algos/parallel.f90 index 4c172768..735dafc7 100644 --- a/src/algos/parallel.f90 +++ b/src/algos/parallel.f90 @@ -306,7 +306,7 @@ subroutine crest_oloop(env,nat,nall,at,xyz,eread,dump) eread(zcopy) = energy xyz(:,:,zcopy) = molsnew(job)%xyz(:,:) else - eread(zcopy) = 0.0_wp + eread(zcopy) = 1.0_wp end if k = k+1 !>--- print progress From f2405510c3da044ca8c0cd3f6c5be1831e43c206 Mon Sep 17 00:00:00 2001 From: Philipp Pracht Date: Tue, 19 Mar 2024 15:11:26 +0000 Subject: [PATCH 6/6] Make refinement presorting optional argument in toml input --- src/algos/refine.f90 | 2 +- src/parsing/parse_maindata.f90 | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/algos/refine.f90 b/src/algos/refine.f90 index 65e96e9c..4acb0be8 100644 --- a/src/algos/refine.f90 +++ b/src/algos/refine.f90 @@ -55,7 +55,7 @@ subroutine crest_refine(env,input,output) else outname = input !> overwrite end if - + !>--- presorting step, if necessary if(env%refine_presort)then call newcregen(env,0,input) diff --git a/src/parsing/parse_maindata.f90 b/src/parsing/parse_maindata.f90 index aad5e614..f3df1b83 100644 --- a/src/parsing/parse_maindata.f90 +++ b/src/parsing/parse_maindata.f90 @@ -220,6 +220,8 @@ subroutine parse_main_bool(env,key,val) end if case ('multilevelopt') env%multilevelopt = val + case ('refine_presort') + env%refine_presort = val end select return end subroutine parse_main_bool @@ -282,7 +284,7 @@ subroutine parse_confsolv(env,blk) integer :: i !>--- add ConfSolv as refinement level to give a ΔΔGsoln call env%addrefine(refine%ConfSolv) - env%refine_presort = .true. + !env%refine_presort = .true. env%ewin = 100.0_wp !>--- parse the arguments