Documentation 6b54b78464
Loading...
Searching...
No Matches
CScalarSolver.inl
Go to the documentation of this file.
1/*!
2 * \file CScalarSolver.inl
3 * \brief Main subroutines of CScalarSolver class
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#include "../../../Common/include/parallelization/omp_structure.hpp"
28#include "../../../Common/include/toolboxes/geometry_toolbox.hpp"
29#include "../../include/solvers/CScalarSolver.hpp"
30#include "../../include/variables/CFlowVariable.hpp"
31
32template <class VariableType>
34 bool conservative, bool bounded_scalar,
35 LINEAR_SOLVER_MODE linear_solver_mode)
36 : CSolver(linear_solver_mode), Conservative(conservative), BoundedScalar(bounded_scalar),
37 prim_idx(config->GetKind_Regime() == ENUM_REGIME::INCOMPRESSIBLE,
38 config->GetNEMOProblem(), geometry->GetnDim(), config->GetnSpecies()) {
40
41 nDim = geometry->GetnDim();
42 nMarker = config->GetnMarker_All();
43
44 /*--- Store the number of vertices on each marker for deallocation later ---*/
45 nVertex.resize(nMarker);
46 for (unsigned long iMarker = 0; iMarker < nMarker; iMarker++) nVertex[iMarker] = geometry->nVertex[iMarker];
47
48 /* A grid is defined as dynamic if there's rigid grid movement or grid deformation AND the problem is time domain */
49 dynamic_grid = config->GetDynamic_Grid();
50
51#ifdef HAVE_OMP
52 /*--- Get the edge coloring, see notes in CEulerSolver's constructor. ---*/
53 su2double parallelEff = 1.0;
54#ifdef CODI_REVERSE_TYPE
55 /*--- For the discrete adjoint, the reducer strategy is costly. Prefer coloring, possibly with reduced edge color
56 * group size. Find the maximum edge color group size that yields an efficient coloring. Also, allow larger numbers
57 * of colors. ---*/
58 const bool relax = config->GetEdgeColoringRelaxDiscAdj();
59 const auto& coloring = geometry->GetEdgeColoring(&parallelEff, relax);
60#else
61 const auto& coloring = geometry->GetEdgeColoring(&parallelEff);
62#endif
63
65
66 if (ReducerStrategy && (coloring.getOuterSize() > 1)) geometry->SetNaturalEdgeColoring();
67
68 if (!coloring.empty()) {
69 auto groupSize = static_cast<su2uint>(ReducerStrategy ? 1ul : geometry->GetEdgeColorGroupSize());
70 auto nColor = coloring.getOuterSize();
71 EdgeColoring.reserve(nColor);
72
73 for (auto iColor = 0ul; iColor < nColor; ++iColor)
74 EdgeColoring.emplace_back(coloring.innerIdx(iColor), coloring.getNumNonZeros(iColor), groupSize);
75 }
76
77 nPoint = geometry->GetnPoint();
79#else
80 EdgeColoring[0] = DummyGridColor<>(geometry->GetnEdge());
81#endif
82
83 /*--- Initialize lower and upper limits for solution clipping. Solvers might overwrite these values. ---*/
84 for (unsigned int iVar = 0; iVar < MAXNVAR; iVar++) {
85 lowerlimit[iVar] = std::numeric_limits<su2double>::lowest();
86 upperlimit[iVar] = std::numeric_limits<su2double>::max();
87 }
88
89 /*--- Ghost flow states and the per-vertex buffers the boundaries share, sized to the largest
90 * marker (see BoundaryFluxResidual) and to the primitive layout of the flow solver. Built here,
91 * where only one thread is running: the boundaries are reached inside a parallel region, and
92 * allocating there would mean a master region, which a CVariable constructor may not run in
93 * (CFlowVariable seeds the BGS solution with an OpenMP work-sharing loop, whose barrier would
94 * take an arrival of the team barrier the other threads are waiting on). ---*/
95 if (flow_solver != nullptr) {
96 unsigned long maxMarkerVertices = 0;
97 for (auto iMarker = 0u; iMarker < nMarker; ++iMarker) maxMarkerVertices = max(maxMarkerVertices, nVertex[iMarker]);
98
99 ghostFlowNodes = make_unique<CGhostFlowVariable>(maxMarkerVertices, nDim, flow_solver->GetnVar(),
100 flow_solver->GetnPrimVar(), flow_solver->GetnPrimVarGrad(),
101 config);
102 ghostNormal.resize(maxMarkerVertices, nDim);
103 ghostCoord.resize(maxMarkerVertices, nDim);
104 ghostSkip.resize(maxMarkerVertices);
105 }
106}
107
108template <class VariableType>
112
113template <class VariableType>
114void CScalarSolver<VariableType>::CommonPreprocessing(CGeometry *geometry, const CConfig *config, const bool Output) {
116
117 /*--- Define booleans that are solver specific through CConfig's GlobalParams which have to be set in CFluidIteration
118 * before calling these solver functions. ---*/
119 const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
120 const bool muscl = config->GetMUSCL();
121 const bool limiter = (config->GetKind_SlopeLimit() != LIMITER::NONE) &&
122 (config->GetInnerIter() <= config->GetLimiterIter());
123
124 /*--- Clear residual and system matrix, not needed for
125 * reducer strategy as we write over the entire matrix. ---*/
126 if (!ReducerStrategy && !Output) {
127 LinSysRes.SetValZero();
128 if (implicit) {
129 Jacobian.SetValDiagonalZero();
130 } else {
132 }
133 }
134
135 /*--- Upwind second order reconstruction and gradients ---*/
136
137 if (config->GetReconstructionGradientRequired()) {
138 switch(config->GetKind_Gradient_Method_Recon()) {
139 case GREEN_GAUSS: SetSolution_Gradient_GG(geometry, config, -1, true); break;
140 case LEAST_SQUARES: SetSolution_Gradient_LS(geometry, config, -1, true); break;
141 case WEIGHTED_LEAST_SQUARES: SetSolution_Gradient_LS(geometry, config, -1, true); break;
142 }
143 }
144
145 switch(config->GetKind_Gradient_Method()) {
146 case GREEN_GAUSS: SetSolution_Gradient_GG(geometry, config, -1); break;
147 case WEIGHTED_LEAST_SQUARES: SetSolution_Gradient_LS(geometry, config, -1); break;
148 }
149
150 if (limiter && muscl) SetSolution_Limiter(geometry, config);
151}
152
153template <class VariableType>
156
157 /*--- EdgeFluxes and EdgeFluxesDiff hold the two row contributions of an edge directly,
158 * flux_i and flux_j, so each point simply accumulates its own side of every incident edge. ---*/
159 SU2_OMP_FOR_STAT(omp_chunk_size)
160 for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) {
161 LinSysRes.SetBlock_Zero(iPoint);
162
163 for (auto iEdge : geometry->nodes->GetEdges(iPoint)) {
164 if (iPoint == geometry->edges->GetNode(iEdge, 0)) {
165 LinSysRes.AddBlock(iPoint, EdgeFluxes.GetBlock(iEdge));
166 } else {
167 LinSysRes.AddBlock(iPoint, EdgeFluxesDiff.GetBlock(iEdge));
168 }
169 }
170 }
172}
173
174template <class VariableType>
175template <class Scheme>
176void CScalarSolver<VariableType>::EdgeFluxResidual(const CGeometry* geometry, CSolver** solver_container,
177 const CConfig* config, const ScalarFluxOptions& opt) {
179
180 using Double = typename Scheme::Double;
181 constexpr int nDim = Scheme::nDim;
182
183 const Scheme flux(*config);
184
185 /*--- Null for solid heat transfer, which has no flow solver to mirror (see EdgeSide). ---*/
186 auto* flowSolver = solver_container[FLOW_SOL];
187 auto* flowNodes = flowSolver ? su2staticcast_p<CFlowVariable*>(flowSolver->GetNodes()) : nullptr;
188 const auto* edgeMassFluxes = flowSolver ? flowSolver->GetEdgeMassFluxes() : nullptr;
189
190 const EdgeSide<VariableType> side{*nodes, flowNodes, CMatrixView<const su2double>(geometry->nodes->GetCoord()),
191 dynamic_grid ? CMatrixView<const su2double>(geometry->nodes->GetGridVel())
193
194 const auto updateType = ReducerStrategy ? UpdateType::REDUCTION : UpdateType::COLORING;
195 auto& target = ReducerStrategy ? EdgeFluxes : LinSysRes;
196
197 /*--- Under the reducer the edges of a thread are not disjoint in their points, so
198 * preaccumulation is paused; under coloring they are, and the faster adjoint evaluation
199 * mode applies. ---*/
200 bool pausePreacc = false;
201 if (ReducerStrategy) pausePreacc = AD::PausePreaccumulation();
203
204 for (auto color : EdgeColoring) {
205 SU2_OMP_FOR_DYN(nextMultiple(OMP_MIN_SIZE, color.groupSize))
206 for (auto k = 0ul; k < color.size; ++k) {
207 const unsigned long iEdge = color.indices[k];
208 const auto iPoint = geometry->edges->GetNode(iEdge, 0);
209 const auto jPoint = geometry->edges->GetNode(iEdge, 1);
210 const auto normal = gatherVariables<nDim>(iEdge, geometry->edges->GetNormal());
211
212 const Double massFlux = opt.boundedScalar ? gatherVariables(iEdge, *edgeMassFluxes) : Double(0.0);
213
214 flux.ComputeFlux(opt, iEdge, iPoint, side, jPoint, side, normal, massFlux, updateType, 1.0, target,
215 EdgeFluxesDiff, Jacobian);
216
217 /*--- Bounded scalar divergence correction, per edge; the ReducerStrategy equivalent runs
218 * in a per-point pass below, where the diagonal is not written from the edge loop. ---*/
219 if (opt.boundedScalar && !ReducerStrategy) {
220 LinSysRes.AddBlock(iPoint, nodes->GetSolution(iPoint), -massFlux);
221 LinSysRes.AddBlock(jPoint, nodes->GetSolution(jPoint), massFlux);
222 if (opt.implicit) {
223 Jacobian.AddVal2Diag(iPoint, -massFlux);
224 Jacobian.AddVal2Diag(jPoint, massFlux);
225 }
226 }
227 }
229 }
230
231 AD::ResumePreaccumulation(pausePreacc);
232 if (!ReducerStrategy) AD::EndNoSharedReading();
233
234 if (ReducerStrategy) {
235 SumEdgeFluxes(geometry);
236 if (opt.implicit) Jacobian.SetDiagonalAsColumnSum();
237
238 if (opt.boundedScalar) {
239 SU2_OMP_FOR_STAT(omp_chunk_size)
240 for (unsigned long iPoint = 0; iPoint < nPoint; ++iPoint) {
241 const auto* solution = nodes->GetSolution(iPoint);
242 su2double divergence = 0;
243
244 for (auto iEdge : geometry->nodes->GetEdges(iPoint)) {
245 const auto sign = (iPoint == geometry->edges->GetNode(iEdge, 0)) ? 1 : -1;
246 const su2double edgeMassFlux = sign * (*edgeMassFluxes)[iEdge];
247 divergence += edgeMassFlux;
248 LinSysRes.AddBlock(iPoint, solution, -edgeMassFlux);
249 }
250 if (opt.implicit) Jacobian.AddVal2Diag(iPoint, -divergence);
251 }
253 }
254 }
255}
256
257template <class VariableType>
258template <class Scheme>
260 const CConfig* config, const ScalarFluxOptions& opt,
261 unsigned short val_marker) {
262 using Double = typename Scheme::Double;
263 constexpr int nDim = Scheme::nDim;
264
265 const Scheme flux(*config);
266
267 auto* flowNodes = su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes());
268
269 const EdgeSide<VariableType> side_i{*nodes, flowNodes, CMatrixView<const su2double>(geometry->nodes->GetCoord()),
270 dynamic_grid ? CMatrixView<const su2double>(geometry->nodes->GetGridVel())
272
273 const EdgeSide<VariableType> side_j{*ghostNodes, ghostFlowNodes.get(), CMatrixView<const su2double>(ghostCoord),
274 side_i.gridVel};
276 SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
277 for (unsigned long iVertex = 0; iVertex < geometry->nVertex[val_marker]; iVertex++) {
278 const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode();
279 if (!geometry->nodes->GetDomain(iPoint) || ghostSkip[iVertex]) continue;
280
281 const auto normal = gatherVariables<nDim>(iVertex, ghostNormal);
282
283 Double massFlux = 0.0;
284 if (opt.boundedScalar) {
285 massFlux = BoundedScalarBCFlux(iPoint, opt.implicit, flowNodes->GetDensity(iPoint),
286 &ghostFlowNodes->GetPrimitive(iVertex)[prim_idx.Velocity()], normal.data());
287 }
288
289 const auto res = flux.ComputeFlux(opt, iPoint, side_i, iVertex, side_j, normal, massFlux);
290
291 /*--- The ghost point has no row, only the contribution to i is assembled. ---*/
292 for (auto iVar = 0ul; iVar < res.nVar; ++iVar) LinSysRes(iPoint, iVar) += res.flux_i(iVar);
293 if (opt.implicit) Jacobian.AddBlock2Diag(iPoint, res.jac_ii);
294 }
296}
297
298template <class VariableType>
299template <class Scheme, class GhostFunc>
301 const CConfig* config, const ScalarFluxOptions& optConv,
302 const ScalarFluxOptions& optVisc,
303 const GhostFunc& fillGhostExtras) {
304 constexpr int nDim = Scheme::nDim;
305
306 const Scheme flux(*config);
307
308 auto* flowSolver = solver_container[FLOW_SOL];
309 auto* flowNodes = su2staticcast_p<CFlowVariable*>(flowSolver->GetNodes());
310 const auto nPrimVar = flowSolver->GetnPrimVar();
311
312 const EdgeSide<VariableType> side_i{*nodes, flowNodes, CMatrixView<const su2double>(geometry->nodes->GetCoord()),
313 dynamic_grid ? CMatrixView<const su2double>(geometry->nodes->GetGridVel())
315 const EdgeSide<VariableType> side_j{*ghostNodes, ghostFlowNodes.get(), CMatrixView<const su2double>(ghostCoord),
316 side_i.gridVel};
317
318 su2activevector PrimVar_j(nPrimVar);
319
320 for (auto iMarker = 0u; iMarker < config->GetnMarker_All(); iMarker++) {
321 if (config->GetMarker_All_KindBC(iMarker) != FLUID_INTERFACE) continue;
322
323 SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
324 for (unsigned long iVertex = 0; iVertex < geometry->nVertex[iMarker]; iVertex++) {
325 const auto iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
326 if (!geometry->nodes->GetDomain(iPoint)) continue;
327
328 const auto Point_Normal = geometry->vertex[iMarker][iVertex]->GetNormal_Neighbor();
329 const auto nDonorVertex = GetnSlidingStates(iMarker, iVertex);
330
331 SetGhostGeometry(geometry, iMarker, iVertex);
332 const auto normal = gatherVariables<nDim>(iVertex, ghostNormal);
333
334 /*--- Loop over the donors and accumulate the weighted-average convective residual. ---*/
335 for (auto jVertex = 0; jVertex < nDonorVertex; jVertex++) {
336 for (auto iVar = 0u; iVar < nPrimVar; iVar++)
337 PrimVar_j[iVar] = flowSolver->GetSlidingState(iMarker, iVertex, iVar, jVertex);
338
339 /*--- Weight computed by the interpolator for this donor vertex. ---*/
340 const su2double weight = flowSolver->GetSlidingState(iMarker, iVertex, nPrimVar, jVertex);
341
342 for (auto iVar = 0u; iVar < nVar; iVar++)
343 ghostNodes->SetSolution(iVertex, iVar, GetSlidingState(iMarker, iVertex, iVar, jVertex));
344
345 SetGhostPrimitives(iVertex, PrimVar_j.data());
346
347 su2double massFlux = 0.0;
348 if (optConv.boundedScalar) {
349 massFlux = BoundedScalarBCFlux(iPoint, optConv.implicit, flowNodes->GetDensity(iPoint),
350 &PrimVar_j[prim_idx.Velocity()], normal.data());
351 }
352
353 const auto res = flux.ComputeFlux(optConv, iPoint, side_i, iVertex, side_j, normal, massFlux);
354
355 for (auto iVar = 0ul; iVar < res.nVar; ++iVar) LinSysRes(iPoint, iVar) += weight * res.flux_i(iVar);
356 if (optConv.implicit) Jacobian.AddBlock2Diag(iPoint, res.jac_ii, weight);
357 }
358
359 /*--- Diffusive term, computed once from the ghost state the last donor left behind. ---*/
360 SetGhostDiffusionState(geometry, iVertex, iPoint, Point_Normal);
361 fillGhostExtras(iVertex, iPoint);
362
363 const auto res = flux.ComputeFlux(optVisc, iPoint, side_i, iVertex, side_j, normal, su2double(0.0));
364 for (auto iVar = 0ul; iVar < res.nVar; ++iVar) LinSysRes(iPoint, iVar) += res.flux_i(iVar);
365 if (optVisc.implicit) Jacobian.AddBlock2Diag(iPoint, res.jac_ii);
366 }
368 }
369}
370
371template<class VariableType>
372void CScalarSolver<VariableType>::BC_Riemann(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) {
374
375 string Marker_Tag = config->GetMarker_All_TagBound(val_marker);
376
377 switch(config->GetKind_Data_Riemann(Marker_Tag))
378 {
380 BC_Inlet(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker);
381 break;
382 case STATIC_PRESSURE:
383 BC_Outlet(geometry, solver_container, conv_numerics, visc_numerics, config, val_marker);
384 break;
385 }
386}
387
388template <class VariableType>
389void CScalarSolver<VariableType>::BC_Periodic(CGeometry* geometry, CSolver** solver_container, CNumerics* numerics,
390 CConfig* config) {
392 /*--- Complete residuals for periodic boundary conditions. We loop over
393 the periodic BCs in matching pairs so that, in the event that there are
394 adjacent periodic markers, the repeated points will have their residuals
395 accumulated corectly during the communications. For implicit calculations
396 the Jacobians and linear system are also correctly adjusted here. ---*/
397
398 for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) {
399 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
400 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_RESIDUAL);
401 }
402}
403
404template <class VariableType>
406 CNumerics* conv_numerics, CNumerics*, CConfig *config,
407 unsigned short val_marker) {
409 const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
410
411 SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
412 for (auto iVertex = 0u; iVertex < geometry->nVertex[val_marker]; iVertex++) {
413
414 const auto iPoint = geometry->vertex[val_marker][iVertex]->GetNode();
415
416 /*--- Check if the node belongs to the domain (i.e, not a halo node) ---*/
417
418 if (geometry->nodes->GetDomain(iPoint)) {
419
420 /*--- Allocate the value at the infinity ---*/
421
422 auto V_infty = solver_container[FLOW_SOL]->GetCharacPrimVar(val_marker, iVertex);
423
424 /*--- Retrieve solution at the farfield boundary node ---*/
426 auto V_domain = solver_container[FLOW_SOL]->GetNodes()->GetPrimitive(iPoint);
427
428 /*--- Grid Movement ---*/
429
430 if (dynamic_grid)
431 conv_numerics->SetGridVel(geometry->nodes->GetGridVel(iPoint), geometry->nodes->GetGridVel(iPoint));
432
433 conv_numerics->SetPrimitive(V_domain, V_infty);
435 /*--- Set turbulent variable at the wall, and at infinity ---*/
436
437 conv_numerics->SetScalarVar(nodes->GetSolution(iPoint), Solution_Inf);
438
439 /*--- Set Normal (it is necessary to change the sign) ---*/
440
441 su2double Normal[MAXNDIM] = {0.0};
442 for (auto iDim = 0u; iDim < nDim; iDim++)
443 Normal[iDim] = -geometry->vertex[val_marker][iVertex]->GetNormal(iDim);
444 conv_numerics->SetNormal(Normal);
445
446 if (conv_numerics->GetBoundedScalar()) {
447 const su2double* velocity = &V_infty[prim_idx.Velocity()];
448 const su2double density = solver_container[FLOW_SOL]->GetNodes()->GetDensity(iPoint);
449 conv_numerics->SetMassFlux(BoundedScalarBCFlux(iPoint, implicit, density, velocity, Normal));
450 }
451
452 /*--- Compute residuals and Jacobians ---*/
453
454 auto residual = conv_numerics->ComputeResidual(config);
455
456 /*--- Add residuals and Jacobians ---*/
457
458 LinSysRes.AddBlock(iPoint, residual);
459 if (implicit) Jacobian.AddBlock2Diag(iPoint, residual.jacobian_i);
460 }
461 }
463}
464
465template <class VariableType>
466void CScalarSolver<VariableType>::SetTime_Step(CGeometry *geometry, CSolver **solver_container, CConfig *config,
467 unsigned short iMesh, unsigned long Iteration) {
469
470 const auto flowNodes = solver_container[FLOW_SOL]->GetNodes();
471
472 SU2_OMP_FOR_STAT(omp_chunk_size)
473 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
474 su2double dt = nodes->GetLocalCFL(iPoint) / flowNodes->GetLocalCFL(iPoint) * flowNodes->GetDelta_Time(iPoint);
475 nodes->SetDelta_Time(iPoint, dt);
476 }
478}
479
480template <class VariableType>
482 CConfig* config) {
484
485 /*--- Set shared residual variables to 0 and declare
486 * local ones for current thread to work on. ---*/
487
488 SetResToZero();
489
490 su2double resMax[MAXNVAR] = {0.0}, resRMS[MAXNVAR] = {0.0};
491 unsigned long idxMax[MAXNVAR] = {0};
492
493 /*--- Build implicit system ---*/
494
495 SU2_OMP_FOR_(schedule(static, omp_chunk_size) SU2_NOWAIT)
496 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
497 /*--- Modify matrix diagonal to improve diagonal dominance. ---*/
498 const su2double dt = nodes->GetDelta_Time(iPoint);
499
500 if (dt != 0.0) {
501 su2double Vol = geometry->nodes->GetVolume(iPoint) + geometry->nodes->GetPeriodicVolume(iPoint);
502 Jacobian.AddVal2Diag(iPoint, Vol / dt);
503 } else {
504 Jacobian.SetVal2Diag(iPoint, 1.0);
505 LinSysRes.SetBlock_Zero(iPoint);
506 }
507
508 /*--- Right hand side of the system (-Residual) and initial guess (x = 0) ---*/
509
510 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
511 LinSysRes(iPoint, iVar) = -LinSysRes(iPoint, iVar);
512 LinSysSol(iPoint, iVar) = 0.0;
513
514 /*--- "Add" residual at (iPoint,iVar) to local residual variables. ---*/
515 ResidualReductions_PerThread(iPoint, iVar, LinSysRes(iPoint, iVar), resRMS, resMax, idxMax);
517 }
519
520 /*--- "Add" residuals from all threads to global residual variables. ---*/
521 ResidualReductions_FromAllThreads(geometry, config, resRMS, resMax, idxMax);
522}
523
524template <class VariableType>
526 CConfig* config) {
528
529 ComputeUnderRelaxationFactor(solver_container, config);
530
531 /*--- Update solution (system written in terms of increments) ---*/
532
533 if (!adjoint) {
534 /*--- Update the scalar solution. For transport equations, where Solution is not equivalent with the transported
535 * quantity, multiply the respective factor. ---*/
536 if (Conservative) {
537 const auto flowNodes = solver_container[FLOW_SOL]->GetNodes();
538
539 SU2_OMP_FOR_STAT(omp_chunk_size)
540 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
541 /*--- Multiply the Solution var with density to get the conservative transported quantity, if necessary. ---*/
542 /* Note that for consistency with residual and jacobian calaulcations, use of current density for conservative variables
543 * of the old solution is used. see pull request https://github.com/su2code/SU2/pull/2458*/
544 const su2double density = flowNodes->GetDensity(iPoint);
545
546 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
547 nodes->AddClippedSolution(iPoint, iVar, nodes->GetUnderRelaxation(iPoint) * LinSysSol(iPoint, iVar),
548 lowerlimit[iVar], upperlimit[iVar], density, density);
549 }
550 }
552 } else {
553 SU2_OMP_FOR_STAT(omp_chunk_size)
554 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
555 for (unsigned short iVar = 0; iVar < nVar; iVar++) {
556 nodes->AddClippedSolution(iPoint, iVar, nodes->GetUnderRelaxation(iPoint) * LinSysSol(iPoint, iVar),
557 lowerlimit[iVar], upperlimit[iVar]);
558 }
559 }
562 }
563
564 for (unsigned short iPeriodic = 1; iPeriodic <= config->GetnMarker_Periodic() / 2; iPeriodic++) {
565 InitiatePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
566 CompletePeriodicComms(geometry, config, iPeriodic, PERIODIC_IMPLICIT);
567 }
568
569 InitiateComms(geometry, config, MPI_QUANTITIES::SOLUTION);
570 CompleteComms(geometry, config, MPI_QUANTITIES::SOLUTION);
571}
572
573template <class VariableType>
575 CConfig* config) {
578 PrepareImplicitIteration(geometry, solver_container, config);
579
580 /*--- Solve or smooth the linear system. ---*/
581
582 SU2_OMP_FOR_(schedule(static, OMP_MIN_SIZE) SU2_NOWAIT)
583 for (unsigned long iPoint = nPointDomain; iPoint < nPoint; iPoint++) {
584 LinSysRes.SetBlock_Zero(iPoint);
585 LinSysSol.SetBlock_Zero(iPoint);
586 }
588
589 auto iter = System.Solve(Jacobian, LinSysRes, LinSysSol, geometry, config);
590
592 SetIterLinSolver(iter);
593 SetResLinSolver(System.GetResidual());
594 }
597 CompleteImplicitIteration(geometry, solver_container, config);
598}
599
600template <class VariableType>
602 CConfig* config) {
604
605 /*--- Local residual variables for current thread ---*/
606 su2double resMax[MAXNVAR] = {0.0}, resRMS[MAXNVAR] = {0.0};
607 unsigned long idxMax[MAXNVAR] = {0};
608
609 SU2_OMP_FOR_STAT(omp_chunk_size)
610 for (unsigned long iPoint = 0; iPoint < nPointDomain; iPoint++) {
611 const su2double dt = nodes->GetDelta_Time(iPoint);
612 const su2double Vol = geometry->nodes->GetVolume(iPoint) + geometry->nodes->GetPeriodicVolume(iPoint);
613
614 for (auto iVar = 0u; iVar < nVar; iVar++) {
615 /*--- "Add" residual at (iPoint,iVar) to local residual variables. ---*/
616 ResidualReductions_PerThread(iPoint, iVar, LinSysRes(iPoint, iVar), resRMS, resMax, idxMax);
617 /*--- Explicit Euler step: ---*/
618 LinSysSol(iPoint, iVar) = -dt / Vol * LinSysRes(iPoint, iVar);
619 }
620 }
622
623 /*--- "Add" residuals from all threads to global residual variables. ---*/
624 ResidualReductions_FromAllThreads(geometry, config, resRMS, resMax, idxMax);
625
626 /*--- Use LinSysSol for solution update. ---*/
627 CompleteImplicitIteration(geometry, solver_container, config);
628}
629
630template <class VariableType>
632 unsigned short iRKStep, unsigned short iMesh,
633 unsigned short RunTime_EqSystem) {
635
636 const bool implicit = (config->GetKind_TimeIntScheme() == EULER_IMPLICIT);
637 const bool first_order = (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_1ST);
638 const bool second_order = (config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND);
639
640 const bool bounded_scalar = BoundedScalar;
641
642 /*--- Flow solution, needed to get density. ---*/
643 auto* flowNodes = su2staticcast_p<CFlowVariable*>(solver_container[FLOW_SOL]->GetNodes());
644
645 /*--- Store the physical time step ---*/
646
647 const su2double TimeStep = config->GetDelta_UnstTimeND();
648
649 /*--- Local variables ---*/
650
651 unsigned short iVar, iMarker, iDim, iNeigh;
652 unsigned long iPoint, jPoint, iVertex, iEdge;
653
654 su2double *U_time_nM1 = nullptr, *U_time_n = nullptr, *U_time_nP1 = nullptr;
655 /*--- For non-Conservative scalars (e.g. SA), multiply the Primitives with 1.0 instead of Density. ---*/
656 su2double Density_nM1 = 1.0, Density_n = 1.0, Density_nP1 = 1.0;
657 su2double Volume_nM1, Volume_nP1;
658 const su2double *Normal = nullptr, *GridVel_i = nullptr, *GridVel_j = nullptr;
659 su2double Residual_GCL;
660
661 /*--- Compute the dual time-stepping source term for static meshes ---*/
662
663 if (!dynamic_grid) {
664 /*--- Loop over all nodes (excluding halos) ---*/
665
667
668 SU2_OMP_FOR_STAT(omp_chunk_size)
669 for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
670 if (Conservative) {
671 Density_nM1 = flowNodes->GetDensity_time_n1(iPoint);
672 Density_n = flowNodes->GetDensity_time_n(iPoint);
673 Density_nP1 = flowNodes->GetDensity(iPoint);
674 }
675
676 /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that
677 we are currently iterating on U^n+1 and that U^n & U^n-1 are fixed,
678 previous solutions that are stored in memory. ---*/
679
680 U_time_nM1 = nodes->GetSolution_time_n1(iPoint);
681 U_time_n = nodes->GetSolution_time_n(iPoint);
682 U_time_nP1 = nodes->GetSolution(iPoint);
683
684 /*--- CV volume at time n+1. As we are on a static mesh, the volume
685 of the CV will remained fixed for all time steps. ---*/
686
687 Volume_nP1 = geometry->nodes->GetVolume(iPoint);
688
689 /*--- Compute the dual time-stepping source term based on the chosen
690 time discretization scheme (1st- or 2nd-order).---*/
691
692 for (iVar = 0; iVar < nVar; iVar++) {
693 su2double unsteady_term = 0.0;
694 if (first_order)
695 unsteady_term = (Density_nP1 * U_time_nP1[iVar] - Density_n * U_time_n[iVar]) * Volume_nP1 / TimeStep;
696 if (second_order)
697 unsteady_term = (3.0 * Density_nP1 * U_time_nP1[iVar] - 4.0 * Density_n * U_time_n[iVar] +
698 1.0 * Density_nM1 * U_time_nM1[iVar]) *
699 Volume_nP1 / (2.0 * TimeStep);
700
701 if (bounded_scalar) {
702 if (first_order) unsteady_term -= U_time_nP1[iVar] * (Density_nP1 - Density_n) * Volume_nP1 / TimeStep;
703 if (second_order) unsteady_term -= U_time_nP1[iVar] * (3.0 * Density_nP1 - 4.0 * Density_n + 1.0 * Density_nM1) * Volume_nP1 / (2.0 * TimeStep);
704 }
705
706 LinSysRes(iPoint, iVar) += unsteady_term;
707 }
708
709 /*--- Compute the Jacobian contribution due to the dual time source term. ---*/
710 if (implicit) {
711 if (first_order) Jacobian.AddVal2Diag(iPoint, Volume_nP1 / TimeStep);
712 if (second_order) Jacobian.AddVal2Diag(iPoint, (Volume_nP1 * 3.0) / (2.0 * TimeStep));
713 }
714 }
716
718
719 } else {
720 /*--- For unsteady flows on dynamic meshes (rigidly transforming or
721 dynamically deforming), the Geometric Conservation Law (GCL) should be
722 satisfied in conjunction with the ALE formulation of the governing
723 equations. The GCL prevents accuracy issues caused by grid motion, i.e.
724 a uniform free-stream should be preserved through a moving grid. First,
725 we will loop over the edges and boundaries to compute the GCL component
726 of the dual time source term that depends on grid velocities. ---*/
727
728 SU2_OMP_FOR_STAT(omp_chunk_size)
729 for (iPoint = 0; iPoint < nPointDomain; ++iPoint) {
730 GridVel_i = geometry->nodes->GetGridVel(iPoint);
731 U_time_n = nodes->GetSolution_time_n(iPoint);
732
733 if (Conservative) {
734 Density_n = flowNodes->GetDensity_time_n(iPoint);
735 }
736
737 for (iNeigh = 0; iNeigh < geometry->nodes->GetnPoint(iPoint); iNeigh++) {
738 iEdge = geometry->nodes->GetEdge(iPoint, iNeigh);
739 Normal = geometry->edges->GetNormal(iEdge);
740
741 jPoint = geometry->nodes->GetPoint(iPoint, iNeigh);
742 GridVel_j = geometry->nodes->GetGridVel(jPoint);
743
744 /*--- Determine whether to consider the normal outward or inward. ---*/
745 su2double dir = (iPoint < jPoint) ? 0.5 : -0.5;
746
747 Residual_GCL = 0.0;
748 for (iDim = 0; iDim < nDim; iDim++) Residual_GCL += dir * (GridVel_i[iDim] + GridVel_j[iDim]) * Normal[iDim];
749
750 Residual_GCL *= Density_n;
751
752 for (iVar = 0; iVar < nVar; iVar++) LinSysRes(iPoint, iVar) += U_time_n[iVar] * Residual_GCL;
753 }
754 }
756
757 /*--- Loop over the boundary edges ---*/
758
759 for (iMarker = 0; iMarker < geometry->GetnMarker(); iMarker++) {
760 if ((config->GetMarker_All_KindBC(iMarker) != INTERNAL_BOUNDARY) &&
761 (config->GetMarker_All_KindBC(iMarker) != NEARFIELD_BOUNDARY) &&
762 (config->GetMarker_All_KindBC(iMarker) != PERIODIC_BOUNDARY)) {
763 SU2_OMP_FOR_STAT(OMP_MIN_SIZE)
764 for (iVertex = 0; iVertex < geometry->GetnVertex(iMarker); iVertex++) {
765 /*--- Get the index for node i plus the boundary face normal ---*/
766
767 iPoint = geometry->vertex[iMarker][iVertex]->GetNode();
768 Normal = geometry->vertex[iMarker][iVertex]->GetNormal();
769
770 /*--- Grid velocities stored at boundary node i ---*/
771
772 GridVel_i = geometry->nodes->GetGridVel(iPoint);
773
774 /*--- Compute the GCL term by dotting the grid velocity with the face
775 normal. The normal is negated to match the boundary convention. ---*/
776
777 Residual_GCL = 0.0;
778 for (iDim = 0; iDim < nDim; iDim++) Residual_GCL -= 0.5 * (GridVel_i[iDim] + GridVel_i[iDim]) * Normal[iDim];
779
780 /*--- Compute the GCL component of the source term for node i ---*/
781
782 U_time_n = nodes->GetSolution_time_n(iPoint);
783
784 /*--- Multiply by density at node i for the SST model ---*/
785
786 if (Conservative) {
787 Density_n = flowNodes->GetDensity_time_n(iPoint);
788 }
789
790 for (iVar = 0; iVar < nVar; iVar++) LinSysRes(iPoint, iVar) += Density_n * U_time_n[iVar] * Residual_GCL;
791 }
793 }
794 }
795
796 /*--- Loop over all nodes (excluding halos) to compute the remainder
797 of the dual time-stepping source term. ---*/
798
800
801 SU2_OMP_FOR_STAT(omp_chunk_size)
802 for (iPoint = 0; iPoint < nPointDomain; iPoint++) {
803 /*--- Retrieve the solution at time levels n-1, n, and n+1. Note that
804 we are currently iterating on U^n+1 and that U^n & U^n-1 are fixed,
805 previous solutions that are stored in memory. ---*/
806
807 U_time_nM1 = nodes->GetSolution_time_n1(iPoint);
808 U_time_n = nodes->GetSolution_time_n(iPoint);
809 U_time_nP1 = nodes->GetSolution(iPoint);
810
811 /*--- CV volume at time n-1 and n+1. In the case of dynamically deforming
812 grids, the volumes will change. On rigidly transforming grids, the
813 volumes will remain constant. ---*/
814
815 Volume_nM1 = geometry->nodes->GetVolume_nM1(iPoint);
816 Volume_nP1 = geometry->nodes->GetVolume(iPoint);
817
818 /*--- Compute the dual time-stepping source residual. Due to the
819 introduction of the GCL term above, the remainder of the source residual
820 due to the time discretization has a new form.---*/
821
822 if (Conservative) {
823 /*--- Get density at different time levels via virtual methods ---*/
824 Density_nM1 = flowNodes->GetDensity_time_n1(iPoint);
825 Density_n = flowNodes->GetDensity_time_n(iPoint);
826 Density_nP1 = flowNodes->GetDensity(iPoint);
827 }
828
829 for (iVar = 0; iVar < nVar; iVar++) {
830 su2double unsteady_term = 0.0;
831 if (first_order)
832 unsteady_term = (Density_nP1 * U_time_nP1[iVar] - Density_n * U_time_n[iVar]) * (Volume_nP1 / TimeStep);
833 if (second_order)
834 unsteady_term = (Density_nP1 * U_time_nP1[iVar] - Density_n * U_time_n[iVar]) * (3.0 * Volume_nP1 / (2.0 * TimeStep)) +
835 (Density_nM1 * U_time_nM1[iVar] - Density_n * U_time_n[iVar]) * (Volume_nM1 / (2.0 * TimeStep));
836
837 if (bounded_scalar) {
838 if (first_order) unsteady_term -= U_time_nP1[iVar] * (Density_nP1 - Density_n) * (Volume_nP1 / TimeStep);
839 if (second_order) unsteady_term -= U_time_nP1[iVar] * ((Density_nP1 - Density_n) * (3.0 * Volume_nP1 / (2.0 * TimeStep)) +
840 (Density_nM1 - Density_n) * (Volume_nM1 / (2.0 * TimeStep)));
841 }
842
843 LinSysRes(iPoint, iVar) += unsteady_term;
844 }
845
846 /*--- Compute the Jacobian contribution due to the dual time source term. ---*/
847 if (implicit) {
848 su2double diag_factor = 1.0;
849 if (Conservative) {
850 if (bounded_scalar) {
851 if (first_order) diag_factor = Density_n;
852 if (second_order) diag_factor = (4.0 * Density_n - Density_nM1) / 3.0;
853 } else {
854 diag_factor = Density_nP1;
855 }
856 }
857 if (first_order) Jacobian.AddVal2Diag(iPoint, diag_factor * Volume_nP1 / TimeStep);
858 if (second_order) Jacobian.AddVal2Diag(iPoint, diag_factor * 3.0 * Volume_nP1 / (2.0 * TimeStep));
859 }
860 }
862
864
865 } // end dynamic grid
866}
867
868
869template <class VariableType>
871 restart,CSolver*** solver_container,
872 CGeometry** geometry, CConfig* config) {
874 const bool dual_time = config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_1ST ||
876 const bool isRestartIter = restart && TimeIter == config->GetRestart_Iter();
877
878 /*--- The value of the solution for the first iteration of the dual time. ---*/
879
880 if (dual_time && (TimeIter == 0 || isRestartIter)) {
881 /*--- Push back the initial condition to previous solution containers
882 for a 1st-order restart or when simply initializing to freestream. ---*/
883
884 nodes->Set_Solution_time_n();
885 nodes->Set_Solution_time_n1();
886
887 if (isRestartIter && config->GetTime_Marching() == TIME_MARCHING::DT_STEPPING_2ND) {
888 /*--- Load an additional restart file for a 2nd-order restart ---*/
889
890 LoadRestart(geometry, solver_container, config, SU2_TYPE::Int(config->GetRestart_Iter()-1), true);
891
892 /*--- Push back this new solution to time level N. ---*/
893
894 nodes->Set_Solution_time_n();
895 }
896 }
897}
simd::Array< su2double > Double
Define Double and Int SIMD types.
Definition CNumericsSIMD.hpp:36
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
Main class for defining the problem; basically this class reads the configuration file,...
Definition CConfig.hpp:64
unsigned long GetInnerIter(void) const
Get the current FSI iteration number.
Definition CConfig.hpp:3405
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 long GetLimiterIter(void) const
Freeze the value of the limiter after a number of iterations.
Definition CConfig.hpp:2563
bool GetReconstructionGradientRequired(void) const
Get flag for whether a second gradient calculation is required for upwind reconstruction alone.
Definition CConfig.hpp:4372
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
bool GetDynamic_Grid(void) const
Get information about dynamic grids.
Definition CConfig.hpp:6276
bool GetMUSCL(void) const
Get if the upwind scheme used MUSCL or not.
Definition CConfig.hpp:4768
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
unsigned short GetnMarker_Periodic(void) const
Get the total number of periodic markers.
Definition CConfig.hpp:3309
LIMITER GetKind_SlopeLimit(void) const
Get the method for limiting the spatial gradients.
Definition CConfig.hpp:4958
string GetMarker_All_TagBound(unsigned short val_marker) const
Get the index of the surface defined in the geometry file.
Definition CConfig.hpp:3473
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_TimeIntScheme(void) const
Get the kind of time integration method.
Definition CConfig.hpp:4732
unsigned short GetKind_Data_Riemann(const string &val_marker) const
Get Kind Data of Riemann boundary.
Definition CConfig.cpp:9676
unsigned short GetMarker_All_KindBC(unsigned short val_marker) const
Get the kind of boundary for each marker.
Definition CConfig.hpp:3556
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
unsigned long GetRestart_Iter(void) const
Get the restart iteration.
Definition CConfig.hpp:9912
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
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
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 GetnPoint() const
Get number of points.
Definition CGeometry.hpp:587
CPoint * nodes
Node vector (dual grid information).
Definition CGeometry.hpp:253
void SetNaturalEdgeColoring()
Force the natural (sequential) edge coloring.
Definition CGeometry.cpp:4256
CVertex *** vertex
Boundary Vertex vector (dual grid information).
Definition CGeometry.hpp:255
unsigned long GetnEdge() const
Get number of edges.
Definition CGeometry.hpp:617
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
unsigned long * nVertex
Number of vertex for each marker.
Definition CGeometry.hpp:258
Class to represent a matrix (without owning the data, this just wraps a pointer).
Definition container_decorators.hpp:40
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
bool GetBoundedScalar() const
Obtain information on bounded scalar problem.
Definition CNumerics.hpp:1864
void SetGridVel(const su2double *val_gridvel_i, const su2double *val_gridvel_j)
Set the velocity of the computational grid.
Definition CNumerics.hpp:987
void SetScalarVar(const su2double *val_scalarvar_i, const su2double *val_scalarvar_j)
Set the value of the scalar variable.
Definition CNumerics.hpp:370
void SetNormal(const su2double *val_normal)
Set the value of the normal vector to the face between two points.
Definition CNumerics.hpp:1086
virtual void ComputeResidual(su2double *val_residual, CConfig *config)
Compute the numerical residual.
Definition CNumerics.hpp:1543
void SetMassFlux(const su2double val_MassFlux)
SetMassFlux.
Definition CNumerics.hpp:1858
CCompressedSparsePatternL::CInnerIter GetEdges(unsigned long iPoint) const
Get inner iterator to loop over neighbor edges.
Definition CPoint.hpp:296
su2double & GetPeriodicVolume(unsigned long iPoint)
Get the missing component of area or volume for a control volume on a periodic marker.
Definition CPoint.hpp:579
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
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
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
~CScalarSolver() override
Destructor of the class.
Definition CScalarSolver.inl:109
@ OMP_MAX_SIZE
Definition CScalarSolver.hpp:65
void SumEdgeFluxes(const CGeometry *geometry)
Sum the edge fluxes for each cell to populate the residual vector, only used on coarse grids.
Definition CScalarSolver.inl:154
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-Stepping Strategy.
Definition CScalarSolver.inl:631
void BoundaryFluxResidual(const CGeometry *geometry, CSolver **solver_container, const CConfig *config, const ScalarFluxOptions &opt, unsigned short val_marker)
Generic boundary flux pass, run after a boundary's fill pass has written the ghost row,...
Definition CScalarSolver.inl:259
su2activematrix ghostNormal
Outward normals, sign flipped from the vertex normals.
Definition CScalarSolver.hpp:105
array< DummyGridColor<>, 1 > EdgeColoring
Definition CScalarSolver.hpp:89
CScalarSolver(CGeometry *geometry, CConfig *config, const CSolver *flow_solver, bool conservative, bool bounded_scalar, LINEAR_SOLVER_MODE linear_solver_mode=LINEAR_SOLVER_MODE::STANDARD)
Constructor of the class.
Definition CScalarSolver.inl:33
unique_ptr< CGhostFlowVariable > ghostFlowNodes
Sized from the flow solver, see the constructor.
Definition CScalarSolver.hpp:104
void EdgeFluxResidual(const CGeometry *geometry, CSolver **solver_container, const CConfig *config, const ScalarFluxOptions &opt)
Generic interior edge loop for a scalar model expressed through the CUpwScalarBase CRTP chain (numeri...
Definition CScalarSolver.inl:176
void PushSolutionBackInTime(unsigned long TimeIter, bool restart, CSolver ***solver_container, CGeometry **geometry, CConfig *config)
Move solution to previous time levels (for restarts).
Definition CScalarSolver.inl:870
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 CScalarSolver.inl:389
su2double upperlimit[MAXNVAR]
contains upper limits for scalar variables.
Definition CScalarSolver.hpp:71
void BC_Riemann(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) final
Impose the boundary condition using characteristic recostruction.
Definition CScalarSolver.inl:372
void PrepareImplicitIteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) final
Prepare an implicit iteration.
Definition CScalarSolver.inl:481
static constexpr size_t MAXNVAR
Max number of variables, for static arrays.
Definition CScalarSolver.hpp:62
su2double lowerlimit[MAXNVAR]
contains lower limits for scalar variables.
Definition CScalarSolver.hpp:70
void CompleteImplicitIteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) final
Complete an implicit iteration.
Definition CScalarSolver.inl:525
su2vector< uint8_t > ghostSkip
Whether a vertex contributes no flux, set by the fill pass.
Definition CScalarSolver.hpp:107
void CommonPreprocessing(CGeometry *geometry, const CConfig *config, const bool Output)
Gradient and Limiter computation.
Definition CScalarSolver.inl:114
void ExplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) final
Update the solution using the explicit Euler scheme.
Definition CScalarSolver.inl:601
void FluidInterfaceFluxResidual(const CGeometry *geometry, CSolver **solver_container, const CConfig *config, const ScalarFluxOptions &optConv, const ScalarFluxOptions &optVisc, const GhostFunc &fillGhostExtras)
Generic fluid interface (sliding mesh) flux pass, shared by every model. The convective term is a per...
Definition CScalarSolver.inl:300
void ImplicitEuler_Iteration(CGeometry *geometry, CSolver **solver_container, CConfig *config) override
Update the solution using an implicit solver.
Definition CScalarSolver.inl:574
su2activematrix ghostCoord
Reflected coordinates, read by the diffusion sites.
Definition CScalarSolver.hpp:106
static constexpr bool ReducerStrategy
Definition CScalarSolver.hpp:91
unsigned long omp_chunk_size
Chunk size used in light point loops.
Definition CScalarSolver.hpp:68
void BC_Far_Field(CGeometry *geometry, CSolver **solver_container, CNumerics *conv_numerics, CNumerics *visc_numerics, CConfig *config, unsigned short val_marker) override
Impose the Far Field boundary condition.
Definition CScalarSolver.inl:405
void SetTime_Step(CGeometry *geometry, CSolver **solver_container, CConfig *config, unsigned short iMesh, unsigned long Iteration) override
This base implementation simply copies the time step of the flow solver.
Definition CScalarSolver.inl:466
Definition CSolver.hpp:71
unsigned short GetnVar(void) const
Get the number of variables of the problem.
Definition CSolver.hpp:416
vector< unsigned long > nVertex
Store nVertex at each marker for deallocation.
Definition CSolver.hpp:146
unsigned short nDim
Number of dimensions of the problem.
Definition CSolver.hpp:90
unsigned short GetnPrimVarGrad(void) const
Get the number of variables of the problem.
Definition CSolver.hpp:426
unsigned long nPoint
Number of points of the computational grid.
Definition CSolver.hpp:91
unsigned short GetnPrimVar(void) const
Get the number of variables of the problem.
Definition CSolver.hpp:421
bool dynamic_grid
Flag that determines whether the grid is dynamic (moving or deforming + grid velocities).
Definition CSolver.hpp:153
CVariable * GetNodes()
Allow outside access to the nodes of the solver, containing conservatives, primitives,...
Definition CSolver.hpp:229
virtual su2double * GetCharacPrimVar(unsigned short val_marker, unsigned long val_vertex)
A virtual member.
Definition CSolver.hpp:2906
unsigned long nMarker
Total number of markers using the grid information.
Definition CSolver.hpp:145
su2double GetLocalCFL(unsigned long iPoint) const
Get the value of the local CFL number for the current control volume (CV).
Definition CVariable.hpp:647
virtual const MatrixType & GetPrimitive() const
Get the primitive variables for all points.
Definition CVariable.hpp:1319
virtual su2double GetDensity(unsigned long iPoint) const
A virtual member.
Definition CVariable.hpp:1009
void GetNormal(su2double *val_normal) const override
Copy the the normal vector of a face.
Definition CVertex.hpp:94
unsigned long GetNode() const
Get the node of the vertex.
Definition CVertex.hpp:70
unsigned long GetNormal_Neighbor() const
Get the value of the closest neighbor.
Definition CVertex.hpp:322
uint32_t su2uint
Definition code_config.hpp:121
passivedouble su2double
Definition code_config.hpp:181
FORCEINLINE ARRAY_T sign(const ARRAY_T &x)
Definition special_vectorization.hpp:118
void ResumePreaccumulation(bool wasActive)
Resume the use of preaccumulation.
Definition ad_structure.hpp:399
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
int Int(const su2double &data)
Casts the primitive value to int (uses GetValue, already implemented for each type).
Definition datatype_structure.hpp:148
void muscl(typename CLaneTraits< Double >::Int iPoint, typename CLaneTraits< Double >::Int jPoint, const Vector< Double, nDim > &vector_ij, const Gradient_t &gradient, const Limiter_t &limiter, size_t iRow, CPair< VarType > &V, const CNonDeduced< Double > &kappa, const CNonDeduced< Double > &umusclRamp, size_t nVarGradRuntime)
U-MUSCL reconstruction of nVarGrad variables, from the gradient rows starting at iRow.
Definition util.hpp:508
Double gatherVariables(Int iPoint, const Container &vars, size_t iVar=0)
Gather a single variable, from column iVar (0 by default) of row iPoint of a 2D container,...
Definition util.hpp:277
#define BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS
Definition omp_structure.hpp:187
#define END_SU2_OMP_FOR
Definition omp_structure.hpp:158
constexpr int omp_get_max_threads()
Maximum number of threads available.
Definition omp_structure.hpp:70
#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 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_FOR_DYN(CHUNK)
Definition omp_structure.hpp:150
#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
@ EULER_IMPLICIT
Implicit Euler time integration definition.
Definition option_structure.hpp:1711
ENUM_REGIME
different regime modes
Definition option_structure.hpp:517
@ INCOMPRESSIBLE
Definition of incompressible solver.
@ STATIC_SUPERSONIC_INFLOW_PD
User specifies static pressure, static temperature, and Mach components.
Definition option_structure.hpp:1967
@ TOTAL_CONDITIONS_PT
User specifies total pressure, total temperature, and flow direction.
Definition option_structure.hpp:1962
@ DENSITY_VELOCITY
User specifies density and velocity, and flow direction.
Definition option_structure.hpp:1963
@ STATIC_PRESSURE
User specifies static pressure.
Definition option_structure.hpp:1964
@ STATIC_SUPERSONIC_INFLOW_PT
User specifies static pressure, static temperature, and Mach components.
Definition option_structure.hpp:1966
@ NONE
No limiter.
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).
@ FLOW_SOL
Position of the mean flow solution in the solver container array.
Definition option_structure.hpp:577
@ INTERNAL_BOUNDARY
Internal Boundary definition.
Definition option_structure.hpp:1840
@ FLUID_INTERFACE
Domain interface definition.
Definition option_structure.hpp:1841
@ NEARFIELD_BOUNDARY
Near-Field boundary definition.
Definition option_structure.hpp:1821
@ PERIODIC_BOUNDARY
Periodic boundary definition.
Definition option_structure.hpp:1820
@ PERIODIC_IMPLICIT
Implicit update communication to ensure consistency across periodic boundaries.
Definition option_structure.hpp:2867
@ PERIODIC_RESIDUAL
Residual and Jacobian communication (periodic only).
Definition option_structure.hpp:2847
@ SOLUTION
Conservative solution communication.
@ WEIGHTED_LEAST_SQUARES
Gradients computation using inverse-distance weighted least squares.
Definition option_structure.hpp:1782
@ LEAST_SQUARES
Gradient computation using unweighted least squares.
Definition option_structure.hpp:1781
@ GREEN_GAUSS
Gradient computation using Green-Gauss theorem.
Definition option_structure.hpp:1780
LINEAR_SOLVER_MODE
Type of operation for the linear system solver, changes the source of solver options.
Definition option_structure.hpp:3027
A way to represent natural coloring {0,1,2,...,size-1} with zero overhead (behaves like looping with ...
Definition graph_toolbox.hpp:684
Locates the data of one endpoint of an edge.
Definition scalar_edge_flux.hpp:42
Loop invariant flags for a scalar edge flux, built once outside the edge loop so the compiler can uns...
Definition scalar_edge_flux.hpp:55
bool implicit
Whether the Jacobians are assembled, and so computed.
Definition scalar_edge_flux.hpp:60
bool boundedScalar
Definition scalar_edge_flux.hpp:57
#define SU2_ZONE_SCOPED
Definition tracy_structure.hpp:39