preCICE
Loading...
Searching...
No Matches
BatchedRBFSolver.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef PRECICE_NO_KOKKOS_KERNELS
3
4#include <Kokkos_Core.hpp>
5#include <array>
6#include <cmath>
7#include <functional>
8#include <numeric>
15#include "mesh/Mesh.hpp"
17#include "profiling/Event.hpp"
18
20
21namespace precice::mapping {
22
33template <typename RADIAL_BASIS_FUNCTION_T>
35public:
36 using RBF_T = RADIAL_BASIS_FUNCTION_T;
37
40 BatchedRBFSolver(RBF_T basisFunction,
41 mesh::PtrMesh inMesh,
42 mesh::PtrMesh outMesh,
43 const std::vector<mesh::Vertex> &centers,
44 double clusterRadius,
45 Polynomial polynomial,
46 bool computeEvaluationOffline,
48
49 void solveConsistent(const time::Sample &globalIn, Eigen::VectorXd &globalOut);
50
51 void solveConservative(const time::Sample &globalIn, Eigen::VectorXd &globalOut);
52
53private:
54 mutable precice::logging::Logger _log{"mapping::BatchedRBFSolver"};
55
56 // Only used internally in the solve function to aid with the dispatch
61
62 template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint>
63 void _solveImpl(const time::Sample &globalIn, Eigen::VectorXd &globalOut);
64
65 // Helper to dispatch the actual kernel. Needed to help with the template parameters
66 template <SolverConstraint Constraint, typename... Args>
67 void _dispatch_solve_kernel(bool polynomial, bool evaluation_op_available, Args &&...args);
68
69 // Linear offsets for each cluster, i.e., all cluster sizes
72
73 // Stores for each cluster the VertexIDs
76
79
82
83 VectorView<> _qrMatrix; // flat view of (nCluster x verticesPerCluster_i x (dim + 1) = nCluster x verticesPerCluster_i x polyParams)
84 VectorView<> _qrTau; // flat view of Householder tau (nCluster x (dim + 1) = nCluster x polyParams)
85 PivotView<> _qrP; // flat view of Permutation and rank (nCluster x (dim + 2) = nCluster x (polyParams + rank))
86
88
91
92 // Currently only scalar data
94 // Kokkos::View<double *>::HostMirror _inDataMirror;
96 // Kokkos::View<double *>::HostMirror _outDataMirror;
97
100
103 const int _nCluster;
104 const int _dim; // Mesh dimension
107 // MappingConfiguration::GinkgoParameter _ginkgoParameter;
108};
109
110template <typename RADIAL_BASIS_FUNCTION_T>
112 mesh::PtrMesh inMesh,
113 mesh::PtrMesh outMesh,
114 const std::vector<mesh::Vertex> &centers,
115 double clusterRadius,
116 Polynomial polynomial,
117 bool computeEvaluationOffline,
119 : _basisFunction(basisFunction), _polynomial(polynomial), _nCluster(static_cast<int>(centers.size())), _dim(inMesh->getDimensions()), _computeEvaluationOffline(computeEvaluationOffline)
120{
122 PRECICE_CHECK(_polynomial != Polynomial::ON, "Setting polynomial to \"on\" for the mapping between \"{}\" and \"{}\" is not supported", inMesh->getName(), outMesh->getName());
123 // The LU decomposition uses no pivoting, which leads to divisions by zero if the diagonal contains zero entries, which is the case for our basis functions
124 PRECICE_CHECK(RADIAL_BASIS_FUNCTION_T::isStrictlyPositiveDefinite(), "batched solver is only available for positive definite basis functions, i.e., compact-polynomial functions and Gaussian.");
125
126 PRECICE_CHECK(!(inMesh->vertices().empty() || outMesh->vertices().empty()), "One of the meshes in the batched solvers is empty, which is invalid.");
127 PRECICE_CHECK(inMesh->getDimensions() == outMesh->getDimensions(), "Incompatible dimensions passed to the batched solver.");
128
129 precice::profiling::Event eInit("solver.initializeKokkos");
130 // We have to initialize Kokkos and Ginkgo here, as the initialization call allocates memory
131 // in the current setup, this will only initialize the device (and allocate memory) on the primary rank
132 // TODO: Document restriction: all mappings must use the same executor configuration within one participant
133 device::Device::initialize(ginkgoParameter.nThreads, ginkgoParameter.deviceId);
134 PRECICE_DEBUG("Using batched PU-RBF solver on executor \"{}\" for \"{}\" PU-RBF clusters in execution mode {}.", ginkgoParameter.executor, centers.size(), _computeEvaluationOffline ? "\"minimal-compute\" (evaluation offline)" : "\"minimal-memory\" (evaluation online)");
135 Kokkos::fence();
136 eInit.stop();
137
138// General assumption of the algorithm
139#ifndef NDEBUG
140 for (int i = 0; i < inMesh->nVertices(); ++i) {
141 PRECICE_ASSERT(inMesh->vertices()[i].getID() == i);
142 }
143 for (int i = 0; i < outMesh->nVertices(); ++i) {
144 PRECICE_ASSERT(outMesh->vertices()[i].getID() == i);
145 }
146#endif
147
148 precice::profiling::Event eNearestNeighbors("solver.queryVertices");
149
150 // Step 1: Query n-nearest neighbors and compute offsets, which hold the range for each cluster
151
152 PRECICE_DEBUG("Computing cluster association on the GPU");
153
154 // Initialize the view for the GPU offsets
155 _inOffsets = VectorOffsetView<>("inOffsets", _nCluster + 1);
156 _outOffsets = VectorOffsetView<>("outOffsets", _nCluster + 1);
157
158 // we fill this view on the host side
159 auto hostIn = Kokkos::create_mirror_view(_inOffsets);
160 auto hostOut = Kokkos::create_mirror_view(_outOffsets);
161
162 // for the global IDs, we use now a std::vector which we emplace
163 // we need at least contiguous memory here
164 // TODO: Check the performance of reallocations
165 std::vector<VertexID> globalInIDs;
166 std::vector<VertexID> globalOutIDs;
167
168 // has to be a separate loop, as we first need to gather knowledge about
169 // the shape for the meshes
170 hostIn(0) = 0;
171 hostOut(0) = 0;
172 // To detect overflows
173 std::uint64_t inCheck = 0;
174 std::uint64_t outCheck = 0;
176 for (int i = 0; i < _nCluster; ++i) {
177 const auto &center = centers[i];
178
179 // First we handle the input side
180 auto inIDs = inMesh->index().getVerticesInsideBox(center, clusterRadius);
181 _maxInClusterSize = std::max(_maxInClusterSize, static_cast<int>(inIDs.size()));
182 std::uint64_t tmpIn = hostIn(i) + inIDs.size();
183
184 // Check overflows
185 if constexpr (std::numeric_limits<offset_1d_type>::digits < std::numeric_limits<std::uint64_t>::digits) {
186 PRECICE_CHECK(tmpIn < std::numeric_limits<offset_1d_type>::max(),
187 "The selected integer precision for the (input) vector offsets (\"offset_1d_type\") overflow. You might want to change the precision specified in \"device/KokkosTypes.hpp\"");
188 }
189 if constexpr (std::numeric_limits<offset_2d_type>::digits < std::numeric_limits<std::uint64_t>::digits) {
190 inCheck += static_cast<std::uint64_t>(inIDs.size() * inIDs.size());
191 PRECICE_CHECK(inCheck < std::numeric_limits<offset_2d_type>::max(),
192 "The selected integer precision for the (input) matrix offsets (\"offset_2d_type\") overflow. You might want to change the precision specified in \"device/KokkosTypes.hpp\"");
193 }
194 hostIn(i + 1) = static_cast<offset_1d_type>(tmpIn);
195 std::copy(inIDs.begin(), inIDs.end(), std::back_inserter(globalInIDs));
196
197 // ... and the same for the output side
198 auto outIDs = outMesh->index().getVerticesInsideBox(center, clusterRadius - math::NUMERICAL_ZERO_DIFFERENCE);
199 _maxOutClusterSize = std::max(_maxOutClusterSize, static_cast<int>(outIDs.size()));
200 std::uint64_t tmpOut = hostOut(i) + outIDs.size();
201
202 // Check overflows
203 if constexpr (std::numeric_limits<offset_1d_type>::digits < std::numeric_limits<std::uint64_t>::digits) {
204 PRECICE_CHECK(tmpOut < std::numeric_limits<offset_1d_type>::max(),
205 "The selected integer precision for the (output) vector offsets (\"offset_1d_type\") overflow. You might want to change the precision specified in \"device/KokkosTypes.hpp\"");
206 }
208 if constexpr (std::numeric_limits<offset_2d_type>::digits < std::numeric_limits<std::uint64_t>::digits) {
209 outCheck += static_cast<std::uint64_t>(outIDs.size() * inIDs.size()); // is in x out
210 PRECICE_CHECK(outCheck < std::numeric_limits<offset_2d_type>::max(),
211 "The selected integer precision for the (output) matrix offsets (\"offset_2d_type\") overflow. You might want to change the precision specified in \"device/KokkosTypes.hpp\"");
212 }
213 }
214 hostOut(i + 1) = static_cast<offset_1d_type>(tmpOut);
215 std::copy(outIDs.begin(), outIDs.end(), std::back_inserter(globalOutIDs));
216 }
217
218 _avgClusterSize = hostIn(_nCluster /* = hostIn.extent(0) - 1 */) / _nCluster;
219 PRECICE_DEBUG("Average cluster size used to find a good team size of the kernel execution: {}", _avgClusterSize);
220
221 // Copy offsets onto the device
222 Kokkos::deep_copy(_inOffsets, hostIn);
223 Kokkos::deep_copy(_outOffsets, hostOut);
224
225 // ... now that we have the sizes, we transfer the map onto the device
226 _globalInIDs = GlobalIDView<>("globalInIDs", globalInIDs.size());
227 _globalOutIDs = GlobalIDView<>("globalOutIDs", globalOutIDs.size());
228
229 // Wrap in a view to perform deep copies further down
230 Kokkos::View<VertexID *, Kokkos::HostSpace, UnmanagedMemory>
231 tmpIn(globalInIDs.data(), globalInIDs.size());
232 Kokkos::View<VertexID *, Kokkos::HostSpace, UnmanagedMemory>
233 tmpOut(globalOutIDs.data(), globalOutIDs.size());
234
235 Kokkos::deep_copy(_globalInIDs, tmpIn);
236 Kokkos::deep_copy(_globalOutIDs, tmpOut);
237
238 Kokkos::fence();
239 eNearestNeighbors.stop();
240
241 precice::profiling::Event eOff2d("solver.kernel.compute2DOffsets");
242
243 // Step 2: Compute the matrix offsets on the device
244 PRECICE_DEBUG("Computing matrix offsets");
245 // We use a parallel scan for that
246 _kernelOffsets = MatrixOffsetView<>("kernelOffsets", _nCluster + 1);
247 Kokkos::deep_copy(_kernelOffsets, 0);
249
251 _evaluationOffsets = MatrixOffsetView<>("evaluationOffsets", _nCluster + 1);
252 Kokkos::deep_copy(_evaluationOffsets, 0);
254 }
255 Kokkos::fence();
256 eOff2d.stop();
257 precice::profiling::Event eMesh("solver.copyMeshes");
258 // Step 3: Handle the mesh data structure and copy over to the device
259 PRECICE_DEBUG("Computing mesh data on the device");
260
261 _inMesh = MeshView<>("inMesh", inMesh->nVertices(), _dim);
262 _outMesh = MeshView<>("outMesh", outMesh->nVertices(), _dim);
263
264 auto hostInMesh = Kokkos::create_mirror_view(_inMesh);
265 auto hostOutMesh = Kokkos::create_mirror_view(_outMesh);
266
267 for (int i = 0; i < inMesh->nVertices(); ++i) {
268 const auto &v = inMesh->vertex(i);
269 for (int d = 0; d < _dim; ++d) {
270 hostInMesh(i, d) = v.rawCoords()[d];
271 }
272 }
273 for (int i = 0; i < outMesh->nVertices(); ++i) {
274 const auto &v = outMesh->vertex(i);
275 for (int d = 0; d < _dim; ++d) {
276 hostOutMesh(i, d) = v.rawCoords()[d];
277 }
278 }
279 // Copy to device
280 Kokkos::deep_copy(_inMesh, hostInMesh);
281 Kokkos::deep_copy(_outMesh, hostOutMesh);
282 Kokkos::fence();
283 eMesh.stop();
284 {
285 PRECICE_DEBUG("Computing PU-RBF weights");
286 precice::profiling::Event eWeights("solver.kernel.computeWeights");
287
288 // Step 4: Compute the weights for each vertex
289 // we first need to transfer the center coordinates and the meshes onto the device
290 MeshView<> centerMesh("centerMesh", _nCluster, _dim);
291 auto hostCenterMesh = Kokkos::create_mirror_view(centerMesh);
292 for (int i = 0; i < _nCluster; ++i) {
293 const auto &v = centers[i];
294 for (int d = 0; d < _dim; ++d) {
295 hostCenterMesh(i, d) = v.rawCoords()[d];
296 }
297 }
298 Kokkos::deep_copy(centerMesh, hostCenterMesh);
299
300 _normalizedWeights = VectorView<>("normalizedWeights", globalOutIDs.size());
301 CompactPolynomialC2 weightingFunction(clusterRadius);
302 // Computing the weights parallelizes over the number of output mesh vertices
303 int avgOutClusterSize = hostOut(_nCluster /* = hostOut.extent(0) - 1 */) / _nCluster;
304 bool success = kernel::compute_weights(_nCluster, avgOutClusterSize, globalOutIDs.size(), outMesh->nVertices(), _dim, _outOffsets,
305 centerMesh, _globalOutIDs, _outMesh, weightingFunction, _normalizedWeights);
306 PRECICE_CHECK(success, "Clustering resulted in unassigned vertices for the output mesh \"{}\".", outMesh->getName());
307 Kokkos::fence();
308 }
309
312 PRECICE_DEBUG("Computing polynomial QR");
313 precice::profiling::Event ePoly("solver.kernel.computePolynomialQR");
314 _qrMatrix = VectorView<>("qrMatrix", globalInIDs.size() * (_dim + 1)); // = nCluster x verticesPerCluster_i x polyParams
315 _qrTau = VectorView<>("qrTau", _nCluster * (_dim + 1)); // = nCluster x polyParams
316 _qrP = PivotView<>("qrP", _nCluster * (_dim + 2)); // = nCluster x (polyParams + rank)
318 Kokkos::fence();
319 }
320 precice::profiling::Event eMatr("solver.kernel.assembleInputMatrices");
321 // Step 6: Launch the parallel kernel to assemble the kernel matrices
322 PRECICE_DEBUG("Assemble batched matrices");
323 // The kernel matrices /////////////
324 offset_2d_type unrolledSize = 0;
325 auto last_elem_view = Kokkos::subview(_kernelOffsets, _nCluster);
326 Kokkos::deep_copy(unrolledSize, last_elem_view);
327 _kernelMatrices = VectorView<>("kernelMatrices", unrolledSize);
328
331
332 Kokkos::fence();
333 eMatr.stop();
334
336 // The eval matrices ///////////////
337 precice::profiling::Event eMatrOut("solver.kernel.assembleOutputMatrices");
338 offset_2d_type evalSize = 0;
339 auto last_elem_view2 = Kokkos::subview(_evaluationOffsets, _nCluster);
340 Kokkos::deep_copy(evalSize, last_elem_view2);
341 _evalMatrices = VectorView<>("evalMatrices", evalSize);
342
345 Kokkos::fence();
346 }
347
348 precice::profiling::Event eLU("solver.kernel.lu");
349 // Step 7: Compute batched lu
350 PRECICE_DEBUG("Compute batched lu");
352 Kokkos::fence();
353 eLU.stop();
354 precice::profiling::Event eAllo("solver.allocateData");
355 // Step 8: Allocate memory for data transfer
356 PRECICE_DEBUG("Allocate data containers for data transfer");
357
358 _inData = VectorView<>("inData", inMesh->nVertices());
359 _outData = VectorView<>("outData", outMesh->nVertices());
360 Kokkos::fence();
361}
362
363template <typename RADIAL_BASIS_FUNCTION_T>
364template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint>
365void BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::_solveImpl(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
366{
367 // Determine target views based on the solver mode
368 auto &deviceIn = (Constraint == SolverConstraint::Consistent) ? _inData : _outData;
369 auto &deviceOut = (Constraint == SolverConstraint::Consistent) ? _outData : _inData;
370
371 auto solve_component =
372 [&](const double *inPtr, Eigen::Index inSize, double *outPtr, Eigen::Index outSize) {
373 // Step 1: Wrap memory into an unmanaged view
374 Kokkos::View<const double *, Kokkos::HostSpace, UnmanagedMemory>
375 inView(inPtr, inSize);
376
377 // Step 2: Copy over
378 precice::profiling::Event e1("solver.copyHostToDevice");
379 Kokkos::deep_copy(deviceIn, inView);
380 Kokkos::deep_copy(deviceOut, 0.0); // Reset output data
381
382 Kokkos::fence();
383 e1.stop();
384
385 // Step 3: Launch the kernel
386 precice::profiling::Event e2("solver.kernel.batchedSolve");
392
393 Kokkos::fence();
394 e2.stop();
395
396 // Step 4: Copy back
397 precice::profiling::Event e3("solver.copyDeviceToHost");
398 Kokkos::View<double *, Kokkos::HostSpace, UnmanagedMemory>
399 outView(outPtr, outSize);
400 Kokkos::deep_copy(outView, deviceOut);
401 Kokkos::fence();
402 e3.stop();
403 };
404
405 const int nComponents = globalIn.dataDims;
406
407 // If we have just one component, we can directly copy the data over and solve
408 if (nComponents == 1) {
409 solve_component(globalIn.values.data(), globalIn.values.size(), globalOut.data(), globalOut.size());
410 } else {
411 // Otherwise, we map the data to a component-wise matrix
412 Eigen::Map<const Eigen::MatrixXd> inMatrix(globalIn.values.data(), nComponents, globalIn.values.size() / nComponents);
413 Eigen::Map<Eigen::MatrixXd> outMatrix(globalOut.data(), nComponents, globalOut.size() / nComponents);
414
415 // ... and solve component-wise. This requires each component to be contiguous in memory
416 Eigen::VectorXd tmpIn(inMatrix.cols());
417 Eigen::VectorXd tmpOut(outMatrix.cols());
418 for (int c = 0; c < nComponents; ++c) {
419 tmpIn = inMatrix.row(c);
420 solve_component(tmpIn.data(), tmpIn.size(), tmpOut.data(), tmpOut.size());
421 outMatrix.row(c) = tmpOut;
422 }
423 }
424}
425
426template <typename RADIAL_BASIS_FUNCTION_T>
431
432template <typename RADIAL_BASIS_FUNCTION_T>
437
438// Forwarding dispatcher for the actual implementation to help with the template parameters:
439template <typename RADIAL_BASIS_FUNCTION_T>
440template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint, typename... Args>
441void BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::_dispatch_solve_kernel(bool polynomial, bool evaluation_op_available,
442 Args &&...args)
443{
444 // Helper lambda to map runtime bools to compile-time template arguments
445 auto call = [&](auto poly, auto eval) {
446 if constexpr (Constraint == SolverConstraint::Consistent) {
447 kernel::do_batched_solve<poly.value, eval.value>(std::forward<Args>(args)...);
448 } else {
449 kernel::do_batched_conservative_solve<poly.value, eval.value>(std::forward<Args>(args)...);
450 }
451 };
452
453 if (polynomial) {
454 if (evaluation_op_available)
455 call(std::true_type{}, std::true_type{});
456 else
457 call(std::true_type{}, std::false_type{});
458 } else {
459 if (evaluation_op_available)
460 call(std::false_type{}, std::true_type{});
461 else
462 call(std::false_type{}, std::false_type{});
463 }
464}
465} // namespace precice::mapping
466
467#else
468
471namespace precice::mapping {
472
473template <typename RADIAL_BASIS_FUNCTION_T>
474class BatchedRBFSolver {
475public:
476 BatchedRBFSolver(RADIAL_BASIS_FUNCTION_T,
479 const std::vector<mesh::Vertex> &,
480 double,
481 Polynomial,
482 bool,
483 MappingConfiguration::GinkgoParameter) {}
484
485 void solveConservative(const time::Sample &, Eigen::VectorXd &) {}
486 void solveConsistent(const time::Sample &, Eigen::VectorXd &) {}
487};
488} // namespace precice::mapping
489#endif // PRECICE_NO_KOKKOS_KERNELS
#define PRECICE_DEBUG(...)
Definition LogMacros.hpp:61
#define PRECICE_TRACE(...)
Definition LogMacros.hpp:92
#define PRECICE_CHECK(check,...)
Definition LogMacros.hpp:32
#define PRECICE_ASSERT(...)
Definition assertion.hpp:85
int getDimensions() const
Definition Mesh.cpp:100
VertexContainer & vertices()
Returns modifieable container holding all vertices.
Definition Mesh.cpp:55
const std::string & getName() const
Returns the name of the mesh, as set in the config file.
Definition Mesh.cpp:243
std::size_t nVertices() const
Returns the number of vertices.
Definition Mesh.cpp:65
Vertex & vertex(VertexID id)
Mutable access to a vertex by VertexID.
Definition Mesh.cpp:43
const query::Index & index() const
Call preprocess() before index() to ensure correct projection handling.
Definition Mesh.hpp:329
static void initialize(int *argc, char ***argv)
Definition Device.cpp:12
This class provides a lightweight logger.
Definition Logger.hpp:17
void _solveImpl(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
void solveConsistent(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
BatchedRBFSolver(RBF_T basisFunction, mesh::PtrMesh inMesh, mesh::PtrMesh outMesh, const std::vector< mesh::Vertex > &centers, double clusterRadius, Polynomial polynomial, bool computeEvaluationOffline, MappingConfiguration::GinkgoParameter ginkgoParameter)
void _dispatch_solve_kernel(bool polynomial, bool evaluation_op_available, Args &&...args)
void solveConservative(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
Wendland radial basis function with compact support.
void stop()
Stops a running event.
Definition Event.cpp:51
void do_batched_qr(int nCluster, int dim, int avgClusterSize, int maxClusterSize, VectorOffsetView< MemorySpace > inOffsets, GlobalIDView< MemorySpace > globalInIDs, MeshView< MemorySpace > inMesh, VectorView< MemorySpace > qrMatrix, VectorView< MemorySpace > qrTau, PivotView< MemorySpace > qrP)
void do_batched_assembly(int nCluster, int dim, int avgClusterSize, EvalFunctionType f, const VectorOffsetView< MemorySpace > &inOffsets, const GlobalIDView< MemorySpace > &globalInIDs, const MeshView< MemorySpace > &inCoords, const VectorOffsetView< MemorySpace > &targetOffsets, const GlobalIDView< MemorySpace > &globalTargetIDs, const MeshView< MemorySpace > &targetCoords, const MatrixOffsetView< MemorySpace > &matrixOffsets, VectorView< MemorySpace > matrices)
void do_batched_conservative_solve(int nCluster, int dim, int avgInClusterSize, int maxInClusterSize, int maxOutClusterSize, EvalFunctionType f, const VectorOffsetView< MemorySpace > &rhsOffsets, const GlobalIDView< MemorySpace > &globalRhsIDs, VectorView< MemorySpace > rhs, const MatrixOffsetView< MemorySpace > &matrixOffsets, const VectorView< MemorySpace > &matrices, const VectorView< MemorySpace > &normalizedWeights, const MatrixOffsetView< MemorySpace > &evalOffsets, const VectorView< MemorySpace > &evalMat, const VectorOffsetView< MemorySpace > &outOffsets, const GlobalIDView< MemorySpace > &globalOutIDs, VectorView< MemorySpace > out, const MeshView< MemorySpace > &inMesh, const MeshView< MemorySpace > &outMesh, const VectorView< MemorySpace > &qrMatrix, const VectorView< MemorySpace > &qrTau, const PivotView< MemorySpace > &qrP)
bool compute_weights(const int nCluster, const int avgOutClusterSize, const offset_1d_type nWeights, const int nMeshVertices, const int dim, VectorOffsetView< MemorySpace > offsets, MeshView< MemorySpace > centers, GlobalIDView< MemorySpace > globalIDs, MeshView< MemorySpace > mesh, const CompactPolynomialC2 &w, VectorView< MemorySpace > normalizedWeights)
void do_input_assembly(int nCluster, int dim, int avgClusterSize, int maxInClusterSize, EvalFunctionType f, const VectorOffsetView< MemorySpace > &inOffsets, const GlobalIDView< MemorySpace > &globalInIDs, const MeshView< MemorySpace > &inCoords, const MatrixOffsetView< MemorySpace > &matrixOffsets, VectorView< MemorySpace > matrices)
void do_batched_solve(int nCluster, int dim, int avgInClusterSize, int maxInClusterSize, int maxOutClusterSize, EvalFunctionType f, const VectorOffsetView< MemorySpace > &rhsOffsets, const GlobalIDView< MemorySpace > &globalRhsIDs, VectorView< MemorySpace > rhs, const MatrixOffsetView< MemorySpace > &matrixOffsets, const VectorView< MemorySpace > &matrices, const VectorView< MemorySpace > &normalizedWeights, const MatrixOffsetView< MemorySpace > &evalOffsets, const VectorView< MemorySpace > &evalMat, const VectorOffsetView< MemorySpace > &outOffsets, const GlobalIDView< MemorySpace > &globalOutIDs, VectorView< MemorySpace > out, const MeshView< MemorySpace > &inMesh, const MeshView< MemorySpace > &outMesh, const VectorView< MemorySpace > &qrMatrix, const VectorView< MemorySpace > &qrTau, const PivotView< MemorySpace > &qrP)
void compute_offsets(const VectorOffsetView< MemorySpace > src1, const VectorOffsetView< MemorySpace > src2, MatrixOffsetView< MemorySpace > dst, int nCluster)
void do_batched_lu(int nCluster, int avgClusterSize, const MatrixOffsetView< MemorySpace > &matrixOffsets, VectorView< MemorySpace > matrices)
contains data mapping from points to meshes.
ExecutionSpace::size_type offset_2d_type
Kokkos::View< int *, MemorySpace > PivotView
Kokkos::View< offset_2d_type *, MemorySpace > MatrixOffsetView
Kokkos::View< offset_1d_type *, MemorySpace > VectorOffsetView
Kokkos::View< VertexID *, MemorySpace > GlobalIDView
ExecutionSpace::size_type offset_1d_type
Kokkos::View< double *, MemorySpace > VectorView
Polynomial
How to handle the polynomial?
Kokkos::View< double **, Kokkos::LayoutRight, MemorySpace > MeshView
constexpr double NUMERICAL_ZERO_DIFFERENCE
std::shared_ptr< Mesh > PtrMesh
Wrapper struct that is used to transfer RBF-specific parameters to the GPU.
int dataDims
The dimensionality of the data.
Definition Sample.hpp:60
Eigen::VectorXd values
Definition Sample.hpp:64