From 7da6153ac9673c7c8d8fbb61603f8eec4de9a035 Mon Sep 17 00:00:00 2001 From: Nikita Ageev Date: Fri, 2 Oct 2026 00:48:16 +0300 Subject: [PATCH 1/2] Fixed CL: write the finite difference derivatives regardless of the screen output frequency SetFixedCLScreenOutput stores the iteration at which the finite difference step starts and, at its end, writes flow.meta with dCD/dCL and dCMx/y/z/dCL. It is called only on screen output iterations, so when the finite difference step ended on an iteration that is not a multiple of SCREEN_WRT_FREQ_INNER the meta data file kept the values from the start of the step and the adjoint read stale derivatives. Always write the screen output at the start and the end of the finite difference step in fixed CL mode. Fixes #2937 --- SU2_CFD/include/output/CFlowOutput.hpp | 9 +++++++++ SU2_CFD/src/output/CFlowOutput.cpp | 17 +++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/SU2_CFD/include/output/CFlowOutput.hpp b/SU2_CFD/include/output/CFlowOutput.hpp index 7e6264f18476..7e09a9956dce 100644 --- a/SU2_CFD/include/output/CFlowOutput.hpp +++ b/SU2_CFD/include/output/CFlowOutput.hpp @@ -364,6 +364,15 @@ class CFlowOutput : public CFVMOutput{ */ void SetFixedCLScreenOutput(const CConfig *config); + /*! + * \brief Determines if the screen output should be written. + * \note In fixed CL mode the start and the end of the finite difference step are always written, + * since SetFixedCLScreenOutput writes the meta data file with the finite difference derivatives. + * \param[in] config - Definition of the particular problem per zone. + * \return if screen output should be written. + */ + bool WriteScreenOutput(const CConfig *config) override; + /*! * \brief Compute the ratio of the stochastic energy backscatter to the turbulent energy dissipation. * \param iPoint - Index of the point. diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 2ac2693b9952..53f706763b2b 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -4282,6 +4282,23 @@ void CFlowOutput::SetFixedCLScreenOutput(const CConfig *config){ } } +bool CFlowOutput::WriteScreenOutput(const CConfig *config) { + + /*--- In fixed CL mode, SetFixedCLScreenOutput stores the iteration at which the finite difference + * step starts and, at its end, writes the meta data file with dCL/dAlpha and dCX/dCL. These events + * must not depend on the screen output frequency (e.g. when the finite difference step ends due to + * ITER_DCL_DALPHA), otherwise the adjoint reads stale derivatives from the meta data file. ---*/ + + if (config->GetFixed_CL_Mode() && config->GetFinite_Difference_Mode() && + !(config->GetMultizone_Problem() && !config->GetWrt_ZoneConv())) { + const bool startFD = fabs(historyOutput_Map["CL_DRIVER_COMMAND"].value) > 1e-16; + const bool endFD = historyOutput_Map["AOA"].value == historyOutput_Map["PREV_AOA"].value; + if (startFD || endFD) return true; + } + + return COutput::WriteScreenOutput(config); +} + void CFlowOutput::AddTurboOutput(unsigned short nZone){ //Adds zone turboperformance history variables for (unsigned short iZone = 0; iZone <= nZone-1; iZone++) { From ea814ec685737655f8879b063e972fcbd3db9ec2 Mon Sep 17 00:00:00 2001 From: Nikita Ageev Date: Sat, 10 Oct 2026 01:16:40 +0300 Subject: [PATCH 2/2] Fixed CL: write the finite difference meta data from LoadHistoryData Address review comments: - move the finite difference bookkeeping (start iteration and WriteMetaData at the end of the step) out of SetFixedCLScreenOutput into SetFixedCLFiniteDifference, called from LoadHistoryData every iteration; - drop the WriteScreenOutput override, screen output frequency is unchanged; - share the start/end conditions via FixedCLStartFD/FixedCLEndFD helpers, using GetHistoryFieldValue and EPS. --- SU2_CFD/include/output/CFlowOutput.hpp | 27 ++++++++++++++++++---- SU2_CFD/src/output/CFlowCompOutput.cpp | 4 ++++ SU2_CFD/src/output/CFlowOutput.cpp | 32 +++++++++++--------------- SU2_CFD/src/output/CNEMOCompOutput.cpp | 4 ++++ 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/SU2_CFD/include/output/CFlowOutput.hpp b/SU2_CFD/include/output/CFlowOutput.hpp index 7e09a9956dce..1eb33baed498 100644 --- a/SU2_CFD/include/output/CFlowOutput.hpp +++ b/SU2_CFD/include/output/CFlowOutput.hpp @@ -365,13 +365,30 @@ class CFlowOutput : public CFVMOutput{ void SetFixedCLScreenOutput(const CConfig *config); /*! - * \brief Determines if the screen output should be written. - * \note In fixed CL mode the start and the end of the finite difference step are always written, - * since SetFixedCLScreenOutput writes the meta data file with the finite difference derivatives. + * \brief Check if the fixed CL driver changed the AoA at the current iteration + * (in finite difference mode this is the start of the finite difference step). + * \return if the AoA was changed. + */ + bool FixedCLStartFD() const { + return fabs(GetHistoryFieldValue("CL_DRIVER_COMMAND")) > EPS; + } + + /*! + * \brief Check if the AoA was restored at the current iteration + * (in finite difference mode this is the end of the finite difference step). + * \return if the AoA is equal to the previous AoA. + */ + bool FixedCLEndFD() const { + return GetHistoryFieldValue("AOA") == GetHistoryFieldValue("PREV_AOA"); + } + + /*! + * \brief Store the iteration at which the finite difference step of the fixed CL driver starts and + * write the meta data file with the finite difference derivatives at its end. + * \note Called every iteration, independently of the screen output frequency. * \param[in] config - Definition of the particular problem per zone. - * \return if screen output should be written. */ - bool WriteScreenOutput(const CConfig *config) override; + void SetFixedCLFiniteDifference(const CConfig *config); /*! * \brief Compute the ratio of the stochastic energy backscatter to the turbulent energy dissipation. diff --git a/SU2_CFD/src/output/CFlowCompOutput.cpp b/SU2_CFD/src/output/CFlowCompOutput.cpp index fd9bd5356b03..46f3acb4688a 100644 --- a/SU2_CFD/src/output/CFlowCompOutput.cpp +++ b/SU2_CFD/src/output/CFlowCompOutput.cpp @@ -470,6 +470,10 @@ void CFlowCompOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSol SetAerodynamicCoefficients(config, flow_solver); + /*--- Fixed CL finite difference step, uses the AOA set above. ---*/ + + if (config->GetFixed_CL_Mode()) SetFixedCLFiniteDifference(config); + if (config->GetViscous()) { SetHistoryOutputValue("BUFFET", flow_solver->GetTotal_Buffet_Metric()); } diff --git a/SU2_CFD/src/output/CFlowOutput.cpp b/SU2_CFD/src/output/CFlowOutput.cpp index 53f706763b2b..50f69f85579d 100644 --- a/SU2_CFD/src/output/CFlowOutput.cpp +++ b/SU2_CFD/src/output/CFlowOutput.cpp @@ -4245,7 +4245,7 @@ void CFlowOutput::LoadTimeAveragedData(unsigned long iPoint, const CVariable *No void CFlowOutput::SetFixedCLScreenOutput(const CConfig *config){ PrintingToolbox::CTablePrinter FixedCLSummary(&cout); - if (fabs(historyOutput_Map["CL_DRIVER_COMMAND"].value) > 1e-16){ + if (FixedCLStartFD()){ FixedCLSummary.AddColumn("Fixed CL Mode", 40); FixedCLSummary.AddColumn("Value", 30); FixedCLSummary.SetAlign(PrintingToolbox::CTablePrinter::LEFT); @@ -4255,7 +4255,6 @@ void CFlowOutput::SetFixedCLScreenOutput(const CConfig *config){ FixedCLSummary << "Previous AOA" << historyOutput_Map["PREV_AOA"].value; if (config->GetFinite_Difference_Mode()){ FixedCLSummary << "Changed AoA by (Finite Difference step)" << historyOutput_Map["CL_DRIVER_COMMAND"].value; - lastInnerIter = curInnerIter - 1; } else FixedCLSummary << "Changed AoA by" << historyOutput_Map["CL_DRIVER_COMMAND"].value; @@ -4263,7 +4262,7 @@ void CFlowOutput::SetFixedCLScreenOutput(const CConfig *config){ SetScreenHeader(config); } - else if (config->GetFinite_Difference_Mode() && historyOutput_Map["AOA"].value == historyOutput_Map["PREV_AOA"].value){ + else if (config->GetFinite_Difference_Mode() && FixedCLEndFD()){ FixedCLSummary.AddColumn("Fixed CL Mode (Finite Difference)", 40); FixedCLSummary.AddColumn("Value", 30); FixedCLSummary.SetAlign(PrintingToolbox::CTablePrinter::LEFT); @@ -4276,27 +4275,24 @@ void CFlowOutput::SetFixedCLScreenOutput(const CConfig *config){ } FixedCLSummary << "Delta CMz / Delta CL" << config->GetdCMz_dCL(); FixedCLSummary.PrintFooter(); - curInnerIter = lastInnerIter; - WriteMetaData(config); - curInnerIter = config->GetInnerIter(); } } -bool CFlowOutput::WriteScreenOutput(const CConfig *config) { +void CFlowOutput::SetFixedCLFiniteDifference(const CConfig *config){ - /*--- In fixed CL mode, SetFixedCLScreenOutput stores the iteration at which the finite difference - * step starts and, at its end, writes the meta data file with dCL/dAlpha and dCX/dCL. These events - * must not depend on the screen output frequency (e.g. when the finite difference step ends due to - * ITER_DCL_DALPHA), otherwise the adjoint reads stale derivatives from the meta data file. ---*/ + /*--- This runs every iteration, independently of the screen output frequency, otherwise the finite + * difference step can end without writing dCL/dAlpha and dCX/dCL to the meta data file. ---*/ - if (config->GetFixed_CL_Mode() && config->GetFinite_Difference_Mode() && - !(config->GetMultizone_Problem() && !config->GetWrt_ZoneConv())) { - const bool startFD = fabs(historyOutput_Map["CL_DRIVER_COMMAND"].value) > 1e-16; - const bool endFD = historyOutput_Map["AOA"].value == historyOutput_Map["PREV_AOA"].value; - if (startFD || endFD) return true; - } + if (!config->GetFinite_Difference_Mode()) return; - return COutput::WriteScreenOutput(config); + if (FixedCLStartFD()){ + lastInnerIter = curInnerIter - 1; + } + else if (FixedCLEndFD()){ + curInnerIter = lastInnerIter; + WriteMetaData(config); + curInnerIter = config->GetInnerIter(); + } } void CFlowOutput::AddTurboOutput(unsigned short nZone){ diff --git a/SU2_CFD/src/output/CNEMOCompOutput.cpp b/SU2_CFD/src/output/CNEMOCompOutput.cpp index 2105ee378991..332d4ca40934 100644 --- a/SU2_CFD/src/output/CNEMOCompOutput.cpp +++ b/SU2_CFD/src/output/CNEMOCompOutput.cpp @@ -437,6 +437,10 @@ void CNEMOCompOutput::LoadHistoryData(CConfig *config, CGeometry *geometry, CSol SetAerodynamicCoefficients(config, NEMO_solver); + /*--- Fixed CL finite difference step, uses the AOA set above. ---*/ + + if (config->GetFixed_CL_Mode()) SetFixedCLFiniteDifference(config); + SetHeatCoefficients(config, NEMO_solver); SetRotatingFrameCoefficients(NEMO_solver);