Gyselalib++
bernstein.hpp
1 #pragma once
2 #include <ddc/ddc.hpp>
3 
4 #include <sll/mapping/barycentric_coordinates.hpp>
5 #include <sll/math_tools.hpp>
6 #include <sll/view.hpp>
7 
8 template <
9  class Tag1,
10  class Tag2,
11  class Corner1Tag,
12  class Corner2Tag,
13  class Corner3Tag,
14  std::size_t D>
16 {
17 public:
19 
20  static constexpr std::size_t rank()
21  {
22  return 2;
23  }
24 
25  static constexpr std::size_t degree() noexcept
26  {
27  return D;
28  }
29 
30  static constexpr std::size_t nbasis()
31  {
32  return (D + 1) * (D + 2) / 2;
33  }
34 
35  template <class DDim, class MemorySpace>
36  class Impl
37  {
38  template <class ODDim, class OMemorySpace>
39  friend class Impl;
40 
41  private:
43  m_coord_changer;
44 
45  public:
47 
48  using discrete_element_type = ddc::DiscreteElement<DDim>;
49 
50  using discrete_domain_type = ddc::DiscreteDomain<DDim>;
51 
52  using discrete_vector_type = ddc::DiscreteVector<DDim>;
53 
55  Tag1,
56  Tag2,
57  Corner1Tag,
58  Corner2Tag,
59  Corner3Tag> const& coord_changer)
60  : m_coord_changer(coord_changer)
61  {
62  }
63 
64  template <class OriginMemorySpace>
65  explicit Impl(Impl<DDim, OriginMemorySpace> const& impl)
66  : m_coord_changer(impl.m_coord_changer)
67  {
68  }
69 
70  Impl(Impl const& x) = default;
71 
72  Impl(Impl&& x) = default;
73 
74  ~Impl() = default;
75 
76  Impl& operator=(Impl const& x) = default;
77 
78  Impl& operator=(Impl&& x) = default;
79 
80  void eval_basis(
81  ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>> values,
82  ddc::Coordinate<Tag1, Tag2> const& x) const;
83  };
84 };
85 
86 template <
87  class Tag1,
88  class Tag2,
89  class Corner1Tag,
90  class Corner2Tag,
91  class Corner3Tag,
92  std::size_t D>
93 template <class DDim, class MemorySpace>
96  ddc::ChunkSpan<double, ddc::DiscreteDomain<DDim>> values,
97  ddc::Coordinate<Tag1, Tag2> const& x) const
98 {
99  const ddc::Coordinate<Corner1Tag, Corner2Tag, Corner3Tag> bary_coords = m_coord_changer(x);
100  const double l1 = ddc::get<Corner1Tag>(bary_coords);
101  const double l2 = ddc::get<Corner2Tag>(bary_coords);
102  const double l3 = ddc::get<Corner3Tag>(bary_coords);
103  assert(values.size() == nbasis());
104 
105  ddc::DiscreteElement<DDim> idx(0);
106  for (std::size_t i(0); i < D + 1; ++i) {
107  for (std::size_t j(0); j < D + 1 - i; ++j, ++idx) {
108  const int k = D - i - j;
109  const double multinomial_coefficient
110  = factorial(D) / (factorial(i) * factorial(j) * factorial(k));
111  values(idx) = multinomial_coefficient * ipow(l1, i) * ipow(l2, j) * ipow(l3, k);
112  }
113  }
114 }
Definition: bernstein.hpp:37
Definition: bernstein.hpp:16