6#if defined BUILD_YOUNG_TABLEAU
10#include <similie/csr/csr.hpp>
11#include <similie/csr/csr_dynamic.hpp>
12#include <similie/misc/permutation_parity.hpp>
13#include <similie/misc/specialization.hpp>
14#include <similie/misc/stride.hpp>
15#include <similie/tensor/dummy_index.hpp>
16#include <similie/tensor/prime.hpp>
17#include <similie/tensor/tensor_impl.hpp>
21namespace young_tableau {
25template <
class T, T... Args>
26constexpr T sum(std::integer_sequence<T, Args...> = {})
33template <
class... Row>
37 using shape = std::index_sequence<Row::size()...>;
39 static constexpr std::size_t rank = detail::sum(shape());
45template <std::
size_t I, std::
size_t Id,
class TableauSeq>
48template <std::size_t I, std::size_t Id,
class HeadRow,
class... TailRow>
49struct ExtractRow<I, Id, YoungTableauSeq<HeadRow, TailRow...>>
51 using type = std::conditional_t<
54 typename ExtractRow<I, Id + 1, YoungTableauSeq<TailRow...>>::type>;
57template <std::
size_t I, std::
size_t Id>
58struct ExtractRow<I, Id, YoungTableauSeq<>>
60 using type = std::index_sequence<>;
63template <std::
size_t I,
class TableauSeq>
64using extract_row_t = ExtractRow<I, 0, TableauSeq>::type;
72 class InterestTableauSeq,
83 class... TailOfTailRow>
88 YoungTableauSeq<HeadRow...>,
89 YoungTableauSeq<InterestRow>,
90 YoungTableauSeq<HeadOfTailRow, TailOfTailRow...>>
92 using type = std::conditional_t<
94 YoungTableauSeq<HeadRow..., RowToSet, HeadOfTailRow, TailOfTailRow...>,
99 YoungTableauSeq<HeadRow..., InterestRow>,
100 YoungTableauSeq<HeadOfTailRow>,
101 YoungTableauSeq<TailOfTailRow...>>::type>;
104template <std::size_t I, std::size_t Id,
class RowToSet,
class... HeadRow,
class InterestRow>
109 YoungTableauSeq<HeadRow...>,
110 YoungTableauSeq<InterestRow>,
113 using type = YoungTableauSeq<HeadRow..., RowToSet>;
116template <std::
size_t I,
class RowToSet,
class TableauSeq>
117struct OverrideRowHelper;
119template <std::size_t I,
class RowToSet,
class InterestRow,
class... TailRow>
120struct OverrideRowHelper<I, RowToSet, YoungTableauSeq<InterestRow, TailRow...>>
122 using type = OverrideRow<
127 YoungTableauSeq<InterestRow>,
128 YoungTableauSeq<TailRow...>>::type;
131template <std::
size_t I,
class RowToSet,
class TableauSeq>
132using override_row_t = OverrideRowHelper<I, RowToSet, TableauSeq>::type;
135template <
class Row, std::
size_t Value>
138template <std::size_t... Elem, std::size_t Value>
139struct AddCellToRow<std::index_sequence<Elem...>, Value>
141 using type = std::index_sequence<Elem..., Value>;
144template <
class Row, std::
size_t Value>
145using add_cell_to_row_t = AddCellToRow<Row, Value>::type;
148template <
class Tableau, std::
size_t I, std::
size_t Value>
149struct AddCellToTableau;
151template <
class... Row, std::size_t I, std::size_t Value>
152struct AddCellToTableau<YoungTableauSeq<Row...>, I, Value>
154 using type = detail::override_row_t<
156 add_cell_to_row_t<extract_row_t<I, YoungTableauSeq<Row...>>, Value>,
157 YoungTableauSeq<Row...>>;
160template <
class Tableau, std::
size_t I, std::
size_t Value>
161using add_cell_to_tableau_t = AddCellToTableau<Tableau, I, Value>::type;
164template <
class TableauDual,
class Tableau, std::
size_t I, std::
size_t J>
169 std::size_t HeadElemOfHeadRow,
170 std::size_t... TailElemOfHeadRow,
176 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
180 using type = std::conditional_t<
181 sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0,
182 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
184 sizeof...(TailElemOfHeadRow) == 0,
186 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
187 YoungTableauSeq<TailRow...>,
191 add_cell_to_tableau_t<TableauDual, J, HeadElemOfHeadRow>,
192 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
197template <
class TableauDual,
class... TailRow, std::size_t I, std::size_t J>
198struct Dual<TableauDual, YoungTableauSeq<std::index_sequence<>, TailRow...>, I, J>
200 using type = YoungTableauSeq<>;
203template <
class TableauDual, std::
size_t I, std::
size_t J>
204struct Dual<TableauDual, YoungTableauSeq<>, I, J>
206 using type = TableauDual;
209template <
class Tableau>
212template <std::size_t... ElemOfHeadRow,
class... TailRow>
213struct DualHelper<YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>>
216 = Dual<YoungTableauSeq<std::conditional_t<
218 std::index_sequence<>,
219 std::index_sequence<>>...>,
220 YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>,
226struct DualHelper<YoungTableauSeq<>>
228 using type = YoungTableauSeq<>;
231template <
class Tableau>
232using dual_t = DualHelper<Tableau>::type;
235template <
class TableauHooks,
class Tableau,
class Shape, std::
size_t I, std::
size_t J>
240 std::size_t HeadElemOfHeadRow,
241 std::size_t... TailElemOfHeadRow,
243 std::size_t HeadRowSize,
244 std::size_t... TailRowSize,
249 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
250 std::index_sequence<HeadRowSize, TailRowSize...>,
254 using type = std::conditional_t<
255 sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0,
256 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
258 sizeof...(TailElemOfHeadRow) == 0,
260 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
261 YoungTableauSeq<TailRow...>,
262 std::index_sequence<TailRowSize...>,
266 add_cell_to_tableau_t<TableauHooks, I, HeadRowSize - J>,
267 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
268 std::index_sequence<HeadRowSize, TailRowSize...>,
273template <
class TableauHooks,
class... TailRow,
class Shape, std::size_t I, std::size_t J>
274struct Hooks<TableauHooks, YoungTableauSeq<std::index_sequence<>, TailRow...>, Shape, I, J>
276 using type = YoungTableauSeq<>;
279template <
class TableauHooks,
class Shape, std::
size_t I, std::
size_t J>
280struct Hooks<TableauHooks, YoungTableauSeq<>, Shape, I, J>
282 using type = TableauHooks;
285template <
class Tableau>
288template <
class... Row>
289struct HooksHelper<YoungTableauSeq<Row...>>
292 = Hooks<YoungTableauSeq<std::conditional_t<true, std::index_sequence<>, Row>...>,
293 YoungTableauSeq<Row...>,
294 typename YoungTableauSeq<Row...>::shape,
300struct HooksHelper<YoungTableauSeq<>>
302 using type = YoungTableauSeq<>;
305template <
class Tableau>
306using hooks_t = HooksHelper<Tableau>::type;
309template <
class TableauHookLengths,
class Tableau1,
class Tableau2, std::
size_t I>
313 class TableauHookLengths,
314 std::size_t HeadElemOfHeadRow1,
315 std::size_t... TailElemOfHeadRow1,
317 std::size_t HeadElemOfHeadRow2,
318 std::size_t... TailElemOfHeadRow2,
324 std::index_sequence<HeadElemOfHeadRow1, TailElemOfHeadRow1...>,
327 std::index_sequence<HeadElemOfHeadRow2, TailElemOfHeadRow2...>,
331 using type = std::conditional_t<
332 sizeof...(TailRow1) == 0 &&
sizeof...(TailElemOfHeadRow1) == 0,
333 add_cell_to_tableau_t<
336 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
338 sizeof...(TailElemOfHeadRow1) == 0,
339 typename HookLengths<
340 add_cell_to_tableau_t<
343 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
344 YoungTableauSeq<TailRow1...>,
345 YoungTableauSeq<TailRow2...>,
347 typename HookLengths<
348 add_cell_to_tableau_t<
351 HeadElemOfHeadRow1 + HeadElemOfHeadRow2 - 1>,
353 std::index_sequence<TailElemOfHeadRow1...>,
356 std::index_sequence<TailElemOfHeadRow2...>,
361template <
class TableauHookLengths,
class... TailRow1,
class... TailRow2, std::size_t I>
364 YoungTableauSeq<std::index_sequence<>, TailRow1...>,
365 YoungTableauSeq<std::index_sequence<>, TailRow2...>,
368 using type = YoungTableauSeq<>;
371template <
class TableauHookLengths, std::
size_t I>
372struct HookLengths<TableauHookLengths, YoungTableauSeq<>, YoungTableauSeq<>, I>
374 using type = TableauHookLengths;
377template <
class Tableau1,
class Tableau2>
378struct HookLengthsHelper;
380template <
class... Row1,
class Tableau2>
381struct HookLengthsHelper<YoungTableauSeq<Row1...>, Tableau2>
383 using type = HookLengths<
384 YoungTableauSeq<std::conditional_t<true, std::index_sequence<>, Row1>...>,
385 YoungTableauSeq<Row1...>,
391struct HookLengthsHelper<YoungTableauSeq<>, YoungTableauSeq<>>
393 using type = YoungTableauSeq<>;
396template <
class Tableau1,
class Tableau2>
397using hook_lengths_t = HookLengthsHelper<Tableau1, Tableau2>::type;
400template <std::
size_t Dimension,
class TableauHookLengths, std::
size_t I, std::
size_t J>
404 std::size_t Dimension,
405 std::size_t HeadElemOfHeadRow,
406 std::size_t... TailElemOfHeadRow,
412 YoungTableauSeq<std::index_sequence<HeadElemOfHeadRow, TailElemOfHeadRow...>, TailRow...>,
416 static consteval std::size_t run(
double prod)
418 prod *= Dimension + J - I;
419 prod /= HeadElemOfHeadRow;
420 if constexpr (
sizeof...(TailRow) == 0 &&
sizeof...(TailElemOfHeadRow) == 0) {
422 }
else if constexpr (
sizeof...(TailElemOfHeadRow) == 0) {
423 return IrrepDim<Dimension, YoungTableauSeq<TailRow...>, I + 1, 0>::run(prod);
427 YoungTableauSeq<std::index_sequence<TailElemOfHeadRow...>, TailRow...>,
439template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
443 using tableau_seq = TableauSeq;
444 using shape =
typename TableauSeq::shape;
447 static constexpr std::size_t s_d = Dimension;
448 static constexpr std::size_t s_r = TableauSeq::rank;
451 using dual = YoungTableau<s_d, detail::dual_t<tableau_seq>>;
452 using hook_lengths = detail::hook_lengths_t<
453 detail::hooks_t<tableau_seq>,
454 detail::dual_t<detail::hooks_t<detail::dual_t<tableau_seq>>>>;
457 static constexpr std::size_t s_irrep_dim = detail::IrrepDim<s_d, hook_lengths, 0, 0>::run(1);
459 static constexpr std::string generate_tag();
461 static constexpr std::string s_tag = generate_tag();
463 static consteval auto load_irrep();
465 static constexpr auto s_irrep = load_irrep();
470 static constexpr std::size_t dimension()
475 static constexpr std::size_t rank()
480 static constexpr std::size_t irrep_dim()
485 static constexpr std::string tag()
491 static constexpr std::size_t n_nonzeros_in_irrep()
493 return std::get<2>(std::get<0>(s_irrep)).size();
497 template <tensor::TensorNatIndex... Id>
498 using projector_domain = ddc::DiscreteDomain<tensor::prime<Id>..., Id...>;
500 template <tensor::TensorNatIndex... Id>
501 static auto projector();
503 template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
504 static constexpr csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...> u(
505 ddc::DiscreteDomain<Id...> restricted_domain);
507 template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
508 static constexpr csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...> v(
509 ddc::DiscreteDomain<Id...> restricted_domain);
514template <std::size_t Dimension,
class... TailRow, std::size_t I, std::size_t J>
515struct IrrepDim<Dimension, YoungTableauSeq<std::index_sequence<>, TailRow...>, I, J>
517 static consteval std::size_t run(
double prod)
523template <std::
size_t Dimension, std::
size_t I, std::
size_t J>
524struct IrrepDim<Dimension, YoungTableauSeq<>, I, J>
526 static consteval std::size_t run(
double prod)
536 class LayoutStridedPolicy,
539tensor::Tensor<ElementType, ddc::DiscreteDomain<Id...>, LayoutStridedPolicy, MemorySpace>
541 tensor::Tensor<ElementType, ddc::DiscreteDomain<Id...>, LayoutStridedPolicy, MemorySpace>
543 csr::CsrDynamic<BasisId, Id...> basis,
544 std::size_t max_basis_id)
546 ddc::Chunk eigentensor_alloc(
547 ddc::DiscreteDomain<BasisId, Id...>(basis.domain()),
548 ddc::HostAllocator<double>());
549 tensor::Tensor eigentensor(eigentensor_alloc);
550 for (ddc::DiscreteElement<BasisId> elem : ddc::DiscreteDomain<BasisId>(
551 ddc::DiscreteElement<BasisId>(0),
552 ddc::DiscreteVector<BasisId>(max_basis_id))) {
553 csr::csr2dense(eigentensor, basis.get(elem));
555 ddc::Chunk scalar_prod_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
556 tensor::Tensor scalar_prod(scalar_prod_alloc);
557 tensor::tensor_prod(scalar_prod, tensor, eigentensor[ddc::DiscreteElement<BasisId>(0)]);
558 ddc::Chunk norm_squared_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
559 tensor::Tensor norm_squared(norm_squared_alloc);
560 tensor::tensor_prod(norm_squared, eigentensor, eigentensor);
562 eigentensor *= -1. * scalar_prod(ddc::DiscreteElement<>())
563 / norm_squared(ddc::DiscreteElement<>());
564 tensor += eigentensor[ddc::DiscreteElement<BasisId>(0)];
570std::vector<bool> index_hamming_weight_code(std::size_t index, std::size_t length)
572 std::size_t count = 0;
573 std::vector<bool> bits(length);
574 for (std::size_t hamming_weight = 0; hamming_weight < length; ++hamming_weight) {
575 std::fill(bits.begin(), bits.begin() + hamming_weight,
true);
576 std::fill(bits.begin() + hamming_weight, bits.end(),
false);
578 if (count == index) {
582 }
while (std::prev_permutation(bits.begin(), bits.end()));
584 assert(
false &&
"hamming weight code not found for index");
589struct BasisId : tensor::TensorNaturalIndex<>
594struct OrthonormalBasisSubspaceEigenvalueOne;
596template <
class... Id>
597struct OrthonormalBasisSubspaceEigenvalueOne<tensor::TensorFullIndex<Id...>>
599 template <
class YoungTableau>
600 static std::pair<csr::CsrDynamic<BasisId, Id...>, csr::CsrDynamic<BasisId, Id...>> run(
601 YoungTableau tableau)
603 auto [proj_alloc, proj] = tableau.template projector<Id...>();
605 tensor::TensorAccessor<Id...> candidate_accessor;
606 ddc::DiscreteDomain<Id...> candidate_dom = candidate_accessor.domain();
607 ddc::Chunk candidate_alloc(candidate_dom, ddc::HostAllocator<double>());
608 tensor::Tensor candidate(candidate_alloc);
609 ddc::Chunk prod_alloc(
610 tensor::natural_tensor_prod_domain(proj.domain(), candidate.domain()),
611 ddc::HostAllocator<double>());
612 tensor::Tensor prod(prod_alloc);
614 ddc::DiscreteDomain<BasisId, Id...> basis_dom(
615 ddc::DiscreteDomain<BasisId>(
616 ddc::DiscreteElement<BasisId>(0),
617 ddc::DiscreteVector<BasisId>(tableau.irrep_dim())),
619 csr::CsrDynamic<BasisId, Id...> u(basis_dom);
620 csr::CsrDynamic<BasisId, Id...> v(basis_dom);
621 std::size_t n_irreps = 0;
622 std::size_t index = 0;
623 while (n_irreps < tableau.irrep_dim()) {
625 std::vector<bool> hamming_weight_code
626 = index_hamming_weight_code(index, (Id::size() * ...));
628 ddc::parallel_for_each(candidate.domain(), [&](ddc::DiscreteElement<Id...> elem) {
629 candidate(elem) = hamming_weight_code[(
630 (misc::detail::stride<Id, Id...>() * elem.template uid<Id>()) + ...)];
633 tensor::tensor_prod(prod, proj, candidate);
635 candidate.allocation_kokkos_view(),
636 prod.allocation_kokkos_view());
638 orthogonalize(candidate, v, n_irreps);
640 if (ddc ::transform_reduce(
643 ddc::reducer::lor<bool>(),
644 [&](ddc::DiscreteElement<Id...> elem) { return candidate(elem) > 1e-6; })) {
646 norm_squared_alloc(ddc::DiscreteDomain<> {}, ddc::HostAllocator<double>());
647 tensor::Tensor norm_squared(norm_squared_alloc);
648 tensor::tensor_prod(norm_squared, candidate, candidate);
649 ddc::parallel_for_each(candidate.domain(), [&](ddc::DiscreteElement<Id...> elem) {
650 candidate(elem) /= Kokkos::sqrt(norm_squared(ddc::DiscreteElement<>()));
653 u.push_back(candidate);
654 v.push_back(candidate);
656 std::cout << n_irreps <<
"/" << tableau.irrep_dim()
657 <<
" eigentensors found associated to the eigenvalue 1 for the Young "
658 "projector labelized "
659 << tableau.tag() << std::endl;
662 return std::pair<csr::CsrDynamic<BasisId, Id...>, csr::CsrDynamic<BasisId, Id...>>(u, v);
668template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
669YoungTableau<Dimension, TableauSeq>::YoungTableau()
673 std::ifstream file(IRREPS_DICT_PATH, std::ios::out | std::ios::binary);
675 while (!file.eof()) {
679 if (n_nonzeros_in_irrep() == 0) {
680 std::cout <<
"\033[1;31mIrrep " << s_tag <<
" in dimension " << s_d
681 <<
" required and found in dictionnary " << IRREPS_DICT_PATH
682 <<
" but the executable has been compiled without it. Please "
692 std::cout <<
"\033[1;31mIrrep " << s_tag <<
" corresponding to the Young Tableau:\033[0m\n"
693 << *
this <<
"\n\033[1;31min dimension " << s_d
694 <<
" required but not found in dictionnary " << IRREPS_DICT_PATH
695 <<
". It will be computed, and you will have to recompile once it is done.\033[0m"
699 = detail::OrthonormalBasisSubspaceEigenvalueOne<tensor::dummy_index_t<s_d, s_r>>::run(
702 std::ofstream file(IRREPS_DICT_PATH, std::ios::app | std::ios::binary);
704 std::cerr <<
"Error opening file: " << IRREPS_DICT_PATH << std::endl;
707 file << s_tag <<
"\n";
713 std::cerr <<
"Error occurred while writing to file " << IRREPS_DICT_PATH
714 <<
" while adding irrep " << s_tag << std::endl;
716 std::cout <<
"\033[1;32mIrrep " << s_tag <<
" added to the dictionnary " << IRREPS_DICT_PATH
717 <<
".\033[0m \033[1;31mPlease recompile.\033[0m" << std::endl;
724template <
class OId,
class... Id>
725using symmetrizer_index_t = std::conditional_t<
726 (ddc::type_seq_rank_v<OId, ddc::detail::TypeSeq<Id...>> < (
sizeof...(Id) / 2)),
728 ddc::type_seq_element_t<
729 static_cast<std::size_t
>(
731 max(
static_cast<std::ptrdiff_t
>(0),
732 static_cast<std::ptrdiff_t
>(
733 ddc::type_seq_rank_v<OId, ddc::detail::TypeSeq<Id...>>
734 - (
sizeof...(Id) / 2)))),
735 ddc::detail::TypeSeq<Id...>>>;
738template <std::size_t Dimension, std::size_t Rank,
class... NaturalId>
742 using TensorType = tensor::Tensor<
744 ddc::DiscreteDomain<NaturalId...>,
745 Kokkos::layout_right,
746 Kokkos::DefaultHostExecutionSpace::memory_space>;
749 std::array<std::size_t, Rank> idx_to_permute;
752 TrFunctor(TensorType t_, std::array<std::size_t, Rank> idx_to_permute_)
754 , idx_to_permute(idx_to_permute_)
758 void operator()(ddc::DiscreteElement<NaturalId...> elem)
const
760 std::array<std::size_t,
sizeof...(NaturalId)> elem_array = ddc::detail::array(elem);
761 bool has_to_be_one =
true;
762 for (std::size_t i = 0; i < Rank; ++i) {
764 = has_to_be_one && (elem_array[i] == elem_array[idx_to_permute[i] + Rank]);
772template <std::size_t Dimension,
bool AntiSym,
class... Id>
773static tensor::Tensor<
775 ddc::DiscreteDomain<Id...>,
776 Kokkos::layout_right,
777 Kokkos::DefaultHostExecutionSpace::memory_space>
781 ddc::DiscreteDomain<Id...>,
782 Kokkos::layout_right,
783 Kokkos::DefaultHostExecutionSpace::memory_space> sym,
784 std::array<std::size_t,
sizeof...(Id) / 2> idx_to_permute)
786 ddc::Chunk tr_alloc(sym.domain(), ddc::HostAllocator<double>());
787 tensor::Tensor tr(tr_alloc);
788 ddc::parallel_fill(tr, 0);
789 ddc::for_each(tr.domain(), TrFunctor<Dimension,
sizeof...(Id) / 2, Id...>(tr, idx_to_permute));
791 if constexpr (AntiSym) {
792 tr *=
static_cast<double>(misc::permutation_parity(idx_to_permute));
803template <std::
size_t Nt, std::
size_t Ns>
804static std::vector<std::array<std::size_t, Nt>> permutations_subset(
805 std::array<std::size_t, Nt> t,
806 std::array<std::size_t, Ns> subset_values)
808 std::array<std::size_t, Ns> subset_indices;
809 std::array<std::size_t, Ns> elements_to_permute;
811 for (std::size_t i = 0; i < t.size(); ++i) {
812 if (std::find(subset_values.begin(), subset_values.end(), t[i] + 1)
813 != std::end(subset_values)) {
814 subset_indices[j] = i;
815 elements_to_permute[j++] = t[i];
819 std::vector<std::array<std::size_t, Nt>> result;
821 std::array<std::size_t, Nt> tmp = t;
822 for (std::size_t i = 0; i < Ns; ++i) {
823 tmp[subset_indices[i]] = elements_to_permute[i];
825 result.push_back(tmp);
826 }
while (std::next_permutation(elements_to_permute.begin(), elements_to_permute.end()));
832template <
class PartialTableauSeq, std::
size_t Dimension,
bool AntiSym = false>
835template <std::size_t... ElemOfHeadRow,
class... TailRow, std::size_t Dimension,
bool AntiSym>
837 YoungTableauSeq<std::index_sequence<ElemOfHeadRow...>, TailRow...>,
841 template <
class... Id>
842 static tensor::Tensor<
844 ddc::DiscreteDomain<Id...>,
845 Kokkos::layout_right,
846 Kokkos::DefaultHostExecutionSpace::memory_space>
849 ddc::DiscreteDomain<Id...>,
850 Kokkos::layout_right,
851 Kokkos::DefaultHostExecutionSpace::memory_space> proj)
853 if constexpr (
sizeof...(ElemOfHeadRow) >= 2) {
855 tensor::TensorAccessor<symmetrizer_index_t<Id, Id...>...> sym_accessor;
856 ddc::DiscreteDomain<symmetrizer_index_t<Id, Id...>...> sym_dom = sym_accessor.domain();
858 ddc::Chunk sym_alloc(sym_dom, ddc::HostAllocator<double>());
859 tensor::Tensor sym(sym_alloc);
860 ddc::parallel_fill(sym, 0);
861 std::array<std::size_t,
sizeof...(Id) / 2> idx_to_permute;
862 for (std::size_t i = 0; i <
sizeof...(Id) / 2; ++i) {
863 idx_to_permute[i] = i;
865 std::array<std::size_t,
sizeof...(ElemOfHeadRow)> row_values {ElemOfHeadRow...};
866 auto idx_permutations = detail::permutations_subset(
869 for (std::size_t i = 0; i < idx_permutations.size(); ++i) {
873 symmetrizer_index_t<Id, Id...>...>(sym, idx_permutations[i]);
877 ddc::Chunk prod_alloc(
879 ddc::HostAllocator<double>());
880 tensor::Tensor prod(prod_alloc);
881 tensor::tensor_prod(prod, sym, proj);
883 proj.allocation_kokkos_view(),
884 prod.allocation_kokkos_view());
886 if constexpr (
sizeof...(TailRow) == 0) {
889 return Projector<YoungTableauSeq<TailRow...>, Dimension, AntiSym>::run(proj);
896template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
897template <tensor::TensorNatIndex... Id>
898auto YoungTableau<Dimension, TableauSeq>::projector()
900 static_assert(
sizeof...(Id) == s_r);
901 tensor::TensorAccessor<tensor::prime<Id>..., Id...> proj_accessor;
902 ddc::DiscreteDomain<tensor::prime<Id>..., Id...> proj_dom = proj_accessor.domain();
905 ddc::Chunk proj_alloc(proj_dom, ddc::HostAllocator<double>());
906 tensor::Tensor proj(proj_alloc);
907 ddc::parallel_fill(proj, 0);
908 std::array<std::size_t, s_r> idx_to_permute;
909 for (std::size_t i = 0; i < s_r; ++i) {
910 idx_to_permute[i] = i;
914 detail::TrFunctor<s_d, s_r, tensor::prime<Id>..., Id...>(proj, idx_to_permute));
917 detail::Projector<tableau_seq, s_d>::run(proj);
918 detail::Projector<typename dual::tableau_seq, s_d, true>::run(proj);
919 return std::make_tuple(std::move(proj_alloc), proj);
923template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
924template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
925constexpr csr::Csr<YoungTableau<Dimension, TableauSeq>::n_nonzeros_in_irrep(), BasisId, Id...>
926YoungTableau<Dimension, TableauSeq>::u(ddc::DiscreteDomain<Id...> restricted_domain)
928 if constexpr (n_nonzeros_in_irrep() != 0) {
929 ddc::DiscreteDomain<BasisId, Id...>
930 domain(ddc::DiscreteDomain<BasisId>(
931 ddc::DiscreteElement<BasisId>(0),
932 ddc::DiscreteVector<BasisId>(n_nonzeros_in_irrep())),
935 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
937 std::get<0>(std::get<0>(s_irrep)),
938 std::get<1>(std::get<0>(s_irrep)),
939 std::get<2>(std::get<0>(s_irrep)));
941 ddc::DiscreteDomain<BasisId, Id...>
942 domain(ddc::DiscreteDomain<BasisId>(
943 ddc::DiscreteElement<BasisId>(0),
944 ddc::DiscreteVector<BasisId>(0)),
947 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
949 std::array<std::size_t, BasisId::mem_size() + 1> {},
950 std::get<1>(std::get<0>(s_irrep)),
951 std::get<2>(std::get<0>(s_irrep)));
955template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
956template <tensor::TensorIndex BasisId, tensor::TensorNatIndex... Id>
957constexpr csr::Csr<YoungTableau<Dimension, TableauSeq>::n_nonzeros_in_irrep(), BasisId, Id...>
958YoungTableau<Dimension, TableauSeq>::v(ddc::DiscreteDomain<Id...> restricted_domain)
960 if constexpr (n_nonzeros_in_irrep() != 0) {
961 ddc::DiscreteDomain<BasisId, Id...>
962 domain(ddc::DiscreteDomain<BasisId>(
963 ddc::DiscreteElement<BasisId>(0),
964 ddc::DiscreteVector<BasisId>(n_nonzeros_in_irrep())),
967 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
969 std::get<0>(std::get<1>(s_irrep)),
970 std::get<1>(std::get<1>(s_irrep)),
971 std::get<2>(std::get<1>(s_irrep)));
973 ddc::DiscreteDomain<BasisId, Id...>
974 domain(ddc::DiscreteDomain<BasisId>(
975 ddc::DiscreteElement<BasisId>(0),
976 ddc::DiscreteVector<BasisId>(0)),
979 return csr::Csr<n_nonzeros_in_irrep(), BasisId, Id...>(
981 std::array<std::size_t, BasisId::mem_size() + 1> {},
982 std::get<1>(std::get<1>(s_irrep)),
983 std::get<2>(std::get<1>(s_irrep)));
990template <std::
size_t Line>
991consteval std::string_view load_irrep_line_for_tag(std::string_view
const tag)
993 constexpr static char raw[] = {
994#embed IRREPS_DICT_PATH
997 constexpr static std::string_view str(raw,
sizeof(raw));
999 size_t tagPos = str.find(tag);
1001 if (tagPos != std::string::npos) {
1002 std::size_t endOfTagLine = str.find(
'\n', tagPos);
1003 if (endOfTagLine != std::string::npos) {
1004 std::size_t nextLineStart = endOfTagLine + 1;
1005 for (std::size_t i = 0; i < Line; ++i) {
1006 nextLineStart = str.find(
"break\n", nextLineStart) + 6;
1008 std::size_t nextLineEnd = str.find(
"break\n", nextLineStart);
1010 return std::string_view(str.data() + nextLineStart, nextLineEnd - nextLineStart);
1017template <
class Ids, std::
size_t Offset>
1018struct LoadIrrepIdxForTag;
1020template <std::size_t... I, std::size_t Offset>
1021struct LoadIrrepIdxForTag<std::index_sequence<I...>, Offset>
1023 static consteval std::array<std::string_view,
sizeof...(I)> run(std::string_view
const tag)
1025 return std::array<std::string_view,
sizeof...(I)> {
1026 load_irrep_line_for_tag<I + Offset>(tag)...};
1030template <
class T, std::
size_t N, std::
size_t I = 0>
1031consteval std::array<T, N> bit_cast_array(
1032 std::array<T, N> vec,
1033 std::string_view
const str,
1034 std::string_view
const tag)
1036 if constexpr (I == N) {
1039 std::array<char,
sizeof(T) /
sizeof(
char)> chars = {};
1040 for (std::size_t j = 0; j <
sizeof(T) /
sizeof(char); ++j) {
1041 chars[j] = str[
sizeof(T) /
sizeof(
char) * I + j];
1044 vec[I] = std::bit_cast<T>(
1046 return bit_cast_array<T, N, I + 1>(vec, str, tag);
1050template <
class T, std::
size_t N, std::
size_t I = 0>
1051consteval std::array<T, N> bit_cast_array(std::string_view
const str, std::string_view
const tag)
1053 std::array<T, N> vec {};
1054 return bit_cast_array<T, N>(vec, str, tag);
1057template <
class T, std::
size_t N,
class Ids>
1058struct BitCastArrayOfArrays;
1060template <
class T, std::size_t N, std::size_t... I>
1061struct BitCastArrayOfArrays<T, N, std::index_sequence<I...>>
1063 static consteval std::array<std::array<T, N>,
sizeof...(I)> run(
1064 std::array<std::string_view,
sizeof...(I)>
const str,
1065 std::string_view
const tag)
1067 return std::array<std::array<T, N>,
sizeof...(I)> {bit_cast_array<T, N>(str[I], tag)...};
1073template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1074consteval auto YoungTableau<Dimension, TableauSeq>::load_irrep()
1076 static constexpr std::string_view str_u_coalesc_idx(detail::load_irrep_line_for_tag<0>(s_tag));
1077 static constexpr std::array<std::string_view, s_r> str_u_idx(
1078 detail::LoadIrrepIdxForTag<std::make_index_sequence<s_r>, 1>::run(s_tag));
1079 static constexpr std::string_view str_u_values(detail::load_irrep_line_for_tag<s_r + 1>(s_tag));
1080 static constexpr std::string_view str_v_coalesc_idx(
1081 detail::load_irrep_line_for_tag<s_r + 2>(s_tag));
1082 static constexpr std::array<std::string_view, s_r> str_v_idx(
1083 detail::LoadIrrepIdxForTag<std::make_index_sequence<s_r>, s_r + 3>::run(s_tag));
1084 static constexpr std::string_view str_v_values(
1085 detail::load_irrep_line_for_tag<2 * s_r + 3>(s_tag));
1087 if constexpr (str_u_values.size() != 0) {
1088 static constexpr std::array u_coalesc_idx = detail::bit_cast_array<
1090 str_u_coalesc_idx.size() /
sizeof(std::size_t)>(str_u_coalesc_idx, s_tag);
1091 static constexpr std::array u_idx = detail::BitCastArrayOfArrays<
1093 str_u_idx[0].size() /
sizeof(std::size_t),
1094 std::make_index_sequence<s_r>>::run(str_u_idx, s_tag);
1095 static constexpr std::array u_values = detail::
1096 bit_cast_array<double, str_u_values.size() /
sizeof(double)>(str_u_values, s_tag);
1097 static constexpr std::array v_coalesc_idx = detail::bit_cast_array<
1099 str_v_coalesc_idx.size() /
sizeof(std::size_t)>(str_v_coalesc_idx, s_tag);
1100 static constexpr std::array v_idx = detail::BitCastArrayOfArrays<
1102 str_v_idx[0].size() /
sizeof(std::size_t),
1103 std::make_index_sequence<s_r>>::run(str_v_idx, s_tag);
1104 static constexpr std::array v_values = detail::
1105 bit_cast_array<double, str_v_values.size() /
sizeof(double)>(str_v_values, s_tag);
1106 return std::make_pair(
1107 std::make_tuple(u_coalesc_idx, u_idx, u_values),
1108 std::make_tuple(v_coalesc_idx, v_idx, v_values));
1110 return std::make_pair(
1112 std::array<std::size_t, 1> {0},
1113 std::array<std::array<std::size_t, 0>, s_r> {},
1114 std::array<double, 0> {}),
1116 std::array<std::size_t, 1> {0},
1117 std::array<std::array<std::size_t, 0>, s_r> {},
1118 std::array<double, 0> {}));
1126struct YoungTableauRowToArray;
1128template <std::size_t... RowElement>
1129struct YoungTableauRowToArray<std::index_sequence<RowElement...>>
1131 static constexpr auto run()
1133 static constexpr std::array row = {RowElement...};
1138template <
class TableauSeq>
1139struct YoungTableauToArray;
1141template <
class... Row>
1142struct YoungTableauToArray<YoungTableauSeq<Row...>>
1144 static constexpr auto run()
1146 static constexpr std::tuple tableau = {YoungTableauRowToArray<Row>::run()...};
1151template <
bool RowDelimiter>
1154 template <std::
size_t N>
1155 static constexpr std::array<char, 2 * N - !RowDelimiter> run(
1156 const std::array<std::size_t, N>& array)
1158 std::array<char, 2 * N - !RowDelimiter> buf = {};
1160 std::size_t current_pos = 0;
1161 for (std::size_t i = 0; i < N; ++i) {
1163 auto [ptr, ec] = std::to_chars(temp, temp +
sizeof(temp), array[i]);
1164 if (ec != std::errc()) {
1165 throw std::runtime_error(
"Failed to convert number to string");
1168 for (
char* p = temp; p < ptr; ++p) {
1169 buf[current_pos++] = *p;
1173 buf[current_pos++] =
'_';
1177 if constexpr (RowDelimiter) {
1178 buf[2 * N - 1] =
'l';
1185template <std::size_t... sizes>
1186constexpr auto concatenate(
const std::array<char, sizes>&... arrays)
1188 std::array<char, (sizes + ...)> result;
1189 std::size_t index {};
1191 ((std::copy_n(arrays.begin(), sizes, result.begin() + index), index += sizes), ...);
1196template <
class RowIdx>
1197struct ArrayToString;
1199template <std::size_t... RowId>
1200struct ArrayToString<std::index_sequence<RowId...>>
1202 template <
class Tuple>
1203 static constexpr auto run(Tuple
const tableau)
1206 RowToString<RowId !=
sizeof...(RowId) - 1>::run(std::get<RowId>(tableau))...);
1210template <std::
size_t size>
1211constexpr auto add_dimension(
const std::array<char, size>& array, std::size_t d)
1213 std::array<char, size + 2> result;
1215 std::to_chars(temp, temp + 1, d);
1216 std::copy_n(array.begin(), size, result.begin());
1218 result[size + 1] = temp[0];
1225template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1226constexpr std::string YoungTableau<Dimension, TableauSeq>::generate_tag()
1228 static constexpr std::tuple tableau = detail::YoungTableauToArray<tableau_seq>::run();
1229 constexpr auto row_str_wo_dimension
1230 = detail::ArrayToString<std::make_index_sequence<tableau_seq::shape::size()>>::run(
1232 constexpr auto row_str = detail::add_dimension(row_str_wo_dimension, s_d);
1233 return std::string(row_str.begin(), row_str.end());
1239template <
class TableauSeq>
1240struct PrintYoungTableauSeq;
1242template <std::size_t HeadRowHeadElement, std::size_t... HeadRowTailElement,
class... TailRow>
1243struct PrintYoungTableauSeq<
1244 YoungTableauSeq<std::index_sequence<HeadRowHeadElement, HeadRowTailElement...>, TailRow...>>
1246 static std::string run(std::string str)
1248 str += std::to_string(HeadRowHeadElement) +
" ";
1249 if constexpr (
sizeof...(TailRow) == 0 &&
sizeof...(HeadRowTailElement) == 0) {
1250 }
else if constexpr (
sizeof...(HeadRowTailElement) == 0) {
1252 str = PrintYoungTableauSeq<YoungTableauSeq<TailRow...>>::run(str);
1254 str = PrintYoungTableauSeq<
1255 YoungTableauSeq<std::index_sequence<HeadRowTailElement...>, TailRow...>>::
1263struct PrintYoungTableauSeq<YoungTableauSeq<>>
1265 static std::string run(std::string str)
1273template <std::
size_t Dimension, misc::Specialization<YoungTableauSeq> TableauSeq>
1274std::ostream&
operator<<(std::ostream& os, YoungTableau<Dimension, TableauSeq>
const& tableau)
1276 std::string str =
"";
1277 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.