6#include "ddc_aliases.hpp"
7#include "ddc_helper.hpp"
9enum class BCond { PERIODIC, DIRICHLET };
17template <
class Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
20 static_assert((BcMin == BCond::PERIODIC) == (BcMax == BCond::PERIODIC));
21 using IdxInterp = Idx<GridInterp>;
22 using IdxStepInterp = IdxStep<GridInterp>;
23 using IdxRangeInterp = IdxRange<GridInterp>;
25 using CoordDimI = Coord<typename GridInterp::continuous_dimension_type>;
28 IdxRangeInterp m_idx_range;
29 IdxRangeInterp m_inner_idx_range;
30 Field<double, IdxRangeInterp, typename Execspace::memory_space> m_lagrange_coeffs;
31 CoordDimI m_left_bound;
32 CoordDimI m_right_bound;
33 IdxStepInterp m_poly_support;
46 Field<double, IdxRangeInterp, typename Execspace::memory_space> x_nodes_fnodes,
47 IdxRangeInterp idx_range,
49 : m_idx_range(idx_range)
50 , m_inner_idx_range(idx_range.remove(ghost, ghost))
51 , m_lagrange_coeffs(x_nodes_fnodes)
52 , m_left_bound(ddc::coordinate(m_inner_idx_range.front()))
53 , m_right_bound(ddc::coordinate(m_inner_idx_range.back()))
54 , m_poly_support(degree + 1)
66 KOKKOS_FUNCTION
double evaluate(CoordDimI x_interp)
const;
69 IdxInterp getclosest(CoordDimI value)
const;
71 KOKKOS_FUNCTION IdxInterp getclosest_binsearch(CoordDimI value)
const;
73 KOKKOS_FUNCTION
double evaluate_lagrange(CoordDimI x_interp)
const;
75 KOKKOS_FUNCTION
double apply_bc(CoordDimI x_interp)
const;
77 KOKKOS_FUNCTION
double compute_basis(
80 IdxRangeInterp polynom_subidx_range)
const;
83template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
86 assert(value >= m_left_bound && value <= m_right_bound);
88 min_element(m_idx_range.begin(), m_idx_range.end(), [=](IdxInterp x, IdxInterp y) {
89 return std::abs(ddc::coordinate(x) - value) < std::abs(ddc::coordinate(y) - value);
93template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
97 assert(x_interp >= m_left_bound && x_interp <= m_right_bound);
98 IdxInterp begin = m_idx_range.front();
99 IdxInterp end = m_idx_range.back();
100 IdxInterp elm_cell = begin + (end - begin) / 2;
101 while (x_interp < ddc::coordinate(elm_cell)
102 || x_interp > ddc::coordinate(elm_cell + IdxStepInterp(1))) {
103 if (x_interp < ddc::coordinate(elm_cell)) {
109 elm_cell = begin + (end - begin) / 2;
123template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
127 IdxRangeInterp polynom_subidx_range)
const
130 CoordDimI coord_j = ddc::coordinate(j);
131 for (IdxInterp
const i : polynom_subidx_range) {
132 CoordDimI coord_i = ddc::coordinate(i);
133 if (coord_i != coord_j) {
134 w *= (x_interp - coord_i) / (coord_j - coord_i);
140template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
142 CoordDimI x_interp)
const
144 CoordDimI bc_val = x_interp;
145 const double d = m_right_bound - m_left_bound;
146 if constexpr (BcMin == BCond::PERIODIC) {
147 bc_val -= Kokkos::floor((x_interp - m_left_bound) / d) * d;
149 if (x_interp < m_left_bound && BcMin == BCond::DIRICHLET) {
150 bc_val = m_left_bound;
151 }
else if (x_interp > m_right_bound && BcMax == BCond::DIRICHLET) {
152 bc_val = m_right_bound;
155 return evaluate_lagrange(bc_val);
158template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
160 CoordDimI x_interp)
const
162 if (x_interp < m_left_bound || m_right_bound < x_interp) {
163 return apply_bc(x_interp);
165 return evaluate_lagrange(x_interp);
169template <
typename Execspace,
class Gr
idInterp, BCond BcMin, BCond BcMax>
171 CoordDimI x_intern)
const
173 assert(x_intern >= m_left_bound && x_intern <= m_right_bound);
175 IdxInterp begin, end;
176 IdxInterp icell = getclosest_binsearch(x_intern);
177 IdxInterp mid = icell;
178 if (mid >= m_inner_idx_range.back() && BcMax == BCond::PERIODIC) {
179 begin = mid - m_poly_support / 2;
180 end = Kokkos::min(m_inner_idx_range.back(), begin + m_poly_support);
181 }
else if (mid <= m_inner_idx_range.front() && BcMin == BCond::PERIODIC) {
182 begin = Kokkos::max(m_idx_range.front(), mid - m_poly_support / 2);
183 end = begin + m_poly_support;
185 if (m_inner_idx_range.front() + m_poly_support / 2 > mid) {
186 begin = m_inner_idx_range.front();
188 begin = mid - m_poly_support / 2;
190 end = Kokkos::min(m_idx_range.back() + IdxStepInterp(1), begin + m_poly_support);
193 if (end == m_idx_range.back())
194 begin = end - m_poly_support;
195 IdxStepInterp npoints_subidx_range(end - begin);
196 IdxRangeInterp subidx_range(begin, npoints_subidx_range);
198 for (IdxInterp
const ix : subidx_range) {
199 p += compute_basis(x_intern, ix, subidx_range) * m_lagrange_coeffs(ix);
A class which implements Lagrange polynomials.
Definition Lagrange.hpp:19
KOKKOS_FUNCTION double evaluate(CoordDimI x_interp) const
Evaluates the approximated value of a function on a point current values at a known set of interpolat...
Definition Lagrange.hpp:159
KOKKOS_FUNCTION Lagrange(int degree, Field< double, IdxRangeInterp, typename Execspace::memory_space > x_nodes_fnodes, IdxRangeInterp idx_range, IdxStepInterp ghost)
Usual Constructor.
Definition Lagrange.hpp:44