Documentation 6b54b78464
Loading...
Searching...
No Matches
computeGradientsLeastSquares.hpp
Go to the documentation of this file.
1/*!
2 * \file computeGradientsLeastSquares.hpp
3 * \brief Generic implementation of Least-Squares gradient computation.
4 * \note This allows the same implementation to be used for conservative
5 * and primitive variables of any solver.
6 * \version 8.5.0 "Harrier"
7 *
8 * SU2 Project Website: https://su2code.github.io
9 *
10 * The SU2 Project is maintained by the SU2 Foundation
11 * (http://su2foundation.org)
12 *
13 * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md)
14 *
15 * SU2 is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * SU2 is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
27 */
28
29#include "../../../Common/include/parallelization/omp_structure.hpp"
30#include "../../../Common/include/toolboxes/geometry_toolbox.hpp"
32
33namespace detail {
34
35/*!
36 * \brief Prepare Smatrix for 2D.
37 * \ingroup FvmAlgos
38 */
40 su2double r22, su2double r23, su2double r33,
41 su2double detR2, su2double Smatrix[][2]) {
42 Smatrix[0][0] = (r12*r12+r22*r22)/detR2;
43 Smatrix[0][1] = -r11*r12/detR2;
44 Smatrix[1][1] = r11*r11/detR2;
45}
46
47/*!
48 * \brief Prepare Smatrix for 3D.
49 * \ingroup FvmAlgos
50 */
52 su2double r22, su2double r23, su2double r33,
53 su2double detR2, su2double Smatrix[][3]) {
54 su2double z11 = r22*r33;
55 su2double z12 =-r12*r33;
56 su2double z13 = r12*r23-r13*r22;
57 su2double z22 = r11*r33;
58 su2double z23 =-r11*r23;
59 su2double z33 = r11*r22;
60
61 Smatrix[0][0] = (z11*z11+z12*z12+z13*z13)/detR2;
62 Smatrix[0][1] = (z12*z22+z13*z23)/detR2;
63 Smatrix[0][2] = (z13*z33)/detR2;
64 Smatrix[1][1] = (z22*z22+z23*z23)/detR2;
65 Smatrix[1][2] = (z23*z33)/detR2;
66 Smatrix[2][2] = (z33*z33)/detR2;
67}
68
69/*!
70 * \brief Solve the least-squares problem for one point.
71 * \ingroup FvmAlgos
72 * \note See detail::computeGradientsLeastSquares for the
73 * purpose of template "nDim" and "periodic".
74 */
75template<size_t nDim, bool periodic, class GradientType, class RMatrixType>
76FORCEINLINE void solveLeastSquares(size_t iPoint,
77 size_t varBegin,
78 size_t varEnd,
79 const RMatrixType& Rmatrix,
80 GradientType& gradient)
81{
82 const auto eps = pow(std::numeric_limits<passivedouble>::epsilon(),2);
83
84 /*--- Entries of upper triangular matrix R. ---*/
85
86 if (periodic) {
88 AD::SetPreaccIn(Rmatrix(iPoint,0,0));
89 AD::SetPreaccIn(Rmatrix(iPoint,0,1));
90 AD::SetPreaccIn(Rmatrix(iPoint,1,1));
91 }
92
93 su2double r11 = Rmatrix(iPoint,0,0);
94 su2double r12 = Rmatrix(iPoint,0,1);
95 su2double r22 = Rmatrix(iPoint,1,1);
96 su2double r13 = 0.0, r23 = 0.0, r33 = 1.0;
97
98 r11 = sqrt(max(r11, eps));
99 r12 /= r11;
100 r22 = sqrt(max(r22 - r12*r12, eps));
101
102 if (nDim == 3) {
103 if (periodic) {
104 AD::SetPreaccIn(Rmatrix(iPoint,0,2));
105 AD::SetPreaccIn(Rmatrix(iPoint,1,2));
106 AD::SetPreaccIn(Rmatrix(iPoint,2,1));
107 AD::SetPreaccIn(Rmatrix(iPoint,2,2));
108 }
109
110 r13 = Rmatrix(iPoint,0,2);
111 r33 = Rmatrix(iPoint,2,2);
112 const auto r23_a = Rmatrix(iPoint,1,2);
113 const auto r23_b = Rmatrix(iPoint,2,1);
114
115 r13 /= r11;
116 r23 = r23_a/r22 - r23_b*r12/(r11*r22);
117 r33 = sqrt(max(r33 - r23*r23 - r13*r13, eps));
118 }
119
120 /*--- Compute determinant ---*/
121
122 const su2double detR2 = pow(r11*r22*r33, 2);
123
124 /*--- S matrix := inv(R)*traspose(inv(R)) ---*/
125
126 su2double Smatrix[nDim][nDim] = {{0.0}};
127
128 /*--- Detect singular matrix ---*/
129
130 if (detR2 > eps) {
131 computeSmatrix(r11, r12, r13, r22, r23, r33, detR2, Smatrix);
132 }
133
134 if (periodic) {
135 /*--- Stop preacc here as gradient is in/out. ---*/
136 for (size_t iDim = 0; iDim < nDim; ++iDim)
137 for (size_t jDim = iDim; jDim < nDim; ++jDim)
138 AD::SetPreaccOut(Smatrix[iDim][jDim]);
140 }
141
142 /*--- Computation of the gradient: S*c ---*/
143
144 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
145 {
146 su2double Cvector[nDim] = {0.0};
147
148 for (size_t iDim = 0; iDim < nDim; ++iDim)
149 for (size_t jDim = 0; jDim < nDim; ++jDim)
150 Cvector[iDim] += Smatrix[min(iDim,jDim)][max(iDim,jDim)] * gradient(iPoint, iVar, jDim);
151
152 for (size_t iDim = 0; iDim < nDim; ++iDim)
153 gradient(iPoint, iVar, iDim) = Cvector[iDim];
154 }
155
156 if (!periodic) {
157 /*--- Stop preacc here instead as gradient is only out. ---*/
158 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
159 for (size_t iDim = 0; iDim < nDim; ++iDim)
160 AD::SetPreaccOut(gradient(iPoint, iVar, iDim));
162 }
163}
164
165/*!
166 * \brief Compute the gradient of a field using inverse-distance-weighted or
167 * unweighted Least-Squares approximation.
168 * \ingroup FvmAlgos
169 * \note See notes from computeGradientsGreenGauss.hpp.
170 * \param[in] solver - Optional, solver associated with the field (used only for MPI).
171 * \param[in] kindMpiComm - Type of MPI communication required.
172 * \param[in] kindPeriodicComm - Type of periodic communication required.
173 * \param[in] geometry - Geometric grid properties.
174 * \param[in] weighted - Use inverse-distance weights.
175 * \param[in] config - Configuration of the problem, used to identify types of boundaries.
176 * \param[in] field - Generic object implementing operator (iPoint, iVar).
177 * \param[in] varBegin - Index of first variable for which to compute the gradient.
178 * \param[in] varEnd - Index of last variable for which to compute the gradient.
179 * \param[in] idxVel - Index to velocity, -1 if no velocity is present in the solver.
180 * \param[out] gradient - Generic object implementing operator (iPoint, iVar, iDim).
181 * \param[out] Rmatrix - Generic object implementing operator (iPoint, iDim, iDim).
182 */
183template<size_t nDim, class FieldType, class GradientType, class RMatrixType>
185 MPI_QUANTITIES kindMpiComm,
186 PERIODIC_QUANTITIES kindPeriodicComm,
187 CGeometry& geometry,
188 const CConfig& config,
189 bool weighted,
190 const FieldType& field,
191 const size_t varBegin,
192 const size_t varEnd,
193 const int idxVel,
194 GradientType& gradient,
195 RMatrixType& Rmatrix)
196{
197 const bool periodic = (solver != nullptr) && (config.GetnMarker_Periodic() > 0);
198
199 const size_t nPointDomain = geometry.GetnPointDomain();
200
201#ifdef HAVE_OMP
202 constexpr size_t OMP_MAX_CHUNK = 512;
203
204 size_t chunkSize = computeStaticChunkSize(nPointDomain,
205 omp_get_max_threads(), OMP_MAX_CHUNK);
206#endif
207
208 /*--- First loop over non-halo points of the grid. ---*/
209
210 SU2_OMP_FOR_DYN(chunkSize)
211 for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint)
212 {
213 auto nodes = geometry.nodes;
214 const auto coord_i = nodes->GetCoord(iPoint);
215
216 /*--- Cannot preaccumulate if hybrid parallel due to shared reading. ---*/
218 AD::SetPreaccIn(coord_i, nDim);
219
220 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
221 AD::SetPreaccIn(field(iPoint,iVar));
222
223 /*--- Clear gradient and Rmatrix. ---*/
224
225 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
226 for (size_t iDim = 0; iDim < nDim; ++iDim)
227 gradient(iPoint, iVar, iDim) = 0.0;
228
229 for (size_t iDim = 0; iDim < nDim; ++iDim)
230 for (size_t jDim = 0; jDim < nDim; ++jDim)
231 Rmatrix(iPoint, iDim, jDim) = 0.0;
232
233
234 for (auto jPoint : nodes->GetPoints(iPoint))
235 {
236 const auto coord_j = geometry.nodes->GetCoord(jPoint);
237 AD::SetPreaccIn(coord_j, nDim);
238
239
240 /*--- Distance vector from iPoint to jPoint ---*/
241
242 su2double dist_ij[nDim] = {0.0};
243 GeometryToolbox::Distance(nDim, coord_j, coord_i, dist_ij);
244
245
246 /*--- Compute inverse weight, default 1 (unweighted). ---*/
247
248 su2double weight = 1.0;
249 if(weighted) weight = GeometryToolbox::SquaredNorm(nDim, dist_ij);
250
251 /*--- Summations for entries of upper triangular matrix R. ---*/
252
253 if (weight > 0.0)
254 {
255 weight = 1.0 / weight;
256
257 for (size_t iDim = 0; iDim < nDim; ++iDim)
258 for (size_t jDim = iDim; jDim < nDim; ++jDim)
259 Rmatrix(iPoint,iDim,jDim) += dist_ij[iDim]*dist_ij[jDim]*weight;
260
261 if (nDim == 3)
262 Rmatrix(iPoint,2,1) += dist_ij[0]*dist_ij[nDim-1]*weight;
263
264 /*--- Entries of c:= transpose(A)*b ---*/
265
266 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
267 {
268 AD::SetPreaccIn(field(jPoint,iVar));
269
270 su2double delta_ij = weight * (field(jPoint,iVar) - field(iPoint,iVar));
271
272 for (size_t iDim = 0; iDim < nDim; ++iDim)
273 gradient(iPoint, iVar, iDim) += dist_ij[iDim] * delta_ij;
274 }
275 }
276 }
277
278 if (periodic)
279 {
280 /*--- A second loop is required after periodic comms, checkpoint the preacc. ---*/
281
282 for (size_t iDim = 0; iDim < nDim; ++iDim)
283 for (size_t jDim = 0; jDim < nDim; ++jDim)
284 AD::SetPreaccOut(Rmatrix(iPoint, iDim, jDim));
285
286 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
287 for (size_t iDim = 0; iDim < nDim; ++iDim)
288 AD::SetPreaccOut(gradient(iPoint, iVar, iDim));
289
291 }
292 else {
293 /*--- Periodic comms are not needed, solve the LS problem for iPoint. ---*/
294
295 solveLeastSquares<nDim, false>(iPoint, varBegin, varEnd, Rmatrix, gradient);
296 }
297 }
299
300 /*--- Correct the gradient values across any periodic boundaries. ---*/
301
302 if (periodic)
303 {
304 for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic)
305 {
306 solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm);
307 solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm);
308 }
309
310 /*--- Second loop over points of the grid to compute final gradient. ---*/
311
312 SU2_OMP_FOR_DYN(chunkSize)
313 for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint)
314 solveLeastSquares<nDim, true>(iPoint, varBegin, varEnd, Rmatrix, gradient);
316 }
317
318 /* --- compute the corrections for symmetry planes and Euler walls. --- */
319
320 correctGradientsSymmetry<nDim>(geometry, config, varBegin, varEnd, idxVel, gradient);
321
322 /*--- If no solver was provided we do not communicate ---*/
323
324 if (solver != nullptr)
325 {
326 /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/
327
328 solver->InitiateComms(&geometry, &config, kindMpiComm);
329 solver->CompleteComms(&geometry, &config, kindMpiComm);
330 }
331
332}
333} // end namespace
334
335/*!
336 * \brief Instantiations for 2D and 3D.
337 * \ingroup FvmAlgos
338 */
339template<class FieldType, class GradientType, class RMatrixType>
341 MPI_QUANTITIES kindMpiComm,
342 PERIODIC_QUANTITIES kindPeriodicComm,
343 CGeometry& geometry,
344 const CConfig& config,
345 bool weighted,
346 const FieldType& field,
347 const size_t varBegin,
348 const size_t varEnd,
349 const int idxVel,
350 GradientType& gradient,
351 RMatrixType& Rmatrix) {
352 switch (geometry.GetnDim()) {
353 case 2:
354 detail::computeGradientsLeastSquares<2>(solver, kindMpiComm, kindPeriodicComm, geometry, config,
355 weighted, field, varBegin, varEnd, idxVel, gradient, Rmatrix);
356 break;
357 case 3:
358 detail::computeGradientsLeastSquares<3>(solver, kindMpiComm, kindPeriodicComm, geometry, config,
359 weighted, field, varBegin, varEnd, idxVel, gradient, Rmatrix);
360 break;
361 default:
362 SU2_MPI::Error("Too many dimensions to compute gradients.", CURRENT_FUNCTION);
363 break;
364 }
365}
static void Error(const std::string &ErrorMsg, const std::string &FunctionName)
Definition mpi_structure.cpp:131
Main class for defining the problem; basically this class reads the configuration file,...
Definition CConfig.hpp:64
unsigned short GetnMarker_Periodic(void) const
Get the total number of periodic markers.
Definition CConfig.hpp:3309
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
Definition CGeometry.hpp:75
CPoint * nodes
Node vector (dual grid information).
Definition CGeometry.hpp:253
unsigned long GetnPointDomain() const
Get number of real points (that belong to the domain).
Definition CGeometry.hpp:593
unsigned short GetnDim() const
Get number of coordinates.
Definition CGeometry.hpp:575
su2double GetCoord(unsigned long iPoint, unsigned long iDim) const
Get the coordinates dor the control volume.
Definition CPoint.hpp:158
Definition CSolver.hpp:71
void InitiatePeriodicComms(CGeometry *geometry, const CConfig *config, unsigned short val_periodic_index, unsigned short commType)
Routine to load a solver quantity into the data structures for MPI periodic communication and to laun...
Definition CSolver.cpp:368
void CompleteComms(CGeometry *geometry, const CConfig *config, MPI_QUANTITIES commType)
Routine to complete the set of non-blocking communications launched by InitiateComms() and unpacking ...
Definition CSolver.cpp:1724
void CompletePeriodicComms(CGeometry *geometry, const CConfig *config, unsigned short val_periodic_index, unsigned short commType)
Routine to complete the set of non-blocking periodic communications launched by InitiatePeriodicComms...
Definition CSolver.cpp:1113
void InitiateComms(CGeometry *geometry, const CConfig *config, MPI_QUANTITIES commType)
Routine to load a solver quantity into the data structures for MPI point-to-point communication and t...
Definition CSolver.cpp:1563
#define FORCEINLINE
Definition code_config.hpp:44
passivedouble su2double
Definition code_config.hpp:181
Implements the symmetry boundary conditions for the gradient computations.
void computeGradientsLeastSquares(CSolver *solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm, CGeometry &geometry, const CConfig &config, bool weighted, const FieldType &field, const size_t varBegin, const size_t varEnd, const int idxVel, GradientType &gradient, RMatrixType &Rmatrix)
Compute the gradient of a field using inverse-distance-weighted or unweighted Least-Squares approxima...
Definition computeGradientsLeastSquares.hpp:184
void solveLeastSquares(size_t iPoint, size_t varBegin, size_t varEnd, const RMatrixType &Rmatrix, GradientType &gradient)
Solve the least-squares problem for one point.
Definition computeGradientsLeastSquares.hpp:76
void computeSmatrix(su2double r11, su2double r12, su2double r13, su2double r22, su2double r23, su2double r33, su2double detR2, su2double Smatrix[][2])
Prepare Smatrix for 2D.
Definition computeGradientsLeastSquares.hpp:39
void computeGradientsLeastSquares(CSolver *solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm, CGeometry &geometry, const CConfig &config, bool weighted, const FieldType &field, const size_t varBegin, const size_t varEnd, const int idxVel, GradientType &gradient, RMatrixType &Rmatrix)
Instantiations for 2D and 3D.
Definition computeGradientsLeastSquares.hpp:340
T Distance(Int nDim, const T *a, const U *b)
Definition geometry_toolbox.hpp:46
T SquaredNorm(Int nDim, const T *a)
Definition geometry_toolbox.hpp:73
FORCEINLINE ARRAY_T sqrt(const ARRAY_T &x)
Definition special_vectorization.hpp:116
FORCEINLINE ARRAY_T pow(const ARRAY_T &a, const ARRAY_T &b)
Definition special_vectorization.hpp:179
#define CURRENT_FUNCTION
Definition mpi_structure.hpp:59
void StartPreacc()
Starts a new preaccumulation section and sets the input variables.
Definition ad_structure.hpp:215
void EndPreacc()
Ends a preaccumulation section and computes the local Jacobi matrix of a code section using the varia...
Definition ad_structure.hpp:243
void SetPreaccOut(Ts &&... data)
Sets the scalar outputs of a preaccumulation section.
Definition ad_structure.hpp:222
void SetPreaccIn(Ts &&... data)
Sets the scalar inputs of a preaccumulation section.
Definition ad_structure.hpp:186
Definition computeGradientsGreenGauss.hpp:37
constexpr int omp_get_num_threads()
Number of threads in current team.
Definition omp_structure.hpp:75
#define END_SU2_OMP_FOR
Definition omp_structure.hpp:158
constexpr int omp_get_max_threads()
Maximum number of threads available.
Definition omp_structure.hpp:70
size_t computeStaticChunkSize(size_t totalWork, size_t numThreads, size_t maxChunkSize)
Compute a chunk size based on totalWork and number of threads such that all threads get the same numb...
Definition omp_structure.hpp:223
#define SU2_OMP_FOR_DYN(CHUNK)
Definition omp_structure.hpp:150
PERIODIC_QUANTITIES
Vertex-based quantities exchanged during periodic marker communications.
Definition option_structure.hpp:2843
MPI_QUANTITIES
Vertex-based quantities exchanged in MPI point-to-point communications.
Definition option_structure.hpp:2873