Documentation 6b54b78464
Loading...
Searching...
No Matches
CFVMFlowSolverBase.inl
Go to the documentation of this file.
1/*!
2 * \file CFVMFlowSolverBase.inl
3 * \brief Base class template for all FVM flow solvers.
4 * \version 8.5.0 "Harrier"
5 *
6 * SU2 Project Website: https://su2code.github.io
7 *
8 * The SU2 Project is maintained by the SU2 Foundation
9 * (http://su2foundation.org)
10 *
11 * Copyright 2012-2026, SU2 Contributors (cf. AUTHORS.md)
12 *
13 * SU2 is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU Lesser General Public
15 * License as published by the Free Software Foundation; either
16 * version 2.1 of the License, or (at your option) any later version.
17 *
18 * SU2 is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 * Lesser General Public License for more details.
22 *
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with SU2. If not, see <http://www.gnu.org/licenses/>.
25 */
26
27#pragma once
28
29#include "../gradients/computeGradientsGreenGauss.hpp"
30#include "../gradients/computeGradientsLeastSquares.hpp"
31#include "../limiters/computeLimiters.hpp"
32#include "../numerics_simd/CNumericsSIMD.hpp"
34
35template <class V, ENUM_REGIME R>
37 _size = size;
38 CD = new su2double[size];
39 CL = new su2double[size];
40 CSF = new su2double[size];
41 CEff = new su2double[size];
42 CFx = new su2double[size];
43 CFy = new su2double[size];
44 CFz = new su2double[size];
45 CMx = new su2double[size];
46 CMy = new su2double[size];
47 CMz = new su2double[size];
48 CoPx = new su2double[size];
49 CoPy = new su2double[size];
50 CoPz = new su2double[size];
51 CT = new su2double[size];
52 CQ = new su2double[size];
53 CMerit = new su2double[size];
54 setZero();
55}
56
57template <class V, ENUM_REGIME R>
59 delete[] CD;
60 delete[] CL;
61 delete[] CSF;
62 delete[] CEff;
63 delete[] CFx;
64 delete[] CFy;
65 delete[] CFz;
66 delete[] CMx;
67 delete[] CMy;
68 delete[] CMz;
69 delete[] CoPx;
70 delete[] CoPy;
71 delete[] CoPz;
72 delete[] CT;
73 delete[] CQ;
74 delete[] CMerit;
75}
76
77template <class V, ENUM_REGIME R>
80
81 /*--- Define some auxiliar vector related with the residual ---*/
82
83 Residual_RMS.resize(nVar,0.0);
84 Residual_Max.resize(nVar,0.0);
85 Point_Max.resize(nVar,0);
87
88 /*--- Define some auxiliar vector related with the undivided lapalacian computation ---*/
89
91 config.GetKind_Upwind_Flow() == UPWIND::MSW) {
94 }
95
96 /*--- Initialize the solution and right hand side vectors for storing
97 the residuals and updating the solution (always needed even for
98 explicit schemes). ---*/
99
100 LinSysSol.Initialize(nPoint, nPointDomain, nVar, 0.0);
101 LinSysRes.Initialize(nPoint, nPointDomain, nVar, 0.0);
102
103 /*--- LinSysSol will always be init to 0. ---*/
104 System.SetxIsZero(true);
105
106 /*--- Store the value of the characteristic primitive variables at the boundaries ---*/
107
109
110 /*--- Store the value of the Total Pressure at the inlet BC ---*/
111
113
114 /*--- Store the value of the Total Temperature at the inlet BC ---*/
115
117
118 /*--- Store the value of the Flow direction at the inlet BC ---*/
119
121
122 /*--- Force definition and coefficient arrays for all of the markers ---*/
123
126
127 /*--- Non dimensional aerodynamic coefficients ---*/
128
136
137 /*--- Heat flux coefficients. ---*/
138
139 HF_Visc.resize(nMarker,0.0);
140 MaxHF_Visc.resize(nMarker,0.0);
141
142 Surface_HF_Visc.resize(config.GetnMarker_Monitoring());
144
145 /*--- Supersonic coefficients ---*/
146
147 CNearFieldOF_Inv.resize(nMarker,0.0);
148
149 /*--- Initializate quantities for SlidingMesh Interface ---*/
150
151 SlidingState.resize(nMarker);
153
154 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
155 if (config.GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) {
156 SlidingState[iMarker].resize(nVertex[iMarker], nPrimVar+1) = nullptr;
157 SlidingStateNodes[iMarker].resize(nVertex[iMarker],0);
158 }
159 }
160
161 /*--- Heat flux in all the markers ---*/
162
165
166 /*--- Y plus in all the markers ---*/
167
169
170 /*--- U Tau in all the markers ---*/
171
173
174 /*--- wall eddy viscosity in all the markers ---*/
175
177
178 /*--- Skin friction in all the markers ---*/
179
181
182 /*--- Wall Shear Stress in all the markers ---*/
183
185
186 /*--- Store the values of the temperature and the heat flux density at the boundaries,
187 used for coupling with a solid donor cell ---*/
188 constexpr auto nHeatConjugateVar = 4u;
190
191 if (MGLevel == MESH_0) {
192 auto nSolidVertex = nVertex;
193 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++)
194 if (!config.GetSolid_Wall(iMarker))
195 nSolidVertex[iMarker] = 0;
196
198
200 }
201
202 /*--- Initialize the BGS residuals in FSI problems. ---*/
203 if (config.GetMultizone_Residual()) {
204 Residual_BGS.resize(nVar,1.0);
205 Residual_Max_BGS.resize(nVar,1.0);
206 Point_Max_BGS.resize(nVar,0);
208 }
209}
210
211template <class V, ENUM_REGIME R>
214
215 /*--- Define some auxiliary vectors related to the residual ---*/
216
217 Residual = new su2double[nVar]();
218 Res_Conv = new su2double[nVar]();
219 Res_Visc = new su2double[nVar]();
220 Res_Sour = new su2double[nVar]();
221
222 /*--- Define some auxiliary vectors related to the solution ---*/
223
224 Solution = new su2double[nVar]();
225 Solution_i = new su2double[nVar]();
226 Solution_j = new su2double[nVar]();
227
228 /*--- Define some auxiliary vectors related to the geometry ---*/
229
230 Vector = new su2double[nDim]();
231 Vector_i = new su2double[nDim]();
232 Vector_j = new su2double[nDim]();
233
234 /*--- Jacobian temporaries. ---*/
235
236 Jacobian_i = new su2double*[nVar];
237 Jacobian_j = new su2double*[nVar];
238 for (auto iVar = 0u; iVar < nVar; iVar++) {
239 Jacobian_i[iVar] = new su2double[nVar];
240 Jacobian_j[iVar] = new su2double[nVar];
241 }
242}
243
244template <class V, ENUM_REGIME R>
247
248 /*--- Define solver parameters needed for execution of destructor ---*/
249
253
254 /*--- Communicate and store volume and the number of neighbors for
255 any dual CVs that lie on on periodic markers. ---*/
256
257 for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) {
258 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
259 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_VOLUME);
260 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
261 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_NEIGHBORS);
262 }
265
266 /*--- Perform the MPI communication of the solution ---*/
267
268 InitiateComms(geometry, config, MPI_QUANTITIES::SOLUTION);
270
271 /*--- Store the initial CFL number for all grid points. ---*/
272
273 const auto CFL = config->GetCFL(MGLevel);
274 for (auto iPoint = 0ul; iPoint < nPoint; iPoint++) {
275 nodes->SetLocalCFL(iPoint, CFL);
276 }
277 Min_CFL_Local = CFL;
278 Max_CFL_Local = CFL;
279 Avg_CFL_Local = CFL;
281
282template <class V, ENUM_REGIME R>
286#ifdef HAVE_OMP
287 /*--- Get the edge coloring. If the expected parallel efficiency becomes too low setup the
288 * reducer strategy. Where one loop is performed over edges followed by a point loop to
289 * sum the fluxes for each cell and set the diagonal of the system matrix. ---*/
291 su2double parallelEff = 1.0;
292
293#ifdef CODI_REVERSE_TYPE
294 /*--- For the discrete adjoint, the reducer strategy is costly. Prefer coloring, possibly with reduced edge color
295 * group size. Find the maximum edge color group size that yields an efficient coloring. Also, allow larger numbers
296 * of colors. ---*/
297 const bool relax = config.GetEdgeColoringRelaxDiscAdj();
298 const auto& coloring = geometry.GetEdgeColoring(&parallelEff, relax);
299#else
300 const auto& coloring = geometry.GetEdgeColoring(&parallelEff);
301#endif
302
303 /*--- The decision to use the strategy is local to each rank. ---*/
304 ReducerStrategy = parallelEff < COLORING_EFF_THRESH;
305
306 /*--- When using the reducer force a single color to reduce the color loop overhead. ---*/
307 if (ReducerStrategy && (coloring.getOuterSize() > 1)) geometry.SetNaturalEdgeColoring();
308
309 if (!coloring.empty()) {
310 /*--- If the reducer strategy is used we are not constrained by group
311 * size as we have no other edge loops in the Euler/NS solvers. ---*/
312 auto groupSize = static_cast<su2uint>(ReducerStrategy ? 1ul : geometry.GetEdgeColorGroupSize());
313 auto nColor = coloring.getOuterSize();
314 EdgeColoring.reserve(nColor);
315
316 for (auto iColor = 0ul; iColor < nColor; ++iColor)
317 EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor), groupSize);
318 }
319
320 /*--- If the reducer strategy is not being forced (by EDGE_COLORING_GROUP_SIZE=0) print some messages. ---*/
321 if (config.GetEdgeColoringGroupSize() != 1 << 30) {
322 su2double minEff = 1.0;
323 SU2_MPI::Reduce(&parallelEff, &minEff, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, SU2_MPI::GetComm());
324
325 int tmp = ReducerStrategy, numRanksUsingReducer = 0;
326 SU2_MPI::Reduce(&tmp, &numRanksUsingReducer, 1, MPI_INT, MPI_SUM, MASTER_NODE, SU2_MPI::GetComm());
327
328 if (minEff < COLORING_EFF_THRESH) {
329 cout << "WARNING: On " << numRanksUsingReducer << " MPI ranks the coloring efficiency was less than "
330 << COLORING_EFF_THRESH << " (min value was " << minEff << ").\n"
331 << " Those ranks will now use a fallback strategy, better performance may be possible\n"
332 << " with a different value of config option EDGE_COLORING_GROUP_SIZE (default 512)."
333#ifdef HAVE_OPDI
334 << "\n The memory usage of the discrete adjoint solver is higher when using the fallback."
335#endif
336 << endl;
337 } else {
338 if (SU2_MPI::GetRank() == MASTER_NODE) {
339 cout << "All ranks use edge coloring." << endl;
340 }
341 }
342
343 const su2double coloredParallelEff = ReducerStrategy ? 1.0 : parallelEff;
344 su2double minColoredParallelEff = 1.0;
345 SU2_MPI::Reduce(&coloredParallelEff, &minColoredParallelEff, 1, MPI_DOUBLE, MPI_MIN, MASTER_NODE, SU2_MPI::GetComm());
346
347 const unsigned long coloredNumColors = ReducerStrategy ? 0 : coloring.getOuterSize();
348 unsigned long maxColoredNumColors = 0;
349 SU2_MPI::Reduce(&coloredNumColors, &maxColoredNumColors, 1, MPI_UNSIGNED_LONG, MPI_MAX, MASTER_NODE, SU2_MPI::GetComm());
350
351 const unsigned long coloredEdgeColorGroupSize = ReducerStrategy ? 1 << 30 : geometry.GetEdgeColorGroupSize();
352 unsigned long minColoredEdgeColorGroupSize = 1 << 30;
353 SU2_MPI::Reduce(&coloredEdgeColorGroupSize, &minColoredEdgeColorGroupSize, 1, MPI_UNSIGNED_LONG, MPI_MIN, MASTER_NODE, SU2_MPI::GetComm());
354
355 if (SU2_MPI::GetRank() == MASTER_NODE && numRanksUsingReducer != SU2_MPI::GetSize()) {
356 cout << "Among the ranks that use edge coloring,\n"
357 << " the minimum efficiency is " << minColoredParallelEff << ",\n"
358 << " the maximum number of colors is " << maxColoredNumColors << ",\n"
359 << " the minimum edge color group size is " << minColoredEdgeColorGroupSize << "." << endl;
360 }
361 }
362
363 if (ReducerStrategy) EdgeFluxes.Initialize(geometry.GetnEdge(), geometry.GetnEdge(), nVar, nullptr);
364
366#else
367 EdgeColoring[0] = DummyGridColor<>(geometry.GetnEdge());
368#endif
369}
370
371template <class V, ENUM_REGIME R>
374
375 for (auto& mat : SlidingState) {
376 for (auto ptr : mat) delete [] ptr;
377 }
378
379 delete nodes;
380 delete edgeNumerics;
381}
382
383template <class V, ENUM_REGIME R>
385 bool reconstruction) {
387
388 const auto& primitives = nodes->GetPrimitive();
389 auto& gradient = reconstruction ? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive();
391 const auto commPer = reconstruction? PERIODIC_PRIM_GG_R : PERIODIC_PRIM_GG;
392
393 computeGradientsGreenGauss(this, comm, commPer, *geometry, *config, primitives, 0, nPrimVarGrad, prim_idx.Velocity(), gradient);
394}
395
396template <class V, ENUM_REGIME R>
398 bool reconstruction) {
400
401 /*--- Set a flag for unweighted or weighted least-squares. ---*/
402 bool weighted;
403 PERIODIC_QUANTITIES commPer;
404
405 if (reconstruction) {
407 commPer = weighted? PERIODIC_PRIM_LS_R : PERIODIC_PRIM_ULS_R;
408 }
409 else {
410 weighted = (config->GetKind_Gradient_Method() == WEIGHTED_LEAST_SQUARES);
411 commPer = weighted? PERIODIC_PRIM_LS : PERIODIC_PRIM_ULS;
412 }
413
414 const auto& primitives = nodes->GetPrimitive();
415 auto& rmatrix = nodes->GetRmatrix();
416 auto& gradient = reconstruction ? nodes->GetGradient_Reconstruction() : nodes->GetGradient_Primitive();
418
419 computeGradientsLeastSquares(this, comm, commPer, *geometry, *config, weighted,
420 primitives, 0, nPrimVarGrad, prim_idx.Velocity(), gradient, rmatrix);
421}
422
423template <class V, ENUM_REGIME R>
426
427 const auto kindLimiter = config->GetKind_SlopeLimit_Flow();
428 const auto umusclKappa = config->GetMUSCL_Kappa_Flow();
429 const auto& primitives = nodes->GetPrimitive();
430 const auto& gradient = nodes->GetGradient_Reconstruction();
431 auto& primMin = nodes->GetSolution_Min();
432 auto& primMax = nodes->GetSolution_Max();
433 auto& limiter = nodes->GetLimiter_Primitive();
434
436 *geometry, *config, 0, nPrimVarGrad, umusclKappa, primitives, gradient, primMin, primMax, limiter);
437}
438
439template <class V, ENUM_REGIME R>
441 CSolver **solver_container,
442 CNumerics *numerics, CConfig *config) {
444
445 const bool tkeNeeded = (config->GetKind_Turb_Model() == TURB_MODEL::SST);
446 const bool backscatter = config->GetSBSParam().StochasticBackscatter;
447 const bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR) ||
448 (config->GetKind_FluidModel() == IDEAL_GAS);
449
450 CVariable* turbNodes = nullptr;
451 if (tkeNeeded || backscatter) turbNodes = solver_container[TURB_SOL]->GetNodes();
452
453 /*--- Points, coordinates and normal vector in edge ---*/
454
455 auto iPoint = geometry->edges->GetNode(iEdge,0);
456 auto jPoint = geometry->edges->GetNode(iEdge,1);
457
458 numerics->SetCoord(geometry->nodes->GetCoord(iPoint),
459 geometry->nodes->GetCoord(jPoint));
460
461 numerics->SetNormal(geometry->edges->GetNormal(iEdge));
462
463 /*--- Primitive and secondary variables. ---*/
464
465 numerics->SetPrimitive(nodes->GetPrimitive(iPoint),
466 nodes->GetPrimitive(jPoint));
467 if (!ideal_gas) {
468 numerics->SetSecondary(nodes->GetSecondary(iPoint),
469 nodes->GetSecondary(jPoint));
470 }
471 /*--- Gradients. ---*/
472
473 numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint),
474 nodes->GetGradient_Primitive(jPoint));
475
476 /*--- Turbulent kinetic energy. ---*/
477
478 if (tkeNeeded)
479 numerics->SetTurbKineticEnergy(turbNodes->GetSolution(iPoint,0),
480 turbNodes->GetSolution(jPoint,0));
481
482 /*--- Stochastic variables from Langevin equations (Stochastic Backscatter Model). ---*/
483
484 if (backscatter) {
485 if (config->GetSBSParam().SBS_Ctau > 0.0) {
486 for (unsigned short iDim = 0; iDim < nDim; iDim++)
487 numerics->SetStochVar(iDim, turbNodes->GetSolution(iPoint, iDim+1),
488 turbNodes->GetSolution(jPoint, iDim+1));
489 } else {
490 for (unsigned short iDim = 0; iDim < nDim; iDim++)
491 numerics->SetStochVar(iDim, turbNodes->GetLangevinSourceTerms(iPoint, iDim),
492 turbNodes->GetLangevinSourceTerms(jPoint, iDim));
493 }
494 su2double DES_length_i = max(turbNodes->GetDES_LengthScale(iPoint), 1e-10);
495 su2double DES_length_j = max(turbNodes->GetDES_LengthScale(jPoint), 1e-10);
496 su2double lesMode_i = turbNodes->GetLES_Mode(iPoint);
497 su2double lesMode_j = turbNodes->GetLES_Mode(jPoint);
498 numerics->SetDistance(DES_length_i, DES_length_j);
499 numerics->SetLES_Mode(lesMode_i, lesMode_j);
500 }
501
502 /*--- Wall shear stress values (wall functions) ---*/
503
504 numerics->SetTau_Wall(nodes->GetTau_Wall(iPoint),
505 nodes->GetTau_Wall(jPoint));
506
507 /*--- Compute and update residual ---*/
508
509 auto residual = numerics->ComputeResidual(config);
510
511 if (ReducerStrategy) {
512 EdgeFluxes.SubtractBlock(iEdge, residual);
513 }
514 else {
515 LinSysRes.SubtractBlock(iPoint, residual);
516 LinSysRes.AddBlock(jPoint, residual);
517 }
518
519 /*--- The Jacobians are applied by the caller, fused with the convective contribution. ---*/
520 return residual;
521}
522
523template <class V, ENUM_REGIME R>
526
527 /*--- The errors only need to be computed on the finest grid. ---*/
528 if (MGLevel != MESH_0) return;
529
530 /*--- If this is a verification case, we can compute the global
531 error metrics by using the difference between the local error
532 and the known solution at each DOF. This is then collected into
533 RMS (L2) and maximum (Linf) global error norms. From these
534 global measures, one can compute the order of accuracy. ---*/
535
536 bool write_heads =
537 ((((config->GetInnerIter() % (config->GetScreen_Wrt_Freq(2) * 40)) == 0) && (config->GetInnerIter() != 0)) ||
538 (config->GetInnerIter() == 1));
539 if (!write_heads) return;
540
542
543 /*--- Check if there actually is an exact solution for this
544 verification case, if computed at all. ---*/
546 /*--- Get the physical time if necessary. ---*/
547 su2double time = 0.0;
548 if (config->GetTime_Marching() != TIME_MARCHING::STEADY) time = config->GetPhysicalTime();
549
550 /*--- Reset the global error measures to zero. ---*/
551 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
553 VerificationSolution->SetError_Max(iVar, 0.0, 0);
554 }
555
556 /*--- Loop over all owned points. ---*/
557 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
558 /* Set the pointers to the coordinates and solution of this DOF. */
559 const su2double* coor = geometry->nodes->GetCoord(iPoint);
560 su2double* solDOF = nodes->GetSolution(iPoint);
561
562 /* Get local error from the verification solution class. */
563 vector<su2double> error(nVar, 0.0);
564 VerificationSolution->GetLocalError(coor, time, solDOF, error.data());
565
566 /* Increment the global error measures */
567 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
568 VerificationSolution->AddError_RMS(iVar, error[iVar] * error[iVar]);
569 VerificationSolution->AddError_Max(iVar, fabs(error[iVar]), geometry->nodes->GetGlobalIndex(iPoint),
570 geometry->nodes->GetCoord(iPoint));
571 }
572 }
573
574 /* Finalize the calculation of the global error measures. */
576
577 /*--- Screen output of the error metrics. This can be improved
578 once the new output classes are in place. ---*/
579
581 }
582
583 }
585}
586
587template <class V, ENUM_REGIME R>
590
592
593 /*--- Update solution with under-relaxation and communicate it. ---*/
594
595 if (!config->GetContinuous_Adjoint()) {
597 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
598 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
599 nodes->AddSolution(iPoint, iVar, nodes->GetUnderRelaxation(iPoint) * LinSysSol(iPoint, iVar));
600 }
601 }
603 }
604
605 for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic()/2; iPeriodic++) {
606 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
607 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
608 }
609
610 InitiateComms(geometry, config, MPI_QUANTITIES::SOLUTION);
611 CompleteComms(geometry, config, MPI_QUANTITIES::SOLUTION);
612
613 /*--- For verification cases, compute the global error metrics. ---*/
614 ComputeVerificationError(geometry, config);
615}
616
617template <class V, ENUM_REGIME R>
620
621 PrepareImplicitIteration(geometry, nullptr, config);
622
623 /*--- Solve or smooth the linear system. ---*/
624
625 SU2_OMP_FOR_(schedule(static,OMP_MIN_SIZE) SU2_NOWAIT)
626 for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) {
627 LinSysRes.SetBlock_Zero(iPoint);
628 LinSysSol.SetBlock_Zero(iPoint);
629 }
631
632 auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config);
633
635 SetIterLinSolver(iter);
637 }
639
640 CompleteImplicitIteration(geometry, nullptr, config);
641}
642
643template <class V, ENUM_REGIME R>
644void CFVMFlowSolverBase<V, R>::ComputeVorticityAndStrainMag(const CConfig& config, const CGeometry *geometry, unsigned short iMesh) {
646
647 auto& StrainMag = nodes->GetStrainMag();
648
650
651 su2double strainMax = 0.0, omegaMax = 0.0;
652
654 for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) {
655
656 const auto VelocityGradient = nodes->GetVelocityGradient(iPoint);
657 auto Vorticity = nodes->GetVorticity(iPoint);
658
659 /*--- Vorticity ---*/
660
661 Vorticity[0] = 0.0;
662 Vorticity[1] = 0.0;
663 Vorticity[2] = VelocityGradient(1,0)-VelocityGradient(0,1);
664
665 if (nDim == 3) {
666 Vorticity[0] = VelocityGradient(2,1)-VelocityGradient(1,2);
667 Vorticity[1] = -(VelocityGradient(2,0)-VelocityGradient(0,2));
668 }
669
670 /*--- Strain Magnitude ---*/
671
672 const su2double vy = nodes->GetVelocity(iPoint, 1);
673 const su2double y = geometry->nodes->GetCoord(iPoint, 1);
675 AD::SetPreaccIn(VelocityGradient, nDim, nDim);
676 AD::SetPreaccIn(vy, y);
677
678 StrainMag(iPoint) = 0.0;
679
680 /*--- Add diagonal part ---*/
681
682 for (unsigned long iDim = 0; iDim < nDim; iDim++) {
683 StrainMag(iPoint) += pow(VelocityGradient(iDim, iDim), 2);
684 }
685 if (config.GetAxisymmetric() && y > EPS) {
686 StrainMag(iPoint) += pow(vy / y, 2);
687 }
688
689 /*--- Add off diagonals ---*/
690
691 StrainMag(iPoint) += 2.0*pow(0.5*(VelocityGradient(0,1) + VelocityGradient(1,0)), 2);
692
693 if (nDim == 3) {
694 StrainMag(iPoint) += 2.0*pow(0.5*(VelocityGradient(0,2) + VelocityGradient(2,0)), 2);
695 StrainMag(iPoint) += 2.0*pow(0.5*(VelocityGradient(1,2) + VelocityGradient(2,1)), 2);
696 }
697
698 StrainMag(iPoint) = sqrt(2.0*StrainMag(iPoint));
699 AD::SetPreaccOut(StrainMag(iPoint));
701
702 /*--- The derivative with respect to strainMax and omegaMax is not required. ---*/
703 bool wa = AD::PauseRecording();
704 strainMax = max(strainMax, StrainMag(iPoint));
705 omegaMax = max(omegaMax, GeometryToolbox::Norm(3, Vorticity));
707 }
709
710 if ((iMesh == MESH_0) && (config.GetComm_Level() == COMM_FULL)) {
711 atomicMax(strainMax, StrainMag_Max);
712 atomicMax(omegaMax, Omega_Max);
713
715 {
716 su2double MyOmega_Max = Omega_Max;
717 su2double MyStrainMag_Max = StrainMag_Max;
718
721 }
723 }
724
725}
726
727template <class V, ENUM_REGIME R>
728void CFVMFlowSolverBase<V, R>::SetInletAtVertex(const su2double* val_inlet, unsigned short iMarker,
729 unsigned long iVertex) {
731
732 /*--- Alias positions within inlet file for readability ---*/
733
734 unsigned short T_position = nDim;
735 unsigned short P_position = nDim + 1;
736 unsigned short FlowDir_position = nDim + 2;
737
738 /*--- Note that it is not necessary anymore to use normalized normals for the inlet velocity ---*/
739
740
741 /*--- Store the values in our inlet data structures. ---*/
742
743 Inlet_Ttotal[iMarker][iVertex] = val_inlet[T_position];
744 Inlet_Ptotal[iMarker][iVertex] = val_inlet[P_position];
745 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
746 Inlet_FlowDir[iMarker][iVertex][iDim] = val_inlet[FlowDir_position + iDim];
747 }
748}
749
750template <class V, ENUM_REGIME R>
751su2double CFVMFlowSolverBase<V, R>::GetInletAtVertex(unsigned short iMarker, unsigned long iVertex,
752 const CGeometry* geometry, su2double* val_inlet) const {
754
755 const auto T_position = nDim;
756 const auto P_position = nDim + 1;
757 const auto FlowDir_position = nDim + 2;
758 val_inlet[T_position] = Inlet_Ttotal[iMarker][iVertex];
759 val_inlet[P_position] = Inlet_Ptotal[iMarker][iVertex];
760 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
761 val_inlet[FlowDir_position + iDim] = Inlet_FlowDir[iMarker][iVertex][iDim];
762 }
763
764 /*--- Compute boundary face area for this vertex. ---*/
765
766 su2double Normal[MAXNDIM] = {0.0};
767 geometry->vertex[iMarker][iVertex]->GetNormal(Normal);
768 return GeometryToolbox::Norm(nDim, Normal);
769}
770
771template <class V, ENUM_REGIME R>
772void CFVMFlowSolverBase<V, R>::SetUniformInlet(const CConfig* config, unsigned short iMarker) {
774
775 if (config->GetMarker_All_KindBC(iMarker) == INLET_FLOW) {
776 const string Marker_Tag = config->GetMarker_All_TagBound(iMarker);
777 const su2double p_total = config->GetInletPtotal(Marker_Tag);
778 const su2double t_total = config->GetInletTtotal(Marker_Tag);
779 const su2double* flow_dir = config->GetInletFlowDir(Marker_Tag);
780
781 for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
782 Inlet_Ttotal[iMarker][iVertex] = t_total;
783 Inlet_Ptotal[iMarker][iVertex] = p_total;
784 for (unsigned short iDim = 0; iDim < nDim; iDim++) Inlet_FlowDir[iMarker][iVertex][iDim] = flow_dir[iDim];
785 }
786 } else if (config->GetMarker_All_KindBC(iMarker) == SUPERSONIC_INLET) {
787 const string Marker_Tag = config->GetMarker_All_TagBound(iMarker);
788 const su2double p = config->GetInlet_Pressure(Marker_Tag);
789 const su2double t = config->GetInlet_Temperature(Marker_Tag);
790 const su2double* vel = config->GetInlet_Velocity(Marker_Tag);
791
792 for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
793 Inlet_Ttotal[iMarker][iVertex] = t;
794 Inlet_Ptotal[iMarker][iVertex] = p;
795 for (unsigned short iDim = 0; iDim < nDim; iDim++) Inlet_FlowDir[iMarker][iVertex][iDim] = vel[iDim];
796 }
797 } else {
798 /*--- For now, non-inlets just get set to zero. In the future, we
799 can do more customization for other boundary types here. ---*/
800 for (unsigned long iVertex = 0; iVertex < nVertex[iMarker]; iVertex++) {
801 Inlet_Ttotal[iMarker][iVertex] = 0.0;
802 Inlet_Ptotal[iMarker][iVertex] = 0.0;
803 for (unsigned short iDim = 0; iDim < nDim; iDim++) Inlet_FlowDir[iMarker][iVertex][iDim] = 0.0;
804 }
805 }
806}
807
808template <class V, ENUM_REGIME R>
810 CGeometry** geometry_container, CSolver*** solver_container, CConfig *config) {
812
813 struct {
814 const CSolver* fine_solver{nullptr};
815 CSolver* coarse_solver{nullptr};
816 unsigned short marker{0};
817 unsigned short var{0};
818
819 su2double Get(unsigned long vertex) const {
820 if (var == 0) {
821 return fine_solver->GetInletTtotal(marker, vertex);
822 } else if (var == 1) {
823 return fine_solver->GetInletPtotal(marker, vertex);
824 }
825 return fine_solver->GetInletFlowDir(marker, vertex, var - 2);
826 }
827
828 void Set(unsigned long vertex, const su2double& val) const {
829 if (var == 0) {
830 coarse_solver->SetInletTtotal(marker, vertex, val);
831 } else if (var == 1) {
832 coarse_solver->SetInletPtotal(marker, vertex, val);
833 }
834 coarse_solver->SetInletFlowDir(marker, vertex, var - 2, val);
835 }
836 } inlet_values;
837
838 for (auto mg_coarse = 1u; mg_coarse <= config->GetnMGLevels(); ++mg_coarse) {
839 const auto mg_fine = mg_coarse - 1;
840 inlet_values.fine_solver = solver_container[mg_fine][FLOW_SOL];
841 inlet_values.coarse_solver = solver_container[mg_coarse][FLOW_SOL];
842
843 for (auto marker = 0u; marker < config->GetnMarker_All(); ++marker) {
844 if (config->GetMarker_All_KindBC(marker) != INLET_FLOW) continue;
845 inlet_values.marker = marker;
846 for (inlet_values.var = 0; inlet_values.var < 2 + nDim; ++inlet_values.var) {
847 geometry_container[mg_coarse]->SetMultiGridMarkerQuantity(geometry_container[mg_fine], marker, inlet_values);
848 }
849 }
850 }
851}
852
853template <class V, ENUM_REGIME R>
854void CFVMFlowSolverBase<V, R>::LoadRestart_impl(CGeometry **geometry, CSolver ***solver, CConfig *config, int iter,
855 bool update_geo, su2double* SolutionRestart,
856 unsigned short nVar_Restart) {
858
859 /*--- Restart the solution from file information ---*/
860
861 string restart_filename = config->GetSolution_FileName();
862 const bool static_fsi = ((config->GetTime_Marching() == TIME_MARCHING::STEADY) && config->GetFSI_Simulation());
863
864 /*--- To make this routine safe to call in parallel most of it can only be executed by one thread. ---*/
866
867 if (nVar_Restart == 0) nVar_Restart = nVar;
868
869 /*--- Skip coordinates ---*/
870
871 unsigned short skipVars = nDim;
872
873 /*--- Read the restart data from either an ASCII or binary SU2 file. ---*/
874 if (config->GetRead_Binary_Restart()) {
875 restart_filename = config->GetFilename(restart_filename, ".dat", iter);
876 Read_SU2_Restart_Binary(geometry[MESH_0], config, restart_filename);
877 } else {
878 restart_filename = config->GetFilename(restart_filename, ".csv", iter);
879 Read_SU2_Restart_ASCII(geometry[MESH_0], config, restart_filename);
880 }
881
882 bool steady_restart = config->GetSteadyRestart();
883 if (update_geo && dynamic_grid) {
884 auto notFound = fields.end();
885 if (find(fields.begin(), notFound, string("\"Grid_Velocity_x\"")) == notFound) {
886 if (rank == MASTER_NODE)
887 cout << "\nWARNING: The restart file does not contain grid velocities, these will be set to zero.\n" << endl;
888 steady_restart = true;
889 }
890 }
891
892 /*--- Load data from the restart into correct containers. ---*/
893
894 unsigned long counter = 0;
895 for (auto iPoint_Global = 0ul; iPoint_Global < geometry[MESH_0]->GetGlobal_nPointDomain(); iPoint_Global++) {
896
897 /*--- Retrieve local index. If this node from the restart file lives
898 on the current processor, we will load and instantiate the vars. ---*/
899
900 const auto iPoint_Local = geometry[MESH_0]->GetGlobal_to_Local_Point(iPoint_Global);
901
902 if (iPoint_Local > -1) {
903
904 /*--- We need to store this point's data, so jump to the correct
905 offset in the buffer of data from the restart file and load it. ---*/
906
907 auto index = counter * Restart_Vars[1] + skipVars;
908
909 if (SolutionRestart == nullptr) {
910 for (auto iVar = 0u; iVar < nVar_Restart; iVar++)
911 nodes->SetSolution(iPoint_Local, iVar, Restart_Data[index+iVar]);
912 }
913 else {
914 /*--- Used as buffer, allows defaults for nVar > nVar_Restart. ---*/
915 for (auto iVar = 0u; iVar < nVar_Restart; iVar++)
916 SolutionRestart[iVar] = Restart_Data[index + iVar];
917 nodes->SetSolution(iPoint_Local, SolutionRestart);
918 }
919
920 /*--- For dynamic meshes, read in and store the
921 grid coordinates and grid velocities for each node. ---*/
922
923 if (dynamic_grid && update_geo) {
924
925 /*--- Read in the next 2 or 3 variables which are the grid velocities ---*/
926 /*--- If we are restarting the solution from a previously computed static calculation (no grid movement) ---*/
927 /*--- the grid velocities are set to 0. This is useful for FSI computations ---*/
928
929 /*--- Rewind the index to retrieve the Coords. ---*/
930 index = counter * Restart_Vars[1];
931 const auto* Coord = &Restart_Data[index];
932
933 su2double GridVel[MAXNDIM] = {0.0};
934 if (!steady_restart) {
935 /*--- Move the index forward to get the grid velocities. ---*/
936 index += skipVars + nVar_Restart + config->GetnTurbVar();
937 for (auto iDim = 0u; iDim < nDim; iDim++) { GridVel[iDim] = Restart_Data[index+iDim]; }
938 }
939
940 for (auto iDim = 0u; iDim < nDim; iDim++) {
941 geometry[MESH_0]->nodes->SetCoord(iPoint_Local, iDim, Coord[iDim]);
942 geometry[MESH_0]->nodes->SetGridVel(iPoint_Local, iDim, GridVel[iDim]);
943 }
944 }
945
946 /*--- For static FSI problems, grid_movement is 0 but we need to read in and store the
947 grid coordinates for each node (but not the grid velocities, as there are none). ---*/
948
949 if (static_fsi && update_geo) {
950 /*--- Rewind the index to retrieve the Coords. ---*/
951 index = counter*Restart_Vars[1];
952 const auto* Coord = &Restart_Data[index];
953
954 for (auto iDim = 0u; iDim < nDim; iDim++) {
955 geometry[MESH_0]->nodes->SetCoord(iPoint_Local, iDim, Coord[iDim]);
956 }
957 }
958
959 /*--- Increment the overall counter for how many points have been loaded. ---*/
960 counter++;
961 }
962 }
963
964 /*--- Detect a wrong solution file ---*/
965
966 if (counter != nPointDomain) {
967 SU2_MPI::Error(string("The solution file ") + restart_filename + string(" does not match with the mesh file.\n") +
968 string("This can be caused by empty lines at the end of the file."), CURRENT_FUNCTION);
969 }
970 }
972
973 /*--- Update the geometry for flows on deforming meshes. ---*/
974
975 if ((dynamic_grid || static_fsi) && update_geo) {
976
977 CGeometry::UpdateGeometry(geometry, config);
978
979 if (dynamic_grid) {
980 for (auto iMesh = 0u; iMesh <= config->GetnMGLevels(); iMesh++) {
981
982 /*--- Compute the grid velocities on the coarser levels. ---*/
983 if (iMesh) geometry[iMesh]->SetRestricted_GridVelocity(geometry[iMesh - 1]);
984 else {
985 geometry[MESH_0]->InitiateComms(geometry[MESH_0], config, MPI_QUANTITIES::GRID_VELOCITY);
986 geometry[MESH_0]->CompleteComms(geometry[MESH_0], config, MPI_QUANTITIES::GRID_VELOCITY);
987 }
988 }
989 }
990 }
991
992 /*--- Communicate the loaded solution on the fine grid before we transfer
993 it down to the coarse levels. We also call the preprocessing routine
994 on the fine level in order to have all necessary quantities updated,
995 especially if this is a turbulent simulation (eddy viscosity). ---*/
996
997 solver[MESH_0][FLOW_SOL]->InitiateComms(geometry[MESH_0], config, MPI_QUANTITIES::SOLUTION);
998 solver[MESH_0][FLOW_SOL]->CompleteComms(geometry[MESH_0], config, MPI_QUANTITIES::SOLUTION);
999
1000 /*--- For turbulent/species simulations the flow preprocessing is done by the turbulence/species solver
1001 * after it loads its variables (they are needed to compute flow primitives). In case turbulence and species, the
1002 * species solver does all the Pre-/Postprocessing. ---*/
1003 if (config->GetKind_Turb_Model() == TURB_MODEL::NONE &&
1005 solver[MESH_0][FLOW_SOL]->Preprocessing(geometry[MESH_0], solver[MESH_0], config, MESH_0, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
1006 }
1007
1008 /*--- Interpolate the solution down to the coarse multigrid levels ---*/
1009
1010 for (auto iMesh = 1u; iMesh <= config->GetnMGLevels(); iMesh++) {
1011 MultigridRestriction(*geometry[iMesh - 1], solver[iMesh - 1][FLOW_SOL]->GetNodes()->GetSolution(),
1012 *geometry[iMesh], solver[iMesh][FLOW_SOL]->GetNodes()->GetSolution());
1013 solver[iMesh][FLOW_SOL]->InitiateComms(geometry[iMesh], config, MPI_QUANTITIES::SOLUTION);
1014 solver[iMesh][FLOW_SOL]->CompleteComms(geometry[iMesh], config, MPI_QUANTITIES::SOLUTION);
1015
1016 if (config->GetKind_Turb_Model() == TURB_MODEL::NONE &&
1018 solver[iMesh][FLOW_SOL]->Preprocessing(geometry[iMesh], solver[iMesh], config, iMesh, NO_RK_ITER, RUNTIME_FLOW_SYS, true);
1019 }
1020 }
1021
1022 /*--- Update the old geometry (coordinates n and n-1) in dual time-stepping strategy. ---*/
1023 const bool dual_time = ((config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_1ST) ||
1025 if (dual_time && config->GetGrid_Movement() && !config->GetDeform_Mesh() &&
1026 (config->GetKind_GridMovement() != RIGID_MOTION)) {
1027 Restart_OldGeometry(geometry[MESH_0], config);
1028 }
1029
1030 /*--- Go back to single threaded execution. ---*/
1033 /*--- Delete the class memory that is used to load the restart. ---*/
1034
1035 Restart_Vars = decltype(Restart_Vars){};
1036 Restart_Data = decltype(Restart_Data){};
1039}
1040
1041template <class V, ENUM_REGIME R>
1043 CConfig *config, int iter, bool update_geo) {
1045 LoadRestart_impl(geometry, solver, config, iter, update_geo);
1046}
1047
1048template <class V, ENUM_REGIME R>
1050 CConfig *config, unsigned long TimeIter) {
1052
1053 const bool restart = (config->GetRestart() || config->GetRestart_Flow());
1054 const bool rans = (config->GetKind_Turb_Model() != TURB_MODEL::NONE);
1055 const bool dual_time = ((config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_1ST) ||
1057
1058 /*--- Start OpenMP parallel region. ---*/
1059
1061
1062 unsigned long iPoint;
1063 unsigned short iMesh;
1064
1065 /*--- Check if a verification solution is to be computed. ---*/
1066 if ((VerificationSolution) && (TimeIter == 0) && !restart) {
1067
1068 /*--- Loop over the multigrid levels. ---*/
1069 for (iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) {
1070
1071 /*--- Loop over all grid points. ---*/
1073 for (iPoint = 0; iPoint < geometry[iMesh]->GetnPoint(); iPoint++) {
1074
1075 /* Set the pointers to the coordinates and solution of this DOF. */
1076 const su2double *coor = geometry[iMesh]->nodes->GetCoord(iPoint);
1077 su2double *solDOF = solver_container[iMesh][FLOW_SOL]->GetNodes()->GetSolution(iPoint);
1078
1079 /* Set the solution in this DOF to the initial condition provided by
1080 the verification solution class. This can be the exact solution,
1081 but this is not necessary. */
1083 }
1085 }
1086 }
1087
1088 /*--- The value of the solution for the first iteration of the dual time ---*/
1089
1090 if (dual_time && TimeIter == config->GetRestart_Iter()) {
1091 PushSolutionBackInTime(TimeIter, restart, rans, solver_container, geometry, config);
1092 }
1094 }
1096
1097}
1098
1099template <class V, ENUM_REGIME R>
1100void CFVMFlowSolverBase<V, R>::PushSolutionBackInTime(unsigned long TimeIter, bool restart, bool rans,
1101 CSolver*** solver_container, CGeometry** geometry,
1102 CConfig* config) {
1104
1105 /*--- Push back the initial condition to previous solution containers
1106 for a 1st-order restart or when simply initializing to freestream. ---*/
1107
1108 for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) {
1109 solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n();
1110 solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n1();
1111 if (rans) {
1112 solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n();
1113 solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n1();
1114 }
1115
1116 if (dynamic_grid) {
1117 geometry[iMesh]->nodes->SetVolume_n();
1118 geometry[iMesh]->nodes->SetVolume_nM1();
1119 }
1120
1121 if (config->GetGrid_Movement()) {
1122 geometry[iMesh]->nodes->SetCoord_n();
1123 geometry[iMesh]->nodes->SetCoord_n1();
1124 }
1125 }
1126
1127 if (restart && (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND)) {
1128
1129 /*--- Load an additional restart file for a 2nd-order restart. ---*/
1130
1131 solver_container[MESH_0][FLOW_SOL]->LoadRestart(geometry, solver_container, config, TimeIter-1, true);
1132
1133 /*--- Load an additional restart file for the turbulence model. ---*/
1134 if (rans)
1135 solver_container[MESH_0][TURB_SOL]->LoadRestart(geometry, solver_container, config, TimeIter-1, false);
1136
1137 /*--- Push back this new solution to time level N. ---*/
1138
1139 for (unsigned short iMesh = 0; iMesh <= config->GetnMGLevels(); iMesh++) {
1140 solver_container[iMesh][FLOW_SOL]->GetNodes()->Set_Solution_time_n();
1141 if (rans) solver_container[iMesh][TURB_SOL]->GetNodes()->Set_Solution_time_n();
1142
1143 geometry[iMesh]->nodes->SetVolume_n();
1144 if (config->GetGrid_Movement()) geometry[iMesh]->nodes->SetCoord_n();
1145 }
1146 }
1147}
1148
1149template <class V, ENUM_REGIME FlowRegime>
1150void CFVMFlowSolverBase<V, FlowRegime>::BC_Sym_Plane(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics,
1151 CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) {
1153
1154 const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
1155 const bool ideal_gas = (config->GetKind_FluidModel() == STANDARD_AIR) ||
1156 (config->GetKind_FluidModel() == IDEAL_GAS);
1157 const auto iVel = prim_idx.Velocity();
1158
1159 /*--- Blazek chapter 8.:
1160 * The components of the momentum residual normal to the symmetry plane are zeroed out.
1161 * The gradients have already been corrected acording to Eq. (8.40).
1162 * Contrary to Blazek we keep some scalar fluxes computed on the boundary to improve stability (see below). ---*/
1163
1164 /*--- Loop over all the vertices on this boundary marker. ---*/
1165
1167 for (auto iVertex = 0ul; iVertex < geometry->nVertex[val_marker]; iVertex++) {
1168 const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode();
1169
1170 /*--- Halo points do not need to be considered. ---*/
1171 if (!geometry->nodes->GetDomain(iPoint)) continue;
1173 /*--- Get the normal of the current symmetry. This may be the original normal of the vertex
1174 * or a modified normal if there are intersecting symmetries. ---*/
1175
1176 su2double Normal[MAXNDIM] = {}, UnitNormal[MAXNDIM] = {};
1177 geometry->vertex[val_marker][iVertex]->GetNormal(Normal);
1178 const auto it = geometry->symmetryNormals[val_marker].find(iVertex);
1179
1180 if (it != geometry->symmetryNormals[val_marker].end()) {
1181 for (auto iDim = 0u; iDim < nDim; iDim++) UnitNormal[iDim] = it->second[iDim];
1182 } else {
1183 const su2double Area = GeometryToolbox::Norm(nDim, Normal);
1184 for (auto iDim = 0u; iDim < nDim; iDim++) UnitNormal[iDim] = Normal[iDim] / Area;
1185 }
1186
1187 /*--- Energy terms due to grid movement (aka work of pressure forces). ---*/
1188 if (dynamic_grid) {
1189 su2double* V_reflected = GetCharacPrimVar(val_marker, iVertex);
1190
1191 conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint),
1192 geometry->nodes->GetGridVel(iPoint));
1193
1194 /*--- Normal vector for this vertex (negate for outward convention). ---*/
1195 for (auto iDim = 0u; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim];
1196 conv_numerics->SetNormal(Normal);
1197
1198 for (auto iVar = 0u; iVar < nPrimVar; iVar++)
1199 V_reflected[iVar] = nodes->GetPrimitive(iPoint, iVar);
1200
1201 su2double ProjVelocity_i = nodes->GetProjVel(iPoint, UnitNormal);
1202 /*--- Adjustment to v.n due to grid movement. ---*/
1203 ProjVelocity_i -= GeometryToolbox::DotProduct(nDim, geometry->nodes->GetGridVel(iPoint), UnitNormal);
1205 for (auto iDim = 0u; iDim < nDim; iDim++)
1206 V_reflected[iDim + iVel] = nodes->GetVelocity(iPoint, iDim) - ProjVelocity_i * UnitNormal[iDim];
1207
1208 /*--- Get current solution at this boundary node. ---*/
1209 const su2double* V_domain = nodes->GetPrimitive(iPoint);
1210
1211 /*--- Set Primitive and Secondary for numerics class. ---*/
1212 conv_numerics->SetPrimitive(V_domain, V_reflected);
1213 if (!ideal_gas) {
1214 conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), nodes->GetSecondary(iPoint));
1215 }
1216
1217 /*--- Compute the residual using an upwind scheme. ---*/
1218 auto residual = conv_numerics->ComputeResidual(config);
1219
1220 /*--- Use just the energy fluxes to update the residual, adding the others would
1221 * increase numerical diffusion which we wish to avoid if possible. ---*/
1222 for (auto iVar = iVel + nDim; iVar < nVar; iVar++) {
1223 LinSysRes(iPoint, iVar) += residual.residual[iVar];
1224 }
1225 if (implicit) {
1226 auto* block = Jacobian.GetBlock(iPoint, iPoint);
1227 /*--- But in the Jacobian we also include the mass flux, this allows some cases with
1228 * motion to use larger CFL, for example pywrapper_translating_naca0012. ---*/
1229 for (auto iVar = 0u; iVar < nVar; iVar++) {
1230 if (iVar < iVel || iVar >= iVel + nDim) {
1231 for (auto jVar = 0u; jVar < nVar; jVar++) {
1232 block[iVar * nVar + jVar] += SU2_TYPE::GetValue(residual.jacobian_i[iVar][jVar]);
1233 }
1234 }
1235 }
1236 }
1237 }
1238
1239 /*--- Explicitly set the velocity components normal to the symmetry plane to zero.
1240 * This is necessary because the modification of the residual leaves the problem
1241 * underconstrained (the normal residual is zero regardless of the normal velocity). ---*/
1242
1243 su2double* solutionOld = nodes->GetSolution_Old(iPoint);
1244
1245 su2double gridVel[MAXNDIM] = {};
1246 if (dynamic_grid) {
1247 for (auto iDim = 0u; iDim < nDim; iDim++) {
1248 gridVel[iDim] = geometry->nodes->GetGridVel(iPoint)[iDim];
1249 }
1250 if (FlowRegime == ENUM_REGIME::COMPRESSIBLE) {
1251 for(auto iDim = 0u; iDim < nDim; iDim++) {
1252 /*--- Multiply by density since we are correcting conservative variables. ---*/
1253 gridVel[iDim] *= nodes->GetDensity(iPoint);
1254 }
1255 }
1256 }
1257 su2double vp = 0.0;
1258 for (auto iDim = 0u; iDim < nDim; iDim++) {
1259 vp += (solutionOld[iVel + iDim] - gridVel[iDim]) * UnitNormal[iDim];
1260 }
1261 for (auto iDim = 0u; iDim < nDim; iDim++) {
1262 solutionOld[iVel + iDim] -= vp * UnitNormal[iDim];
1263 }
1264
1265 /*--- Keep only the tangential part of the momentum residuals. ---*/
1266 su2double normalRes = 0.0;
1267 for (auto iDim = 0u; iDim < nDim; iDim++) {
1268 normalRes += LinSysRes(iPoint, iVel + iDim) * UnitNormal[iDim];
1269 }
1270 for (auto iDim = 0u; iDim < nDim; iDim++) {
1271 LinSysRes(iPoint, iVel + iDim) -= normalRes * UnitNormal[iDim];
1272 }
1273
1274 /*--- Jacobian contribution for implicit integration. ---*/
1275 if (implicit) {
1276 /*--- Modify the Jacobians according to the modification of the residual
1277 * J_new = (I - n * n^T) * J where n = {0, nx, ny, nz, 0, ...} ---*/
1278 su2double mat[MAXNVAR * MAXNVAR] = {};
1279
1280 for (auto iVar = 0u; iVar < nVar; iVar++)
1281 mat[iVar * nVar + iVar] = 1;
1282 for (auto iDim = 0u; iDim < nDim; iDim++)
1283 for (auto jDim = 0u; jDim < nDim; jDim++)
1284 mat[(iDim + iVel) * nVar + jDim + iVel] -= UnitNormal[iDim] * UnitNormal[jDim];
1285
1286 auto ModifyJacobian = [&](const unsigned long jPoint) {
1287 su2double jac[MAXNVAR * MAXNVAR], newJac[MAXNVAR * MAXNVAR];
1288 const auto view = Jacobian.GetBlockView(iPoint, jPoint);
1289 if (!view) return;
1290 for (auto iVar = 0u; iVar < nVar; iVar++)
1291 for (auto jVar = 0u; jVar < nVar; jVar++) jac[iVar * nVar + jVar] = view(iVar, jVar);
1292
1293 CBlasStructure().gemm(nVar, nVar, nVar, mat, jac, newJac, config);
1294
1295 Jacobian.SetBlock(iPoint, jPoint, newJac);
1296 };
1297 ModifyJacobian(iPoint);
1298 for (size_t iNeigh = 0; iNeigh < geometry->nodes->GetnPoint(iPoint); ++iNeigh) {
1299 ModifyJacobian(geometry->nodes->GetPoint(iPoint, iNeigh));
1300 }
1301 }
1302
1303 /*--- Correction for multigrid. ---*/
1304 normalRes = 0.0;
1305 su2double* Res_TruncError = nodes->GetResTruncError(iPoint);
1306 for (auto iDim = 0u; iDim < nDim; iDim++) {
1307 normalRes += Res_TruncError[iVel + iDim] * UnitNormal[iDim];
1308 }
1309 for (auto iDim = 0u; iDim < nDim; iDim++) {
1310 Res_TruncError[iVel + iDim] -= normalRes * UnitNormal[iDim];
1311 }
1312 }
1314
1315}
1316
1317template <class V, ENUM_REGIME R>
1318void CFVMFlowSolverBase<V, R>::BC_Periodic(CGeometry* geometry, CSolver** solver_container, CNumerics* numerics,
1319 CConfig* config) {
1321
1322 /*--- Complete residuals for periodic boundary conditions. We loop over
1323 the periodic BCs in matching pairs so that, in the event that there are
1324 adjacent periodic markers, the repeated points will have their residuals
1325 accumulated correctly during the communications. For implicit calculations,
1326 the Jacobians and linear system are also correctly adjusted here. ---*/
1327
1328 for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) {
1329 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
1330 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
1331 }
1332}
1333
1334template <class V, ENUM_REGIME FlowRegime>
1336 CNumerics* conv_numerics, CNumerics* visc_numerics,
1337 CConfig* config) {
1339
1340 const bool ideal_gas = config->GetKind_FluidModel() == STANDARD_AIR || config->GetKind_FluidModel() == IDEAL_GAS;
1341
1342 unsigned long iVertex, jVertex, iPoint, Point_Normal = 0;
1343 unsigned short iDim, iVar, jVar, iMarker, nDonorVertex;
1344
1345 bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
1346 bool viscous = config->GetViscous();
1347
1348 su2double Normal[MAXNDIM] = {0.0};
1349 su2double PrimVar_i[MAXNVAR] = {0.0};
1350 su2double PrimVar_j[MAXNVAR] = {0.0};
1351 su2double Secondary_j[MAXNVAR] = {0.0};
1352 su2double Residual[MAXNVAR] = {0.0};
1354 for (iVar = 0; iVar < nVar; iVar++) Jacobian_i[iVar] = new su2double[nVar];
1355
1356 su2double weight;
1357 su2double P_static, rho_static;
1358
1359 for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) {
1360 if (config->GetMarker_All_KindBC(iMarker) == FLUID_INTERFACE) {
1362 for (iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
1363 iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1364
1365 if (geometry->nodes->GetDomain(iPoint)) {
1366 nDonorVertex = GetnSlidingStates(iMarker, iVertex);
1367
1368 /*--- Initialize Residual, this will serve to accumulate the average ---*/
1369
1370 for (iVar = 0; iVar < nVar; iVar++) {
1371 Residual[iVar] = 0.0;
1372 for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0;
1373 }
1374
1375 /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/
1376
1377 for (jVertex = 0; jVertex < nDonorVertex; jVertex++) {
1378 Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor();
1379
1380 for (iVar = 0; iVar < nPrimVar; iVar++) {
1381 PrimVar_i[iVar] = nodes->GetPrimitive(iPoint, iVar);
1382 PrimVar_j[iVar] = GetSlidingState(iMarker, iVertex, iVar, jVertex);
1383 }
1384
1385 /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/
1386
1387 weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex);
1388
1389 /*--- Set primitive variables ---*/
1390
1391 conv_numerics->SetPrimitive(PrimVar_i, PrimVar_j);
1392
1393 if (FlowRegime == ENUM_REGIME::COMPRESSIBLE && !ideal_gas) {
1394 P_static = PrimVar_j[nDim + 1];
1395 rho_static = PrimVar_j[nDim + 2];
1396 GetFluidModel()->SetTDState_Prho(P_static, rho_static);
1397
1398 Secondary_j[0] = GetFluidModel()->GetdPdrho_e();
1399 Secondary_j[1] = GetFluidModel()->GetdPde_rho();
1400
1401 conv_numerics->SetSecondary(nodes->GetSecondary(iPoint), Secondary_j);
1402 }
1403
1404 /*--- Set the normal vector ---*/
1405
1406 geometry->vertex[iMarker][iVertex]->GetNormal(Normal);
1407 for (iDim = 0; iDim < nDim; iDim++) Normal[iDim] = -Normal[iDim];
1408
1409 conv_numerics->SetNormal(Normal);
1410
1411 if (dynamic_grid)
1412 conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint));
1413
1414 /*--- Compute the convective residual using an upwind scheme ---*/
1415
1416 auto residual = conv_numerics->ComputeResidual(config);
1417
1418 /*--- Accumulate the residuals to compute the average ---*/
1419
1420 for (iVar = 0; iVar < nVar; iVar++) {
1421 Residual[iVar] += weight * residual[iVar];
1422 for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] += weight * residual.jacobian_i[iVar][jVar];
1423 }
1424 }
1425
1426 /*--- Add Residuals and Jacobians ---*/
1427
1428 LinSysRes.AddBlock(iPoint, Residual);
1429
1430 if (implicit) Jacobian.AddBlock2Diag(iPoint, Jacobian_i);
1431
1432 if (viscous) {
1433 /*--- Initialize Residual, this will serve to accumulate the average ---*/
1434
1435 for (iVar = 0; iVar < nVar; iVar++) {
1436 Residual[iVar] = 0.0;
1437 for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] = 0.0;
1438 }
1439
1440 /*--- Loop over the nDonorVertexes and compute the averaged flux ---*/
1441
1442 for (jVertex = 0; jVertex < nDonorVertex; jVertex++) {
1443 PrimVar_j[nDim + 5] = GetSlidingState(iMarker, iVertex, nDim + 5, jVertex);
1444 PrimVar_j[nDim + 6] = GetSlidingState(iMarker, iVertex, nDim + 6, jVertex);
1445
1446 /*--- Get the weight computed in the interpolator class for the j-th donor vertex ---*/
1447
1448 weight = GetSlidingState(iMarker, iVertex, nPrimVar, jVertex);
1449
1450 /*--- Set the normal vector and the coordinates ---*/
1451
1452 visc_numerics->SetNormal(Normal);
1453 su2double Coord_Reflected[MAXNDIM];
1454 GeometryToolbox::PointPointReflect(nDim, geometry->nodes->GetCoord(Point_Normal),
1455 geometry->nodes->GetCoord(iPoint), Coord_Reflected);
1456 visc_numerics->SetCoord(geometry->nodes->GetCoord(iPoint), Coord_Reflected);
1457
1458 /*--- Primitive variables, and gradient ---*/
1459
1460 visc_numerics->SetPrimitive(PrimVar_i, PrimVar_j);
1461 visc_numerics->SetPrimVarGradient(nodes->GetGradient_Primitive(iPoint),
1462 nodes->GetGradient_Primitive(iPoint));
1463
1464 /*--- Turbulent kinetic energy ---*/
1465
1466 if (config->GetKind_Turb_Model() == TURB_MODEL::SST)
1467 visc_numerics->SetTurbKineticEnergy(solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0),
1468 solver_container[TURB_SOL]->GetNodes()->GetSolution(iPoint, 0));
1469
1470 /*--- Compute and update residual ---*/
1471
1472 auto residual = visc_numerics->ComputeResidual(config);
1473
1474 /*--- Accumulate the residuals to compute the average ---*/
1475
1476 for (iVar = 0; iVar < nVar; iVar++) {
1477 Residual[iVar] += weight * residual[iVar];
1478 for (jVar = 0; jVar < nVar; jVar++) Jacobian_i[iVar][jVar] += weight * residual.jacobian_i[iVar][jVar];
1479 }
1480 }
1481
1483
1484 /*--- Jacobian contribution for implicit integration ---*/
1485
1486 if (implicit) Jacobian.SubtractBlock2Diag(iPoint, Jacobian_i);
1487 }
1488 }
1489 }
1491 }
1492 }
1493
1494 for (iVar = 0; iVar < nVar; iVar++) delete[] Jacobian_i[iVar];
1495 delete[] Jacobian_i;
1496}
1497
1498template <class V, ENUM_REGIME R>
1499void CFVMFlowSolverBase<V, R>::BC_Custom(CGeometry* geometry, CSolver** solver_container, CNumerics* conv_numerics,
1500 CNumerics* visc_numerics, CConfig* config, unsigned short val_marker) {
1502
1503 /* Check for a verification solution. */
1504
1506 unsigned short iVar;
1507 unsigned long iVertex, iPoint;
1508
1509 bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
1510
1511 /*--- Get the physical time. ---*/
1512
1513 su2double time = 0.0;
1514 if (config->GetTime_Marching() != TIME_MARCHING::STEADY) time = config->GetPhysicalTime();
1515
1516 /*--- Loop over all the vertices on this boundary marker ---*/
1517
1519 for (iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
1520 /*--- Get the point index for the current node. ---*/
1521
1522 iPoint = geometry->vertex[val_marker][iVertex]->GetNode();
1523
1524 /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/
1525
1526 if (geometry->nodes->GetDomain(iPoint)) {
1527 /*--- Get the coordinates for the current node. ---*/
1528
1529 const su2double* coor = geometry->nodes->GetCoord(iPoint);
1530
1531 /*--- Get the conservative state from the verification solution. ---*/
1532
1533 su2double Solution[MAXNVAR] = {0.0};
1535
1536 /*--- For verification cases, we will apply a strong Dirichlet
1537 condition by setting the solution values at the boundary nodes
1538 directly and setting the residual to zero at those nodes. ---*/
1539
1540 nodes->SetSolution_Old(iPoint, Solution);
1541 nodes->SetSolution(iPoint, Solution);
1542 nodes->SetRes_TruncErrorZero(iPoint);
1543 LinSysRes.SetBlock_Zero(iPoint);
1544
1545 /*--- Adjust rows of the Jacobian (includes 1 in the diagonal) ---*/
1546
1547 if (implicit) {
1548 for (iVar = 0; iVar < nVar; iVar++) {
1549 Jacobian.DeleteValsRowi(iPoint, iVar);
1550 }
1551 }
1552 }
1553 }
1555
1556 } else {
1557 /* The user must specify the custom BC's here. */
1558 SU2_MPI::Error("Implement customized boundary conditions here.", CURRENT_FUNCTION);
1559 }
1560}
1561
1562template <class V, ENUM_REGIME R>
1564 const CSolver* const* solvers,
1565 CConfig *config) {
1567
1568 if (!edgeNumerics) {
1569 if (!ReducerStrategy && (omp_get_max_threads() > 1) &&
1570 (config->GetEdgeColoringGroupSize() % Double::Size != 0)) {
1571 SU2_MPI::Error("When using vectorization, the EDGE_COLORING_GROUP_SIZE must be divisible "
1572 "by the SIMD length (2, 4, or 8).", CURRENT_FUNCTION);
1573 }
1574 InstantiateEdgeNumerics(solvers, config);
1575
1576 /*--- The SIMD numerics do not use gradients of density and enthalpy. ---*/
1577 if (!config->GetContinuous_Adjoint()) {
1578 SU2_OMP_SAFE_GLOBAL_ACCESS(nPrimVarGrad = std::min<unsigned short>(nDim + 2, nPrimVarGrad);)
1579 }
1580 }
1581
1582 /*--- Non-physical counter. ---*/
1583 unsigned long counterLocal = 0;
1585 ErrorCounter = 0;
1587
1588 su2activevector* massFluxes = config->GetBounded_Scalar() ? &EdgeMassFluxes : nullptr;
1589
1590 /*--- For hybrid parallel AD, pause preaccumulation if there is shared reading of
1591 * variables, otherwise switch to the faster adjoint evaluation mode. ---*/
1592 bool pausePreacc = false;
1593 if (ReducerStrategy) pausePreacc = AD::PausePreaccumulation();
1595
1596 /*--- Loop over edge colors. ---*/
1597 for (auto color : EdgeColoring) {
1598 /*--- Chunk size is at least OMP_MIN_SIZE and a multiple of the color group size. ---*/
1599 SU2_OMP_FOR_DYN(nextMultiple(OMP_MIN_SIZE, color.groupSize))
1600 for(auto k = 0ul; k < color.size; k += Double::Size) {
1601 Int iEdge;
1602 Double mask;
1603 for (auto j = 0ul; j < Double::Size; ++j) {
1604 bool in = (k+j < color.size);
1605 mask[j] = in;
1606 iEdge[j] = color.indices[k+j*in];
1607 }
1608
1609 if (ReducerStrategy) {
1610 edgeNumerics->ComputeFlux(iEdge, *config, *geometry, *nodes, UpdateType::REDUCTION, mask, EdgeFluxes, Jacobian, massFluxes);
1611 } else {
1612 edgeNumerics->ComputeFlux(iEdge, *config, *geometry, *nodes, UpdateType::COLORING, mask, LinSysRes, Jacobian, massFluxes);
1613 }
1614 if (MGLevel == MESH_0) {
1615 for (auto j = 0ul; j < Double::Size; ++j)
1616 counterLocal += (nodes->NonPhysicalEdgeCounter[iEdge[j]] > 0);
1617 }
1618 }
1620 }
1621
1622 FinalizeResidualComputation(geometry, pausePreacc, counterLocal, config);
1623}
1624
1625template <class V, ENUM_REGIME R>
1628
1630 for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) {
1631
1632 LinSysRes.SetBlock_Zero(iPoint);
1633
1634 for (auto iEdge : geometry->nodes->GetEdges(iPoint)) {
1635 if (iPoint == geometry->edges->GetNode(iEdge,0))
1636 LinSysRes.AddBlock(iPoint, EdgeFluxes.GetBlock(iEdge));
1637 else
1639 }
1640 }
1642}
1643
1644template <class V, ENUM_REGIME FlowRegime>
1646 CConfig *config, unsigned short iRKStep, unsigned short iMesh,
1647 unsigned short RunTime_EqSystem) {
1648 /*--- Local variables ---*/
1649
1650 unsigned short iVar, iMarker, iDim, iNeigh;
1651 unsigned long iPoint, jPoint, iEdge, iVertex;
1652
1653 const su2double *U_time_nM1 = nullptr, *U_time_n = nullptr, *U_time_nP1 = nullptr;
1654 su2double Volume_nM1, Volume_nP1, TimeStep;
1655 const su2double *Normal = nullptr, *GridVel_i = nullptr, *GridVel_j = nullptr;
1656 su2double Residual_GCL;
1657
1658 const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
1659 const bool first_order = (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_1ST);
1660 const bool second_order = (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND);
1661
1662 /*--- Store the physical time step ---*/
1663
1664 TimeStep = config->GetDelta_UnstTimeND();
1665
1666 /*--- Compute the dual time-stepping source term for static meshes ---*/
1667
1668 if (!dynamic_grid) {
1669
1670 /*--- Loop over all nodes (excluding halos) ---*/
1671
1673
1675 for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
1676
1677 /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that
1678 we are currently iterating on U^n+1 and that U^n & U^n-1 are fixed,
1679 previous solutions that are stored in memory. ---*/
1680
1681 U_time_nM1 = nodes->GetSolution_time_n1(iPoint);
1682 U_time_n = nodes->GetSolution_time_n(iPoint);
1683 U_time_nP1 = nodes->GetSolution(iPoint);
1684
1685 /*--- CV volume at time n+1. As we are on a static mesh, the volume
1686 of the CV will remained fixed for all time steps. ---*/
1687
1688 Volume_nP1 = geometry->nodes->GetVolume(iPoint);
1689
1690 /*--- Compute the dual time-stepping source term based on the chosen
1691 time discretization scheme (1st- or 2nd-order).---*/
1692
1693 for (iVar = 0; iVar < nVar; iVar++) {
1694 if (first_order)
1695 LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*Volume_nP1 / TimeStep;
1696 if (second_order)
1697 LinSysRes(iPoint,iVar) += ( 3.0*U_time_nP1[iVar] - 4.0*U_time_n[iVar]
1698 +1.0*U_time_nM1[iVar])*Volume_nP1 / (2.0*TimeStep);
1699 }
1700
1701 /*--- Compute the Jacobian contribution due to the dual time source term. ---*/
1702 if (implicit) {
1703 if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep);
1704 if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep));
1705 }
1706 }
1708
1710
1711 }
1712
1713 else {
1714
1715 /*--- For unsteady flows on dynamic meshes (rigidly transforming or
1716 dynamically deforming), the Geometric Conservation Law (GCL) should be
1717 satisfied in conjunction with the ALE formulation of the governing
1718 equations. The GCL prevents accuracy issues caused by grid motion, i.e.
1719 a uniform free-stream should be preserved through a moving grid. First,
1720 we will loop over the edges and boundaries to compute the GCL component
1721 of the dual time source term that depends on grid velocities. ---*/
1722
1724 for (iPoint = 0; iPoint < nPointDomain; ++iPoint) {
1725
1726 GridVel_i = geometry->nodes->GetGridVel(iPoint);
1727 U_time_n = nodes->GetSolution_time_n(iPoint);
1728
1729 for (iNeigh = 0; iNeigh < geometry->nodes->GetnPoint(iPoint); iNeigh++) {
1730
1731 iEdge = geometry->nodes->GetEdge(iPoint, iNeigh);
1732 Normal = geometry->edges->GetNormal(iEdge);
1733
1734 jPoint = geometry->nodes->GetPoint(iPoint, iNeigh);
1735 GridVel_j = geometry->nodes->GetGridVel(jPoint);
1736
1737 /*--- Determine whether to consider the normal outward or inward. ---*/
1738 su2double dir = (iPoint < jPoint)? 0.5 : -0.5;
1739
1740 Residual_GCL = 0.0;
1741 for (iDim = 0; iDim < nDim; iDim++)
1742 Residual_GCL += dir*(GridVel_i[iDim]+GridVel_j[iDim])*Normal[iDim];
1743
1744 for (iVar = 0; iVar < nVar; iVar++)
1745 LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL;
1746 }
1747 }
1749
1750 /*--- Loop over the boundary edges ---*/
1751
1752 for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
1753 if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
1754 (config->GetMarker_All_KindBC(iMarker) != NEARFIELD_BOUNDARY) &&
1755 (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
1756
1758 for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
1759
1760 /*--- Get the index for node i plus the boundary face normal ---*/
1761
1762 iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
1763 Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
1764
1765 /*--- Grid velocities stored at boundary node i ---*/
1766
1767 GridVel_i = geometry->nodes->GetGridVel(iPoint);
1768
1769 /*--- Compute the GCL term by dotting the grid velocity with the face
1770 normal. The normal is negated to match the boundary convention. ---*/
1771
1772 Residual_GCL = 0.0;
1773 for (iDim = 0; iDim < nDim; iDim++)
1774 Residual_GCL -= 0.5*(GridVel_i[iDim]+GridVel_i[iDim])*Normal[iDim];
1775
1776 /*--- Compute the GCL component of the source term for node i ---*/
1777
1778 U_time_n = nodes->GetSolution_time_n(iPoint);
1779 for (iVar = 0; iVar < nVar; iVar++)
1780 LinSysRes(iPoint,iVar) += U_time_n[iVar]*Residual_GCL;
1781 }
1783 }
1784 }
1785
1786 /*--- Loop over all nodes (excluding halos) to compute the remainder
1787 of the dual time-stepping source term. ---*/
1788
1790
1792 for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
1793
1794 /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that
1795 we are currently iterating on U^n+1 and that U^n & U^n-1 are fixed,
1796 previous solutions that are stored in memory. ---*/
1797
1798 U_time_nM1 = nodes->GetSolution_time_n1(iPoint);
1799 U_time_n = nodes->GetSolution_time_n(iPoint);
1800 U_time_nP1 = nodes->GetSolution(iPoint);
1801
1802 /*--- CV volume at time n-1 and n+1. In the case of dynamically deforming
1803 grids, the volumes will change. On rigidly transforming grids, the
1804 volumes will remain constant. ---*/
1805
1806 Volume_nM1 = geometry->nodes->GetVolume_nM1(iPoint);
1807 Volume_nP1 = geometry->nodes->GetVolume(iPoint);
1808
1809 /*--- Compute the dual time-stepping source residual. Due to the
1810 introduction of the GCL term above, the remainder of the source residual
1811 due to the time discretization has a new form.---*/
1812
1813 for (iVar = 0; iVar < nVar; iVar++) {
1814 if (first_order)
1815 LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(Volume_nP1/TimeStep);
1816 if (second_order)
1817 LinSysRes(iPoint,iVar) += (U_time_nP1[iVar] - U_time_n[iVar])*(3.0*Volume_nP1/(2.0*TimeStep))
1818 + (U_time_nM1[iVar] - U_time_n[iVar])*(Volume_nM1/(2.0*TimeStep));
1819 }
1820
1821 /*--- Compute the Jacobian contribution due to the dual time source term. ---*/
1822 if (implicit) {
1823 if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1/TimeStep);
1824 if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1*3.0)/(2.0*TimeStep));
1825 }
1826 }
1828
1830 }
1831
1832}
1833
1834/*--- Helpers shared by Pressure_Forces, Momentum_Forces and Friction_Forces. Free function
1835 * templates rather than members: none need instance state, and the AeroCoeffs/AeroCoeffsArray
1836 * types are simply deduced from the caller's arguments. ---*/
1837namespace {
1838
1839/*!
1840 * \brief Whether a marker's boundary kind is one of the momentum (inlet/outlet/actuator-disk/
1841 * engine) surfaces handled by Momentum_Forces, used both to gate accumulation into
1842 * MntCoeff and to gate the later CEff/CMerit derivation from it.
1843 * \param[in] Boundary - Boundary kind of the marker (config->GetMarker_All_KindBC(iMarker)).
1844 */
1845inline bool IsMomentumBoundary(unsigned short Boundary) {
1846 return (Boundary == INLET_FLOW) || (Boundary == OUTLET_FLOW) || (Boundary == ACTDISK_INLET) ||
1847 (Boundary == ACTDISK_OUTLET) || (Boundary == ENGINE_INFLOW) || (Boundary == ENGINE_EXHAUST);
1848}
1849
1850/*!
1851 * \brief Find iMarker's index within the monitoring markers, and its reference origin if found.
1852 * \param[in] config - Problem definition.
1853 * \param[in] iMarker - Marker to look up.
1854 * \param[in] Monitoring - config->GetMarker_All_Monitoring(iMarker).
1855 * \param[in,out] Origin - Set to iMarker's reference origin if found, left unchanged otherwise.
1856 * \return Index within the monitoring markers, or -1 if iMarker is not monitored, or not found
1857 * among the monitoring markers.
1858 */
1859inline int FindMonitoringIndex(const CConfig* config, unsigned long iMarker, unsigned short Monitoring,
1860 std::array<su2double, 3>& Origin) {
1861 if (Monitoring != YES) return -1;
1862 const string Marker_Tag = config->GetMarker_All_TagBound(iMarker);
1863 const auto nMarker_Monitoring = static_cast<int>(config->GetnMarker_Monitoring());
1864 for (int iMarker_Monitoring = 0; iMarker_Monitoring < nMarker_Monitoring; iMarker_Monitoring++) {
1865 if (Marker_Tag == config->GetMarker_Monitoring_TagBound(iMarker_Monitoring)) {
1866 Origin = config->GetRefOriginMoment(iMarker_Monitoring);
1867 return iMarker_Monitoring;
1868 }
1869 }
1870 return -1;
1871}
1872
1873/*!
1874 * \brief Fold one thread's partial force/moment coefficient contribution (accumulated over
1875 * its share of a marker's vertices) into the per-marker, AllBound and per-surface
1876 * aerodynamic coefficient totals, in a single critical section. Does not touch
1877 * CEff/CMerit (nonlinear ratios), those are derived once from the fully-reduced totals
1878 * after all threads have merged in.
1879 * \param[in] iMarker - Marker index the contribution belongs to.
1880 * \param[in] iMarker_Monitoring - If iMarker is monitored, index within the monitoring markers, -1 otherwise.
1881 * \param[in] partial - This thread's partial coefficients (CD, CL, ..., CQ only).
1882 * \param[in,out] coeffArray - Per-marker totals to update at iMarker.
1883 * \param[in,out] allBoundCoeff - Totals over all boundaries to update.
1884 * \param[in,out] surfaceCoeff - Per-monitoring-surface totals to update.
1885 */
1886template <class AeroCoeffsT, class AeroCoeffsArrayT>
1887void AddCoeffContribution(unsigned long iMarker, int iMarker_Monitoring, const AeroCoeffsT& partial,
1888 AeroCoeffsArrayT& coeffArray, AeroCoeffsT& allBoundCoeff, AeroCoeffsArrayT& surfaceCoeff) {
1890 coeffArray.CD[iMarker] += partial.CD;
1891 coeffArray.CL[iMarker] += partial.CL;
1892 coeffArray.CSF[iMarker] += partial.CSF;
1893 coeffArray.CFx[iMarker] += partial.CFx;
1894 coeffArray.CFy[iMarker] += partial.CFy;
1895 coeffArray.CFz[iMarker] += partial.CFz;
1896 coeffArray.CMx[iMarker] += partial.CMx;
1897 coeffArray.CMy[iMarker] += partial.CMy;
1898 coeffArray.CMz[iMarker] += partial.CMz;
1899 coeffArray.CoPx[iMarker] += partial.CoPx;
1900 coeffArray.CoPy[iMarker] += partial.CoPy;
1901 coeffArray.CoPz[iMarker] += partial.CoPz;
1902 coeffArray.CT[iMarker] += partial.CT;
1903 coeffArray.CQ[iMarker] += partial.CQ;
1904
1905 allBoundCoeff.CD += partial.CD;
1906 allBoundCoeff.CL += partial.CL;
1907 allBoundCoeff.CSF += partial.CSF;
1908 allBoundCoeff.CFx += partial.CFx;
1909 allBoundCoeff.CFy += partial.CFy;
1910 allBoundCoeff.CFz += partial.CFz;
1911 allBoundCoeff.CMx += partial.CMx;
1912 allBoundCoeff.CMy += partial.CMy;
1913 allBoundCoeff.CMz += partial.CMz;
1914 allBoundCoeff.CoPx += partial.CoPx;
1915 allBoundCoeff.CoPy += partial.CoPy;
1916 allBoundCoeff.CoPz += partial.CoPz;
1917 allBoundCoeff.CT += partial.CT;
1918 allBoundCoeff.CQ += partial.CQ;
1919
1920 /*--- Compute the coefficients per surface ---*/
1921
1922 if (iMarker_Monitoring >= 0) {
1923 surfaceCoeff.CL[iMarker_Monitoring] += partial.CL;
1924 surfaceCoeff.CD[iMarker_Monitoring] += partial.CD;
1925 surfaceCoeff.CSF[iMarker_Monitoring] += partial.CSF;
1926 surfaceCoeff.CFx[iMarker_Monitoring] += partial.CFx;
1927 surfaceCoeff.CFy[iMarker_Monitoring] += partial.CFy;
1928 surfaceCoeff.CFz[iMarker_Monitoring] += partial.CFz;
1929 surfaceCoeff.CMx[iMarker_Monitoring] += partial.CMx;
1930 surfaceCoeff.CMy[iMarker_Monitoring] += partial.CMy;
1931 surfaceCoeff.CMz[iMarker_Monitoring] += partial.CMz;
1932 }
1933 }
1935}
1936
1937/*!
1938 * \brief Project summed force/moment components onto the wind axes (Alpha, Beta) to get the
1939 * standard aerodynamic coefficients. Identical formulas are used by Pressure_Forces,
1940 * Momentum_Forces and Friction_Forces, applied respectively to their inviscid,
1941 * momentum and viscous force/moment sums. Does not set CEff/CMerit (nonlinear ratios,
1942 * derived later from fully-reduced totals) nor CSF/CMx/CMy/CFz/CoPz in 2D (n/a).
1943 * \param[in] nDim - Number of spatial dimensions (2 or 3).
1944 * \param[in] CosAlpha, SinAlpha, CosBeta, SinBeta - sin/cos of the angle of attack and sideslip,
1945 * precomputed once by the caller (this is called once per monitored marker, redundantly
1946 * by every thread, so recomputing the trig functions here would not be free).
1947 * \param[in] Force - Summed force components (size MAXNDIM).
1948 * \param[in] Moment - Summed moment components about Origin (size MAXNDIM).
1949 * \param[in] MomentX_Force, MomentY_Force, MomentZ_Force - Summed moment-of-force components
1950 * about the coordinate axes, used for the center-of-pressure coordinates.
1951 * \return The wind-axis aerodynamic coefficients (CD, CL, CSF, CFx..CFz, CMx..CMz, CoPx..CoPz,
1952 * CT, CQ). AeroCoeffsT is explicit at the call site (it can't be deduced, since it is
1953 * only the return type): ComputeAeroCoeffsFromForceMoment<AeroCoeffs>(...).
1954 */
1955template <class AeroCoeffsT>
1956AeroCoeffsT ComputeAeroCoeffsFromForceMoment(unsigned short nDim, su2double CosAlpha, su2double SinAlpha,
1957 su2double CosBeta, su2double SinBeta, const su2double* Force,
1958 const su2double* Moment, const su2double* MomentX_Force,
1959 const su2double* MomentY_Force, const su2double* MomentZ_Force) {
1960 AeroCoeffsT c;
1961
1962 if (nDim == 2) {
1963 c.CD = Force[0] * CosAlpha + Force[1] * SinAlpha;
1964 c.CL = -Force[0] * SinAlpha + Force[1] * CosAlpha;
1965 c.CMz = Moment[2];
1966 c.CoPx = MomentZ_Force[1];
1967 c.CoPy = -MomentZ_Force[0];
1968 c.CFx = Force[0];
1969 c.CFy = Force[1];
1970 c.CT = -c.CFx;
1971 c.CQ = -c.CMz;
1972 }
1973 if (nDim == 3) {
1974 c.CD = Force[0] * CosAlpha * CosBeta + Force[1] * SinBeta + Force[2] * SinAlpha * CosBeta;
1975 c.CL = -Force[0] * SinAlpha + Force[2] * CosAlpha;
1976 c.CSF = -Force[0] * SinBeta * CosAlpha + Force[1] * CosBeta - Force[2] * SinBeta * SinAlpha;
1977 c.CMx = Moment[0];
1978 c.CMy = Moment[1];
1979 c.CMz = Moment[2];
1980 c.CoPx = -MomentY_Force[0];
1981 c.CoPz = MomentY_Force[2];
1982 c.CFx = Force[0];
1983 c.CFy = Force[1];
1984 c.CFz = Force[2];
1985 c.CT = -c.CFz;
1986 c.CQ = -c.CMz;
1987 }
1988
1989 return c;
1990}
1991
1992/*!
1993 * \brief MPI-sum a single value across ranks (identity if not built with MPI).
1994 * \param[in] x - Value to reduce.
1995 * \return Sum of x over all ranks.
1996 */
1997inline su2double MPIReduceSum(su2double x) {
1998#ifdef HAVE_MPI
1999 su2double tmp = x;
2000 x = 0.0;
2002#endif
2003 return x;
2004}
2005
2006/*!
2007 * \brief MPI-sum an array of per-monitoring-surface values across ranks, in place
2008 * (no-op if not built with MPI).
2009 * \param[in,out] x - Array of size n to reduce in place.
2010 * \param[in] n - Number of entries in x.
2011 */
2012inline void MPIReduceSumInPlace(su2double* x, int n) {
2013#ifdef HAVE_MPI
2014 if (SU2_MPI::GetSize() == SINGLE_NODE) return;
2015 static vector<su2double> buffer;
2016 buffer.resize(n);
2017 SU2_MPI::Allreduce(x, buffer.data(), n, MPI_DOUBLE, MPI_SUM, SU2_MPI::GetComm());
2018 for (int i = 0; i < n; ++i) x[i] = buffer[i];
2019#endif
2020}
2021
2022/*!
2023 * \brief MPI-reduce an AllBound/Surface aerodynamic coefficient pair across ranks (no-op if
2024 * not built with MPI, or if the comm level does not require it).
2025 * \param[in] config - Definition of the particular problem.
2026 * \param[in,out] allBoundCoeff - Totals over all boundaries to reduce.
2027 * \param[in,out] surfaceCoeff - Per-monitoring-surface totals to reduce.
2028 */
2029template <class AeroCoeffsT, class AeroCoeffsArrayT>
2030void ReduceCoeffsMPI(const CConfig* config, AeroCoeffsT& allBoundCoeff, AeroCoeffsArrayT& surfaceCoeff) {
2031#ifdef HAVE_MPI
2032 if (config->GetComm_Level() != COMM_FULL) return;
2033
2034 /*--- Add AllBound information using all the nodes ---*/
2035
2036 allBoundCoeff.CD = MPIReduceSum(allBoundCoeff.CD);
2037 allBoundCoeff.CL = MPIReduceSum(allBoundCoeff.CL);
2038 allBoundCoeff.CSF = MPIReduceSum(allBoundCoeff.CSF);
2039 allBoundCoeff.CEff = allBoundCoeff.CL / (allBoundCoeff.CD + EPS);
2040
2041 allBoundCoeff.CMx = MPIReduceSum(allBoundCoeff.CMx);
2042 allBoundCoeff.CMy = MPIReduceSum(allBoundCoeff.CMy);
2043 allBoundCoeff.CMz = MPIReduceSum(allBoundCoeff.CMz);
2044
2045 allBoundCoeff.CoPx = MPIReduceSum(allBoundCoeff.CoPx);
2046 allBoundCoeff.CoPy = MPIReduceSum(allBoundCoeff.CoPy);
2047 allBoundCoeff.CoPz = MPIReduceSum(allBoundCoeff.CoPz);
2048
2049 allBoundCoeff.CFx = MPIReduceSum(allBoundCoeff.CFx);
2050 allBoundCoeff.CFy = MPIReduceSum(allBoundCoeff.CFy);
2051 allBoundCoeff.CFz = MPIReduceSum(allBoundCoeff.CFz);
2052
2053 allBoundCoeff.CT = MPIReduceSum(allBoundCoeff.CT);
2054 allBoundCoeff.CQ = MPIReduceSum(allBoundCoeff.CQ);
2055 allBoundCoeff.CMerit = allBoundCoeff.CT / (allBoundCoeff.CQ + EPS);
2056
2057 /*--- Add the forces on the surfaces using all the nodes ---*/
2058
2059 const int nMarkerMon = config->GetnMarker_Monitoring();
2060
2061 MPIReduceSumInPlace(surfaceCoeff.CL, nMarkerMon);
2062 MPIReduceSumInPlace(surfaceCoeff.CD, nMarkerMon);
2063 MPIReduceSumInPlace(surfaceCoeff.CSF, nMarkerMon);
2064
2065 for (int iMarker_Monitoring = 0; iMarker_Monitoring < nMarkerMon; iMarker_Monitoring++)
2066 surfaceCoeff.CEff[iMarker_Monitoring] =
2067 surfaceCoeff.CL[iMarker_Monitoring] / (surfaceCoeff.CD[iMarker_Monitoring] + EPS);
2068
2069 MPIReduceSumInPlace(surfaceCoeff.CFx, nMarkerMon);
2070 MPIReduceSumInPlace(surfaceCoeff.CFy, nMarkerMon);
2071 MPIReduceSumInPlace(surfaceCoeff.CFz, nMarkerMon);
2072
2073 MPIReduceSumInPlace(surfaceCoeff.CMx, nMarkerMon);
2074 MPIReduceSumInPlace(surfaceCoeff.CMy, nMarkerMon);
2075 MPIReduceSumInPlace(surfaceCoeff.CMz, nMarkerMon);
2076#endif
2077}
2078
2079/*!
2080 * \brief Merge an AllBound/Surface aerodynamic coefficient pair into the running total/
2081 * surfaceTotal grand totals.
2082 * \param[in] config - Definition of the particular problem.
2083 * \param[in] allBoundCoeff - Totals over all boundaries to merge in (already MPI-reduced).
2084 * \param[in] surfaceCoeff - Per-monitoring-surface totals to merge in (already MPI-reduced).
2085 * \param[in,out] total - Grand total to update (e.g. the solver's TotalCoeff).
2086 * \param[in,out] surfaceTotal - Per-surface grand total to update (e.g. the solver's SurfaceCoeff).
2087 * \param[in] overwrite - True to overwrite total/surfaceTotal (first contributor, i.e.
2088 * Pressure_Forces, which also resets them to zero beforehand), false to add to them.
2089 */
2090template <class AeroCoeffsT, class AeroCoeffsArrayT>
2091void AccumulateTotalCoeffs(const CConfig* config, const AeroCoeffsT& allBoundCoeff,
2092 const AeroCoeffsArrayT& surfaceCoeff, AeroCoeffsT& total, AeroCoeffsArrayT& surfaceTotal,
2093 bool overwrite) {
2094 auto Update = [overwrite](su2double& dst, su2double src) {
2095 if (overwrite) dst = src;
2096 else dst += src;
2097 };
2098
2099 Update(total.CD, allBoundCoeff.CD);
2100 Update(total.CL, allBoundCoeff.CL);
2101 Update(total.CSF, allBoundCoeff.CSF);
2102 total.CEff = total.CL / (total.CD + EPS);
2103 Update(total.CFx, allBoundCoeff.CFx);
2104 Update(total.CFy, allBoundCoeff.CFy);
2105 Update(total.CFz, allBoundCoeff.CFz);
2106 Update(total.CMx, allBoundCoeff.CMx);
2107 Update(total.CMy, allBoundCoeff.CMy);
2108 Update(total.CMz, allBoundCoeff.CMz);
2109 Update(total.CoPx, allBoundCoeff.CoPx);
2110 Update(total.CoPy, allBoundCoeff.CoPy);
2111 Update(total.CoPz, allBoundCoeff.CoPz);
2112 Update(total.CT, allBoundCoeff.CT);
2113 Update(total.CQ, allBoundCoeff.CQ);
2114 total.CMerit = total.CT / (total.CQ + EPS);
2115
2116 /*--- Update the total coefficients per surface (note that all the nodes have the same value)---*/
2117
2118 for (unsigned short iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring();
2119 iMarker_Monitoring++) {
2120 Update(surfaceTotal.CL[iMarker_Monitoring], surfaceCoeff.CL[iMarker_Monitoring]);
2121 Update(surfaceTotal.CD[iMarker_Monitoring], surfaceCoeff.CD[iMarker_Monitoring]);
2122 Update(surfaceTotal.CSF[iMarker_Monitoring], surfaceCoeff.CSF[iMarker_Monitoring]);
2123 surfaceTotal.CEff[iMarker_Monitoring] =
2124 surfaceTotal.CL[iMarker_Monitoring] / (surfaceTotal.CD[iMarker_Monitoring] + EPS);
2125 Update(surfaceTotal.CFx[iMarker_Monitoring], surfaceCoeff.CFx[iMarker_Monitoring]);
2126 Update(surfaceTotal.CFy[iMarker_Monitoring], surfaceCoeff.CFy[iMarker_Monitoring]);
2127 Update(surfaceTotal.CFz[iMarker_Monitoring], surfaceCoeff.CFz[iMarker_Monitoring]);
2128 Update(surfaceTotal.CMx[iMarker_Monitoring], surfaceCoeff.CMx[iMarker_Monitoring]);
2129 Update(surfaceTotal.CMy[iMarker_Monitoring], surfaceCoeff.CMy[iMarker_Monitoring]);
2130 Update(surfaceTotal.CMz[iMarker_Monitoring], surfaceCoeff.CMz[iMarker_Monitoring]);
2131 }
2132}
2133
2134/*!
2135 * \brief Fold one vertex's Force/MomentDist/Coord into the running moment sums. Identical
2136 * formulas are used by Pressure_Forces, Momentum_Forces and Friction_Forces, applied
2137 * respectively to their inviscid, momentum and viscous force/moment sums.
2138 * \param[in] nDim - Number of spatial dimensions (2 or 3).
2139 * \param[in] RefLength - Reference length used to non-dimensionalize the moments.
2140 * \param[in] Force, MomentDist, Coord - This vertex's force, moment arm and position (size MAXNDIM).
2141 * \param[in,out] Moment - Running moment sum about Origin.
2142 * \param[in,out] MomentX_Force, MomentY_Force, MomentZ_Force - Running moment-of-force sums about
2143 * the coordinate axes, used for the center-of-pressure coordinates.
2144 */
2145void AccumulateMoment(unsigned short nDim, su2double RefLength, const su2double* Force,
2146 const su2double* MomentDist, const su2double* Coord, su2double* Moment,
2147 su2double* MomentX_Force, su2double* MomentY_Force, su2double* MomentZ_Force) {
2148 if (nDim == 3) {
2149 Moment[0] += (Force[2] * MomentDist[1] - Force[1] * MomentDist[2]) / RefLength;
2150 MomentX_Force[1] += (-Force[1] * Coord[2]);
2151 MomentX_Force[2] += (Force[2] * Coord[1]);
2152
2153 Moment[1] += (Force[0] * MomentDist[2] - Force[2] * MomentDist[0]) / RefLength;
2154 MomentY_Force[2] += (-Force[2] * Coord[0]);
2155 MomentY_Force[0] += (Force[0] * Coord[2]);
2156 }
2157 Moment[2] += (Force[1] * MomentDist[0] - Force[0] * MomentDist[1]) / RefLength;
2158 MomentZ_Force[0] += (-Force[0] * Coord[1]);
2159 MomentZ_Force[1] += (Force[1] * Coord[0]);
2160}
2161
2162} // namespace
2163
2164template <class V, ENUM_REGIME FlowRegime>
2167
2168 const su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0;
2169 const su2double Beta = config->GetAoS() * PI_NUMBER / 180.0;
2170 /*--- Precomputed once here since ComputeAeroCoeffsFromForceMoment is called once per monitored
2171 * marker, redundantly by every thread (see below). ---*/
2172 const su2double CosAlpha = cos(Alpha), SinAlpha = sin(Alpha), CosBeta = cos(Beta), SinBeta = sin(Beta);
2173 const su2double RefArea = config->GetRefArea();
2174 const su2double RefLength = config->GetRefLength();
2175 auto Origin = config->GetRefOriginMoment(0);
2176 const bool axisymmetric = config->GetAxisymmetric();
2177
2178 /*--- Variables initialization, and other writes to shared (possibly AD-active) state,
2179 * are confined to the master thread, synchronized with a barrier so that the
2180 * subsequent parallel loop over markers sees consistent, zeroed accumulators. ---*/
2181
2183 SetReferenceValues(*config);
2184 Total_CNearFieldOF = 0.0;
2185 Total_Heat = 0.0;
2186 Total_MaxHeat = 0.0;
2188 /*--- AeroCoeffs::setZero is not parallel. ---*/
2191 }
2193
2196 InvCoeff.setZero();
2197
2199 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) CNearFieldOF_Inv[iMarker] = 0.0;
2201
2202 const su2double factor = 1.0 / AeroCoeffForceRef;
2203
2204 /*--- Reference pressure is always the far-field value. ---*/
2205
2206 const su2double RefPressure = Pressure_Inf;
2207
2208 /*--- Loop over the Euler and Navier-Stokes markers. Every thread runs this marker loop
2209 * redundantly; only the per-vertex loop nested inside it is work-shared (SU2_OMP_FOR_STAT).
2210 * Each thread accumulates its own partial force/moment sums and folds them into the shared
2211 * per-marker/AllBound/Surface totals via AddCoeffContribution. CEff/CMerit are nonlinear
2212 * ratios, so they are derived once after the loop, from the fully-reduced totals. ---*/
2213
2214 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2215 const auto Boundary = config->GetMarker_All_KindBC(iMarker);
2216
2217 if (config->GetSolid_Wall(iMarker) || (Boundary == NEARFIELD_BOUNDARY) || IsMomentumBoundary(Boundary)) {
2218
2219 /*--- Obtain the origin for the moment computation for a particular marker ---*/
2220
2221 const auto Monitoring = config->GetMarker_All_Monitoring(iMarker);
2222 const int iMarker_Monitoring = FindMonitoringIndex(config, iMarker, Monitoring, Origin);
2223
2224 su2double ForceInviscid[MAXNDIM] = {0.0}, MomentInviscid[MAXNDIM] = {0.0};
2225 su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0};
2226
2227 su2double NFPressOF = 0.0;
2228
2229 /*--- Loop over the vertices to compute the forces ---*/
2230
2231 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2232 for (unsigned long iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
2233 const auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2234
2235 const su2double Pressure = nodes->GetPressure(iPoint);
2236
2237 CPressure[iMarker][iVertex] = (Pressure - RefPressure) * factor * RefArea;
2239 /*--- Note that the pressure coefficient is computed at the
2240 halo cells (for visualization purposes), but not the forces ---*/
2241
2242 if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) {
2243 const su2double* Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
2244 const su2double* Coord = geometry->nodes->GetCoord(iPoint);
2245
2246 /*--- Quadratic objective function for the near-field.
2247 This uses the infinity pressure regardless of Mach number. ---*/
2248
2249 NFPressOF += 0.5 * (Pressure - Pressure_Inf) * (Pressure - Pressure_Inf) * Normal[nDim - 1];
2250
2251 su2double MomentDist[MAXNDIM] = {0.0};
2252 GeometryToolbox::Distance(nDim, Coord, Origin.data(), MomentDist);
2253
2254 /*--- Axisymmetric simulations ---*/
2255
2256 const su2double AxiFactor = axisymmetric ? su2double(2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1)) : su2double(1.0);
2257
2258 /*--- Force computation, note the minus sign due to the
2259 orientation of the normal (outward) ---*/
2260
2261 su2double Force[MAXNDIM] = {0.0};
2262 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2263 Force[iDim] = -(Pressure - Pressure_Inf) * Normal[iDim] * factor * AxiFactor;
2264 ForceInviscid[iDim] += Force[iDim];
2265 }
2266
2267 /*--- Moment with respect to the reference axis ---*/
2268
2269 AccumulateMoment(nDim, RefLength, Force, MomentDist, Coord, MomentInviscid, MomentX_Force, MomentY_Force,
2270 MomentZ_Force);
2271 }
2272 }
2274
2275 if (Monitoring == YES) {
2276 if (Boundary != NEARFIELD_BOUNDARY) {
2277 const auto partial = ComputeAeroCoeffsFromForceMoment<AeroCoeffs>(
2278 nDim, CosAlpha, SinAlpha, CosBeta, SinBeta, ForceInviscid, MomentInviscid, MomentX_Force, MomentY_Force,
2279 MomentZ_Force);
2280
2281 AddCoeffContribution(iMarker, iMarker_Monitoring, partial, InvCoeff, AllBoundInvCoeff, SurfaceInvCoeff);
2282 } else {
2283 /*--- At the Nearfield SU2 only cares about the pressure coeffient ---*/
2285 CNearFieldOF_Inv[iMarker] += NFPressOF;
2286 AllBound_CNearFieldOF_Inv += NFPressOF;
2287 }
2290 }
2291 }
2292 }
2293 /*--- For the SU2_NOWAIT in the vertex loop. ---*/
2295
2296 /*--- Derive the (nonlinear) per-marker, AllBound and Surface ratio coefficients from the
2297 * now fully-reduced totals. This must happen once, after every thread has finished
2298 * folding its partial contributions above (guaranteed by the barrier at the start of
2299 * the safe-global-access section). ---*/
2300
2301 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2302 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2303 const auto Boundary = config->GetMarker_All_KindBC(iMarker);
2304 const auto Monitoring = config->GetMarker_All_Monitoring(iMarker);
2305 if (Monitoring == YES && Boundary != NEARFIELD_BOUNDARY) {
2306 InvCoeff.CEff[iMarker] = InvCoeff.CL[iMarker] / (InvCoeff.CD[iMarker] + EPS);
2307 InvCoeff.CMerit[iMarker] = InvCoeff.CT[iMarker] / (InvCoeff.CQ[iMarker] + EPS);
2308 }
2309 }
2311
2312 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2313 for (unsigned short iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring();
2314 iMarker_Monitoring++) {
2315 SurfaceInvCoeff.CEff[iMarker_Monitoring] =
2316 SurfaceInvCoeff.CL[iMarker_Monitoring] / (SurfaceInvCoeff.CD[iMarker_Monitoring] + EPS);
2317 }
2319
2323
2324 ReduceCoeffsMPI(config, AllBoundInvCoeff, SurfaceInvCoeff);
2325
2326 /*--- AllBound_CNearFieldOF_Inv, not covered by ReduceCoeffsMPI, is reduced separately. ---*/
2327 if (config->GetComm_Level() == COMM_FULL) {
2329 }
2330
2331 AccumulateTotalCoeffs(config, AllBoundInvCoeff, SurfaceInvCoeff, TotalCoeff, SurfaceCoeff, /*overwrite=*/true);
2333 }
2335}
2336
2337template <class V, ENUM_REGIME FlowRegime>
2340
2341 const su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0;
2342 const su2double Beta = config->GetAoS() * PI_NUMBER / 180.0;
2343 const su2double CosAlpha = cos(Alpha), SinAlpha = sin(Alpha), CosBeta = cos(Beta), SinBeta = sin(Beta);
2344 const su2double RefLength = config->GetRefLength();
2345 auto Origin = config->GetRefOriginMoment(0);
2346 const bool axisymmetric = config->GetAxisymmetric();
2347
2348 const su2double factor = 1.0 / AeroCoeffForceRef;
2349
2352 MntCoeff.setZero();
2353
2354 /*--- Loop over the Inlet-Outlet Markers (see Pressure_Forces for how the parallel
2355 * reduction over threads is organized). ---*/
2356
2357 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2358 const auto Boundary = config->GetMarker_All_KindBC(iMarker);
2359 if (!IsMomentumBoundary(Boundary)) continue;
2360
2361 const auto Monitoring = config->GetMarker_All_Monitoring(iMarker);
2362
2363 /*--- Obtain the origin for the moment computation for a particular marker ---*/
2364
2365 const int iMarker_Monitoring = FindMonitoringIndex(config, iMarker, Monitoring, Origin);
2366
2367 su2double ForceMomentum[MAXNDIM] = {0.0}, MomentMomentum[MAXNDIM] = {0.0};
2368 su2double MomentX_Force[3] = {0.0}, MomentY_Force[3] = {0.0}, MomentZ_Force[3] = {0.0};
2369
2370 /*--- Loop over the vertices to compute the forces (work-shared across threads, see
2371 * Pressure_Forces for why the chunk size is computed and the barrier skipped). ---*/
2372
2373 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2374 for (unsigned long iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
2375 const auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2376
2377 /*--- Note that the pressure coefficient is computed at the
2378 halo cells (for visualization purposes), but not the forces ---*/
2379
2380 if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) {
2381 const su2double* Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
2382 const su2double* Coord = geometry->nodes->GetCoord(iPoint);
2383 const su2double Density = nodes->GetDensity(iPoint);
2384 su2double MassFlow = 0.0;
2385 su2double Velocity[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0};
2386 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2387 Velocity[iDim] = nodes->GetVelocity(iPoint, iDim);
2388 MomentDist[iDim] = Coord[iDim] - Origin[iDim];
2389 MassFlow -= Normal[iDim] * Velocity[iDim] * Density;
2390 }
2391
2392 /*--- Axisymmetric simulations ---*/
2393
2394 const su2double AxiFactor = axisymmetric ? su2double(2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1)) : su2double(1.0);
2395
2396 /*--- Force computation, note the minus sign due to the
2397 orientation of the normal (outward) ---*/
2398
2399 su2double Force[MAXNDIM] = {0.0};
2400 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2401 Force[iDim] = MassFlow * Velocity[iDim] * factor * AxiFactor;
2402 ForceMomentum[iDim] += Force[iDim];
2403 }
2404
2405 /*--- Moment with respect to the reference axis ---*/
2406
2407 AccumulateMoment(nDim, RefLength, Force, MomentDist, Coord, MomentMomentum, MomentX_Force, MomentY_Force,
2408 MomentZ_Force);
2409 }
2410 }
2412
2413 if (Monitoring == YES) {
2414 const auto partial = ComputeAeroCoeffsFromForceMoment<AeroCoeffs>(
2415 nDim, CosAlpha, SinAlpha, CosBeta, SinBeta, ForceMomentum, MomentMomentum, MomentX_Force, MomentY_Force,
2416 MomentZ_Force);
2417
2418 AddCoeffContribution(iMarker, iMarker_Monitoring, partial, MntCoeff, AllBoundMntCoeff, SurfaceMntCoeff);
2419 }
2420 }
2421 /*--- For the SU2_NOWAIT in the vertex loop. ---*/
2423
2424 /*--- Derive the ratio coefficients from the fully-reduced totals, once. ---*/
2425
2426 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2427 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2428 const auto Boundary = config->GetMarker_All_KindBC(iMarker);
2429 const auto Monitoring = config->GetMarker_All_Monitoring(iMarker);
2430 if (Monitoring == YES && IsMomentumBoundary(Boundary)) {
2431 MntCoeff.CEff[iMarker] = MntCoeff.CL[iMarker] / (MntCoeff.CD[iMarker] + EPS);
2432 MntCoeff.CMerit[iMarker] = MntCoeff.CT[iMarker] / (MntCoeff.CQ[iMarker] + EPS);
2433 }
2434 }
2436
2437 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2438 for (unsigned short iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring();
2439 iMarker_Monitoring++) {
2440 SurfaceMntCoeff.CEff[iMarker_Monitoring] =
2441 SurfaceMntCoeff.CL[iMarker_Monitoring] / (SurfaceMntCoeff.CD[iMarker_Monitoring] + EPS);
2442 }
2444
2448
2449 ReduceCoeffsMPI(config, AllBoundMntCoeff, SurfaceMntCoeff);
2450 AccumulateTotalCoeffs(config, AllBoundMntCoeff, SurfaceMntCoeff, TotalCoeff, SurfaceCoeff, /*overwrite=*/false);
2451 }
2453}
2454
2455template <class V, ENUM_REGIME FlowRegime>
2458 if (!config->GetViscous()) return;
2459
2460 constexpr int MaxNorm = 8;
2461 const su2double minYPlus = config->GetwallModel_MinYPlus();
2462
2463 const su2double Alpha = config->GetAoA() * PI_NUMBER / 180.0;
2464 const su2double Beta = config->GetAoS() * PI_NUMBER / 180.0;
2465 const su2double CosAlpha = cos(Alpha), SinAlpha = sin(Alpha), CosBeta = cos(Beta), SinBeta = sin(Beta);
2466 const su2double RefLength = config->GetRefLength();
2467 const su2double RefHeatFlux = config->GetHeat_Flux_Ref();
2468 const su2double RefTemperature = config->GetTemperature_Ref();
2469 auto Origin = config->GetRefOriginMoment(0);
2470
2471 const bool energy = config->GetEnergy_Equation();
2472 const bool QCR = config->GetSAParsedOptions().qcr2000;
2473 const bool axisymmetric = config->GetAxisymmetric();
2474 const bool roughwall = (config->GetnRoughWall() > 0);
2475 const bool nemo = config->GetNEMOProblem();
2476
2477 const su2double factor = 1.0 / AeroCoeffForceRef;
2478 const su2double factorFric = config->GetRefArea() * factor;
2479
2480 /*--- Variables initialization ---*/
2481
2483 AllBound_HF_Visc = 0.0;
2484 AllBound_MaxHF_Visc = 0.0;
2486 }
2488
2490
2491 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2492 for (unsigned short iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring();
2493 iMarker_Monitoring++) {
2494 Surface_HF_Visc[iMarker_Monitoring] = 0.0;
2495 Surface_MaxHF_Visc[iMarker_Monitoring] = 0.0;
2496 }
2498
2500 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2501 if (!config->GetViscous_Wall(iMarker)) continue;
2502 ViscCoeff.setZero(iMarker);
2503 HF_Visc[iMarker] = 0.0;
2504 MaxHF_Visc[iMarker] = 0.0;
2505 }
2507
2508 /*--- Loop over the Navier-Stokes markers (see Pressure_Forces for how the parallel
2509 * reduction over threads is organized). The per-vertex loop below is the expensive
2510 * part (stress-tensor and heat-flux evaluations) and is work-shared across threads. ---*/
2511
2512 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2513
2514 if (!config->GetViscous_Wall(iMarker)) continue;
2515 const auto Marker_Tag = config->GetMarker_All_TagBound(iMarker);
2516 const auto Monitoring = config->GetMarker_All_Monitoring(iMarker);
2517 const bool py_custom = config->GetMarker_All_PyCustom(iMarker);
2518
2519 /*--- Obtain the origin for the moment computation for a particular marker ---*/
2520
2521 const int iMarker_Monitoring = FindMonitoringIndex(config, iMarker, Monitoring, Origin);
2522
2523 su2double ForceViscous[MAXNDIM] = {0.0}, MomentViscous[MAXNDIM] = {0.0};
2524 su2double MomentX_Force[MAXNDIM] = {0.0}, MomentY_Force[MAXNDIM] = {0.0}, MomentZ_Force[MAXNDIM] = {0.0};
2525 su2double HF_Visc_Local = 0.0, MaxHF_Visc_Local = 0.0;
2526
2527 /* --- check if wall functions are used --- */
2528
2529 const bool wallfunctions = (config->GetWallFunction_Treatment(Marker_Tag) != WALL_FUNCTIONS::NONE);
2530
2531 /*--- Marker-level lookups hoisted out of the per-vertex loop below: GetWallRoughnessProperties,
2532 * GetWall_HeatFlux, GetIsothermal_Temperature and GetCatalytic_Wall all scan over marker
2533 * lists (some by string comparison), so evaluating them once per vertex instead of once per
2534 * marker was a real cost for markers with many vertices. ---*/
2535
2536 WALL_TYPE WallType = WALL_TYPE::SMOOTH;
2537 if (roughwall) {
2538 su2double Roughness_Height;
2539 tie(WallType, Roughness_Height) = config->GetWallRoughnessProperties(Marker_Tag);
2540 }
2541
2542 const auto KindBC = config->GetMarker_All_KindBC(iMarker);
2543 su2double Wall_HeatFlux_Value = 0.0, Twall = 0.0;
2544 if (!nemo && !py_custom) {
2545 if (KindBC == BC_TYPE::HEAT_FLUX) {
2546 Wall_HeatFlux_Value = -config->GetWall_HeatFlux(Marker_Tag);
2547 if (config->GetIntegrated_HeatFlux()) Wall_HeatFlux_Value /= geometry->GetSurfaceArea(config, iMarker);
2548 } else if (KindBC == BC_TYPE::ISOTHERMAL) {
2549 Twall = config->GetIsothermal_Temperature(Marker_Tag) / RefTemperature;
2550 }
2551 }
2552 const bool catalytic = nemo && config->GetCatalytic_Wall(iMarker);
2553
2554 /*--- Loop over the vertices to compute the forces (work-shared across threads, see
2555 * Pressure_Forces for why the chunk size is computed and the barrier skipped). ---*/
2556
2557 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2558 for (unsigned long iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2559 const auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2560
2561 const su2double* Coord = geometry->nodes->GetCoord(iPoint);
2562
2563 const su2double* Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
2564
2565 /*--- One view covering the whole velocity-gradient block, instead of nDim*nDim separate
2566 * single-element lookups (ComputeStressTensor/AddQCR accept any [][]-indexable type). ---*/
2567 const auto Grad_Vel = nodes->GetVelocityGradient(iPoint);
2568
2569 su2double Grad_Temp[3] = {0.0}, Grad_Temp_ve[3] = {0.0};
2570 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2571 Grad_Temp[iDim] = nodes->GetGradient_Primitive(iPoint, prim_idx.Temperature(), iDim);
2572 if (nemo) Grad_Temp_ve[iDim] = nodes->GetGradient_Primitive(iPoint, prim_idx.Temperature_ve(), iDim);
2573 }
2574
2575 su2double Viscosity = nodes->GetLaminarViscosity(iPoint);
2576 su2double EddyViscosity = 0.0;
2577 if (WallType == WALL_TYPE::ROUGH) {
2578 EddyViscosity = nodes->GetEddyViscosity(iPoint);
2579 Viscosity += EddyViscosity;
2580 }
2581 const su2double Density = nodes->GetDensity(iPoint);
2582
2583 const su2double Area = GeometryToolbox::Norm(nDim, Normal);
2584 su2double UnitNormal[3] = {0.0};
2585 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2586 UnitNormal[iDim] = Normal[iDim] / Area;
2587 }
2588
2589 /*--- Evaluate Tau ---*/
2590 su2double Tau[3][3] = {{0.0}};
2591 CNumerics::ComputeStressTensor(nDim, Tau, Grad_Vel, Viscosity);
2592
2593 /*--- If necessary evaluate the QCR contribution to Tau ---*/
2594
2595 if (QCR) CNumerics::AddQCR(nDim, Grad_Vel, Tau, EddyViscosity / Viscosity);
2596
2597 /*--- Project Tau in each surface element ---*/
2598
2599 su2double TauElem[3] = {0.0};
2600 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2601 for (unsigned short jDim = 0; jDim < nDim; jDim++) {
2602 TauElem[iDim] += Tau[iDim][jDim] * UnitNormal[jDim];
2603 }
2604 }
2605
2606 /*--- Compute wall shear stress (using the stress tensor). Compute wall skin friction coefficient, and heat flux
2607 * on the wall ---*/
2608
2609 su2double TauTangent[MAXNDIM] = {0.0};
2610 GeometryToolbox::TangentProjection(nDim, Tau, UnitNormal, TauTangent);
2611
2612 WallShearStress[iMarker][iVertex] = GeometryToolbox::Norm(int(MAXNDIM), TauTangent);
2613
2614 /*--- For wall functions, the wall stresses need to be scaled by the wallfunction stress Tau_Wall---*/
2615 if (wallfunctions && (YPlus[iMarker][iVertex] > minYPlus)){
2616 const su2double Tau_Wall = nodes->GetTau_Wall(iPoint);
2617 const su2double scale = Tau_Wall / WallShearStress[iMarker][iVertex];
2618 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2619 TauTangent[iDim] *= scale;
2620 TauElem[iDim] *= scale;
2621 }
2622
2623 WallShearStress[iMarker][iVertex] = Tau_Wall;
2624 }
2625
2626 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2627 CSkinFriction[iMarker](iVertex,iDim) = TauTangent[iDim] * factorFric;
2628 }
2629
2630 /*--- Compute non-dimensional velocity and y+ ---*/
2631
2632 const su2double FrictionVel = sqrt(fabs(WallShearStress[iMarker][iVertex]) / Density);
2633
2634 if (!wallfunctions && MGLevel == MESH_0 && geometry->nodes->GetDomain(iPoint)) {
2635 // for CMultiGridGeometry and halos, the nearest neighbor distance is not set
2636 const su2double WallDistMod = geometry->vertex[iMarker][iVertex]->GetNearestNeighborDistance();
2637 YPlus[iMarker][iVertex] = WallDistMod * FrictionVel * Density / Viscosity;
2638 }
2639
2640 /*--- Compute total and maximum heat flux on the wall ---*/
2641
2642 if (!nemo) {
2643 su2double thermal_conductivity = 0.0;
2644 if ((FlowRegime == ENUM_REGIME::COMPRESSIBLE) || (FlowRegime == ENUM_REGIME::INCOMPRESSIBLE)) {
2645 thermal_conductivity = nodes->GetThermalConductivity(iPoint);
2646 }
2647
2648 if (KindBC == BC_TYPE::HEAT_FLUX) {
2649 HeatFlux[iMarker][iVertex] =
2650 py_custom ? -geometry->GetCustomBoundaryHeatFlux(iMarker, iVertex) : Wall_HeatFlux_Value;
2651 } else if (KindBC == BC_TYPE::ISOTHERMAL) {
2652 const su2double Twall_local =
2653 py_custom ? geometry->GetCustomBoundaryTemperature(iMarker, iVertex) / RefTemperature : Twall;
2654 const auto iPointNormal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor();
2655 const su2double* Coord_Normal = geometry->nodes->GetCoord(iPointNormal);
2656 const su2double dist_ij = GeometryToolbox::NormalDistance(nDim, UnitNormal, Coord, Coord_Normal);
2657 const su2double There = nodes->GetTemperature(iPointNormal);
2658 HeatFlux[iMarker][iVertex] = thermal_conductivity * (There - Twall_local) / dist_ij * RefHeatFlux;
2659 } else {
2660 su2double dTdn = GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal);
2661 if (FlowRegime == ENUM_REGIME::INCOMPRESSIBLE && !energy) dTdn = 0.0;
2662 HeatFlux[iMarker][iVertex] = thermal_conductivity * dTdn * RefHeatFlux;
2663 }
2664 } else {
2665
2666 const auto& thermal_conductivity_tr = nodes->GetThermalConductivity(iPoint);
2667 const auto& thermal_conductivity_ve = nodes->GetThermalConductivity_ve(iPoint);
2668
2669 const su2double dTdn = -GeometryToolbox::DotProduct(nDim, Grad_Temp, UnitNormal);
2670 const su2double dTvedn = -GeometryToolbox::DotProduct(nDim, Grad_Temp_ve, UnitNormal);
2671
2672 /*--- Surface energy balance: trans-rot heat flux, vib-el heat flux ---*/
2673 HeatFlux[iMarker][iVertex] = -(thermal_conductivity_tr*dTdn + thermal_conductivity_ve*dTvedn);
2674
2675 /*--- Compute enthalpy transport to surface due to mass diffusion ---*/
2676 if (catalytic) {
2677
2678 const auto nSpecies = config->GetnSpecies();
2679 const auto& Grad_PrimVar = nodes->GetGradient_Primitive(iPoint);
2680 const auto& PrimVar = nodes->GetPrimitive(iPoint);
2681 const auto& Ds = nodes->GetDiffusionCoeff(iPoint);
2682 const auto& hs = nodes->GetEnthalpys(iPoint);
2683 const su2double rho = PrimVar[prim_idx.Density()];
2684
2685 su2double sumJhs = 0.0;
2686 for (auto iSpecies = 0u; iSpecies < nSpecies; iSpecies++) {
2687 for (auto iDim = 0u; iDim < nDim; iDim++) {
2688 su2double dYdn = 1.0/rho*(Grad_PrimVar[iSpecies][iDim] - PrimVar[iSpecies]*Grad_PrimVar[prim_idx.Density()][iDim]/rho);
2689 sumJhs += rho*Ds[iSpecies]*hs[iSpecies]*dYdn*UnitNormal[iDim];
2690 }
2691 }
2692 /*--- Surface energy balance: mass diffusion ---*/
2693 HeatFlux[iMarker][iVertex] += sumJhs;
2694
2695 }
2696 }
2697
2698 /*--- Note that heat is computed at the
2699 halo cells (for visualization purposes), but not the forces ---*/
2700
2701 if ((geometry->nodes->GetDomain(iPoint)) && (Monitoring == YES)) {
2702 /*--- Axisymmetric simulations ---*/
2703
2704 const su2double AxiFactor = axisymmetric ? su2double(2.0 * PI_NUMBER * geometry->nodes->GetCoord(iPoint, 1)) : su2double(1.0);
2705
2706 /*--- Force computation ---*/
2707
2708 su2double Force[MAXNDIM] = {0.0}, MomentDist[MAXNDIM] = {0.0};
2709 for (unsigned short iDim = 0; iDim < nDim; iDim++) {
2710 Force[iDim] = TauElem[iDim] * Area * factor * AxiFactor;
2711 ForceViscous[iDim] += Force[iDim];
2712 MomentDist[iDim] = Coord[iDim] - Origin[iDim];
2713 }
2714
2715 /*--- Moment with respect to the reference axis ---*/
2716
2717 AccumulateMoment(nDim, RefLength, Force, MomentDist, Coord, MomentViscous, MomentX_Force, MomentY_Force,
2718 MomentZ_Force);
2719
2720 HF_Visc_Local += HeatFlux[iMarker][iVertex] * Area;
2721 MaxHF_Visc_Local += pow(HeatFlux[iMarker][iVertex], MaxNorm);
2722 }
2723 }
2725
2726 /*--- MaxHF_Visc_Local (and the shared accumulators it feeds below) are left un-rooted,
2727 * i.e. still a raw sum of HeatFlux^MaxNorm; pow(., 1/MaxNorm) is taken once at the end,
2728 * which is equivalent since pow(x^(1/n), n) == x. ---*/
2729
2730 if (Monitoring == YES) {
2731 const auto partial = ComputeAeroCoeffsFromForceMoment<AeroCoeffs>(
2732 nDim, CosAlpha, SinAlpha, CosBeta, SinBeta, ForceViscous, MomentViscous, MomentX_Force, MomentY_Force,
2733 MomentZ_Force);
2734
2735 AddCoeffContribution(iMarker, iMarker_Monitoring, partial, ViscCoeff, AllBoundViscCoeff, SurfaceViscCoeff);
2736
2737 /*--- Heat flux, not covered by AddCoeffContribution, is folded in its own critical section. ---*/
2738
2740 HF_Visc[iMarker] += HF_Visc_Local;
2741 AllBound_HF_Visc += HF_Visc_Local;
2742 MaxHF_Visc[iMarker] += MaxHF_Visc_Local;
2743 AllBound_MaxHF_Visc += MaxHF_Visc_Local;
2744
2745 if (iMarker_Monitoring >= 0) {
2746 Surface_HF_Visc[iMarker_Monitoring] += HF_Visc_Local;
2747 Surface_MaxHF_Visc[iMarker_Monitoring] += MaxHF_Visc_Local;
2748 }
2749 }
2751 }
2752 }
2753 /*--- For the SU2_NOWAIT in the vertex loop. ---*/
2755
2756 /*--- Derive the ratio coefficients, and root the (still raw) per-marker maximum heat flux,
2757 * from the fully-reduced totals, once. Surface_MaxHF_Visc and AllBound_MaxHF_Visc are
2758 * rooted later below, after the MPI reduction. ---*/
2759
2760 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2761 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) {
2762 if (!config->GetViscous_Wall(iMarker)) continue;
2763 if (config->GetMarker_All_Monitoring(iMarker) == YES) {
2764 ViscCoeff.CEff[iMarker] = ViscCoeff.CL[iMarker] / (ViscCoeff.CD[iMarker] + EPS);
2765 ViscCoeff.CMerit[iMarker] = ViscCoeff.CT[iMarker] / (ViscCoeff.CQ[iMarker] + EPS);
2766 MaxHF_Visc[iMarker] = pow(MaxHF_Visc[iMarker], 1.0 / MaxNorm);
2767 }
2768 }
2770
2771 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
2772 for (unsigned short iMarker_Monitoring = 0; iMarker_Monitoring < config->GetnMarker_Monitoring();
2773 iMarker_Monitoring++) {
2774 SurfaceViscCoeff.CEff[iMarker_Monitoring] =
2775 SurfaceViscCoeff.CL[iMarker_Monitoring] / (SurfaceViscCoeff.CD[iMarker_Monitoring] + EPS);
2776 }
2778
2780 ReduceCoeffsMPI(config, AllBoundViscCoeff, SurfaceViscCoeff);
2781
2782 /*--- HF_Visc/MaxHF_Visc, not covered by ReduceCoeffsMPI, are reduced separately. ---*/
2783 if (config->GetComm_Level() == COMM_FULL) {
2784 AllBound_HF_Visc = MPIReduceSum(AllBound_HF_Visc);
2786
2787 const int nMarkerMon = config->GetnMarker_Monitoring();
2788 MPIReduceSumInPlace(Surface_HF_Visc.data(), nMarkerMon);
2789 MPIReduceSumInPlace(Surface_MaxHF_Visc.data(), nMarkerMon);
2790 }
2791
2792 /*--- Complete the calculation of maximum heat flux. ---*/
2793
2794 for (auto& hf : Surface_MaxHF_Visc) {
2795 hf = pow(hf, 1.0 / MaxNorm);
2796 }
2798
2799 AccumulateTotalCoeffs(config, AllBoundViscCoeff, SurfaceViscCoeff, TotalCoeff, SurfaceCoeff, /*overwrite=*/false);
2802
2803 /*--- Buffet_Monitoring is not thread-safe, hence confined to the master thread. ---*/
2804
2805 Buffet_Monitoring(geometry, config);
2806 }
2808}
2809
2810template<class V, ENUM_REGIME R>
2812
2813 su2double objFun = 0.0;
2814
2815 /*--- Loop over all monitored markers, add to the 'combo' objective ---*/
2816
2817 for (auto iMarker = 0u; iMarker < config.GetnMarker_Monitoring(); iMarker++) {
2818
2819 const auto weight = config.GetWeight_ObjFunc(iMarker);
2820
2821 switch (config.GetKind_ObjFunc(iMarker)) {
2822 case DRAG_COEFFICIENT:
2823 objFun += weight * SurfaceCoeff.CD[iMarker];
2824 break;
2825 case LIFT_COEFFICIENT:
2826 objFun += weight * SurfaceCoeff.CL[iMarker];
2827 break;
2829 objFun += weight * SurfaceCoeff.CSF[iMarker];
2830 break;
2832 objFun += weight * SurfaceCoeff.CMx[iMarker];
2833 break;
2835 objFun += weight * SurfaceCoeff.CMy[iMarker];
2836 break;
2838 objFun += weight * SurfaceCoeff.CMz[iMarker];
2839 break;
2841 objFun += weight * SurfaceCoeff.CFx[iMarker];
2842 break;
2844 objFun += weight * SurfaceCoeff.CFy[iMarker];
2845 break;
2847 objFun += weight * SurfaceCoeff.CFz[iMarker];
2848 break;
2849 case TOTAL_HEATFLUX:
2850 objFun += weight * Surface_HF_Visc[iMarker];
2851 break;
2852 case MAXIMUM_HEATFLUX:
2853 objFun += weight * Surface_MaxHF_Visc[iMarker];
2854 break;
2855 default:
2856 break;
2857 }
2858 }
2859
2860 /*--- The following are not per-surface, and so to avoid that they are
2861 double-counted when multiple surfaces are specified, they have been
2862 placed outside of the loop above. In addition, multi-objective mode is
2863 also disabled for these objective functions (error thrown at start). ---*/
2864
2865 const auto weight = config.GetWeight_ObjFunc(0);
2866
2867 switch (config.GetKind_ObjFunc(0)) {
2868 case EFFICIENCY:
2869 objFun += weight * TotalCoeff.CEff;
2870 break;
2872 objFun += weight * Total_CpDiff;
2873 break;
2875 objFun += weight * Total_HeatFluxDiff;
2876 break;
2877 case EQUIVALENT_AREA:
2878 objFun += weight*Total_CEquivArea;
2879 break;
2880 case THRUST_COEFFICIENT:
2881 objFun += weight * TotalCoeff.CT;
2882 break;
2883 case TORQUE_COEFFICIENT:
2884 objFun += weight * TotalCoeff.CQ;
2885 break;
2886 case FIGURE_OF_MERIT:
2887 objFun += weight * TotalCoeff.CMerit;
2888 break;
2890 objFun += weight * config.GetSurface_TotalPressure(0);
2891 break;
2893 objFun += weight * config.GetSurface_Pressure(0);
2894 break;
2896 objFun += weight * config.GetSurface_Temperature(0);
2897 break;
2898 case SURFACE_MASSFLOW:
2899 objFun += weight * config.GetSurface_MassFlow(0);
2900 break;
2901 case SURFACE_UNIFORMITY:
2902 objFun += weight * config.GetSurface_Uniformity(0);
2903 break;
2904 case SURFACE_SECONDARY:
2905 objFun += weight * config.GetSurface_SecondaryStrength(0);
2906 break;
2908 objFun += weight * config.GetSurface_MomentumDistortion(0);
2909 break;
2911 objFun += weight * config.GetSurface_SecondOverUniform(0);
2912 break;
2914 objFun += weight * config.GetSurface_PressureDrop(0);
2915 break;
2916 case SURFACE_SPECIES_0:
2917 objFun += weight * config.GetSurface_Species_0(0);
2918 break;
2920 objFun += weight * config.GetSurface_Species_Variance(0);
2921 break;
2922 case CUSTOM_OBJFUNC:
2923 objFun += weight * Total_Custom_ObjFunc;
2924 break;
2925 default:
2926 break;
2927 }
2928
2929 return objFun;
2930}
2931
2932template <class V, ENUM_REGIME FlowRegime>
2934
2935 const bool nemo = config->GetNEMOProblem();
2936 /*--- Loop through all points to set the auxvargrad --*/
2938 for (auto iPoint = 0ul; iPoint < nPoint; iPoint++) {
2939 su2double yCoord = geometry->nodes->GetCoord(iPoint, 1);
2940 su2double yVelocity = nodes->GetVelocity(iPoint,1);
2941 su2double xVelocity = nodes->GetVelocity(iPoint,0);
2942 su2double Total_Viscosity = nodes->GetLaminarViscosity(iPoint) + nodes->GetEddyViscosity(iPoint);
2943 const auto VelocityGradient = nodes->GetVelocityGradient(iPoint);
2944
2945 if (yCoord > EPS) {
2946 su2double nu_v_on_y = Total_Viscosity*yVelocity/yCoord;
2947 nodes->SetAuxVar(iPoint, 0, nu_v_on_y);
2948 nodes->SetAuxVar(iPoint, 1, nu_v_on_y*yVelocity);
2949 nodes->SetAuxVar(iPoint, 2, nu_v_on_y*xVelocity);
2950 } else {
2951 if (!nemo) {
2952 /*--- At the axis of symmetry, use L'Hôpital's rule instead of setting each to zero: lim(v/r) = dv/dr ---*/
2953 su2double dv_dr = VelocityGradient(1,1); // ∂v/∂r
2954 su2double nu_dv_dr = Total_Viscosity * dv_dr;
2955 nodes->SetAuxVar(iPoint, 0, nu_dv_dr); // μ(∂v/∂r)
2956 nodes->SetAuxVar(iPoint, 1, 0.0); // μv(∂v/∂r) = 0 since v=0 at axis
2957 nodes->SetAuxVar(iPoint, 2, nu_dv_dr*xVelocity); // μu(∂v/∂r)
2958 }
2959 }
2960 }
2962
2963 /*--- Compute the auxiliary variable gradient with GG or WLS. ---*/
2964 if (config->GetKind_Gradient_Method() == GREEN_GAUSS) {
2965 SetAuxVar_Gradient_GG(geometry, config);
2966 }
2968 SetAuxVar_Gradient_LS(geometry, config);
2969 }
2970}
2971
2972template <class V, ENUM_REGIME FlowRegime>
2974 bool use_solution_old) {
2975 const auto iVel = prim_idx.Velocity();
2976 const auto nDim = geometry->GetnDim();
2977
2978 for (auto iMarker = 0u; iMarker < config->GetnMarker_All(); iMarker++) {
2979 if (config->GetMarker_All_KindBC(iMarker) != EULER_WALL) continue;
2980
2982 for (auto iVertex = 0ul; iVertex < geometry->nVertex[iMarker]; iVertex++) {
2983 const auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
2984
2985 if (!geometry->nodes->GetDomain(iPoint)) continue;
2986
2987 /*--- Use the Gram-Schmidt corrected normal for nodes on intersecting walls,
2988 * consistent with BC_Sym_Plane. Fall back to the raw marker normal otherwise. ---*/
2989 su2double UnitNormal[MAXNDIM] = {0.0};
2990 const auto it = geometry->symmetryNormals[iMarker].find(iVertex);
2991 if (it != geometry->symmetryNormals[iMarker].end()) {
2992 for (auto iDim = 0u; iDim < nDim; iDim++) UnitNormal[iDim] = it->second[iDim];
2993 } else {
2994 su2double Normal[MAXNDIM] = {0.0};
2995 geometry->vertex[iMarker][iVertex]->GetNormal(Normal);
2996 const su2double Area = GeometryToolbox::Norm(nDim, Normal);
2997 if (Area < EPS) continue;
2998 for (auto iDim = 0u; iDim < nDim; iDim++) UnitNormal[iDim] = Normal[iDim] / Area;
2999 }
3000
3001 su2double* sol = use_solution_old ? nodes->GetSolution_Old(iPoint) : nodes->GetSolution(iPoint);
3002
3003 /*--- Compute normal component of the velocity / momentum vector.
3004 * For dynamic grids subtract the grid velocity to enforce (v - v_grid).n = 0,
3005 * multiplying by density for compressible flow (conservative variables). ---*/
3006 su2double gridVel[MAXNDIM] = {};
3007 if (dynamic_grid && !use_solution_old) {
3008 for (auto iDim = 0u; iDim < nDim; iDim++)
3009 gridVel[iDim] = geometry->nodes->GetGridVel(iPoint)[iDim];
3010 if constexpr (FlowRegime == ENUM_REGIME::COMPRESSIBLE) {
3011 for (auto iDim = 0u; iDim < nDim; iDim++)
3012 gridVel[iDim] *= nodes->GetDensity(iPoint);
3013 }
3014 }
3015
3016 su2double momentum_n = 0.0;
3017 for (auto iDim = 0u; iDim < nDim; iDim++)
3018 momentum_n += (sol[iVel + iDim] - gridVel[iDim]) * UnitNormal[iDim];
3019
3020 /*--- Project to tangent plane. ---*/
3021 for (auto iDim = 0u; iDim < nDim; iDim++) sol[iVel + iDim] -= momentum_n * UnitNormal[iDim];
3022 }
3024 }
3025}
Base class template for all FVM flow solvers.
A templated matrix/vector-like object.
Definition C2DContainer.hpp:374
C2DContainer & resize(const Index_t size1, const Index_t size2=1) noexcept
Request a change of size.
Definition C2DContainer.hpp:541
static int GetRank()
Definition mpi_structure.hpp:524
static void Reduce(const void *sendbuf, void *recvbuf, int count, Datatype datatype, Op op, int root, Comm comm)
Definition mpi_structure.hpp:565
static Comm GetComm()
Definition mpi_structure.hpp:530
static void Allreduce(const void *sendbuf, void *recvbuf, int count, Datatype datatype, Op op, Comm comm)
Definition mpi_structure.hpp:570
static void Error(const std::string &ErrorMsg, const std::string &FunctionName)
Definition mpi_structure.cpp:131
static int GetSize()
Definition mpi_structure.hpp:526
Class, which serves as an interface to the BLAS functionalities needed.
Definition blas_structure.hpp:41
void gemm(const int M, const int N, const int K, const su2double *A, const su2double *B, su2double *C, const CConfig *config)
Function, which carries out a dense matrix product. It is a limited version of the BLAS gemm function...
Definition blas_structure.cpp:63
Main class for defining the problem; basically this class reads the configuration file,...
Definition CConfig.hpp:64
WALL_FUNCTIONS GetWallFunction_Treatment(const string &val_marker) const
Get the wall function treatment for the given boundary marker.
Definition CConfig.cpp:9949
unsigned short GetKind_GridMovement() const
Get the type of dynamic mesh motion. Each zone gets a config file.
Definition CConfig.hpp:6303
UPWIND GetKind_Upwind_Flow(void) const
Get the kind of upwind convective numerical scheme for the flow equations.
Definition CConfig.hpp:4928
unsigned long GetInnerIter(void) const
Get the current FSI iteration number.
Definition CConfig.hpp:3405
bool GetEnergy_Equation(void) const
Flag for whether to solve the energy equation for incompressible flows.
Definition CConfig.hpp:4106
su2double GetDelta_UnstTimeND(void) const
If we are prforming an unsteady simulation, there is only one value of the time step for the complete...
Definition CConfig.hpp:6187
unsigned short GetKind_FluidModel(void) const
Fluid model that we are using.
Definition CConfig.hpp:4083
bool GetMultizone_Residual(void) const
Check if the mesh read supports multiple zones.
Definition CConfig.hpp:9942
unsigned short GetnMGLevels(void) const
Get the number of multigrid levels.
Definition CConfig.hpp:2950
bool GetSteadyRestart(void) const
Identifies if we want to restart from a steady or an unsteady solution.
Definition CConfig.hpp:9346
string GetSolution_FileName(void) const
Get the name of the file with the solution of the flow problem.
Definition CConfig.hpp:5864
bool GetSolid_Wall(unsigned short iMarker) const
Determines whether a marker with index iMarker is a solid boundary.
Definition CConfig.cpp:8630
bool GetContinuous_Adjoint(void) const
Determines if problem is adjoint.
Definition CConfig.hpp:6902
su2double GetTemperature_Ref(void) const
Get the value of the reference temperature for non-dimensionalization.
Definition CConfig.hpp:1961
su2double GetAoS(void) const
Get the angle of sideslip of the body. It relates to the rotation of the aircraft centerline from the...
Definition CConfig.hpp:2938
su2double GetInletPtotal(const string &val_index) const
Get the total pressure at an inlet boundary.
Definition CConfig.cpp:9559
unsigned long GetEdgeColoringGroupSize(void) const
Get the size of the edge groups colored for OpenMP parallelization of edge loops.
Definition CConfig.hpp:10224
LIMITER GetKind_SlopeLimit_Flow(void) const
Get the method for limiting the spatial gradients.
Definition CConfig.hpp:4964
su2double GetCFL(unsigned short val_mesh) const
Get the Courant Friedrich Levi number for each grid.
Definition CConfig.hpp:2989
std::array< su2double, 3 > GetRefOriginMoment(unsigned short val_marker) const
Get reference origin for moment computation.
Definition CConfig.hpp:1604
su2double GetInlet_Pressure(const string &val_index) const
Get the pressure at a supersonic inlet boundary.
Definition CConfig.cpp:9587
su2double GetMUSCL_Kappa_Flow(void) const
Get the blending coefficient for the MUSCL scheme.
Definition CConfig.hpp:4795
su2double GetSurface_TotalPressure(unsigned short val_marker) const
Get the total pressure at an outlet boundary.
Definition CConfig.hpp:8650
TURB_MODEL GetKind_Turb_Model(void) const
Get the kind of the turbulence model.
Definition CConfig.hpp:4693
string GetMarker_Monitoring_TagBound(unsigned short val_marker) const
Get the name of the surface defined in the geometry file.
Definition CConfig.hpp:3521
unsigned short GetnMarker_All(void) const
Get the total number of boundary markers of the local process including send/receive domains.
Definition CConfig.hpp:3183
su2double GetPhysicalTime(void) const
Get the current physical time.
Definition CConfig.hpp:3417
bool GetAxisymmetric(void) const
Get information about the axisymmetric frame.
Definition CConfig.hpp:6692
su2double GetRefArea(void) const
Get the reference area for non dimensional coefficient computation. If the value from the is 0 then,...
Definition CConfig.hpp:2211
su2double GetSurface_SecondaryStrength(unsigned short val_marker) const
Get the secondary flow strength at the surface.
Definition CConfig.hpp:8622
unsigned short GetKind_TimeIntScheme_Flow(void) const
Get the kind of integration scheme (explicit or implicit) for the flow equations.
Definition CConfig.hpp:4816
su2double GetInlet_Temperature(const string &val_index) const
Get the temperature at a supersonic inlet boundary.
Definition CConfig.cpp:9580
unsigned short GetnTurbVar(void) const
Get the number of Turbulence Variables.
Definition CConfig.hpp:4687
su2double GetWeight_ObjFunc(unsigned short val_obj) const
Get the weight of objective function. There are several options: Drag coefficient,...
Definition CConfig.hpp:5615
SA_ParsedOptions GetSAParsedOptions() const
Get parsed SA option data structure.
Definition CConfig.hpp:10377
unsigned short GetnMarker_Monitoring(void) const
Get the total number of monitoring markers.
Definition CConfig.hpp:3267
unsigned short GetMarker_All_Monitoring(unsigned short val_marker) const
Get the monitoring information for a marker val_marker.
Definition CConfig.hpp:3748
SPECIES_MODEL GetKind_Species_Model(void) const
Get the kind of the species model.
Definition CConfig.hpp:4717
bool GetDeform_Mesh(void) const
Get information about whether the mesh will be deformed using pseudo linear elasticity.
Definition CConfig.hpp:4599
su2double GetSurface_SecondOverUniform(unsigned short val_marker) const
Get the relative secondary flow strength at the surface.
Definition CConfig.hpp:8629
su2double GetSurface_Temperature(unsigned short val_marker) const
Get the temperature at an outlet boundary.
Definition CConfig.hpp:8580
bool GetRead_Binary_Restart(void) const
Flag for whether binary SU2 native restart files are read.
Definition CConfig.hpp:5678
su2double GetSurface_Uniformity(unsigned short val_marker) const
Get the streamwise flow uniformity at the surface.
Definition CConfig.hpp:8615
unsigned short GetKind_Gradient_Method(void) const
Get the kind of method for computation of spatial gradients used for viscous and source terms.
Definition CConfig.hpp:4360
bool GetViscous_Wall(unsigned short iMarker) const
Determines whether a marker with index iMarker is a viscous no-slip boundary.
Definition CConfig.cpp:8610
pair< WALL_TYPE, su2double > GetWallRoughnessProperties(const string &val_marker) const
Get the type of wall and roughness height on a wall boundary (Heatflux or Isothermal).
Definition CConfig.cpp:9938
const CStochBackScatParam & GetSBSParam(void) const
Get the Stochastic BackScatter (SBS) model parameters.
Definition CConfig.hpp:9766
const su2double * GetInletFlowDir(const string &val_index) const
Get the flow direction unit vector at an inlet boundary.
Definition CConfig.cpp:9573
unsigned short GetnMarker_Periodic(void) const
Get the total number of periodic markers.
Definition CConfig.hpp:3309
bool GetGrid_Movement(void) const
Get information about the grid movement.
Definition CConfig.hpp:6268
unsigned short GetKind_ObjFunc(unsigned short val_obj=0) const
Get the kind of objective function. There are several options: Drag coefficient, Lift coefficient,...
Definition CConfig.hpp:5606
su2double GetWall_HeatFlux(const string &val_index) const
Get the wall heat flux on a constant heat flux boundary.
Definition CConfig.cpp:9911
const su2double * GetInlet_Velocity(const string &val_index) const
Get the velocity vector at a supersonic inlet boundary.
Definition CConfig.cpp:9594
unsigned short GetComm_Level(void) const
Get the level of MPI communications to be performed.
Definition CConfig.hpp:9930
su2double GetAoA(void) const
Get the angle of attack of the body. This is the angle between a reference line on a lifting body (of...
Definition CConfig.hpp:2881
su2double GetIsothermal_Temperature(const string &val_index) const
Get the wall temperature (static) at an isothermal boundary.
Definition CConfig.cpp:9902
su2double GetSurface_MassFlow(unsigned short val_marker) const
Get the massflow at an outlet boundary.
Definition CConfig.hpp:8566
bool GetDiscrete_Adjoint(void) const
Get the indicator whether we are solving an discrete adjoint problem.
Definition CConfig.hpp:9299
bool GetFSI_Simulation(void) const
Check if the simulation we are running is a FSI simulation.
Definition CConfig.hpp:9514
string GetMarker_All_TagBound(unsigned short val_marker) const
Get the index of the surface defined in the geometry file.
Definition CConfig.hpp:3473
su2double GetHeat_Flux_Ref(void) const
Get the reference value for the heat flux.
Definition CConfig.hpp:1835
TIME_MARCHING GetTime_Marching() const
Provides information about the time integration, and change the write in the output files information...
Definition CConfig.hpp:5648
unsigned short GetKind_ConvNumScheme_Flow(void) const
Get the kind of convective numerical scheme for the flow equations (centered or upwind).
Definition CConfig.hpp:4886
su2double GetwallModel_MinYPlus() const
Get the value of the minimum Y+ value below which the wall function is deactivated.
Definition CConfig.hpp:1924
unsigned short GetnSpecies() const
Provides the number of species present in the gas mixture.
Definition CConfig.hpp:5654
unsigned short GetMarker_All_PyCustom(unsigned short val_marker) const
Get the Python customization for a marker val_marker.
Definition CConfig.hpp:3881
unsigned short GetKind_TimeIntScheme(void) const
Get the kind of time integration method.
Definition CConfig.hpp:4732
unsigned long GetScreen_Wrt_Freq(unsigned short iter) const
GetScreen_Wrt_Freq_Inner.
Definition CConfig.hpp:10154
bool GetIntegrated_HeatFlux() const
Check if values passed to the BC_HeatFlux-Routine are already integrated.
Definition CConfig.hpp:9805
bool GetViscous(void) const
Determines if problem is viscous.
Definition CConfig.hpp:6908
su2double GetSurface_Pressure(unsigned short val_marker) const
Get the pressure at an outlet boundary.
Definition CConfig.hpp:8587
bool GetRestart_Flow(void) const
For some problems like adjoint or the linearized equations it is necessary to restart the flow soluti...
Definition CConfig.hpp:5743
su2double GetSurface_Species_0(unsigned short val_marker) const
Get avg species_0 at a boundary.
Definition CConfig.hpp:8664
unsigned short GetnRoughWall(void) const
Get the total number of rough markers.
Definition CConfig.hpp:3321
unsigned short GetMarker_All_KindBC(unsigned short val_marker) const
Get the kind of boundary for each marker.
Definition CConfig.hpp:3556
bool GetNEMOProblem(void) const
Return true if a NEMO solver is in use.
Definition CConfig.hpp:3994
bool GetEdgeColoringRelaxDiscAdj() const
Check if the discrete adjoint is allowed to relax the coloring, that is, allow smaller edge color gro...
Definition CConfig.hpp:10229
bool GetRestart(void) const
Provides the restart information.
Definition CConfig.hpp:5672
su2double GetSurface_PressureDrop(unsigned short val_marker) const
Get the pressure drop between two surfaces.
Definition CConfig.hpp:8657
su2double GetInletTtotal(const string &val_index) const
Get the total temperature at an inlet boundary.
Definition CConfig.cpp:9552
su2double GetSurface_MomentumDistortion(unsigned short val_marker) const
Get the momentum distortion at the surface.
Definition CConfig.hpp:8636
bool GetBounded_Scalar() const
Returns true if bounded scalar mode is used for any equation.
Definition CConfig.hpp:5172
unsigned long GetRestart_Iter(void) const
Get the restart iteration.
Definition CConfig.hpp:9912
bool GetCatalytic_Wall(unsigned short iMarker) const
Determines whether a marker with index iMarker is a catalytic boundary.
Definition CConfig.cpp:8619
su2double GetSurface_Species_Variance(unsigned short val_marker) const
Get the species variance at a boundary.
Definition CConfig.hpp:8671
unsigned short GetKind_Gradient_Method_Recon(void) const
Get the kind of method for computation of spatial gradients used for upwind reconstruction.
Definition CConfig.hpp:4366
string GetFilename(string filename, const string &ext, int Iter) const
Add any numbers necessary to the filename (iteration number, zone ID ...)
Definition CConfig.cpp:8890
su2double GetTemperature_FreeStreamND(void) const
Get the value of the non-dimensionalized freestream temperature.
Definition CConfig.hpp:2058
su2double GetRefLength(void) const
Get the reference length for computing moment (the default value is 1).
Definition CConfig.hpp:2480
void GetNormal(unsigned long iEdge, T &normal) const
Copy the the normal vector of a face.
Definition CEdge.hpp:161
unsigned long GetNode(unsigned long iEdge, unsigned long iNode) const
Get left/right node index defining the edge.
Definition CEdge.hpp:72
su2double AllBound_MaxHF_Visc
Maximum heat flux (viscous contribution) for all boundaries.
Definition CFVMFlowSolverBase.hpp:179
AeroCoeffs AllBoundMntCoeff
Total momentum contribution for all the boundaries.
Definition CFVMFlowSolverBase.hpp:153
vector< vector< su2double > > Inlet_Ttotal
Value of the Total T.
Definition CFVMFlowSolverBase.hpp:182
AeroCoeffsArray SurfaceCoeff
Totals for each monitoring surface.
Definition CFVMFlowSolverBase.hpp:159
AeroCoeffsArray SurfaceViscCoeff
Viscous contributions for each monitoring boundary.
Definition CFVMFlowSolverBase.hpp:156
void FinalizeResidualComputation(const CGeometry *geometry, bool pausePreacc, unsigned long localCounter, CConfig *config)
Sums edge fluxes (if required) and computes the global error counter.
Definition CFVMFlowSolverBase.hpp:298
su2double Total_Heat
Total heat load for all the boundaries.
Definition CFVMFlowSolverBase.hpp:170
su2double GetSlidingState(unsigned short val_marker, unsigned long val_vertex, unsigned short val_state, unsigned long donor_index) const final
Get the outer state for fluid interface nodes.
Definition CFVMFlowSolverBase.hpp:2359
vector< vector< su2double > > CPressureTarget
Target Pressure coefficient for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:191
void Pressure_Forces(const CGeometry *geometry, const CConfig *config) final
Compute the pressure forces and all the adimensional coefficients.
Definition CFVMFlowSolverBase.inl:2165
AeroCoeffs TotalCoeff
Totals for all boundaries.
Definition CFVMFlowSolverBase.hpp:160
static void ompMasterAssignBarrier(Ts &&... lhsRhsPairs)
Utility to set the value of a member variables safely, and so that the new values are seen by all thr...
Definition CFVMFlowSolverBase.hpp:65
su2double Total_CEquivArea
Total Equivalent Area coefficient for all the boundaries.
Definition CFVMFlowSolverBase.hpp:167
su2double GetInletAtVertex(unsigned short iMarker, unsigned long iVertex, const CGeometry *geometry, su2double *val_inlet) const final
Get the set of values imposed at an inlet.
Definition CFVMFlowSolverBase.inl:751
void SetUniformInlet(const CConfig *config, unsigned short iMarker) final
Set a uniform inlet profile.
Definition CFVMFlowSolverBase.inl:772
vector< su2activematrix > Inlet_FlowDir
Value of the Flow Direction.
Definition CFVMFlowSolverBase.hpp:183
int GetnSlidingStates(unsigned short val_marker, unsigned long val_vertex) const final
Get the number of outer state for fluid interface nodes.
Definition CFVMFlowSolverBase.hpp:2348
void CompleteImplicitIteration(CGeometry *geometry, CSolver **, CConfig *config) final
Complete an implicit iteration.
Definition CFVMFlowSolverBase.inl:588
su2double Total_MaxHeat
Maximum heat flux on all boundaries.
Definition CFVMFlowSolverBase.hpp:171
void BC_Periodic(CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config) final
Impose a periodic boundary condition by summing contributions from the complete control volume.
Definition CFVMFlowSolverBase.inl:1318
void SetInitialCondition(CGeometry **geometry, CSolver ***solver_container, CConfig *config, unsigned long ExtIter) override
Set the initial condition for the Euler Equations.
Definition CFVMFlowSolverBase.inl:1049
vector< su2activematrix > HeatConjugateVar
CHT variables for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:189
void AllocateTerribleLegacyTemporaryVariables()
Allocate small member variables that ideally should not be used.
Definition CFVMFlowSolverBase.inl:212
void LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int iter, bool update_geo) override
Load a solution from a restart file.
Definition CFVMFlowSolverBase.inl:1042
array< DummyGridColor<>, 1 > EdgeColoring
Definition CFVMFlowSolverBase.hpp:213
static constexpr size_t OMP_MAX_SIZE
Max chunk size for light point loops.
Definition CFVMFlowSolverBase.hpp:53
vector< su2activematrix > CSkinFriction
Skin friction coefficient for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:187
bool least_squares
True if computing gradients by least squares.
Definition CFVMFlowSolverBase.hpp:198
bool space_centered
True if space centered scheme used.
Definition CFVMFlowSolverBase.hpp:196
unsigned long ErrorCounter
Counter for number of un-physical states.
Definition CFVMFlowSolverBase.hpp:86
su2double Total_HeatFluxDiff
Total Equivalent Area coefficient for all the boundaries.
Definition CFVMFlowSolverBase.hpp:166
CNumericsSIMD * edgeNumerics
Object for edge flux computation.
Definition CFVMFlowSolverBase.hpp:226
vector< su2double > Surface_MaxHF_Visc
Maximum heat flux for each monitored surface.
Definition CFVMFlowSolverBase.hpp:175
VariableType * nodes
The highest level in the variable hierarchy the DERIVED solver can safely use.
Definition CFVMFlowSolverBase.hpp:231
void BC_Custom(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) final
Impose a custom or verification boundary condition.
Definition CFVMFlowSolverBase.inl:1499
vector< vector< su2double > > YPlus
Yplus for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:192
AeroCoeffsArray SurfaceMntCoeff
Inviscid momentum contributions for each monitoring boundary.
Definition CFVMFlowSolverBase.hpp:152
virtual void ComputeUnderRelaxationFactor(const CConfig *config)
Compute a suitable under-relaxation parameter to limit the change in the solution variables over a no...
Definition CFVMFlowSolverBase.hpp:396
AeroCoeffsArray SurfaceInvCoeff
Inviscid pressure contributions for each monitoring boundary.
Definition CFVMFlowSolverBase.hpp:148
AeroCoeffsArray ViscCoeff
Viscous contributions for each boundary.
Definition CFVMFlowSolverBase.hpp:155
virtual void Buffet_Monitoring(const CGeometry *geometry, const CConfig *config)
Compute the buffet sensor.
Definition CFVMFlowSolverBase.hpp:2303
su2double Pressure_Inf
Pressure at the infinity.
Definition CFVMFlowSolverBase.hpp:74
void SetPrimitive_Limiter(CGeometry *geometry, const CConfig *config) final
Compute the limiter of the primitive variables.
Definition CFVMFlowSolverBase.inl:424
AeroCoeffs AllBoundInvCoeff
Total pressure contribution for all the boundaries.
Definition CFVMFlowSolverBase.hpp:149
AeroCoeffsArray MntCoeff
Inviscid momentum contributions for each boundary.
Definition CFVMFlowSolverBase.hpp:151
void Momentum_Forces(const CGeometry *geometry, const CConfig *config) final
Compute the pressure forces and all the adimensional coefficients.
Definition CFVMFlowSolverBase.inl:2338
void LoadRestart_impl(CGeometry **geometry, CSolver ***solver, CConfig *config, int iter, bool update_geo, su2double *RestartSolution=nullptr, unsigned short nVar_Restart=0)
General implementation to load a flow solution from a restart file.
Definition CFVMFlowSolverBase.inl:854
virtual void PrintVerificationError(const CConfig *config) const =0
Print verification error to screen, derived solvers must define this.
vector< su2double > Surface_HF_Visc
Total (integrated) heat flux for each monitored surface.
Definition CFVMFlowSolverBase.hpp:174
void EdgeFluxResidual(const CGeometry *geometry, const CSolver *const *solvers, CConfig *config)
Method to compute convective and viscous residual contribution using vectorized numerics.
Definition CFVMFlowSolverBase.inl:1563
void PushSolutionBackInTime(unsigned long TimeIter, bool restart, bool rans, CSolver ***solver_container, CGeometry **geometry, CConfig *config)
Move solution to previous time levels (for restarts).
Definition CFVMFlowSolverBase.inl:1100
su2double AeroCoeffForceRef
Reference force for aerodynamic coefficients.
Definition CFVMFlowSolverBase.hpp:162
vector< vector< int > > SlidingStateNodes
Definition CFVMFlowSolverBase.hpp:205
vector< su2double > CNearFieldOF_Inv
Near field pressure (inviscid) for each boundary.
Definition CFVMFlowSolverBase.hpp:173
CNumerics::ResidualType Viscous_Residual_impl(unsigned long iEdge, CGeometry *geometry, CSolver **solver_container, CNumerics *numerics, CConfig *config)
Definition CFVMFlowSolverBase.inl:440
su2activevector EdgeMassFluxes
Mass fluxes across each edge, for discretization of transported scalars.
Definition CFVMFlowSolverBase.hpp:58
su2double Total_CpDiff
Total Equivalent Area coefficient for all the boundaries.
Definition CFVMFlowSolverBase.hpp:165
AeroCoeffs AllBoundViscCoeff
Total pressure contribution for all the boundaries.
Definition CFVMFlowSolverBase.hpp:157
void Allocate(const CConfig &config)
Allocate member variables.
Definition CFVMFlowSolverBase.inl:78
void MultigridProjectEulerWall(CGeometry *geometry, const CConfig *config, bool use_solution_old) override
Enforce Euler wall BC on a restricted or prolongated multigrid solution by projecting the momentum to...
Definition CFVMFlowSolverBase.inl:2973
virtual void SetReferenceValues(const CConfig &config)=0
Set reference values for pressure, forces, etc., e.g. "AeroCoeffForceRef".
void SetPrimitive_Gradient_LS(CGeometry *geometry, const CConfig *config, bool reconstruction=false) final
Compute the gradient of the primitive variables using a Least-Squares method, and stores the result i...
Definition CFVMFlowSolverBase.inl:397
vector< vector< su2double > > HeatFlux
Heat transfer coefficient for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:184
vector< su2matrix< su2double * > > SlidingState
Definition CFVMFlowSolverBase.hpp:204
vector< vector< su2double > > UTau
UTau for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:193
su2double * GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex) final
Value of the characteristic variables at the boundaries.
Definition CFVMFlowSolverBase.hpp:2132
void ComputeVerificationError(CGeometry *geometry, CConfig *config) final
Compute the global error measures (L2, Linf) for verification cases.
Definition CFVMFlowSolverBase.inl:524
vector< vector< su2double > > Inlet_Ptotal
Value of the Total P.
Definition CFVMFlowSolverBase.hpp:181
vector< su2activematrix > CharacPrimVar
Value of the characteristic variables at each boundary.
Definition CFVMFlowSolverBase.hpp:186
void BC_Fluid_Interface(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config) final
Impose the interface state across sliding meshes.
Definition CFVMFlowSolverBase.inl:1335
void BC_Sym_Plane(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) override
Impose the symmetry boundary condition using the residual.
Definition CFVMFlowSolverBase.inl:1150
su2double EvaluateCommonObjFunc(const CConfig &config) const
Evaluate common part of objective function to all solvers.
Definition CFVMFlowSolverBase.inl:2811
void ComputeAxisymmetricAuxGradients(CGeometry *geometry, const CConfig *config)
Computes and sets the required auxilliary vars (and gradients) for axisymmetric flow.
Definition CFVMFlowSolverBase.inl:2933
void SumEdgeFluxes(const CGeometry *geometry)
Sum the edge fluxes for each cell to populate the residual vector, only used on coarse grids.
Definition CFVMFlowSolverBase.inl:1626
~CFVMFlowSolverBase()
Destructor.
Definition CFVMFlowSolverBase.inl:372
unsigned long omp_chunk_size
Chunk size used in light point loops.
Definition CFVMFlowSolverBase.hpp:56
AeroCoeffsArray InvCoeff
Inviscid pressure contributions for each boundary.
Definition CFVMFlowSolverBase.hpp:147
static constexpr bool ReducerStrategy
Definition CFVMFlowSolverBase.hpp:215
su2double AllBound_HF_Visc
Heat load (viscous contribution) for all the boundaries.
Definition CFVMFlowSolverBase.hpp:178
bool euler_implicit
True if euler implicit scheme used.
Definition CFVMFlowSolverBase.hpp:197
vector< vector< su2double > > WallShearStress
Wall Shear Stress for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:188
void UpdateCustomBoundaryConditions(CGeometry **geometry_container, CSolver ***solver_container, CConfig *config) final
Update the multi-grid structure for the customized boundary conditions.
Definition CFVMFlowSolverBase.inl:809
void HybridParallelInitialization(const CConfig &config, CGeometry &geometry)
Initialize thread parallel variables.
Definition CFVMFlowSolverBase.inl:283
static constexpr size_t MAXNVAR
Max number of variables, for static arrays.
Definition CFVMFlowSolverBase.hpp:51
void CommunicateInitialState(CGeometry *geometry, const CConfig *config)
Communicate the initial solver state.
Definition CFVMFlowSolverBase.inl:245
static constexpr size_t OMP_MIN_SIZE
Min chunk size for edge loops (max is color group size).
Definition CFVMFlowSolverBase.hpp:54
void SetPrimitive_Gradient_GG(CGeometry *geometry, const CConfig *config, bool reconstruction=false) override
Compute the gradient of the primitive variables using Green-Gauss method, and stores the result in th...
Definition CFVMFlowSolverBase.inl:384
void ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) final
Implementation of implicit Euler iteration.
Definition CFVMFlowSolverBase.inl:618
static constexpr size_t MAXNDIM
Max number of space dimensions, used in some static arrays.
Definition CFVMFlowSolverBase.hpp:50
vector< vector< su2double > > EddyViscWall
Eddy viscosuty at the wall for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:194
su2double Total_CNearFieldOF
Total Near-Field Pressure coefficient for all the boundaries.
Definition CFVMFlowSolverBase.hpp:169
vector< vector< su2double > > CPressure
Pressure coefficient for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:190
su2double AllBound_CNearFieldOF_Inv
Near-Field press coeff (inviscid) for all the boundaries.
Definition CFVMFlowSolverBase.hpp:172
CSysVector< su2double > EdgeFluxes
Flux across each edge.
Definition CFVMFlowSolverBase.hpp:224
const VariableType::template CIndices< unsigned short > prim_idx
Object with indices of primitive variables.
Definition CFVMFlowSolverBase.hpp:48
vector< su2double > MaxHF_Visc
Maximum heat flux (viscous contribution) for each boundary.
Definition CFVMFlowSolverBase.hpp:177
void Friction_Forces(const CGeometry *geometry, const CConfig *config) final
Compute the viscous forces and all the addimensional coefficients.
Definition CFVMFlowSolverBase.inl:2456
virtual void InstantiateEdgeNumerics(const CSolver *const *solvers, const CConfig *config)
Instantiate a SIMD numerics object.
Definition CFVMFlowSolverBase.hpp:336
su2double StrainMag_Max
Maximum Strain Rate magnitude.
Definition CFVMFlowSolverBase.hpp:80
vector< su2double > HF_Visc
Heat load (viscous contribution) for each boundary.
Definition CFVMFlowSolverBase.hpp:176
void ComputeVorticityAndStrainMag(const CConfig &config, const CGeometry *geometry, unsigned short iMesh)
Evaluate the vorticity and strain rate magnitude.
Definition CFVMFlowSolverBase.inl:644
su2double Omega_Max
Maximum Omega.
Definition CFVMFlowSolverBase.hpp:81
vector< vector< su2double > > HeatFluxTarget
Heat transfer coefficient for each boundary and vertex.
Definition CFVMFlowSolverBase.hpp:185
void SetResidual_DualTime(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iRKStep, unsigned short iMesh, unsigned short RunTime_EqSystem) override
Set the total residual adding the term that comes from the Dual Time Strategy.
Definition CFVMFlowSolverBase.inl:1645
void SetInletAtVertex(const su2double *val_inlet, unsigned short iMarker, unsigned long iVertex) final
Store of a set of provided inlet profile values at a vertex.
Definition CFVMFlowSolverBase.inl:728
su2double GetdPdrho_e() const
Get fluid pressure partial derivative.
Definition CFluidModel.hpp:222
virtual void SetTDState_Prho(su2double P, su2double rho)
virtual member that would be different for each gas model implemented
Definition CFluidModel.hpp:321
su2double GetdPde_rho() const
Get fluid pressure partial derivative.
Definition CFluidModel.hpp:227
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
unsigned long GetEdgeColorGroupSize() const
Get the group size used in edge coloring.
Definition CGeometry.hpp:1928
const CCompressedSparsePatternUL & GetEdgeColoring(su2double *efficiency=nullptr, bool maximizeEdgeColorGroupSize=false)
Get the edge coloring.
Definition CGeometry.cpp:4161
unsigned long GetGlobal_nPointDomain() const
Retrieve total number of nodes in a simulation across all processors (excluding halos).
Definition CGeometry.hpp:605
static void UpdateGeometry(CGeometry **geometry_container, CConfig *config)
Update the multi-grid structure and the wall-distance.
Definition CGeometry.cpp:2730
unsigned long GetnPoint() const
Get number of points.
Definition CGeometry.hpp:587
vector< std::unordered_map< unsigned long, std::array< su2double, MAXNDIM > > > symmetryNormals
Bool if boundary-marker is straight(2D)/plane(3D) for each local marker.
Definition CGeometry.hpp:263
CPoint * nodes
Node vector (dual grid information).
Definition CGeometry.hpp:253
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 CGeometry.cpp:737
su2double GetCustomBoundaryTemperature(unsigned short val_marker, unsigned long val_vertex) const
Get the value of the customized temperature at a specified vertex on a specified marker.
Definition CGeometry.hpp:1739
void SetNaturalEdgeColoring()
Force the natural (sequential) edge coloring.
Definition CGeometry.cpp:4256
su2double GetSurfaceArea(const CConfig *config, unsigned short val_marker) const
Get global Surface Area to a local marker.
Definition CGeometry.cpp:2843
void SetMultiGridMarkerQuantity(const CGeometry *fine_grid, unsigned short val_marker, T &wall_quantity)
Set a representative wall value of the agglomerated control volumes on a particular boundary marker.
Definition CGeometry.hpp:1781
virtual long GetGlobal_to_Local_Point(unsigned long val_ipoint) const
A virtual member.
Definition CGeometry.hpp:1330
CVertex *** vertex
Boundary Vertex vector (dual grid information).
Definition CGeometry.hpp:255
unsigned long GetnEdge() const
Get number of edges.
Definition CGeometry.hpp:617
virtual void SetRestricted_GridVelocity(const CGeometry *fine_grid)
A virtual member.
Definition CGeometry.hpp:1130
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 GetCustomBoundaryHeatFlux(unsigned short val_marker, unsigned long val_vertex) const
Get the value of the customized normal heat flux at a specified vertex on a specified marker.
Definition CGeometry.hpp:1759
unsigned long * nVertex
Number of vertex for each marker.
Definition CGeometry.hpp:258
void InitiateComms(CGeometry *geometry, const CConfig *config, MPI_QUANTITIES commType) const
Routine to load a geometric quantity into the data structures for MPI point-to-point communication an...
Definition CGeometry.cpp:640
virtual void ComputeFlux(Int iEdge, const CConfig &config, const CGeometry &geometry, const CVariable &solution, UpdateType updateType, Double updateMask, CSysVector< su2double > &vector, SparseMatrixType &matrix, su2activevector *edgeMassFluxes) const =0
Interface for edge flux computation.
Class for defining the numerical methods.
Definition CNumerics.hpp:48
void SetPrimitive(const su2double *val_v_i, const su2double *val_v_j)
Set the value of the primitive variables.
Definition CNumerics.hpp:301
void SetSecondary(const su2double *val_s_i, const su2double *val_s_j)
Set the value of the primitive variables.
Definition CNumerics.hpp:311
static void ComputeStressTensor(size_t nDim, Mat1 &stress, const Mat2 &velgrad, Scalar viscosity, Scalar density=0.0, Scalar turb_ke=0.0, bool reynolds3x3=false)
Compute the stress tensor from the velocity gradients.
Definition CNumerics.hpp:494
virtual void SetTau_Wall(su2double val_tauwall_i, su2double val_tauwall_j)
Set the value of the Tauwall.
Definition CNumerics.hpp:1765
void SetLES_Mode(su2double val_lesMode_i, su2double val_lesMode_j)
Set the LES sensor for hybrid RANS-LES methods.
Definition CNumerics.hpp:938
void SetGridVel(const su2double *val_gridvel_i, const su2double *val_gridvel_j)
Set the velocity of the computational grid.
Definition CNumerics.hpp:987
void SetPrimVarGradient(CMatrixView< const su2double > val_primvar_grad_i, CMatrixView< const su2double > val_primvar_grad_j)
Set the gradient of the primitive variables.
Definition CNumerics.hpp:338
void SetStochVar(unsigned short iDim, su2double val_stochvar_i, su2double val_stochvar_j)
Set the stochastic variables from Langevin equations (Stochastic Backscatter Model).
Definition CNumerics.hpp:920
void SetCoord(const su2double *val_coord_i, const su2double *val_coord_j)
Set coordinates of the points.
Definition CNumerics.hpp:977
void SetNormal(const su2double *val_normal)
Set the value of the normal vector to the face between two points.
Definition CNumerics.hpp:1086
void SetDistance(su2double val_dist_i, su2double val_dist_j)
Set the value of the distance from the nearest wall.
Definition CNumerics.hpp:948
static void AddQCR(size_t nDim, const Mat1 &gradvel, Mat2 &tau, Scalar2 turb_fraction)
Add a correction using a Quadratic Constitutive Relation to the stress tensor.
Definition CNumerics.hpp:535
virtual void ComputeResidual(su2double *val_residual, CConfig *config)
Compute the numerical residual.
Definition CNumerics.hpp:1543
void SetTurbKineticEnergy(su2double val_turb_ke_i, su2double val_turb_ke_j)
Set the turbulent kinetic energy.
Definition CNumerics.hpp:909
void SetVolume_n()
Set the volume of the control volume at time n.
Definition CPoint.cpp:139
void SetCoord_n1()
Set the coordinates of the control volume at time n-1 to the ones in Coord_n.
Definition CPoint.cpp:179
CCompressedSparsePatternL::CInnerIter GetEdges(unsigned long iPoint) const
Get inner iterator to loop over neighbor edges.
Definition CPoint.hpp:296
unsigned long GetPoint(unsigned long iPoint, unsigned long npoint) const
Get all the points that compose the control volume.
Definition CPoint.hpp:264
long GetEdge(unsigned long iPoint, unsigned long nedge) const
Get all the edges that compose the control volume.
Definition CPoint.hpp:291
unsigned long GetGlobalIndex(unsigned long iPoint) const
Get the global index in a parallel computation.
Definition CPoint.hpp:452
void SetVolume_nM1()
Set the volume of the control volume at time n-1.
Definition CPoint.cpp:144
bool GetDomain(unsigned long iPoint) const
For parallel computation, its indicates if a point must be computed or not.
Definition CPoint.hpp:423
su2double GetCoord(unsigned long iPoint, unsigned long iDim) const
Get the coordinates dor the control volume.
Definition CPoint.hpp:158
su2double & GetVolume(unsigned long iPoint)
Get area or volume of the control volume.
Definition CPoint.hpp:557
void SetGridVel(unsigned long iPoint, unsigned long iDim, su2double gridvel)
Set the value of the grid velocity at the point.
Definition CPoint.hpp:829
unsigned short GetnPoint(unsigned long iPoint) const
Get the number of points that compose the control volume.
Definition CPoint.hpp:256
su2double * GetGridVel(unsigned long iPoint)
Get the value of the grid velocity at the point.
Definition CPoint.hpp:816
su2double GetVolume_nM1(unsigned long iPoint) const
Get the volume of the control volume at time n+1.
Definition CPoint.hpp:601
void SetCoord_n()
Set the coordinates of the control volume at time n to the ones in Coord.
Definition CPoint.cpp:174
void SetCoord(unsigned long iPoint, unsigned long iDim, su2double coord)
Set the coordinates for the control volume.
Definition CPoint.hpp:178
Definition CSolver.hpp:71
vector< string > fields
Definition CSolver.hpp:209
void Read_SU2_Restart_Binary(CGeometry *geometry, const CConfig *config, string val_filename)
Read a native SU2 restart file in binary format.
Definition CSolver.cpp:3142
su2activematrix Point_Max_Coord_BGS
Vector with pointers to the coords of the maximal residual for each variable.
Definition CSolver.hpp:105
CSysMatrix< su2mixedfloat > Jacobian
Complete sparse Jacobian structure for implicit computations.
Definition CSolver.hpp:201
unsigned short nPrimVarGrad
Number of primitive variables of the problem in the gradient computation.
Definition CSolver.hpp:87
su2double ** Jacobian_j
Auxiliary matrices for storing point to point Jacobians at point j.
Definition CSolver.hpp:129
vector< unsigned long > nVertex
Store nVertex at each marker for deallocation.
Definition CSolver.hpp:146
vector< unsigned long > Point_Max_BGS
Vector with the maximal residual for each variable.
Definition CSolver.hpp:103
void Restart_OldGeometry(CGeometry *geometry, CConfig *config) const
Load the geometries at the previous time states n and nM1.
Definition CSolver.cpp:2819
su2activematrix Point_Max_Coord
Vector with pointers to the coords of the maximal residual for each variable.
Definition CSolver.hpp:104
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 SetRotatePeriodic(bool val_rotate_periodic)
Routine that sets the flag controlling solution rotation for periodic BCs.
Definition CSolver.hpp:4237
virtual su2double GetInletTtotal(unsigned short val_marker, unsigned long val_vertex) const
A virtual member.
Definition CSolver.hpp:2915
CSysSolve< su2mixedfloat > System
Linear solver/smoother.
Definition CSolver.hpp:202
unsigned short nDim
Number of dimensions of the problem.
Definition CSolver.hpp:90
su2double ** Jacobian_i
Auxiliary matrices for storing point to point Jacobians at point i.
Definition CSolver.hpp:128
su2double Total_Custom_ObjFunc
Total custom objective function.
Definition CSolver.hpp:107
void Read_SU2_Restart_ASCII(CGeometry *geometry, const CConfig *config, string val_filename)
Read a native SU2 restart file in ASCII format.
Definition CSolver.cpp:2979
virtual CFluidModel * GetFluidModel(void) const
Compute the pressure at the infinity.
Definition CSolver.hpp:359
virtual void PrepareImplicitIteration(CGeometry *geometry, CSolver **solver_container, CConfig *config)
A virtual member.
Definition CSolver.hpp:1470
virtual void LoadRestart(CGeometry **geometry, CSolver ***solver, CConfig *config, int val_iter, bool val_update_geo)
A virtual member.
Definition CSolver.hpp:3472
vector< int > Restart_Vars
Auxiliary structure for holding the number of variables and points in a restart.
Definition CSolver.hpp:140
void SetAuxVar_Gradient_LS(CGeometry *geometry, const CConfig *config)
Compute the Least Squares gradient of the auxiliary variable.
Definition CSolver.cpp:2336
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
CVerificationSolution * VerificationSolution
Verification solution class used within the solver.
Definition CSolver.hpp:207
int size
MPI Size.
Definition CSolver.hpp:76
CSysVector< su2double > LinSysSol
vector to store iterative solution of implicit linear system.
Definition CSolver.hpp:199
vector< passivedouble > Restart_Data
Auxiliary structure for holding the data values from a restart.
Definition CSolver.hpp:142
vector< su2activematrix > VertexTraction
Definition CSolver.hpp:155
su2double * Res_Conv
Auxiliary nVar vector for storing the convective residual.
Definition CSolver.hpp:121
vector< su2double > Residual_BGS
Vector with the mean residual for each variable for BGS subiterations.
Definition CSolver.hpp:100
su2double * Res_Sour
Auxiliary nVar vector for storing the viscous residual.
Definition CSolver.hpp:123
void SetIterLinSolver(unsigned short val_iterlinsolver)
Set number of linear solver iterations.
Definition CSolver.hpp:316
unsigned long nPoint
Number of points of the computational grid.
Definition CSolver.hpp:91
void SetResLinSolver(su2double val_reslinsolver)
Set the final linear solver residual.
Definition CSolver.hpp:322
vector< su2double > Residual_Max
Vector with the maximal residual for each variable.
Definition CSolver.hpp:99
void SetImplicitPeriodic(bool val_implicit_periodic)
Routine that sets the flag controlling implicit treatment for periodic BCs.
Definition CSolver.hpp:4231
vector< su2activematrix > VertexTractionAdjoint
Definition CSolver.hpp:156
int rank
MPI Rank.
Definition CSolver.hpp:75
unsigned short MGLevel
Multigrid level of this solver object.
Definition CSolver.hpp:78
su2double * Res_Visc
Auxiliary nVar vector for storing the viscous residual.
Definition CSolver.hpp:122
unsigned short nVar
Number of variables of the problem.
Definition CSolver.hpp:85
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
CSysVector< su2double > LinSysRes
vector to store iterative residual of implicit linear system.
Definition CSolver.hpp:200
void SetAuxVar_Gradient_GG(CGeometry *geometry, const CConfig *config)
Compute the Green-Gauss gradient of the auxiliary variable.
Definition CSolver.cpp:2326
su2double * Solution
Auxiliary nVar vector.
Definition CSolver.hpp:115
unsigned long nPointDomain
Number of points of the computational grid.
Definition CSolver.hpp:92
su2double * Solution_j
Auxiliary nVar vector for storing the solution at point j.
Definition CSolver.hpp:117
su2double * Solution_i
Auxiliary nVar vector for storing the solution at point i.
Definition CSolver.hpp:116
su2double Avg_CFL_Local
Average value of the CFL across all the control volumes.
Definition CSolver.hpp:97
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
su2activevector iPoint_UndLapl
Auxiliary variable for the undivided Laplacians.
Definition CSolver.hpp:137
vector< su2double > Residual_Max_BGS
Vector with the maximal residual for each variable for BGS subiterations.
Definition CSolver.hpp:101
unsigned short nPrimVar
Number of primitive variables of the problem.
Definition CSolver.hpp:86
su2double Min_CFL_Local
Minimum value of the CFL across all the control volumes.
Definition CSolver.hpp:96
vector< su2double > Residual_RMS
Vector with the mean residual for each variable.
Definition CSolver.hpp:98
bool dynamic_grid
Flag that determines whether the grid is dynamic (moving or deforming + grid velocities).
Definition CSolver.hpp:153
static void MultigridRestriction(const CGeometry &geoFine, const su2activematrix &varsFine, const CGeometry &geoCoarse, su2activematrix &varsCoarse)
Interpolate variables to a coarser grid level.
Definition CSolver.hpp:4379
su2activevector jPoint_UndLapl
Auxiliary variable for the undivided Laplacians.
Definition CSolver.hpp:138
CVariable * GetNodes()
Allow outside access to the nodes of the solver, containing conservatives, primitives,...
Definition CSolver.hpp:229
su2double * Residual
Auxiliary nVar vector.
Definition CSolver.hpp:112
virtual void Preprocessing(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned short iRKStep, unsigned short RunTime_EqSystem, bool Output)
A virtual member.
Definition CSolver.hpp:764
su2double Max_CFL_Local
Maximum value of the CFL across all the control volumes.
Definition CSolver.hpp:95
vector< unsigned long > Point_Max
Vector with the maximal residual for each variable.
Definition CSolver.hpp:102
su2double * Vector_i
Auxiliary nDim vector to do the reconstruction of the variables at point i.
Definition CSolver.hpp:119
su2double * Vector_j
Auxiliary nDim vector to do the reconstruction of the variables at point j.
Definition CSolver.hpp:120
unsigned long nMarker
Total number of markers using the grid information.
Definition CSolver.hpp:145
void DeleteValsRowi(unsigned long block_i, unsigned long row)
Deletes the values of a row of the sparse matrix.
Definition CSysMatrix.cpp:922
void SubtractBlock2Diag(unsigned long block_i, const OtherType &val_block)
Short-hand to AddBlock2Diag with alpha = -1, i.e. subtracts from the current diagonal.
Definition CSysMatrix.hpp:1226
void AddBlock2Diag(unsigned long block_i, const OtherType &val_block, T alpha=1.0)
Non overwrite version of SetBlock2Diag, also with scaling.
Definition CSysMatrix.hpp:1218
void SetBlock(unsigned long block_i, unsigned long block_j, MatrixType &val_block, std::decay_t< typename MatrixType::Scalar > alpha=1.0)
Set the value of a scaled block in the sparse matrix.
Definition CSysMatrix.hpp:820
const ScalarType * GetBlock(unsigned long block_i, unsigned long block_j) const
Get a pointer to the start of block "ij".
Definition CSysMatrix.hpp:760
void AddVal2Diag(unsigned long block_i, OtherType val_matrix)
Adds the specified value to the diagonal of the (i, i) subblock of the matrix-by-blocks structure.
Definition CSysMatrix.hpp:1237
CBlockView< const ScalarType > GetBlockView(unsigned long block_i, unsigned long block_j) const
Read-only view of block (block_i, block_j). In Q_LU_SGS mode values are decoded on access inside CBlo...
Definition CSysMatrix.hpp:785
ScalarType GetResidual() const
Get the final residual.
Definition CSysSolve.hpp:493
void SetxIsZero(bool isZero)
Assume the initial solution is 0 to save one product, or don't.
Definition CSysSolve.hpp:503
unsigned long Solve(MatrixType &Jacobian, const CSysVector< su2double > &LinSysRes, CSysVector< su2double > &LinSysSol, CGeometry *geometry, const CConfig *config)
Solve the linear system using a Krylov subspace method.
Definition CSysSolve.cpp:1406
void SubtractBlock(unsigned long iPoint, const VectorType &block)
Subtract "block" from the vector, see AddBlock.
Definition CSysVector.hpp:639
ScalarType * GetBlock(unsigned long iPoint)
Get pointer to a block.
Definition CSysVector.hpp:600
void SetBlock_Zero(unsigned long iPoint)
Set the values to zero for one block.
Definition CSysVector.hpp:607
void AddBlock(unsigned long iPoint, const VectorType &block, ScalarType alpha=1)
Add "block" to the vector, see SetBlock.
Definition CSysVector.hpp:631
Main class for defining the variables.
Definition CVariable.hpp:50
virtual su2double GetDES_LengthScale(unsigned long iPoint) const
A virtual member.
Definition CVariable.hpp:394
virtual su2double GetLES_Mode(unsigned long iPoint) const
A virtual member.
Definition CVariable.hpp:406
su2double GetSolution(unsigned long iPoint, unsigned long iVar) const
Get the solution.
Definition CVariable.hpp:248
void Set_Solution_time_n1()
Set the variable solution at time n-1.
Definition CVariable.cpp:119
virtual su2double GetLangevinSourceTerms(unsigned long iPoint, unsigned short iDim) const
A virtual member.
Definition CVariable.hpp:420
void Set_Solution_time_n()
Set the variable solution at time n.
Definition CVariable.cpp:114
void AddError_RMS(unsigned short val_var, su2double val_error)
Increments the global RMS error for verification cases.
Definition CVerificationSolution.hpp:142
void SetVerificationError(unsigned long nDOFsGlobal, CConfig *config)
Calculate the global error metrics for verification cases.
Definition CVerificationSolution.cpp:122
void AddError_Max(unsigned short val_var, su2double val_error, unsigned long val_point, const su2double *val_coord)
Increment the global maximum error for verification cases.
Definition CVerificationSolution.hpp:168
void SetError_Max(unsigned short val_var, su2double val_error, unsigned long val_point)
Set the global maximum error for verification cases.
Definition CVerificationSolution.hpp:156
void GetLocalError(const su2double *val_coords, const su2double val_t, const su2double *GetLocalErrorval_solution, su2double *val_error) const
Get the local error defined as the local solution minus the verification solution.
Definition CVerificationSolution.cpp:109
void GetInitialCondition(const su2double *val_coords, su2double *val_solution) const
Get the exact solution at the current position and t = 0.
Definition CVerificationSolution.cpp:88
virtual void GetBCState(const su2double *val_coords, const su2double val_t, su2double *val_solution) const
Get the boundary conditions state for an exact solution.
Definition CVerificationSolution.cpp:93
virtual bool ExactSolutionKnown(void) const
Whether or not the exact solution is known for this verification solution.
Definition CVerificationSolution.cpp:107
void SetError_RMS(unsigned short val_var, su2double val_error)
Set the global RMS error for verification cases.
Definition CVerificationSolution.hpp:135
void GetNormal(su2double *val_normal) const override
Copy the the normal vector of a face.
Definition CVertex.hpp:94
const su2double & GetNearestNeighborDistance() const
Get the distance to the nearest internal neighbor that is not a wall.
Definition CVertex.hpp:332
unsigned long GetNode() const
Get the node of the vertex.
Definition CVertex.hpp:70
unsigned long GetNormal_Neighbor() const
Get the value of the closest neighbor.
Definition CVertex.hpp:322
A simple SIMD type relying on implicit vectorization, i.e. done by the compiler, explicitly vectorize...
Definition vectorization.hpp:89
@ Size
Definition vectorization.hpp:95
uint32_t su2uint
Definition code_config.hpp:121
passivedouble su2double
Definition code_config.hpp:181
void AllocVectorOfVectors(size_t M, const IndexVector &N, VectorOfVector &X, Scalar val=0)
Allocate a vector of varying-size vectors and initialize with some value.
Definition container_decorators.hpp:275
void AllocVectorOfMatrices(size_t M, const IndexVector &N, size_t P, VectorOfMatrix &X, Scalar val=0)
Allocate a vector of matrices with varying row count, and initialize with some value.
Definition container_decorators.hpp:303
void computeLimiters(LIMITER LimiterKind, 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)
A wrapper funtion that calls specialized implementations depending on "LimiterKind"....
Definition computeLimiters.hpp:39
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
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 DotProduct(Int nDim, const T *a, const T *b)
Definition geometry_toolbox.hpp:65
void TangentProjection(Int nDim, const Mat &tensor, const Scalar *vector, Scalar *proj)
Tangent projection
Definition geometry_toolbox.hpp:246
T Norm(Int nDim, const T *a)
Definition geometry_toolbox.hpp:79
T NormalDistance(Int nDim, const T *n, const T *a, const T *b)
dn = max(abs(n.(a-b)), 0.05 * ||a-b||
Definition geometry_toolbox.hpp:85
void PointPointReflect(Int nDim, const T *a, const T *b, T *d)
Reflect a at b: c = 2*b - a.
Definition geometry_toolbox.hpp:59
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 MPI_INT
Definition mpi_structure.hpp:491
#define MPI_MAX
Definition mpi_structure.hpp:490
#define CURRENT_FUNCTION
Definition mpi_structure.hpp:59
#define MPI_UNSIGNED_LONG
Definition mpi_structure.hpp:480
#define MPI_SUM
Definition mpi_structure.hpp:486
#define MPI_MIN
Definition mpi_structure.hpp:489
#define MPI_DOUBLE
Definition mpi_structure.hpp:484
bool PauseRecording()
Pause the recording of the operations and involved variables. If called, all operations occuring afte...
Definition ad_structure.hpp:69
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 StartNoSharedReading()
Begin a hybrid parallel adjoint evaluation mode that assumes an inherently safe reverse path.
Definition ad_structure.hpp:404
void EndNoSharedReading()
End the "no shared reading" adjoint evaluation mode.
Definition ad_structure.hpp:409
bool PausePreaccumulation()
Pause the use of preaccumulation.
Definition ad_structure.hpp:393
void ResumeRecording(bool wasActive)
Resume the recording of the operations and variables after the recording had been paused.
Definition ad_structure.hpp:74
passivedouble GetValue(const su2double &data)
Get the (primitive) value of the datatype (needs to be specialized for active types).
Definition datatype_structure.hpp:113
#define BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS
Definition omp_structure.hpp:187
#define END_SU2_OMP_FOR
Definition omp_structure.hpp:158
#define END_SU2_OMP_PARALLEL
Definition omp_structure.hpp:157
constexpr int omp_get_max_threads()
Maximum number of threads available.
Definition omp_structure.hpp:70
#define SU2_OMP_FOR_(ARGS)
Definition omp_structure.hpp:149
#define SU2_NOWAIT
Definition omp_structure.hpp:153
#define END_SU2_OMP_SAFE_GLOBAL_ACCESS
Definition omp_structure.hpp:192
#define END_SU2_OMP_MASTER
Definition omp_structure.hpp:155
#define SU2_OMP_BARRIER
Definition omp_structure.hpp:142
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_MASTER
Definition omp_structure.hpp:141
#define SU2_OMP_FOR_DYN(CHUNK)
Definition omp_structure.hpp:150
#define SU2_OMP_CRITICAL
Definition omp_structure.hpp:143
#define SU2_OMP_PARALLEL
Definition omp_structure.hpp:145
#define SU2_OMP_SAFE_GLOBAL_ACCESS(...)
Definition omp_structure.hpp:197
#define END_SU2_OMP_CRITICAL
Definition omp_structure.hpp:156
void atomicMax(const T &local, T &shared)
Definition omp_structure.hpp:305
#define SU2_OMP_FOR_STAT(CHUNK)
Definition omp_structure.hpp:151
constexpr size_t nextMultiple(size_t argument, size_t multiple)
Round up to next multiple.
Definition omp_structure.hpp:211
const int MASTER_NODE
Master node for MPI parallelization.
Definition option_structure.hpp:112
@ NONE
No wall function treatment, integration to the wall. Default behavior.
WALL_TYPE
types of wall boundary condition - smooth or rough
Definition option_structure.hpp:2216
@ SMOOTH
Smooth wall.
@ ROUGH
Rough wall.
@ YES
Boolean definition of yes.
Definition option_structure.hpp:284
@ EULER_IMPLICIT
Implicit Euler time integration definition.
Definition option_structure.hpp:1711
@ SPACE_CENTERED
Space centered convective numerical method.
Definition option_structure.hpp:632
@ MSW
Modified Steger-Warming method.
@ INCOMPRESSIBLE
Definition of incompressible solver.
@ COMPRESSIBLE
Definition of compressible solver.
@ SST
Kind of Turbulence model (Menter SST).
@ NONE
No turbulence model.
const unsigned int MESH_0
Definition of the finest grid level.
Definition option_structure.hpp:88
@ TOTAL_HEATFLUX
Total heat flux.
Definition option_structure.hpp:2231
@ FORCE_Y_COEFFICIENT
Y-direction force objective function definition.
Definition option_structure.hpp:2240
@ SURFACE_SPECIES_VARIANCE
Species Variance objective function definition.
Definition option_structure.hpp:2257
@ SURFACE_MASSFLOW
Mass Flow Rate objective function definition.
Definition option_structure.hpp:2249
@ TORQUE_COEFFICIENT
Torque objective function definition.
Definition option_structure.hpp:2243
@ MAXIMUM_HEATFLUX
Maximum heat flux.
Definition option_structure.hpp:2232
@ THRUST_COEFFICIENT
Thrust objective function definition.
Definition option_structure.hpp:2242
@ SURFACE_MOM_DISTORTION
Momentum distortion objective function definition.
Definition option_structure.hpp:2253
@ SURFACE_SECOND_OVER_UNIFORM
Secondary over uniformity (relative secondary strength) objective function definition.
Definition option_structure.hpp:2254
@ SURFACE_PRESSURE_DROP
Pressure drop objective function definition.
Definition option_structure.hpp:2255
@ MOMENT_X_COEFFICIENT
Pitching moment objective function definition.
Definition option_structure.hpp:2234
@ SIDEFORCE_COEFFICIENT
Side force objective function definition.
Definition option_structure.hpp:2227
@ LIFT_COEFFICIENT
Lift objective function definition.
Definition option_structure.hpp:2226
@ INVERSE_DESIGN_HEATFLUX
Heat flux objective function definition (inverse design).
Definition option_structure.hpp:2230
@ SURFACE_SECONDARY
Secondary flow strength objective function definition.
Definition option_structure.hpp:2252
@ SURFACE_SPECIES_0
Surface Avg. Species_0 objective function definition.
Definition option_structure.hpp:2256
@ INVERSE_DESIGN_PRESSURE
Pressure objective function definition (inverse design).
Definition option_structure.hpp:2229
@ EFFICIENCY
Efficiency objective function definition.
Definition option_structure.hpp:2228
@ FORCE_Z_COEFFICIENT
Z-direction force objective function definition.
Definition option_structure.hpp:2241
@ DRAG_COEFFICIENT
Drag objective function definition.
Definition option_structure.hpp:2225
@ SURFACE_TOTAL_PRESSURE
Total Pressure objective function definition.
Definition option_structure.hpp:2246
@ MOMENT_Y_COEFFICIENT
Rolling moment objective function definition.
Definition option_structure.hpp:2235
@ FORCE_X_COEFFICIENT
X-direction force objective function definition.
Definition option_structure.hpp:2239
@ SURFACE_STATIC_TEMPERATURE
Static Temperature objective function definition.
Definition option_structure.hpp:2248
@ CUSTOM_OBJFUNC
Custom objective function definition.
Definition option_structure.hpp:2258
@ EQUIVALENT_AREA
Equivalent area objective function definition.
Definition option_structure.hpp:2237
@ FIGURE_OF_MERIT
Rotor Figure of Merit objective function definition.
Definition option_structure.hpp:2244
@ SURFACE_STATIC_PRESSURE
Static Pressure objective function definition.
Definition option_structure.hpp:2247
@ SURFACE_UNIFORMITY
Flow uniformity objective function definition.
Definition option_structure.hpp:2251
@ MOMENT_Z_COEFFICIENT
Yawing objective function definition.
Definition option_structure.hpp:2236
@ RIGID_MOTION
Simulation with rigid mesh motion (plunging/pitching/rotation).
Definition option_structure.hpp:862
constexpr passivedouble PI_NUMBER
Pi number (not using M_PI to avoid Windows issues).
Definition option_structure.hpp:108
constexpr passivedouble COLORING_EFF_THRESH
Below this value fallback strategies are used instead.
Definition option_structure.hpp:270
@ DT_STEPPING_1ST
Use a dual time stepping strategy for unsteady computations (1st order).
@ DT_STEPPING_2ND
Use a dual time stepping strategy for unsteady computations (2nd order).
@ STEADY
A steady computation.
@ RUNTIME_FLOW_SYS
One-physics case, the code is solving the flow equations(Euler and Navier-Stokes).
Definition option_structure.hpp:559
constexpr passivedouble EPS
Error scale.
Definition option_structure.hpp:100
@ COMM_FULL
Perform all MPI communications.
Definition option_structure.hpp:2912
@ FLOW_SOL
Position of the mean flow solution in the solver container array.
Definition option_structure.hpp:577
@ TURB_SOL
Position of the turbulence model solution in the solver container array.
Definition option_structure.hpp:579
const int SINGLE_NODE
There is only a node in the MPI parallelization.
Definition option_structure.hpp:113
@ ENGINE_EXHAUST
Boundary nacelle exhaust.
Definition option_structure.hpp:1829
@ INTERNAL_BOUNDARY
Internal Boundary definition.
Definition option_structure.hpp:1840
@ EULER_WALL
Boundary Euler wall definition.
Definition option_structure.hpp:1815
@ ISOTHERMAL
No slip isothermal wall boundary condition.
Definition option_structure.hpp:1831
@ INLET_FLOW
Boundary inlet flow definition.
Definition option_structure.hpp:1818
@ ACTDISK_OUTLET
Actuator disk outlet boundary definition.
Definition option_structure.hpp:1835
@ OUTLET_FLOW
Boundary outlet flow definition.
Definition option_structure.hpp:1819
@ SUPERSONIC_INLET
Boundary supersonic inlet definition.
Definition option_structure.hpp:1826
@ ENGINE_INFLOW
Boundary nacelle inflow.
Definition option_structure.hpp:1828
@ HEAT_FLUX
No slip constant heat flux wall boundary condition.
Definition option_structure.hpp:1832
@ FLUID_INTERFACE
Domain interface definition.
Definition option_structure.hpp:1841
@ NEARFIELD_BOUNDARY
Near-Field boundary definition.
Definition option_structure.hpp:1821
@ ACTDISK_INLET
Actuator disk inlet boundary definition.
Definition option_structure.hpp:1834
@ PERIODIC_BOUNDARY
Periodic boundary definition.
Definition option_structure.hpp:1820
@ NONE
No scalar transport model.
@ IDEAL_GAS
Ideal gas model.
Definition option_structure.hpp:642
@ STANDARD_AIR
Standard air gas model.
Definition option_structure.hpp:641
const unsigned int NO_RK_ITER
No Runge-Kutta iteration.
Definition option_structure.hpp:84
PERIODIC_QUANTITIES
Vertex-based quantities exchanged during periodic marker communications.
Definition option_structure.hpp:2843
@ PERIODIC_PRIM_LS
Primitive gradient communication for weighted Least Squares (periodic only).
Definition option_structure.hpp:2854
@ PERIODIC_PRIM_ULS_R
Same but reconstruction.
Definition option_structure.hpp:2862
@ PERIODIC_IMPLICIT
Implicit update communication to ensure consistency across periodic boundaries.
Definition option_structure.hpp:2867
@ PERIODIC_PRIM_GG
Primitive gradient communication for Green-Gauss (periodic only).
Definition option_structure.hpp:2852
@ PERIODIC_PRIM_ULS
Primitive gradient communication for unweighted Least Squares (periodic only).
Definition option_structure.hpp:2856
@ PERIODIC_NEIGHBORS
Communication of the number of neighbors for centered schemes (periodic only).
Definition option_structure.hpp:2846
@ PERIODIC_PRIM_GG_R
Same but reconstruction.
Definition option_structure.hpp:2858
@ PERIODIC_RESIDUAL
Residual and Jacobian communication (periodic only).
Definition option_structure.hpp:2847
@ PERIODIC_LIM_PRIM_2
Primitive limiter communication phase 2 of 2 (periodic only).
Definition option_structure.hpp:2866
@ PERIODIC_LIM_PRIM_1
Primitive limiter communication phase 1 of 2 (periodic only).
Definition option_structure.hpp:2865
@ PERIODIC_VOLUME
Volume communication for summing total CV (periodic only).
Definition option_structure.hpp:2845
@ PERIODIC_PRIM_LS_R
Same but reconstruction.
Definition option_structure.hpp:2860
@ PRIMITIVE_GRAD_REC
Primitive reconstruction gradient communication.
@ PRIMITIVE_LIMITER
Primitive limiter communication.
@ GRID_VELOCITY
Grid velocity communication.
@ PRIMITIVE_GRADIENT
Primitive gradient communication.
@ SOLUTION
Conservative solution communication.
@ WEIGHTED_LEAST_SQUARES
Gradients computation using inverse-distance weighted least squares.
Definition option_structure.hpp:1782
@ GREEN_GAUSS
Gradient computation using Green-Gauss theorem.
Definition option_structure.hpp:1780
su2double * CQ
Torque coefficient.
Definition CFVMFlowSolverBase.hpp:106
su2double * CMz
z Moment coefficient.
Definition CFVMFlowSolverBase.hpp:101
su2double * CT
Thrust coefficient.
Definition CFVMFlowSolverBase.hpp:105
su2double * CoPz
z Moment coefficient.
Definition CFVMFlowSolverBase.hpp:104
su2double * CMy
y Moment coefficient.
Definition CFVMFlowSolverBase.hpp:100
su2double * CoPy
y Moment coefficient.
Definition CFVMFlowSolverBase.hpp:103
su2double * CFy
y Force coefficient.
Definition CFVMFlowSolverBase.hpp:97
su2double * CMx
x Moment coefficient.
Definition CFVMFlowSolverBase.hpp:99
void allocate(int size)
Allocates arrays.
Definition CFVMFlowSolverBase.inl:36
su2double * CD
Drag coefficient.
Definition CFVMFlowSolverBase.hpp:92
void setZero()
Definition CFVMFlowSolverBase.hpp:121
su2double * CMerit
Rotor Figure of Merit.
Definition CFVMFlowSolverBase.hpp:107
su2double * CoPx
x Moment coefficient.
Definition CFVMFlowSolverBase.hpp:102
su2double * CSF
Sideforce coefficient.
Definition CFVMFlowSolverBase.hpp:94
su2double * CEff
Efficiency (Cl/Cd).
Definition CFVMFlowSolverBase.hpp:95
su2double * CFz
z Force coefficient.
Definition CFVMFlowSolverBase.hpp:98
~AeroCoeffsArray()
Definition CFVMFlowSolverBase.inl:58
int _size
Array size.
Definition CFVMFlowSolverBase.hpp:108
su2double * CL
Lift coefficient.
Definition CFVMFlowSolverBase.hpp:93
su2double * CFx
x Force coefficient.
Definition CFVMFlowSolverBase.hpp:96
void setZero(int i)
Sets all values to zero for all indices.
Definition CFVMFlowSolverBase.hpp:113
su2double CMerit
Definition CFVMFlowSolverBase.hpp:138
su2double CEff
Definition CFVMFlowSolverBase.hpp:138
su2double CT
Definition CFVMFlowSolverBase.hpp:138
su2double CQ
Definition CFVMFlowSolverBase.hpp:138
su2double CD
Definition CFVMFlowSolverBase.hpp:138
void setZero()
Definition CFVMFlowSolverBase.hpp:140
su2double CL
Definition CFVMFlowSolverBase.hpp:138
Return type used in some "ComputeResidual" overloads to give a const-view of the internally stored fl...
Definition CNumerics.hpp:218
A way to represent natural coloring {0,1,2,...,size-1} with zero overhead (behaves like looping with ...
Definition graph_toolbox.hpp:684
bool qcr2000
Use QCR-2000.
Definition option_structure.hpp:1293
#define SU2_ZONE_SCOPED
Definition tracy_structure.hpp:39