OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
MonomialBasis.hpp
1 //
2 // Created by tommaso on 20/03/19.
3 //
4 
5 #ifndef OPENFPM_PDATA_MONOMIALBASIS_H
6 #define OPENFPM_PDATA_MONOMIALBASIS_H
7 
8 #include <vector>
9 #include <Grid/grid_sm.hpp>
10 #include <Grid/iterators/grid_key_dx_iterator_sub_bc.hpp>
11 #include "Monomial.hpp"
12 
13 template<unsigned int dim>
15 {
16 private:
17  std::vector<Monomial<dim>> basis;
18 
19 public:
20  MonomialBasis(const std::vector<unsigned int> &degrees, unsigned int convergenceOrder);
21 
22  MonomialBasis(unsigned int degrees[dim], unsigned int convergenceOrder);
23 
24 // explicit MonomialBasis(Point<dim, unsigned int> degrees, unsigned int convergenceOrder);
25 
26  explicit MonomialBasis(const std::vector<Monomial<dim>> &basis) : basis(basis) {}
27 
28  MonomialBasis(const MonomialBasis &other);
29 
30  MonomialBasis &operator=(const MonomialBasis &other);
31 
32  unsigned int size() const;
33 
34  const Monomial<dim> &getElement(unsigned int i) const;
35 
36  Monomial<dim> &getElement(unsigned int i);
37 
38  const std::vector<Monomial<dim>> &getElements() const;
39 
40  MonomialBasis<dim> getDerivative(Point<dim, unsigned int> differentialOrder) const;
41 
42  bool operator==(const MonomialBasis &other) const;
43 
44  template<typename charT, typename traits>
45  friend std::basic_ostream<charT, traits> &
46  operator<<(std::basic_ostream<charT, traits> &lhs, MonomialBasis<dim> const &rhs)
47  {
48  lhs << "MonomialBasis: size=" << rhs.size() << ", elements={ ";
49  for (const auto &el : rhs.getElements())
50  {
51  lhs << "(" << el << ") ";
52  }
53  lhs << "}" << std::endl;
54  return lhs;
55  }
56 
57 private:
58  void generateBasis(std::vector<unsigned int> m, unsigned int r);
59 };
60 
62 
63 template<unsigned int dim>
64 MonomialBasis<dim>::MonomialBasis(const std::vector<unsigned int> &degrees, unsigned int convergenceOrder)
65 {
66  generateBasis(degrees, convergenceOrder);
67 }
68 
69 template<unsigned int dim>
70 MonomialBasis<dim>::MonomialBasis(unsigned int *degrees, unsigned int convergenceOrder)
71  : MonomialBasis(std::vector<unsigned int>(degrees, degrees + dim), convergenceOrder) {}
72 
73 template<unsigned int dim>
75 {
76  basis = other.basis; // Here it works because both std::vector and Monomial perform a deep copy.
77 }
78 
79 template<unsigned int dim>
81 {
82  basis = other.basis; // Here it works because both std::vector and Monomial perform a deep copy.
83  return *this;
84 }
85 
86 template<unsigned int dim>
87 unsigned int MonomialBasis<dim>::size() const
88 {
89  return basis.size();
90 }
91 
92 template<unsigned int dim>
93 const Monomial<dim> &MonomialBasis<dim>::getElement(unsigned int i) const
94 {
95  return basis[i];
96 }
97 
98 template<unsigned int dim>
100 {
101  return basis[i];
102 }
103 
104 template<unsigned int dim>
105 void MonomialBasis<dim>::generateBasis(std::vector<unsigned int> m, unsigned int r)
106 {
107  // Compute the vector of actual dimensions to iterate over
108  // NOTE: each index can go up to sum(m)+r
109  unsigned int mSum = std::accumulate(m.begin(), m.end(), 0U);
110  unsigned int orderLimit = mSum + r;
111  size_t dimensions[dim];
112  std::fill(dimensions, dimensions + dim, orderLimit);
113 
114  // Now initialize grid with appropriate size, then start-stop points and boundary conditions for the iterator
115  grid_sm<dim, void> grid(dimensions);
116 
117  long int startV[dim] = {}; // 0-initialized
118  grid_key_dx<dim, long int> start(startV);
119  grid_key_dx<dim, long int> stop(dimensions);
120 
121  size_t bc[dim];
122  std::fill(bc, bc + dim, NON_PERIODIC);
123 
124  grid_key_dx_iterator_sub_bc<dim> it(grid, start, stop, bc);
125 
126  // Finally compute alpha_min
127  unsigned char alphaMin = static_cast<unsigned char>(!(mSum % 2)); // if mSum is even, alpha_min must be 1
128  //std::cout<<"AlphaMin: "<<alphaMin<<std::endl;
129  //unsigned char alphaMin = 0; // we want to always have 1 in the basis
130 
131  while (it.isNext())
132  {
133  Point<dim, long int> p = it.get().get_k();
134  Monomial<dim> candidateBasisElement(p);
135  // Filter out the elements which don't fullfil the theoretical condition for being in the vandermonde matrix
136  if (candidateBasisElement.order() < orderLimit && candidateBasisElement.order() >= alphaMin)
137  {
138  basis.push_back(candidateBasisElement);
139  }
140  ++it;
141  }
142 }
143 
144 template<unsigned int dim>
145 const std::vector<Monomial<dim>> &MonomialBasis<dim>::getElements() const
146 {
147  return basis;
148 }
149 
150 template<unsigned int dim>
152 {
153  std::vector<Monomial<dim>> derivatives;
154  for (const auto &monomial : getElements())
155  {
156  derivatives.push_back(monomial.getDerivative(differentialOrder));
157  }
158  return MonomialBasis<dim>(derivatives);
159 }
160 
161 template<unsigned int dim>
162 bool MonomialBasis<dim>::operator==(const MonomialBasis &other) const
163 {
164  return basis == other.basis;
165 }
166 
167 //template<unsigned int dim>
168 //MonomialBasis<dim>::MonomialBasis(Point<dim, unsigned int> degrees, unsigned int convergenceOrder)
169 // : MonomialBasis(degrees.asArray(), convergenceOrder) {}
170 
171 #endif //OPENFPM_PDATA_MONOMIALBASIS_H
__device__ __host__ const T & get(unsigned int i) const
Get coordinate.
Definition: Point.hpp:172
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data