diff --git a/.azure-pipelines/azure-pipelines-linux.yml b/.azure-pipelines/azure-pipelines-linux.yml index 3a89736179e..ca0320ccafb 100644 --- a/.azure-pipelines/azure-pipelines-linux.yml +++ b/.azure-pipelines/azure-pipelines-linux.yml @@ -9,13 +9,13 @@ jobs: strategy: maxParallel: 8 matrix: - gcc_7: - CXX_COMPILER: 'g++-7' + gcc_10: + CXX_COMPILER: 'g++-10' PYTHON_VER: '3.8' - C_COMPILER: 'gcc-7' + C_COMPILER: 'gcc-10' F_COMPILER: 'gfortran' BUILD_TYPE: 'release' - APT_INSTALL: 'gfortran gcc-7 g++-7' + APT_INSTALL: 'gfortran gcc-10 g++-10' vmImage: 'ubuntu-20.04' PYTEST_MARKER_EXPR: "quick" @@ -99,8 +99,11 @@ jobs: echo " - psi4::gcp" >> env_p4env.yaml echo " - psi4::dftd3" >> env_p4env.yaml fi - sed -i "s;- conda-forge/label/libint_dev;#- conda-forge/label/libint_dev;g" env_p4env.yaml - sed -i "s;#- psi4/label/testing::libint2;- psi4/label/testing::libint=2.8.0dev2;g" env_p4env.yaml + sed -i "s;- libint;#- libint;g" env_p4env.yaml + sed -i "s;#- psi4::libint;- psi4::libint=2.8.1;g" env_p4env.yaml + echo " - einsums" >> env_p4env.yaml + echo " - range-v3" >> env_p4env.yaml + echo " - zlib" >> env_p4env.yaml echo "\n<<< env_p4env.yaml >>>\n" cat env_p4env.yaml conda env create -n p4env -f env_p4env.yaml @@ -128,6 +131,7 @@ jobs: -D CMAKE_Fortran_COMPILER=${F_COMPILER} \ -D CMAKE_BUILD_TYPE=${BUILD_TYPE} \ -D ENABLE_PLUGIN_TESTING=ON \ + -D ENABLE_Einsums=ON \ -D CMAKE_INSTALL_PREFIX=$(Agent.BuildDirectory)/Install displayName: 'Configure Build' diff --git a/.azure-pipelines/azure-pipelines-windows.yml b/.azure-pipelines/azure-pipelines-windows.yml index 66582f4b23f..67cf666900e 100644 --- a/.azure-pipelines/azure-pipelines-windows.yml +++ b/.azure-pipelines/azure-pipelines-windows.yml @@ -110,7 +110,6 @@ jobs: # conda=23.10 forced a bugfix at conda-build stage - script: | conda config --set always_yes yes - conda config --add channels conda-forge/label/libint_dev conda config --add channels psi4/label/testing conda config --set channel_priority strict conda config --set solver libmamba @@ -147,7 +146,7 @@ jobs: gcp-correction ^ gau2grid ^ libxc-c ^ - libint=2.8.0dev2 ^ + libint ^ qcelemental ^ qcengine ^ pydantic=1.10.13 ^ diff --git a/.github/workflows/ecosystem.yml b/.github/workflows/ecosystem.yml index 765ac035ac3..77120d9a974 100644 --- a/.github/workflows/ecosystem.yml +++ b/.github/workflows/ecosystem.yml @@ -151,7 +151,6 @@ jobs: fi if [[ "${{ runner.os }}" == "macOS" ]]; then : - sed -E -i.bak "s;- conda-forge/label/libint_dev::libint==2.7.3dev1;- psi4/label/testing::libint=2.8.0dev2;g" env_p4build.yaml # sed -E -i.bak "s;;;g" env_p4build.yaml fi if [[ "${{ runner.os }}" == "Windows" ]]; then diff --git a/codedeps.yaml b/codedeps.yaml index 2d5bbc78a48..2629e8ad661 100644 --- a/codedeps.yaml +++ b/codedeps.yaml @@ -429,7 +429,7 @@ data: - project: libint use: added: "1.0" - added_note: "Switched from Libint1 to C++11 intf of Libint2 at 1.4." + added_note: "Switched from Libint1 to C++11 intf of Libint2 at 1.4. Can use upstream Libint2 v2.8.0 at 1.9." required: true buildable: true buildtime: true @@ -437,9 +437,8 @@ data: repository: host: github account: evaleev - #account: loriab # TODO using evaleev for license but commit only at loriab name: libint - commit: 0eca57e + commit: v2.8.1 #cmake: # name: Libint2 # constraint: @@ -461,16 +460,17 @@ data: # - onebody_d1_l3 # - onebody_d2_l3 conda: - channel: conda-forge/label/libint_dev + channel: conda-forge name: libint - constraint: "==2.7.3dev1" - constraint_note: "v2.7.3dev1 provides rt-switchable ordering (src) and derivative integrals (build)." + name_note: "On the psi4 channel, libint/libint2 were used c.2021-23 to distinguish v1/v2. c-f always used libint as the package name. Starting with the v2.8 reunification with upstream, the supplementary 'bigAM' packages published on the psi4 channel will use the name libint for consistency with c-f." + constraint: null + constraint_note: "v2.8.0 provides rt-switchable ordering (src) and derivative integrals (build)." aux_build_names: - - //psi4/label/testing::libint2 + - //psi4::libint - libboost-headers - eigen aux_build_names_note: - "//psi4/label/testing::libint2": "Optionally for linux-64, an AM=7 build is available here." + "//psi4::libint": "Optionally for linux-64, an AM=7 build is available here." cmake: BOOST_ROOT: unix: ${CONDA_PREFIX} @@ -1420,12 +1420,11 @@ data: conda: channel: conda-forge name: einsums - constraint: null - # todo: weird to be targeting the openblas einsums variant (instead of constraint: "=*=mkl*") but right now with blas-devel only for 2023 yet packages only for 2022 AND needing to find clas.h, this is the only way it will solve. also, tie einsums variant to libblas selection. + constraint: "=*=mkl*" + # todo: tie einsums variant to libblas selection, rather than mkl constraint above. aux_build_names: - range-v3 - zlib - - openblas skip_win: true cmake: ENABLE_Einsums: true diff --git a/conda/psi4-path-advisor.py b/conda/psi4-path-advisor.py index 7659574f897..f4e6a726c31 100755 --- a/conda/psi4-path-advisor.py +++ b/conda/psi4-path-advisor.py @@ -1007,6 +1007,15 @@ def _split_lines(self, text, width): notes = f""" + * [21 Dec 2023] The Psi4 source can use most any Libint packaged as psi4*::libint2 + in 2023, as conda-forge/label/libint_dev::libint in 2023 or + conda-forge::libint>=2.8.0 . They may not detect the same with CMake, but at + runtime, as far as Psi4 uses the library, they're the same. You are encouraged + to upgrade to v2.8.1 soon, as the master branch will start to require it in + early 2024. AM5 production builds are available from conda-forge, and an AM7 + is available for Linux from psi4. Henceforth, all packages will be named + "libint", not "libint2". + * [15 Nov 2023] If ever you are building from git source and the version is undefined (shows up in CMake output, too), the solution is to pull tags: `git fetch upstream "refs/tags/*:refs/tags/*"`, then recompile (trivial). diff --git a/external/upstream/libint2/CMakeLists.txt b/external/upstream/libint2/CMakeLists.txt index 57dc2a84d05..c233ba3f7df 100644 --- a/external/upstream/libint2/CMakeLists.txt +++ b/external/upstream/libint2/CMakeLists.txt @@ -30,6 +30,8 @@ # edit the CMake to use a gss. # * Upon additions to the Libint2 API to allow runtime SHGAUSS switching, Psi4 can no longer be adapted to use a libtool+cmake source. # * Libraries of different AM are not hot-swappable in a Psi4 build, but they only require a relinking. +# [Jan 2024] +# * As of v1.9, Psi4 can use an upstream v2.8 Libint2. This is a libtool+cmake build, so `find_package(Libint2 ... COMPONENTS ...)` has no components to check. find_package( Libint2 @@ -46,7 +48,7 @@ find_package( eri_c4_d2_l2 eri_c3_d2_l3 eri_c2_d2_l3 ) -# If L2 v2.8.0 (1) exported CMake components and (2) libint2-config.cmake actually +# If L2 v2.8.1 (1) exported CMake components and (2) libint2-config.cmake actually # checked, the below is the new find_package call. #if (${MAX_AM_ERI} GREATER 8) # set(amchar "llll") @@ -61,7 +63,7 @@ find_package( #endif() #find_package( # Libint2 -# 2.8.0 +# 2.8.1 # CONFIG # COMPONENTS # ss @@ -76,13 +78,14 @@ find_package( if (TARGET Libint2::cxx) get_target_property(_loc Libint2::int2 LOCATION) - get_target_property(Libint2_VERSION Libint2::int2 Libint2_VERSION) - get_target_property(Libint2_MAX_AM_ERI Libint2::int2 Libint2_MAX_AM_ERI) + # defer until upstream provides full-dress targets get_target_property(Libint2_VERSION Libint2::int2 Libint2_VERSION) + # defer until upstream provides full-dress targets get_target_property(Libint2_MAX_AM_ERI Libint2::int2 Libint2_MAX_AM_ERI) get_target_property(Libint2_CONFIGURATION Libint2::int2 Libint2_CONFIGURATION) message(STATUS "${Cyan}Found Libint2 ${Libint2_MAX_AM_ERI}${ColourReset}: ${_loc} (found version ${Libint2_VERSION})") - if (NOT eri_c4_d2_l2 IN_LIST Libint2_CONFIGURATION) - message(WARNING "Libint2 detected but missing ERI 2nd derivative integrals (components eri_c4_d2_l2 eri_c3_d2_l3 eri_c2_d2_l3). Psi4 will automatically fall back to finite difference.") - endif() + # TODO revive this message. For now, can't tell if cmake build missing Hessian ints or libtool build w/o component info. + # if (NOT eri_c4_d2_l2 IN_LIST Libint2_CONFIGURATION) + # message(WARNING "Libint2 detected but missing ERI 2nd derivative integrals (components eri_c4_d2_l2 eri_c3_d2_l3 eri_c2_d2_l3). Psi4 will automatically fall back to finite difference.") + # endif() add_library(libint2_external INTERFACE) # dummy if(${CMAKE_INSIST_FIND_PACKAGE_Libint2}) @@ -104,12 +107,12 @@ else() if(NOT ${BUILD_Libint2_GENERATOR}) if (${MAX_AM_ERI} GREATER 5) - set(_url_am_src "7-7-4-7-7-5") # passes E&G 7z conv and 6z df, H Qz conv and df. covers all internal basis sets for energy and gradient + set(_url_am_src "7-7-4-12-7-5") # passes E&G 7z conv and 6z df, H Qz conv and df. covers all internal basis sets for energy and gradient elseif (${MAX_AM_ERI} LESS_EQUAL 5) set(_url_am_src "5-4-3-6-5-4") # passes full. production Mac, temp production Linux endif() - set(_url_l2_tarball "https://github.com/loriab/libint/releases/download/v0.1/libint-2.7.2-post1-${_url_am_src}_mm4f12ob2_1.tgz") + set(_url_l2_tarball "https://github.com/loriab/libint/releases/download/v0.1/libint-2.8.1-${_url_am_src}_mm10f12ob2_0.tgz") message(STATUS "Suitable Libint2 could not be located, ${Magenta}Building Libint2 ${_url_am_src}${ColourReset} instead.") @@ -133,10 +136,9 @@ else() -DEigen3_DIR=${Eigen3_DIR} -DEigen3_ROOT=${Eigen3_ROOT} -DBUILD_SHARED_LIBS=${_build_shared_libs} - -DLIBINT2_REQUIRE_CXX_API=ON - -DLIBINT2_REQUIRE_CXX_API_COMPILED=OFF - -DLIBINT2_ENABLE_FORTRAN=OFF - -DLIBINT2_ENABLE_PYTHON=OFF + -DREQUIRE_CXX_API=ON + -DENABLE_FORTRAN=OFF + -DLIBINT2_PYTHON=OFF -DENABLE_XHOST=${ENABLE_XHOST} -DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET} -DCMAKE_OSX_SYSROOT=${CMAKE_OSX_SYSROOT} @@ -145,9 +147,13 @@ else() -DCMAKE_CXX_COMPILER_ARG1:STRING=${CMAKE_CXX_COMPILER_ARG1} -DCMAKE_C_COMPILER_ARG1:STRING=${CMAKE_C_COMPILER_ARG1}) + #-DLIBINT2_REQUIRE_CXX_API=ON + #-DLIBINT2_REQUIRE_CXX_API_COMPILED=OFF + #-DLIBINT2_ENABLE_FORTRAN=OFF + #-DLIBINT2_ENABLE_PYTHON=OFF else() message(STATUS "Suitable Libint2 could not be located, ${Magenta}Building Libint2${ColourReset} from generator source instead.") - message(WARNING "${Yellow}Libint2 generator source build requires Ninja (not Makefile) builder and Boost, Eigen, and GMPXX dependencies. The build will be very long for non-trivial AM, and parallelism won't help for the generation phase. Edit external/upstream/libint2/CMakeLists.txt for AM, derivative, and integral classes settings.${ColourReset}") + message(WARNING "${Yellow}Libint2 generator source build requires Ninja (not Makefile) builder and Boost, Eigen, and GMPXX dependencies. The build will be very long for non-trivial AM, and parallelism won't help for the generation phase. Edit external/upstream/libint2/CMakeLists.txt for AM, derivative, and integral classes settings. This is also building v2.7, not v2.8 Libint2.${ColourReset}") if (MSVC) message(FATAL_ERROR "${Red}Libint2 generator source build faulty on Windows.${ColourReset}") diff --git a/psi4/CMakeLists.txt b/psi4/CMakeLists.txt index c47ad9d5075..0527e26b9f2 100644 --- a/psi4/CMakeLists.txt +++ b/psi4/CMakeLists.txt @@ -182,8 +182,8 @@ find_package( eri_c4_d2_l2 eri_c3_d2_l3 eri_c2_d2_l3 ) get_property(_loc TARGET Libint2::int2 PROPERTY LOCATION) -get_property(Libint2_VERSION_ver TARGET Libint2::int2 PROPERTY Libint2_VERSION) -get_property(Libint2_MAX_AM_ERI TARGET Libint2::int2 PROPERTY Libint2_MAX_AM_ERI) +# defer until upstream provides full-dress targets get_property(Libint2_VERSION TARGET Libint2::int2 PROPERTY Libint2_VERSION) +# defer until upstream provides full-dress targets get_property(Libint2_MAX_AM_ERI TARGET Libint2::int2 PROPERTY Libint2_MAX_AM_ERI) list(APPEND _addons ${_loc}) message(STATUS "${Cyan}Using Libint2 ${Libint2_MAX_AM_ERI}${ColourReset}: ${_loc} (version ${Libint2_VERSION})") diff --git a/psi4/driver/p4util/util.py b/psi4/driver/p4util/util.py index 07c33bcba26..914721cffa3 100644 --- a/psi4/driver/p4util/util.py +++ b/psi4/driver/p4util/util.py @@ -412,12 +412,12 @@ def _l2_config_style_eri_c4(): def libint2_print_out() -> None: ams = libint2_configuration() - # excluding sph_emultipole - sho = {1: 'standard', 2: 'gaussian'}[core._libint2_solid_harmonics_ordering()] core.print_out(" => Libint2 <=\n\n"); + # when L2 is pure cmake core.print_out(core.libint2_citation()); core.print_out(f" Primary basis highest AM E, G, H: {', '.join(('-' if d is None else str(d)) for d in ams['eri'])}\n") core.print_out(f" Auxiliary basis highest AM E, G, H: {', '.join(('-' if d is None else str(d)) for d in ams['eri3'])}\n") core.print_out(f" Onebody basis highest AM E, G, H: {', '.join(('-' if d is None else str(d)) for d in ams['onebody'])}\n") - core.print_out(f" Solid Harmonics ordering: {sho}\n") + # excluding sph_emultipole + core.print_out(f" Solid Harmonics ordering: {core.libint2_solid_harmonics_ordering()}\n") diff --git a/psi4/src/export_mints.cc b/psi4/src/export_mints.cc index 3e80c353f92..67e91a64166 100644 --- a/psi4/src/export_mints.cc +++ b/psi4/src/export_mints.cc @@ -1727,6 +1727,22 @@ void export_mints(py::module& m) { "Returns string with codes detailing the integral classes, angular momenta, and ordering \ characteristics of the linked Libint2. Prefer the processed libint2_configuration function."); - m.def("_libint2_solid_harmonics_ordering", []() { return int(libint2::solid_harmonics_ordering()); }, - "Libint2 SH setting"); + m.def("libint2_solid_harmonics_ordering", []() { + const std::string SHOrderingsList[] = {"null", "Standard", "Gaussian"}; + std::string sho = SHOrderingsList[int(libint2::solid_harmonics_ordering())]; + return sho; + }, + "The solid harmonics setting of Libint2 currently active for Psi4"); + + // when psi4 requires >=v2.8.0 + // m.def("libint2_supports", [](const std::string& comp) { return libint2::supports(comp); }, + // "Whether the linked Libint2 supports a particular ordering or integral type/derivative/AM. Use maximally uniform AM for latter."); + + // when L2 is pure cmake + // m.def("libint2_citation", []() { + // const std::string cit = " Version " + libint2::libint_version_string(true) + "\n " + + // "Edward F. Valeev, http://libint.valeyev.net/" + " (" + libint2::libint_reference_doi() + ")"; + // return cit; + // }, + // "Citation blurb for Libint2"); } diff --git a/tests/pytests/test_task_planner.py b/tests/pytests/test_task_planner.py index 56fdc7a4d06..671d569b846 100644 --- a/tests/pytests/test_task_planner.py +++ b/tests/pytests/test_task_planner.py @@ -398,9 +398,9 @@ def test_findif_1_0(mtd, kw): assert plan2.method == mtd assert plan2.driver == "energy" assert np.allclose(plan2.molecule.geometry().np, displacements[k2]) - assert plan2.keywords["SCF__E_CONVERGENCE"] == 1.0e-10 - assert plan2.keywords["SCF__D_CONVERGENCE"] == 1.0e-10 - assert plan2.keywords["E_CONVERGENCE"] == 1.0e-8 + assert psi4.compare_values(1.0e-10, plan2.keywords["SCF__E_CONVERGENCE"], atol=1.0e-14) + assert psi4.compare_values(1.0e-10, plan2.keywords["SCF__D_CONVERGENCE"], atol=1.e-14) + assert psi4.compare_values(1.0e-8, plan2.keywords["E_CONVERGENCE"], atol=1.e-14) @pytest.mark.parametrize("kw, pts", [({"ref_gradient": np.zeros((2, 3))}, 3), ({}, 5)]) @@ -435,8 +435,8 @@ def test_findif_2_1(kw, pts): assert plan2.method == "mp2" assert plan2.driver == "gradient" assert np.allclose(plan2.molecule.geometry().np, displacements[k2]) - assert plan2.keywords["SCF__D_CONVERGENCE"] == 1.0e-10 - assert plan2.keywords["E_CONVERGENCE"] == 1.0e-6 + assert psi4.compare_values(1.0e-10, plan2.keywords["SCF__D_CONVERGENCE"], atol=1.e-14) + assert psi4.compare_values(1.0e-6, plan2.keywords["E_CONVERGENCE"], atol=1.e-14) @pytest.mark.parametrize("kw, pts", [({"ref_gradient": np.zeros((2, 3))}, 5), ({}, 9)]) @@ -475,6 +475,6 @@ def test_findif_2_0(kw, pts): assert plan2.method == "mp2" assert plan2.driver == "energy" assert np.allclose(plan2.molecule.geometry().np, displacements[k2]) - assert plan2.keywords["SCF__E_CONVERGENCE"] == 1.0e-6 - assert plan2.keywords["SCF__D_CONVERGENCE"] == 1.0e-11 - assert plan2.keywords["E_CONVERGENCE"] == 1.0e-10 + assert psi4.compare_values(1.0e-6, plan2.keywords["SCF__E_CONVERGENCE"], atol=1.e-14) + assert psi4.compare_values(1.0e-11, plan2.keywords["SCF__D_CONVERGENCE"], atol=1.e-14) + assert psi4.compare_values(1.0e-10, plan2.keywords["E_CONVERGENCE"], atol=1.e-14)