6#if defined BUILD_YOUNG_TABLEAU
10#include <similie/csr/csr.hpp>
11#include <similie/csr/csr_dynamic.hpp>
12#include <similie/misc/macros.hpp>
13#include <similie/misc/permutation_parity.hpp>
14#include <similie/misc/specialization.hpp>
15#include <similie/misc/stride.hpp>
16#include <similie/tensor/dummy_index.hpp>
17#include <similie/tensor/prime.hpp>
18#include <similie/tensor/tensor_impl.hpp>
22namespace young_tableau {
26template <
class T, T... Args>
27constexpr T sum(std::integer_sequence<T, Args...> = {})
34template <
class... Row>
38 using shape = std::index_sequence<Row::size()...>;
40 static constexpr std::size_t rank = detail::sum(shape());
46template <std::
size_t I, std::
size_t Id,
class TableauSeq>
49template <std::size_t I, std::size_t Id,
class HeadRow,
class... TailRow>
50struct ExtractRow<I, Id, YoungTableauSeq<HeadRow, TailRow...>>
52 using type = std::conditional_t<
55 typename ExtractRow<I, Id + 1, YoungTableauSeq<TailRow...>>::type>;
58template <std::
size_t I, std::
size_t Id>
59struct ExtractRow<I, Id, YoungTableauSeq<>>
61 using type = std::index_sequence<>;
64template <std::
size_t I,
class TableauSeq>
65using extract_row_t = ExtractRow<I, 0, TableauSeq>::type;
73 class InterestTableauSeq,
84 class... TailOfTailRow>
89 YoungTableauSeq<HeadRow...>,
90 YoungTableauSeq<InterestRow>,
91 YoungTableauSeq<HeadOfTailRow, TailOfTailRow...>>
93 using type = std::conditional_t<
95 YoungTableauSeq<HeadRow..., RowToSet, HeadOfTailRow, TailOfTailRow...>,
100 YoungTableauSeq<HeadRow..., InterestRow>,
101 YoungTableauSeq<HeadOfTailRow>,
102 YoungTableauSeq<TailOfTailRow...>>::type>;
105template <std::size_t I, std::size_t Id,
class RowToSet,
class... HeadRow,
class InterestRow>
110 YoungTableauSeq<HeadRow...>,
111 YoungTableauSeq<InterestRow>,
114 using type = YoungTableauSeq<HeadRow..., RowToSet>;
117template <std::
size_t I,
class RowToSet,
class TableauSeq>
118struct OverrideRowHelper;
120template <std::size_t I,
class RowToSet,
class InterestRow,
class... TailRow>
121struct OverrideRowHelper<I, RowToSet, YoungTableauSeq<InterestRow, TailRow...>>
123 using type = OverrideRow<
128 YoungTableauSeq<InterestRow>,
129 YoungTableauSeq<TailRow...>>::type;
132template <std::
size_t I,
class RowToSet,
class TableauSeq>
133using override_row_t = OverrideRowHelper<I, RowToSet, TableauSeq>::type;
136template <
class Row, std::
size_t Value>
139template <std::size_t... Elem, std::size_t Value>
140struct AddCellToRow<std::index_sequence<Elem...>, Value>
142 using type = std::index_sequence<Elem..., Value>;
145template <
class Row, std::
size_t Value>
146using add_cell_to_row_t = AddCellToRow<Row, Value>::type;
149template <
class Tableau, std::
size_t I, std::
size_t Value>
150struct AddCellToTableau;
152template <
class... Row, std::size_t I, std::size_t Value>
153struct AddCellToTableau<YoungTableauSeq<Row...>, I, Value>
155 using type = detail::override_row_t<
157 add_cell_to_row_t<extract_row_t<I, YoungTableauSeq<Row...>>, Value>,
158 YoungTableauSeq<Row...>>;
161template <
class Tableau, std::
size_t I, std::
size_t Value>
162using add_cell_to_tableau_t = AddCellToTableau<Tableau, I, Value>::type;
165template <
class TableauDual,
class Tableau, std::
size_t I, std::
size_t J>
170 std::size_t HeadElemOfHeadRow,
171 std::size_t... TailElemOfHeadRow,
177 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
181 using type = std::conditional_t<
182 sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0,
183 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
185 sizeof...(TailElemOfHeadRow) == 0,
187 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
188 YoungTableauSeq<TailRow...>,
192 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
193 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
198template <
class TableauDual,
class... TailRow, std::size_t I, std::size_t J>
199struct Dual<TableauDual, YoungTableauSeq<std::index_sequence<>, TailRow...>, I, J>
201 using type = YoungTableauSeq<>;
204template <
class TableauDual, std::
size_t I, std::
size_t J>
205struct Dual<TableauDual, YoungTableauSeq<>, I, J>
207 using type = TableauDual;
210template <
class Tableau>
213template <std::size_t... ElemOfHeadRow,
class... TailRow>
214struct DualHelper<YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>>
217 = Dual<YoungTableauSeq<std::conditional_t<
219 std::index_sequence<>,
220 std::index_sequence<>>...>,
221 YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>,
227struct DualHelper<YoungTableauSeq<>>
229 using type = YoungTableauSeq<>;
232template <
class Tableau>
233using dual_t = DualHelper<Tableau>::type;
236template <
class TableauHooks,
class Tableau,
class Shape, std::
size_t I, std::
size_t J>
241 std::size_t HeadElemOfHeadRow,
242 std::size_t... TailElemOfHeadRow,
244 std::size_t HeadRowSize,
245 std::size_t... TailRowSize,
250 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
251 std::index_sequence<HeadRowSize, TailRowSize...>,
255 using type = std::conditional_t<
256 sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0,
257 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
259 sizeof...(TailElemOfHeadRow) == 0,
261 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
262 YoungTableauSeq<TailRow...>,
263 std::index_sequence<TailRowSize...>,
267 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
268 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
269 std::index_sequence<HeadRowSize, TailRowSize...>,
274template <
class TableauHooks,
class... TailRow,
class Shape, std::size_t I, std::size_t J>
275struct Hooks<TableauHooks, YoungTableauSeq<std::index_sequence<>, TailRow...>, Shape, I, J>
277 using type = YoungTableauSeq<>;
280template <
class TableauHooks,
class Shape, std::
size_t I, std::
size_t J>
281struct Hooks<TableauHooks, YoungTableauSeq<>, Shape, I, J>
283 using type = TableauHooks;
286template <
class Tableau>
289template <
class... Row>
290struct HooksHelper<YoungTableauSeq<Row...>>
293 = Hooks<YoungTableauSeq<std::conditional_t<true, std::index_sequence<>, Row>...>,
294 YoungTableauSeq<Row...>,
295 typename YoungTableauSeq<Row...>::shape,
301struct HooksHelper<YoungTableauSeq<>>
303 using type = YoungTableauSeq<>;
306template <
class Tableau>
307using hooks_t = HooksHelper<Tableau>::type;
310template <
class TableauHookLengths,
class Tableau1,
class Tableau2, std::
size_t I>
314 class TableauHookLengths,
315 std::size_t HeadElemOfHeadRow1,
316 std::size_t... TailElemOfHeadRow1,
318 std::size_t HeadElemOfHeadRow2,
319 std::size_t... TailElemOfHeadRow2,
325 std::index_sequence<HeadElemOfHeadRow1, TailElemOfHeadRow1...>,
328 std::index_sequence<HeadElemOfHeadRow2, TailElemOfHeadRow2...>,
332 using type = std::conditional_t<
333 sizeof...(TailRow1) == 0 &&
sizeof...(TailElemOfHeadRow1) == 0,
334 add_cell_to_tableau_t<
337 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
339 sizeof...(TailElemOfHeadRow1) == 0,
340 typename HookLengths<
341 add_cell_to_tableau_t<
344 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
345 YoungTableauSeq<TailRow1...>,
346 YoungTableauSeq<TailRow2...>,
348 typename HookLengths<
349 add_cell_to_tableau_t<
352 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
354 std::index_sequence<TailElemOfHeadRow1...>,
357 std::index_sequence<TailElemOfHeadRow2...>,
362template <
class TableauHookLengths,
class... TailRow1,
class... TailRow2, std::size_t I>
365 YoungTableauSeq<std::index_sequence<>, TailRow1...>,
366 YoungTableauSeq<std::index_sequence<>, TailRow2...>,
369 using type = YoungTableauSeq<>;
372template <
class TableauHookLengths, std::
size_t I>
373struct HookLengths<TableauHookLengths, YoungTableauSeq<>, YoungTableauSeq<>, I>
375 using type = TableauHookLengths;
378template <
class Tableau1,
class Tableau2>
379struct HookLengthsHelper;
381template <
class... Row1,
class Tableau2>
382struct HookLengthsHelper<YoungTableauSeq<Row1...>, Tableau2>
384 using type = HookLengths<
385 YoungTableauSeq<std::conditional_t<true, std::index_sequence<>, Row1>...>,
386 YoungTableauSeq<Row1...>,
392struct HookLengthsHelper<YoungTableauSeq<>, YoungTableauSeq<>>
394 using type = YoungTableauSeq<>;
397template <
class Tableau1,
class Tableau2>
398using hook_lengths_t = HookLengthsHelper<Tableau1, Tableau2>::type;
401template <std::
size_t Dimension,
class TableauHookLengths, std::
size_t I, std::
size_t J>
405 std::size_t Dimension,
406 std::size_t HeadElemOfHeadRow,
407 std::size_t... TailElemOfHeadRow,
413 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
417 static consteval std::size_t run(
double prod)
419 prod *= Dimension + J - I;
420 prod /= HeadElemOfHeadRow;
421 if constexpr (
sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0) {
423 }
else if constexpr (
sizeof...(TailElemOfHeadRow) == 0) {
424 return IrrepDim<Dimension, YoungTableauSeq<TailRow...>, I + 1, 0>::run(prod);
428 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
440template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
444 using tableau_seq = TableauSeq;
445 using shape =
typename TableauSeq::shape;
448 static constexpr std::size_t s_d = Dimension;
449 static constexpr std::size_t s_r = TableauSeq::rank;
452 using dual = YoungTableau<s_d, detail::dual_t<tableau_seq>>;
453 using hook_lengths = detail::hook_lengths_t<
454 detail::hooks_t<tableau_seq>,
455 detail::dual_t<detail::hooks_t<detail::dual_t<tableau_seq>>>>;
458 static constexpr std::size_t s_irrep_dim = detail::IrrepDim<s_d, hook_lengths, 0, 0>::run(1);
460 static constexpr std::string generate_tag();
462 static constexpr std::string s_tag = generate_tag();
464 static consteval auto load_irrep();
466 static constexpr auto s_irrep = load_irrep();
471 static constexpr std::size_t dimension()
476 static constexpr std::size_t rank()
481 static constexpr std::size_t irrep_dim()
486 static constexpr std::string tag()
492 static constexpr std::size_t n_nonzeros_in_irrep()
494 return std::get<2>(std::get<0>(s_irrep)).size();
498 template <tensor::TensorNatIndex... Id>
499 using projector_domain = ddc::DiscreteDomain<tensor::prime<Id>..., Id...>;
501 template <tensor::TensorNatIndex... Id>
502 static auto projector();
504 template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
505 static constexpr csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...> u(
506 ddc::DiscreteDomain<Id...> restricted_domain);
508 template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
509 static constexpr csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...> v(
510 ddc::DiscreteDomain<Id...> restricted_domain);
515template <std::size_t Dimension,
class... TailRow, std::size_t I, std::size_t J>
516struct IrrepDim<Dimension, YoungTableauSeq<std::index_sequence<>, TailRow...>, I, J>
518 static consteval std::size_t run(
double prod)
524template <std::
size_t Dimension, std::
size_t I, std::
size_t J>
525struct IrrepDim<Dimension, YoungTableauSeq<>, I, J>
527 static consteval std::size_t run(
double prod)
537 class LayoutStridedPolicy,
540tensor::Tensor<ElementType, ddc::DiscreteDomain<Id...>, LayoutStridedPolicy, MemorySpace>
542 tensor::Tensor<ElementType, ddc::DiscreteDomain<Id...>, LayoutStridedPolicy, MemorySpace>
544 csr::CsrDynamic<BasisId, Id...> basis,
545 std::size_t max_basis_id)
547 ddc::Chunk eigentensor_alloc(
548 ddc::DiscreteDomain<BasisId, Id...>(basis.domain()),
549 ddc::HostAllocator<double>());
550 tensor::Tensor eigentensor(eigentensor_alloc);
551 for (ddc::DiscreteElement<BasisId> elem : ddc::DiscreteDomain<BasisId>(
552 ddc::DiscreteElement<BasisId>(0),
553 ddc::DiscreteVector<BasisId>(max_basis_id))) {
554 csr::csr2dense(eigentensor, basis.get(elem));
556 ddc::Chunk scalar_prod_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
557 tensor::Tensor scalar_prod(scalar_prod_alloc);
558 tensor::tensor_prod(scalar_prod, tensor, eigentensor[ddc::DiscreteElement<BasisId>(0)]);
559 ddc::Chunk norm_squared_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
560 tensor::Tensor norm_squared(norm_squared_alloc);
561 tensor::tensor_prod(norm_squared, eigentensor, eigentensor);
563 eigentensor *= -1. * scalar_prod(ddc::DiscreteElement<>())
564 / norm_squared(ddc::DiscreteElement<>());
565 tensor += eigentensor[ddc::DiscreteElement<BasisId>(0)];
571std::vector<bool> index_hamming_weight_code(std::size_t index, std::size_t length)
573 std::size_t count = 0;
574 std::vector<bool> bits(length);
575 for (std::size_t hamming_weight = 0; hamming_weight < length; ++hamming_weight) {
576 std::fill(bits.begin(), bits.begin() + hamming_weight,
true);
577 std::fill(bits.begin() + hamming_weight, bits.end(),
false);
579 if (count == index) {
583 }
while (std::prev_permutation(bits.begin(), bits.end()));
585 assert(
false &&
"hamming weight code not found for index");
590struct BasisId : tensor::TensorNaturalIndex<>
595struct OrthonormalBasisSubspaceEigenvalueOne;
597template <
class... Id>
598struct OrthonormalBasisSubspaceEigenvalueOne<tensor::TensorFullIndex<Id...>>
600 template <
class YoungTableau>
601 static std::pair<csr::CsrDynamic<BasisId, Id...>, csr::CsrDynamic<BasisId, Id...>> run(
602 YoungTableau tableau)
604 auto [proj_alloc, proj] = tableau.template projector<Id...>();
606 tensor::TensorAccessor<Id...> candidate_accessor;
607 ddc::DiscreteDomain<Id...> candidate_dom = candidate_accessor.domain();
608 ddc::Chunk candidate_alloc(candidate_dom, ddc::HostAllocator<double>());
609 tensor::Tensor candidate(candidate_alloc);
610 ddc::Chunk prod_alloc(
611 tensor::natural_tensor_prod_domain(proj.domain(), candidate.domain()),
612 ddc::HostAllocator<double>());
613 tensor::Tensor prod(prod_alloc);
615 ddc::DiscreteDomain<BasisId, Id...> basis_dom(
616 ddc::DiscreteDomain<BasisId>(
617 ddc::DiscreteElement<BasisId>(0),
618 ddc::DiscreteVector<BasisId>(tableau.irrep_dim())),
620 csr::CsrDynamic<BasisId, Id...> u(basis_dom);
621 csr::CsrDynamic<BasisId, Id...> v(basis_dom);
622 std::size_t n_irreps = 0;
623 std::size_t index = 0;
624 while (n_irreps < tableau.irrep_dim()) {
626 std::vector<bool> hamming_weight_code
627 = index_hamming_weight_code(index, (Id::size() * ...));
629 SIMILIE_DEBUG_LOG(
"similie_init_young_tableau_candidate");
630 ddc::parallel_for_each(
631 "similie_init_young_tableau_candidate",
632 Kokkos::DefaultHostExecutionSpace(),
634 [&](ddc::DiscreteElement<Id...> elem) {
635 candidate(elem) = hamming_weight_code[(
636 (misc::detail::stride<Id, Id...>() * elem.template uid<Id>())
640 tensor::tensor_prod(prod, proj, candidate);
641 SIMILIE_DEBUG_LOG(
"similie_compute_young_tableau_candidate_copy");
643 candidate.allocation_kokkos_view(),
644 prod.allocation_kokkos_view());
646 orthogonalize(candidate, v, n_irreps);
648 if (ddc ::host_transform_reduce(
651 ddc::reducer::lor<bool>(),
652 [&](ddc::DiscreteElement<Id...> elem) { return candidate(elem) > 1e-6; })) {
654 norm_squared_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
655 tensor::Tensor norm_squared(norm_squared_alloc);
656 tensor::tensor_prod(norm_squared, candidate, candidate);
657 SIMILIE_DEBUG_LOG(
"similie_normalize_young_tableau_candidate");
658 ddc::parallel_for_each(
659 "similie_normalize_young_tableau_candidate",
660 Kokkos::DefaultHostExecutionSpace(),
662 [&](ddc::DiscreteElement<Id...> elem) {
663 candidate(elem) /= Kokkos::sqrt(norm_squared(ddc::DiscreteElement<>()));
666 u.push_back(candidate);
667 v.push_back(candidate);
669 std::cout << n_irreps <<
"/" << tableau.irrep_dim()
670 <<
" eigentensors found associated to the eigenvalue 1 for the Young "
671 "projector labelized "
672 << tableau.tag() << std::endl;
675 return std::pair<csr::CsrDynamic<BasisId, Id...>, csr::CsrDynamic<BasisId, Id...>>(u, v);
681template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
682YoungTableau<Dimension, TableauSeq>::YoungTableau()
686 std::ifstream file(IRREPS_DICT_PATH, std::ios::out | std::ios::binary);
688 while (!file.eof()) {
692 if (n_nonzeros_in_irrep() == 0) {
693 std::cout <<
"\033[1;31mIrrep " << s_tag <<
" in dimension " << s_d
694 <<
" required and found in dictionnary " << IRREPS_DICT_PATH
695 <<
" but the executable has been compiled without it. Please "
705 std::cout <<
"\033[1;31mIrrep " << s_tag <<
" corresponding to the Young Tableau:\033[0m\n"
706 << *
this <<
"\n\033[1;31min dimension " << s_d
707 <<
" required but not found in dictionnary " << IRREPS_DICT_PATH
708 <<
". It will be computed, and you will have to recompile once it is done.\033[0m"
712 = detail::OrthonormalBasisSubspaceEigenvalueOne<tensor::dummy_index_t<s_d, s_r>>::run(
715 std::ofstream file(IRREPS_DICT_PATH, std::ios::app | std::ios::binary);
717 std::cerr <<
"Error opening file: " << IRREPS_DICT_PATH << std::endl;
720 file << s_tag <<
"\n";
726 std::cerr <<
"Error occurred while writing to file " << IRREPS_DICT_PATH
727 <<
" while adding irrep " << s_tag << std::endl;
729 std::cout <<
"\033[1;32mIrrep " << s_tag <<
" added to the dictionnary " << IRREPS_DICT_PATH
730 <<
".\033[0m \033[1;31mPlease recompile.\033[0m" << std::endl;
737template <
class OId,
class... Id>
738using symmetrizer_index_t = std::conditional_t<
739 (ddc::type_seq_rank_v<OId, ddc::detail::TypeSeq<Id...>> < (
sizeof...(Id) / 2)),
741 ddc::type_seq_element_t<
742 static_cast<std::size_t
>(
744 max(
static_cast<std::ptrdiff_t
>(0),
745 static_cast<std::ptrdiff_t
>(
746 ddc::type_seq_rank_v<OId, ddc::detail::TypeSeq<Id...>>
747 - (
sizeof...(Id) / 2)))),
748 ddc::detail::TypeSeq<Id...>>>;
751template <std::size_t Dimension, std::size_t Rank,
class... NaturalId>
755 using TensorType = tensor::Tensor<
757 ddc::DiscreteDomain<NaturalId...>,
758 Kokkos::layout_right,
759 Kokkos::DefaultHostExecutionSpace::memory_space>;
762 std::array<std::size_t, Rank> idx_to_permute;
765 TrFunctor(TensorType t_, std::array<std::size_t, Rank> idx_to_permute_)
767 , idx_to_permute(idx_to_permute_)
771 void operator()(ddc::DiscreteElement<NaturalId...> elem)
const
773 std::array<std::size_t,
sizeof...(NaturalId)> elem_array = ddc::detail::array(elem);
774 bool has_to_be_one =
true;
775 for (std::size_t i = 0; i < Rank; ++i) {
777 = has_to_be_one && (elem_array[i] == elem_array[idx_to_permute[i] + Rank]);
785template <std::size_t Dimension,
bool AntiSym,
class... Id>
786static tensor::Tensor<
788 ddc::DiscreteDomain<Id...>,
789 Kokkos::layout_right,
790 Kokkos::DefaultHostExecutionSpace::memory_space>
794 ddc::DiscreteDomain<Id...>,
795 Kokkos::layout_right,
796 Kokkos::DefaultHostExecutionSpace::memory_space> sym,
797 std::array<std::size_t,
sizeof...(Id) / 2> idx_to_permute)
799 ddc::Chunk tr_alloc(sym.domain(), ddc::HostAllocator<double>());
800 tensor::Tensor tr(tr_alloc);
801 ddc::parallel_fill(tr, 0);
804 TrFunctor<Dimension,
sizeof...(Id) / 2, Id...>(tr, idx_to_permute));
806 if constexpr (AntiSym) {
807 tr *=
static_cast<double>(misc::permutation_parity(idx_to_permute));
818template <std::
size_t Nt, std::
size_t Ns>
819static std::vector<std::array<std::size_t, Nt>> permutations_subset(
820 std::array<std::size_t, Nt> t,
821 std::array<std::size_t, Ns> subset_values)
823 std::array<std::size_t, Ns> subset_indices;
824 std::array<std::size_t, Ns> elements_to_permute;
826 for (std::size_t i = 0; i < t.size(); ++i) {
827 if (std::find(subset_values.begin(), subset_values.end(), t[i] + 1)
828 != std::end(subset_values)) {
829 subset_indices[j] = i;
830 elements_to_permute[j++] = t[i];
834 std::vector<std::array<std::size_t, Nt>> result;
836 std::array<std::size_t, Nt> tmp = t;
837 for (std::size_t i = 0; i < Ns; ++i) {
838 tmp[subset_indices[i]] = elements_to_permute[i];
840 result.push_back(tmp);
841 }
while (std::next_permutation(elements_to_permute.begin(), elements_to_permute.end()));
847template <
class PartialTableauSeq, std::
size_t Dimension,
bool AntiSym = false>
850template <std::size_t... ElemOfHeadRow,
class... TailRow, std::size_t Dimension,
bool AntiSym>
852 YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>,
856 template <
class... Id>
857 static tensor::Tensor<
859 ddc::DiscreteDomain<Id...>,
860 Kokkos::layout_right,
861 Kokkos::DefaultHostExecutionSpace::memory_space>
864 ddc::DiscreteDomain<Id...>,
865 Kokkos::layout_right,
866 Kokkos::DefaultHostExecutionSpace::memory_space> proj)
868 if constexpr (
sizeof...(ElemOfHeadRow) >= 2) {
870 tensor::TensorAccessor<symmetrizer_index_t<Id, Id...>...> sym_accessor;
871 ddc::DiscreteDomain<symmetrizer_index_t<Id, Id...>...> sym_dom = sym_accessor.domain();
873 ddc::Chunk sym_alloc(sym_dom, ddc::HostAllocator<double>());
874 tensor::Tensor sym(sym_alloc);
875 ddc::parallel_fill(sym, 0);
876 std::array<std::size_t,
sizeof...(Id) / 2> idx_to_permute;
877 for (std::size_t i = 0; i <
sizeof...(Id) / 2; ++i) {
878 idx_to_permute[i] = i;
880 std::array<std::size_t,
sizeof...(ElemOfHeadRow)> row_values {ElemOfHeadRow...};
881 auto idx_permutations = detail::permutations_subset(
884 for (std::size_t i = 0; i < idx_permutations.size(); ++i) {
888 symmetrizer_index_t<Id, Id...>...>(sym, idx_permutations[i]);
892 ddc::Chunk prod_alloc(
894 ddc::HostAllocator<double>());
895 tensor::Tensor prod(prod_alloc);
896 tensor::tensor_prod(prod, sym, proj);
898 proj.allocation_kokkos_view(),
899 prod.allocation_kokkos_view());
901 if constexpr (
sizeof...(TailRow) == 0) {
904 return Projector<YoungTableauSeq<TailRow...>, Dimension, AntiSym>::run(proj);
911template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
912template <tensor::TensorNatIndex... Id>
913auto YoungTableau<Dimension, TableauSeq>::projector()
915 static_assert(
sizeof...(Id) == s_r);
916 tensor::TensorAccessor<tensor::prime<Id>..., Id...> proj_accessor;
917 ddc::DiscreteDomain<tensor::prime<Id>..., Id...> proj_dom = proj_accessor.domain();
920 ddc::Chunk proj_alloc(proj_dom, ddc::HostAllocator<double>());
921 tensor::Tensor proj(proj_alloc);
922 ddc::parallel_fill(proj, 0);
923 std::array<std::size_t, s_r> idx_to_permute;
924 for (std::size_t i = 0; i < s_r; ++i) {
925 idx_to_permute[i] = i;
929 detail::TrFunctor<s_d, s_r, tensor::prime<Id>..., Id...>(proj, idx_to_permute));
932 detail::Projector<tableau_seq, s_d>::run(proj);
933 detail::Projector<typename dual::tableau_seq, s_d, true>::run(proj);
934 return std::make_tuple(std::move(proj_alloc), proj);
938template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
939template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
940constexpr csr::Csr<YoungTableau<Dimension, TableauSeq>::n_nonzeros_in_irrep(), BasisId, Id...>
941YoungTableau<Dimension, TableauSeq>::u(ddc::DiscreteDomain<Id...> restricted_domain)
943 if constexpr (n_nonzeros_in_irrep() != 0) {
944 ddc::DiscreteDomain<BasisId, Id...>
945 domain(ddc::DiscreteDomain<BasisId>(
946 ddc::DiscreteElement<BasisId>(0),
947 ddc::DiscreteVector<BasisId>(n_nonzeros_in_irrep())),
950 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
952 std::get<0>(std::get<0>(s_irrep)),
953 std::get<1>(std::get<0>(s_irrep)),
954 std::get<2>(std::get<0>(s_irrep)));
956 ddc::DiscreteDomain<BasisId, Id...>
957 domain(ddc::DiscreteDomain<BasisId>(
958 ddc::DiscreteElement<BasisId>(0),
959 ddc::DiscreteVector<BasisId>(0)),
962 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
964 std::array<std::size_t, BasisId::mem_size() + 1> {},
965 std::get<1>(std::get<0>(s_irrep)),
966 std::get<2>(std::get<0>(s_irrep)));
970template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
971template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
972constexpr csr::Csr<YoungTableau<Dimension, TableauSeq>::n_nonzeros_in_irrep(), BasisId, Id...>
973YoungTableau<Dimension, TableauSeq>::v(ddc::DiscreteDomain<Id...> restricted_domain)
975 if constexpr (n_nonzeros_in_irrep() != 0) {
976 ddc::DiscreteDomain<BasisId, Id...>
977 domain(ddc::DiscreteDomain<BasisId>(
978 ddc::DiscreteElement<BasisId>(0),
979 ddc::DiscreteVector<BasisId>(n_nonzeros_in_irrep())),
982 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
984 std::get<0>(std::get<1>(s_irrep)),
985 std::get<1>(std::get<1>(s_irrep)),
986 std::get<2>(std::get<1>(s_irrep)));
988 ddc::DiscreteDomain<BasisId, Id...>
989 domain(ddc::DiscreteDomain<BasisId>(
990 ddc::DiscreteElement<BasisId>(0),
991 ddc::DiscreteVector<BasisId>(0)),
994 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
996 std::array<std::size_t, BasisId::mem_size() + 1> {},
997 std::get<1>(std::get<1>(s_irrep)),
998 std::get<2>(std::get<1>(s_irrep)));
1005template <std::
size_t Line>
1006consteval std::string_view load_irrep_line_for_tag(std::string_view
const tag)
1008 constexpr static char raw[] = {
1009#embed IRREPS_DICT_PATH
1012 constexpr static std::string_view str(raw,
sizeof(raw));
1014 size_t tagPos = str.find(tag);
1016 if (tagPos != std::string::npos) {
1017 std::size_t endOfTagLine = str.find(
'\n', tagPos);
1018 if (endOfTagLine != std::string::npos) {
1019 std::size_t nextLineStart = endOfTagLine + 1;
1020 for (std::size_t i = 0; i < Line; ++i) {
1021 nextLineStart = str.find(
"break\n", nextLineStart) + 6;
1023 std::size_t nextLineEnd = str.find(
"break\n", nextLineStart);
1025 return std::string_view(str.data() + nextLineStart, nextLineEnd - nextLineStart);
1032template <
class Ids, std::
size_t Offset>
1033struct LoadIrrepIdxForTag;
1035template <std::size_t... I, std::size_t Offset>
1036struct LoadIrrepIdxForTag<std::index_sequence<I...>, Offset>
1038 static consteval std::array<std::string_view,
sizeof...(I)> run(std::string_view
const tag)
1040 return std::array<std::string_view,
sizeof...(I)> {
1041 load_irrep_line_for_tag<I + Offset>(tag)...};
1045template <
class T, std::
size_t N, std::
size_t I = 0>
1046consteval std::array<T, N> bit_cast_array(
1047 std::array<T, N> vec,
1048 std::string_view
const str,
1049 std::string_view
const tag)
1051 if constexpr (I == N) {
1054 std::array<char,
sizeof(T) /
sizeof(
char)> chars = {};
1055 for (std::size_t j = 0; j <
sizeof(T) /
sizeof(char); ++j) {
1056 chars[j] = str[
sizeof(T) /
sizeof(
char) * I + j];
1059 vec[I] = std::bit_cast<T>(
1061 return bit_cast_array<T, N, I + 1>(vec, str, tag);
1065template <
class T, std::
size_t N, std::
size_t I = 0>
1066consteval std::array<T, N> bit_cast_array(std::string_view
const str, std::string_view
const tag)
1068 std::array<T, N> vec {};
1069 return bit_cast_array<T, N>(vec, str, tag);
1072template <
class T, std::
size_t N,
class Ids>
1073struct BitCastArrayOfArrays;
1075template <
class T, std::size_t N, std::size_t... I>
1076struct BitCastArrayOfArrays<T, N, std::index_sequence<I...>>
1078 static consteval std::array<std::array<T, N>,
sizeof...(I)> run(
1079 std::array<std::string_view,
sizeof...(I)>
const str,
1080 std::string_view
const tag)
1082 return std::array<std::array<T, N>,
sizeof...(I)> {bit_cast_array<T, N>(str[I], tag)...};
1088template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1089consteval auto YoungTableau<Dimension, TableauSeq>::load_irrep()
1091 static constexpr std::string_view str_u_coalesc_idx(detail::load_irrep_line_for_tag<0>(s_tag));
1092 static constexpr std::array<std::string_view, s_r> str_u_idx(
1093 detail::LoadIrrepIdxForTag<std::make_index_sequence<s_r>, 1>::run(s_tag));
1094 static constexpr std::string_view str_u_values(detail::load_irrep_line_for_tag<s_r + 1>(s_tag));
1095 static constexpr std::string_view str_v_coalesc_idx(
1096 detail::load_irrep_line_for_tag<s_r + 2>(s_tag));
1097 static constexpr std::array<std::string_view, s_r> str_v_idx(
1098 detail::LoadIrrepIdxForTag<std::make_index_sequence<s_r>, s_r + 3>::run(s_tag));
1099 static constexpr std::string_view str_v_values(
1100 detail::load_irrep_line_for_tag<2 * s_r + 3>(s_tag));
1102 if constexpr (str_u_values.size() != 0) {
1103 static constexpr std::array u_coalesc_idx = detail::bit_cast_array<
1105 str_u_coalesc_idx.size() /
sizeof(std::size_t)>(str_u_coalesc_idx, s_tag);
1106 static constexpr std::array u_idx = detail::BitCastArrayOfArrays<
1108 str_u_idx[0].size() /
sizeof(std::size_t),
1109 std::make_index_sequence<s_r>>::run(str_u_idx, s_tag);
1110 static constexpr std::array u_values = detail::
1111 bit_cast_array<double, str_u_values.size() /
sizeof(double)>(str_u_values, s_tag);
1112 static constexpr std::array v_coalesc_idx = detail::bit_cast_array<
1114 str_v_coalesc_idx.size() /
sizeof(std::size_t)>(str_v_coalesc_idx, s_tag);
1115 static constexpr std::array v_idx = detail::BitCastArrayOfArrays<
1117 str_v_idx[0].size() /
sizeof(std::size_t),
1118 std::make_index_sequence<s_r>>::run(str_v_idx, s_tag);
1119 static constexpr std::array v_values = detail::
1120 bit_cast_array<double, str_v_values.size() /
sizeof(double)>(str_v_values, s_tag);
1121 return std::make_pair(
1122 std::make_tuple(u_coalesc_idx, u_idx, u_values),
1123 std::make_tuple(v_coalesc_idx, v_idx, v_values));
1125 return std::make_pair(
1127 std::array<std::size_t, 1> {0},
1128 std::array<std::array<std::size_t, 0>, s_r> {},
1129 std::array<double, 0> {}),
1131 std::array<std::size_t, 1> {0},
1132 std::array<std::array<std::size_t, 0>, s_r> {},
1133 std::array<double, 0> {}));
1141struct YoungTableauRowToArray;
1143template <std::size_t... RowElement>
1144struct YoungTableauRowToArray<std::index_sequence<RowElement...>>
1146 static constexpr auto run()
1148 static constexpr std::array row = {RowElement...};
1153template <
class TableauSeq>
1154struct YoungTableauToArray;
1156template <
class... Row>
1157struct YoungTableauToArray<YoungTableauSeq<Row...>>
1159 static constexpr auto run()
1161 static constexpr std::tuple tableau = {YoungTableauRowToArray<Row>::run()...};
1166template <
bool RowDelimiter>
1169 template <std::
size_t N>
1170 static constexpr std::array<char, 2 * N - !RowDelimiter> run(
1171 const std::array<std::size_t, N>& array)
1173 std::array<char, 2 * N - !RowDelimiter> buf = {};
1175 std::size_t current_pos = 0;
1176 for (std::size_t i = 0; i < N; ++i) {
1178 auto [ptr, ec] = std::to_chars(temp, temp +
sizeof(temp), array[i]);
1179 if (ec != std::errc()) {
1180 throw std::runtime_error(
"Failed to convert number to string");
1183 for (
char* p = temp; p < ptr; ++p) {
1184 buf[current_pos++] = *p;
1188 buf[current_pos++] =
'_';
1192 if constexpr (RowDelimiter) {
1193 buf[2 * N - 1] =
'l';
1200template <std::size_t... sizes>
1201constexpr auto concatenate(
const std::array<char, sizes>&... arrays)
1203 std::array<char, (sizes + ...)> result;
1204 std::size_t index {};
1206 ((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...);
1211template <
class RowIdx>
1212struct ArrayToString;
1214template <std::size_t... RowId>
1215struct ArrayToString<std::index_sequence<RowId...>>
1217 template <
class Tuple>
1218 static constexpr auto run(Tuple
const tableau)
1221 RowToString < RowId !=
sizeof...(RowId) - 1 > ::run(std::get<RowId>(tableau))...);
1225template <std::
size_t size>
1226constexpr auto add_dimension(
const std::array<char, size>& array, std::size_t d)
1228 std::array<char, size + 2> result;
1230 std::to_chars(temp, temp + 1, d);
1231 std::copy_n(array.begin(), size, result.begin());
1233 result[size + 1] = temp[0];
1240template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1241constexpr std::string YoungTableau<Dimension, TableauSeq>::generate_tag()
1243 static constexpr std::tuple tableau = detail::YoungTableauToArray<tableau_seq>::run();
1244 constexpr auto row_str_wo_dimension
1245 = detail::ArrayToString<std::make_index_sequence<tableau_seq::shape::size()>>::run(
1247 constexpr auto row_str = detail::add_dimension(row_str_wo_dimension, s_d);
1248 return std::string(row_str.begin(), row_str.end());
1254template <
class TableauSeq>
1255struct PrintYoungTableauSeq;
1257template <std::size_t HeadRowHeadElement, std::size_t... HeadRowTailElement,
class... TailRow>
1258struct PrintYoungTableauSeq<
1259 YoungTableauSeq<std::index_sequence<HeadRowHeadElement, HeadRowTailElement...>, TailRow...>>
1261 static std::string run(std::string str)
1263 str += std::to_string(HeadRowHeadElement) +
" ";
1264 if constexpr (
sizeof...(TailRow) == 0 &&
sizeof...(HeadRowTailElement) == 0) {
1265 }
else if constexpr (
sizeof...(HeadRowTailElement) == 0) {
1267 str = PrintYoungTableauSeq<YoungTableauSeq<TailRow...>>::run(str);
1269 str = PrintYoungTableauSeq<
1270 YoungTableauSeq<std::index_sequence<HeadRowTailElement...>, TailRow...>>::
1278struct PrintYoungTableauSeq<YoungTableauSeq<>>
1280 static std::string run(std::string str)
1288template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1289std::ostream&
operator<<(std::ostream& os, YoungTableau<Dimension, TableauSeq>
const& tableau)
1291 std::string str =
"";
1292 os << detail::PrintYoungTableauSeq<TableauSeq>::run(str);
std::ostream & operator<<(std::ostream &os, Csr< N, TensorIndex... > const &csr)
natural_tensor_prod_domain_t< Dom1, Dom2 > natural_tensor_prod_domain(Dom1 dom1, Dom2 dom2)
The top-level namespace of SimiLie.