Gyselalib++
 
Loading...
Searching...
No Matches
matching_idx_slice.hpp
1// SPDX-License-Identifier: MIT
2
3#pragma once
4
5#include <numeric>
6#include <stdexcept>
7
8#include <ddc/ddc.hpp>
9
10#include "ddc_aliases.hpp"
11#include "ddc_helper.hpp"
12#include "edge.hpp"
13#include "edge_transformation.hpp"
14#include "idx_range_slice.hpp"
15
37template <class Interface>
39{
40 static_assert(
41 (!std::is_same_v<typename Interface::Edge1, OutsideEdge>)&&(
42 !std::is_same_v<typename Interface::Edge2, OutsideEdge>),
43 "The interface cannot be an interface with an OutsideEdge.");
44
45 using Patch1 = typename Interface::Edge1::associated_patch;
46 using Patch2 = typename Interface::Edge2::associated_patch;
47
48 using EdgeGrid1 = typename Interface::Edge1::parallel_grid;
49 using EdgeGrid2 = typename Interface::Edge2::parallel_grid;
50
51 using PerpEdgeGrid1 = typename Interface::Edge1::perpendicular_grid;
52 using PerpEdgeGrid2 = typename Interface::Edge2::perpendicular_grid;
53
54 using IdxRange1D_1 = IdxRange<EdgeGrid1>;
55 using IdxRange1D_2 = IdxRange<EdgeGrid2>;
56
57 using IdxRange2D_1 = typename Patch1::IdxRange12;
58 using IdxRange2D_2 = typename Patch2::IdxRange12;
59
62
63 static constexpr bool are_grids_uniform = (ddc::is_uniform_point_sampling_v<EdgeGrid1>)&&(
64 ddc::is_uniform_point_sampling_v<EdgeGrid2>);
65
66 IdxRange1D_1 const m_idx_range_edge_1;
67 IdxRange1D_2 const m_idx_range_edge_2;
68
69 IdxRangeSlice1 m_conforming_idx_1;
70 IdxRangeSlice2 m_conforming_idx_2;
71
72public:
73 ~MatchingIdxSlice() = default;
74
90 MatchingIdxSlice(IdxRange1D_1 const& idx_range_1, IdxRange1D_2 const& idx_range_2)
91 : m_idx_range_edge_1(idx_range_1)
92 , m_idx_range_edge_2(idx_range_2)
93 {
94 std::vector<Idx<EdgeGrid1>> conforming_indices_1;
95 std::vector<Idx<EdgeGrid2>> conforming_indices_2;
96 if constexpr (!are_grids_uniform) {
97 get_conforming_idx_vector(conforming_indices_1, conforming_indices_2);
98 }
99 m_conforming_idx_1 = get_idx_range_slice(m_idx_range_edge_1, conforming_indices_1);
100 m_conforming_idx_2 = get_idx_range_slice(m_idx_range_edge_2, conforming_indices_2);
101 }
102
103
119 MatchingIdxSlice(IdxRange2D_1 const& idx_range_1, IdxRange2D_2 const& idx_range_2)
120 : MatchingIdxSlice(ddc::select<EdgeGrid1>(idx_range_1), ddc::select<EdgeGrid2>(idx_range_2))
121 {
122 }
123
124
130 template <
131 class ParallelGrid,
132 std::enable_if_t<
133 (std::is_same_v<ParallelGrid, EdgeGrid1>)
134 || (std::is_same_v<ParallelGrid, EdgeGrid2>),
135 bool> = true>
137 {
138 if constexpr (std::is_same_v<ParallelGrid, EdgeGrid1>) {
139 return m_conforming_idx_1;
140 } else {
141 return m_conforming_idx_2;
142 }
143 }
144
145
152 template <
153 class PerpendicularGrid,
154 std::enable_if_t<
155 (std::is_same_v<PerpendicularGrid, PerpEdgeGrid1>)
156 || (std::is_same_v<PerpendicularGrid, PerpEdgeGrid2>),
157 bool> = true>
158 auto get_from_perp() const
159 {
160 if constexpr (std::is_same_v<PerpendicularGrid, PerpEdgeGrid1>) {
161 return m_conforming_idx_1;
162 } else {
163 return m_conforming_idx_2;
164 }
165 }
166
167
168private:
170 void get_conforming_idx_vector(
171 std::vector<Idx<EdgeGrid1>>& conforming_idx_vec_1,
172 std::vector<Idx<EdgeGrid2>>& conforming_idx_vec_2)
173 {
174 EdgeTransformation<Interface> edge_transformation(m_idx_range_edge_1, m_idx_range_edge_2);
175 Idx<EdgeGrid2> idx_2;
176 ddc::for_each(m_idx_range_edge_1, [&](Idx<EdgeGrid1> const& idx_1) {
177 if (edge_transformation.search_for_match(idx_2, idx_1)) {
178 conforming_idx_vec_1.push_back(idx_1);
179 conforming_idx_vec_2.push_back(idx_2);
180 }
181 });
182 }
183
184
186 template <class Grid1D>
187 IdxStep<Grid1D> get_idx_step(std::vector<Idx<Grid1D>> const& conforming_idx_vec) const
188 {
189 if constexpr (are_grids_uniform) {
190 std::size_t const n_cells_1 = m_idx_range_edge_1.size() - 1;
191 std::size_t const n_cells_2 = m_idx_range_edge_2.size() - 1;
192
193 // Get greatest common divisor
194 int const gcd_cells = std::gcd(n_cells_1, n_cells_2);
195 // Select right number of cells
196 std::size_t const n_cells = std::is_same_v<Grid1D, EdgeGrid1> ? n_cells_1 : n_cells_2;
197 int const step = n_cells / gcd_cells;
198 return IdxStep<Grid1D>(step);
199 } else {
200 IdxStep<Grid1D> const first_idx_step = conforming_idx_vec[1] - conforming_idx_vec[0];
201 for (std::size_t i(2); i < conforming_idx_vec.size(); i++) {
202 Idx<Grid1D> const idx = conforming_idx_vec[i];
203 Idx<Grid1D> const previous_idx = conforming_idx_vec[i - 1];
204
205 IdxStep<Grid1D> idx_step = idx - previous_idx;
206 if (idx_step != first_idx_step) {
207 throw std::invalid_argument(
208 "The steps between conforming indexes have to be uniform.");
209 }
210 };
211 return first_idx_step;
212 }
213 }
214
215
217 template <class Grid1D>
218 IdxRangeSlice<Grid1D> get_idx_range_slice(
219 IdxRange<Grid1D> const& idx_range,
220 std::vector<Idx<Grid1D>> const& conforming_idx_vec) const
221 {
222 Idx<Grid1D> idx_front = idx_range.front();
223 IdxStep<Grid1D> stride = get_idx_step(conforming_idx_vec);
224 IdxStep<Grid1D> size((idx_range.size() - 1) / stride.value() + 1);
225 return IdxRangeSlice<Grid1D>(idx_front, size, stride);
226 }
227};
Transform a coordinate or an index from one edge to the one on the other edge.
Definition edge_transformation.hpp:35
KOKKOS_FUNCTION constexpr Idx< Dims... > front() const noexcept
Get the first element in the index range slice.
Definition idx_range_slice.hpp:179
Store the conforming indexes of each patch of a given interface.
Definition matching_idx_slice.hpp:39
IdxRangeSlice< ParallelGrid > get() const
Get the IdxRangeSlice containing the conforming indexes.
Definition matching_idx_slice.hpp:136
MatchingIdxSlice(IdxRange2D_1 const &idx_range_1, IdxRange2D_2 const &idx_range_2)
Instantiate the class from 2D index ranges.
Definition matching_idx_slice.hpp:119
MatchingIdxSlice(IdxRange1D_1 const &idx_range_1, IdxRange1D_2 const &idx_range_2)
Instantiate the class from 1D index ranges.
Definition matching_idx_slice.hpp:90
auto get_from_perp() const
Get the IdxRangeSlice containing the conforming indexes.
Definition matching_idx_slice.hpp:158