SimiLie
Loading...
Searching...
No Matches
volume.hpp
1// SPDX-FileCopyrightText: 2026 Baptiste Legouix
2// SPDX-License-Identifier: MIT
3
4#pragma once
5
6#include <array>
7
8#include <ddc/ddc.hpp>
9
10#include <similie/misc/binomial_coefficient.hpp>
11#include <similie/misc/clamp_to_domain.hpp>
12#include <similie/misc/domain_contains.hpp>
13#include <similie/misc/factorial.hpp>
14#include <similie/misc/small_matrix.hpp>
15#include <similie/tensor/metric.hpp>
16
17namespace sil {
18
19namespace exterior {
20
26
27namespace detail {
28template <std::size_t N, std::size_t K>
29KOKKOS_FUNCTION std::array<std::size_t, N - K> complement(std::array<std::size_t, K> const& ids)
30{
31 std::array<std::size_t, N - K> complement_ids {};
32 std::size_t complement_id = 0;
33 for (std::size_t i = 0; i < N; ++i) {
34 bool found = false;
35 for (std::size_t id : ids) {
36 found = found || id == i;
37 }
38 if (!found) {
39 complement_ids[complement_id++] = i;
40 }
41 }
42 return complement_ids;
43}
44
45template <CellComplex Complex, std::size_t N>
46KOKKOS_FUNCTION double complex_volume_factor(std::size_t const simplex_dim)
47{
48 if constexpr (Complex == CellComplex::Primal || Complex == CellComplex::CircumcentricDual) {
49 return 1.;
50 } else {
51 return 1. / static_cast<double>(misc::binomial_coefficient(N, simplex_dim));
52 }
53}
54
55template <class PositionIndex, class PositionType, class BatchElem>
56KOKKOS_FUNCTION std::array<double, PositionIndex::size()> edge_vector(
57 PositionType position,
58 BatchElem elem,
59 std::size_t const dim_id)
60{
61 std::array<double, PositionIndex::size()> vector {};
62 BatchElem forward = elem;
63 BatchElem backward = elem;
64 ddc::detail::array(forward)[dim_id] += 1;
65 ddc::detail::array(backward)[dim_id] -= 1;
66
67 bool const has_forward = misc::domain_contains(position.non_indices_domain(), forward);
68 bool const has_backward = misc::domain_contains(position.non_indices_domain(), backward);
69
70 for (std::size_t comp = 0; comp < PositionIndex::size(); ++comp) {
71 ddc::DiscreteElement<PositionIndex> const component(comp);
72 double const center = position.get(position.access_element(elem, component));
73 if (has_forward) {
74 vector[comp] = position.get(position.access_element(forward, component)) - center;
75 } else if (has_backward) {
76 vector[comp] = center - position.get(position.access_element(backward, component));
77 } else {
78 vector[comp] = 0.;
79 }
80 }
81 return vector;
82}
83
84template <std::size_t N>
85KOKKOS_FUNCTION double dot(
86 std::array<double, N> const& lhs,
87 std::array<double, N> const& rhs,
88 std::array<double, N * N> const& local_metric)
89{
90 double result = 0.;
91 for (std::size_t i = 0; i < N; ++i) {
92 for (std::size_t j = 0; j < N; ++j) {
93 result += lhs[i] * local_metric[i * N + j] * rhs[j];
94 }
95 }
96 return result;
97}
98
99} // namespace detail
100
101template <CellComplex Complex, std::size_t N, class MetricType, class PositionType, class BatchElem>
103{
104 template <std::size_t K>
105 KOKKOS_FUNCTION static double run(
106 MetricType metric,
107 PositionType position,
108 BatchElem elem,
109 std::array<std::size_t, K> const& ids)
110 {
111 if constexpr (K == 0) {
112 return 1.;
113 } else {
114 using PositionIndex = ddc::type_seq_element_t<
115 0,
116 ddc::to_type_seq_t<typename PositionType::indices_domain_t>>;
117 using MetricIndex = ddc::type_seq_element_t<
118 0,
119 ddc::to_type_seq_t<typename MetricType::indices_domain_t>>;
120 using MetricIndex1 = tensor::metric_index_1<MetricIndex>;
121 using MetricIndex2 = tensor::metric_index_2<MetricIndex>;
122
123 std::array<double, N * N> local_metric {};
124 for (std::size_t i = 0; i < N; ++i) {
125 for (std::size_t j = 0; j < N; ++j) {
126 local_metric[i * N + j] = metric.get(metric.access_element(
127 elem,
128 ddc::DiscreteElement<MetricIndex1, MetricIndex2>(i, j)));
129 }
130 }
131
132 std::array<std::array<double, N>, K> edges {};
133 for (std::size_t i = 0; i < K; ++i) {
134 edges[i] = detail::edge_vector<PositionIndex>(position, elem, ids[i]);
135 }
136
137 std::array<double, K * K> gram_matrix {};
138 for (std::size_t i = 0; i < K; ++i) {
139 for (std::size_t j = i; j < K; ++j) {
140 double const value = detail::dot(edges[i], edges[j], local_metric);
141 gram_matrix[i * K + j] = value;
142 gram_matrix[j * K + i] = value;
143 }
144 }
145
146 return Kokkos::sqrt(Kokkos::abs([&]() {
147 std::array<double, K * K> determinant_alloc = gram_matrix;
148 auto determinant_view = misc::math::matrix_view<
149 double,
150 typename MetricType::memory_space>(determinant_alloc.data(), K, K);
151 return misc::math::determinant(determinant_view);
152 }()));
153 }
154 }
155};
156
157template <CellComplex Complex, std::size_t N, class MetricType, class PositionType, class BatchElem>
159{
160 template <std::size_t K>
161 KOKKOS_FUNCTION static double run(
162 MetricType metric,
163 PositionType position,
164 BatchElem elem,
165 std::array<std::size_t, K> const& ids)
166 {
167 static_assert(
168 Complex != CellComplex::Primal,
169 "DualSimplexVolume must use a dual cell complex.");
171 N - K>(metric, position, elem, detail::complement<N>(ids));
172 }
173};
174
175} // namespace exterior
176
177} // namespace sil
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)
KOKKOS_FUNCTION bool domain_contains(ddc::DiscreteDomain< DDim... > dom, ddc::DiscreteElement< ODDim... > elem)
constexpr std::size_t binomial_coefficient(std::size_t n, std::size_t k) noexcept
ddc::type_seq_element_t< 0, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_1
Definition metric.hpp:33
ddc::type_seq_element_t< 1, ddc::to_type_seq_t< typename MetricIndex::subindices_domain_t > > metric_index_2
Definition metric.hpp:41
The top-level namespace of SimiLie.
Definition csr.hpp:15
static KOKKOS_FUNCTION double run(MetricType metric, PositionType position, BatchElem elem, std::array< std::size_t, K > const &ids)
Definition volume.hpp:161
static KOKKOS_FUNCTION double run(MetricType metric, PositionType position, BatchElem elem, std::array< std::size_t, K > const &ids)
Definition volume.hpp:105