Skip to content

Commit a5087a5

Browse files
committed
Merge remote-tracking branch 'origin/develop' into pedro/deflation
2 parents f3dd117 + 3dba507 commit a5087a5

13 files changed

Lines changed: 138 additions & 32 deletions

File tree

AUTHORS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ Eduardo Molina
7171
Edwin van der Weide
7272
Eitan Aberman
7373
Ethan Alan Hereth
74+
Ezgi Orbay Akcengiz
7475
Florian Dittmann
7576
Filip Hahs
7677
Francesco Poli

Common/include/CConfig.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ class CConfig {
515515
Kind_SlopeLimit_AdjFlow, /*!< \brief Slope limiter for the adjoint equation.*/
516516
Kind_SlopeLimit_Heat, /*!< \brief Slope limiter for the adjoint equation.*/
517517
Kind_SlopeLimit_Species; /*!< \brief Slope limiter for the species equation.*/
518+
LINEAR_SOLVER_INNER Kind_Linear_Solver_Inner; /*!< \brief Inner solver used in nested Krylov schemes. */
518519
unsigned short Kind_FluidModel, /*!< \brief Kind of the Fluid Model: Ideal, van der Waals, etc. */
519520
Kind_InitOption, /*!< \brief Kind of Init option to choose if initializing with Reynolds number or with thermodynamic conditions */
520521
Kind_GridMovement, /*!< \brief Kind of the static mesh movement. */
@@ -4289,6 +4290,10 @@ class CConfig {
42894290
*/
42904291
unsigned short GetKind_Linear_Solver(void) const { return Kind_Linear_Solver; }
42914292

4293+
/*!
4294+
* \brief Get the inner linear solver used in nested Krylov linear solvers.
4295+
*/
4296+
LINEAR_SOLVER_INNER GetKind_Linear_Solver_Inner(void) const { return Kind_Linear_Solver_Inner; }
42924297

42934298
/*!
42944299
* \brief Get the kind of preconditioner for the implicit solver.

Common/include/linear_algebra/CPreconditioner.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#pragma once
3030

31+
#include <functional>
3132
#include "../CConfig.hpp"
3233
#include "../geometry/CGeometry.hpp"
3334
#include "CSysVector.hpp"
@@ -305,6 +306,25 @@ class CPastixPreconditioner final : public CPreconditioner<ScalarType> {
305306
inline void Build() override { sparse_matrix.BuildPastixPreconditioner(geometry, config, kind_fact); }
306307
};
307308

309+
/*!
310+
* \class CAbstractPreconditioner
311+
* \brief Applies a std::function as the preconditioning operation.
312+
* \note This can be used to treat almost anything as a preconditioner.
313+
*/
314+
template <class ScalarType>
315+
class CAbstractPreconditioner final : public CPreconditioner<ScalarType> {
316+
private:
317+
std::function<void(const CSysVector<ScalarType>&, CSysVector<ScalarType>&)> impl;
318+
319+
public:
320+
CAbstractPreconditioner() = delete;
321+
322+
template <class F>
323+
explicit CAbstractPreconditioner(const F& function) : impl(function) {}
324+
325+
inline void operator()(const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) const override { impl(u, v); }
326+
};
327+
308328
template <class ScalarType>
309329
CPreconditioner<ScalarType>* CPreconditioner<ScalarType>::Create(ENUM_LINEAR_SOLVER_PREC kind,
310330
CSysMatrix<ScalarType>& jacobian, CGeometry* geometry,

Common/include/linear_algebra/CSysSolve.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "../containers/C2DContainer.hpp"
3232

3333
#include <cmath>
34+
#include <memory>
3435
#include <vector>
3536
#include <iostream>
3637
#include <cstdlib>
@@ -116,6 +117,9 @@ class CSysSolve {
116117
bool recomputeRes = false; /*!< \brief Recompute the residual after inner iterations, if monitoring. */
117118
unsigned long monitorFreq = 10; /*!< \brief Monitoring frequency. */
118119

120+
/*!< \brief Inner solver for nested preconditioning. */
121+
std::unique_ptr<CSysSolve<ScalarType>> inner_solver;
122+
119123
/*!
120124
* \brief sign transfer function
121125
* \param[in] x - value having sign prescribed

Common/include/option_structure.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,6 +2371,19 @@ static const MapType<std::string, ENUM_LINEAR_SOLVER> Linear_Solver_Map = {
23712371
MakePair("PASTIX_LU", PASTIX_LU)
23722372
};
23732373

2374+
/*!
2375+
* \brief Inner solver for nested linear solver, only compatible with "flexible" linear solvers.
2376+
*/
2377+
enum class LINEAR_SOLVER_INNER {
2378+
NONE, /*!< \brief Do not use a nested linear solver. */
2379+
BCGSTAB, /*!< \brief Use BCGSTAB as the preconditioning linear solver. */
2380+
};
2381+
static const MapType<std::string, LINEAR_SOLVER_INNER> Inner_Linear_Solver_Map = {
2382+
MakePair("NONE", LINEAR_SOLVER_INNER::NONE)
2383+
MakePair("BCGSTAB", LINEAR_SOLVER_INNER::BCGSTAB)
2384+
};
2385+
2386+
23742387
/*!
23752388
* \brief Types surface continuity at the intersection with the FFD
23762389
*/

Common/src/CConfig.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1889,6 +1889,8 @@ void CConfig::SetConfig_Options() {
18891889
addDoubleOption("LINEAR_SOLVER_SMOOTHER_RELAXATION", Linear_Solver_Smoother_Relaxation, 1.0);
18901890
/* DESCRIPTION: Custom number of threads used for additive domain decomposition for ILU and LU_SGS (0 is "auto"). */
18911891
addUnsignedLongOption("LINEAR_SOLVER_PREC_THREADS", Linear_Solver_Prec_Threads, 0);
1892+
/* DESCRIPTION: Use an inner linear solver. */
1893+
addEnumOption("LINEAR_SOLVER_INNER", Kind_Linear_Solver_Inner, Inner_Linear_Solver_Map, LINEAR_SOLVER_INNER::NONE);
18921894
/* DESCRIPTION: Relaxation factor for updates of adjoint variables. */
18931895
addDoubleOption("RELAXATION_FACTOR_ADJOINT", Relaxation_Factor_Adjoint, 1.0);
18941896
/* DESCRIPTION: Relaxation of the CHT coupling */
@@ -1909,7 +1911,6 @@ void CConfig::SetConfig_Options() {
19091911
addEnumOption("DISCADJ_LIN_SOLVER", Kind_DiscAdj_Linear_Solver, Linear_Solver_Map, FGMRES);
19101912
/* DESCRIPTION: Preconditioner for the discrete adjoint Krylov linear solvers */
19111913
addEnumOption("DISCADJ_LIN_PREC", Kind_DiscAdj_Linear_Prec, Linear_Solver_Prec_Map, ILU);
1912-
/* DESCRIPTION: Linear solver for the discete adjoint systems */
19131914

19141915
/* DESCRIPTION: Maximum update ratio value for flow density and energy variables */
19151916
addDoubleOption("MAX_UPDATE_FLOW", MaxUpdateFlow, 0.2);
@@ -7262,13 +7263,16 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) {
72627263
case BCGSTAB:
72637264
case FGMRES:
72647265
case RESTARTED_FGMRES:
7265-
case FGCRODR:
7266-
if (Kind_Linear_Solver == BCGSTAB)
7266+
if (Kind_Linear_Solver == BCGSTAB) {
72677267
cout << "BCGSTAB is used for solving the linear system." << endl;
7268-
else if (Kind_Linear_Solver == FGCRODR)
7269-
cout << "FGCRODR is used for solving the linear system." << endl;
7270-
else
7271-
cout << "FGMRES is used for solving the linear system." << endl;
7268+
} else {
7269+
const std::string name = Kind_Linear_Solver == FGCRODR ? "FGCRODR" : "FGMRES";
7270+
if (Kind_Linear_Solver_Inner == LINEAR_SOLVER_INNER::BCGSTAB){
7271+
cout << "Nested " << name << " (with inner BiCGSTAB) is used for solving the linear system." << endl;
7272+
} else {
7273+
cout << name << " is used for solving the linear system." << endl;
7274+
}
7275+
}
72727276
switch (Kind_Linear_Solver_Prec) {
72737277
case ILU: cout << "Using a ILU("<< Linear_Solver_ILU_n <<") preconditioning."<< endl; break;
72747278
case LINELET: cout << "Using a linelet preconditioning."<< endl; break;
@@ -7315,6 +7319,8 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) {
73157319
cout << "FGMRES is used for solving the linear system." << endl;
73167320
cout << "Convergence criteria of the linear solver: "<< Linear_Solver_Error <<"."<< endl;
73177321
cout << "Max number of iterations: "<< Linear_Solver_Iter <<"."<< endl;
7322+
if (Kind_Linear_Solver_Inner == LINEAR_SOLVER_INNER::BCGSTAB)
7323+
cout << "Nested BiCGSTAB is used as the inner solver." << endl;
73187324
break;
73197325
case FGCRODR:
73207326
cout << "FGCRODR is used for solving the linear system." << endl;

Common/src/linear_algebra/CSysSolve.cpp

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <iostream>
4343
#include <limits>
4444
#include <type_traits>
45+
#include <memory>
4546

4647
/*!
4748
* \brief Epsilon used in CSysSolve depending on datatype to
@@ -1307,9 +1308,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13071308
break;
13081309
}
13091310

1310-
/*--- Normal mode
1311-
* assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
1312-
* ---*/
1311+
/*--- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
1312+
* but does not enforce it to avoid compiler warning. ---*/
13131313
default: {
13141314
KindSolver = config->GetKind_Linear_Solver();
13151315
KindPrecond = config->GetKind_Linear_Solver_Prec();
@@ -1320,6 +1320,17 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13201320
}
13211321
}
13221322

1323+
const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1324+
config->GetKind_Linear_Solver_Inner() != LINEAR_SOLVER_INNER::NONE;
1325+
1326+
if (nested && !inner_solver) {
1327+
BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1328+
inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1329+
inner_solver->SetxIsZero(true);
1330+
}
1331+
END_SU2_OMP_SAFE_GLOBAL_ACCESS
1332+
}
1333+
13231334
/*--- Stop the recording for the linear solver ---*/
13241335
bool TapeActive = NO;
13251336

@@ -1353,13 +1364,25 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13531364

13541365
auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
13551366

1356-
const auto kindPrec = static_cast<ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1357-
1358-
auto precond = CPreconditioner<ScalarType>::Create(kindPrec, Jacobian, geometry, config);
1359-
13601367
/*--- Build preconditioner. ---*/
13611368

1362-
precond->Build();
1369+
const auto kindPrec = static_cast<ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1370+
auto* normal_prec = CPreconditioner<ScalarType>::Create(kindPrec, Jacobian, geometry, config);
1371+
normal_prec->Build();
1372+
1373+
CPreconditioner<ScalarType>* nested_prec = nullptr;
1374+
if (nested) {
1375+
nested_prec = new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u,
1376+
CSysVector<ScalarType>& v) {
1377+
/*--- Initialize to 0 to be safe. ---*/
1378+
v = ScalarType{};
1379+
ScalarType unused{};
1380+
/*--- Handle other types here if desired but do not call Solve because
1381+
* that will create issues with the AD external function. ---*/
1382+
(void)inner_solver->BCGSTAB_LinSolver(u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false, config);
1383+
});
1384+
}
1385+
const auto* precond = nested ? nested_prec : normal_prec;
13631386

13641387
/*--- Solve system. ---*/
13651388

@@ -1409,7 +1432,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
14091432

14101433
HandleTemporariesOut(LinSysSol);
14111434

1412-
delete precond;
1435+
delete normal_prec;
1436+
delete nested_prec;
14131437

14141438
if (TapeActive) {
14151439
/*--- To keep the behavior of SU2_DOT, but not strictly required since jacobian is symmetric(?). ---*/
@@ -1494,9 +1518,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
14941518
break;
14951519
}
14961520

1497-
/*--- Normal mode
1498-
* assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
1499-
* ---*/
1521+
/*--- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
1522+
* but does not enforce it to avoid compiler warning. ---*/
15001523
default: {
15011524
KindSolver = config->GetKind_Linear_Solver();
15021525
KindPrecond = config->GetKind_Linear_Solver_Prec();
@@ -1507,19 +1530,43 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15071530
}
15081531
}
15091532

1533+
const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1534+
config->GetKind_Linear_Solver_Inner() != LINEAR_SOLVER_INNER::NONE;
1535+
1536+
if (nested && !inner_solver) {
1537+
BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1538+
inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1539+
inner_solver->SetxIsZero(true);
1540+
}
1541+
END_SU2_OMP_SAFE_GLOBAL_ACCESS
1542+
}
1543+
15101544
/*--- Set up preconditioner and matrix-vector product ---*/
15111545

1512-
const auto kindPrec = static_cast<ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1546+
auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
15131547

1514-
auto precond = CPreconditioner<ScalarType>::Create(kindPrec, Jacobian, geometry, config);
1548+
const auto kindPrec = static_cast<ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1549+
auto* normal_prec = CPreconditioner<ScalarType>::Create(kindPrec, Jacobian, geometry, config);
15151550

15161551
/*--- If there was no call to solve first the preconditioner needs to be built here. ---*/
15171552
if (directCall) {
15181553
Jacobian.TransposeInPlace();
1519-
precond->Build();
1554+
normal_prec->Build();
15201555
}
15211556

1522-
auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
1557+
CPreconditioner<ScalarType>* nested_prec = nullptr;
1558+
if (nested) {
1559+
nested_prec =
1560+
new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
1561+
/*--- Initialize to 0 to be safe. ---*/
1562+
v = ScalarType{};
1563+
ScalarType unused{};
1564+
/*--- Handle other types here if desired but do not call Solve because
1565+
* that will create issues with the AD external function. ---*/
1566+
(void)inner_solver->BCGSTAB_LinSolver(u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false, config);
1567+
});
1568+
}
1569+
const auto* precond = nested ? nested_prec : normal_prec;
15231570

15241571
/*--- Solve the system ---*/
15251572

@@ -1567,7 +1614,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15671614

15681615
HandleTemporariesOut(LinSysSol);
15691616

1570-
delete precond;
1617+
delete normal_prec;
1618+
delete nested_prec;
15711619

15721620
SU2_OMP_MASTER {
15731621
Residual = residual;

SU2_CFD/include/integration/CNewtonIntegration.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,11 @@ class CNewtonIntegration final : public CIntegration {
158158
auto product = CSysMatrixVectorProduct<MixedScalar>(solvers[FLOW_SOL]->Jacobian, geometry, config);
159159
v = MixedScalar(0.0);
160160
MixedScalar eps_t = eps;
161-
iters = solvers[FLOW_SOL]->System.FGMRES_LinSolver(u, v, product, *preconditioner, eps, iters, eps_t, false, config);
161+
if (config->GetKind_Linear_Solver_Inner() == LINEAR_SOLVER_INNER::NONE) {
162+
iters = solvers[FLOW_SOL]->System.FGMRES_LinSolver(u, v, product, *preconditioner, eps, iters, eps_t, false, config);
163+
} else {
164+
iters = solvers[FLOW_SOL]->System.BCGSTAB_LinSolver(u, v, product, *preconditioner, eps, iters, eps_t, false, config);
165+
}
162166
eps = eps_t;
163167
return iters;
164168
}

TestCases/hybrid_regression.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ def main():
404404
inc_turb_naca0012.cfg_dir = "incomp_rans/naca0012"
405405
inc_turb_naca0012.cfg_file = "naca0012.cfg"
406406
inc_turb_naca0012.test_iter = 20
407-
inc_turb_naca0012.test_vals = [-4.788405, -11.040877, 0.000008, 0.309505]
407+
inc_turb_naca0012.test_vals = [-4.758062, -10.974496, -0.000005, -0.028654, 4, -5.397415, 2, -6.426845]
408408
test_list.append(inc_turb_naca0012)
409409

410410
# NACA0012, SST_SUST

TestCases/incomp_rans/naca0012/naca0012.cfg

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ MARKER_MONITORING= ( airfoil )
5050
%
5151
NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES
5252
CFL_NUMBER= 10.0
53-
CFL_ADAPT= NO
54-
CFL_ADAPT_PARAM= ( 1.5, 0.5, 1.0, 100.0 )
53+
CFL_ADAPT= YES
54+
CFL_ADAPT_PARAM= ( 0.8, 1.1, 1.0, 100.0 )
5555
ITER= 2500
5656

5757
% ----------------------- SLOPE LIMITER DEFINITION ----------------------------%
@@ -64,6 +64,7 @@ SENS_REMOVE_SHARP= NO
6464
% ------------------------ LINEAR SOLVER DEFINITION ---------------------------%
6565
%
6666
LINEAR_SOLVER= FGMRES
67+
LINEAR_SOLVER_INNER= BCGSTAB
6768
LINEAR_SOLVER_PREC= LU_SGS
6869
LINEAR_SOLVER_ERROR= 1E-4
6970
LINEAR_SOLVER_ITER= 5
@@ -107,4 +108,4 @@ GRAD_OBJFUNC_FILENAME= of_grad
107108
SURFACE_FILENAME= surface_flow
108109
SURFACE_ADJ_FILENAME= surface_adjoint
109110
OUTPUT_WRT_FREQ= 100
110-
SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_NU_TILDE, LIFT, DRAG, TOTAL_HEATFLUX)
111+
SCREEN_OUTPUT= (INNER_ITER, RMS_PRESSURE, RMS_NU_TILDE, LIFT, DRAG, LINSOL)

0 commit comments

Comments
 (0)