|
37 | 37 | /// \addtogroup SpLinSys |
38 | 38 | /// @{ |
39 | 39 |
|
| 40 | +/*! |
| 41 | + * \brief Applies a preconditioner that only has a host implementation to vectors that live |
| 42 | + * on the device: bring the input down, apply, put the result back. |
| 43 | + * \note This is what keeps ILU, LU-SGS, Linelet and PaStiX usable on the GPU path. The |
| 44 | + * transfers are issued by one thread with the team synchronized around them, the apply |
| 45 | + * itself is the normal OpenMP parallel host code. |
| 46 | + */ |
| 47 | +template <class ScalarType, class Apply> |
| 48 | +inline void ApplyPreconditionerOnHost(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v, Apply&& apply) { |
| 49 | +#ifdef SU2_ENABLE_CUDA_KERNELS |
| 50 | + if constexpr (su2_gpu_capable_v<ScalarType>) { |
| 51 | + if (VecExpr::UseDeviceExpressions()) { |
| 52 | + /*--- The host code must not see the device pointers of any expression it builds, so |
| 53 | + * the switch is flipped for the duration of the apply. It is written inside the |
| 54 | + * regions, by one thread, and published to the team by the trailing barrier. ---*/ |
| 55 | + SU2_DEVICE_REGION(u.DtHTransfer(); VecExpr::SetUseDeviceExpressions(false);) |
| 56 | + |
| 57 | + apply(); |
| 58 | + |
| 59 | + SU2_DEVICE_REGION(VecExpr::SetUseDeviceExpressions(true); v.HtDTransfer();) |
| 60 | + return; |
| 61 | + } |
| 62 | + } |
| 63 | +#endif |
| 64 | + apply(); |
| 65 | +} |
| 66 | + |
40 | 67 | /*! |
41 | 68 | * \class CPreconditioner |
42 | 69 | * \brief Abstract base class for defining a preconditioning operation. |
@@ -77,6 +104,18 @@ class CPreconditioner { |
77 | 104 | template <class ScalarType> |
78 | 105 | CPreconditioner<ScalarType>::~CPreconditioner() {} |
79 | 106 |
|
| 107 | +/*! |
| 108 | + * \class CIdentityPreconditioner |
| 109 | + * \brief No-op preconditioner used when Krylov solvers run without preconditioning. |
| 110 | + */ |
| 111 | +template <class ScalarType> |
| 112 | +class CIdentityPreconditioner final : public CPreconditioner<ScalarType> { |
| 113 | + public: |
| 114 | + inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { v = u; } |
| 115 | + |
| 116 | + inline bool IsIdentity() const override { return true; } |
| 117 | +}; |
| 118 | + |
80 | 119 | /*! |
81 | 120 | * \class CJacobiPreconditioner |
82 | 121 | * \brief Specialization of preconditioner that uses CSysMatrix class. |
@@ -160,7 +199,7 @@ class CILUPreconditioner final : public CPreconditioner<ScalarType> { |
160 | 199 | * \param[out] v - CSysVector that is the result of the preconditioning. |
161 | 200 | */ |
162 | 201 | inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { |
163 | | - sparse_matrix.ComputeILUPreconditioner(u, v, geometry, config); |
| 202 | + ApplyPreconditionerOnHost(u, v, [&] { sparse_matrix.ComputeILUPreconditioner(u, v, geometry, config); }); |
164 | 203 | } |
165 | 204 |
|
166 | 205 | /*! |
@@ -206,7 +245,7 @@ class CLU_SGSPreconditioner final : public CPreconditioner<ScalarType> { |
206 | 245 | * \param[out] v - CSysVector that is the result of the preconditioning. |
207 | 246 | */ |
208 | 247 | inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { |
209 | | - sparse_matrix.ComputeLU_SGSPreconditioner(u, v, geometry, config); |
| 248 | + ApplyPreconditionerOnHost(u, v, [&] { sparse_matrix.ComputeLU_SGSPreconditioner(u, v, geometry, config); }); |
210 | 249 | } |
211 | 250 | }; |
212 | 251 |
|
@@ -234,7 +273,7 @@ class CQuantizedLUSGSPreconditioner final : public CPreconditioner<ScalarType> { |
234 | 273 | CQuantizedLUSGSPreconditioner() = delete; |
235 | 274 |
|
236 | 275 | inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { |
237 | | - sparse_matrix.ComputeLU_SGSPreconditioner(u, v, geometry, config); |
| 276 | + ApplyPreconditionerOnHost(u, v, [&] { sparse_matrix.ComputeLU_SGSPreconditioner(u, v, geometry, config); }); |
238 | 277 | } |
239 | 278 |
|
240 | 279 | /*! \brief Quantize the diagonal blocks (off diagonals are quantized on the fly). */ |
@@ -278,7 +317,7 @@ class CLineletPreconditioner final : public CPreconditioner<ScalarType> { |
278 | 317 | * \param[out] v - CSysVector that is the result of the preconditioning. |
279 | 318 | */ |
280 | 319 | inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { |
281 | | - sparse_matrix.ComputeLineletPreconditioner(u, v, geometry, config); |
| 320 | + ApplyPreconditionerOnHost(u, v, [&] { sparse_matrix.ComputeLineletPreconditioner(u, v, geometry, config); }); |
282 | 321 | } |
283 | 322 |
|
284 | 323 | /*! |
@@ -328,7 +367,7 @@ class CPastixPreconditioner final : public CPreconditioner<ScalarType> { |
328 | 367 | * \param[out] v - CSysVector that is the result of the preconditioning. |
329 | 368 | */ |
330 | 369 | inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { |
331 | | - sparse_matrix.ComputePastixPreconditioner(u, v, geometry, config); |
| 370 | + ApplyPreconditionerOnHost(u, v, [&] { sparse_matrix.ComputePastixPreconditioner(u, v, geometry, config); }); |
332 | 371 | } |
333 | 372 |
|
334 | 373 | /*! |
@@ -363,6 +402,9 @@ CPreconditioner<ScalarType>* CPreconditioner<ScalarType>::Create(ENUM_LINEAR_SOL |
363 | 402 | CPreconditioner<ScalarType>* prec = nullptr; |
364 | 403 |
|
365 | 404 | switch (kind) { |
| 405 | + case IDENTITY: |
| 406 | + prec = new CIdentityPreconditioner<ScalarType>(); |
| 407 | + break; |
366 | 408 | case JACOBI: |
367 | 409 | prec = new CJacobiPreconditioner<ScalarType>(jacobian, geometry, config); |
368 | 410 | break; |
|
0 commit comments