10#include <Eigen/SparseCore>
14#include <oneapi/tbb.h>
18template <
typename Scalar>
19Eigen::SparseMatrix<Scalar, Eigen::RowMajor>
22 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix1,
23 const Eigen::SparseMatrix<Scalar, Eigen::RowMajor> &matrix2) {
25 constexpr real_t numerical_precision = 100 * std::numeric_limits<real_t>::epsilon();
27 oneapi::tbb::concurrent_vector<Eigen::Triplet<Scalar>> triplets;
30 oneapi::tbb::parallel_for(
31 oneapi::tbb::blocked_range<Eigen::Index>(0, matrix1.outerSize()), [&](
const auto &range) {
32 for (Eigen::Index row1 = range.begin(); row1 != range.end(); ++row1) {
34 const auto &range_row2 = basis_final->get_index_range(row1);
37 for (auto row2 = static_cast<Eigen::Index>(range_row2.min());
38 row2 < static_cast<Eigen::Index>(range_row2.max()); ++row2) {
40 Eigen::Index row = basis_final->get_ket_index_from_tuple(row1, row2);
46 for (typename Eigen::SparseMatrix<Scalar, Eigen::RowMajor>::InnerIterator it1(
50 Eigen::Index col1 = it1.col();
51 Scalar value1 = it1.value();
55 Eigen::Index begin_idxptr2 = matrix2.outerIndexPtr()[row2];
56 Eigen::Index end_idxptr2 = matrix2.outerIndexPtr()[row2 + 1];
60 const auto &range_col2 = basis_initial->get_index_range(it1.index());
62 std::distance(matrix2.innerIndexPtr() + begin_idxptr2,
63 std::lower_bound(matrix2.innerIndexPtr() + begin_idxptr2,
64 matrix2.innerIndexPtr() + end_idxptr2,
70 for (Eigen::Index idxptr2 = begin_idxptr2; idxptr2 < end_idxptr2;
73 Eigen::Index col2 = matrix2.innerIndexPtr()[idxptr2];
74 if (col2 >= static_cast<Eigen::Index>(range_col2.max())) {
78 Eigen::Index col = basis_initial->get_ket_index_from_tuple(col1, col2);
83 Scalar value2 = matrix2.valuePtr()[idxptr2];
86 Scalar value = value1 * value2;
87 if (std::abs(value) > numerical_precision) {
88 triplets.emplace_back(row, col, value);
97 Eigen::SparseMatrix<Scalar, Eigen::RowMajor> matrix(basis_final->get_number_of_kets(),
98 basis_initial->get_number_of_kets());
99 matrix.setFromTriplets(triplets.begin(), triplets.end());
100 matrix.makeCompressed();
106template Eigen::SparseMatrix<double, Eigen::RowMajor>
108 const std::shared_ptr<
const BasisPair<double>> &,
109 const Eigen::SparseMatrix<double, Eigen::RowMajor> &,
110 const Eigen::SparseMatrix<double, Eigen::RowMajor> &);
111template Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor>
113 const std::shared_ptr<
const BasisPair<std::complex<double>>> &,
114 const Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor> &,
115 const Eigen::SparseMatrix<std::complex<double>, Eigen::RowMajor> &);
Eigen::SparseMatrix< Scalar, Eigen::RowMajor > calculate_tensor_product(const std::shared_ptr< const BasisPair< Scalar > > &basis_initial, const std::shared_ptr< const BasisPair< Scalar > > &basis_final, const Eigen::SparseMatrix< Scalar, Eigen::RowMajor > &matrix1, const Eigen::SparseMatrix< Scalar, Eigen::RowMajor > &matrix2)