30#include "../code_config.hpp"
31#include "../parallelization/omp_structure.hpp"
54#ifndef CODI_REVERSE_TYPE
94template <
typename Comm>
185template <
class... Ts>
203inline void SetPreaccIn(
const T& data,
const int size_x,
const int size_y) {}
221template <
class... Ts>
236inline void SetPreaccOut(T&& data,
const int size_x,
const int size_y) {}
266inline void SetExtFuncIn(
const T& data,
const int size_x,
const int size_y) {}
412using CheckpointHandler = codi::ExternalFunctionUserData;
414using Tape = su2double::Tape;
418using ExtFuncHelper = codi::OpenMPExternalFunctionHelper<su2double>;
420using ExtFuncHelper = codi::ExternalFunctionHelper<su2double>;
423extern ExtFuncHelper FuncHelper;
425extern bool PreaccActive;
427SU2_OMP(threadprivate(PreaccActive))
430extern bool PreaccEnabled;
433using CoDiTapePosition = Tape::Position;
434using OpDiState =
void*;
435using TapePosition = std::pair<CoDiTapePosition, OpDiState>;
437using TapePosition = Tape::Position;
440extern TapePosition StartPosition, EndPosition;
442extern std::vector<TapePosition> TapePositions;
444extern codi::PreaccumulationHelper<su2double> PreaccHelper;
446SU2_OMP(threadprivate(PreaccHelper))
451FORCEINLINE Tape& getTape() {
return su2double::getTape(); }
462 if (AD::getTape().isActive()) {
463 AD::getTape().setPassive();
471 AD::getTape().setActive();
479template <
typename Comm>
482 std::cout <<
"-------------------------------------------------------\n";
483 std::cout <<
" Serial parts of the tape\n";
485 std::cout <<
" (aggregated across MPI processes)\n";
487 std::cout <<
"-------------------------------------------------------\n";
490 codi::TapeValues serialTapeValues = AD::getTape().getTapeValues();
491 serialTapeValues.combineDataMPI(communicator);
494 serialTapeValues.formatDefault(std::cout);
497 double totalMemoryUsed = serialTapeValues.getUsedMemorySize();
498 double totalMemoryAllocated = serialTapeValues.getAllocatedMemorySize();
503 std::cout <<
"-------------------------------------------------------\n";
504 std::cout <<
" OpenMP parallel parts of the tape\n";
505 std::cout <<
" (aggregated across OpenMP threads)\n";
507 std::cout <<
" (aggregated across MPI processes)\n";
509 std::cout <<
"-------------------------------------------------------\n";
512 codi::TapeValues* aggregatedOpenMPTapeValues =
nullptr;
518 codi::TapeValues masterTapeValues = AD::getTape().getTapeValues();
519 aggregatedOpenMPTapeValues = &masterTapeValues;
524 aggregatedOpenMPTapeValues->combineDataMPI(communicator);
525 totalMemoryUsed += aggregatedOpenMPTapeValues->getUsedMemorySize();
526 totalMemoryAllocated += aggregatedOpenMPTapeValues->getAllocatedMemorySize();
528 aggregatedOpenMPTapeValues->formatDefault(std::cout);
530 aggregatedOpenMPTapeValues =
nullptr;
534 aggregatedOpenMPTapeValues->combineData(AD::getTape().getTapeValues());
544 std::cout <<
"-------------------------------------------------------\n";
545 std::cout <<
" Total memory used : " << totalMemoryUsed / 1024.0 / 1024.0 <<
" MB\n";
546 std::cout <<
" Total memory allocated : " << totalMemoryAllocated / 1024.0 / 1024.0 <<
" MB\n";
547 std::cout <<
"-------------------------------------------------------\n";
554#if defined(HAVE_OPDI)
555 opdi::logic->prepareEvaluate();
557 AD::getTape().evaluate();
558#if defined(HAVE_OPDI)
559 opdi::logic->postEvaluate();
564#if defined(HAVE_OPDI)
565 opdi::logic->recoverState(TapePositions[enter].second);
566 opdi::logic->prepareEvaluate();
567 AD::getTape().evaluate(TapePositions[enter].first, TapePositions[leave].first);
569 AD::getTape().evaluate(TapePositions[enter], TapePositions[leave]);
576 AD::getTape().reset();
577#if defined(HAVE_OPDI)
578 opdi::logic->reset();
580 if (TapePositions.size() != 0) {
581#if defined(HAVE_OPDI)
582 for (TapePosition& pos : TapePositions) {
583 opdi::logic->freeState(pos.second);
586 TapePositions.clear();
604 if (!AD::getTape().isIdentifierActive(index))
return;
606 AD::getTape().setGradient(index, val, codi::AdjointsManagement::Manual);
615 return AD::getTape().getGradient(index, codi::AdjointsManagement::Manual);
625 if (!PreaccActive)
return;
626 PreaccHelper.addInput(data);
632 static_assert(!std::is_same<T, su2double>::value,
"rvalues cannot be registered");
638 for (
int i = 0; i < size; i++) {
639 PreaccHelper.addInput(data[i]);
646 if (!PreaccActive)
return;
647 for (
int i = 0; i < size_x; i++) {
648 for (
int j = 0; j < size_y; j++) {
649 PreaccHelper.addInput(data[i][j]);
655 if (AD::getTape().isActive() && PreaccEnabled) {
656 PreaccHelper.start();
666 if (!PreaccActive)
return;
667 PreaccHelper.addOutput(data);
674 for (
int i = 0; i < size; i++) {
675 PreaccHelper.addOutput(data[i]);
682 if (!PreaccActive)
return;
683 for (
int i = 0; i < size_x; i++) {
684 for (
int j = 0; j < size_y; j++) {
685 PreaccHelper.addOutput(data[i][j]);
691#if defined(HAVE_OPDI)
692 TapePositions.push_back({AD::getTape().getPosition(), opdi::logic->exportState()});
694 TapePositions.push_back(AD::getTape().getPosition());
700 PreaccHelper.finish(
false);
701 PreaccActive =
false;
709 for (
int i = 0; i < size; i++) {
710 FuncHelper.addInput(data[i]);
716 for (
int i = 0; i < size_x; i++) {
717 for (
int j = 0; j < size_y; j++) {
718 FuncHelper.addInput(data[i][j]);
724 if (AD::getTape().isActive()) {
725 FuncHelper.addOutput(data);
731 for (
int i = 0; i < size; i++) {
732 if (AD::getTape().isActive()) {
733 FuncHelper.addOutput(data[i]);
740 for (
int i = 0; i < size_x; i++) {
741 for (
int j = 0; j < size_y; j++) {
742 if (AD::getTape().isActive()) {
743 FuncHelper.addOutput(data[i][j]);
750 CheckpointHandler* checkpoint =
static_cast<CheckpointHandler*
>(handler);
755 if (AD::getTape().isActive()) {
756 AD::getTape().setPassive();
763 if (wasActive) AD::getTape().setActive();
768 opdi::logic->setAdjointAccessMode(opdi::LogicInterface::AdjointAccessMode::Classical);
769 opdi::logic->addReverseBarrier();
775 opdi::logic->setAdjointAccessMode(opdi::LogicInterface::AdjointAccessMode::Atomic);
776 opdi::logic->addReverseBarrier();
781 const auto current = PreaccEnabled;
782 if (!current)
return false;
788 if (!wasActive)
return;
796 bool multizone_tags =
false;
797 bool init_run =
false;
798 bool allow_preacc =
false;
799 bool allow_zones =
false;
800 unsigned short allow_izone = 0;
801 unsigned long ErrorCounter = 0;
802 std::ostream* out = &std::cout;
805struct AdjustDebugControl {
807 void (*adjust)(DebugControl*,
unsigned short);
810static const AdjustDebugControl debug_control_adjustments[] = {
816 [](DebugControl* c,
unsigned short) {
817 c->allow_zones =
false;
821 [](DebugControl* c,
unsigned short) {
822 c->allow_preacc =
false;
823 c->allow_zones =
false;
837extern DebugControl* current_control;
842 current_control->current_tag = tag;
843 AD::getTape().setCurTag(tag);
849 if (current_control->init_run) {
850 return (current_control->multizone_tags) ? ((int)iZone + 1) * 10 + 1 : 1;
852 return (current_control->multizone_tags) ? ((int)iZone + 1) * 10 + 2 : 2;
859 int tag = v.getIdentifier().tag;
860 int tens = (zone_tag > 0) ? zone_tag + 1 : tag / 10;
861 int ones = (run_tag > 0 && run_tag < 10) ? run_tag : tag % 10;
863 v.getIdentifier().tag = tens * 10 + ones;
867static void tagErrorCallback(
const int& correctTag,
const int& wrongTag,
void* userData) {
868 auto* status =
static_cast<DebugControl*
>(userData);
870 bool throw_mismatch_error =
true;
873 if (status->allow_preacc) {
874 if (correctTag == 1337 || wrongTag == 1337) {
875 throw_mismatch_error =
false;
880 if (status->allow_zones) {
881 throw_mismatch_error =
false;
882 }
else if (status->allow_izone > 0) {
883 if (wrongTag / 10 == status->allow_izone) {
884 throw_mismatch_error =
false;
888 if (throw_mismatch_error) {
889 status->ErrorCounter += 1;
890 *(status->out) <<
"Use of variable with bad tag '" << std::setw(2) << std::setfill(
'0') << wrongTag
891 <<
"', should be '" << std::setw(2) << std::setfill(
'0') << correctTag <<
"'." << std::endl;
896 if (current_control ==
nullptr) {
899 for (
const AdjustDebugControl& entry : debug_control_adjustments) {
900 if (entry.option == option) {
901 entry.adjust(current_control, izone);
908 if (current_control != NULL) {
909 AD::getTape().setTagErrorCallback(tagErrorCallback, current_control);
911 std::cout <<
"No tape debug control set!" << std::endl;
916struct DebugControl {};
948 return sqrt(x.real() * x.real() + x.imag() * x.imag());
952inline complex<su2double>
operator/(
const complex<su2double>& x,
const complex<su2double>& y) {
953 su2double d = (y.real() * y.real() + y.imag() * y.imag());
954 su2double real = (x.real() * y.real() + x.imag() * y.imag()) / d;
955 su2double imag = (x.imag() * y.real() - x.real() * y.imag()) / d;
957 return complex<su2double>(real, imag);
961inline complex<su2double>
operator*(
const complex<su2double>& x,
const complex<su2double>& y) {
962 su2double real = (x.real() * y.real() - x.imag() * y.imag());
963 su2double imag = (x.imag() * y.real() + x.real() * y.imag());
965 return complex<su2double>(real, imag);
#define FORCEINLINE
Definition code_config.hpp:44
passivedouble su2double
Definition code_config.hpp:181
typename std::enable_if< condition, bool >::type su2enable_if
Definition code_config.hpp:75
FORCEINLINE ARRAY_T sqrt(const ARRAY_T &x)
Definition special_vectorization.hpp:116
FORCEINLINE ARRAY_T operator/(const ARRAY_T &a, const ARRAY_T &b)
Definition special_vectorization.hpp:130
FORCEINLINE ARRAY_T operator*(const ARRAY_T &a, const ARRAY_T &b)
Definition special_vectorization.hpp:129
FORCEINLINE ARRAY_T abs(const ARRAY_T &x)
Definition special_vectorization.hpp:117
Contains routines for the reverse mode of AD. In case there is no reverse type configured,...
void SetExtFuncIn(su2double &data)
Sets the scalar input of a externally differentiated function.
Definition ad_structure.hpp:249
void ComputeAdjoint()
Computes the adjoints, i.e. the derivatives of the output with respect to the input variables.
Definition ad_structure.hpp:155
bool PauseRecording()
Pause the recording of the operations and involved variables. If called, all operations occuring afte...
Definition ad_structure.hpp:69
void SetDebugControl(DebugControl *control)
Set a pointer to the current DebugControl.
Definition ad_structure.hpp:338
void RegisterInput(su2double &data)
Registers the variable as an input. I.e. as a leaf of the computational graph.
Definition ad_structure.hpp:101
void ClearTagOnVariable(su2double &v)
Sets the tag of a variable to 0.
Definition ad_structure.hpp:321
bool BeginPassive()
Start a passive region, i.e. stop recording.
Definition ad_structure.hpp:381
void SetTagOnVariable(su2double &v, int zone_tag=0, int run_tag=0)
Sets the tag of a variable to a specified value.
Definition ad_structure.hpp:327
void StartPreacc()
Starts a new preaccumulation section and sets the input variables.
Definition ad_structure.hpp:215
void SetExtFuncOut(su2double &data)
Sets the scalar output of a externally differentiated function.
Definition ad_structure.hpp:272
void EndPreacc()
Ends a preaccumulation section and computes the local Jacobi matrix of a code section using the varia...
Definition ad_structure.hpp:243
void ResumePreaccumulation(bool wasActive)
Resume the use of preaccumulation.
Definition ad_structure.hpp:399
void ResetErrorCounter(DebugControl &control)
Reset the error counter in a DebugControl.
Definition ad_structure.hpp:363
void PrintStatistics(Comm communicator, bool printingRank)
Prints out tape statistics.
Definition ad_structure.hpp:95
void Reset()
Reset the tape structure to be ready for a new recording.
Definition ad_structure.hpp:173
void ActivateTagErrorCallback()
Activate the error callback by letting the tape call tagErrorCallback whenever a tag mismatch arises.
Definition ad_structure.hpp:350
int Identifier
Definition ad_structure.hpp:56
void Finalize()
Definition ad_structure.cpp:64
void ResizeAdjoints()
Resize the adjoint vector, for subsequent access without bounds checking.
Definition ad_structure.hpp:112
void SetTapeDebugOption(TAPE_DEBUG_OPTION option, unsigned short izone=0)
Set options which kind of tag mismatches are considered errors and written to file.
Definition ad_structure.hpp:345
void Initialize()
Definition ad_structure.cpp:57
void Push_TapePosition()
Pushes back the current tape position to the tape position's vector.
Definition ad_structure.hpp:375
void ClearAdjoints()
Clears the currently stored adjoints but keeps the computational graph.
Definition ad_structure.hpp:150
void SetTag(int tag)
Sets the tag tape to a specific tag.
Definition ad_structure.hpp:302
double GetDerivative(Identifier index)
Extracts the adjoint value at index.
Definition ad_structure.hpp:139
void ResetInput(su2double &data)
Reset the variable (set index to zero).
Definition ad_structure.hpp:179
void SetDerivative(Identifier index, const double val)
Sets the adjoint value at index to val.
Definition ad_structure.hpp:132
void SetPreaccOut(Ts &&... data)
Sets the scalar outputs of a preaccumulation section.
Definition ad_structure.hpp:222
void StopRecording()
Stops the recording of the operations and variables.
Definition ad_structure.hpp:79
Identifier GetPassiveIndex()
Returns the identifier that represents an inactive variable.
Definition ad_structure.hpp:145
void SetPreaccIn(Ts &&... data)
Sets the scalar inputs of a preaccumulation section.
Definition ad_structure.hpp:186
void SetDebugReportFile(DebugControl &control, std::ostream *output_file)
Set a pointer to the output file of a DebugControl.
Definition ad_structure.hpp:357
void StartRecording()
Start the recording of the operations and involved variables. If called, the computational graph of a...
Definition ad_structure.hpp:63
int ComputeTag(unsigned short iZone)
Compute the zone-specific tag.
Definition ad_structure.hpp:315
void ComputeAdjointForward()
Computes the adjoints, i.e., the derivatives of the output with respect to the input variables,...
Definition ad_structure.hpp:168
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
int GetTag()
Gets the current tag.
Definition ad_structure.hpp:308
bool PausePreaccumulation()
Pause the use of preaccumulation.
Definition ad_structure.hpp:393
unsigned long GetErrorCount(const DebugControl &control)
Get the error count of a DebugControl.
Definition ad_structure.hpp:370
void SetIndex(Identifier &index, const su2double &data)
Evaluates and saves gradient data from a variable.
Definition ad_structure.hpp:296
bool TapeActive()
Check if the tape is active.
Definition ad_structure.hpp:85
void RegisterOutput(su2double &data)
Registers the variable as an output. I.e. as the root of the computational graph.
Definition ad_structure.hpp:107
TAPE_DEBUG_OPTION
Definition ad_structure.hpp:42
void ResumeRecording(bool wasActive)
Resume the recording of the operations and variables after the recording had been paused.
Definition ad_structure.hpp:74
void EndUseAdjoints()
Declare that the adjoints are no longer being used.
Definition ad_structure.hpp:125
void BeginUseAdjoints()
Declare that the adjoints are being used, to protect against resizing.
Definition ad_structure.hpp:120
void EndPassive(bool wasActive)
End a passive region, i.e. start recording if we were recording before.
Definition ad_structure.hpp:387
#define END_SU2_OMP_PARALLEL
Definition omp_structure.hpp:157
#define SU2_OMP_BARRIER
Definition omp_structure.hpp:142
#define SU2_OMP(ARGS)
Definition omp_structure.hpp:65
#define SU2_OMP_CRITICAL
Definition omp_structure.hpp:143
#define SU2_OMP_PARALLEL
Definition omp_structure.hpp:145
#define SU2_OMP_SAFE_GLOBAL_ACCESS(...)
Definition omp_structure.hpp:197
constexpr int omp_get_thread_num()
Index of current thread, akin to MPI rank.
Definition omp_structure.hpp:85
#define END_SU2_OMP_CRITICAL
Definition omp_structure.hpp:156
Struct to store information about errors during a tag debug run.
Definition ad_structure.hpp:332