10#include <similie/misc/are_all_same.hpp>
11#include <similie/misc/clamp_to_domain.hpp>
12#include <similie/misc/domain_contains.hpp>
13#include <similie/misc/filled_struct.hpp>
14#include <similie/misc/macros.hpp>
15#include <similie/misc/portable_stl.hpp>
16#include <similie/misc/select_from_type_seq.hpp>
17#include <similie/misc/specialization.hpp>
18#include <similie/misc/type_seq_conversion.hpp>
19#include <similie/tensor/antisymmetric_tensor.hpp>
20#include <similie/tensor/dummy_index.hpp>
21#include <similie/tensor/tensor_impl.hpp>
23#include <Kokkos_StdAlgorithms.hpp>
26#include "cosimplex.hpp"
42 class LayoutStridedPolicy1,
43 class LayoutStridedPolicy2,
48 LayoutStridedPolicy2>>
50 using type = Cosimplex<
Simplex<K + 1, Tag...>, ElementType>;
55template <misc::Specialization<Cochain> CochainType>
56using coboundary_t =
typename detail::CoboundaryType<CochainType>::type;
60template <
class TagToAddToCochain,
class CochainTag>
61struct CoboundaryIndex;
63template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorNatIndex CochainTag>
64 requires(CochainTag::rank() == 0)
65struct CoboundaryIndex<TagToAddToCochain, CochainTag>
67 using type = TagToAddToCochain;
70template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorNatIndex CochainTag>
71 requires(CochainTag::rank() == 1)
72struct CoboundaryIndex<TagToAddToCochain, CochainTag>
78struct CoboundaryIndex<TagToAddToCochain, tensor::TensorAntisymmetricIndex<Tag...>>
85template <
class TagToAddToCochain,
class CochainTag>
94struct CoboundaryTensorType;
103struct CoboundaryTensorType<
106 tensor::Tensor<ElementType, ddc::DiscreteDomain<DDim...>, SupportType, MemorySpace>>
108 static_assert(ddc::type_seq_contains_v<
109 ddc::detail::TypeSeq<CochainIndex>,
110 ddc::detail::TypeSeq<DDim...>>);
113 ddc::replace_dim_of_t<
114 ddc::DiscreteDomain<DDim...>,
128 typename detail::CoboundaryTensorType<TagToAddToCochain, CochainTag, TensorType>::type;
132template <misc::Specialization<Chain> ChainType>
133struct ComputeSimplex;
135template <std::size_t K,
class... Tag,
class LayoutStridedPolicy,
class ExecSpace>
136struct ComputeSimplex<
Chain<
Simplex<K, Tag...>, LayoutStridedPolicy, ExecSpace>>
138 KOKKOS_FUNCTION
static Simplex<K + 1, Tag...> run(
141 ddc::DiscreteVector<Tag...> vect {
142 0 * ddc::type_seq_rank_v<Tag, ddc::detail::TypeSeq<Tag...>>...};
143 for (
auto i = chain.begin(); i < chain.end(); ++i) {
144 vect = ddc::DiscreteVector<Tag...> {
145 (
static_cast<bool>(vect.template get<Tag>())
146 ||
static_cast<bool>((*i).discrete_vector().
template get<Tag>()))...};
149 std::integral_constant<std::size_t, K + 1> {},
150 chain[0].discrete_element(),
157template <
class... Args>
160template <
class... Args>
163template <misc::Specialization<Cochain> CochainType>
170 assert(cochain.size() == 2 * (cochain.dimension() + 1)
171 &&
"only cochain over the boundary of a single simplex is supported");
179 detail::ComputeSimplex<typename CochainType::chain_type>::run(cochain.chain()),
180 cochain.integrate());
186template <tensor::TensorNatIndex Index,
class Dom>
187struct NonSpectatorDimension;
190struct NonSpectatorDimension<Index, ddc::DiscreteDomain<DDim...>>
192 using type = ddc::cartesian_prod_t<std::conditional_t<
193 ddc::type_seq_contains_v<
194 ddc::detail::TypeSeq<typename DDim::continuous_dimension_type>,
195 typename Index::type_seq_dimensions>,
196 ddc::DiscreteDomain<DDim>,
197 ddc::DiscreteDomain<>>...>;
200struct CoboundaryDummyIndex
206template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorIndex CochainTag>
210 class CoboundaryTensorType,
213 class LowerChainType,
215 KOKKOS_FUNCTION
static void run(
216 CoboundaryTensorType coboundary_tensor,
219 LowerChainType lower_chain,
222 constexpr std::size_t BOUNDARY_SIZE = 2 * (CochainTag::rank() + 1);
223 std::array<typename LowerChainType::simplex_type, BOUNDARY_SIZE> simplex_boundary_alloc {};
224 std::array<double, BOUNDARY_SIZE> boundary_values_alloc {};
225 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>
const boundary_domain(
226 ddc::DiscreteElement<detail::CoboundaryDummyIndex>(0),
227 ddc::DiscreteVector<detail::CoboundaryDummyIndex>(BOUNDARY_SIZE));
229 typename LowerChainType::simplex_type,
230 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>,
231 Kokkos::layout_right,
232 typename CoboundaryTensorType::memory_space>
233 simplex_boundary(simplex_boundary_alloc.data(), boundary_domain);
236 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>,
237 Kokkos::layout_right,
238 typename CoboundaryTensorType::memory_space>
239 boundary_values(boundary_values_alloc.data(), boundary_domain);
241 auto cochain =
Cochain(chain, coboundary_tensor);
242 for (
auto i = cochain.begin(); i < cochain.end(); ++i) {
243 typename ChainType::simplex_type
244 simplex(std::integral_constant<std::size_t, CochainTag::rank() + 1> {},
245 typename ChainType::simplex_type::discrete_element_type(elem),
246 (*i).discrete_vector());
247 auto boundary_chain =
boundary(simplex_boundary.allocation_kokkos_view(), simplex);
248 for (
auto j = boundary_chain.begin(); j < boundary_chain.end(); ++j) {
249 std::size_t
const boundary_id
250 = Kokkos::Experimental::distance(boundary_chain.begin(), j);
252 ddc::type_seq_size_v<ddc::type_seq_remove_t<
253 ddc::to_type_seq_t<Elem>,
254 ddc::to_type_seq_t<
typename LowerChainType::simplex_type::
255 discrete_element_type>>>
257 boundary_values(ddc::DiscreteElement<detail::CoboundaryDummyIndex>(boundary_id))
259 Elem((*j).discrete_element()),
260 ddc::DiscreteElement<CochainTag>(Kokkos::Experimental::distance(
263 find(lower_chain.begin(),
265 (*j).discrete_vector()))));
267 boundary_values(ddc::DiscreteElement<detail::CoboundaryDummyIndex>(boundary_id))
269 Elem((*j).discrete_element(),
271 ddc::to_type_seq_t<Elem>,
273 typename LowerChainType::simplex_type::
274 discrete_element_type>>>(elem)),
275 ddc::DiscreteElement<CochainTag>(Kokkos::Experimental::distance(
278 find(lower_chain.begin(),
280 (*j).discrete_vector()))));
283 Cochain cochain_boundary(boundary_chain, boundary_values.allocation_kokkos_view());
284 coboundary_tensor.mem(
286 Kokkos::Experimental::distance(cochain.begin(), i)))
292template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorIndex CochainTag>
296 class CoboundaryTensorType,
299 class LowerChainType,
301 KOKKOS_FUNCTION
static void run(
302 CoboundaryTensorType coboundary_tensor,
305 LowerChainType lower_chain,
308 constexpr std::size_t BOUNDARY_SIZE = 2 * (CochainTag::rank() + 1);
309 std::array<typename LowerChainType::simplex_type, BOUNDARY_SIZE> simplex_boundary_alloc {};
310 std::array<double, BOUNDARY_SIZE> boundary_values_alloc {};
311 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>
const boundary_domain(
312 ddc::DiscreteElement<detail::CoboundaryDummyIndex>(0),
313 ddc::DiscreteVector<detail::CoboundaryDummyIndex>(BOUNDARY_SIZE));
315 typename LowerChainType::simplex_type,
316 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>,
317 Kokkos::layout_right,
318 typename CoboundaryTensorType::memory_space>
319 simplex_boundary(simplex_boundary_alloc.data(), boundary_domain);
322 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>,
323 Kokkos::layout_right,
324 typename CoboundaryTensorType::memory_space>
325 boundary_values(boundary_values_alloc.data(), boundary_domain);
327 auto cochain =
Cochain(chain, coboundary_tensor);
328 for (
auto i = cochain.begin(); i < cochain.end(); ++i) {
329 typename ChainType::simplex_type
330 simplex(std::integral_constant<std::size_t, CochainTag::rank() + 1> {},
331 typename ChainType::simplex_type::discrete_element_type(elem),
332 (*i).discrete_vector());
333 auto boundary_chain =
boundary(simplex_boundary.allocation_kokkos_view(), simplex);
334 for (
auto j = boundary_chain.begin(); j < boundary_chain.end(); ++j) {
335 std::size_t
const boundary_id
336 = Kokkos::Experimental::distance(boundary_chain.begin(), j);
337 auto sampled_face_vector = (*j).discrete_vector();
338 auto sampled_face_elem = (*j).discrete_element();
339 if (boundary_id >= CochainTag::rank() + 1) {
340 auto simplex_vector = (*i).discrete_vector();
341 for (std::size_t dim_id = 0;
342 dim_id < ddc::type_seq_size_v<ddc::to_type_seq_t<
343 typename ChainType::simplex_type::discrete_element_type>>;
345 if (ddc::detail::array(simplex_vector)[dim_id] != 0
346 && ddc::detail::array(sampled_face_vector)[dim_id] == 0) {
347 ddc::detail::array(sampled_face_elem)[dim_id] -= 2;
353 ddc::type_seq_size_v<ddc::type_seq_remove_t<
354 ddc::to_type_seq_t<Elem>,
355 ddc::to_type_seq_t<
typename LowerChainType::simplex_type::
356 discrete_element_type>>>
358 boundary_values(ddc::DiscreteElement<detail::CoboundaryDummyIndex>(boundary_id))
360 Elem(sampled_face_elem),
361 ddc::DiscreteElement<CochainTag>(Kokkos::Experimental::distance(
364 find(lower_chain.begin(),
366 sampled_face_vector))));
368 boundary_values(ddc::DiscreteElement<detail::CoboundaryDummyIndex>(boundary_id))
370 Elem(sampled_face_elem,
372 ddc::to_type_seq_t<Elem>,
374 typename LowerChainType::simplex_type::
375 discrete_element_type>>>(elem)),
376 ddc::DiscreteElement<CochainTag>(Kokkos::Experimental::distance(
379 find(lower_chain.begin(),
381 sampled_face_vector))));
384 Cochain cochain_boundary(boundary_chain, boundary_values.allocation_kokkos_view());
385 coboundary_tensor.mem(
387 Kokkos::Experimental::distance(cochain.begin(), i)))
393template <misc::Specialization<Cochain> CochainType>
405 ExecSpace
const& exec_space,
409 ddc::DiscreteDomain batch_dom
410 = ddc::remove_dims_of<coboundary_index_t<TagToAddToCochain, CochainTag>>(
411 coboundary_tensor.domain());
414 CochainTag::rank() + 1,
415 typename detail::NonSpectatorDimension<
417 typename TensorType::non_indices_domain_t>::type>(exec_space);
420 typename detail::NonSpectatorDimension<
422 typename TensorType::non_indices_domain_t>::type>(exec_space);
424 SIMILIE_DEBUG_LOG(
"similie_compute_coboundary");
425 ddc::parallel_for_each(
426 "similie_compute_coboundary",
429 KOKKOS_LAMBDA(
typename decltype(batch_dom)::discrete_element_type elem) {
431 coboundary_tensor[elem],
433 [&](
auto sampled_elem,
auto cochain_elem) {
434 auto const clamped_elem =
misc::
436 return tensor.mem(clamped_elem, cochain_elem);
443 return coboundary_tensor;
452 ExecSpace
const& exec_space,
456 ddc::DiscreteDomain batch_dom
457 = ddc::remove_dims_of<coboundary_index_t<TagToAddToCochain, CochainTag>>(
458 coboundary_tensor.domain());
461 CochainTag::rank() + 1,
462 typename detail::NonSpectatorDimension<
464 typename TensorType::non_indices_domain_t>::type>(exec_space);
467 typename detail::NonSpectatorDimension<
469 typename TensorType::non_indices_domain_t>::type>(exec_space);
471 SIMILIE_DEBUG_LOG(
"similie_compute_transposed_coboundary");
472 ddc::parallel_for_each(
473 "similie_compute_transposed_coboundary",
476 KOKKOS_LAMBDA(
typename decltype(batch_dom)::discrete_element_type elem) {
478 coboundary_tensor[elem],
479 [&](
auto sampled_elem,
auto cochain_elem) {
483 return tensor.mem(sampled_elem, cochain_elem);
490 return coboundary_tensor;
499 ExecSpace
const& exec_space,
KOKKOS_FUNCTION element_type integrate() noexcept
constexpr auto tangent_basis(ExecSpace const &exec_space)
Cochain(ChainType, TensorType) -> Cochain< ChainType, typename TensorType::value_type, ddc::detail::mdspan_to_kokkos_layout_t< typename TensorType::layout_type > >
Simplex(ddc::DiscreteElement< Tag... >, ddc::DiscreteVector< T... >) -> Simplex< sizeof...(T), Tag... >
KOKKOS_FUNCTION coboundary_t< CochainType > coboundary(CochainType cochain)
Chain(Head, Tail...) -> Chain< typename Head::value_type, typename Head::array_layout, typename Head::memory_space >
typename detail::CoboundaryTensorType< TagToAddToCochain, CochainTag, TensorType >::type coboundary_tensor_t
coboundary_tensor_t< TagToAddToCochain, CochainTag, TensorType > deriv(ExecSpace const &exec_space, coboundary_tensor_t< TagToAddToCochain, CochainTag, TensorType > coboundary_tensor, TensorType tensor)
coboundary_tensor_t< TagToAddToCochain, CochainTag, TensorType > transposed_coboundary(ExecSpace const &exec_space, coboundary_tensor_t< TagToAddToCochain, CochainTag, TensorType > coboundary_tensor, TensorType tensor)
KOKKOS_FUNCTION Chain< boundary_t< SimplexType >, typename AllocationType::array_layout, typename AllocationType::memory_space > boundary(AllocationType allocation, SimplexType simplex)
typename detail::CoboundaryIndex< TagToAddToCochain, CochainTag >::type coboundary_index_t
typename detail::CoboundaryType< CochainType >::type coboundary_t
KOKKOS_FUNCTION Elem clamp_to_domain(BatchDomain const &batch_domain, Elem const &elem)
KOKKOS_FUNCTION bool domain_contains(ddc::DiscreteDomain< DDim... > dom, ddc::DiscreteElement< ODDim... > elem)
KOKKOS_FUNCTION auto select_from_type_seq(T t)
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
The top-level namespace of SimiLie.
static KOKKOS_FUNCTION coboundary_t< CochainType > run(CochainType cochain)
static KOKKOS_FUNCTION void run(CoboundaryTensorType coboundary_tensor, Evaluator evaluator, ChainType chain, LowerChainType lower_chain, Elem elem)
static KOKKOS_FUNCTION void run(CoboundaryTensorType coboundary_tensor, Evaluator evaluator, ChainType chain, LowerChainType lower_chain, Elem elem)