Documentation 6b54b78464
Loading...
Searching...
No Matches
computeLimiters_impl.hpp
Go to the documentation of this file.
1/*!
2 * \file computeLimiters_impl.hpp
3 * \brief Generic computation of limiters.
4 * \note Common methods are derived by defining small details
5 * via specialization of CLimiterDetails.
6 * \author P. Gomes
7 * \version 8.5.0 "Harrier"
8 *
9 * SU2 Project Website: https://su2code.github.io
10 *
11 * The SU2 Project is maintained by the SU2 Foundation
12 * (http://su2foundation.org)
13 *
14 * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md)
15 *
16 * SU2 is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * SU2 is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
28 */
29
30
31/*!
32 * \brief Generic limiter computation for methods based on one limiter
33 * value per point (as opposed to one per edge) and per variable.
34 * \ingroup FvmAlgos
35 * \note This implementation can be used to derive most common methods
36 * by specializing the limiter functions (e.g. Venkatakrishnan)
37 * and the geometric modifications (e.g. sharp edges), this is done
38 * via specialization of "CLimiterDetails" (all its methods). Then,
39 * a call to this function with the specialized "LimiterKind" should
40 * be added to the body of "computeLimiters()".
41 * See also the notes in computeGradientsGreenGauss.hpp
42 *
43 * Arguments:
44 * \param[in] solver - Optional, solver associated with the field (used only for MPI).
45 * \param[in] kindMpiComm - Type of MPI communication required.
46 * \param[in] kindPeriodicComm1 - Type of periodic comm. to determine min/max.
47 * \param[in] kindPeriodicComm2 - Type of periodic comm. to adjust limiters.
48 * \param[in] geometry - Geometric grid properties.
49 * \param[in] config - Configuration of the problem.
50 * \param[in] varBegin - First variable index for which to compute limiters.
51 * \param[in] varEnd - End of computation range (nVar = end-begin).
52 * \param[in] umusclKappa - Blending parameter for U-MUSCL reconstruction.
53 * \param[in] field - Variable field.
54 * \param[in] gradient - Gradient of the field.
55 * \param[out] fieldMin - Minimum field values over direct neighbors of each point.
56 * \param[out] fieldMax - As above but maximum values.
57 * \param[out] limiter - Reconstruction limiter for the field.
58 *
59 * Template parameters:
60 * \param nDim - Number of dimensions.
61 * \param LimiterKind - Used to instantiate the right details class.
62 * \param FieldType - Generic object with operator (iPoint,iVar).
63 * \param GradientType - Generic object with operator (iPoint,iVar,iDim).
64 */
65template<size_t nDim, LIMITER LimiterKind, class FieldType, class GradientType>
67 MPI_QUANTITIES kindMpiComm,
68 PERIODIC_QUANTITIES kindPeriodicComm1,
69 PERIODIC_QUANTITIES kindPeriodicComm2,
70 CGeometry& geometry,
71 const CConfig& config,
72 size_t varBegin,
73 size_t varEnd,
74 su2double umusclKappa,
75 const FieldType& field,
76 const GradientType& gradient,
77 FieldType& fieldMin,
78 FieldType& fieldMax,
79 FieldType& limiter)
80{
81 constexpr size_t MAXNVAR = 32;
82
83 if (varEnd > MAXNVAR)
84 SU2_MPI::Error("Number of variables is too large, increase MAXNVAR.", CURRENT_FUNCTION);
85
86 const size_t nPointDomain = geometry.GetnPointDomain();
87 const size_t nPoint = geometry.GetnPoint();
88
89 /*--- If we do not have periodicity we can use a
90 * more efficient access pattern to memory. ---*/
91
92 const bool periodic = (solver != nullptr) &&
93 (kindPeriodicComm1 != PERIODIC_NONE) &&
94 (config.GetnMarker_Periodic() > 0);
95
96#ifdef HAVE_OMP
97 constexpr size_t OMP_MAX_CHUNK = 512;
98
99 const auto chunkSize = computeStaticChunkSize(nPointDomain, omp_get_max_threads(), OMP_MAX_CHUNK);
100#endif
101
102 /*--- If limiters are frozen do not record the computation ---*/
103 bool wasActive = false;
104 if (config.GetDiscrete_Adjoint() && config.GetFrozen_Limiter_Disc()) {
105 wasActive = AD::BeginPassive();
106 }
107
108 CLimiterDetails<LimiterKind> limiterDetails;
109
110 limiterDetails.preprocess(geometry, config, varBegin, varEnd, field);
111
112 /*--- With rotational periodicity, the first periodic comm. also brings the min/max
113 * projections over the edges of the periodic matches (stored after each other),
114 * because the limiters of the velocity cannot be compared across a rotation. ---*/
115
116 su2activematrix* periodicProj = nullptr;
117
118 if (periodic && (kindPeriodicComm1 == PERIODIC_LIM_PRIM_1))
119 periodicProj = solver->GetPeriodicProjections(geometry, config);
120
121 /*--- Initialize all min/max field values if we have
122 * periodic comms. otherwise do it inside main loop. ---*/
123
124 if (periodic)
125 {
126 if (periodicProj != nullptr)
127 {
128 SU2_OMP_FOR_STAT(chunkSize)
129 for (auto iPoint = 0ul; iPoint < periodicProj->rows(); ++iPoint)
130 for (auto iVar = 0ul; iVar < periodicProj->cols(); ++iVar)
131 (*periodicProj)(iPoint,iVar) = 0.0;
133 }
134
135 SU2_OMP_FOR_STAT(chunkSize)
136 for (size_t iPoint = 0; iPoint < nPoint; ++iPoint)
137 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
138 fieldMax(iPoint,iVar) = fieldMin(iPoint,iVar) = field(iPoint,iVar);
140
141 for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic)
142 {
143 solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1);
144 solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm1);
145 }
146 }
147
148 /*--- Compute limiter for each point. ---*/
149
150 SU2_OMP_FOR_DYN(chunkSize)
151 for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint)
152 {
153 auto nodes = geometry.nodes;
154 const auto coord_i = nodes->GetCoord(iPoint);
155
156 /*--- Cannot preaccumulate if hybrid parallel due to shared reading. ---*/
158 AD::SetPreaccIn(coord_i, nDim);
159
160 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
161 {
162 AD::SetPreaccIn(field(iPoint,iVar));
163
164 if (periodic) {
165 /*--- Started outside loop, so counts as input. ---*/
166 AD::SetPreaccIn(fieldMax(iPoint,iVar));
167 AD::SetPreaccIn(fieldMin(iPoint,iVar));
168 }
169 else {
170 /*--- Initialize min/max now for iPoint if not periodic. ---*/
171 fieldMax(iPoint,iVar) = field(iPoint,iVar);
172 fieldMin(iPoint,iVar) = field(iPoint,iVar);
173 }
174
175 for(size_t iDim = 0; iDim < nDim; ++iDim)
176 AD::SetPreaccIn(gradient(iPoint,iVar,iDim));
177 }
178
179 /*--- Initialize min/max projection out of iPoint. ---*/
180
181 su2double projMax[MAXNVAR], projMin[MAXNVAR];
182
183 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
184 projMax[iVar] = projMin[iVar] = 0.0;
185
186 if (periodicProj != nullptr && nodes->GetPeriodicBoundary(iPoint))
187 {
188 /*--- Start from the min/max over the edges of the periodic matches. ---*/
189
190 const auto* projections = solver->GetPeriodicProjection(iPoint);
191 if (projections != nullptr) {
192 for (auto iVar = varBegin; iVar < varEnd; ++iVar) {
193 const auto& periodicMin = projections[iVar];
194 const auto& periodicMax = projections[periodicProj->cols()/2 + iVar];
195 AD::SetPreaccIn(periodicMin);
196 AD::SetPreaccIn(periodicMax);
197 projMin[iVar] = periodicMin;
198 projMax[iVar] = periodicMax;
199 }
200 }
201 }
202
203 /*--- Compute max/min projection and values over direct neighbors. ---*/
204
205 for (auto jPoint : geometry.nodes->GetPoints(iPoint)) {
206
207 const auto coord_j = geometry.nodes->GetCoord(jPoint);
208 AD::SetPreaccIn(coord_j, nDim);
209
210 /*--- Distance vector from iPoint to face (middle of the edge). ---*/
211
212 su2double dist_ij[nDim] = {0.0};
213 for (size_t iDim = 0; iDim < nDim; ++iDim)
214 dist_ij[iDim] = 0.5 * (coord_j[iDim] - coord_i[iDim]);
215
216 /*--- Project each variable, update min/max. ---*/
217
218 for(size_t iVar = varBegin; iVar < varEnd; ++iVar)
219 {
220 AD::SetPreaccIn(field(jPoint,iVar));
221 const su2double proj = LimiterHelpers<>::reconstructionIncrement(nDim, dist_ij,
222 gradient[iPoint][iVar], field(iPoint,iVar), field(jPoint,iVar), umusclKappa);
223
224 projMax[iVar] = max(projMax[iVar], proj);
225 projMin[iVar] = min(projMin[iVar], proj);
226
227 fieldMax(iPoint,iVar) = max(fieldMax(iPoint,iVar), field(jPoint,iVar));
228 fieldMin(iPoint,iVar) = min(fieldMin(iPoint,iVar), field(jPoint,iVar));
229 }
230 }
231
232 /*--- Compute the geometric factor. ---*/
233
234 su2double geoFactor = limiterDetails.geometricFactor(iPoint, geometry);
235
236 /*--- Final limiter computation for each variable, get the min limiter
237 * out of the positive/negative projections and deltas. ---*/
238
239 for(size_t iVar = varBegin; iVar < varEnd; ++iVar)
240 {
241 su2double limMax = limiterDetails.limiterFunction(iVar, projMax[iVar],
242 fieldMax(iPoint,iVar) - field(iPoint,iVar));
243
244 su2double limMin = limiterDetails.limiterFunction(iVar, projMin[iVar],
245 fieldMin(iPoint,iVar) - field(iPoint,iVar));
246
247 limiter(iPoint,iVar) = geoFactor * min(limMax, limMin);
248
249 AD::SetPreaccOut(limiter(iPoint,iVar));
250 }
251
253 }
255
256 /*--- Account for periodic effects, take the minimum limiter on each periodic pair
257 * (except for the velocity with rotational periodicity). ---*/
258 if (periodic)
259 {
260 for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic()/2; ++iPeriodic)
261 {
262 solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm2);
263 solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm2);
264 }
265 }
266
267 /*--- Obtain the limiters at halo points from the MPI ranks that own them.
268 * If no solver was provided we do not communicate. ---*/
269 if (solver != nullptr)
270 {
271 solver->InitiateComms(&geometry, &config, kindMpiComm);
272 solver->CompleteComms(&geometry, &config, kindMpiComm);
273 }
274
275 AD::EndPassive(wasActive);
276
277}
A templated matrix/vector-like object.
Definition C2DContainer.hpp:374
Index_t cols() const noexcept
Definition C2DContainer.hpp:222
Index_t rows() const noexcept
Definition C2DContainer.hpp:222
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
bool GetFrozen_Limiter_Disc(void) const
Provides information about the way in which the limiter will be treated by the disc....
Definition CConfig.hpp:5223
unsigned short GetnMarker_Periodic(void) const
Get the total number of periodic markers.
Definition CConfig.hpp:3309
bool GetDiscrete_Adjoint(void) const
Get the indicator whether we are solving an discrete adjoint problem.
Definition CConfig.hpp:9299
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
Definition CGeometry.hpp:75
unsigned long GetnPoint() const
Get number of points.
Definition CGeometry.hpp:587
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
const CCompressedSparsePatternUL & GetPoints() const
Get the entire point adjacency information in compressed format (CSR).
Definition CPoint.hpp:241
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
su2double * GetPeriodicProjection(unsigned long iPoint)
Reconstruction increment bounds for a periodic receive point, nullptr for other points.
Definition CSolver.hpp:4249
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
su2activematrix * GetPeriodicProjections(const CGeometry &geometry, const CConfig &config)
Storage for the limiters with rotational periodicity: the min and max, over the edges of the periodic...
Definition CSolver.cpp:351
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
passivedouble su2double
Definition code_config.hpp:181
void computeLimiters_impl(CSolver *solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm1, PERIODIC_QUANTITIES kindPeriodicComm2, CGeometry &geometry, const CConfig &config, size_t varBegin, size_t varEnd, su2double umusclKappa, const FieldType &field, const GradientType &gradient, FieldType &fieldMin, FieldType &fieldMax, FieldType &limiter)
Generic limiter computation for methods based on one limiter value per point (as opposed to one per e...
Definition computeLimiters_impl.hpp:66
#define CURRENT_FUNCTION
Definition mpi_structure.hpp:59
bool BeginPassive()
Start a passive region, i.e. stop recording.
Definition ad_structure.hpp:381
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
void EndPassive(bool wasActive)
End a passive region, i.e. start recording if we were recording before.
Definition ad_structure.hpp:387
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
#define SU2_OMP_FOR_STAT(CHUNK)
Definition omp_structure.hpp:151
PERIODIC_QUANTITIES
Vertex-based quantities exchanged during periodic marker communications.
Definition option_structure.hpp:2843
@ PERIODIC_NONE
No periodic communication required.
Definition option_structure.hpp:2844
@ PERIODIC_LIM_PRIM_1
Primitive limiter communication phase 1 of 2 (periodic only).
Definition option_structure.hpp:2865
MPI_QUANTITIES
Vertex-based quantities exchanged in MPI point-to-point communications.
Definition option_structure.hpp:2873
A traits class for limiters, see notes for "computeLimiters_impl()".
Definition CLimiterDetails.hpp:39
su2double geometricFactor(size_t iPoint, CGeometry &) const
Geometric modifier (e.g. increase limiting near sharp edges).
void preprocess(CGeometry &, CConfig &, size_t varBegin, size_t varEnd, const FieldType &)
Compute any global value that may be needed by the other functions.
su2double limiterFunction(size_t iVar, su2double proj, su2double delta) const
Smooth (usually) function of the maximum/minimum (positive/negative) gradient projections onto the ed...
static FORCEINLINE Type reconstructionIncrement(Int nDim, const Type *halfEdge, const Type *gradient, const Type &value_i, const Type &value_j, const Type &kappa)
MUSCL reconstruction increment using the displacement to the middle of an edge.
Definition CLimiterDetails.hpp:77