DDC 0.1.0
Loading...
Searching...
No Matches
periodic_sampling.hpp
1// Copyright (C) The DDC development team, see COPYRIGHT.md file
2//
3// SPDX-License-Identifier: MIT
4
5#pragma once
6
7#include <cassert>
8#include <cstddef>
9#include <ostream>
10#include <tuple>
11#include <type_traits>
12#include <utility>
13
14#include <Kokkos_Core.hpp>
15
16#include "ddc/coordinate.hpp"
17#include "ddc/discrete_domain.hpp"
18#include "ddc/discrete_element.hpp"
19#include "ddc/discrete_space.hpp"
20#include "ddc/discrete_vector.hpp"
21#include "ddc/real_type.hpp"
22
23namespace ddc {
24
25namespace detail {
26
27struct PeriodicSamplingBase
28{
29};
30
31} // namespace detail
32
33/** PeriodicSampling models a periodic discretization of the provided continuous dimension
34 */
35template <class CDim>
36class PeriodicSampling : detail::PeriodicSamplingBase
37{
38public:
39 using continuous_dimension_type = CDim;
40
41 using continuous_element_type = Coordinate<CDim>;
42
43
44 using discrete_dimension_type = PeriodicSampling;
45
46public:
47 template <class DDim, class MemorySpace>
48 class Impl
49 {
50 template <class ODDim, class OMemorySpace>
51 friend class Impl;
52
53 private:
54 continuous_element_type m_origin {0};
55
56 Real m_step {1};
57
58 std::size_t m_n_period {2};
59
60 public:
61 using discrete_dimension_type = PeriodicSampling;
62
63 using discrete_domain_type = DiscreteDomain<DDim>;
64
65 using discrete_element_type = DiscreteElement<DDim>;
66
67 using discrete_vector_type = DiscreteVector<DDim>;
68
69 Impl() = default;
70
71 Impl(Impl const&) = delete;
72
73 template <class OriginMemorySpace>
74 explicit Impl(Impl<DDim, OriginMemorySpace> const& impl)
75 : m_origin(impl.m_origin)
76 , m_step(impl.m_step)
77 , m_n_period(impl.m_n_period)
78 {
79 }
80
81 Impl(Impl&&) = default;
82
83 /** @brief Construct a `Impl` from a point and a spacing step.
84 *
85 * @param origin the real coordinate of mesh coordinate 0
86 * @param step the real distance between two points of mesh distance 1
87 * @param n_period the number of steps in a period
88 */
89 Impl(continuous_element_type origin, Real step, std::size_t n_period)
90 : m_origin(origin)
91 , m_step(step)
92 , m_n_period(n_period)
93 {
94 assert(step > 0);
95 assert(n_period > 0);
96 }
97
98 ~Impl() = default;
99
100 Impl& operator=(Impl const& x) = delete;
101
102 Impl& operator=(Impl&& x) = default;
103
104 /// @brief Lower bound index of the mesh
105 KOKKOS_FUNCTION continuous_element_type origin() const noexcept
106 {
107 return m_origin;
108 }
109
110 /// @brief Lower bound index of the mesh
111 KOKKOS_FUNCTION discrete_element_type front() const noexcept
112 {
113 return discrete_element_type {0};
114 }
115
116 /// @brief Spacing step of the mesh
117 KOKKOS_FUNCTION Real step() const
118 {
119 return m_step;
120 }
121
122 /// @brief Number of steps in a period
123 KOKKOS_FUNCTION std::size_t n_period() const
124 {
125 return m_n_period;
126 }
127
128 /// @brief Convert a mesh index into a position in `CDim`
129 KOKKOS_FUNCTION continuous_element_type
130 coordinate(discrete_element_type const& icoord) const noexcept
131 {
132 return m_origin
133 + continuous_element_type(
134 static_cast<int>((icoord.uid() + m_n_period / 2) % m_n_period)
135 - static_cast<int>(m_n_period / 2))
136 * m_step;
137 }
138 };
139
140 /** Construct a Impl<Kokkos::HostSpace> and associated discrete_domain_type from a segment
141 * \f$[a, b] \subset [a, +\infty[\f$ and a number of points `n`.
142 * Note that there is no guarantee that either the boundaries a or b will be exactly represented in the sampling.
143 * One should expect usual floating point rounding errors.
144 *
145 * @param a coordinate of the first point of the domain
146 * @param b coordinate of the last point of the domain
147 * @param n number of points to map on the segment \f$[a, b]\f$ including a & b
148 * @param n_period the number of steps in a period
149 */
150 template <class DDim>
151 static std::tuple<typename DDim::template Impl<DDim, Kokkos::HostSpace>, DiscreteDomain<DDim>>
152 init(Coordinate<CDim> a,
153 Coordinate<CDim> b,
154 DiscreteVector<DDim> n,
155 DiscreteVector<DDim> n_period)
156 {
157 assert(a < b);
158 assert(n > 1);
159 assert(n_period > 1);
160 typename DDim::template Impl<DDim, Kokkos::HostSpace>
161 disc(a, Coordinate<CDim> {(b - a) / (n - 1)}, n_period);
162 DiscreteDomain<DDim> domain {disc.front(), n};
163 return std::make_tuple(std::move(disc), std::move(domain));
164 }
165
166 /** Construct a periodic `DiscreteDomain` from a segment \f$[a, b] \subset [a, +\infty[\f$ and a
167 * number of points `n`.
168 * Note that there is no guarantee that either the boundaries a or b will be exactly represented in the sampling.
169 * One should expect usual floating point rounding errors.
170 *
171 * @param a coordinate of the first point of the domain
172 * @param b coordinate of the last point of the domain
173 * @param n the number of points to map the segment \f$[a, b]\f$ including a & b
174 * @param n_period the number of steps in a period
175 * @param n_ghosts_before number of additional "ghost" points before the segment
176 * @param n_ghosts_after number of additional "ghost" points after the segment
177 */
178 template <class DDim>
179 std::tuple<
180 Impl<DDim, Kokkos::HostSpace>,
181 DiscreteDomain<DDim>,
182 DiscreteDomain<DDim>,
183 DiscreteDomain<DDim>,
184 DiscreteDomain<DDim>>
186 continuous_element_type a,
187 continuous_element_type b,
188 DiscreteVector<DDim> n,
189 DiscreteVector<DDim> n_period,
190 DiscreteVector<DDim> n_ghosts_before,
191 DiscreteVector<DDim> n_ghosts_after)
192 {
193 using discrete_domain_type = DiscreteDomain<DDim>;
194 assert(a < b);
195 assert(n > 1);
196 assert(n_period > 1);
197 Real discretization_step {(b - a) / (n - 1)};
198 Impl<DDim, Kokkos::HostSpace>
199 disc(a - n_ghosts_before.value() * discretization_step,
200 discretization_step,
201 n_period);
202 discrete_domain_type ghosted_domain
203 = discrete_domain_type(disc.front(), n + n_ghosts_before + n_ghosts_after);
204 discrete_domain_type pre_ghost
205 = discrete_domain_type(ghosted_domain.front(), n_ghosts_before);
206 discrete_domain_type main_domain
207 = discrete_domain_type(ghosted_domain.front() + n_ghosts_before, n);
208 discrete_domain_type post_ghost
209 = discrete_domain_type(main_domain.back() + 1, n_ghosts_after);
210 return std::make_tuple(
211 std::move(disc),
212 std::move(main_domain),
213 std::move(ghosted_domain),
214 std::move(pre_ghost),
215 std::move(post_ghost));
216 }
217
218 /** Construct a periodic `DiscreteDomain` from a segment \f$[a, b] \subset [a, +\infty[\f$ and a
219 * number of points `n`.
220 * Note that there is no guarantee that either the boundaries a or b will be exactly represented in the sampling.
221 * One should expect usual floating point rounding errors.
222 *
223 * @param a coordinate of the first point of the domain
224 * @param b coordinate of the last point of the domain
225 * @param n the number of points to map the segment \f$[a, b]\f$ including a & b
226 * @param n_period the number of steps in a period
227 * @param n_ghosts number of additional "ghost" points before and after the segment
228 */
229 template <class DDim>
230 std::tuple<
231 Impl<DDim, Kokkos::HostSpace>,
232 DiscreteDomain<DDim>,
233 DiscreteDomain<DDim>,
234 DiscreteDomain<DDim>,
235 DiscreteDomain<DDim>>
237 continuous_element_type a,
238 continuous_element_type b,
239 DiscreteVector<DDim> n,
240 DiscreteVector<DDim> n_period,
241 DiscreteVector<DDim> n_ghosts)
242 {
243 return init_ghosted(a, b, n, n_period, n_ghosts, n_ghosts);
244 }
245};
246
247template <class DDim>
248struct is_periodic_sampling : public std::is_base_of<detail::PeriodicSamplingBase, DDim>
249{
250};
251
252template <class DDim>
254
255template <
256 class DDimImpl,
257 std::enable_if_t<is_periodic_sampling_v<typename DDimImpl::discrete_dimension_type>, int>
258 = 0>
259std::ostream& operator<<(std::ostream& out, DDimImpl const& mesh)
260{
261 return out << "PeriodicSampling( origin=" << mesh.origin() << ", step=" << mesh.step() << " )";
262}
263
264/// @brief Lower bound index of the mesh
265template <class DDim>
266KOKKOS_FUNCTION std::enable_if_t<
267 is_periodic_sampling_v<DDim>,
268 Coordinate<typename DDim::continuous_dimension_type>>
269origin() noexcept
270{
271 return discrete_space<DDim>().origin();
272}
273
274/// @brief Lower bound index of the mesh
275template <class DDim>
276KOKKOS_FUNCTION std::enable_if_t<is_periodic_sampling_v<DDim>, DiscreteElement<DDim>>
277front() noexcept
278{
279 return discrete_space<DDim>().front();
280}
281
282/// @brief Spacing step of the mesh
283template <class DDim>
284KOKKOS_FUNCTION std::enable_if_t<is_periodic_sampling_v<DDim>, Real> step() noexcept
285{
286 return discrete_space<DDim>().step();
287}
288
289template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
290KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> coordinate(
291 DiscreteElement<DDim> const& c)
292{
293 return discrete_space<DDim>().coordinate(c);
294}
295
296template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
297KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> distance_at_left(
298 DiscreteElement<DDim>)
299{
300 return Coordinate<typename DDim::continuous_dimension_type>(step<DDim>());
301}
302
303template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
304KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> distance_at_right(
305 DiscreteElement<DDim>)
306{
307 return Coordinate<typename DDim::continuous_dimension_type>(step<DDim>());
308}
309
310template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
311KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> rmin(
312 DiscreteDomain<DDim> const& d)
313{
314 return coordinate(d.front());
315}
316
317template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
318KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> rmax(
319 DiscreteDomain<DDim> const& d)
320{
321 return coordinate(d.back());
322}
323
324template <class DDim, std::enable_if_t<is_periodic_sampling_v<DDim>, int> = 0>
325KOKKOS_FUNCTION Coordinate<typename DDim::continuous_dimension_type> rlength(
326 DiscreteDomain<DDim> const& d)
327{
328 return rmax(d) - rmin(d);
329}
330
331} // namespace ddc
friend class DiscreteDomain
KOKKOS_FUNCTION constexpr bool operator!=(DiscreteVector< OTags... > const &rhs) const noexcept
Impl & operator=(Impl &&x)=default
Impl(continuous_element_type origin, Real step, std::size_t n_period)
Construct a Impl from a point and a spacing step.
KOKKOS_FUNCTION discrete_element_type front() const noexcept
Lower bound index of the mesh.
Impl(Impl const &)=delete
KOKKOS_FUNCTION std::size_t n_period() const
Number of steps in a period.
KOKKOS_FUNCTION continuous_element_type origin() const noexcept
Lower bound index of the mesh.
KOKKOS_FUNCTION continuous_element_type coordinate(discrete_element_type const &icoord) const noexcept
Convert a mesh index into a position in CDim
Impl(Impl< DDim, OriginMemorySpace > const &impl)
KOKKOS_FUNCTION Real step() const
Spacing step of the mesh.
Impl & operator=(Impl const &x)=delete
PeriodicSampling models a periodic discretization of the provided continuous dimension.
std::tuple< Impl< DDim, Kokkos::HostSpace >, DiscreteDomain< DDim >, DiscreteDomain< DDim >, DiscreteDomain< DDim >, DiscreteDomain< DDim > > init_ghosted(continuous_element_type a, continuous_element_type b, DiscreteVector< DDim > n, DiscreteVector< DDim > n_period, DiscreteVector< DDim > n_ghosts)
Construct a periodic DiscreteDomain from a segment and a number of points n.
static std::tuple< typename DDim::template Impl< DDim, Kokkos::HostSpace >, DiscreteDomain< DDim > > init(Coordinate< CDim > a, Coordinate< CDim > b, DiscreteVector< DDim > n, DiscreteVector< DDim > n_period)
Construct a Impl<Kokkos::HostSpace> and associated discrete_domain_type from a segment and a number ...
std::tuple< Impl< DDim, Kokkos::HostSpace >, DiscreteDomain< DDim >, DiscreteDomain< DDim >, DiscreteDomain< DDim >, DiscreteDomain< DDim > > init_ghosted(continuous_element_type a, continuous_element_type b, DiscreteVector< DDim > n, DiscreteVector< DDim > n_period, DiscreteVector< DDim > n_ghosts_before, DiscreteVector< DDim > n_ghosts_after)
Construct a periodic DiscreteDomain from a segment and a number of points n.
The top-level namespace of DDC.
KOKKOS_FUNCTION std::enable_if_t< is_periodic_sampling_v< DDim >, Real > step() noexcept
Spacing step of the mesh.
KOKKOS_FUNCTION std::enable_if_t< is_periodic_sampling_v< DDim >, Coordinate< typename DDim::continuous_dimension_type > > origin() noexcept
Lower bound index of the mesh.
constexpr bool is_periodic_sampling_v
KOKKOS_FUNCTION std::enable_if_t< is_periodic_sampling_v< DDim >, DiscreteElement< DDim > > front() noexcept
Lower bound index of the mesh.