8#include <KokkosBatched_Copy_Decl.hpp>
9#include <Kokkos_Core.hpp>
10#include <Kokkos_Profiling_ScopedRegion.hpp>
14#include "interpolator.hxx"
21#define VIEW_ALLOC(name) \
22 Kokkos::view_alloc(ExecSpace{}, Kokkos::WithoutInitializing, \
23 _region_name + "::" + name)
35void TEMPLATED_CLASSNAME::Interpolate(
void) {
36 const std::string _region_name =
"RbfPumInterpolator::Interpolate";
37 const ExecSpace execspace{};
39 const index_t K = this->mClusters.extent(0);
41 Kokkos::Profiling::pushRegion(_region_name +
42 "::fetch source and target nodes");
45 VectorView<index_t> clusters_source_indices(
47 VectorView<offset_t> clusters_source_offsets(
49 GetClustersPoints get_clusters_points_predicate{this->mClusters,
51 GetClustersPointsCallback get_clusters_points_callback;
54 VectorView<index_t> clusters_target_indices(
56 VectorView<offset_t> clusters_target_offsets(
59 this->mSourceBvh.query(ExecSpace{}, get_clusters_points_predicate,
60 get_clusters_points_callback, clusters_source_indices,
61 clusters_source_offsets);
63 this->mTargetBvh.query(ExecSpace{}, get_clusters_points_predicate,
64 get_clusters_points_callback, clusters_target_indices,
65 clusters_target_offsets);
67 Kokkos::Profiling::popRegion();
69 Kokkos::Profiling::pushRegion(_region_name +
70 "::compute offsets and allocate memory");
74 VectorView<offset_t> rbf_mat_offsets(
VIEW_ALLOC(
"rbf_mat_offsets"), K + 1);
75 VectorView<offset_t> eval_mat_offsets(
VIEW_ALLOC(
"eval_mat_offsets"), K + 1);
78 OffsetsScan<ExecSpace> offsets_scan{clusters_source_offsets,
79 clusters_target_offsets, rbf_mat_offsets,
81 Kokkos::parallel_scan(_region_name +
"::p_scan create access offsets",
82 Kokkos::RangePolicy(execspace, 0, K), offsets_scan);
85 auto sv1 = Kokkos::subview(rbf_mat_offsets, K);
86 auto sv2 = Kokkos::subview(rbf_mat_offsets, 0);
87 auto sv3 = Kokkos::subview(eval_mat_offsets, K);
88 auto sv4 = Kokkos::subview(eval_mat_offsets, 0);
89 Kokkos::deep_copy(rbf_mat_size, sv1);
90 Kokkos::deep_copy(sv2, 0);
91 Kokkos::deep_copy(eval_mat_size, sv3);
92 Kokkos::deep_copy(sv4, 0);
94 const int_t source_size = clusters_source_indices.extent_int(0);
95 const int_t target_size = clusters_target_indices.extent_int(0);
96 constexpr int_t poly_vals = Dim + 1;
114 VectorView<fp_t> As(
VIEW_ALLOC(
"As"), rbf_mat_size);
115 VectorView<fp_t> Bs(
VIEW_ALLOC(
"Bs"), source_size);
116 VectorView<fp_t> Qs(
VIEW_ALLOC(
"Qs"), source_size * poly_vals);
117 VectorView<fp_t> Vs(
VIEW_ALLOC(
"Vs"), target_size * poly_vals);
118 VectorView<fp_t> Es(
VIEW_ALLOC(
"Es"), eval_mat_size);
119 VectorView<fp_t> Ts(
VIEW_ALLOC(
"Ts"), poly_vals * K);
120 VectorView<fp_t> Ws(
VIEW_ALLOC(
"Ws"), source_size);
121 VectorView<fp_t> Xs(
VIEW_ALLOC(
"Xs"), source_size);
122 VectorView<fp_t> TempView(
VIEW_ALLOC(
"TempView"), target_size);
123 VectorView<Kokkos::Array<bool, Dim>> AxisView(
VIEW_ALLOC(
"AxisView"), K);
126 Kokkos::Profiling::popRegion();
129 Kokkos::Profiling::pushRegion(_region_name +
"::compute clusters weights");
130 const auto centers = this->mClusters;
131 const auto source = this->mSource;
132 const auto target = this->mTarget;
133 const auto values = this->mValues;
134 const auto rbf_function = this->mRbfFunction;
135 const auto weighting_function = this->mWeightingFunction;
137 const auto center_bvh = ::ArborX::BoundingVolumeHierarchy{
138 execspace, ::ArborX::Experimental::attach_indices(centers)};
139 GetClustersPoints get_target_clusters{target, this->mRadius};
140 GetClustersPointsCallback get_target_clusters_callback;
141 VectorView<index_t> weights_indices(
VIEW_ALLOC(
"weights_indices"), 0);
142 VectorView<offset_t> weights_offsets(
VIEW_ALLOC(
"weights_offsets"), 0);
143 center_bvh.query(execspace, get_target_clusters, get_target_clusters_callback,
144 weights_indices, weights_offsets);
149 VectorView<fp_t> weights(
VIEW_ALLOC(
"weights"), weights_indices.extent(0));
151 Kokkos::parallel_for(
152 _region_name +
"::p_for compute weights",
153 Kokkos::RangePolicy(execspace, 0, target.extent(0)),
154 KOKKOS_LAMBDA(
const index_t &i) {
155 const auto target_point = target(i);
157 for (
offset_t k = weights_offsets(i); k < weights_offsets(i + 1); ++k) {
158 const auto center_point = centers(weights_indices(k));
159 const auto w = weighting_function.Eval(
164 for (
offset_t k = weights_offsets(i); k < weights_offsets(i + 1); ++k) {
169 Kokkos::Profiling::popRegion();
172 auto output = this->out;
174 using team_policy = Kokkos::TeamPolicy<ExecSpace>;
175 using member_type = team_policy::member_type;
179 Kokkos::Profiling::pushRegion(_region_name +
"::fill and solve systems");
180 Kokkos::parallel_for(
181 _region_name +
"::p_for team fill A, E, B",
182 team_policy(execspace, K, Kokkos::AUTO),
183 KOKKOS_LAMBDA(
const member_type &team) {
184 const index_t k = team.league_rank();
185 const auto source_slice = Kokkos::make_pair(
186 clusters_source_offsets(k), clusters_source_offsets(k + 1));
187 const auto target_slice = Kokkos::make_pair(
188 clusters_target_offsets(k), clusters_target_offsets(k + 1));
190 const auto source_points =
191 Kokkos::subview(clusters_source_indices, source_slice);
192 const auto target_points =
193 Kokkos::subview(clusters_target_indices, target_slice);
195 const index_t n = source_slice.second - source_slice.first;
196 const index_t m = target_slice.second - target_slice.first;
202 auto B =
GetRbfVector(k, Bs, clusters_source_offsets, n);
205 TeamFillA(team, A, source, source_points, rbf_function);
206 TeamFillE(team, E, source, source_points, target, target_points,
208 TeamFillB(team, B, values, source_points);
217 Kokkos::parallel_for(
218 _region_name +
"::p_for fill and solve remaining systems",
219 Kokkos::RangePolicy(execspace, 0, K), KOKKOS_LAMBDA(
const index_t &k) {
220 const auto source_slice = Kokkos::make_pair(
221 clusters_source_offsets(k), clusters_source_offsets(k + 1));
222 const auto target_slice = Kokkos::make_pair(
223 clusters_target_offsets(k), clusters_target_offsets(k + 1));
225 const auto source_points =
226 Kokkos::subview(clusters_source_indices, source_slice);
227 const auto target_points =
228 Kokkos::subview(clusters_target_indices, target_slice);
230 const index_t n = source_slice.second - source_slice.first;
231 const index_t m = target_slice.second - target_slice.first;
235 auto B =
GetRbfMatrix(k, Bs, clusters_source_offsets, n, 1);
236 auto b = Kokkos::subview(B, Kokkos::ALL(), 0);
238 auto active_axis = AxisView(k);
239 for (
int_t d = 0; d < active_axis.size(); ++d) {
240 active_axis[d] =
true;
242 auto tQ =
GetPolyMatrix(k, Qs, clusters_source_offsets, n, active_axis);
243 auto W =
GetRbfVector(k, Ws, clusters_source_offsets, n);
248 auto V =
GetPolyMatrix(k, Vs, clusters_target_offsets, m, active_axis);
251 auto X =
GetRbfMatrix(k, Xs, clusters_source_offsets, n, 1);
252 auto T = Kokkos::subview(
253 Ts, Kokkos::make_pair(k * poly_vals, k * poly_vals + pv));
255 auto Q =
GetPolyMatrix(k, Qs, clusters_source_offsets, n, active_axis);
259 const auto polynomial_contrib =
260 Kokkos::subview(X, Kokkos::make_pair(0, pv), 0);
265 auto temp_out =
GetRbfVector(k, TempView, clusters_target_offsets, m);
267 auto x = Kokkos::subview(X, Kokkos::make_pair(0, pv), 0);
271 auto eval_mat_slice = Kokkos::subview(E, Kokkos::ALL(), 0);
275 for (
index_t i = 0; i < m; ++i) {
276 const auto target_indice = target_points(i);
277 const auto local_contribution = temp_out(i);
278 const auto output_addr = &(output(target_indice));
279 for (
offset_t t = weights_offsets(target_indice);
280 t < weights_offsets(target_indice + 1); ++t) {
281 if (weights_indices(t) == k) {
282 Kokkos::atomic_add(output_addr, weights(t) * local_contribution);
288 Kokkos::Profiling::popRegion();
KOKKOS_FORCEINLINE_FUNCTION void SerialVecVecSub(UViewType &U, const VViewType &V)
Perform an inplace difference of 2 vectors such as U = U - V.
KOKKOS_FORCEINLINE_FUNCTION auto GetPolyMatrix(const index_t &k, const PsViewType &Ps, const OffsViewType &offs, const int_t &n, const AxisType &activeAxis)
Returns a matrix of rank 2, shaped as (n, m), using the given data view, team rank,...
KOKKOS_FORCEINLINE_FUNCTION int_t SerialFillQ(QViewType &Q, const XViewType &X, const XOffsType &XOffs, WViewType &W, AxisType &activeAxis)
Fill the polynomial augmentation matrix Q and sets activeAxis accordingly to the deactivated axis in ...
KOKKOS_FORCEINLINE_FUNCTION auto GetRbfVector(const index_t &k, const BsViewType &Bs, const OffsViewType &offs, const int_t &n)
Returns a vector view of rank 1, of length n, using the given data view, team rank,...
KOKKOS_FORCEINLINE_FUNCTION void SerialSolveLU(AViewType &A, BViewType &B)
Solves AX=B for X using a LU factorization on A.
KOKKOS_FUNCTION void SerialFillPoly(PViewType &P, const XViewType &X, const OffsViewType &XOffs, AxisType &activeAxis)
Fill the polynomial augmentation matrix accordingly to the activated axis in activeAxis
KOKKOS_FORCEINLINE_FUNCTION void TeamFillA(const TeamHandleType &teamHandle, const AViewType &A, const XType &X, const XOffsType &XOffs, const RbfFuncType &func)
Fills the RBF matrix A in parallel.
KOKKOS_FORCEINLINE_FUNCTION void TeamFillB(const TeamHandleType &teamHandle, BViewType &B, const XType &X, const XOffsType &XOffs)
Fills the vector of known source values B in parallel.
KOKKOS_FORCEINLINE_FUNCTION auto GetRbfMatrix(const index_t &k, const AsViewType &As, const OffsViewType &offs, const int_t &n, const int_t &m)
Returns a matrix of rank 2, shaped as (n, m), using the given data view, team rank,...
KOKKOS_FORCEINLINE_FUNCTION void SerialMulMatVec(const AViewType &A, const BViewType &B, OutViewType &out)
Perform: out = Ab.
KOKKOS_INLINE_FUNCTION fp_t DistanceNoCheck(const ::ArborX::Point< Dim, coordinates_t > &lhs, const ::ArborX::Point< Dim, coordinates_t > &rhs)
Returns the euclidian norm between two points by performing a square root operation on the SquaredDif...
KOKKOS_FORCEINLINE_FUNCTION void SerialVecVecAdd(UViewType &U, const VViewType &V)
Perform an inplace addition of 2 vectors such as U = U + V.
KOKKOS_FORCEINLINE_FUNCTION void TeamFillE(const TeamHandleType &teamHandle, AViewType &A, const XType &X, const XOffsType &XOffs, const YType &Y, const YOffsType &YOffs, const RbfFuncType &func)
Fills the RBF evaluation matrix E in parallel.
KOKKOS_FORCEINLINE_FUNCTION auto SerialSolveQR(AViewType &A, const BViewType &B, TViewType &T, XViewType &X, WViewType &W)
Solves AX=B for X using a QR factorization on A.
KOKKOS_INLINE_FUNCTION consteval fp_t zero(void)
KOKKOS_INLINE_FUNCTION consteval fp_t epsilon(void)