Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
e1dba87
set hardcoded biorthogonal coeffs till rank 7
ABesharat Oct 13, 2025
1323fc6
rank 7
ABesharat Oct 13, 2025
897a42a
discard redundant assertion
ABesharat Oct 13, 2025
a22809c
better name: computed_coefficients
ABesharat Oct 13, 2025
dbcd4e5
add hardcoded file to cmakelist
ABesharat Oct 13, 2025
8fd5be0
v2: correct rescaling factor
ABesharat Oct 13, 2025
47ccfe1
renaming original coeffs to computed_coefficients
ABesharat Oct 13, 2025
93829df
Merge remote-tracking branch 'origin/azam/feature/hardcoded_biorthogo…
ABesharat Oct 13, 2025
70ef68a
renaming
ABesharat Nov 11, 2025
4fc0898
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Dec 8, 2025
fc0dcda
discard old coefficients
ABesharat Dec 8, 2025
f309f62
discard only the old coefficients, not num_perms
ABesharat Dec 8, 2025
b5da4b8
no inline anymore for performance
ABesharat Dec 10, 2025
25bb6f4
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Dec 10, 2025
3926bde
at max rank 6 is enough
ABesharat Dec 10, 2025
e485b9c
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Dec 12, 2025
87b8177
test_eval_ta: add rank 4 nns test, fix rank 3
ABesharat Dec 13, 2025
5ca6d55
test_eval_btas: fix nns for rank 3
ABesharat Dec 13, 2025
188825c
add hardcoded biortho coeffs and nns projection
ABesharat Dec 13, 2025
8e66ac7
fix include
ABesharat Dec 13, 2025
1dc89b3
use hardcoded biortho coeffs for rank<=6, otherwise use computed ones
ABesharat Dec 13, 2025
53b47be
do not call nns with int type ,use hardcoded nns for rank<=6, otherwi…
ABesharat Dec 13, 2025
a28d886
make libperm public to build the same order of permutations
ABesharat Dec 13, 2025
ab8f453
fix include for Eigen!
ABesharat Dec 13, 2025
d5b20f6
change the name of hardcoded nns fn
ABesharat Dec 14, 2025
278dcc3
renaming again!
ABesharat Dec 14, 2025
aede8b3
renaming hardcoded_biortho_coeffs fn
ABesharat Dec 14, 2025
4b1a92f
change assert to SEQUANT_ASSERT
ABesharat Dec 15, 2025
8ee5a57
no need to have rescaling for v2. new nns is enough for restoring WK …
ABesharat Dec 18, 2025
a3345c4
documentation correction
ABesharat Dec 18, 2025
78dc616
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Dec 18, 2025
d2323d0
use abort for calling nns with int type
ABesharat Dec 21, 2025
0f4ab0c
normalization factor of S
ABesharat Dec 22, 2025
acc25f8
Remove additional print statements, cleaning
ABesharat Dec 25, 2025
877e3d4
address the requested changes
ABesharat Dec 25, 2025
0a60656
address the requested changes, except the namespace
ABesharat Dec 26, 2025
14fbd13
extract libperm calls into a helper function to avoid public dependency
ABesharat Dec 27, 2025
f4a0c82
Optimize build command with parallel jobs
ABesharat Dec 28, 2025
7087e16
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Dec 28, 2025
519e68a
a better name: biorth_threshold
ABesharat Jan 3, 2026
2e67e8e
use default threshold for compute_nns_p_matricx to avoid an additiona…
ABesharat Jan 3, 2026
aa7a41c
add some documentations
ABesharat Jan 11, 2026
69ab3a1
clear documentation
ABesharat Jan 12, 2026
af93394
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Jan 12, 2026
2d10389
apply encapsulation for nns
ABesharat Jan 15, 2026
a9a17b1
memoize nns_projection weights
ABesharat Jan 16, 2026
afed9c4
add include
ABesharat Jan 16, 2026
1ca7fa6
dox cleanup
evaleev Jan 16, 2026
ff05b7c
nns_projection_weights: no third lock needed to return the result
evaleev Jan 16, 2026
4732bf5
removed the no-longer-used biorthogonalization_hardcoded.ipp
evaleev Jan 16, 2026
ecde7eb
memoize biorthogonal coeffs by lambda to have separate cache for hard…
ABesharat Jan 16, 2026
5f490ef
Merge remote-tracking branch 'refs/remotes/origin/azam/feature/hardco…
ABesharat Jan 16, 2026
333f296
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Jan 16, 2026
6697a4e
Merge remote-tracking branch 'refs/remotes/origin/master' into azam/f…
ABesharat Jan 16, 2026
8f42dac
remove the redundant header include
ABesharat Jan 16, 2026
2e171a8
move Eigen usage from public header to implementation
ABesharat Jan 16, 2026
370bd30
remove the redundant header include
ABesharat Jan 16, 2026
e6adbab
biorthogonalization.cpp: forward declaration to avoid having Eigen in…
ABesharat Jan 16, 2026
72dac7e
move hardcoded contents to biorthogonalization.cpp and hpp
ABesharat Jan 17, 2026
711e460
add to header file to keep the documentation
ABesharat Jan 17, 2026
f8f3115
make compute-nns compact
ABesharat Jan 18, 2026
9d98421
using auto instead of std::size_t
ABesharat Jan 21, 2026
c3a6c07
remove biorthogonalization from IR since it is too domain-specific
evaleev Jan 21, 2026
c8cf5b9
fix the cmake
ABesharat Jan 21, 2026
6c138ef
fix nns call in eval_ta and eval_btas
ABesharat Jan 22, 2026
5b64bdd
refactor SQ/eval to live in core/eval and separate backend-specific a…
evaleev Jan 23, 2026
93fab50
Merge pull request #465 from ValeevGroup/evaleev/feature/conditional-…
bimalgaudel Jan 23, 2026
30f76e0
fix Copilot suggestions
ABesharat Jan 23, 2026
40663b4
biorthogonalization: renames/restruct
evaleev Jan 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 48 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ set(SEQUANT_INSTALL_CMAKEDIR "lib/cmake/sequant"
############################
option(SEQUANT_BENCHMARKS "Enable SeQuant benchmarks" ${PROJECT_IS_TOP_LEVEL})
option(SEQUANT_UTILITIES "Enable SeQuant utility programs" ${PROJECT_IS_TOP_LEVEL})
option(SEQUANT_EVAL_TESTS "OBSOLETE: use SEQUANT_TILEDARRAY and SEQUANT_BTAS" OFF)
option(SEQUANT_BTAS "Enable BTAS eval backend" ${SEQUANT_EVAL_TESTS})
add_feature_info(SEQUANT_EVAL_BTAS SEQUANT_BTAS "Enable BTAS eval backend")
option(SEQUANT_TILEDARRAY "Enable TiledArray eval backend" ${SEQUANT_EVAL_TESTS})
add_feature_info(SEQUANT_EVAL_TILEDARRAY SEQUANT_TILEDARRAY "Enable TiledArray eval backend")

option(SEQUANT_IWYU "Whether to use the include-what-you-use tool (if found)" OFF)
option(SEQUANT_WARNINGS_AS_ERRORS "Whether to treat compiler warnings as errors" ${PROJECT_IS_TOP_LEVEL})
Expand Down Expand Up @@ -260,9 +265,9 @@ set(SeQuant_src
SeQuant/core/container.hpp
SeQuant/core/context.cpp
SeQuant/core/context.hpp
SeQuant/core/eval_expr.cpp
SeQuant/core/eval_expr.hpp
SeQuant/core/eval_node.hpp
SeQuant/core/eval/eval_expr.cpp
SeQuant/core/eval/eval_expr.hpp
SeQuant/core/eval/eval_node.hpp
SeQuant/core/export/compute_selection.cpp
SeQuant/core/export/compute_selection.hpp
SeQuant/core/export/context.cpp
Expand Down Expand Up @@ -405,20 +410,44 @@ set_source_files_properties(
)

### optional prereqs
if (SEQUANT_EVAL_TESTS)
include(FindOrFetchTiledArray)
endif (SEQUANT_EVAL_TESTS)

if (TARGET tiledarray)
set(SEQUANT_HAS_EVAL OFF) # do not build SQ/eval unless there is a backend
if (SEQUANT_TILEDARRAY)
if (NOT TARGET tiledarray)
include(FindOrFetchTiledArray)
endif()
set(SEQUANT_HAS_EVAL ON)
set(SEQUANT_HAS_TILEDARRAY ON)
endif ()
if (SEQUANT_BTAS)
if (NOT TARGET BTAS::BTAS)
include(FindOrFetchBTAS)
endif()
set(SEQUANT_HAS_EVAL ON)
set(SEQUANT_HAS_BTAS ON)
endif ()

if (SEQUANT_HAS_EVAL)
list(APPEND SeQuant_src
SeQuant/core/eval/cache_manager.cpp
SeQuant/core/eval/cache_manager.hpp
SeQuant/core/eval/eval.hpp
SeQuant/core/eval/result.cpp
SeQuant/core/eval/result.hpp
SeQuant/core/eval/eval_fwd.hpp
SeQuant/core/eval/fwd.hpp
)
if (SEQUANT_HAS_TILEDARRAY)
list(APPEND SeQuant_src
SeQuant/core/eval/backends/tiledarray/eval_expr.hpp
SeQuant/core/eval/backends/tiledarray/result.hpp
SeQuant/core/eval/backends/tiledarray/result.cpp
)
endif ()
if (SEQUANT_HAS_BTAS)
list(APPEND SeQuant_src
SeQuant/core/eval/backends/btas/eval_expr.hpp
SeQuant/core/eval/backends/btas/result.hpp
)
endif ()
endif ()

add_library(SeQuant
Expand Down Expand Up @@ -451,9 +480,17 @@ if (Boost_IS_MODULARIZED)
Boost::spirit
)
endif()
if (TARGET tiledarray)
if (SEQUANT_HAS_EVAL)
target_compile_definitions(SeQuant PUBLIC SEQUANT_HAS_EVAL=1)
if (SEQUANT_HAS_TILEDARRAY)
target_link_libraries(SeQuant PUBLIC tiledarray)
endif ()
target_compile_definitions(SeQuant PUBLIC SEQUANT_HAS_TILEDARRAY=1)
endif ()
if (SEQUANT_HAS_BTAS)
target_link_libraries(SeQuant PUBLIC BTAS::BTAS)
target_compile_definitions(SeQuant PUBLIC SEQUANT_HAS_BTAS=1)
endif ()
endif()
if (SEQUANT_HAS_EXECUTION_HEADER_STANDALONE OR SEQUANT_HAS_EXECUTION_HEADER_WITH_TBB)
target_compile_definitions(SeQuant PUBLIC SEQUANT_HAS_EXECUTION_HEADER)
if (SEQUANT_HAS_EXECUTION_HEADER_WITH_TBB)
Expand Down
70 changes: 70 additions & 0 deletions SeQuant/core/eval/backends/btas/eval_expr.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#ifndef SEQUANT_EVAL_BACKENDS_BTAS_EVAL_EXPR_HPP
#define SEQUANT_EVAL_BACKENDS_BTAS_EVAL_EXPR_HPP

#ifdef SEQUANT_HAS_BTAS

#include <SeQuant/core/eval/eval_expr.hpp>

#include <SeQuant/core/container.hpp>
#include <SeQuant/core/hash.hpp>
#include <SeQuant/core/index.hpp>

#include <range/v3/view.hpp>

namespace sequant {

///
/// \brief This class extends the EvalExpr class by adding an annot() method so
/// that it can be used to evaluate using BTAS.
///
class EvalExprBTAS final : public EvalExpr {
public:
using annot_t = container::svector<long>;

///
/// \param bk iterable of Index objects.
/// \return vector of long-type hash values
/// of the labels of indices in \c bk
///
template <typename Iterable>
static auto index_hash(Iterable&& bk) {
return ranges::views::transform(
std::forward<Iterable>(bk), [](auto const& idx) {
//
// WARNING!
// The BTAS uses long for scalar indexing by default.
// Hence, here we explicitly cast the size_t values to long
// Which is a potentially narrowing conversion leading to
// integral overflow. Hence, the values in the returned
// container are mixed negative and positive integers (long type)
//
return static_cast<long>(sequant::hash::value(Index{idx}.label()));
});
}

template <typename... Args, typename = std::enable_if_t<
std::is_constructible_v<EvalExpr, Args...>>>
EvalExprBTAS(Args&&... args) : EvalExpr{std::forward<Args>(args)...} {
annot_ = index_hash(canon_indices()) | ranges::to<annot_t>;
}

///
/// \return Annotation (container::svector<long>) for BTAS::Tensor.
///
[[nodiscard]] inline annot_t const& annot() const noexcept { return annot_; }

private:
annot_t annot_;
};

/// Type alias for BTAS evaluation nodes
using EvalNodeBTAS = EvalNode<EvalExprBTAS>;

static_assert(meta::eval_node<EvalNodeBTAS>);
static_assert(meta::can_evaluate<EvalNodeBTAS>);

} // namespace sequant

#endif // SEQUANT_HAS_BTAS

#endif // SEQUANT_EVAL_BACKENDS_BTAS_EVAL_EXPR_HPP
217 changes: 217 additions & 0 deletions SeQuant/core/eval/backends/btas/result.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
#ifndef SEQUANT_EVAL_BACKENDS_BTAS_RESULT_HPP
#define SEQUANT_EVAL_BACKENDS_BTAS_RESULT_HPP

#ifdef SEQUANT_HAS_BTAS

#include <SeQuant/core/eval/result.hpp>

#include <btas/btas.h>

namespace sequant {

namespace {

///
/// \brief This function implements the symmetrization of btas::Tensor.
///
/// \param arr The tensor to be symmetrized.
///
/// \pre The rank of the tensor must be even.
///
/// \return The symmetrized btas::Tensor.
///
template <typename... Args>
auto column_symmetrize_btas(btas::Tensor<Args...> const& arr) {
using ranges::views::iota;

size_t const rank = arr.rank();

if (rank % 2 != 0)
throw std::domain_error("This function only supports even-ranked tensors");

perm_t perm = iota(size_t{0}, rank) | ranges::to<perm_t>;

auto const lannot = perm;

auto result = btas::Tensor<Args...>{arr.range()};
result.fill(0);

auto call_back = [&result, &lannot, &arr, &perm = std::as_const(perm)]() {
btas::Tensor<Args...> temp;
btas::permute(arr, lannot, temp, perm);
result += temp;
};

auto const nparticles = rank / 2;
symmetric_permutation(SymmetricParticleRange{perm.begin(), //
perm.begin() + nparticles, //
nparticles},
call_back);

return result;
}

///
/// \brief This function implements the antisymmetrization of btas::Tensor.
///
/// \param arr The tensor to be antisymmetrized
///
/// \param bra_rank The rank of the bra indices
///
/// \return The antisymmetrized btas::Tensor.
///
template <typename... Args>
auto particle_antisymmetrize_btas(btas::Tensor<Args...> const& arr,
size_t bra_rank) {
using ranges::views::concat;
using ranges::views::iota;
size_t const rank = arr.rank();
SEQUANT_ASSERT(bra_rank <= rank);
size_t const ket_rank = rank - bra_rank;

perm_t bra_perm = iota(size_t{0}, bra_rank) | ranges::to<perm_t>;
perm_t ket_perm = iota(bra_rank, rank) | ranges::to<perm_t>;
const auto lannot = iota(size_t{0}, rank) | ranges::to<perm_t>;

auto process_permutations = [&lannot](const btas::Tensor<Args...>& input_arr,
size_t range_rank, perm_t range_perm,
const perm_t& other_perm, bool is_bra) {
if (range_rank <= 1) return input_arr;
btas::Tensor<Args...> result{input_arr.range()};

auto callback = [&](int parity) {
const auto annot =
is_bra ? concat(range_perm, other_perm) | ranges::to<perm_t>()
: concat(other_perm, range_perm) | ranges::to<perm_t>();

typename decltype(result)::numeric_type p_ = parity == 0 ? 1 : -1;
btas::Tensor<Args...> temp;
btas::permute(input_arr, lannot, temp, annot);
btas::scal(p_, temp);
result += temp;
};

antisymmetric_permutation(ParticleRange{range_perm.begin(), range_rank},
callback);
return result;
};
// Process bra permutations first
const auto ket_annot = ket_rank == 0 ? perm_t{} : ket_perm;
auto result = process_permutations(arr, bra_rank, bra_perm, ket_annot, true);

// Process ket permutations if needed
const auto bra_annot = bra_rank == 0 ? perm_t{} : bra_perm;
result = process_permutations(result, ket_rank, ket_perm, bra_annot, false);

return result;
}

} // namespace

///
/// \brief Result for a tensor value of btas::Tensor type.
/// \tparam T btas::Tensor type. Must be a specialization of btas::Tensor.
///
template <typename T>
class ResultTensorBTAS final : public Result {
public:
using Result::id_t;
using numeric_type = typename T::numeric_type;

explicit ResultTensorBTAS(T arr) : Result{std::move(arr)} {}

private:
// TODO make it same as that used by EvalExprBTAS class from eval.hpp file
using annot_t = container::svector<long>;
using annot_wrap = Annot<annot_t>;

[[nodiscard]] id_t type_id() const noexcept override {
return id_for_type<ResultTensorBTAS<T>>();
}

[[nodiscard]] ResultPtr sum(
Result const& other,
std::array<std::any, 3> const& annot) const override {
SEQUANT_ASSERT(other.is<ResultTensorBTAS<T>>());
auto const a = annot_wrap{annot};

T lres, rres;
btas::permute(get<T>(), a.lannot, lres, a.this_annot);
btas::permute(other.get<T>(), a.rannot, rres, a.this_annot);
return eval_result<ResultTensorBTAS<T>>(lres + rres);
}

[[nodiscard]] ResultPtr prod(Result const& other,
std::array<std::any, 3> const& annot,
DeNest /*DeNestFlag*/) const override {
auto const a = annot_wrap{annot};

if (other.is<ResultScalar<numeric_type>>()) {
T result;
btas::permute(get<T>(), a.lannot, result, a.this_annot);
btas::scal(other.as<ResultScalar<numeric_type>>().value(), result);
return eval_result<ResultTensorBTAS<T>>(std::move(result));
}

SEQUANT_ASSERT(other.is<ResultTensorBTAS<T>>());

if (a.this_annot.empty()) {
T rres;
btas::permute(other.get<T>(), a.rannot, rres, a.lannot);
return eval_result<ResultScalar<numeric_type>>(btas::dot(get<T>(), rres));
}

T result;
btas::contract(numeric_type{1}, //
get<T>(), a.lannot, //
other.get<T>(), a.rannot, //
numeric_type{0}, //
result, a.this_annot);
return eval_result<ResultTensorBTAS<T>>(std::move(result));
}

[[nodiscard]] ResultPtr mult_by_phase(std::int8_t factor) const override {
auto pre = get<T>();
btas::scal(numeric_type(factor), pre);
return eval_result<ResultTensorBTAS<T>>(std::move(pre));
}

[[nodiscard]] ResultPtr permute(
std::array<std::any, 2> const& ann) const override {
auto const pre_annot = std::any_cast<annot_t>(ann[0]);
auto const post_annot = std::any_cast<annot_t>(ann[1]);
T result;
btas::permute(get<T>(), pre_annot, result, post_annot);
return eval_result<ResultTensorBTAS<T>>(std::move(result));
}

void add_inplace(Result const& other) override {
auto& t = get<T>();
auto const& o = other.get<T>();
SEQUANT_ASSERT(t.range() == o.range());
t += o;
}

[[nodiscard]] ResultPtr symmetrize() const override {
return eval_result<ResultTensorBTAS<T>>(column_symmetrize_btas(get<T>()));
}

[[nodiscard]] ResultPtr antisymmetrize(size_t bra_rank) const override {
return eval_result<ResultTensorBTAS<T>>(
particle_antisymmetrize_btas(get<T>(), bra_rank));
}

private:
[[nodiscard]] std::size_t size_in_bytes() const final {
static_assert(std::is_arithmetic_v<typename T::value_type>);
const auto& tensor = get<T>();
// only count data
return tensor.range().volume() * sizeof(T);
}
};

} // namespace sequant

#endif // SEQUANT_HAS_BTAS

#endif // SEQUANT_EVAL_BACKENDS_BTAS_RESULT_HPP
Loading