SimiLie
Loading...
Searching...
No Matches
local_chain.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/are_all_same.hpp>
9#include <similie/misc/binomial_coefficient.hpp>
10#include <similie/misc/filled_struct.hpp>
11#include <similie/misc/specialization.hpp>
12
13#include "simplex.hpp"
14
15namespace sil {
16
17namespace exterior {
18
19namespace detail {
20
21template <
22 class SimplexType,
23 class LayoutStridedPolicy1,
24 class LayoutStridedPolicy2,
25 class MemorySpace>
26Kokkos::View<typename SimplexType::discrete_vector_type*, MemorySpace> extract_vects(
27 Kokkos::View<typename SimplexType::discrete_vector_type*, LayoutStridedPolicy1, MemorySpace>
28 vects,
29 Kokkos::View<SimplexType*, LayoutStridedPolicy2, MemorySpace> simplices)
30{
31 for (auto i = Kokkos::Experimental::begin(simplices); i < Kokkos::Experimental::end(simplices);
32 ++i) {
33 vects(i) = i->discrete_vector();
34 }
35 return vects;
36}
37
38} // namespace detail
39
40
42template <
43 class SimplexType,
44 class LayoutStridedPolicy = Kokkos::LayoutRight,
45 class MemorySpace = Kokkos::HostSpace>
47{
48public:
49 using memory_space = MemorySpace;
50
51 using simplex_type = SimplexType;
52 using simplices_type = Kokkos::View<SimplexType*, LayoutStridedPolicy, memory_space>;
53 using discrete_element_type = typename simplex_type::discrete_element_type;
54 using discrete_vector_type = typename simplex_type::discrete_vector_type;
55 using vects_type = Kokkos::View<discrete_vector_type*, LayoutStridedPolicy, memory_space>;
56
57 using iterator_type = Kokkos::Experimental::Impl::RandomAccessIterator<vects_type>;
58
59private:
60 static constexpr bool s_is_local = true;
61 static constexpr std::size_t s_k = simplex_type::dimension();
62 vects_type m_vects;
63 std::size_t
64 m_size; // Effective size, m_simplices elements between m_size and m_simplices.size() are undefined
65
66public:
67 KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain() = default;
68
69 KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain(LocalChain const&) = default;
70
71 KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain(LocalChain&&) = default;
72
73 // TODO Reorganize discrete vectors in all constructors ?
74
75 template <misc::NotSpecialization<ddc::DiscreteVector>... T>
76 KOKKOS_FUNCTION constexpr explicit LocalChain(vects_type allocation, T... simplex) noexcept
77 : m_vects(std::move(allocation))
78 , m_size(sizeof...(T))
79 {
80 std::size_t i = 0;
81 ((m_vects(i++) = misc::filled_struct<discrete_vector_type>() + simplex.discrete_vector()),
82 ...);
83 assert(check() == 0 && "there are duplicate simplices in the chain");
84 if constexpr (sizeof...(T) > 1) {
85 assert(misc::are_all_equal(simplex.discrete_element()...)
86 && "LocalChain must contain simplices with same origin (if not, use Chain)");
87 }
88 assert((!simplex.negative() && ...)
89 && "negative simplices are not supported in LocalChain");
90 }
91
92 KOKKOS_FUNCTION constexpr explicit LocalChain(
94 simplices_type simplices,
95 std::size_t size) noexcept
96 : m_vects(std::move(allocation))
97 , m_size(size)
98 {
99 detail::extract_vects(m_vects, simplices)
100 assert(check() == 0 && "there are duplicate simplices in the chain");
101#if not defined NDEBUG
102 Kokkos::View<discrete_element_type*, memory_space> elems(simplices.size());
103 for (auto i = Kokkos::Experimental::begin(simplices);
104 i < Kokkos::Experimental::end(simplices);
105 ++i) {
106 elems[Kokkos::Experimental::distance(Kokkos::Experimental::begin(simplices), i)]
107 = i->discrete_element();
108 }
109 assert(misc::are_all_equal(elems)
110 && "LocalChain must contain simplices with same origin (if not, use Chain)");
111
112 /* Does not compile with nvcc, so we inline it
113 assert(misc::all_of(
114 Kokkos::Experimental::begin(simplices),
115 Kokkos::Experimental::end(simplices),
116 KOKKOS_LAMBDA(const std::size_t i) { return !simplices[i].negative(); })
117 && "LocalChain must contain simplices with same origin (if not, use Chain)");
118 */
119 bool flag = true;
120 for (auto i = Kokkos::Experimental::begin(simplices);
121 i < Kokkos::Experimental::end(simplices);
122 ++i) {
123 flag &= !i->negative();
124 }
125 assert(flag && "LocalChain must contain simplices with same origin (if not, use Chain)");
126#endif
127 }
128
129 template <misc::Specialization<ddc::DiscreteVector>... T>
130 requires(sizeof...(T) >= 1)
131 KOKKOS_FUNCTION constexpr explicit LocalChain(vects_type allocation, T... vect) noexcept
132 : m_vects(std::move(allocation))
133 , m_size(sizeof...(T))
134 {
135 std::size_t i = 0;
136 ((m_vects(i++) = misc::filled_struct<discrete_vector_type>() + vect), ...);
137 assert(check() == 0 && "there are duplicate simplices in the chain");
138 }
139
140 KOKKOS_FUNCTION constexpr explicit LocalChain(vects_type allocation, std::size_t size) noexcept
141 : m_vects(std::move(allocation))
142 , m_size(size)
143 {
144 assert(check() == 0 && "there are duplicate simplices in the chain");
145 }
146
147 KOKKOS_DEFAULTED_FUNCTION ~LocalChain() = default;
148
149 KOKKOS_DEFAULTED_FUNCTION LocalChain& operator=(LocalChain const& other) = default;
150
151 KOKKOS_DEFAULTED_FUNCTION LocalChain& operator=(LocalChain&& other) = default;
152
153 static KOKKOS_FUNCTION constexpr bool is_local() noexcept
154 {
155 return s_is_local;
156 }
157
158 static KOKKOS_FUNCTION constexpr std::size_t dimension() noexcept
159 {
160 return s_k;
161 }
162
163 KOKKOS_FUNCTION simplices_type& allocation() noexcept
164 {
165 return m_vects;
166 }
167
168 KOKKOS_FUNCTION std::size_t size() noexcept
169 {
170 return m_size;
171 }
172
173 KOKKOS_FUNCTION std::size_t size() const noexcept
174 {
175 return m_size;
176 }
177
178 KOKKOS_FUNCTION std::size_t allocation_size() noexcept
179 {
180 return m_vects.size();
181 }
182
183 KOKKOS_FUNCTION std::size_t allocation_size() const noexcept
184 {
185 return m_vects.size();
186 }
187
188 static KOKKOS_FUNCTION constexpr bool negative()
189 {
190 return false;
191 }
192
193 void resize()
194 {
195 Kokkos::resize(m_vects, size());
196 }
197
198 void resize(std::size_t size)
199 {
200 Kokkos::resize(m_vects, size);
201 }
202
203 KOKKOS_FUNCTION int check()
204 {
205 /* // TODO reactivate, support checking if MemorySpace is not accessible
206 for (auto i = this->begin(); i < this->end() - 1; ++i) {
207 for (auto j = i + 1; j < this->end(); ++j) {
208 if (*i == *j) {
209 return -1;
210 }
211 }
212 }
213 */
214 return 0;
215 }
216
217 KOKKOS_FUNCTION auto begin()
218 {
219 return Kokkos::Experimental::begin(m_vects);
220 }
221
222 KOKKOS_FUNCTION auto begin() const
223 {
224 return Kokkos::Experimental::begin(m_vects);
225 }
226
227 KOKKOS_FUNCTION auto end()
228 {
229 return Kokkos::Experimental::begin(m_vects) + size();
230 }
231
232 KOKKOS_FUNCTION auto end() const
233 {
234 return Kokkos::Experimental::begin(m_vects) + size();
235 }
236
237 KOKKOS_FUNCTION auto cbegin() const
238 {
239 return Kokkos::Experimental::begin(m_vects);
240 }
241
242 KOKKOS_FUNCTION auto cend() const
243 {
244 return Kokkos::Experimental::begin(m_vects) + size();
245 }
246
247 KOKKOS_FUNCTION simplex_type operator[](std::size_t i) noexcept
248 {
249 assert(i < size());
251 }
252
253 KOKKOS_FUNCTION simplex_type const operator[](std::size_t i) const noexcept
254 {
255 assert(i < size());
257 }
258
259 KOKKOS_FUNCTION LocalChain& operator++()
260 {
261 assert(size() < allocation_size());
262 m_size++;
263 return *this;
264 }
265
266 KOKKOS_FUNCTION LocalChain& operator+=(const std::size_t n)
267 {
268 assert(size() + n <= allocation_size());
269 m_size += n;
270 return *this;
271 }
272
273 KOKKOS_FUNCTION LocalChain& operator+=(const discrete_vector_type& vect)
274 {
275 assert(size() < allocation_size());
276 m_vects(m_size) = vect;
277 m_size++;
278 return *this;
279 }
280
281 KOKKOS_FUNCTION LocalChain& operator+=(const simplex_type& simplex)
282 {
283 assert(size() < allocation_size());
284 m_vects(m_size) = simplex.discrete_vector();
285 m_size++;
286 return *this;
287 }
288
289 KOKKOS_FUNCTION LocalChain& operator+=(const vects_type& vects_to_add)
290 {
291 assert(size() + vects_to_add.size() <= allocation_size());
292 for (auto i = vects_to_add.begin(); i < vects_to_add.end(); ++i) {
293 m_vects(m_size + Kokkos::Experimental::distance(vects_to_add.begin(), i)) = *i;
294 }
295 m_size += vects_to_add.size();
296 return *this;
297 }
298
299 KOKKOS_FUNCTION LocalChain& operator+=(const LocalChain& simplices_to_add)
300 {
301 assert(size() + simplices_to_add.size() <= allocation_size());
302 for (auto i = simplices_to_add.begin(); i < simplices_to_add.end(); ++i) {
303 m_vects(m_size + Kokkos::Experimental::distance(simplices_to_add.begin(), i)) = *i;
304 }
305 m_size += simplices_to_add.size();
306 return *this;
307 }
308
309 KOKKOS_FUNCTION LocalChain operator+(simplex_type simplex)
310 {
311 LocalChain local_chain = *this;
312 local_chain += simplex;
313 return local_chain;
314 }
315
316 KOKKOS_FUNCTION LocalChain operator+(LocalChain simplices_to_add)
317 {
318 LocalChain local_chain = *this;
319 local_chain += simplices_to_add;
320 return local_chain;
321 }
322
324
326
327 template <class T>
328 KOKKOS_FUNCTION LocalChain& operator*=(T t)
329 {
330 if (t == 1) {
331 } else if (t == -1) {
332 assert(false && "negative simplices are unsupported in LocalChain");
333 } else {
334 assert(false && "chain must be multiplied by 1 or -1");
335 }
336 return *this;
337 }
338
339 template <class T>
340 KOKKOS_FUNCTION auto operator*(T t)
341 {
342 Chain chain = *this;
343 chain *= t;
344 return chain;
345 }
346
347 KOKKOS_FUNCTION bool operator==(LocalChain simplices)
348 {
349 for (auto i = simplices.begin(); i < simplices.end(); ++i) {
350 if (*i != m_vects(Kokkos::Experimental::distance(simplices.begin(), i))) {
351 return false;
352 }
353 }
354 return true;
355 }
356};
357
358template <class Head, misc::NotSpecialization<ddc::DiscreteVector>... Tail>
359LocalChain(Head, Tail...) -> LocalChain<
360 ddc::type_seq_element_t<0, ddc::detail::TypeSeq<Tail...>>,
361 typename Head::array_layout,
362 typename Head::memory_space>;
363
364template <class Head, misc::Specialization<ddc::DiscreteVector>... Tail>
365LocalChain(Head, Tail...)
366 -> LocalChain<
367 decltype(Simplex(
369 ddc::DiscreteElement,
370 ddc::to_type_seq_t<typename Head::value_type>>(),
371 ddc::type_seq_element_t<0, ddc::detail::TypeSeq<Tail...>>())),
372 typename Head::array_layout,
373 typename Head::memory_space>;
374
375namespace detail {
376
377template <std::size_t K, misc::Specialization<ddc::DiscreteDomain> Dom>
378struct TangentBasis;
379
380template <std::size_t K, class... Tag>
381struct TangentBasis<K, ddc::DiscreteDomain<Tag...>>
382{
383 template <class ExecSpace>
384 static auto constexpr run(ExecSpace const& exec_space)
385 {
386 std::array<std::ptrdiff_t, sizeof...(Tag)> permutation
387 = {0 * ddc::type_seq_rank_v<Tag, ddc::detail::TypeSeq<Tag...>>...};
388 for (auto i = permutation.begin(); i < permutation.begin() + K; ++i) {
389 *i = 1;
390 }
391 Kokkos::View<ddc::DiscreteVector<Tag...>*, Kokkos::HostSpace>
392 basis_host("", misc::binomial_coefficient(sizeof...(Tag), K));
393 std::size_t i = 0;
394 do {
395 basis_host(i) = ddc::DiscreteVector<Tag...>();
396 ddc::detail::array(basis_host(i++)) = permutation;
397 } while (std::prev_permutation(permutation.begin(), permutation.end()));
398 Kokkos::View<ddc::DiscreteVector<Tag...>*, typename ExecSpace::memory_space> basis
399 = create_mirror_view_and_copy(exec_space, basis_host);
400
401 return LocalChain<
402 Simplex<K, Tag...>,
403 Kokkos::LayoutRight,
404 typename ExecSpace::memory_space>(basis, basis.size());
405 }
406};
407
408} // namespace detail
409
410template <std::size_t K, misc::Specialization<ddc::DiscreteDomain> Dom, class ExecSpace>
411constexpr auto tangent_basis(ExecSpace const& exec_space)
412{
413 return detail::TangentBasis<K, Dom>::run(exec_space);
414}
415
416template <misc::Specialization<LocalChain> ChainType>
417std::ostream& operator<<(std::ostream& out, ChainType const& chain)
418{
419 out << "[\n";
420 for (typename ChainType::discrete_vector_type const& vect : chain) {
421 out << " -> " << vect << "\n";
422 }
423 out << "]";
424 return out;
425}
426
427} // namespace exterior
428
429} // namespace sil
Chain class.
Definition chain.hpp:26
KOKKOS_FUNCTION constexpr LocalChain(vects_type allocation, std::size_t size) noexcept
static KOKKOS_FUNCTION constexpr std::size_t dimension() noexcept
KOKKOS_FUNCTION int check()
KOKKOS_FUNCTION std::size_t allocation_size() const noexcept
KOKKOS_FUNCTION LocalChain & operator*=(T t)
LocalChain operator-()=delete
KOKKOS_FUNCTION LocalChain & operator++()
KOKKOS_FUNCTION auto operator*(T t)
KOKKOS_FUNCTION LocalChain operator+(LocalChain simplices_to_add)
Kokkos::View< discrete_vector_type *, LayoutStridedPolicy, memory_space > vects_type
static KOKKOS_FUNCTION constexpr bool is_local() noexcept
KOKKOS_FUNCTION constexpr LocalChain(vects_type allocation, T... simplex) noexcept
KOKKOS_FUNCTION constexpr LocalChain(vects_type allocation, T... vect) noexcept
Kokkos::View< SimplexType *, LayoutStridedPolicy, memory_space > simplices_type
KOKKOS_FUNCTION std::size_t allocation_size() noexcept
KOKKOS_DEFAULTED_FUNCTION LocalChain & operator=(LocalChain &&other)=default
void resize(std::size_t size)
typename simplex_type::discrete_vector_type discrete_vector_type
KOKKOS_FUNCTION LocalChain & operator+=(const LocalChain &simplices_to_add)
KOKKOS_FUNCTION auto cend() const
KOKKOS_FUNCTION auto cbegin() const
KOKKOS_FUNCTION auto begin()
KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain()=default
KOKKOS_DEFAULTED_FUNCTION ~LocalChain()=default
KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain(LocalChain const &)=default
KOKKOS_FUNCTION constexpr LocalChain(vects_type allocation, simplices_type simplices, std::size_t size) noexcept
KOKKOS_FUNCTION auto end() const
KOKKOS_FUNCTION simplex_type operator[](std::size_t i) noexcept
KOKKOS_FUNCTION std::size_t size() const noexcept
KOKKOS_DEFAULTED_FUNCTION LocalChain & operator=(LocalChain const &other)=default
typename simplex_type::discrete_element_type discrete_element_type
KOKKOS_FUNCTION LocalChain & operator+=(const vects_type &vects_to_add)
KOKKOS_DEFAULTED_FUNCTION constexpr LocalChain(LocalChain &&)=default
KOKKOS_FUNCTION LocalChain operator+(simplex_type simplex)
KOKKOS_FUNCTION simplices_type & allocation() noexcept
LocalChain operator-(LocalChain)=delete
KOKKOS_FUNCTION LocalChain & operator+=(const std::size_t n)
KOKKOS_FUNCTION LocalChain & operator+=(const discrete_vector_type &vect)
KOKKOS_FUNCTION simplex_type const operator[](std::size_t i) const noexcept
KOKKOS_FUNCTION std::size_t size() noexcept
KOKKOS_FUNCTION auto begin() const
static KOKKOS_FUNCTION constexpr bool negative()
KOKKOS_FUNCTION bool operator==(LocalChain simplices)
Kokkos::Experimental::Impl::RandomAccessIterator< vects_type > iterator_type
KOKKOS_FUNCTION LocalChain & operator+=(const simplex_type &simplex)
KOKKOS_FUNCTION auto end()
Simplex class.
Definition simplex.hpp:75
std::ostream & operator<<(std::ostream &out, ChainType const &chain)
Definition chain.hpp:304
constexpr auto tangent_basis(ExecSpace const &exec_space)
Simplex(ddc::DiscreteElement< Tag... >, ddc::DiscreteVector< T... >) -> Simplex< sizeof...(T), Tag... >
LocalChain(Head, Tail...) -> LocalChain< ddc::type_seq_element_t< 0, ddc::detail::TypeSeq< Tail... > >, typename Head::array_layout, typename Head::memory_space >
constexpr bool are_all_equal(Head head, Tail... tail)
constexpr T filled_struct(ElementType const n=0)
constexpr std::size_t binomial_coefficient(std::size_t n, std::size_t k) noexcept
typename detail::ConvertTypeSeqTo< T, Seq >::type convert_type_seq_to_t
The top-level namespace of SimiLie.
Definition csr.hpp:14