SimiLie
Loading...
Searching...
No Matches
antisymmetric_tensor.hpp
1// SPDX-FileCopyrightText: 2024 Baptiste Legouix
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include <ddc/ddc.hpp>
7
8#include <similie/misc/binomial_coefficient.hpp>
9#include <similie/misc/portable_stl.hpp>
10
11#include "tensor_impl.hpp"
12
13namespace sil {
14
15namespace tensor {
16
17// struct representing an abstract unique index sweeping on all possible combination of natural indices, for an antisymmetric tensor.
18template <TensorNatIndex... TensorIndex>
20{
21 static constexpr bool is_tensor_index = true;
22 static constexpr bool is_explicitely_stored_tensor = true;
23
24 using subindices_domain_t = ddc::DiscreteDomain<TensorIndex...>;
25
26 KOKKOS_FUNCTION static constexpr subindices_domain_t subindices_domain()
27 {
28 return ddc::DiscreteDomain<TensorIndex...>(
29 ddc::DiscreteElement<TensorIndex...>(ddc::DiscreteElement<TensorIndex>(0)...),
30 ddc::DiscreteVector<TensorIndex...>(
31 ddc::DiscreteVector<TensorIndex>(TensorIndex::size())...));
32 }
33
34 KOKKOS_FUNCTION static constexpr std::size_t rank()
35 {
36 if constexpr (sizeof...(TensorIndex) == 0) {
37 return 0;
38 } else {
39 return (TensorIndex::rank() + ...);
40 }
41 }
42
43 KOKKOS_FUNCTION static constexpr std::size_t size()
44 {
45 if constexpr (rank() == 0) {
46 return 1;
47 } else {
48 return (TensorIndex::size() + ...);
49 }
50 }
51
52 KOKKOS_FUNCTION static constexpr std::size_t mem_size()
53 {
54 if constexpr (rank() == 0) {
55 return 1;
56 } else {
58 ddc::type_seq_element_t<0, ddc::detail::TypeSeq<TensorIndex...>>::mem_size(),
59 rank());
60 }
61 }
62
63 KOKKOS_FUNCTION static constexpr std::size_t access_size()
64 {
65 if constexpr (rank() <= 1) {
66 return mem_size();
67 } else {
68 return mem_size() + 1;
69 }
70 }
71
72 KOKKOS_FUNCTION static constexpr std::size_t mem_id(
73 std::array<std::size_t, rank()> const natural_ids)
74 {
75 std::array<std::size_t, rank()> sorted_ids(natural_ids);
76 misc::detail::sort(sorted_ids.begin(), sorted_ids.end());
77 return mem_size()
78 - (0 + ...
79 + (sorted_ids[ddc::type_seq_rank_v<
81 ddc::detail::TypeSeq<TensorIndex...>>]
82 == TensorIndex::mem_size() - rank()
83 + ddc::type_seq_rank_v<
85 ddc::detail::TypeSeq<TensorIndex...>>
86 ? 0
88 TensorIndex::mem_size()
89 - sorted_ids[ddc::type_seq_rank_v<
91 ddc::detail::TypeSeq<TensorIndex...>>]
92 - 1,
93 rank()
94 - ddc::type_seq_rank_v<
96 ddc::detail::TypeSeq<TensorIndex...>>)))
97 - 1;
98 }
99
100private:
101 static constexpr bool permutation_parity(std::array<std::size_t, rank()> ids)
102 {
103 bool cnt = false;
104 for (std::size_t i = 0; i < rank(); i++)
105 for (std::size_t j = i + 1; j < rank(); j++)
106 if (ids[i] > ids[j])
107 cnt = !cnt;
108 return cnt;
109 }
110
111public:
112 KOKKOS_FUNCTION static constexpr std::size_t access_id(
113 std::array<std::size_t, rank()> const natural_ids)
114 {
115 if constexpr (rank() <= 1) {
116 return mem_id(natural_ids);
117 } else {
118 if (std::all_of(natural_ids.begin(), natural_ids.end(), [&](const std::size_t id) {
119 return id == *natural_ids.begin();
120 })) {
121 return 0;
122 } else if (!permutation_parity(natural_ids)) {
123 return 1 + mem_id(natural_ids);
124 } else {
125 return access_size() + mem_id(natural_ids);
126 }
127 }
128 }
129
130 KOKKOS_FUNCTION static constexpr std::size_t access_id_to_mem_id(std::size_t access_id)
131 {
132 if constexpr (rank() <= 1) {
133 return access_id;
134 } else {
135 if (access_id != 0) {
136 return (access_id - 1) % mem_size();
137 } else {
138 return std::numeric_limits<std::size_t>::max();
139 }
140 }
141 }
142
143 template <class Tensor, class Elem, class Id, class FunctorType>
144 KOKKOS_FUNCTION static constexpr Tensor::element_type process_access(
145 const FunctorType& access,
146 Tensor tensor,
147 Elem elem)
148 {
149 if constexpr (rank() <= 1) {
150 return access(tensor, elem);
151 } else {
152 if (elem.template uid<Id>() == 0) {
153 return 0.;
154 } else if (elem.template uid<Id>() < access_size()) {
155 return access(tensor, elem);
156 } else {
157 return -access(tensor, elem);
158 }
159 }
160 }
161
162 KOKKOS_FUNCTION static constexpr std::array<std::size_t, rank()>
164 {
165 assert(mem_id < mem_size());
166 if constexpr (rank() == 0) {
167 return std::array<std::size_t, rank()> {};
168 } else {
169 std::array<std::size_t, rank()> ids;
170 std::size_t d
171 = ddc::type_seq_element_t<0, ddc::detail::TypeSeq<TensorIndex...>>::mem_size();
172 std::size_t r = rank();
173 for (std::size_t i = 0; i < rank(); ++i) {
174 const std::size_t triangle_size = misc::binomial_coefficient(d, r - i);
175 for (std::size_t j = 0; j < d; ++j) {
176 const std::size_t subtriangle_size
177 = misc::binomial_coefficient(d - j - 1, r - i);
178 if (triangle_size - subtriangle_size > mem_id) {
179 ids[i] = ddc::type_seq_element_t<0, ddc::detail::TypeSeq<TensorIndex...>>::
180 mem_size()
181 - d + j;
182 mem_id -= triangle_size - misc::binomial_coefficient(d - j, r - i);
183 d -= j + 1;
184 break;
185 }
186 ids[i] = 0;
187 }
188 }
189 return ids;
190 }
191 }
192};
193
194namespace detail {
195
196template <class T>
197struct ToTensorAntisymmetricIndex;
198
199template <tensor::TensorNatIndex Index>
200 requires(Index::rank() == 0)
201struct ToTensorAntisymmetricIndex<Index>
202{
203 using type = TensorAntisymmetricIndex<>;
204};
205
206template <tensor::TensorNatIndex Index>
207 requires(Index::rank() > 0)
208struct ToTensorAntisymmetricIndex<Index>
209{
210 using type = TensorAntisymmetricIndex<Index>;
211};
212
213template <tensor::TensorNatIndex... Index>
214struct ToTensorAntisymmetricIndex<TensorAntisymmetricIndex<Index...>>
215{
216 using type = TensorAntisymmetricIndex<Index...>;
217};
218
219} // namespace detail
220
221template <class T>
222using to_tensor_antisymmetric_index_t = typename detail::ToTensorAntisymmetricIndex<T>::type;
223
224} // namespace tensor
225
226} // namespace sil
constexpr std::size_t binomial_coefficient(std::size_t n, std::size_t k) noexcept
typename detail::ToTensorAntisymmetricIndex< T >::type to_tensor_antisymmetric_index_t
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
The top-level namespace of SimiLie.
Definition csr.hpp:14
static KOKKOS_FUNCTION constexpr std::size_t access_size()
static KOKKOS_FUNCTION constexpr std::size_t mem_size()
static KOKKOS_FUNCTION constexpr std::size_t access_id(std::array< std::size_t, rank()> const natural_ids)
static KOKKOS_FUNCTION constexpr Tensor::element_type process_access(const FunctorType &access, Tensor tensor, Elem elem)
static KOKKOS_FUNCTION constexpr std::size_t rank()
static KOKKOS_FUNCTION constexpr std::size_t mem_id(std::array< std::size_t, rank()> const natural_ids)
ddc::DiscreteDomain< TensorIndex... > subindices_domain_t
static KOKKOS_FUNCTION constexpr std::size_t access_id_to_mem_id(std::size_t access_id)
static KOKKOS_FUNCTION constexpr std::size_t size()
static KOKKOS_FUNCTION constexpr std::array< std::size_t, rank()> mem_id_to_canonical_natural_ids(std::size_t mem_id)
static KOKKOS_FUNCTION constexpr subindices_domain_t subindices_domain()