Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
85ad370
Change some simple functions in ad_structure.hpp belonging to the tap…
oleburghardt Jan 28, 2026
a25b871
Changes in CDiscAdjMultizoneDriver.hpp for extension of the tape chec…
oleburghardt Jan 28, 2026
6bd7a48
Adding SetCurrentStatus to ad_structure.hpp for extension of the tape…
oleburghardt Jan 28, 2026
ec85644
Extend tagErrorCallback to transform tag mismatches into errors in a …
oleburghardt Jan 29, 2026
d27cbd7
Set the tagErrorCallback function via a AD::SetCallbackMode wrapper.
oleburghardt Jan 29, 2026
0d9a5e9
Add CDiscAdjMultizoneDriver::TapeTestGetTag for zone-specific tags.
oleburghardt Jan 29, 2026
557299a
Main changes in CDiscAdjMultizoneDriver::TapeTest and CDiscAdjMultizo…
oleburghardt Jan 29, 2026
e893ee7
Merge branch 'develop' of https://github.com/su2code/SU2 into enhance…
oleburghardt Jan 29, 2026
5d21f3f
Small fix.
oleburghardt Jan 29, 2026
e345e55
Clang format.
oleburghardt Jan 29, 2026
1162b46
Redefine CHECK_TAPE_VARIABLES as SOLUTION_VARIABLES and MESH_COORDS, …
oleburghardt Feb 4, 2026
cabe6e0
Register solution variables, too, when CHECK_TAPE_VARIABLES = MESH_CO…
oleburghardt Feb 4, 2026
25eca83
Move CDiscAdjMultizoneDriver::TapeTestGetTag to AD::GetTag.
oleburghardt Feb 4, 2026
5afe777
Follow-up removal of RECORDING_TAG* options.
oleburghardt Feb 4, 2026
935ddaf
Renamings, transform AD::SetCallbackMode to AD::SetTapeDebugOption th…
oleburghardt Feb 5, 2026
12916b0
Add AD::ActivateTagErrorCallback that sets the tag error callback fun…
oleburghardt Feb 6, 2026
86f4508
Set init and check tags via SetTapeDebugOption (tape debug mode).
oleburghardt Feb 6, 2026
4e4d671
Set multizone tags via SetTapeDebugOption (tape debug mode).
oleburghardt Feb 6, 2026
ad14b50
Fixes (tape debug mode).
oleburghardt Feb 6, 2026
61c5313
Fix (tape debug mode).
oleburghardt Feb 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions Common/include/CConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5601,14 +5601,14 @@ class CConfig {
unsigned short GetnVar(void);

/*!
* \brief Provides the number of variables.
* \return Number of variables.
* \brief Provides the total number of zones.
* \return Total number of zones.
*/
unsigned short GetnZone(void) const { return nZone; }

/*!
* \brief Provides the number of variables.
* \return Number of variables.
* \brief Provides the zone index the configuration belongs to.
* \return Zone index.
*/
unsigned short GetiZone(void) const { return iZone; }

Expand Down
174 changes: 148 additions & 26 deletions Common/include/basic_types/ad_structure.hpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*!
* \file ad_structure.hpp
* \brief Main routines for the algorithmic differentiation (AD) structure.
* \author T. Albring, J. Blühdorn
* \author T. Albring, J. Blühdorn, O. Burghardt
* \version 8.4.0 "Harrier"
*
* SU2 Project Website: https://su2code.github.io
Expand Down Expand Up @@ -36,7 +36,22 @@
* In case there is no reverse type configured, they have no effect at all,
* and so the real versions of the routined are after #else.
*/

namespace AD {

enum class TAPE_DEBUG_OPTION {
IGNORE_PREACC,
ACTIVATE_PREACC,
IGNORE_SINGLE_ZONE,
ACTIVATE_SINGLE_ZONE,
IGNORE_ZONES,
ACTIVATE_ZONES,
ACTIVATE_ALL_ERRORS,
MULTIZONE_TAGS,
INIT_RUN,
CHECK_RUN
};

#ifndef CODI_REVERSE_TYPE

using Identifier = int;
Expand Down Expand Up @@ -287,6 +302,13 @@ inline void SetIndex(Identifier& index, const su2double& data) {}
*/
inline void SetTag(int tag) {}

/*!
* \brief Compute the zone-specific tag.
* \param[in] iZone - Zone index from which the zone-specific tag is formed.
* \return The zone-specific tag.
*/
inline int GetTag(unsigned short iZone) { return 0; }

/*!
* \brief Sets the tag of a variable to 0.
* \param[in] v - the variable whose tag is cleared.
Expand All @@ -296,33 +318,45 @@ inline void ClearTagOnVariable(su2double& v) {}
/*!
* \brief Struct to store information about errors during a tag debug run.
*/
struct ErrorReport {};
struct DebugControl {};

/*!
* \brief Set a reference to the output file of an ErrorReport.
* \param[in] report - the ErrorReport whose output file is set.
* \param[in] output_file - pointer to the output file.
* \brief Set a pointer to the current DebugControl.
* \param[in] control - pointer to the current debug control.
*/
inline void SetDebugControl(DebugControl* control) {}

/*!
* \brief Set options which kind of tag mismatches are considered errors and written to file.
* \param[in] option - specification which kind of tag mismatches are considered.
* \param[in] izone - the zone w.r.t. which a tag mismatch is allowed.
*/
inline void SetDebugReportFile(ErrorReport& report, std::ostream* output_file) {}
inline void SetTapeDebugOption(TAPE_DEBUG_OPTION option, unsigned short izone = 0) {}

/*!
* \brief Set the ErrorReport to which error information from a tag debug recording is written.
* \param[in] report - the ErrorReport to which error information is written.
* \brief Activate the error callback by letting the tape call tagErrorCallback whenever a tag mismatch arises.
*/
inline void SetTagErrorCallback(ErrorReport& report) {}
inline void ActivateTagErrorCallback() {}

/*!
* \brief Reset the error counter in an ErrorReport.
* \param[in] report - the ErrorReport whose error counter is resetted.
* \brief Set a pointer to the output file of a DebugControl.
* \param[in] control - the DebugControl whose output file is set.
* \param[in] output_file - pointer to the output file.
*/
inline void SetDebugReportFile(DebugControl& control, std::ostream* output_file) {}

/*!
* \brief Reset the error counter in a DebugControl.
* \param[in] control - the DebugControl whose error counter is resetted.
*/
inline void ResetErrorCounter(ErrorReport& report) {}
inline void ResetErrorCounter(DebugControl& control) {}

/*!
* \brief Get the error count of an ErrorReport.
* \param[in] report - the ErrorReport whose pointer to its error counter is returned.
* \brief Get the error count of a DebugControl.
* \param[in] control - the DebugControl whose error count is reported.
* \return Value of the error counter.
*/
inline unsigned long GetErrorCount(const ErrorReport& report) { return 0; }
inline unsigned long GetErrorCount(const DebugControl& control) { return 0; }

/*!
* \brief Pushes back the current tape position to the tape position's vector.
Expand Down Expand Up @@ -744,37 +778,125 @@ FORCEINLINE void ResumePreaccumulation(bool wasActive) {
SU2_OMP_SAFE_GLOBAL_ACCESS(PreaccEnabled = true;)
}

struct ErrorReport {
#ifdef CODI_TAG_TAPE

struct DebugControl {
bool multizone_tags = false;
bool init_run = false;
bool ignore_preacc = false;
bool ignore_single_zone = false;
bool ignore_zones = false;
unsigned short ignore_izone = 0;
unsigned long ErrorCounter = 0;
std::ostream* out = &std::cout;
};

FORCEINLINE void ResetErrorCounter(ErrorReport& report) { report.ErrorCounter = 0; }
FORCEINLINE void ResetErrorCounter(DebugControl& control) { control.ErrorCounter = 0; }

FORCEINLINE void SetDebugReportFile(ErrorReport& report, std::ostream* output_file) { report.out = output_file; }
FORCEINLINE void SetDebugReportFile(DebugControl& control, std::ostream* output_file) { control.out = output_file; }

FORCEINLINE unsigned long GetErrorCount(const ErrorReport& report) { return report.ErrorCounter; }
FORCEINLINE unsigned long GetErrorCount(const DebugControl& control) { return control.ErrorCounter; }

#ifdef CODI_TAG_TAPE
extern DebugControl* current_control;

FORCEINLINE void SetDebugControl(DebugControl* control) { current_control = control; }

FORCEINLINE void SetTag(int tag) { AD::getTape().setCurTag(tag); }

FORCEINLINE int GetTag(unsigned short iZone) {
if (current_control->init_run) {
return (current_control->multizone_tags) ? ((int)iZone + 1) * 10 + 1 : 1;
} else {
return (current_control->multizone_tags) ? ((int)iZone + 1) * 10 + 2 : 2;
}
}

FORCEINLINE void ClearTagOnVariable(su2double& v) { AD::getTape().clearTagOnVariable(v); }

static void tagErrorCallback(const int& correctTag, const int& wrongTag, void* userData) {
auto* report = static_cast<ErrorReport*>(userData);
auto* status = static_cast<DebugControl*>(userData);

bool throw_mismatch_error = true;

if (status->ignore_preacc || status->ignore_single_zone || status->ignore_zones) {
/*--- The callback could be due to a preaccumulation tag mismatch, if not, we deduce
* that it is either due to a zone index mismatch, or due to a mismatch in the least
* significant bit that will always result in an error. ---*/

if (correctTag == 1337) {
if (status->ignore_preacc) {
throw_mismatch_error = false;
}
} else if (correctTag % 10 == wrongTag % 10) {
if (status->ignore_single_zone) {
/*--- A mismatch with a specified zone index might be allowed. ---*/
if (wrongTag / 10 == status->ignore_single_zone) {
throw_mismatch_error = false;
}
}
if (status->ignore_zones) {
throw_mismatch_error = false;
}
}
}

if (throw_mismatch_error) {
status->ErrorCounter += 1;
*(status->out) << "Use of variable with bad tag '" << std::setw(2) << std::setfill('0') << wrongTag
<< "', should be '" << std::setw(2) << std::setfill('0') << correctTag << "'." << std::endl;
}
}

report->ErrorCounter += 1;
*(report->out) << "Use of variable with bad tag '" << wrongTag << "', should be '" << correctTag << "'." << std::endl;
FORCEINLINE void SetTapeDebugOption(TAPE_DEBUG_OPTION option, unsigned short izone = 0) {
if (option == AD::TAPE_DEBUG_OPTION::IGNORE_PREACC) {
current_control->ignore_preacc = true;
}
if (option == AD::TAPE_DEBUG_OPTION::ACTIVATE_PREACC || option == AD::TAPE_DEBUG_OPTION::ACTIVATE_ALL_ERRORS) {
current_control->ignore_preacc = false;
}
if (option == AD::TAPE_DEBUG_OPTION::IGNORE_SINGLE_ZONE) {
current_control->ignore_single_zone = true;
current_control->ignore_izone = izone;
}
if (option == AD::TAPE_DEBUG_OPTION::ACTIVATE_SINGLE_ZONE || option == AD::TAPE_DEBUG_OPTION::ACTIVATE_ALL_ERRORS) {
current_control->ignore_single_zone = false;
}
if (option == AD::TAPE_DEBUG_OPTION::IGNORE_ZONES) {
current_control->ignore_zones = true;
}
if (option == AD::TAPE_DEBUG_OPTION::ACTIVATE_ZONES || option == AD::TAPE_DEBUG_OPTION::ACTIVATE_ALL_ERRORS) {
current_control->ignore_zones = false;
}
if (option == AD::TAPE_DEBUG_OPTION::INIT_RUN) {
current_control->init_run = true;
}
if (option == AD::TAPE_DEBUG_OPTION::CHECK_RUN) {
current_control->init_run = false;
}
if (option == AD::TAPE_DEBUG_OPTION::MULTIZONE_TAGS) {
current_control->multizone_tags = true;
}
}

FORCEINLINE void SetTagErrorCallback(ErrorReport& report) {
AD::getTape().setTagErrorCallback(tagErrorCallback, &report);
FORCEINLINE void ActivateTagErrorCallback() {
if (current_control != NULL) {
AD::getTape().setTagErrorCallback(tagErrorCallback, current_control);
} else {
std::cout << "No tape debug control set!" << std::endl;
}
}

#else
struct DebugControl {};
FORCEINLINE void ResetErrorCounter(DebugControl& control) {}
FORCEINLINE void SetDebugReportFile(DebugControl& control, std::ostream* output_file) {}
FORCEINLINE unsigned long GetErrorCount(const DebugControl& control) { return 0; }
FORCEINLINE void SetDebugControl(DebugControl* status) {}
FORCEINLINE void SetTag(int tag) {}
FORCEINLINE int GetTag(unsigned short iZone) { return 0; }
FORCEINLINE void ClearTagOnVariable(su2double& v) {}
FORCEINLINE void SetTagErrorCallback(ErrorReport report) {}
FORCEINLINE void SetTapeDebugOption(TAPE_DEBUG_OPTION option, unsigned short izone = 0) {}
FORCEINLINE void ActivateTagErrorCallback() {}

#endif // CODI_TAG_TAPE

Expand Down
8 changes: 2 additions & 6 deletions Common/include/option_structure.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2618,19 +2618,15 @@ enum class CHECK_TAPE_VARIABLES {
};
static const MapType<std::string, CHECK_TAPE_VARIABLES> CheckTapeVariables_Map = {
MakePair("SOLVER_VARIABLES", CHECK_TAPE_VARIABLES::SOLVER_VARIABLES)
MakePair("SOLVER_VARIABLES_AND_MESH_COORDINATES", CHECK_TAPE_VARIABLES::MESH_COORDINATES)
MakePair("MESH_COORDINATES", CHECK_TAPE_VARIABLES::MESH_COORDINATES)
};

enum class RECORDING {
CLEAR_INDICES,
SOLUTION_VARIABLES,
MESH_COORDS,
MESH_DEFORM,
SOLUTION_AND_MESH,
TAG_INIT_SOLVER_VARIABLES,
TAG_CHECK_SOLVER_VARIABLES,
TAG_INIT_SOLVER_AND_MESH,
TAG_CHECK_SOLVER_AND_MESH
SOLUTION_AND_MESH
};

/*!
Expand Down
4 changes: 4 additions & 0 deletions Common/src/basic_types/ad_structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ SU2_OMP(threadprivate(PreaccHelper))

ExtFuncHelper FuncHelper;

#ifdef CODI_TAG_TAPE
DebugControl* current_control = NULL;
#endif // CODI_TAG_TAPE

#endif

void Initialize() {
Expand Down
21 changes: 11 additions & 10 deletions SU2_CFD/include/drivers/CDiscAdjMultizoneDriver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,16 +141,6 @@ class CDiscAdjMultizoneDriver : public CMultizoneDriver {
*/
void StartSolver() override;

/*!
* \brief [Overload] Launch the tape test mode for the discrete adjoint multizone solver.
*/
void TapeTest ();

/*!
* \brief [Overload] Get error numbers after a tape test run of the discrete adjoint multizone solver.
*/
int TapeTestGatherErrors(AD::ErrorReport& error_report) const;

/*!
* \brief Preprocess the multizone iteration
*/
Expand Down Expand Up @@ -303,4 +293,15 @@ class CDiscAdjMultizoneDriver : public CMultizoneDriver {
}
}

/*!
* \brief Launch the tape test run of the discrete adjoint multizone solver.
*/
void TapeTest ();

/*!
* \brief Get the total error count after a tape test run of the discrete adjoint multizone solver.
* \param[in] debug_control - DebugControl from which this rank's contribution to the total error count is read.
* \return The total error count across all ranks.
*/
int TapeTestGatherErrors(AD::DebugControl& debug_control) const;
};
Loading