SimiLie
Loading...
Searching...
No Matches
metric.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/macros.hpp>
9#include <similie/misc/small_matrix.hpp>
10#include <similie/misc/unsecure_parallel_deepcopy.hpp>
11
12#include "character.hpp"
13#include "diagonal_tensor.hpp"
14#include "identity_tensor.hpp"
15#include "lorentzian_sign_tensor.hpp"
16#include "prime.hpp"
17#include "relabelization.hpp"
18#include "symmetric_tensor.hpp"
19#include "tensor_prod.hpp"
20
21namespace sil {
22
23namespace tensor {
24
25// Abstract indices used to characterize a generic metric
26
27template <class... CDim>
29{
30};
31
32template <class MetricIndex>
34 = ddc::type_seq_element_t<0, ddc::to_type_seq_t<typename MetricIndex::subindices_domain_t>>;
35
36template <class... CDim>
37struct MetricIndex2 : TensorNaturalIndex<CDim...>
38{
39};
40
41template <class MetricIndex>
43 = ddc::type_seq_element_t<1, ddc::to_type_seq_t<typename MetricIndex::subindices_domain_t>>;
44
45namespace detail {
46
47template <class TypeSeqCDim>
48struct ConvertTypeSeqToMetricIndex1;
49
50template <class... CDim>
51struct ConvertTypeSeqToMetricIndex1<ddc::detail::TypeSeq<CDim...>>
52{
53 using type = MetricIndex1<CDim...>;
54};
55
56template <class TypeSeqCDim>
57struct ConvertTypeSeqToMetricIndex2;
58
59template <class... CDim>
60struct ConvertTypeSeqToMetricIndex2<ddc::detail::TypeSeq<CDim...>>
61{
62 using type = MetricIndex2<CDim...>;
63};
64
65} // namespace detail
66
67// Relabelize metric
68template <
71 TensorNatIndex Index2>
73 Dom,
74 ddc::detail::TypeSeq<
75 typename detail::ConvertTypeSeqToMetricIndex1<
76 typename Index1::type_seq_dimensions>::type,
77 typename detail::ConvertTypeSeqToMetricIndex2<
78 typename Index2::type_seq_dimensions>::type>,
79 ddc::detail::TypeSeq<uncharacterize_t<Index1>, uncharacterize_t<Index2>>>;
81template <TensorNatIndex Index1, TensorNatIndex Index2, class Dom>
83 Dom metric_dom)
84{
86 ddc::detail::TypeSeq<
87 typename detail::ConvertTypeSeqToMetricIndex1<
88 typename Index1::type_seq_dimensions>::type,
89 typename detail::ConvertTypeSeqToMetricIndex2<
90 typename Index2::type_seq_dimensions>::type>,
91 ddc::detail::TypeSeq<uncharacterize_t<Index1>, uncharacterize_t<Index2>>>(metric_dom);
92}
94template <misc::Specialization<Tensor> TensorType, TensorNatIndex Index1, TensorNatIndex Index2>
96 TensorType,
97 ddc::detail::TypeSeq<
98 typename detail::ConvertTypeSeqToMetricIndex1<
99 typename Index1::type_seq_dimensions>::type,
100 typename detail::ConvertTypeSeqToMetricIndex2<
101 typename Index2::type_seq_dimensions>::type>,
102 ddc::detail::TypeSeq<uncharacterize_t<Index1>, uncharacterize_t<Index2>>>;
104template <TensorNatIndex Index1, TensorNatIndex Index2, misc::Specialization<Tensor> TensorType>
106{
108 ddc::detail::TypeSeq<
109 typename detail::ConvertTypeSeqToMetricIndex1<
110 typename Index1::type_seq_dimensions>::type,
111 typename detail::ConvertTypeSeqToMetricIndex2<
112 typename Index2::type_seq_dimensions>::type>,
113 ddc::detail::TypeSeq<uncharacterize_t<Index1>, uncharacterize_t<Index2>>>(tensor);
114}
115
116// Compute domain for a tensor product of metrics (ie. g_mu_muprime*g_nu_nuprime*...)
117namespace detail {
118
119template <class MetricIndex, class Indices1, class Indices2>
120struct MetricProdDomainType;
121
122template <class MetricIndex, class... Index1, class... Index2>
123struct MetricProdDomainType<
124 MetricIndex,
125 ddc::detail::TypeSeq<Index1...>,
126 ddc::detail::TypeSeq<Index2...>>
127{
128 static_assert(sizeof...(Index1) == sizeof...(Index2));
129 using type = ddc::cartesian_prod_t<relabelize_metric_in_domain_t<
130 ddc::DiscreteDomain<MetricIndex>,
131 Index1,
132 ddc::type_seq_element_t<
133 ddc::type_seq_rank_v<Index1, ddc::detail::TypeSeq<Index1...>>,
134 ddc::detail::TypeSeq<Index2...>>>...>;
135};
136
137} // namespace detail
138
139template <
140 TensorIndex MetricIndex,
144 typename detail::MetricProdDomainType<MetricIndex, Indices1, Indices2>::type;
145
146namespace detail {
147
148// Compute tensor product of metrics (ie. g_mu_muprime*g_nu_nuprime*...)
149template <
150 class NonMetricDom,
151 class MetricIndex,
152 class Indices1,
153 class Indices2,
154 class LayoutStridedPolicy,
155 class MemorySpace>
156struct MetricProdType;
157
158template <
159 class NonMetricDom,
160 class MetricIndex,
161 class... Index1,
162 class... Index2,
163 class LayoutStridedPolicy,
164 class MemorySpace>
165struct MetricProdType<
166 NonMetricDom,
167 MetricIndex,
168 ddc::detail::TypeSeq<Index1...>,
169 ddc::detail::TypeSeq<Index2...>,
170 LayoutStridedPolicy,
171 MemorySpace>
172{
173 using type = tensor::Tensor<
174 double,
175 ddc::cartesian_prod_t<
176 NonMetricDom,
178 MetricIndex,
179 ddc::detail::TypeSeq<Index1...>,
180 ddc::detail::TypeSeq<Index2...>>>,
181 LayoutStridedPolicy,
182 MemorySpace>;
183};
184
185template <class MetricType, class BatchElem, class Indices1, class Indices2>
186struct MetricProdValue;
187
188template <class MetricType, class BatchElem>
189struct MetricProdValue<MetricType, BatchElem, ddc::detail::TypeSeq<>, ddc::detail::TypeSeq<>>
190{
191 KOKKOS_FUNCTION static double run(
192 [[maybe_unused]] MetricType metric,
193 [[maybe_unused]] BatchElem elem,
194 [[maybe_unused]] auto natural_elem)
195 {
196 return 1.;
197 }
198};
199
200template <
201 class MetricType,
202 class BatchElem,
203 class HeadIndex1,
204 class... TailIndex1,
205 class HeadIndex2,
206 class... TailIndex2>
207struct MetricProdValue<
208 MetricType,
209 BatchElem,
210 ddc::detail::TypeSeq<HeadIndex1, TailIndex1...>,
211 ddc::detail::TypeSeq<HeadIndex2, TailIndex2...>>
212{
213 KOKKOS_FUNCTION static double run(MetricType metric, BatchElem elem, auto natural_elem)
214 {
215 auto const relabeled_metric = relabelize_metric<HeadIndex1, HeadIndex2>(metric);
216 using metric_natural_elem_type = typename decltype(relabeled_metric)::accessor_t::
217 natural_domain_t::discrete_element_type;
218 metric_natural_elem_type const metric_natural_elem(natural_elem);
219 return relabeled_metric.get(relabeled_metric.access_element(elem, metric_natural_elem))
220 * MetricProdValue<
221 MetricType,
222 BatchElem,
223 ddc::detail::TypeSeq<TailIndex1...>,
224 ddc::detail::TypeSeq<TailIndex2...>>::run(metric, elem, natural_elem);
225 }
226};
227
228} // namespace detail
229
230template <
232 TensorIndex MetricIndex,
235 class LayoutStridedPolicy,
236 class MemorySpace>
237using metric_prod_t = typename detail::MetricProdType<
238 NonMetricDom,
239 MetricIndex,
240 Indices1,
241 Indices2,
242 LayoutStridedPolicy,
243 MemorySpace>::type;
244
245template <
246 TensorIndex MetricIndex,
250 class BatchElem>
251struct MetricProd
253 template <misc::Specialization<Tensor> MetricProdType_>
254 KOKKOS_FUNCTION static void run(MetricProdType_ metric_prod, MetricType metric, BatchElem elem)
255 {
256 ddc::device_for_each(metric_prod.domain(), [&](auto mem_elem) {
257 metric_prod.mem(mem_elem)
258 = value(metric, elem, metric_prod.canonical_natural_element(mem_elem));
259 });
261
262 KOKKOS_FUNCTION static double value(MetricType metric, BatchElem elem, auto natural_elem)
263 {
264 return detail::MetricProdValue<MetricType, BatchElem, Indices1, Indices2>::
265 run(metric, elem, natural_elem);
266 }
267};
268
269template <
270 TensorIndex MetricIndex,
271 misc::Specialization<ddc::detail::TypeSeq> Indices1,
272 misc::Specialization<ddc::detail::TypeSeq> Indices2,
273 misc::Specialization<Tensor> MetricType,
274 class ExecSpace>
276 typename MetricType::non_indices_domain_t,
277 MetricIndex,
278 Indices1,
279 Indices2,
280 typename MetricType::layout_type,
281 typename MetricType::memory_space>
283 ExecSpace const& exec_space,
285 typename MetricType::non_indices_domain_t,
286 MetricIndex,
287 Indices1,
288 Indices2,
289 typename MetricType::layout_type,
290 typename MetricType::memory_space> metric_prod,
291 MetricType metric)
292{
293 SIMILIE_DEBUG_LOG("similie_compute_metric_prod");
294 ddc::parallel_for_each(
295 "similie_compute_metric_prod",
296 exec_space,
297 metric_prod.non_indices_domain(),
298 KOKKOS_LAMBDA(
299 typename decltype(metric_prod)::non_indices_domain_t::discrete_element_type
300 elem) {
301 MetricProd<MetricIndex, Indices1, Indices2, MetricType, decltype(elem)>::
302 run(metric_prod[elem], metric, elem);
303 });
304 return metric_prod;
305}
306
307namespace detail {
308
309template <class Dom>
310using non_primes = ddc::type_seq_remove_t<ddc::to_type_seq_t<Dom>, primes<ddc::to_type_seq_t<Dom>>>;
311
312} // namespace detail
313
314// Apply metrics inplace (like g_mu_muprime*T^muprime^nu)
315template <
316 misc::Specialization<Tensor> MetricType,
317 misc::Specialization<Tensor> TensorType,
318 class ExecSpace>
320 TensorType,
322 detail::non_primes<typename MetricType::accessor_t::natural_domain_t>>
323inplace_apply_metric(ExecSpace const& exec_space, TensorType tensor, MetricType metric_prod)
324{
325 ddc::Chunk result_alloc(
328 detail::non_primes<typename MetricType::accessor_t::natural_domain_t>>,
329 detail::non_primes<typename MetricType::accessor_t::natural_domain_t>>(
330 tensor.domain()),
331 ddc::KokkosAllocator<double, typename ExecSpace::memory_space>());
333 TensorType,
335 detail::non_primes<typename MetricType::accessor_t::natural_domain_t>>
336 result(result_alloc);
337 SIMILIE_DEBUG_LOG("similie_inplace_apply_metric");
338 ddc::parallel_for_each(
339 "similie_inplace_apply_metric",
340 exec_space,
341 tensor.non_indices_domain(),
342 KOKKOS_LAMBDA(typename TensorType::non_indices_domain_t::discrete_element_type elem) {
344 result[elem],
345 metric_prod[elem],
347 swap_character_t<detail::non_primes<
348 typename MetricType::accessor_t::natural_domain_t>>,
349 primes<swap_character_t<detail::non_primes<
350 typename MetricType::accessor_t::natural_domain_t>>>>(
351 tensor)[elem]);
352 });
353 misc::detail::unsecure_parallel_deepcopy(exec_space, tensor, result);
354
357 detail::non_primes<typename MetricType::accessor_t::natural_domain_t>>(tensor);
358}
359
360template <
361 TensorIndex MetricIndex,
362 TensorNatIndex... Index1,
365 class ExecSpace>
367 TensorType,
368 swap_character_t<ddc::detail::TypeSeq<Index1...>>,
369 ddc::detail::TypeSeq<Index1...>>
370inplace_apply_metric(ExecSpace const& exec_space, TensorType tensor, MetricType metric)
371{
373 MetricIndex,
374 ddc::detail::TypeSeq<Index1...>,
375 primes<ddc::detail::TypeSeq<Index1...>>>>
376 metric_prod_accessor;
377 ddc::Chunk metric_prod_alloc(
378 ddc::cartesian_prod_t<
379 typename TensorType::non_indices_domain_t,
381 MetricIndex,
382 ddc::detail::TypeSeq<Index1...>,
383 primes<ddc::detail::TypeSeq<Index1...>>>>(
384 tensor.non_indices_domain(),
385 metric_prod_accessor.domain()),
386 ddc::KokkosAllocator<double, typename ExecSpace::memory_space>());
387 tensor::Tensor metric_prod(metric_prod_alloc);
388
390 MetricIndex,
391 ddc::detail::TypeSeq<Index1...>,
392 primes<ddc::detail::TypeSeq<Index1...>>>(exec_space, metric_prod, metric);
393
394 return inplace_apply_metric(exec_space, tensor, metric_prod);
395}
397template <misc::Specialization<Tensor> MetricType>
399 MetricType,
400 ddc::to_type_seq_t<typename MetricType::accessor_t::natural_domain_t>,
403template <TensorIndex MetricIndex, misc::Specialization<Tensor> MetricType, class BatchElem>
405{
408 template <misc::Specialization<Tensor> OutputTensorType>
409 KOKKOS_FUNCTION static void run(OutputTensorType inv_metric, MetricType metric, BatchElem elem)
410 {
411 if constexpr (
414 ddc::device_for_each(inv_metric.domain(), [&](auto mem_elem) {
415 inv_metric.mem(mem_elem)
416 = value(metric, elem, inv_metric.canonical_natural_element(mem_elem));
417 });
419 ddc::device_for_each(inv_metric.domain(), [&](auto mem_elem) {
420 inv_metric.mem(mem_elem)
421 = value(metric, elem, inv_metric.canonical_natural_element(mem_elem));
422 });
424 constexpr std::size_t N = metric_index_1<MetricIndex>::size();
425 using memory_space = typename MetricType::memory_space;
426 using metric_index_1_t = metric_index_1<MetricIndex>;
427 using metric_index_2_t = metric_index_2<MetricIndex>;
428
429 std::array<double, N * N> matrix_alloc {};
430 std::array<double, N * N> inverse_alloc {};
431 std::array<double, N * N> workspace_alloc {};
432 auto matrix_view
433 = misc::math::matrix_view<double, memory_space>(matrix_alloc.data(), N, N);
434 auto inverse_view
435 = misc::math::matrix_view<double, memory_space>(inverse_alloc.data(), N, N);
436 auto workspace
437 = misc::math::vector_view<double, memory_space>(workspace_alloc.data(), N * N);
438
439 for (std::size_t i = 0; i < N; ++i) {
440 for (std::size_t j = 0; j < N; ++j) {
441 matrix_view(i, j) = metric.get(metric.access_element(
442 elem,
443 ddc::DiscreteElement<metric_index_1_t, metric_index_2_t>(i, j)));
444 }
445 }
446
447 bool const success = misc::math::invert(inverse_view, matrix_view, workspace);
448 assert(success && "Kokkos-kernels failed at inverting metric tensor");
449
450 ddc::device_for_each(inv_metric.domain(), [&](auto mem_elem) {
451 auto const natural_elem = inv_metric.canonical_natural_element(mem_elem);
452 auto const ids = ddc::detail::array(natural_elem);
453 inv_metric.mem(mem_elem) = inverse_view(ids[0], ids[1]);
454 });
455 }
457
458 KOKKOS_FUNCTION static double value(MetricType metric, BatchElem elem, auto natural_elem)
459 {
461 auto const ids = ddc::detail::array(natural_elem);
462 return ids[0] == ids[1] ? 1. : 0.;
464 return metric.get(metric.access_element(elem, natural_elem));
465 } else if constexpr (misc::Specialization<MetricIndex, TensorDiagonalIndex>) {
466 return 1.
467 / metric.get(
469 swap_character_t<ddc::to_type_seq_t<
470 typename MetricType::accessor_t::natural_domain_t>>,
471 ddc::to_type_seq_t<
472 typename MetricType::accessor_t::natural_domain_t>>(
473 metric)
474 .access_element(elem, natural_elem));
475 } else if constexpr (misc::Specialization<MetricIndex, TensorSymmetricIndex>) {
476 [[maybe_unused]] typename output_tensor_type::accessor_t accessor;
477 std::array<double, output_tensor_type::accessor_t::domain().size()> alloc {};
478 ddc::ChunkSpan<
479 double,
480 typename output_tensor_type::indices_domain_t,
481 Kokkos::layout_right,
482 typename MetricType::memory_space>
483 span(alloc.data(), accessor.domain());
484 tensor::Tensor local_inverse(span);
485 run(local_inverse, metric, elem);
486 return local_inverse.get(local_inverse.access_element(natural_elem));
487 } else {
488 return 0.;
489 }
490 }
491};
492
493// Compute invert metric (g_mu_nu for gmunu or gmunu for g_mu_nu)
494template <TensorIndex MetricIndex, misc::Specialization<Tensor> MetricType, class ExecSpace>
496 ExecSpace const& exec_space,
498 MetricType metric)
499{
500 SIMILIE_DEBUG_LOG("similie_invert_metric");
501 ddc::parallel_for_each(
502 "similie_invert_metric",
503 exec_space,
504 inv_metric.non_indices_domain(),
505 KOKKOS_LAMBDA(
506 typename invert_metric_t<
507 MetricType>::non_indices_domain_t::discrete_element_type elem) {
508 InverseMetric<MetricIndex, MetricType, decltype(elem)>::
509 run(inv_metric[elem], metric, elem);
510 });
511
512 return inv_metric;
513}
514
515} // namespace tensor
516
517} // namespace sil
KOKKOS_FUNCTION bool invert(InverseView inverse, MatrixView matrix, WorkspaceView workspace)
KOKKOS_FUNCTION unmanaged_vector_view_t< Scalar, MemorySpace > vector_view(Scalar *data, std::size_t n)
KOKKOS_FUNCTION unmanaged_matrix_view_t< Scalar, MemorySpace > matrix_view(Scalar *data, std::size_t rows, std::size_t cols)
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
relabelize_indices_of_t< MetricType, ddc::to_type_seq_t< typename MetricType::accessor_t::natural_domain_t >, swap_character_t< ddc::to_type_seq_t< typename MetricType::accessor_t::natural_domain_t > > > invert_metric_t
Definition metric.hpp:396
typename detail::MetricProdType< NonMetricDom, MetricIndex, Indices1, Indices2, LayoutStridedPolicy, MemorySpace >::type metric_prod_t
Definition metric.hpp:235
detail::RelabelizeIndicesOfType< TensorType, OldIndices, NewIndices >::type relabelize_indices_of_t
ddc::type_seq_element_t< 0, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_1
Definition metric.hpp:33
detail::Primes< Indices, I >::type primes
Definition prime.hpp:56
constexpr relabelize_indices_in_t< T, OldIndices, NewIndices > relabelize_indices_in(T t)
invert_metric_t< MetricType > fill_inverse_metric(ExecSpace const &exec_space, invert_metric_t< MetricType > inv_metric, MetricType metric)
Definition metric.hpp:493
constexpr relabelize_metric_in_domain_t< Dom, Index1, Index2 > relabelize_metric_in_domain(Dom metric_dom)
Definition metric.hpp:80
relabelize_indices_of_t< TensorType, ddc::detail::TypeSeq< typename detail::ConvertTypeSeqToMetricIndex1< typename Index1::type_seq_dimensions >::type, typename detail::ConvertTypeSeqToMetricIndex2< typename Index2::type_seq_dimensions >::type >, ddc::detail::TypeSeq< uncharacterize_t< Index1 >, uncharacterize_t< Index2 > > > relabelize_metric_t
Definition metric.hpp:93
constexpr relabelize_metric_t< TensorType, Index1, Index2 > relabelize_metric(TensorType tensor)
Definition metric.hpp:103
ddc::type_seq_element_t< 1, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_2
Definition metric.hpp:41
typename detail::MetricProdDomainType< MetricIndex, Indices1, Indices2 >::type metric_prod_domain_t
Definition metric.hpp:141
metric_prod_t< typename MetricType::non_indices_domain_t, MetricIndex, Indices1, Indices2, typename MetricType::layout_type, typename MetricType::memory_space > fill_metric_prod(ExecSpace const &exec_space, metric_prod_t< typename MetricType::non_indices_domain_t, MetricIndex, Indices1, Indices2, typename MetricType::layout_type, typename MetricType::memory_space > metric_prod, MetricType metric)
Definition metric.hpp:280
Tensor< ElementType, ddc::DiscreteDomain< ProdDDim... >, LayoutStridedPolicy, MemorySpace > tensor_prod(Tensor< ElementType, ddc::DiscreteDomain< ProdDDim... >, LayoutStridedPolicy, MemorySpace > prod_tensor, Tensor< ElementType, ddc::DiscreteDomain< DDim1... >, LayoutStridedPolicy, MemorySpace > tensor1, Tensor< ElementType, ddc::DiscreteDomain< DDim2... >, LayoutStridedPolicy, MemorySpace > tensor2)
detail::SwapCharacter< T >::type swap_character_t
relabelize_indices_of_t< TensorType, swap_character_t< detail::non_primes< typename MetricType::accessor_t::natural_domain_t > >, detail::non_primes< typename MetricType::accessor_t::natural_domain_t > > inplace_apply_metric(ExecSpace const &exec_space, TensorType tensor, MetricType metric_prod)
Definition metric.hpp:321
relabelize_indices_in_t< Dom, ddc::detail::TypeSeq< typename detail::ConvertTypeSeqToMetricIndex1< typename Index1::type_seq_dimensions >::type, typename detail::ConvertTypeSeqToMetricIndex2< typename Index2::type_seq_dimensions >::type >, ddc::detail::TypeSeq< uncharacterize_t< Index1 >, uncharacterize_t< Index2 > > > relabelize_metric_in_domain_t
Definition metric.hpp:70
detail::Uncharacterize< Index >::type uncharacterize_t
constexpr relabelize_indices_of_t< Tensor, OldIndices, NewIndices > relabelize_indices_of(Tensor tensor)
detail::TensorAccessorForDomain< Dom >::type tensor_accessor_for_domain_t
typename detail::RelabelizeIndicesInType< T, OldIndices, NewIndices >::type relabelize_indices_in_t
The top-level namespace of SimiLie.
Definition csr.hpp:15
invert_metric_t< MetricType > output_tensor_type
Definition metric.hpp:404
static KOKKOS_FUNCTION void run(OutputTensorType inv_metric, MetricType metric, BatchElem elem)
Definition metric.hpp:407
static KOKKOS_FUNCTION double value(MetricType metric, BatchElem elem, auto natural_elem)
Definition metric.hpp:456
static KOKKOS_FUNCTION double value(MetricType metric, BatchElem elem, auto natural_elem)
Definition metric.hpp:260
static KOKKOS_FUNCTION void run(MetricProdType_ metric_prod, MetricType metric, BatchElem elem)
Definition metric.hpp:252