2#ifndef PRECICE_NO_KOKKOS_KERNELS
4#include <Kokkos_Core.hpp>
33template <
typename RADIAL_BASIS_FUNCTION_T>
36 using RBF_T = RADIAL_BASIS_FUNCTION_T;
43 const std::vector<mesh::Vertex> ¢ers,
46 bool computeEvaluationOffline,
62 template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint>
110template <
typename RADIAL_BASIS_FUNCTION_T>
114 const std::vector<mesh::Vertex> ¢ers,
115 double clusterRadius,
117 bool computeEvaluationOffline,
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.");
126 PRECICE_CHECK(!(inMesh->
vertices().empty() || outMesh->
vertices().empty()),
"One of the meshes in the batched solvers is empty, which is invalid.");
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)");
140 for (
int i = 0; i < inMesh->
nVertices(); ++i) {
143 for (
int i = 0; i < outMesh->
nVertices(); ++i) {
159 auto hostIn = Kokkos::create_mirror_view(
_inOffsets);
160 auto hostOut = Kokkos::create_mirror_view(
_outOffsets);
165 std::vector<VertexID> globalInIDs;
166 std::vector<VertexID> globalOutIDs;
173 std::uint64_t inCheck = 0;
174 std::uint64_t outCheck = 0;
177 const auto ¢er = centers[i];
180 auto inIDs = inMesh->
index().getVerticesInsideBox(center, clusterRadius);
182 std::uint64_t tmpIn = hostIn(i) + inIDs.size();
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\"");
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\"");
195 std::copy(inIDs.begin(), inIDs.end(), std::back_inserter(globalInIDs));
200 std::uint64_t tmpOut = hostOut(i) + outIDs.size();
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\"");
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());
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\"");
215 std::copy(outIDs.begin(), outIDs.end(), std::back_inserter(globalOutIDs));
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());
239 eNearestNeighbors.
stop();
264 auto hostInMesh = Kokkos::create_mirror_view(
_inMesh);
265 auto hostOutMesh = Kokkos::create_mirror_view(
_outMesh);
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];
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];
280 Kokkos::deep_copy(
_inMesh, hostInMesh);
281 Kokkos::deep_copy(
_outMesh, hostOutMesh);
291 auto hostCenterMesh = Kokkos::create_mirror_view(centerMesh);
293 const auto &v = centers[i];
294 for (
int d = 0; d <
_dim; ++d) {
295 hostCenterMesh(i, d) = v.rawCoords()[d];
298 Kokkos::deep_copy(centerMesh, hostCenterMesh);
306 PRECICE_CHECK(success,
"Clustering resulted in unassigned vertices for the output mesh \"{}\".", outMesh->
getName());
326 Kokkos::deep_copy(unrolledSize, last_elem_view);
340 Kokkos::deep_copy(evalSize, last_elem_view2);
363template <
typename RADIAL_BASIS_FUNCTION_T>
364template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint>
371 auto solve_component =
372 [&](
const double *inPtr, Eigen::Index inSize,
double *outPtr, Eigen::Index outSize) {
374 Kokkos::View<const double *, Kokkos::HostSpace, UnmanagedMemory>
375 inView(inPtr, inSize);
379 Kokkos::deep_copy(deviceIn, inView);
380 Kokkos::deep_copy(deviceOut, 0.0);
398 Kokkos::View<double *, Kokkos::HostSpace, UnmanagedMemory>
399 outView(outPtr, outSize);
400 Kokkos::deep_copy(outView, deviceOut);
405 const int nComponents = globalIn.
dataDims;
408 if (nComponents == 1) {
409 solve_component(globalIn.
values.data(), globalIn.
values.size(), globalOut.data(), globalOut.size());
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);
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;
426template <
typename RADIAL_BASIS_FUNCTION_T>
432template <
typename RADIAL_BASIS_FUNCTION_T>
439template <
typename RADIAL_BASIS_FUNCTION_T>
440template <BatchedRBFSolver<RADIAL_BASIS_FUNCTION_T>::SolverConstraint Constraint,
typename... Args>
445 auto call = [&](
auto poly,
auto eval) {
454 if (evaluation_op_available)
455 call(std::true_type{}, std::true_type{});
457 call(std::true_type{}, std::false_type{});
459 if (evaluation_op_available)
460 call(std::false_type{}, std::true_type{});
462 call(std::false_type{}, std::false_type{});
473template <
typename RADIAL_BASIS_FUNCTION_T>
474class BatchedRBFSolver {
476 BatchedRBFSolver(RADIAL_BASIS_FUNCTION_T,
479 const std::vector<mesh::Vertex> &,
483 MappingConfiguration::GinkgoParameter) {}
485 void solveConservative(
const time::Sample &, Eigen::VectorXd &) {}
486 void solveConsistent(
const time::Sample &, Eigen::VectorXd &) {}
#define PRECICE_DEBUG(...)
#define PRECICE_TRACE(...)
#define PRECICE_CHECK(check,...)
#define PRECICE_ASSERT(...)
int getDimensions() const
VertexContainer & vertices()
Returns modifieable container holding all vertices.
const std::string & getName() const
Returns the name of the mesh, as set in the config file.
std::size_t nVertices() const
Returns the number of vertices.
Vertex & vertex(VertexID id)
Mutable access to a vertex by VertexID.
const query::Index & index() const
Call preprocess() before index() to ensure correct projection handling.
static void initialize(int *argc, char ***argv)
This class provides a lightweight logger.
RADIAL_BASIS_FUNCTION_T RBF_T
precice::logging::Logger _log
VectorView _kernelMatrices
MatrixOffsetView _evaluationOffsets
void _solveImpl(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
MatrixOffsetView _kernelOffsets
VectorView _normalizedWeights
void solveConsistent(const time::Sample &globalIn, Eigen::VectorXd &globalOut)
BatchedRBFSolver(RBF_T basisFunction, mesh::PtrMesh inMesh, mesh::PtrMesh outMesh, const std::vector< mesh::Vertex > ¢ers, double clusterRadius, Polynomial polynomial, bool computeEvaluationOffline, MappingConfiguration::GinkgoParameter ginkgoParameter)
const bool _computeEvaluationOffline
VectorOffsetView _inOffsets
VectorOffsetView _outOffsets
GlobalIDView _globalInIDs
GlobalIDView _globalOutIDs
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.
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.