12#include <similie/exterior/hodge_star.hpp>
13#include <similie/misc/domain_contains.hpp>
14#include <similie/misc/macros.hpp>
15#include <similie/misc/specialization.hpp>
16#include <similie/tensor/character.hpp>
17#include <similie/tensor/tensor_impl.hpp>
19#include <Kokkos_StdAlgorithms.hpp>
21#include "coboundary.hpp"
23#include "cosimplex.hpp"
33struct CodifferentialType;
39 class LayoutStridedPolicy1,
40 class LayoutStridedPolicy2,
42struct CodifferentialType<
45 LayoutStridedPolicy2>>
47 using type = Cosimplex<
Simplex<K - 1, Tag...>, ElementType>;
52template <misc::Specialization<Cochain> CochainType>
57template <
class TagToRemoveFromCochain,
class CochainTag>
58struct CodifferentialIndex;
60template <tensor::TensorNatIndex TagToRemoveFromCochain, tensor::TensorNatIndex CochainTag>
61 requires(CochainTag::rank() == 1 && std::is_same_v<TagToRemoveFromCochain, CochainTag>)
62struct CodifferentialIndex<TagToRemoveFromCochain, CochainTag>
67template <tensor::TensorNatIndex TagToRemoveFromCochain, tensor::TensorNatIndex Tag>
68struct CodifferentialIndex<
69 TagToRemoveFromCochain,
70 tensor::TensorAntisymmetricIndex<TagToRemoveFromCochain, Tag>>
76 requires(
sizeof...(Tag) > 1)
77struct CodifferentialIndex<
78 TagToRemoveFromCochain,
86template <
class TagToRemoveFromCochain,
class CochainTag>
88 typename detail::CodifferentialIndex<TagToRemoveFromCochain, CochainTag>::type;
96struct CodifferentialTensorType;
105 requires(ddc::type_seq_contains_v<
106 ddc::detail::TypeSeq<CochainIndex>,
107 ddc::detail::TypeSeq<DDim...>>)
108struct CodifferentialTensorType<
109 TagToRemoveFromCochain,
111 tensor::Tensor<ElementType, ddc::DiscreteDomain<DDim...>, SupportType, MemorySpace>>
115 ddc::replace_dim_of_t<
116 ddc::DiscreteDomain<DDim...>,
130 CodifferentialTensorType<TagToRemoveFromCochain, CochainTag, TensorType>::type;
134template <std::
size_t I,
class T>
139template <
class Ids,
class T>
140struct CodifferentialHodgeOutputIndexSeq_;
142template <std::size_t... Id,
class T>
143struct CodifferentialHodgeOutputIndexSeq_<std::index_sequence<Id...>, T>
145 using type = ddc::detail::TypeSeq<tensor::Covariant<CodifferentialHodgeOutputIndex<Id, T>>...>;
148template <std::
size_t EndId,
class T>
149struct CodifferentialHodgeOutputIndexSeq;
151template <std::
size_t EndId,
class T>
153struct CodifferentialHodgeOutputIndexSeq<EndId, T>
155 using type = ddc::detail::TypeSeq<>;
158template <std::
size_t EndId,
class T>
160struct CodifferentialHodgeOutputIndexSeq<EndId, T>
163 typename CodifferentialHodgeOutputIndexSeq_<std::make_index_sequence<EndId>, T>::type;
168template <std::
size_t EndId,
class T>
170 typename detail::CodifferentialHodgeOutputIndexSeq<EndId, T>::type;
172template <
class... Args>
184 TagToRemoveFromCochain,
190 template <
class ChainType,
class LowerChainType,
class NaturalElem>
194 PositionType position,
196 LowerChainType lower_chain,
197 typename TensorType::non_indices_domain_t::discrete_element_type elem,
198 NaturalElem natural_elem)
200 auto stencil = detail::make_stencil<typename TensorType::memory_space, CochainTag>(
201 detail::decrement_all(
202 typename TensorType::non_indices_domain_t::discrete_element_type(elem)));
203 ddc::device_for_each(stencil.domain(), [&](
auto stencil_elem) {
205 = detail::make_stencil<typename TensorType::memory_space, CochainTag>(
206 stencil.non_indices_domain().front());
207 basis_stencil.mem(stencil_elem) = 1.0;
209 [[maybe_unused]] tensor::TensorAccessor<
210 codifferential_index_t<TagToRemoveFromCochain, CochainTag>>
211 codifferential_accessor;
214 codifferential_index_t<TagToRemoveFromCochain, CochainTag>::access_size()>
215 codifferential_alloc {};
219 Kokkos::layout_right,
220 typename TensorType::memory_space>
222 codifferential_alloc.data(),
223 codifferential_accessor.domain());
226 run(codifferential_tensor, basis_stencil, metric, position, chain, lower_chain, elem);
227 stencil.mem(stencil_elem) = codifferential_tensor(natural_elem);
232 KOKKOS_FUNCTION
static void run(
233 auto codifferential_tensor,
236 PositionType position,
239 typename TensorType::non_indices_domain_t::discrete_element_type elem)
241 using source_hodge_input_indices
244 TagToRemoveFromCochain::size() - CochainTag::rank(),
245 TagToRemoveFromCochain>;
246 using target_hodge_input_indices = ddc::type_seq_merge_t<
247 ddc::detail::TypeSeq<TagToRemoveFromCochain>,
248 source_hodge_output_indices>;
251 source_hodge_output_indices>;
252 using dual_codifferential_index = misc::
253 convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, target_hodge_input_indices>;
255 dual_codifferential_accessor;
257 std::array<double, dual_codifferential_index::access_size()> dual_codifferential_alloc {};
260 ddc::DiscreteDomain<dual_codifferential_index>,
261 Kokkos::layout_right,
262 typename TensorType::memory_space>
263 dual_codifferential_span(
264 dual_codifferential_alloc.data(),
265 dual_codifferential_accessor.
domain());
269 auto dual_evaluator = [&](
auto sampled_elem,
auto dual_elem) {
274 std::array<double, dual_tensor_index::access_size()> dual_tensor_alloc {};
277 ddc::DiscreteDomain<dual_tensor_index>,
278 Kokkos::layout_right,
279 typename TensorType::memory_space>
280 dual_tensor_span(dual_tensor_alloc.data(), dual_tensor_accessor.
domain());
285 source_hodge_input_indices,
286 source_hodge_output_indices,
289 typename TensorType::non_indices_domain_t::discrete_element_type>::
290 run(dual_tensor, tensor[sampled_elem], metric, position, sampled_elem);
291 return dual_tensor.mem(dual_elem);
295 run(dual_codifferential, dual_evaluator, chain, lower_chain, elem);
300 ddc::type_seq_remove_t<
302 ddc::detail::TypeSeq<TagToRemoveFromCochain>>,
305 typename TensorType::non_indices_domain_t::discrete_element_type>::
306 run(codifferential_tensor, dual_codifferential, metric, position, elem);
307 if constexpr ((TagToRemoveFromCochain::size() * (CochainTag::rank() + 1) + 1) % 2 == 1) {
308 codifferential_tensor *= -1;
323 using CodifferentialTensorType
325 using MemorySpace =
typename TensorType::memory_space;
326 using AllocatorType = ddc::KokkosAllocator<double, MemorySpace>;
327 using SourceHodgeInputIndices
330 TagToRemoveFromCochain::size() - CochainTag::rank(),
331 TagToRemoveFromCochain>;
332 using TargetHodgeInputIndices = ddc::type_seq_merge_t<
333 ddc::detail::TypeSeq<TagToRemoveFromCochain>,
334 SourceHodgeOutputIndices>;
335 using TargetHodgeOutputIndices = ddc::type_seq_remove_t<
337 ddc::detail::TypeSeq<TagToRemoveFromCochain>>;
338 using DualTensorIndex = misc::
339 convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, SourceHodgeOutputIndices>;
340 using DualCodifferentialIndex = misc::
341 convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, TargetHodgeInputIndices>;
342 using NonSpectatorDimensions =
typename detail::NonSpectatorDimension<
343 TagToRemoveFromCochain,
344 typename TensorType::non_indices_domain_t>::type;
345 using ChainType =
decltype(tangent_basis<DualTensorIndex::rank() + 1, NonSpectatorDimensions>(
346 std::declval<ExecSpace const&>()));
347 using LowerChainType =
decltype(tangent_basis<DualTensorIndex::rank(), NonSpectatorDimensions>(
348 std::declval<ExecSpace const&>()));
350 using HodgeStarDomainType = ddc::cartesian_prod_t<
351 typename MetricType::non_indices_domain_t,
353 using DualHodgeStarDomainType = ddc::cartesian_prod_t<
354 typename MetricType::non_indices_domain_t,
357 TargetHodgeOutputIndices>>;
358 using DualTensorDomainType = ddc::cartesian_prod_t<
359 typename TensorType::non_indices_domain_t,
360 ddc::DiscreteDomain<DualTensorIndex>>;
362 using HodgeStarAllocType = ddc::Chunk<double, HodgeStarDomainType, AllocatorType>;
363 using DualHodgeStarAllocType = ddc::Chunk<double, DualHodgeStarDomainType, AllocatorType>;
364 using DualTensorAllocType = ddc::Chunk<double, DualTensorDomainType, AllocatorType>;
366 using HodgeStarTensorType
367 = tensor::Tensor<double, HodgeStarDomainType, Kokkos::layout_right, MemorySpace>;
368 using DualHodgeStarTensorType
369 = tensor::Tensor<double, DualHodgeStarDomainType, Kokkos::layout_right, MemorySpace>;
371 = tensor::Tensor<double, DualTensorDomainType, Kokkos::layout_right, MemorySpace>;
373 ExecSpace m_exec_space;
374 std::optional<HodgeStarAllocType> m_hodge_star_alloc;
375 std::optional<DualHodgeStarAllocType> m_dual_hodge_star_alloc;
376 std::optional<DualTensorAllocType> m_dual_tensor_alloc;
377 std::optional<HodgeStarTensorType> m_hodge_star;
378 std::optional<DualHodgeStarTensorType> m_dual_hodge_star;
379 std::optional<DualTensorType> m_dual_tensor_buffer;
381 LowerChainType m_lower_chain;
385 ExecSpace
const& exec_space,
386 HodgeStarTensorType&& hodge_star,
387 DualHodgeStarTensorType&& dual_hodge_star,
388 DualTensorType&& dual_tensor_buffer)
389 : m_exec_space(exec_space)
390 , m_hodge_star(std::move(hodge_star))
391 , m_dual_hodge_star(std::move(dual_hodge_star))
392 , m_dual_tensor_buffer(std::move(dual_tensor_buffer))
393 , m_chain(
tangent_basis<DualTensorIndex::rank() + 1, NonSpectatorDimensions>(exec_space))
394 , m_lower_chain(
tangent_basis<DualTensorIndex::rank(), NonSpectatorDimensions>(exec_space))
399 ExecSpace
const& exec_space,
402 PositionType position)
403 : m_exec_space(exec_space)
404 , m_chain(
tangent_basis<DualTensorIndex::rank() + 1, NonSpectatorDimensions>(exec_space))
405 , m_lower_chain(
tangent_basis<DualTensorIndex::rank(), NonSpectatorDimensions>(exec_space))
412 TargetHodgeOutputIndices>> dual_hodge_star_accessor;
415 m_hodge_star_alloc.emplace(
416 HodgeStarDomainType(metric.non_indices_domain(), hodge_star_accessor.domain()),
418 m_dual_hodge_star_alloc.emplace(
419 DualHodgeStarDomainType(
420 metric.non_indices_domain(),
421 dual_hodge_star_accessor.domain()),
423 m_dual_tensor_alloc.emplace(
424 DualTensorDomainType(tensor.non_indices_domain(), dual_tensor_accessor.
domain()),
427 m_hodge_star.emplace(*m_hodge_star_alloc);
428 m_dual_hodge_star.emplace(*m_dual_hodge_star_alloc);
429 m_dual_tensor_buffer.emplace(*m_dual_tensor_alloc);
432 SourceHodgeInputIndices,
433 SourceHodgeOutputIndices>(exec_space, *m_hodge_star, metric, position);
436 TargetHodgeOutputIndices>(exec_space, *m_dual_hodge_star, metric, position);
439 CodifferentialTensorType run(CodifferentialTensorType codifferential_tensor, TensorType tensor)
442 auto exec_space = m_exec_space;
443 auto hodge_star = *m_hodge_star;
444 auto dual_hodge_star = *m_dual_hodge_star;
445 auto dual_tensor_buffer = *m_dual_tensor_buffer;
446 auto chain = m_chain;
447 auto lower_chain = m_lower_chain;
449 SIMILIE_DEBUG_LOG(
"similie_apply_first_hodge_star_for_codifferential");
450 ddc::parallel_for_each(
451 "similie_apply_first_hodge_star_for_codifferential",
453 dual_tensor_buffer.non_indices_domain(),
455 typename TensorType::non_indices_domain_t::discrete_element_type elem) {
457 tensor_prod(dual_tensor_buffer[elem], tensor[elem], hodge_star[elem]);
460 SIMILIE_DEBUG_LOG(
"similie_apply_second_hodge_star_for_codifferential");
461 ddc::parallel_for_each(
462 "similie_apply_second_hodge_star_for_codifferential",
464 codifferential_tensor.non_indices_domain(),
466 typename TensorType::non_indices_domain_t::discrete_element_type elem) {
468 dual_codifferential_accessor;
469 std::array<double, DualCodifferentialIndex::access_size()>
470 dual_codifferential_alloc {};
473 ddc::DiscreteDomain<DualCodifferentialIndex>,
474 Kokkos::layout_right,
475 typename TensorType::memory_space>
476 dual_codifferential_span(
477 dual_codifferential_alloc.data(),
478 dual_codifferential_accessor.
domain());
481 TransposedCoboundary<TagToRemoveFromCochain, DualTensorIndex>::run(
483 [&](
auto sampled_elem,
auto dual_elem) {
484 if (!misc::domain_contains(
485 dual_tensor_buffer.non_indices_domain(),
489 return dual_tensor_buffer.mem(sampled_elem, dual_elem);
496 codifferential_tensor[elem],
498 dual_hodge_star[elem]);
500 (TagToRemoveFromCochain::size() * (CochainTag::rank() + 1) + 1) % 2
502 codifferential_tensor[elem] *= -1;
506 return codifferential_tensor;
511 tensor::TensorIndex MetricIndex,
512 tensor::TensorNatIndex TagToRemoveFromCochain,
513 tensor::TensorIndex CochainTag,
515 misc::Specialization<tensor::Tensor> TensorType,
516 misc::Specialization<tensor::Tensor> MetricType,
517 misc::Specialization<tensor::Tensor> PositionType>
520 TagToRemoveFromCochain,
527 ExecSpace
const& exec_space,
530 PositionType position)
534 TagToRemoveFromCochain,
539 ExecSpace>(exec_space, tensor, metric, position);
552 ExecSpace
const& exec_space,
554 codifferential_tensor,
556 HodgeStarType hodge_star,
557 DualHodgeStarType dual_hodge_star,
558 DualTensorType dual_tensor_buffer)
562 TagToRemoveFromCochain::size() - CochainTag::rank(),
563 TagToRemoveFromCochain>;
564 using dual_tensor_index = misc::
565 convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, source_hodge_output_indices>;
566 using target_hodge_input_indices = ddc::type_seq_merge_t<
567 ddc::detail::TypeSeq<TagToRemoveFromCochain>,
568 source_hodge_output_indices>;
569 using dual_codifferential_index = misc::
570 convert_type_seq_to_t<tensor::TensorAntisymmetricIndex, target_hodge_input_indices>;
571 using non_spectator_dimensions =
typename detail::NonSpectatorDimension<
572 TagToRemoveFromCochain,
573 typename TensorType::non_indices_domain_t>::type;
574 auto chain = tangent_basis<dual_tensor_index::rank() + 1, non_spectator_dimensions>(exec_space);
576 = tangent_basis<dual_tensor_index::rank(), non_spectator_dimensions>(exec_space);
578 SIMILIE_DEBUG_LOG(
"similie_apply_first_hodge_star_for_codifferential");
579 ddc::parallel_for_each(
580 "similie_apply_first_hodge_star_for_codifferential",
582 dual_tensor_buffer.non_indices_domain(),
583 KOKKOS_LAMBDA(
typename TensorType::non_indices_domain_t::discrete_element_type elem) {
587 SIMILIE_DEBUG_LOG(
"similie_apply_second_hodge_star_for_codifferential");
588 ddc::parallel_for_each(
589 "similie_apply_second_hodge_star_for_codifferential",
591 codifferential_tensor.non_indices_domain(),
592 KOKKOS_LAMBDA(
typename TensorType::non_indices_domain_t::discrete_element_type elem) {
594 dual_codifferential_accessor;
595 std::array<double, dual_codifferential_index::access_size()>
596 dual_codifferential_alloc {};
599 ddc::DiscreteDomain<dual_codifferential_index>,
600 Kokkos::layout_right,
601 typename TensorType::memory_space>
602 dual_codifferential_span(
603 dual_codifferential_alloc.data(),
604 dual_codifferential_accessor.
domain());
609 [&](
auto sampled_elem,
auto dual_elem) {
611 dual_tensor_buffer.non_indices_domain(),
615 return dual_tensor_buffer.mem(sampled_elem, dual_elem);
622 codifferential_tensor[elem],
624 dual_hodge_star[elem]);
626 (TagToRemoveFromCochain::size() * (CochainTag::rank() + 1) + 1) % 2 == 1) {
627 codifferential_tensor[elem] *= -1;
631 return codifferential_tensor;
643 ExecSpace
const& exec_space,
645 codifferential_tensor,
648 PositionType position)
653 TagToRemoveFromCochain,
654 CochainTag>(exec_space, tensor, metric, position)
655 .run(codifferential_tensor, tensor);
static constexpr discrete_domain_type domain()
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... >
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
KOKKOS_FUNCTION constexpr auto tangent_basis(Elem elem)
typename detail:: CodifferentialTensorType< TagToRemoveFromCochain, CochainTag, TensorType >::type codifferential_tensor_t
Chain(Head, Tail...) -> Chain< typename Head::value_type, typename Head::array_layout, typename Head::memory_space >
StagedCodifferential< MetricIndex, TagToRemoveFromCochain, CochainTag, TensorType, MetricType, PositionType, ExecSpace > make_staged_codifferential(ExecSpace const &exec_space, TensorType tensor, MetricType metric, PositionType position)
HodgeStarType fill_discrete_hodge_star(ExecSpace const &exec_space, HodgeStarType hodge_star, MetricType metric, PositionType position)
codifferential_tensor_t< TagToRemoveFromCochain, CochainTag, TensorType > codifferential(ExecSpace const &exec_space, codifferential_tensor_t< TagToRemoveFromCochain, CochainTag, TensorType > codifferential_tensor, TensorType tensor, HodgeStarType hodge_star, DualHodgeStarType dual_hodge_star, DualTensorType dual_tensor_buffer)
typename detail::CodifferentialIndex< TagToRemoveFromCochain, CochainTag >::type codifferential_index_t
typename detail::CodifferentialHodgeOutputIndexSeq< EndId, T >::type codifferential_hodge_output_indices_t
typename detail::CodifferentialType< CochainType >::type codifferential_t
KOKKOS_FUNCTION bool domain_contains(ddc::DiscreteDomain< DDim... > dom, ddc::DiscreteElement< ODDim... > elem)
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 >
detail::Upper< T >::type upper_t
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::Uncharacterize< Index >::type uncharacterize_t
detail::Lower< T >::type lower_t
bool constexpr is_covariant_v
detail::TensorAccessorForDomain< Dom >::type tensor_accessor_for_domain_t
The top-level namespace of SimiLie.
static KOKKOS_FUNCTION void run(auto codifferential_tensor, TensorType tensor, MetricType metric, PositionType position, auto chain, auto lower_chain, typename TensorType::non_indices_domain_t::discrete_element_type elem)
static KOKKOS_FUNCTION auto value(TensorType tensor, MetricType metric, PositionType position, ChainType chain, LowerChainType lower_chain, typename TensorType::non_indices_domain_t::discrete_element_type elem, NaturalElem natural_elem)