10#include <similie/misc/factorial.hpp>
11#include <similie/misc/macros.hpp>
12#include <similie/misc/small_matrix.hpp>
13#include <similie/misc/specialization.hpp>
14#include <similie/misc/type_seq_conversion.hpp>
15#include <similie/tensor/antisymmetric_tensor.hpp>
16#include <similie/tensor/character.hpp>
17#include <similie/tensor/full_tensor.hpp>
18#include <similie/tensor/metric.hpp>
20#include "reduction_and_reconstruction.hpp"
28 misc::Specialization<ddc::detail::TypeSeq> Indices1,
29 misc::Specialization<ddc::detail::TypeSeq> Indices2>
31 = ddc::detail::convert_type_seq_to_discrete_domain_t<ddc::type_seq_merge_t<
35 (ddc::type_seq_size_v<Indices2> == 0),
36 ddc::detail::TypeSeq<>,
59template <std::
size_t N, std::
size_t M>
60KOKKOS_FUNCTION
bool has_unique_ids(std::array<std::size_t, M>
const& ids)
62 if constexpr (M > 0) {
63 for (std::size_t i = 0; i < M; ++i) {
67 for (std::size_t j = i + 1; j < M; ++j) {
68 if (ids[i] == ids[j]) {
77template <std::
size_t N, std::
size_t M1, std::
size_t M2>
78KOKKOS_FUNCTION
bool is_complete_permutation(
79 std::array<std::size_t, M1>
const& source_ids,
80 std::array<std::size_t, M2>
const& target_ids)
82 std::array<int, N> counts {};
83 for (std::size_t
id : source_ids) {
89 for (std::size_t
id : target_ids) {
95 for (
int count : counts) {
103template <std::
size_t N, std::
size_t M1, std::
size_t M2>
104KOKKOS_FUNCTION
int permutation_sign(
105 std::array<std::size_t, M1>
const& source_ids,
106 std::array<std::size_t, M2>
const& target_ids)
108 std::array<std::size_t, N> permutation {};
109 for (std::size_t i = 0; i < M1; ++i) {
110 permutation[i] = source_ids[i];
112 if constexpr (M2 > 0) {
113 for (std::size_t i = 0; i < M2; ++i) {
114 permutation[M1 + i] = target_ids[i];
119 for (std::size_t i = 0; i < N; ++i) {
120 for (std::size_t j = i + 1; j < N; ++j) {
121 odd = (permutation[i] > permutation[j]) != odd;
127template <std::
size_t N, std::
size_t M>
128KOKKOS_FUNCTION std::array<std::size_t, N - M> complement_ids(std::array<std::size_t, M>
const& ids)
130 std::array<std::size_t, N - M> complement {};
131 std::size_t complement_id = 0;
132 for (std::size_t i = 0; i < N; ++i) {
134 for (std::size_t
id : ids) {
135 found = found || (
id == i);
138 complement[complement_id++] = i;
144template <misc::Specialization<ddc::detail::TypeSeq> Indices>
145struct HodgeStarTargetSize
147 static constexpr std::size_t value
148 = misc::convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, Indices>::access_size();
152struct HodgeStarTargetSize<ddc::detail::TypeSeq<>>
154 static constexpr std::size_t value = 1;
159 misc::Specialization<ddc::detail::TypeSeq> Indices1,
160 misc::Specialization<ddc::detail::TypeSeq> Indices2,
161 misc::Specialization<tensor::Tensor> HodgeStarType,
162 misc::Specialization<tensor::Tensor> MetricType,
163 misc::Specialization<tensor::Tensor> PositionType,
165struct FillDiscreteHodgeStarMem
167 HodgeStarType m_hodge_star;
169 PositionType m_position;
172 template <
class MemElem>
173 KOKKOS_FUNCTION
void operator()(MemElem mem_elem)
const
175 m_hodge_star.mem(
typename HodgeStarType::discrete_element_type(m_elem, mem_elem))
186 m_hodge_star.accessor().canonical_natural_element(mem_elem));
191 misc::Specialization<ddc::detail::TypeSeq> Indices1,
192 misc::Specialization<ddc::detail::TypeSeq> Indices2,
193 misc::Specialization<tensor::Tensor> HodgeStarType,
194 misc::Specialization<tensor::Tensor> MetricType,
196struct FillContinuousHodgeStarMem
198 HodgeStarType m_hodge_star;
202 template <
class MemElem>
203 KOKKOS_FUNCTION
void operator()(MemElem mem_elem)
const
205 m_hodge_star.mem(
typename HodgeStarType::discrete_element_type(m_elem, mem_elem))
209 m_hodge_star.accessor().canonical_natural_element(mem_elem));
217 misc::Specialization<ddc::detail::TypeSeq> Indices1,
218 misc::Specialization<ddc::detail::TypeSeq> Indices2,
227 KOKKOS_FUNCTION
static void run(
228 HodgeTensorType hodge_tensor,
229 FormTensorType form_tensor,
231 PositionType position,
234 using InputIndex = ddc::type_seq_element_t<
236 ddc::to_type_seq_t<typename FormTensorType::indices_domain_t>>;
237 using OutputIndex = ddc::type_seq_element_t<
239 ddc::to_type_seq_t<typename HodgeTensorType::indices_domain_t>>;
241 = ddc::to_type_seq_t<typename FormTensorType::accessor_t::natural_domain_t>;
243 = ddc::to_type_seq_t<typename HodgeTensorType::accessor_t::natural_domain_t>;
246 std::array<double, InputIndex::access_size()> reconstructed_alloc {};
249 ddc::DiscreteDomain<InputIndex>,
250 Kokkos::layout_right,
251 typename FormTensorType::memory_space>
252 reconstructed_span(reconstructed_alloc.data(), reconstructed_accessor.
domain());
256 std::array<double, OutputIndex::access_size()> continuous_output_alloc {};
259 ddc::DiscreteDomain<OutputIndex>,
260 Kokkos::layout_right,
261 typename HodgeTensorType::memory_space>
262 continuous_output_span(
263 continuous_output_alloc.data(),
264 continuous_output_accessor.
domain());
268 run(reconstructed_form, form_tensor, position, elem);
270 run(continuous_output, reconstructed_form, metric, elem);
272 run(hodge_tensor, continuous_output, metric, position, elem);
275 KOKKOS_FUNCTION
static double value(
277 PositionType position,
283 using SourceNaturalElem =
285 using TargetNaturalElem =
291 std::array<double, SourceIndex::access_size()> source_alloc {};
294 ddc::DiscreteDomain<SourceIndex>,
295 Kokkos::layout_right,
296 typename MetricType::memory_space>
297 source_span(source_alloc.data(), source_accessor.
domain());
299 ddc::device_for_each(source_tensor.domain(), [&](
auto source_mem_elem) {
300 source_tensor.mem(source_mem_elem) = 0.;
304 std::array<double, TargetIndex::access_size()> target_alloc {};
307 ddc::DiscreteDomain<TargetIndex>,
308 Kokkos::layout_right,
309 typename MetricType::memory_space>
310 target_span(target_alloc.data(), target_accessor.
domain());
312 ddc::device_for_each(target_tensor.domain(), [&](
auto target_mem_elem) {
313 target_tensor.mem(target_mem_elem) = 0.;
316 std::array source_ids = ddc::detail::array(SourceFullElem(natural_elem));
317 if constexpr (ddc::type_seq_size_v<Indices1> > 1) {
318 if (!detail::has_unique_ids<SourceIndex::size()>(source_ids)) {
323 for (std::size_t i = 0; i < source_ids.size(); ++i) {
324 for (std::size_t j = i + 1; j < source_ids.size(); ++j) {
325 odd = (source_ids[i] > source_ids[j]) != odd;
328 std::array canonical_source_ids(source_ids);
329 if constexpr (source_ids.size() > 1) {
330 for (std::size_t i = 0; i < canonical_source_ids.size(); ++i) {
331 for (std::size_t j = i + 1; j < canonical_source_ids.size(); ++j) {
332 if (canonical_source_ids[j] < canonical_source_ids[i]) {
333 Kokkos::kokkos_swap(canonical_source_ids[i], canonical_source_ids[j]);
339 SourceNaturalElem source_natural_elem;
340 ddc::detail::array(source_natural_elem) = canonical_source_ids;
341 source_tensor(source_tensor.accessor().access_element(source_natural_elem)) = 1.;
343 run(target_tensor, source_tensor, metric, position, elem);
345 double const source_factor
347 if constexpr (ddc::type_seq_size_v<Indices2> == 0) {
349 * target_tensor(target_tensor.accessor().access_element(TargetNaturalElem()));
351 TargetNaturalElem target_natural_elem;
352 ddc::detail::array(target_natural_elem)
353 = ddc::detail::array(TargetFullElem(natural_elem));
356 target_tensor.accessor().access_element(target_natural_elem));
371 KOKKOS_FUNCTION
static void run(
372 HodgeTensorType hodge_tensor,
373 FormTensorType form_tensor,
379 static constexpr std::size_t HODGE_STAR_SIZE
381 * detail::HodgeStarTargetSize<Indices2>::value;
382 std::array<double, HODGE_STAR_SIZE> hodge_star_alloc {};
386 Kokkos::layout_right,
387 typename HodgeTensorType::memory_space>
388 hodge_star_span(hodge_star_alloc.data(), hodge_star_accessor.domain());
390 ddc::device_for_each(hodge_star.domain(), [&](
auto it) {
391 hodge_star.mem(it) = value(metric, elem, hodge_star.canonical_natural_element(it));
396 KOKKOS_FUNCTION
static double value(MetricType metric, BatchElem elem,
auto natural_elem)
398 constexpr std::size_t N = ddc::type_seq_size_v<Indices1> + ddc::type_seq_size_v<Indices2>;
399 constexpr std::size_t K = ddc::type_seq_size_v<Indices1>;
402 std::array
const source_ids = ddc::detail::array(SourceElem(natural_elem));
403 std::array
const target_ids = ddc::detail::array(TargetElem(natural_elem));
405 if (!detail::has_unique_ids<N>(source_ids) || !detail::has_unique_ids<N>(target_ids)
406 || !detail::is_complete_permutation<N>(source_ids, target_ids)) {
410 std::array<std::size_t, K>
const complement = detail::complement_ids<N>(target_ids);
411 using MetricIndex = ddc::
412 type_seq_element_t<0, ddc::to_type_seq_t<typename MetricType::indices_domain_t>>;
415 std::array<double, N * N> metric_alloc {};
416 std::array<double, N * N> determinant_metric_alloc {};
417 std::array<double, N * N> inverse_metric_alloc {};
418 std::array<double, N * N> workspace_alloc {};
419 std::array<double, K * K> submatrix_alloc {};
420 for (std::size_t i = 0; i < N; ++i) {
421 for (std::size_t j = 0; j < N; ++j) {
422 metric_alloc[i * N + j] = metric.get(metric.access_element(
424 ddc::DiscreteElement<MetricIndex1, MetricIndex2>(i, j)));
427 determinant_metric_alloc = metric_alloc;
431 typename MetricType::memory_space>(determinant_metric_alloc.data(), N, N);
437 typename MetricType::memory_space>(inverse_metric_alloc.data(), N, N);
440 typename MetricType::memory_space>(workspace_alloc.data(), N * N);
445 return Kokkos::sqrt(Kokkos::abs(determinant))
446 *
static_cast<double>(detail::permutation_sign<N>(complement, target_ids))
448 K>(inverse_metric_view, source_ids, complement, submatrix_alloc)
462 ExecSpace
const& exec_space,
463 HodgeStarType hodge_star,
465 PositionType position)
468 ddc::type_seq_size_v<ddc::to_type_seq_t<typename PositionType::indices_domain_t>> == 1);
470 SIMILIE_DEBUG_LOG(
"similie_compute_hodge_star");
471 ddc::parallel_for_each(
472 "similie_compute_hodge_star",
474 hodge_star.non_indices_domain(),
476 typename HodgeStarType::non_indices_domain_t::discrete_element_type elem) {
477 ddc::device_for_each(
478 hodge_star.accessor().domain(),
479 detail::FillDiscreteHodgeStarMem<
486 typename HodgeStarType::non_indices_domain_t::
487 discrete_element_type> {
503 ExecSpace
const& exec_space,
504 HodgeStarType hodge_star,
507 SIMILIE_DEBUG_LOG(
"similie_compute_continuous_hodge_star");
508 ddc::parallel_for_each(
509 "similie_compute_continuous_hodge_star",
511 hodge_star.non_indices_domain(),
513 typename HodgeStarType::non_indices_domain_t::discrete_element_type elem) {
514 ddc::device_for_each(
515 hodge_star.accessor().domain(),
516 detail::FillContinuousHodgeStarMem<
521 typename HodgeStarType::non_indices_domain_t::
522 discrete_element_type> {hodge_star, metric, elem});
static constexpr discrete_domain_type domain()
ddc::detail::convert_type_seq_to_discrete_domain_t< ddc::type_seq_merge_t< ddc::detail::TypeSeq< misc::convert_type_seq_to_t< tensor::TensorFullIndex, Indices1 > >, std::conditional_t<(ddc::type_seq_size_v< Indices2 >==0), ddc::detail::TypeSeq<>, ddc::detail::TypeSeq< misc::convert_type_seq_to_t< tensor::TensorAntisymmetricIndex, Indices2 > > > > > hodge_star_domain_t
HodgeStarType fill_continuous_hodge_star(ExecSpace const &exec_space, HodgeStarType hodge_star, MetricType metric)
typename detail::ReductionTargetIndex< Indices >::type reduction_index_t
HodgeStarType fill_discrete_hodge_star(ExecSpace const &exec_space, HodgeStarType hodge_star, MetricType metric, PositionType position)
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 double submatrix_determinant(MatrixView matrix, RowIds const &row_ids, ColIds const &col_ids, std::array< double, N *N > &submatrix_alloc)
KOKKOS_FUNCTION unmanaged_matrix_view_t< Scalar, MemorySpace > matrix_view(Scalar *data, std::size_t rows, std::size_t cols)
KOKKOS_FUNCTION MatrixView::non_const_value_type determinant(MatrixView matrix)
constexpr std::size_t factorial(std::size_t k) noexcept
typename detail::ConvertTypeSeqTo< T, Seq >::type convert_type_seq_to_t
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
ddc::type_seq_element_t< 0, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_1
ddc::type_seq_element_t< 1, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_2
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::Lower< T >::type lower_t
typename detail::NaturalDomainType< Index >::type natural_domain_t
detail::TensorAccessorForDomain< Dom >::type tensor_accessor_for_domain_t
The top-level namespace of SimiLie.
static KOKKOS_FUNCTION double value(MetricType metric, BatchElem elem, auto natural_elem)
static KOKKOS_FUNCTION void run(HodgeTensorType hodge_tensor, FormTensorType form_tensor, MetricType metric, BatchElem elem)
static KOKKOS_FUNCTION double value(MetricType metric, PositionType position, BatchElem elem, auto natural_elem)
static KOKKOS_FUNCTION void run(HodgeTensorType hodge_tensor, FormTensorType form_tensor, MetricType metric, PositionType position, BatchElem elem)
static KOKKOS_FUNCTION void run(ReconstructedTensorType reconstructed_tensor, CochainTensorType cochain_tensor, PositionType position, BatchElem elem)
static KOKKOS_FUNCTION void run(ReductionTensorType reduced_tensor, FormTensorType form_tensor, PositionType position, BatchElem elem)