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