From 3463cd2108c852bc10f797e970058ec7da73ea05 Mon Sep 17 00:00:00 2001 From: Jan Rottmayer Date: Wed, 25 Jun 2025 13:38:04 +0200 Subject: [PATCH 1/4] Added HICKS_HENNE_CAMBER as design parameter option for 2D Airfoil; Thickness distribution is kept accoring to provided reference geometry. --- Common/include/geometry/CPhysicalGeometry.hpp | 6 +- .../grid_movement/CSurfaceMovement.hpp | 7 + Common/include/option_structure.hpp | 2 + Common/include/option_structure.inl | 4 + Common/src/CConfig.cpp | 5 +- Common/src/grid_movement/CSurfaceMovement.cpp | 141 +++++++++++++++++- .../src/drivers/CDiscAdjDeformationDriver.cpp | 4 + SU2_GEO/src/SU2_GEO.cpp | 11 ++ 8 files changed, 174 insertions(+), 6 deletions(-) diff --git a/Common/include/geometry/CPhysicalGeometry.hpp b/Common/include/geometry/CPhysicalGeometry.hpp index 1148471f1c3..ff4761a6712 100644 --- a/Common/include/geometry/CPhysicalGeometry.hpp +++ b/Common/include/geometry/CPhysicalGeometry.hpp @@ -620,7 +620,7 @@ class CPhysicalGeometry final : public CGeometry { /*! * \brief Compute the maximum thickness of an airfoil. - * \return Maximum thickness at a particular seccion. + * \return Maximum thickness at a particular section. */ su2double Compute_MaxThickness(su2double* Plane_P0, su2double* Plane_Normal, CConfig* config, vector& Xcoord_Airfoil, vector& Ycoord_Airfoil, @@ -628,7 +628,7 @@ class CPhysicalGeometry final : public CGeometry { /*! * \brief Compute the twist of an airfoil. - * \return Twist at a particular seccion. + * \return Twist at a particular section. */ su2double Compute_Twist(su2double* Plane_P0, su2double* Plane_Normal, vector& Xcoord_Airfoil, vector& Ycoord_Airfoil, vector& Zcoord_Airfoil) override; @@ -708,7 +708,7 @@ class CPhysicalGeometry final : public CGeometry { /*! * \brief Compute the dihedral of a wing. - * \return Dihedral at a particular seccion. + * \return Dihedral at a particular section. */ su2double Compute_Dihedral(su2double* LeadingEdge_im1, su2double* TrailingEdge_im1, su2double* LeadingEdge_i, su2double* TrailingEdge_i) override; diff --git a/Common/include/grid_movement/CSurfaceMovement.hpp b/Common/include/grid_movement/CSurfaceMovement.hpp index b39f9698f1d..6ce78b9b6d1 100644 --- a/Common/include/grid_movement/CSurfaceMovement.hpp +++ b/Common/include/grid_movement/CSurfaceMovement.hpp @@ -95,6 +95,13 @@ class CSurfaceMovement : public CGridMovement { */ void SetCST(CGeometry* boundary, CConfig* config, unsigned short iDV, bool ResetDef); + /*! + * \brief Set a Hicks-Henne deformation bump function on the camberline of an airfoil. + * \param[in] boundary - Geometry of the boundary. + * \param[in] config - Definition of the particular problem. + */ + void SetHicksHenneCamber(CGeometry* boundary, CConfig* config); + /*! * \brief Set a NACA 4 digits airfoil family for airfoil deformation. * \param[in] boundary - Geometry of the boundary. diff --git a/Common/include/option_structure.hpp b/Common/include/option_structure.hpp index 6f118ce2919..0974d7aa2c3 100644 --- a/Common/include/option_structure.hpp +++ b/Common/include/option_structure.hpp @@ -2287,6 +2287,7 @@ enum ENUM_PARAM { CST = 34, /*!< \brief CST method with Kulfan parameters for airfoil deformation. */ SURFACE_BUMP = 35, /*!< \brief Surfacebump function for flat surfaces deformation. */ SURFACE_FILE = 36, /*!< \brief Nodal coordinates for surface set using a file (external parameterization). */ + HICKS_HENNE_CAMBER = 37, /*!< \brief Hicks-Henne bump function for camber line deformation. */ DV_EFIELD = 40, /*!< \brief Electric field in deformable membranes. */ DV_YOUNG = 41, DV_POISSON = 42, @@ -2304,6 +2305,7 @@ static const MapType Param_Map = { MakePair("FFD_CAMBER_2D", FFD_CAMBER_2D) MakePair("FFD_THICKNESS_2D", FFD_THICKNESS_2D) MakePair("HICKS_HENNE", HICKS_HENNE) + MakePair("HICKS_HENNE_CAMBER", HICKS_HENNE_CAMBER) MakePair("SURFACE_BUMP", SURFACE_BUMP) MakePair("ANGLE_OF_ATTACK", ANGLE_OF_ATTACK) MakePair("NACA_4DIGITS", NACA_4DIGITS) diff --git a/Common/include/option_structure.inl b/Common/include/option_structure.inl index 29c4f6710f5..33d6e5c52e0 100644 --- a/Common/include/option_structure.inl +++ b/Common/include/option_structure.inl @@ -26,6 +26,7 @@ * License along with SU2. If not, see . */ +#include "option_structure.hpp" #include "parallelization/mpi_structure.hpp" using namespace std; @@ -570,6 +571,9 @@ class COptionDVParam : public COptionBase { case HICKS_HENNE: nParamDV[iDV] = 2; break; + case HICKS_HENNE_CAMBER: + nParamDV[iDV] = 1; + break; case SURFACE_BUMP: nParamDV[iDV] = 3; break; diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index f70eae2bcbf..31cb18b247b 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -2358,6 +2358,7 @@ void CConfig::SetConfig_Options() { - FFD_CAMBER_2D ( FFDBox ID, i_Ind ) - FFD_THICKNESS_2D ( FFDBox ID, i_Ind ) - HICKS_HENNE ( Lower Surface (0)/Upper Surface (1)/Only one Surface (2), x_Loc ) + - HICKS_HENNE_CAMBER ( x_Loc ) - SURFACE_BUMP ( x_start, x_end, x_Loc ) - CST ( Lower Surface (0)/Upper Surface (1), Kulfan parameter number, Total number of Kulfan parameters for surface ) - NACA_4DIGITS ( 1st digit, 2nd digit, 3rd and 4th digit ) @@ -6654,6 +6655,7 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { case FFD_CAMBER_2D: cout << "FFD 2D (camber) <-> "; break; case FFD_THICKNESS_2D: cout << "FFD 2D (thickness) <-> "; break; case HICKS_HENNE: cout << "Hicks Henne <-> " ; break; + case HICKS_HENNE_CAMBER: cout << "Hicks Henne (camber) <-> " ; break; case SURFACE_BUMP: cout << "Surface bump <-> " ; break; case ANGLE_OF_ATTACK: cout << "Angle of attack <-> " ; break; case CST: cout << "Kulfan parameter number (CST) <-> " ; break; @@ -6689,7 +6691,8 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { if ((Design_Variable[iDV] == NO_DEFORMATION) || (Design_Variable[iDV] == FFD_SETTING) || (Design_Variable[iDV] == SCALE) ) nParamDV = 0; - if (Design_Variable[iDV] == ANGLE_OF_ATTACK) nParamDV = 1; + if ((Design_Variable[iDV] == ANGLE_OF_ATTACK) || + (Design_Variable[iDV] == HICKS_HENNE_CAMBER)) nParamDV = 1; if ((Design_Variable[iDV] == FFD_CAMBER_2D) || (Design_Variable[iDV] == FFD_THICKNESS_2D) || (Design_Variable[iDV] == HICKS_HENNE) || diff --git a/Common/src/grid_movement/CSurfaceMovement.cpp b/Common/src/grid_movement/CSurfaceMovement.cpp index 05dce01fce9..8be6815bf21 100644 --- a/Common/src/grid_movement/CSurfaceMovement.cpp +++ b/Common/src/grid_movement/CSurfaceMovement.cpp @@ -26,6 +26,7 @@ */ #include "../../include/grid_movement/CSurfaceMovement.hpp" +#include #include "../../include/toolboxes/C1DInterpolation.hpp" #include "../../include/toolboxes/geometry_toolbox.hpp" @@ -584,7 +585,7 @@ vector > CSurfaceMovement::SetSurface_Deformation(CGeometry* g else if ((config->GetDesign_Variable(0) == ROTATION) || (config->GetDesign_Variable(0) == TRANSLATION) || (config->GetDesign_Variable(0) == SCALE) || (config->GetDesign_Variable(0) == HICKS_HENNE) || (config->GetDesign_Variable(0) == SURFACE_BUMP) || (config->GetDesign_Variable(0) == ANGLE_OF_ATTACK) || - (config->GetDesign_Variable(0) == CST)) { + (config->GetDesign_Variable(0) == CST) || (config->GetDesign_Variable(0) == HICKS_HENNE_CAMBER)) { /*--- Apply rotation, displacement and stretching design variables (this should be done before the bump function design variables) ---*/ @@ -639,9 +640,15 @@ vector > CSurfaceMovement::SetSurface_Deformation(CGeometry* g break; } } - + + /*--- HICKS_HENNE_CAMBER design variable ---*/ + + if (config->GetDesign_Variable(0) == HICKS_HENNE_CAMBER) { + SetHicksHenneCamber(geometry, config); + } } + /*--- NACA_4Digits design variable ---*/ else if (config->GetDesign_Variable(0) == NACA_4DIGITS) { @@ -666,6 +673,8 @@ vector > CSurfaceMovement::SetSurface_Deformation(CGeometry* g if (rank == MASTER_NODE) cout << "No surface deformation (setting FFD)." << endl; } + + /*--- Scale, Translate, and Rotate will be done with rigid mesh transforms. ---*/ else if ((config->GetDesign_Variable(0) == ROTATION) || (config->GetDesign_Variable(0) == TRANSLATION) || @@ -2761,6 +2770,8 @@ void CSurfaceMovement::SetHicksHenne(CGeometry* boundary, CConfig* config, unsig } } + + #ifdef HAVE_MPI int iProcessor, nProcessor = size; @@ -3696,6 +3707,132 @@ void CSurfaceMovement::SetExternal_Deformation(CGeometry* geometry, CConfig* con } } +void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) { + unsigned long iVertex; + unsigned short iMarker, nDV_Camber = 0; + su2double VarCoord[3] = {0.0, 0.0, 0.0}, VarCoordTrans[3] = {0.0, 0.0, 0.0}, *CoordTrans, *NormalTrans, ek, fk, + Coord[3] = {0.0, 0.0, 0.0}, TPCoord[2] = {0.0, 0.0}, LPCoord[2] = {0.0, 0.0}, + USTPCoord[2] = {0.0, 0.0}, LSTPCoord[2] = {0.0, 0.0}, Distance, Chord, AoA, ValCos, ValSin; + vector positions, values, X_Coord_upper, Y_Coord_upper, X_Coord_lower, Y_Coord_lower; + + // --- Check if the type of design variables is only HICKS_HENNE_CAMBER ---// // TODO: Extend to CAMBER + THICKNESS + for (unsigned short iDV = 0; iDV < config->GetnDV(); iDV++) + if (config->GetDesign_Variable(iDV) != HICKS_HENNE_CAMBER) { + cout << "'HicksHenneCamber' can not be combined with other design variables."; + cin.get(); + } else { + nDV_Camber++; + } + + positions.resize(nDV_Camber); + values.resize(nDV_Camber); + + /*--- Collect the values of the Hicks-Henne camber design variables ---*/ + for (unsigned short iDV = 0, counter = 0; iDV < config->GetnDV(); iDV++){ + if (config->GetDesign_Variable(iDV) == HICKS_HENNE_CAMBER) { + positions[counter] = config->GetParamDV(iDV, 0); /*--- Position of the camber point as a fraction of the chord ---*/ + values[counter] = config->GetDV_Value(iDV); /*--- Value of the deformation ---*/ + counter++; + } + } + + + + /*--- Compute the angle of attack, Leading-edge (LP) and Trailing-edge (TP) point. + We do this for upper and lower surface separately to detect blunt trailing edges ---*/ + + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if (config->GetMarker_All_DV(iMarker) == YES) { + CoordTrans = boundary->vertex[iMarker][0]->GetCoord(); + LSTPCoord[0] = CoordTrans[0]; + LSTPCoord[1] = CoordTrans[1]; + USTPCoord[0] = CoordTrans[0]; + USTPCoord[1] = CoordTrans[1]; + for (iVertex = 1; iVertex < boundary->nVertex[iMarker]; iVertex++) { + CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); + NormalTrans = boundary->vertex[iMarker][0]->GetNormal(); + if ((CoordTrans[0] > TPCoord[0]) && (abs(NormalTrans[1]) > abs(NormalTrans[0]))) { + if (NormalTrans[1] >= 0.0) { + USTPCoord[0] = CoordTrans[0]; + USTPCoord[1] = CoordTrans[1]; + } else { + LSTPCoord[0] = CoordTrans[0]; + LSTPCoord[1] = CoordTrans[1]; + } + } + } + } + } + + /*--- Correct the TP coordinates if the trailing edge is blunt ---*/ + if ((USTPCoord[0] != LSTPCoord[0]) || (USTPCoord[1] != LSTPCoord[1])) { + TPCoord[0] = (USTPCoord[0] + LSTPCoord[0]) / 2.0; + TPCoord[1] = (USTPCoord[1] + LSTPCoord[1]) / 2.0; + } else { + TPCoord[0] = USTPCoord[0]; + TPCoord[1] = USTPCoord[1]; + } + + Chord = 0.0; + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + if (config->GetMarker_All_DV(iMarker) == YES) { + for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) { + CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); + Distance = sqrt(pow(CoordTrans[0] - TPCoord[0], 2.0) + pow(CoordTrans[1] - TPCoord[1], 2.0)); + if (Chord < Distance) { + Chord = Distance; + LPCoord[0] = CoordTrans[0]; + LPCoord[1] = CoordTrans[1]; + } + } + } + } + + AoA = atan((LPCoord[1] - TPCoord[1]) / (TPCoord[0] - LPCoord[0])) * 180 / PI_NUMBER; + + /*--- Apply deformation based on the camberline Hicks-Henne deformation and the existing airfoil thickness distribution ---*/ + for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { + for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) { + if (config->GetMarker_All_DV(iMarker) == YES) { + CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); + NormalTrans = boundary->vertex[iMarker][iVertex]->GetNormal(); + + ValCos = cos(AoA * PI_NUMBER / 180.0); + ValSin = sin(AoA * PI_NUMBER / 180.0); + + /*--- Transform the coordinates ---*/ + Coord[0] = (CoordTrans[0] - LPCoord[0]) * ValCos - (CoordTrans[1] - LPCoord[1]) * ValSin; + Coord[0] = max(0.0, Coord[0]); // Coord x should be always positive + Coord[1] = (CoordTrans[1] - LPCoord[1]) * ValCos + (CoordTrans[0] - LPCoord[0]) * ValSin; + + /*--- Special case: surface point is part of trailing edge ---*/ + if (Coord[0] > 0.99) { + continue; + } + + /*--- Compute the Hicks-Henne bumps ---*/ + fk = 0.0; + for (unsigned short iDV = 0; iDV < nDV_Camber; iDV++) { + ek = log10(0.5) / log10(positions[iDV]); + if (Coord[0] > 10 * EPS) + fk += pow(sin(PI_NUMBER * pow(Coord[0], ek)), 3) * values[iDV]; + } + VarCoord[1] = fk; + } + + /*--- Apply the transformation to the coordinate variation ---*/ + + ValCos = cos(-AoA * PI_NUMBER / 180.0); + ValSin = sin(-AoA * PI_NUMBER / 180.0); + + VarCoordTrans[0] = VarCoord[0] * ValCos - VarCoord[1] * ValSin; + VarCoordTrans[1] = VarCoord[1] * ValCos + VarCoord[0] * ValSin; + + boundary->vertex[iMarker][iVertex]->SetVarCoord(VarCoordTrans); + } + } +} + void CSurfaceMovement::SetNACA_4Digits(CGeometry* boundary, CConfig* config) { unsigned long iVertex; unsigned short iMarker; diff --git a/SU2_DEF/src/drivers/CDiscAdjDeformationDriver.cpp b/SU2_DEF/src/drivers/CDiscAdjDeformationDriver.cpp index e2abe0197ec..22d5c52578f 100644 --- a/SU2_DEF/src/drivers/CDiscAdjDeformationDriver.cpp +++ b/SU2_DEF/src/drivers/CDiscAdjDeformationDriver.cpp @@ -563,6 +563,10 @@ void CDiscAdjDeformationDriver::SetProjection_FD(CGeometry* geometry, CConfig* c surface_movement->SetRotation(geometry, config, iDV, true); } + else if (config->GetDesign_Variable(iDV) == HICKS_HENNE_CAMBER) { + surface_movement->SetHicksHenneCamber(geometry, config); + } + /*--- NACA_4Digits design variable. ---*/ else if (config->GetDesign_Variable(iDV) == NACA_4DIGITS) { diff --git a/SU2_GEO/src/SU2_GEO.cpp b/SU2_GEO/src/SU2_GEO.cpp index f432a7c2eca..0f6b521e7e7 100644 --- a/SU2_GEO/src/SU2_GEO.cpp +++ b/SU2_GEO/src/SU2_GEO.cpp @@ -934,6 +934,17 @@ int main(int argc, char* argv[]) { surface_movement->SetRotation(geometry_container[ZONE_0], config_container[ZONE_0], iDV, true); } + /*--- HICKS_HENNE_CAMBER design variable ---*/ + + else if (config_container[ZONE_0]->GetDesign_Variable(iDV) == HICKS_HENNE_CAMBER) { + if (rank == MASTER_NODE) { + cout << endl << "Design variable number " << iDV << "." << endl; + cout << "Perform 2D deformation of the surface." << endl; + } + MoveSurface = true; + surface_movement->SetHicksHenneCamber(geometry_container[ZONE_0], config_container[ZONE_0]); + } + /*--- NACA_4Digits design variable ---*/ else if (config_container[ZONE_0]->GetDesign_Variable(iDV) == NACA_4DIGITS) { From 74cf16ec3bcf832f03db8f5bdf95cb3bcd0f18b7 Mon Sep 17 00:00:00 2001 From: Jan Rottmayer Date: Tue, 15 Jul 2025 12:03:48 +0200 Subject: [PATCH 2/4] Added python support in SU2_py for shape optimization --- SU2_PY/SU2/io/tools.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SU2_PY/SU2/io/tools.py b/SU2_PY/SU2/io/tools.py index a040f386578..ed3b0f2d8f9 100755 --- a/SU2_PY/SU2/io/tools.py +++ b/SU2_PY/SU2/io/tools.py @@ -600,6 +600,7 @@ def get_dvMap(): 34: "CST", 35: "SURFACE_BUMP", 36: "SURFACE_FILE", + 37: "HICKS_HENNE_CAMBER", 40: "DV_EFIELD", 41: "DV_YOUNG", 42: "DV_POISSON", @@ -722,6 +723,9 @@ def get_gradFileFormat(grad_type, plot_format, kindID, special_cases=[]): elif kindID == "HICKS_HENNE": header.append(r',"Up/Down","Loc_Max"') write_format.append(r", %s, %s") + if kindID == "HICKS_HENNE_CAMBER": + header.append(r',"Loc_Max"') + write_format.append(r", %s") elif kindID == "SURFACE_BUMP": header.append(r',"Loc_Start","Loc_End","Loc_Max"') write_format.append(r", %s, %s, %s") From ef83a78df5dd2076e7b58d80a97bd51c865364f7 Mon Sep 17 00:00:00 2001 From: Jan Rottmayer Date: Wed, 23 Jul 2025 09:04:51 +0200 Subject: [PATCH 3/4] Added regression test; ran pre-commit --- Common/src/CConfig.cpp | 2 +- Common/src/grid_movement/CSurfaceMovement.cpp | 42 +++--- .../naca0012/def_NACA0012_camber.cfg | 134 ++++++++++++++++++ TestCases/parallel_regression.py | 13 ++ TestCases/serial_regression.py | 13 ++ 5 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 TestCases/deformation/naca0012/def_NACA0012_camber.cfg diff --git a/Common/src/CConfig.cpp b/Common/src/CConfig.cpp index 31cb18b247b..26d1d660ffd 100644 --- a/Common/src/CConfig.cpp +++ b/Common/src/CConfig.cpp @@ -6691,7 +6691,7 @@ void CConfig::SetOutput(SU2_COMPONENT val_software, unsigned short val_izone) { if ((Design_Variable[iDV] == NO_DEFORMATION) || (Design_Variable[iDV] == FFD_SETTING) || (Design_Variable[iDV] == SCALE) ) nParamDV = 0; - if ((Design_Variable[iDV] == ANGLE_OF_ATTACK) || + if ((Design_Variable[iDV] == ANGLE_OF_ATTACK) || (Design_Variable[iDV] == HICKS_HENNE_CAMBER)) nParamDV = 1; if ((Design_Variable[iDV] == FFD_CAMBER_2D) || (Design_Variable[iDV] == FFD_THICKNESS_2D) || diff --git a/Common/src/grid_movement/CSurfaceMovement.cpp b/Common/src/grid_movement/CSurfaceMovement.cpp index 8be6815bf21..6cffc30ba2e 100644 --- a/Common/src/grid_movement/CSurfaceMovement.cpp +++ b/Common/src/grid_movement/CSurfaceMovement.cpp @@ -640,15 +640,14 @@ vector > CSurfaceMovement::SetSurface_Deformation(CGeometry* g break; } } - + /*--- HICKS_HENNE_CAMBER design variable ---*/ - + if (config->GetDesign_Variable(0) == HICKS_HENNE_CAMBER) { SetHicksHenneCamber(geometry, config); } } - /*--- NACA_4Digits design variable ---*/ else if (config->GetDesign_Variable(0) == NACA_4DIGITS) { @@ -673,8 +672,6 @@ vector > CSurfaceMovement::SetSurface_Deformation(CGeometry* g if (rank == MASTER_NODE) cout << "No surface deformation (setting FFD)." << endl; } - - /*--- Scale, Translate, and Rotate will be done with rigid mesh transforms. ---*/ else if ((config->GetDesign_Variable(0) == ROTATION) || (config->GetDesign_Variable(0) == TRANSLATION) || @@ -2770,8 +2767,6 @@ void CSurfaceMovement::SetHicksHenne(CGeometry* boundary, CConfig* config, unsig } } - - #ifdef HAVE_MPI int iProcessor, nProcessor = size; @@ -3711,8 +3706,8 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) unsigned long iVertex; unsigned short iMarker, nDV_Camber = 0; su2double VarCoord[3] = {0.0, 0.0, 0.0}, VarCoordTrans[3] = {0.0, 0.0, 0.0}, *CoordTrans, *NormalTrans, ek, fk, - Coord[3] = {0.0, 0.0, 0.0}, TPCoord[2] = {0.0, 0.0}, LPCoord[2] = {0.0, 0.0}, - USTPCoord[2] = {0.0, 0.0}, LSTPCoord[2] = {0.0, 0.0}, Distance, Chord, AoA, ValCos, ValSin; + Coord[3] = {0.0, 0.0, 0.0}, TPCoord[2] = {0.0, 0.0}, LPCoord[2] = {0.0, 0.0}, USTPCoord[2] = {0.0, 0.0}, + LSTPCoord[2] = {0.0, 0.0}, Distance, Chord, AoA, ValCos, ValSin; vector positions, values, X_Coord_upper, Y_Coord_upper, X_Coord_lower, Y_Coord_lower; // --- Check if the type of design variables is only HICKS_HENNE_CAMBER ---// // TODO: Extend to CAMBER + THICKNESS @@ -3728,16 +3723,15 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) values.resize(nDV_Camber); /*--- Collect the values of the Hicks-Henne camber design variables ---*/ - for (unsigned short iDV = 0, counter = 0; iDV < config->GetnDV(); iDV++){ + for (unsigned short iDV = 0, counter = 0; iDV < config->GetnDV(); iDV++) { if (config->GetDesign_Variable(iDV) == HICKS_HENNE_CAMBER) { - positions[counter] = config->GetParamDV(iDV, 0); /*--- Position of the camber point as a fraction of the chord ---*/ + positions[counter] = + config->GetParamDV(iDV, 0); /*--- Position of the camber point as a fraction of the chord ---*/ values[counter] = config->GetDV_Value(iDV); /*--- Value of the deformation ---*/ counter++; } } - - /*--- Compute the angle of attack, Leading-edge (LP) and Trailing-edge (TP) point. We do this for upper and lower surface separately to detect blunt trailing edges ---*/ @@ -3750,7 +3744,7 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) USTPCoord[1] = CoordTrans[1]; for (iVertex = 1; iVertex < boundary->nVertex[iMarker]; iVertex++) { CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); - NormalTrans = boundary->vertex[iMarker][0]->GetNormal(); + NormalTrans = boundary->vertex[iMarker][0]->GetNormal(); if ((CoordTrans[0] > TPCoord[0]) && (abs(NormalTrans[1]) > abs(NormalTrans[0]))) { if (NormalTrans[1] >= 0.0) { USTPCoord[0] = CoordTrans[0]; @@ -3785,20 +3779,21 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) LPCoord[1] = CoordTrans[1]; } } - } + } } - + AoA = atan((LPCoord[1] - TPCoord[1]) / (TPCoord[0] - LPCoord[0])) * 180 / PI_NUMBER; - - /*--- Apply deformation based on the camberline Hicks-Henne deformation and the existing airfoil thickness distribution ---*/ + + /*--- Apply deformation based on the camberline Hicks-Henne deformation and the existing airfoil thickness + * distribution ---*/ for (iMarker = 0; iMarker < config->GetnMarker_All(); iMarker++) { for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) { if (config->GetMarker_All_DV(iMarker) == YES) { CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); NormalTrans = boundary->vertex[iMarker][iVertex]->GetNormal(); - + ValCos = cos(AoA * PI_NUMBER / 180.0); - ValSin = sin(AoA * PI_NUMBER / 180.0); + ValSin = sin(AoA * PI_NUMBER / 180.0); /*--- Transform the coordinates ---*/ Coord[0] = (CoordTrans[0] - LPCoord[0]) * ValCos - (CoordTrans[1] - LPCoord[1]) * ValSin; @@ -3806,16 +3801,15 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) Coord[1] = (CoordTrans[1] - LPCoord[1]) * ValCos + (CoordTrans[0] - LPCoord[0]) * ValSin; /*--- Special case: surface point is part of trailing edge ---*/ - if (Coord[0] > 0.99) { + if (Coord[0] > 0.99) { continue; - } + } /*--- Compute the Hicks-Henne bumps ---*/ fk = 0.0; for (unsigned short iDV = 0; iDV < nDV_Camber; iDV++) { ek = log10(0.5) / log10(positions[iDV]); - if (Coord[0] > 10 * EPS) - fk += pow(sin(PI_NUMBER * pow(Coord[0], ek)), 3) * values[iDV]; + if (Coord[0] > 10 * EPS) fk += pow(sin(PI_NUMBER * pow(Coord[0], ek)), 3) * values[iDV]; } VarCoord[1] = fk; } diff --git a/TestCases/deformation/naca0012/def_NACA0012_camber.cfg b/TestCases/deformation/naca0012/def_NACA0012_camber.cfg new file mode 100644 index 00000000000..72749394e26 --- /dev/null +++ b/TestCases/deformation/naca0012/def_NACA0012_camber.cfg @@ -0,0 +1,134 @@ +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % +% SU2 configuration file % +% Case description: Transonic inviscid flow around a NACA0012 airfoil % +% Author: Thomas D. Economon % +% Institution: Stanford University % +% Date: 2014.06.11 % +% File Version 8.2.0 "Harrier" % +% % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% ------------- DIRECT, ADJOINT, AND LINEARIZED PROBLEM DEFINITION ------------% +% +SOLVER= EULER +MATH_PROBLEM= DIRECT +RESTART_SOL= NO + +% ----------- COMPRESSIBLE AND INCOMPRESSIBLE FREE-STREAM DEFINITION ----------% +% +MACH_NUMBER= 0.8 +AOA= 1.25 +FREESTREAM_PRESSURE= 101325.0 +FREESTREAM_TEMPERATURE= 273.15 + +% -------------- COMPRESSIBLE AND INCOMPRESSIBLE FLUID CONSTANTS --------------% +% +GAMMA_VALUE= 1.4 +GAS_CONSTANT= 287.87 + +% ---------------------- REFERENCE VALUE DEFINITION ---------------------------% +% +REF_ORIGIN_MOMENT_X = 0.25 +REF_ORIGIN_MOMENT_Y = 0.00 +REF_ORIGIN_MOMENT_Z = 0.00 +REF_LENGTH= 1.0 +REF_AREA= 1.0 +REF_DIMENSIONALIZATION= DIMENSIONAL + +% ----------------------- BOUNDARY CONDITION DEFINITION -----------------------% +% +MARKER_EULER= ( airfoil ) +MARKER_FAR= ( farfield ) + +% ------------------------ SURFACES IDENTIFICATION ----------------------------% +% +MARKER_PLOTTING = ( airfoil ) +MARKER_MONITORING = ( airfoil ) +MARKER_DESIGNING = ( airfoil ) + +% ------------- COMMON PARAMETERS TO DEFINE THE NUMERICAL METHOD --------------% +% +NUM_METHOD_GRAD= WEIGHTED_LEAST_SQUARES +OBJECTIVE_FUNCTION= DRAG +CFL_NUMBER= 4.0 +ITER= 250 + +% ------------------------ LINEAR SOLVER DEFINITION ---------------------------% +% +LINEAR_SOLVER= FGMRES +LINEAR_SOLVER_PREC= LU_SGS +LINEAR_SOLVER_ERROR= 1E-6 +LINEAR_SOLVER_ITER= 5 + +% -------------------------- MULTIGRID PARAMETERS -----------------------------% +% +MGLEVEL= 3 +MGCYCLE= W_CYCLE +MG_PRE_SMOOTH= ( 1, 2, 3, 3 ) +MG_POST_SMOOTH= ( 0, 0, 0, 0 ) +MG_CORRECTION_SMOOTH= ( 0, 0, 0, 0 ) +MG_DAMP_RESTRICTION= 1.0 +MG_DAMP_PROLONGATION= 1.0 + +% -------------------- FLOW NUMERICAL METHOD DEFINITION -----------------------% +% +CONV_NUM_METHOD_FLOW= JST +JST_SENSOR_COEFF= ( 0.5, 0.02 ) +TIME_DISCRE_FLOW= EULER_IMPLICIT + +% ---------------- ADJOINT-FLOW NUMERICAL METHOD DEFINITION -------------------% +% +CONV_NUM_METHOD_ADJFLOW= JST +ADJ_JST_SENSOR_COEFF= ( 0.5, 0.02 ) +CFL_REDUCTION_ADJFLOW= 0.5 +TIME_DISCRE_ADJFLOW= EULER_IMPLICIT + +% ----------------------- DESIGN VARIABLE PARAMETERS --------------------------% +% +DV_KIND= HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER, HICKS_HENNE_CAMBER +DV_MARKER= ( airfoil ) +DV_PARAM= ( 0.06666666666666667 ); ( 0.13333333333333333 ); ( 0.2 ); ( 0.26666666666666666 ); ( 0.3333333333333333 ); ( 0.4 ); ( 0.4666666666666667 ); ( 0.5333333333333333 ); ( 0.6 ); ( 0.6666666666666666 ); ( 0.7333333333333333 ); ( 0.8 ); ( 0.8666666666666667 ); ( 0.9333333333333333 ) +DV_VALUE= 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.005 + +% ------------------------ GRID DEFORMATION PARAMETERS ------------------------% +% +DEFORM_LINEAR_SOLVER= FGMRES +DEFORM_LINEAR_SOLVER_PREC= LU_SGS +DEFORM_LINEAR_SOLVER_ITER= 1000 +DEFORM_NONLINEAR_ITER= 1 +DEFORM_CONSOLE_OUTPUT= YES +DEFORM_LINEAR_SOLVER_ERROR= 1E-14 +DEFORM_COEFF = 1E6 +DEFORM_STIFFNESS_TYPE= INVERSE_VOLUME + +% --------------------------- CONVERGENCE PARAMETERS --------------------------% +% +CONV_RESIDUAL_MINVAL= -8 +CONV_STARTITER= 10 +CONV_CAUCHY_ELEMS= 100 +CONV_CAUCHY_EPS= 1E-6 + +% ------------------------- INPUT/OUTPUT INFORMATION --------------------------% +% +MESH_FILENAME= mesh_NACA0012_inv.su2 +MESH_FORMAT= SU2 +MESH_OUT_FILENAME= mesh_out.su2 +SOLUTION_FILENAME= solution_flow.dat +SOLUTION_ADJ_FILENAME= solution_adj.dat +TABULAR_FORMAT= CSV +CONV_FILENAME= history +RESTART_FILENAME= restart_flow.dat +RESTART_ADJ_FILENAME= restart_adj.dat +VOLUME_FILENAME= flow +VOLUME_ADJ_FILENAME= adjoint +GRAD_OBJFUNC_FILENAME= of_grad.dat +SURFACE_FILENAME= surface_flow +SURFACE_ADJ_FILENAME= surface_adjoint +OUTPUT_WRT_FREQ= 250 + +% --------------------- OPTIMAL SHAPE DESIGN DEFINITION -----------------------% +% +OPT_OBJECTIVE= DRAG * 0.001 +OPT_CONSTRAINT= ( LIFT > 0.328188 ) * 0.001; ( MOMENT_Z > 0.034068 ) * 0.001; ( AIRFOIL_THICKNESS > 0.11 ) * 0.001 +DEFINITION_DV= ( 37, 1.0 | airfoil | 0.06666666666666667 ); ( 37, 1.0 | airfoil | 0.13333333333333333 ); ( 37, 1.0 | airfoil | 0.2 ); ( 37, 1.0 | airfoil | 0.26666666666666666 ); ( 37, 1.0 | airfoil | 0.3333333333333333 ); ( 37, 1.0 | airfoil | 0.4 ); ( 37, 1.0 | airfoil | 0.4666666666666667 ); ( 37, 1.0 | airfoil | 0.5333333333333333 ); ( 37, 1.0 | airfoil | 0.6 ); ( 37, 1.0 | airfoil | 0.6666666666666666 ); ( 37, 1.0 | airfoil | 0.7333333333333333 ); ( 37, 1.0 | airfoil | 0.8 ); ( 37, 1.0 | airfoil | 0.8666666666666667 ); ( 37, 1.0 | airfoil | 0.9333333333333333 ) \ No newline at end of file diff --git a/TestCases/parallel_regression.py b/TestCases/parallel_regression.py index fe18c70ed44..b52ff823d12 100644 --- a/TestCases/parallel_regression.py +++ b/TestCases/parallel_regression.py @@ -1715,6 +1715,19 @@ def main(): pass_list.append(naca0012_def.run_def()) test_list.append(naca0012_def) + # Inviscid NACA0012 based on Camberline deformation (triangles) + naca0012_def_file_camber = TestCase('naca0012_def_camber') + naca0012_def_file_camber.cfg_dir = "deformation/naca0012" + naca0012_def_file_camber.cfg_file = "def_NACA0012_camber.cfg" + naca0012_def_file_camber.test_iter = 10 + naca0012_def_file_camber.test_vals = [0.00854844] + naca0012_def_file_camber.command = TestCase.Command("mpirun -n 2", "SU2_DEF") + naca0012_def_file_camber.timeout = 1600 + naca0012_def_file_camber.tol = 1e-8 + + pass_list.append(naca0012_def_file_camber.run_def()) + test_list.append(naca0012_def_file_camber) + # Inviscid NACA0012 based on SURFACE_FILE input (surface_bump.dat) naca0012_def_file = TestCase('naca0012_def_file') naca0012_def_file.cfg_dir = "deformation/naca0012" diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index aba223dcefd..2a322b777bb 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -1256,6 +1256,19 @@ def main(): pass_list.append(naca0012_def.run_def(args.tsan, args.asan)) test_list.append(naca0012_def) + # Inviscid NACA0012 based on Camberline deformation (triangles) + naca0012_def_camber = TestCase('naca0012_def_camber') + naca0012_def_camber.cfg_dir = "deformation/naca0012" + naca0012_def_camber.cfg_file = "def_NACA0012_camber.cfg" + naca0012_def_camber.test_iter = 10 + naca0012_def_camber.test_vals = [0.0201692] + naca0012_def_camber.command = TestCase.Command(exec = "SU2_DEF") + naca0012_def_camber.timeout = 1600 + naca0012_def_camber.tol = 1e-06 + + pass_list.append(naca0012_def_camber.run_def(args.tsan, args.asan)) + test_list.append(naca0012_def_camber) + # Inviscid NACA0012 based on SURFACE_FILE input (surface_bump.dat) naca0012_def_file = TestCase('naca0012_def_file') naca0012_def_file.cfg_dir = "deformation/naca0012" From 24e406defc239507c4999d88f8adf5c55d9969fa Mon Sep 17 00:00:00 2001 From: Jan Rottmayer Date: Tue, 29 Jul 2025 08:24:55 +0200 Subject: [PATCH 4/4] Addressed feedback from PR #2538 --- Common/src/grid_movement/CSurfaceMovement.cpp | 8 +++----- TestCases/serial_regression.py | 13 ------------- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/Common/src/grid_movement/CSurfaceMovement.cpp b/Common/src/grid_movement/CSurfaceMovement.cpp index 6cffc30ba2e..d7b6d394c48 100644 --- a/Common/src/grid_movement/CSurfaceMovement.cpp +++ b/Common/src/grid_movement/CSurfaceMovement.cpp @@ -26,7 +26,6 @@ */ #include "../../include/grid_movement/CSurfaceMovement.hpp" -#include #include "../../include/toolboxes/C1DInterpolation.hpp" #include "../../include/toolboxes/geometry_toolbox.hpp" @@ -3713,8 +3712,7 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) // --- Check if the type of design variables is only HICKS_HENNE_CAMBER ---// // TODO: Extend to CAMBER + THICKNESS for (unsigned short iDV = 0; iDV < config->GetnDV(); iDV++) if (config->GetDesign_Variable(iDV) != HICKS_HENNE_CAMBER) { - cout << "'HicksHenneCamber' can not be combined with other design variables."; - cin.get(); + SU2_MPI::Error("'HicksHenneCamber' can not be combined with other design variables.", CURRENT_FUNCTION); } else { nDV_Camber++; } @@ -3759,7 +3757,7 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) } /*--- Correct the TP coordinates if the trailing edge is blunt ---*/ - if ((USTPCoord[0] != LSTPCoord[0]) || (USTPCoord[1] != LSTPCoord[1])) { + if ((fabs(USTPCoord[0] - LSTPCoord[0]) > EPS) || (fabs(USTPCoord[1] - LSTPCoord[1]) > EPS)) { TPCoord[0] = (USTPCoord[0] + LSTPCoord[0]) / 2.0; TPCoord[1] = (USTPCoord[1] + LSTPCoord[1]) / 2.0; } else { @@ -3772,7 +3770,7 @@ void CSurfaceMovement::SetHicksHenneCamber(CGeometry* boundary, CConfig* config) if (config->GetMarker_All_DV(iMarker) == YES) { for (iVertex = 0; iVertex < boundary->nVertex[iMarker]; iVertex++) { CoordTrans = boundary->vertex[iMarker][iVertex]->GetCoord(); - Distance = sqrt(pow(CoordTrans[0] - TPCoord[0], 2.0) + pow(CoordTrans[1] - TPCoord[1], 2.0)); + Distance = GeometryToolbox::Distance(2, CoordTrans, TPCoord); if (Chord < Distance) { Chord = Distance; LPCoord[0] = CoordTrans[0]; diff --git a/TestCases/serial_regression.py b/TestCases/serial_regression.py index 2a322b777bb..b5d80109417 100644 --- a/TestCases/serial_regression.py +++ b/TestCases/serial_regression.py @@ -1255,19 +1255,6 @@ def main(): pass_list.append(naca0012_def.run_def(args.tsan, args.asan)) test_list.append(naca0012_def) - - # Inviscid NACA0012 based on Camberline deformation (triangles) - naca0012_def_camber = TestCase('naca0012_def_camber') - naca0012_def_camber.cfg_dir = "deformation/naca0012" - naca0012_def_camber.cfg_file = "def_NACA0012_camber.cfg" - naca0012_def_camber.test_iter = 10 - naca0012_def_camber.test_vals = [0.0201692] - naca0012_def_camber.command = TestCase.Command(exec = "SU2_DEF") - naca0012_def_camber.timeout = 1600 - naca0012_def_camber.tol = 1e-06 - - pass_list.append(naca0012_def_camber.run_def(args.tsan, args.asan)) - test_list.append(naca0012_def_camber) # Inviscid NACA0012 based on SURFACE_FILE input (surface_bump.dat) naca0012_def_file = TestCase('naca0012_def_file')