8#include <similie/misc/are_all_same.hpp>
9#include <similie/misc/domain_contains.hpp>
10#include <similie/misc/filled_struct.hpp>
11#include <similie/misc/portable_stl.hpp>
12#include <similie/misc/specialization.hpp>
13#include <similie/misc/type_seq_conversion.hpp>
14#include <similie/tensor/antisymmetric_tensor.hpp>
15#include <similie/tensor/dummy_index.hpp>
16#include <similie/tensor/tensor_impl.hpp>
18#include <Kokkos_StdAlgorithms.hpp>
21#include "cosimplex.hpp"
37 class LayoutStridedPolicy1,
38 class LayoutStridedPolicy2,
43 LayoutStridedPolicy2>>
45 using type = Cosimplex<
Simplex<K + 1, Tag...>, ElementType>;
50template <misc::Specialization<Cochain> CochainType>
51using coboundary_t =
typename detail::CoboundaryType<CochainType>::type;
55template <
class TagToAddToCochain,
class CochainTag>
56struct CoboundaryIndex;
58template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorNatIndex CochainTag>
59 requires(CochainTag::rank() == 0)
60struct CoboundaryIndex<TagToAddToCochain, CochainTag>
62 using type = TagToAddToCochain;
65template <tensor::TensorNatIndex TagToAddToCochain, tensor::TensorNatIndex CochainTag>
66 requires(CochainTag::rank() == 1)
67struct CoboundaryIndex<TagToAddToCochain, CochainTag>
73struct CoboundaryIndex<TagToAddToCochain, tensor::TensorAntisymmetricIndex<Tag...>>
80template <
class TagToAddToCochain,
class CochainTag>
89struct CoboundaryTensorType;
98struct CoboundaryTensorType<
101 tensor::Tensor<ElementType, ddc::DiscreteDomain<DDim...>, SupportType, MemorySpace>>
103 static_assert(ddc::type_seq_contains_v<
104 ddc::detail::TypeSeq<CochainIndex>,
105 ddc::detail::TypeSeq<DDim...>>);
108 ddc::replace_dim_of_t<
109 ddc::DiscreteDomain<DDim...>,
123 typename detail::CoboundaryTensorType<TagToAddToCochain, CochainTag, TensorType>::type;
127template <misc::Specialization<Chain> ChainType>
128struct ComputeSimplex;
130template <std::size_t K,
class... Tag,
class LayoutStridedPolicy,
class ExecSpace>
131struct ComputeSimplex<
Chain<
Simplex<K, Tag...>, LayoutStridedPolicy, ExecSpace>>
133 KOKKOS_FUNCTION
static Simplex<K + 1, Tag...> run(
136 ddc::DiscreteVector<Tag...> vect {
137 0 * ddc::type_seq_rank_v<Tag, ddc::detail::TypeSeq<Tag...>>...};
138 for (
auto i = chain.begin(); i < chain.end(); ++i) {
139 vect = ddc::DiscreteVector<Tag...> {
140 (
static_cast<bool>(vect.template get<Tag>())
141 ||
static_cast<bool>((*i).discrete_vector().
template get<Tag>()))...};
144 std::integral_constant<std::size_t, K + 1> {},
145 chain[0].discrete_element(),
152template <misc::Specialization<Cochain> CochainType>
157 assert(cochain.size() == 2 * (cochain.dimension() + 1)
158 &&
"only cochain over the boundary of a single simplex is supported");
166 detail::ComputeSimplex<typename CochainType::chain_type>::run(cochain.chain()),
167 cochain.integrate());
172template <tensor::TensorNatIndex Index,
class Dom>
173struct NonSpectatorDimension;
176struct NonSpectatorDimension<Index, ddc::DiscreteDomain<DDim...>>
178 using type = ddc::cartesian_prod_t<std::conditional_t<
179 ddc::type_seq_contains_v<
180 ddc::detail::TypeSeq<typename DDim::continuous_dimension_type>,
181 typename Index::type_seq_dimensions>,
182 ddc::DiscreteDomain<DDim>,
183 ddc::DiscreteDomain<>>...>;
186struct CoboundaryDummyIndex
193 tensor::TensorNatIndex TagToAddToCochain,
194 tensor::TensorIndex CochainTag,
195 misc::Specialization<tensor::Tensor> TensorType,
198 ExecSpace
const& exec_space,
202 ddc::DiscreteDomain batch_dom
203 = ddc::remove_dims_of<coboundary_index_t<TagToAddToCochain, CochainTag>>(
204 coboundary_tensor.domain());
207 ddc::Chunk simplex_boundary_alloc(
208 ddc::cartesian_prod_t<
209 ddc::remove_dims_of_t<
213 TensorType>::discrete_domain_type,
215 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>>(
217 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>(
218 ddc::DiscreteElement<detail::CoboundaryDummyIndex>(0),
219 ddc::DiscreteVector<detail::CoboundaryDummyIndex>(
220 2 * (CochainTag::rank() + 1)))),
221 ddc::KokkosAllocator<
224 ddc::remove_dims_of_t<
228 TensorType>::discrete_domain_type,
230 typename ExecSpace::memory_space>());
231 ddc::ChunkSpan simplex_boundary(simplex_boundary_alloc);
234 ddc::Chunk boundary_values_alloc(
235 ddc::cartesian_prod_t<
236 ddc::remove_dims_of_t<
240 TensorType>::discrete_domain_type,
242 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>>(
244 ddc::DiscreteDomain<detail::CoboundaryDummyIndex>(
245 ddc::DiscreteElement<detail::CoboundaryDummyIndex>(0),
246 ddc::DiscreteVector<detail::CoboundaryDummyIndex>(
247 2 * (CochainTag::rank() + 1)))),
248 ddc::KokkosAllocator<double, typename ExecSpace::memory_space>());
249 ddc::ChunkSpan boundary_values(boundary_values_alloc);
253 CochainTag::rank() + 1,
254 typename detail::NonSpectatorDimension<
256 typename TensorType::non_indices_domain_t>::type>(exec_space);
261 typename detail::NonSpectatorDimension<
263 typename TensorType::non_indices_domain_t>::type>(exec_space);
266 ddc::parallel_for_each(
269 KOKKOS_LAMBDA(
typename decltype(batch_dom)::discrete_element_type elem) {
271 auto cochain =
Cochain(chain, coboundary_tensor[elem]);
272 for (
auto i = cochain.begin(); i < cochain.end(); ++i) {
275 std::integral_constant<std::size_t, CochainTag::rank() + 1> {},
277 (*i).discrete_vector());
280 =
boundary(simplex_boundary[elem].allocation_kokkos_view(), simplex);
282 for (
auto j = boundary_chain.
begin(); j < boundary_chain.
end(); ++j) {
284 boundary_values[elem].allocation_kokkos_view()(
285 Kokkos::Experimental::distance(boundary_chain.
begin(), j))
289 (*j).discrete_element())
290 ? (*j).discrete_element()
292 ddc::DiscreteElement<CochainTag>(
293 Kokkos::Experimental::distance(
296 find(lower_chain.begin(),
298 (*j).discrete_vector()))));
303 boundary_values[elem].allocation_kokkos_view());
308 ddc::DiscreteElement<
310 Kokkos::Experimental::distance(cochain.begin(), i)))
315 return coboundary_tensor;
324 ExecSpace
const& exec_space,
331 TensorType>(exec_space, coboundary_tensor, tensor);
KOKKOS_FUNCTION auto end()
KOKKOS_FUNCTION auto begin()
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)
KOKKOS_FUNCTION Chain< boundary_t< SimplexType >, typename AllocationType::array_layout, typename AllocationType::memory_space > boundary(AllocationType allocation, SimplexType simplex)
detail::SimplexForDomain< K, Dom >::type simplex_for_domain_t
typename detail::CoboundaryIndex< TagToAddToCochain, CochainTag >::type coboundary_index_t
typename detail::CoboundaryType< CochainType >::type coboundary_t
KOKKOS_FUNCTION bool domain_contains(ddc::DiscreteDomain< DDim... > dom, ddc::DiscreteElement< ODDim... > elem)
Tensor(ddc::Chunk< ElementType, SupportType, Allocator >) -> Tensor< ElementType, SupportType, Kokkos::layout_right, typename Allocator::memory_space >
The top-level namespace of SimiLie.