diff --git a/CMakeLists.txt b/CMakeLists.txt index 33d7b0dcd5..d53eb20ed3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -332,6 +332,7 @@ set(SeQuant_src SeQuant/core/runtime.hpp SeQuant/core/space.cpp SeQuant/core/space.hpp + SeQuant/core/slotted_index.hpp SeQuant/core/tag.hpp SeQuant/core/tensor_canonicalizer.cpp SeQuant/core/tensor_canonicalizer.hpp @@ -359,6 +360,7 @@ set(SeQuant_src SeQuant/core/utility/macros.hpp SeQuant/core/utility/memoize.hpp SeQuant/core/utility/nodiscard.hpp + SeQuant/core/utility/overloads.hpp SeQuant/core/utility/permutation.hpp SeQuant/core/utility/scope.hpp SeQuant/core/utility/singleton.hpp @@ -381,6 +383,7 @@ set(SeQuant_src SeQuant/domain/mbpt/context.hpp SeQuant/domain/mbpt/convention.cpp SeQuant/domain/mbpt/convention.hpp + SeQuant/domain/mbpt/detail/concepts.hpp SeQuant/domain/mbpt/models/cc.cpp SeQuant/domain/mbpt/models/cc.hpp SeQuant/domain/mbpt/op_registry.hpp diff --git a/SeQuant/core/attr.hpp b/SeQuant/core/attr.hpp index a83e3d4067..5d8e499a17 100644 --- a/SeQuant/core/attr.hpp +++ b/SeQuant/core/attr.hpp @@ -9,6 +9,7 @@ #include #include +#include #include namespace sequant { @@ -79,6 +80,36 @@ inline std::wstring to_wolfram(BraKetPos a) { } } +/// index slot types +/// +/// @note This does not include slot bundles, like braket, etc. +enum class SlotType { + Bra, + Ket, + Aux, + Proto, +}; + +template +std::basic_ostream& operator<<( + std::basic_ostream& stream, SlotType origin) { + switch (origin) { + case SlotType::Bra: + stream << "Bra"; + break; + case SlotType::Ket: + stream << "Ket"; + break; + case SlotType::Aux: + stream << "Aux"; + break; + case SlotType::Proto: + stream << "Proto"; + break; + } + return stream; +} + enum class Statistics { FermiDirac, BoseEinstein, diff --git a/SeQuant/core/expressions/abstract_tensor.hpp b/SeQuant/core/expressions/abstract_tensor.hpp index a41699d465..329381fd1a 100644 --- a/SeQuant/core/expressions/abstract_tensor.hpp +++ b/SeQuant/core/expressions/abstract_tensor.hpp @@ -15,7 +15,6 @@ #include #include -#include #include #include #include @@ -27,31 +26,6 @@ namespace sequant { -/// index slot types -/// -/// @note This does not include slot bundles, like braket, etc. -enum class SlotType { Bra = 0, Ket = 1, Aux = 2, Proto = 3 }; - -template -std::basic_ostream& operator<<( - std::basic_ostream& stream, SlotType origin) { - switch (origin) { - case SlotType::Bra: - stream << "Bra"; - break; - case SlotType::Ket: - stream << "Ket"; - break; - case SlotType::Aux: - stream << "Aux"; - break; - case SlotType::Proto: - stream << "Proto"; - break; - } - return stream; -} - class TensorCanonicalizer; /// AbstractTensor is a [tensor](https://en.wikipedia.org/wiki/Tensor) over diff --git a/SeQuant/core/expressions/result_expr.hpp b/SeQuant/core/expressions/result_expr.hpp index bc26db069d..2e67cfb5b3 100644 --- a/SeQuant/core/expressions/result_expr.hpp +++ b/SeQuant/core/expressions/result_expr.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -102,15 +103,24 @@ class ResultExpr { // based on the particle they belong to and that bra and // ket indices are assigned to the same set of particles. for (std::size_t i = 0; i < m_braIndices.size(); ++i) { - if constexpr (std::is_constructible_v>) { + if constexpr (std::is_constructible_v< + Group, std::initializer_list>) { + groups.emplace_back(std::initializer_list{ + {m_braIndices.at(i), SlotType::Bra}, + {m_ketIndices.at(i), SlotType::Ket}}); + } else if constexpr (std::is_constructible_v< + Group, std::initializer_list>) { groups.emplace_back(std::initializer_list{m_braIndices.at(i), m_ketIndices.at(i)}); + } else if constexpr (std::is_constructible_v) { + groups.emplace_back(SlottedIndex{m_braIndices.at(i), SlotType::Bra}, + SlottedIndex{m_ketIndices.at(i), SlotType::Ket}); } else { static_assert( std::is_constructible_v, - "Group is expected to be constructible from two indices or from an " - "initializer_list of indices"); + "Group is expected to be constructible from two (slotted) indices " + "or from an initializer_list of (slotted) indices"); groups.emplace_back(m_braIndices.at(i), m_ketIndices.at(i)); } } diff --git a/SeQuant/core/meta.hpp b/SeQuant/core/meta.hpp index 23b20f76bb..8de5139f24 100644 --- a/SeQuant/core/meta.hpp +++ b/SeQuant/core/meta.hpp @@ -7,9 +7,10 @@ #include #include +#include + #include #include -#include namespace sequant { @@ -506,6 +507,81 @@ struct std_array_size> template constexpr inline std::size_t std_array_size_v = std_array_size::value; +/// make_immutable_t +/// Contrary to std::add_const_t, this works as one would expect on reference +/// types +template +using make_immutable_t = std::conditional_t< + std::is_lvalue_reference_v, + std::add_lvalue_reference_t>>, + std::conditional_t, + std::add_rvalue_reference_t< + std::add_const_t>>, + std::add_const_t>>; +static_assert(std::is_const_v>); +static_assert(std::is_const_v>); +static_assert(std::is_lvalue_reference_v>); +static_assert(std::is_lvalue_reference_v>); +static_assert( + std::is_const_v>>); +static_assert( + std::is_const_v>>); +static_assert(std::is_rvalue_reference_v>); +static_assert(std::is_rvalue_reference_v>); +static_assert( + std::is_const_v>>); +static_assert( + std::is_const_v>>); + +/// make_mutable_t +/// Contrary to std::remove_const_t, this works as one would expect on reference +/// types +template +using make_mutable_t = std::conditional_t< + std::is_lvalue_reference_v, + std::add_lvalue_reference_t< + std::remove_const_t>>, + std::conditional_t, + std::add_rvalue_reference_t< + std::remove_const_t>>, + std::remove_const_t>>; +static_assert(!std::is_const_v>); +static_assert(!std::is_const_v>); +static_assert(std::is_lvalue_reference_v>); +static_assert(std::is_lvalue_reference_v>); +static_assert( + !std::is_const_v>>); +static_assert( + !std::is_const_v>>); +static_assert(std::is_rvalue_reference_v>); +static_assert(std::is_rvalue_reference_v>); +static_assert( + !std::is_const_v>>); +static_assert( + !std::is_const_v>>); + +/// is_immutable_v +/// Contrary to std::is_const_v, this works as one would expect on reference +/// types +template +constexpr bool is_immutable_v = std::is_const_v>; +static_assert(is_immutable_v); +static_assert(!is_immutable_v); +static_assert(is_immutable_v); +static_assert(!is_immutable_v); +static_assert(is_immutable_v); +static_assert(!is_immutable_v); + +/// mimic_constness_t +/// Makes To const, if From is const, else makes To non-const +template +using mimic_constness_t = + std::conditional_t, make_immutable_t, + make_mutable_t>; +static_assert( + std::same_as, const float &>); +static_assert(std::same_as, float &>); + } // namespace meta } // namespace sequant diff --git a/SeQuant/core/slotted_index.hpp b/SeQuant/core/slotted_index.hpp new file mode 100644 index 0000000000..4c655813df --- /dev/null +++ b/SeQuant/core/slotted_index.hpp @@ -0,0 +1,42 @@ +#ifndef SEQUANT_SLOTTED_INDEX_H +#define SEQUANT_SLOTTED_INDEX_H + +#include +#include + +namespace sequant { + +/// Combination of an Index along with information about the Slot it occupies +/// +/// @note Usage of this class only makes sense, if the index in question does +/// not appear in multiple slots +/// +/// @sa Index +/// @sa Slot +class SlottedIndex { + public: + SlottedIndex(Index idx, SlotType slot) + : idx_(std::move(idx)), slot_(std::move(slot)) {} + + Index &index() { return idx_; } + + const Index &index() const { return idx_; } + + SlotType slot_type() const { return slot_; } + + friend bool operator==(const SlottedIndex &lhs, const SlottedIndex &rhs) { + return lhs.index() == rhs.index() && lhs.slot_type() == rhs.slot_type(); + } + + friend bool operator!=(const SlottedIndex &lhs, const SlottedIndex &rhs) { + return !(lhs == rhs); + } + + private: + Index idx_; + SlotType slot_; +}; + +} // namespace sequant + +#endif diff --git a/SeQuant/core/utility/indices.hpp b/SeQuant/core/utility/indices.hpp index 504ca00661..e348547ac1 100644 --- a/SeQuant/core/utility/indices.hpp +++ b/SeQuant/core/utility/indices.hpp @@ -1,20 +1,25 @@ #ifndef SEQUANT_CORE_UTILITY_INDICES_HPP #define SEQUANT_CORE_UTILITY_INDICES_HPP +#include #include #include #include +#include #include #include +#include #include #include #include +#include #include #include #include #include +#include #include #include @@ -434,8 +439,11 @@ std::string csv_labels(Rng&& idxs) { /// /// @see get_bra_idx /// @see get_ket_idx -template >> -Container external_indices(const Expr& expr) { +template