Documentation 6b54b78464
Loading...
Searching...
No Matches
computeGradientsGreenGauss.hpp
Go to the documentation of this file.
1/*!
2 * \file computeGradientsGreenGauss.hpp
3 * \brief Generic implementation of Green-Gauss gradient computation.
4 * \note This allows the same implementation to be used for conservative
5 * and primitive variables of any solver.
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#include <vector>
31#include <algorithm>
32
33#include "../../../Common/include/parallelization/omp_structure.hpp"
34#include "../../../Common/include/toolboxes/geometry_toolbox.hpp"
36
37namespace detail {
38
39/*!
40 * \brief Compute the gradient of a field using the Green-Gauss theorem.
41 * \ingroup FvmAlgos
42 * \note Template nDim to allow efficient unrolling of inner loops.
43 * \note Gradients can be computed only for a contiguous range of variables, defined
44 * by [varBegin, varEnd[ (e.g. 0,1 computes the gradient of the 1st variable).
45 * This can be used, for example, to compute only velocity gradients.
46 * \note The function uses an optional solver object to perform communications, if
47 * none (nullptr) is provided the function does not fail (the objective of
48 * this is to improve test-ability).
49 * \param[in] solver - Optional, solver associated with the field (used only for MPI).
50 * \param[in] kindMpiComm - Type of MPI communication required.
51 * \param[in] kindPeriodicComm - Type of periodic communication required.
52 * \param[in] geometry - Geometric grid properties.
53 * \param[in] config - Configuration of the problem, used to identify types of boundaries.
54 * \param[in] field - Generic object implementing operator (iPoint, iVar).
55 * \param[in] varBegin - Index of first variable for which to compute the gradient.
56 * \param[in] varEnd - Index of last variable for which to compute the gradient.
57 * \param[in] idxVel - Index of velocity, or -1 if no velocity present.
58 * \param[out] gradient - Generic object implementing operator (iPoint, iVar, iDim).
59 */
60template <size_t nDim, class FieldType, class GradientType>
61void computeGradientsGreenGauss(CSolver* solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm,
62 CGeometry& geometry, const CConfig& config, const FieldType& field,
63 const size_t varBegin, const size_t varEnd, const int idxVel, GradientType& gradient) {
64 const size_t nPointDomain = geometry.GetnPointDomain();
65
66#ifdef HAVE_OMP
67 constexpr size_t OMP_MAX_CHUNK = 512;
68
69 const auto chunkSize = computeStaticChunkSize(nPointDomain, omp_get_max_threads(), OMP_MAX_CHUNK);
70#endif
71
72 static constexpr size_t MAXNVAR = 20;
73
74 /*--- For each (non-halo) volume integrate over its faces (edges). ---*/
75
76 SU2_OMP_FOR_DYN(chunkSize)
77 for (size_t iPoint = 0; iPoint < nPointDomain; ++iPoint) {
78 auto nodes = geometry.nodes;
79
80 /*--- Cannot preaccumulate if hybrid parallel due to shared reading. ---*/
82 AD::SetPreaccIn(nodes->GetVolume(iPoint));
83 AD::SetPreaccIn(nodes->GetPeriodicVolume(iPoint));
84
85 for (size_t iVar = varBegin; iVar < varEnd; ++iVar) AD::SetPreaccIn(field(iPoint, iVar));
86
87 /*--- Clear the gradient. --*/
88
89 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
90 for (size_t iDim = 0; iDim < nDim; ++iDim) gradient(iPoint, iVar, iDim) = 0.0;
91
92 /*--- Handle averaging and division by volume in one constant. ---*/
93
94 su2double halfOnVol = 0.5 / (nodes->GetVolume(iPoint) + nodes->GetPeriodicVolume(iPoint));
95
96 /*--- Add a contribution due to each neighbor. ---*/
97
98 for (size_t iNeigh = 0; iNeigh < nodes->GetnPoint(iPoint); ++iNeigh) {
99 size_t iEdge = nodes->GetEdge(iPoint, iNeigh);
100 size_t jPoint = nodes->GetPoint(iPoint, iNeigh);
101
102 /*--- Determine if edge points inwards or outwards of iPoint.
103 * If inwards we need to flip the area vector. ---*/
104
105 su2double dir = (iPoint < jPoint) ? 1.0 : -1.0;
106 su2double weight = dir * halfOnVol;
107
108 const auto area = geometry.edges->GetNormal(iEdge);
109 AD::SetPreaccIn(area, nDim);
110
111 for (size_t iVar = varBegin; iVar < varEnd; ++iVar) {
112 AD::SetPreaccIn(field(jPoint, iVar));
113 su2double flux = weight * (field(iPoint, iVar) + field(jPoint, iVar));
114
115 for (size_t iDim = 0; iDim < nDim; ++iDim) gradient(iPoint, iVar, iDim) += flux * area[iDim];
116 }
117 }
118
119 for (size_t iVar = varBegin; iVar < varEnd; ++iVar)
120 for (size_t iDim = 0; iDim < nDim; ++iDim) AD::SetPreaccOut(gradient(iPoint, iVar, iDim));
121
123 }
125
126 su2double flux[MAXNVAR] = {0.0};
127
128 /*--- Add edges of markers that contribute to the gradients ---*/
129 for (size_t iMarker = 0; iMarker < geometry.GetnMarker(); ++iMarker) {
130 if ((config.GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
131 (config.GetMarker_All_KindBC(iMarker) != NEARFIELD_BOUNDARY) &&
132 (config.GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
133 /*--- Work is shared in inner loop as two markers
134 * may try to update the same point. ---*/
135
137 for (size_t iVertex = 0; iVertex < geometry.GetnVertex(iMarker); ++iVertex) {
138 size_t iPoint = geometry.vertex[iMarker][iVertex]->GetNode();
139 auto nodes = geometry.nodes;
140
141 /*--- Halo points do not need to be considered. ---*/
142
143 if (!nodes->GetDomain(iPoint)) continue;
144
145 su2double volume = nodes->GetVolume(iPoint) + nodes->GetPeriodicVolume(iPoint);
146 const auto area = geometry.vertex[iMarker][iVertex]->GetNormal();
147
148 for (size_t iVar = varBegin; iVar < varEnd; iVar++)
149 flux[iVar] = field(iPoint,iVar) / volume;
150
151 for (size_t iVar = varBegin; iVar < varEnd; iVar++) {
152 for (size_t iDim = 0; iDim < nDim; iDim++) {
153 gradient(iPoint, iVar, iDim) -= flux[iVar] * area[iDim];
154 }
155 } // loop over variables
156 } // vertices
158 } //found right marker
159 } // iMarkers
160
161
162 /*--- Compute the corrections for symmetry planes and Euler walls. ---*/
163
164 correctGradientsSymmetry<nDim>(geometry, config, varBegin, varEnd, idxVel, gradient);
165
166 /*--- If no solver was provided we do not communicate ---*/
167
168 if (solver == nullptr) return;
169
170 /*--- Account for periodic contributions. ---*/
171
172 for (size_t iPeriodic = 1; iPeriodic <= config.GetnMarker_Periodic() / 2; ++iPeriodic) {
173 solver->InitiatePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm);
174 solver->CompletePeriodicComms(&geometry, &config, iPeriodic, kindPeriodicComm);
175 }
176
177 /*--- Obtain the gradients at halo points from the MPI ranks that own them. ---*/
178
179 solver->InitiateComms(&geometry, &config, kindMpiComm);
180 solver->CompleteComms(&geometry, &config, kindMpiComm);
181}
182} // namespace detail
183
184
185
186/*!
187 * \brief Instantiations for 2D and 3D.
188 * \ingroup FvmAlgos
189 */
190template <class FieldType, class GradientType>
191void computeGradientsGreenGauss(CSolver* solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm,
192 CGeometry& geometry, const CConfig& config, const FieldType& field,
193 const size_t varBegin, const size_t varEnd, const int idxVel, GradientType& gradient) {
194 switch (geometry.GetnDim()) {
195 case 2:
196 detail::computeGradientsGreenGauss<2>(solver, kindMpiComm, kindPeriodicComm, geometry, config, field, varBegin,
197 varEnd, idxVel, gradient);
198 break;
199 case 3:
200 detail::computeGradientsGreenGauss<3>(solver, kindMpiComm, kindPeriodicComm, geometry, config, field, varBegin,
201 varEnd, idxVel, gradient);
202 break;
203 default:
204 SU2_MPI::Error("Too many dimensions to compute gradients.", CURRENT_FUNCTION);
205 break;
206 }
207}
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
unsigned short GetMarker_All_KindBC(unsigned short val_marker) const
Get the kind of boundary for each marker.
Definition CConfig.hpp:3556
void GetNormal(unsigned long iEdge, T &normal) const
Copy the the normal vector of a face.
Definition CEdge.hpp:161
Parent class for defining the geometry of the problem (complete geometry, multigrid agglomerated geom...
Definition CGeometry.hpp:75
unsigned long GetnVertex(unsigned short val_marker) const
Get number of vertices.
Definition CGeometry.hpp:637
CPoint * nodes
Node vector (dual grid information).
Definition CGeometry.hpp:253
CVertex *** vertex
Boundary Vertex vector (dual grid information).
Definition CGeometry.hpp:255
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
unsigned short GetnMarker() const
Get number of markers.
Definition CGeometry.hpp:623
CEdge * edges
Edge vector (dual grid information).
Definition CGeometry.hpp:254
su2double & GetVolume(unsigned long iPoint)
Get area or volume of the control volume.
Definition CPoint.hpp:557
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
void GetNormal(su2double *val_normal) const override
Copy the the normal vector of a face.
Definition CVertex.hpp:94
unsigned long GetNode() const
Get the node of the vertex.
Definition CVertex.hpp:70
passivedouble su2double
Definition code_config.hpp:181
Implements the symmetry boundary conditions for the gradient computations.
void computeGradientsGreenGauss(CSolver *solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm, CGeometry &geometry, const CConfig &config, const FieldType &field, const size_t varBegin, const size_t varEnd, const int idxVel, GradientType &gradient)
Compute the gradient of a field using the Green-Gauss theorem.
Definition computeGradientsGreenGauss.hpp:61
void computeGradientsGreenGauss(CSolver *solver, MPI_QUANTITIES kindMpiComm, PERIODIC_QUANTITIES kindPeriodicComm, CGeometry &geometry, const CConfig &config, const FieldType &field, const size_t varBegin, const size_t varEnd, const int idxVel, GradientType &gradient)
Instantiations for 2D and 3D.
Definition computeGradientsGreenGauss.hpp:191
#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
#define SU2_OMP_FOR_STAT(CHUNK)
Definition omp_structure.hpp:151
@ INTERNAL_BOUNDARY
Internal Boundary definition.
Definition option_structure.hpp:1840
@ NEARFIELD_BOUNDARY
Near-Field boundary definition.
Definition option_structure.hpp:1821
@ PERIODIC_BOUNDARY
Periodic boundary definition.
Definition option_structure.hpp:1820
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