From 121db3cb349be598f1667e3e04a72f7a990c6bf8 Mon Sep 17 00:00:00 2001 From: Alex Wietek Date: Wed, 17 Jul 2024 10:49:39 +0200 Subject: [PATCH] Added Intel MPI continuous integration workflow --- .github/workflows/intelmpi.yml | 40 +++++++++++++++++++ README.md | 1 + .../test_time_evolution_distributed.cpp | 28 ++++++------- .../test_tj_distributed_apply.cpp | 15 ++++--- xdiag/basis/spinhalf_distributed/basis_sz.cpp | 12 ++++-- xdiag/basis/spinhalf_distributed/basis_sz.hpp | 1 + .../tj_distributed/terms/apply_exchange.hpp | 12 ++++-- .../tj_distributed/terms/apply_hopping.hpp | 5 ++- .../tj_distributed/terms/apply_ising.hpp | 5 ++- .../tj_distributed/terms/apply_number.hpp | 7 +++- .../terms/apply_raise_lower.hpp | 9 +++-- .../tj_distributed/terms/apply_terms.hpp | 2 +- .../tj_distributed/tj_distributed_apply.cpp | 12 +++--- .../tj_distributed/tj_distributed_apply.hpp | 2 +- xdiag/parallel/mpi/comm_pattern.hpp | 2 +- xdiag/utils/error.cpp | 2 +- 16 files changed, 107 insertions(+), 48 deletions(-) create mode 100644 .github/workflows/intelmpi.yml diff --git a/.github/workflows/intelmpi.yml b/.github/workflows/intelmpi.yml new file mode 100644 index 00000000..503f17d8 --- /dev/null +++ b/.github/workflows/intelmpi.yml @@ -0,0 +1,40 @@ +# this method does not use Github Actions cache--good for infrequent simple runs +jobs: + + linux-intel-oneapi: + runs-on: ubuntu-latest + + steps: + - name: Intel Apt repository + timeout-minutes: 1 + run: | + wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + rm GPG-PUB-KEY-INTEL-SW-PRODUCTS-2023.PUB + echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + sudo apt-get update + + - name: Install Intel oneAPI compilers + timeout-minutes: 5 + run: sudo apt-get install intel-oneapi-compiler-fortran intel-oneapi-compiler-dpcpp-cpp + + # optional + - name: Install Intel MPI and MKL + timeout-minutes: 5 + run: intel-oneapi-mpi intel-oneapi-mpi-devel intel-oneapi-mkl + + - name: Setup Intel oneAPI environment + run: | + source /opt/intel/oneapi/setvars.sh + printenv >> $GITHUB_ENV + - name: checkout project code + uses: actions/checkout@v4 + + - name: CMake Configure + run: | + cmake -S . -B build -D XDIAG_DISTRIBUTED=On -D CMAKE_CXX_COMPILER=icpx -D BUILD_TESTING=On + cmake --build build + + - name: run tests + run: | + ./build/tests/tests_distributed \ No newline at end of file diff --git a/README.md b/README.md index 675c609b..01526e04 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![docs](https://img.shields.io/badge/Documentation-here-red.svg)](https://awietek.github.io/xdiag) [![Linux CI](https://github.com/awietek/xdiag/actions/workflows/linux.yml/badge.svg?style=for-the-badge)](https://github.com/awietek/xdiag/actions/workflows/linux.yml) [![Mac OSX CI](https://github.com/awietek/xdiag/actions/workflows/osx.yml/badge.svg?style=for-the-badge)](https://github.com/awietek/xdiag/actions/workflows/osx.yml) +[![[Intel MPI CI](https://github.com/awietek/xdiag/actions/workflows/intelmpi.yml/badge.svg?style=for-the-badge)](https://github.com/awietek/xdiag/actions/workflows/intelmpi.yml) [![DOI](https://zenodo.org/badge/169422780.svg)](https://zenodo.org/badge/latestdoi/169422780) diff --git a/tests/algorithms/time_evolution/test_time_evolution_distributed.cpp b/tests/algorithms/time_evolution/test_time_evolution_distributed.cpp index 01fa3c7f..0ff65d7d 100644 --- a/tests/algorithms/time_evolution/test_time_evolution_distributed.cpp +++ b/tests/algorithms/time_evolution/test_time_evolution_distributed.cpp @@ -15,7 +15,7 @@ TEST_CASE("time_evolution_distributed", "[time_evolution]") try { using namespace xdiag; Log("Test time_evolution_distributed"); - + int L = 3; int n_sites = L * L; @@ -29,14 +29,13 @@ TEST_CASE("time_evolution_distributed", "[time_evolution]") try { int site = y * L + x; int right = y * L + nx; int top = ny * L + x; - ops << Op("HOP", "T", {site, right}); - ops << Op("TJISING", "JZ", {site, right}); - ops << Op("EXCHANGE", "JEX", {site, right}); - - ops << Op("HOP", "T", {site, top}); - ops << Op("TJISING", "JZ", {site, top}); - ops << Op("EXCHANGE", "JEX", {site, top}); + ops += Op("HOP", "T", {site, right}); + ops += Op("TJISING", "JZ", {site, right}); + ops += Op("EXCHANGE", "JEX", {site, right}); + ops += Op("HOP", "T", {site, top}); + ops += Op("TJISING", "JZ", {site, top}); + ops += Op("EXCHANGE", "JEX", {site, top}); } } ops["T"] = 1.0 + 0.2i; @@ -63,15 +62,14 @@ TEST_CASE("time_evolution_distributed", "[time_evolution]") try { fill(psi_0, pstate); fill(psi_0d, pstate); - auto H_psi_0 = State(block, false); apply(ops, psi_0, H_psi_0); auto H_psi_0d = State(blockd, false); apply(ops, psi_0d, H_psi_0d); - + for (int s = 0; s < n_sites; ++s) { - auto n = innerC(Op("NUMBER", s), H_psi_0); - auto nd = innerC(Op("NUMBER", s), H_psi_0d); + auto n = innerC(Op("NUMBER", 1.0, s), H_psi_0); + auto nd = innerC(Op("NUMBER", 1.0, s), H_psi_0d); // Log("i {} {} {}", s, n, nd); REQUIRE(close(n, nd)); } @@ -83,14 +81,14 @@ TEST_CASE("time_evolution_distributed", "[time_evolution]") try { auto psi = time_evolve(ops, psi_0, time, tol); auto psid = time_evolve(ops, psi_0d, time, tol); for (int s = 0; s < n_sites; ++s) { - auto n = innerC(Op("NUMBER", s), psi); - auto nd = innerC(Op("NUMBER", s), psid); + auto n = innerC(Op("NUMBER", 1.0, s), psi); + auto nd = innerC(Op("NUMBER", 1.0, s), psid); Log("{} {} {} {:.6f}", s, n, nd, time); REQUIRE(std::abs(n - nd) < 1e-6); } Log("\n"); } - } catch (xdiag::Error e) { +} catch (xdiag::Error e) { error_trace(e); } diff --git a/tests/blocks/tj_distributed/test_tj_distributed_apply.cpp b/tests/blocks/tj_distributed/test_tj_distributed_apply.cpp index c7a245f4..96967b88 100644 --- a/tests/blocks/tj_distributed/test_tj_distributed_apply.cpp +++ b/tests/blocks/tj_distributed/test_tj_distributed_apply.cpp @@ -14,8 +14,7 @@ using namespace xdiag; -void test_tjdistributed_e0_real(OpSum ops, int nup, int ndn, double e0) { - int n_sites = ops.n_sites(); +void test_tjdistributed_e0_real(OpSum ops, int n_sites, int nup, int ndn, double e0) { auto block = tJDistributed(n_sites, nup, ndn); double e0c = eigval0(ops, block); REQUIRE(std::abs(e0 - e0c) < 1e-6); @@ -33,10 +32,10 @@ TEST_CASE("tj_distributed_apply", "[tj_distributed]") try { auto block = tJDistributed(N, nup, ndn); OpSum ops; for (int i = 0; i < N; ++i) { - ops << Op("ISING", "Jz", {i, (i + 1) % N}); - ops << Op("EXCHANGE", "Jx", {i, (i + 1) % N}); - ops << Op("HOPDN", "TDN", {i, (i + 1) % N}); - ops << Op("HOPUP", "TUP", {i, (i + 1) % N}); + ops += Op("ISING", "Jz", {i, (i + 1) % N}); + ops += Op("EXCHANGE", "Jx", {i, (i + 1) % N}); + ops += Op("HOPDN", "TDN", {i, (i + 1) % N}); + ops += Op("HOPUP", "TUP", {i, (i + 1) % N}); } ops["Jz"] = 1.32; ops["Jx"] = complex(.432, .576); @@ -82,7 +81,7 @@ TEST_CASE("tj_distributed_apply", "[tj_distributed]") try { {4, 2, -2.11803398}, {5, 0, -0.99999999}, {5, 1, -0.49999999}, {6, 0, 1.500000000}}; for (auto [nup, ndn, e0] : nup_ndn_e0) { - test_tjdistributed_e0_real(ops, nup, ndn, e0); + test_tjdistributed_e0_real(ops, 6, nup, ndn, e0); } } @@ -101,7 +100,7 @@ TEST_CASE("tj_distributed_apply", "[tj_distributed]") try { {4, 2, 0.000000000}, {5, 0, -2.00000000}, {5, 1, 0.000000000}, {6, 0, 0.000000000}}; for (auto [nup, ndn, e0] : nup_ndn_e0) { - test_tjdistributed_e0_real(ops, nup, ndn, e0); + test_tjdistributed_e0_real(ops, 6, nup, ndn, e0); } } diff --git a/xdiag/basis/spinhalf_distributed/basis_sz.cpp b/xdiag/basis/spinhalf_distributed/basis_sz.cpp index 67074dc2..27f66f9d 100644 --- a/xdiag/basis/spinhalf_distributed/basis_sz.cpp +++ b/xdiag/basis/spinhalf_distributed/basis_sz.cpp @@ -117,7 +117,7 @@ BasisSz::BasisSz(int64_t n_sites, int64_t n_up) // Create the transpose communicator std::vector n_states_i_send(mpi_size_, 0); for (bit_t prefix : prefixes()) { - for (bit_t postfix : postfixes(prefix)) { + for (bit_t postfix : postfix_states(prefix)) { int target_rank = rank(postfix); ++n_states_i_send[target_rank]; } @@ -127,9 +127,9 @@ BasisSz::BasisSz(int64_t n_sites, int64_t n_up) // Create the transpose communicator (reverse) std::vector n_states_i_send_reverse(mpi_size_, 0); for (bit_t postfix : postfixes()) { - for (bit_t prefix : prefixes(postfix)) { + for (bit_t prefix : prefix_states(postfix)) { int target_rank = rank(prefix); - ++n_states_i_send_reverse[target_rank; + ++n_states_i_send_reverse[target_rank]; } } transpose_communicator_reverse_ = mpi::Communicator(n_states_i_send_reverse); @@ -204,7 +204,11 @@ std::vector const &BasisSz::prefix_states(bit_t postfix) const { return prefix_states_[n_up_prefix]; } -mpi::CommPattern &BasisSz::comm_pattern() { return comm_pattern_; } +template mpi::CommPattern &BasisSz::comm_pattern() { + return comm_pattern_; +} + +template mpi::Communicator BasisSz::transpose_communicator(bool reverse) const { return reverse ? transpose_communicator_reverse_ : transpose_communicator_; } diff --git a/xdiag/basis/spinhalf_distributed/basis_sz.hpp b/xdiag/basis/spinhalf_distributed/basis_sz.hpp index d8c2d166..c6e481e8 100644 --- a/xdiag/basis/spinhalf_distributed/basis_sz.hpp +++ b/xdiag/basis/spinhalf_distributed/basis_sz.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include diff --git a/xdiag/blocks/tj_distributed/terms/apply_exchange.hpp b/xdiag/blocks/tj_distributed/terms/apply_exchange.hpp index 7773ba20..cbe5ea94 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_exchange.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_exchange.hpp @@ -14,6 +14,8 @@ namespace xdiag::tj_distributed { template void apply_exchange(Op const &op, Basis &&basis, const coeff_t *vec_in, coeff_t *vec_out) { + using namespace bits; + assert(op.coupling_defined()); assert(op.type_defined()); assert(op.size() == 2); @@ -24,13 +26,15 @@ void apply_exchange(Op const &op, Basis &&basis, const coeff_t *vec_in, int mpi_size; MPI_Comm_size(MPI_COMM_WORLD, &mpi_size); - using namespace bits; + Coupling cpl = op.coupling(); + assert(cpl.isexplicit() && !cpl.ismatrix()); + coeff_t J = cpl.as(); + coeff_t Jhalf = J / 2.; + coeff_t Jhalf_conj = conj(Jhalf); int64_t s1 = op[0]; int64_t s2 = op[1]; - coeff_t J = op.coupling(); - coeff_t Jhalf = J / 2.; - coeff_t Jhalf_conj = xdiag::conj(Jhalf); + bit_t flipmask = ((bit_t)1 << s1) | ((bit_t)1 << s2); int64_t l = std::min(s1, s2); diff --git a/xdiag/blocks/tj_distributed/terms/apply_hopping.hpp b/xdiag/blocks/tj_distributed/terms/apply_hopping.hpp index 4d42fc6d..76019027 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_hopping.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_hopping.hpp @@ -20,13 +20,16 @@ void apply_hopping(Op const &op, Basis &&basis, const coeff_t *vec_in, std::string type = op.type(); assert((type == "HOPUP") || (type == "HOPDN")); + Coupling cpl = op.coupling(); + assert(cpl.isexplicit() && !cpl.ismatrix()); + coeff_t t = cpl.as(); + int64_t s1 = op[0]; int64_t s2 = op[1]; bit_t flipmask = ((bit_t)1 << s1) | ((bit_t)1 << s2); int64_t l = std::min(s1, s2); int64_t u = std::max(s1, s2); bit_t fermimask = (((bit_t)1 << (u - l - 1)) - 1) << (l + 1); - coeff_t t = op.coupling(); auto term_action = [&](bit_t spins) -> std::pair { bool fermi = bits::popcnt(spins & fermimask) & 1; diff --git a/xdiag/blocks/tj_distributed/terms/apply_ising.hpp b/xdiag/blocks/tj_distributed/terms/apply_ising.hpp index 1f2c04f4..b0e831e9 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_ising.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_ising.hpp @@ -17,7 +17,10 @@ void apply_ising(Op const &op, Basis &&basis, const coeff_t *vec_in, std::string type = op.type(); assert((type == "ISING") || (type == "TJISING")); - coeff_t J = op.coupling(); + Coupling cpl = op.coupling(); + assert(cpl.isexplicit() && !cpl.ismatrix()); + coeff_t J = cpl.as(); + int64_t s1 = op[0]; int64_t s2 = op[1]; bit_t s1_mask = (bit_t)1 << s1; diff --git a/xdiag/blocks/tj_distributed/terms/apply_number.hpp b/xdiag/blocks/tj_distributed/terms/apply_number.hpp index 7a04a9c9..1d39e14c 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_number.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_number.hpp @@ -16,8 +16,11 @@ void apply_number(Op const &op, Basis &&basis, const coeff_t *vec_in, std::string type = op.type(); assert((type == "NUMBERUP") || (type == "NUMBERDN")); - coeff_t mu = op.coupling(); - int64_t s = op.site(0); + Coupling cpl = op.coupling(); + assert(cpl.isexplicit() && !cpl.ismatrix()); + coeff_t mu = cpl.as(); + + int64_t s = op[0]; bit_t mask = (bit_t)1 << s; if (type == "NUMBERUP") { diff --git a/xdiag/blocks/tj_distributed/terms/apply_raise_lower.hpp b/xdiag/blocks/tj_distributed/terms/apply_raise_lower.hpp index e8850c77..731a41a0 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_raise_lower.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_raise_lower.hpp @@ -10,8 +10,8 @@ namespace xdiag::tj_distributed { template -void apply_raise_lower(Op const &op, BasisIn &&basis_in, - BasisOut &&basis_out, Fill &&fill) { +void apply_raise_lower(Op const &op, BasisIn &&basis_in, BasisOut &&basis_out, + Fill &&fill) { assert(op.coupling_defined()); assert(op.type_defined()); assert(op.size() == 1); @@ -23,7 +23,10 @@ void apply_raise_lower(Op const &op, BasisIn &&basis_in, int64_t s = op[0]; bit_t site_mask = (bit_t)1 << s; bit_t fermi_mask = site_mask - 1; - coeff_t c = op.coupling(); + + Coupling cpl = op.coupling(); + assert(cpl.isexplicit() && !cpl.ismatrix()); + coeff_t c = cpl.as(); // Raising operators if ((type == "CDAGUP") || (type == "CDAGDN")) { diff --git a/xdiag/blocks/tj_distributed/terms/apply_terms.hpp b/xdiag/blocks/tj_distributed/terms/apply_terms.hpp index 5b166a0e..e4958f57 100644 --- a/xdiag/blocks/tj_distributed/terms/apply_terms.hpp +++ b/xdiag/blocks/tj_distributed/terms/apply_terms.hpp @@ -10,7 +10,7 @@ namespace xdiag::tj_distributed { template -void apply_terms(OpList const &ops, BasisIn const &basis_in, +void apply_terms(OpSum const &ops, BasisIn const &basis_in, arma::Col const &vec_in, BasisOut const &basis_out, arma::Col &vec_out) try { (void)basis_out; diff --git a/xdiag/blocks/tj_distributed/tj_distributed_apply.cpp b/xdiag/blocks/tj_distributed/tj_distributed_apply.cpp index 20e4cd58..44297c8e 100644 --- a/xdiag/blocks/tj_distributed/tj_distributed_apply.cpp +++ b/xdiag/blocks/tj_distributed/tj_distributed_apply.cpp @@ -17,12 +17,12 @@ void apply(OpSum const &ops, tJDistributed const &block_in, XDIAG_RETHROW(e); } -template void apply(OpSum const &, tJDistributed const &, - arma::Col const &, tJDistributed const &, - arma::Col &, double); +template void apply(OpSum const &, tJDistributed const &, + arma::Col const &, tJDistributed const &, + arma::Col &, double); -template void apply(OpSum const &, tJDistributed const &, - arma::Col const &, tJDistributed const &, - arma::Col &, double); +template void apply(OpSum const &, tJDistributed const &, + arma::Col const &, tJDistributed const &, + arma::Col &, double); } // namespace xdiag diff --git a/xdiag/blocks/tj_distributed/tj_distributed_apply.hpp b/xdiag/blocks/tj_distributed/tj_distributed_apply.hpp index 71a2da50..442d3160 100644 --- a/xdiag/blocks/tj_distributed/tj_distributed_apply.hpp +++ b/xdiag/blocks/tj_distributed/tj_distributed_apply.hpp @@ -11,7 +11,7 @@ namespace xdiag { template void apply(OpSum const &ops, tJDistributed const &block_in, arma::Col const &vec_in, tJDistributed const &block_out, - arma::Col &vec_out); + arma::Col &vec_out, double zero_precision=1e-12); } // namespace xdiag #endif diff --git a/xdiag/parallel/mpi/comm_pattern.hpp b/xdiag/parallel/mpi/comm_pattern.hpp index e417738c..44c6eb69 100644 --- a/xdiag/parallel/mpi/comm_pattern.hpp +++ b/xdiag/parallel/mpi/comm_pattern.hpp @@ -8,7 +8,7 @@ namespace xdiag::mpi { class CommPattern { public: - CommPattern = default(); + CommPattern() = default; bool contains(Op const &op); Communicator const &operator[](Op const &op) const; Communicator &operator[](Op const &op); diff --git a/xdiag/utils/error.cpp b/xdiag/utils/error.cpp index d4b88d8e..e1bfdbec 100644 --- a/xdiag/utils/error.cpp +++ b/xdiag/utils/error.cpp @@ -97,7 +97,7 @@ void check_dimension_works_with_blas_int_size(int64_t dim) try { "backend, for example the ILP64 interface of IntelMKL."); } // Backend 64 bit Blas implementation - else if ((sizeof(arma::blas_int) == 8) && (dim > ((int64_t)1 << 63) - 2)) { + else if ((sizeof(arma::blas_int) == 8) && (dim > ((int64_t)1 << 62) - 2)) { XDIAG_THROW( "Trying to create a block whose dimension is too large for the " "backend BLAS routines. The block dimension requested is larger than"