diff --git a/documentation/Changelog.md b/documentation/Changelog.md index fc793844..a1d7b665 100644 --- a/documentation/Changelog.md +++ b/documentation/Changelog.md @@ -1,6 +1,11 @@ Changelog {#Changelog} =========================== +### v ??? + - Features: + * Tape evaluations with generalized custom adjoints. + * Preaccumulation with local mapped adjoints. + ### v 2.2.0 - 2024-01-30 - Features: * New helper for adding Enzyme-generated derivative functions to the tape. See \ref Example_24_Enzyme_external_function_helper. diff --git a/documentation/examples/customAdjointVectorEvaluationTapeInterface.cpp b/documentation/examples/customAdjointVectorEvaluationTapeInterface.cpp index 62af242a..c62545a5 100644 --- a/documentation/examples/customAdjointVectorEvaluationTapeInterface.cpp +++ b/documentation/examples/customAdjointVectorEvaluationTapeInterface.cpp @@ -6,6 +6,7 @@ int main(int nargs, char** args) { //! [Custom vector] using Real = codi::RealReverse; using Tape = typename Real::Tape; + using Gradient = codi::Direction; Tape& tape = Real::getTape(); @@ -25,7 +26,7 @@ int main(int nargs, char** args) { // Reverse evaluation size_t adjointSize = tape.getParameter(codi::TapeParameters::LargestIdentifier); - codi::Direction* adjoints = new codi::Direction[adjointSize + 1]; + Gradient* adjoints = new Gradient[adjointSize + 1]; adjoints[y1.getIdentifier()] = {1.0, 0.0}; adjoints[y2.getIdentifier()] = {0.0, 1.0}; diff --git a/include/codi/tapes/indices/linearIndexManager.hpp b/include/codi/tapes/indices/linearIndexManager.hpp index 132784c1..e3d198b8 100644 --- a/include/codi/tapes/indices/linearIndexManager.hpp +++ b/include/codi/tapes/indices/linearIndexManager.hpp @@ -105,9 +105,8 @@ namespace codi { /// \copydoc IndexManagerInterface::addToTapeValues

/// Implementation: Adds maximum live indices. void addToTapeValues(TapeValues& values) const { - TapeValues::LocalReductionOperation constexpr operation = NeedsStaticStorage - ? TapeValues::LocalReductionOperation::Max - : TapeValues::LocalReductionOperation::Sum; + TapeValues::LocalReductionOperation constexpr operation = + NeedsStaticStorage ? TapeValues::LocalReductionOperation::Max : TapeValues::LocalReductionOperation::Sum; values.addLongEntry("Max. live indices", getLargestCreatedIndex(), operation); } diff --git a/include/codi/tapes/indices/multiUseIndexManager.hpp b/include/codi/tapes/indices/multiUseIndexManager.hpp index 97120cb9..4a0ec7c2 100644 --- a/include/codi/tapes/indices/multiUseIndexManager.hpp +++ b/include/codi/tapes/indices/multiUseIndexManager.hpp @@ -93,9 +93,8 @@ namespace codi { double memoryindexUseVector = (double)indexUse.size() * (double)(sizeof(Index)); - TapeValues::LocalReductionOperation constexpr operation = NeedsStaticStorage - ? TapeValues::LocalReductionOperation::Max - : TapeValues::LocalReductionOperation::Sum; + TapeValues::LocalReductionOperation constexpr operation = + NeedsStaticStorage ? TapeValues::LocalReductionOperation::Max : TapeValues::LocalReductionOperation::Sum; values.addDoubleEntry("Memory: index use vector", memoryindexUseVector, operation, true, true); } diff --git a/include/codi/tapes/indices/reuseIndexManager.hpp b/include/codi/tapes/indices/reuseIndexManager.hpp index e5fc1a0a..aa15728c 100644 --- a/include/codi/tapes/indices/reuseIndexManager.hpp +++ b/include/codi/tapes/indices/reuseIndexManager.hpp @@ -93,9 +93,8 @@ namespace codi { unsigned long storedIndices = this->usedIndicesPos + this->unusedIndicesPos; long currentLiveIndices = maximumGlobalIndex - storedIndices; - TapeValues::LocalReductionOperation constexpr operation = NeedsStaticStorage - ? TapeValues::LocalReductionOperation::Max - : TapeValues::LocalReductionOperation::Sum; + TapeValues::LocalReductionOperation constexpr operation = + NeedsStaticStorage ? TapeValues::LocalReductionOperation::Max : TapeValues::LocalReductionOperation::Sum; values.addUnsignedLongEntry("Max. live indices", maximumGlobalIndex, operation); values.addLongEntry("Cur. live indices", currentLiveIndices, operation); diff --git a/include/codi/tapes/indices/reuseIndexManagerBase.hpp b/include/codi/tapes/indices/reuseIndexManagerBase.hpp index 814e174c..b01131c9 100644 --- a/include/codi/tapes/indices/reuseIndexManagerBase.hpp +++ b/include/codi/tapes/indices/reuseIndexManagerBase.hpp @@ -244,8 +244,8 @@ namespace codi { double memoryAllocatedIndices = (double)allocatedIndices * (double)(sizeof(Index)); TapeValues::LocalReductionOperation constexpr operation = Impl::NeedsStaticStorage - ? TapeValues::LocalReductionOperation::Max - : TapeValues::LocalReductionOperation::Sum; + ? TapeValues::LocalReductionOperation::Max + : TapeValues::LocalReductionOperation::Sum; values.addUnsignedLongEntry("Indices stored", storedIndices, operation); values.addDoubleEntry("Memory used", memoryStoredIndices, operation, true, false); diff --git a/include/codi/tapes/interfaces/customAdjointVectorEvaluationTapeInterface.hpp b/include/codi/tapes/interfaces/customAdjointVectorEvaluationTapeInterface.hpp index a01e2eac..1c9a351b 100644 --- a/include/codi/tapes/interfaces/customAdjointVectorEvaluationTapeInterface.hpp +++ b/include/codi/tapes/interfaces/customAdjointVectorEvaluationTapeInterface.hpp @@ -37,6 +37,7 @@ #include "../../config.h" #include "../../misc/macros.hpp" #include "../data/position.hpp" +#include "../misc/internalAdjointsInterface.hpp" #include "../misc/tapeParameters.hpp" #include "forwardEvaluationTapeInterface.hpp" @@ -44,16 +45,23 @@ namespace codi { /** - * @brief Allows user defined vectors for the forward and adjoint evaluation. + * @brief Allows user defined vectors for the forward and adjoint evaluation, and for clearing adjoints. * * See \ref TapeInterfaces for a general overview of the tape interface design in CoDiPack. * - * The two additional evaluate methods allow for the evaluation of the tape with a custom adjoint vector. The type of - * the vector must support the following operators: + * The two additional evaluate methods allow for the evaluation of the tape with a custom adjoint vector, and the + * additional clearing method allows clearing the custom adjoint vector according to the recorded tape. + * + * The adjoint vector type (template parameter AdjointVector in the member functions) must be a accessible with + * operator[]. Suitable choices are pointers, e.g., Adjoint*, or classes with overloaded operator[] like + * std::vector. + * + * codi::AdjointVectorTraits::GradientImplementation must be specialized for AdjointVector. + * The type of the vector entries deduced from these traits (gradient type) must support the following operators: * - operator = * - operator *(Tape::Real, Adjoint) (Scalar multiplication from the left) * - operator += - * It must also specialize #codi::GradientTraits::TraitsImplementation. + * The gradient type must also specialize #codi::GradientTraits::TraitsImplementation. * * Here is an example for an evaluation with a custom adjoint vector * (documentation/examples/customAdjointVectorEvaluationTapeInterface.cpp): @@ -71,21 +79,51 @@ namespace codi { /// @name Interface definition /** - * \copydoc codi::PositionalEvaluationTapeInterface::evaluate + * \copybrief codi::PositionalEvaluationTapeInterface::evaluate * - * @tparam Adjoint See CustomAdjointVectorEvaluationTapeInterface documentation. + * Tape evaluation with a custom adjoint vector. + * + * @tparam AdjointVector See CustomAdjointVectorEvaluationTapeInterface documentation. */ - template - void evaluate(Position const& start, Position const& end, Adjoint* data); + template + void evaluate(Position const& start, Position const& end, AdjointVector&& data); // clang-format off /** - * \copydoc codi::ForwardEvaluationTapeInterface::evaluateForward(T_Position const&, T_Position const&, AdjointsManagement) + * \copybrief codi::ForwardEvaluationTapeInterface::evaluateForward(T_Position const&, T_Position const&, AdjointsManagement) + * + * Tape evaluation with a custom adjoint vector. * - * @tparam Adjoint See CustomAdjointVectorEvaluationTapeInterface documentation. + * @tparam AdjointVector See CustomAdjointVectorEvaluationTapeInterface documentation. */ // clang-format on - template - void evaluateForward(Position const& start, Position const& end, Adjoint* data); + template + void evaluateForward(Position const& start, Position const& end, AdjointVector&& data); + + /** + * \copybrief codi::ReverseTapeInterface::clearAdjoints + * + * Clear custom adjoint vector according to a tape recording. + * + * @tparam AdjointVector See CustomAdjointVectorEvaluationTapeInterface documentation. + */ + template + void clearCustomAdjoints(Position const& start, Position const& end, AdjointVector&& data); + + /** + * @brief Obtain a representation of the tape's internal adjoint vector that can be used as custom adjoints. + * + * To avoid that functionality has to be implemented both for custom, external and internal adjoints, this method + * provides access to the internal adjoints so that they can be used as if they were custom adjoints. + * + * Warning: If you use this method, proceed with care. If internal adjoints are modified due to side effect of + * other methods, the object returned here might become invalid, or, conversely, modifications of the returned + * object other than reading/writing adjoints might interfere with the tape's management of internal adjoints. + * + * @tparam InternalAdjoints Placeholder for the implementation-dependent return type. + */ + CODI_DD(CODI_T(template), ) + CODI_DD(InternalAdjoints, CODI_T(InternalAdjointsInterface)) + getInternalAdjoints(); }; } diff --git a/include/codi/tapes/interfaces/dataManagementTapeInterface.hpp b/include/codi/tapes/interfaces/dataManagementTapeInterface.hpp index 865555a8..a0f1ea17 100644 --- a/include/codi/tapes/interfaces/dataManagementTapeInterface.hpp +++ b/include/codi/tapes/interfaces/dataManagementTapeInterface.hpp @@ -133,8 +133,10 @@ namespace codi { VectorAccessInterface* createVectorAccess(); ///< See \ref vectorAccess. /// See \ref vectorAccess. - template - VectorAccessInterface* createVectorAccessCustomAdjoints(Adjoint* data); + /// @tparam AdjointVector Type that supports access with operator[]. + /// See codi::CustomAdjointVectorEvaluationTapeInterface. + template + VectorAccessInterface* createVectorAccessCustomAdjoints(AdjointVector&& data); void deleteVectorAccess(VectorAccessInterface* access); ///< See \ref vectorAccess. diff --git a/include/codi/tapes/interfaces/preaccumulationEvaluationTapeInterface.hpp b/include/codi/tapes/interfaces/preaccumulationEvaluationTapeInterface.hpp index d8f3d771..57f1a78d 100644 --- a/include/codi/tapes/interfaces/preaccumulationEvaluationTapeInterface.hpp +++ b/include/codi/tapes/interfaces/preaccumulationEvaluationTapeInterface.hpp @@ -87,6 +87,16 @@ namespace codi { void evaluateKeepState(Position const& start, Position const& end, AdjointsManagement adjointsManagement = AdjointsManagement::Automatic); + /** + * \copybrief evaluateKeepState(Position const&, Position const&, AdjointsManagement) + * + * Performs the evaluation on custom adjoints. + * + * @tparam AdjointVector See codi::CustomAdjointVectorEvaluationTapeInterface. + */ + template + void evaluateKeepState(Position const& start, Position const& end, AdjointVector&& data); + /** * @brief Perform a tape evaluation but restore the state afterwards such that it is the same as when the * evaluation started. It hast to hold start <= end. @@ -96,5 +106,15 @@ namespace codi { */ void evaluateForwardKeepState(Position const& start, Position const& end, AdjointsManagement adjointsManagement = AdjointsManagement::Automatic); + + /** + * \copybrief evaluateForwardKeepState(Position const&, Position const&, AdjointsManagement) + * + * Performs the evaluation on custom adjoints. + * + * @tparam AdjointVector See codi::CustomAdjointVectorEvaluationTapeInterface. + */ + template + void evaluateForwardKeepState(Position const& start, Position const& end, AdjointVector&& data); }; } diff --git a/include/codi/tapes/jacobianBaseTape.hpp b/include/codi/tapes/jacobianBaseTape.hpp index 6cf3af75..c51d919d 100644 --- a/include/codi/tapes/jacobianBaseTape.hpp +++ b/include/codi/tapes/jacobianBaseTape.hpp @@ -149,9 +149,9 @@ namespace codi { using NestedPosition = typename JacobianData::Position; ///< See JacobianTapeTypes. using Position = typename Base::Position; ///< See TapeTypesInterface. - template - using VectorAccess = - AdjointVectorAccess; ///< Vector access type generated by this tape. + /// Vector access type generated by this tape. + template + using VectorAccess = AdjointVectorAccess; static bool constexpr AllowJacobianOptimization = true; ///< See InternalStatementRecordingTapeInterface. static bool constexpr HasPrimalValues = false; ///< See PrimalEvaluationTapeInterface. @@ -495,7 +495,7 @@ namespace codi { size_t nAdjoints = indexManager.get().getLargestCreatedIndex(); double memoryAdjoints = static_cast(nAdjoints) * static_cast(sizeof(Gradient)); - bool constexpr globalAdjoints = AdjointVectorTraits::IsGlobal::value; + bool constexpr globalAdjoints = InternalAdjointVectorTraits::IsGlobal::value; TapeValues::LocalReductionOperation constexpr operation = globalAdjoints ? TapeValues::LocalReductionOperation::Max : TapeValues::LocalReductionOperation::Sum; @@ -521,8 +521,9 @@ namespace codi { protected: /// Performs the AD \ref sec_reverseAD "reverse" equation for a statement. - template - CODI_INLINE static void incrementAdjoints(Adjoint* adjointVector, Adjoint const& lhsAdjoint, + template + CODI_INLINE static void incrementAdjoints(AdjointVector& adjointVector, + AdjointVectorTraits::Gradient const& lhsAdjoint, Config::ArgumentSize const& numberOfArguments, size_t& curJacobianPos, Real const* const rhsJacobians, Identifier const* const rhsIdentifiers) { @@ -543,8 +544,9 @@ namespace codi { Impl::template internalEvaluateReverse_EvalStatements); /// Performs the AD \ref sec_forwardAD "forward" equation for a statement. - template - CODI_INLINE static void incrementTangents(Adjoint const* const adjointVector, Adjoint& lhsAdjoint, + template + CODI_INLINE static void incrementTangents(AdjointVector const& adjointVector, + AdjointVectorTraits::Gradient& lhsAdjoint, Config::ArgumentSize const& numberOfArguments, size_t& curJacobianPos, Real const* const rhsJacobians, Identifier const* const rhsIdentifiers) { @@ -568,35 +570,40 @@ namespace codi { using Base::evaluate; /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::evaluate() - template - CODI_NO_INLINE void evaluate(Position const& start, Position const& end, Adjoint* data) { - VectorAccess adjointWrapper(data); + template + CODI_NO_INLINE void evaluate(Position const& start, Position const& end, AdjointVector&& data) { + VectorAccess adjointWrapper(data); EventSystem::notifyTapeEvaluateListeners( cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Reverse, EventHints::Endpoint::Begin); - Wrap_internalEvaluateReverse_EvalStatements evalFunc; - Base::llfByteData.evaluateReverse(start, end, evalFunc, cast(), data); + Wrap_internalEvaluateReverse_EvalStatements evalFunc; + Base::llfByteData.evaluateReverse(start, end, evalFunc, cast(), std::forward(data)); EventSystem::notifyTapeEvaluateListeners(cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Reverse, EventHints::Endpoint::End); } /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::evaluate() - template - CODI_NO_INLINE void evaluateForward(Position const& start, Position const& end, Adjoint* data) { - VectorAccess adjointWrapper(data); + template + CODI_NO_INLINE void evaluateForward(Position const& start, Position const& end, AdjointVector&& data) { + VectorAccess adjointWrapper(data); EventSystem::notifyTapeEvaluateListeners( cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Forward, EventHints::Endpoint::Begin); - Wrap_internalEvaluateForward_EvalStatements evalFunc; - Base::llfByteData.evaluateForward(start, end, evalFunc, cast(), data); + Wrap_internalEvaluateForward_EvalStatements evalFunc; + Base::llfByteData.evaluateForward(start, end, evalFunc, cast(), std::forward(data)); EventSystem::notifyTapeEvaluateListeners(cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Forward, EventHints::Endpoint::End); } + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::getInternalAdjoints() + CODI_INLINE decltype(adjoints.data()) getInternalAdjoints() { + return adjoints.data(); + } + /// @} /*******************************************************************************/ /// @name Functions from DataManagementTapeInterface @@ -674,14 +681,21 @@ namespace codi { } /// \copydoc codi::DataManagementTapeInterface::createVectorAccess() - VectorAccess* createVectorAccess() { + VectorAccess* createVectorAccess() { return createVectorAccessCustomAdjoints(adjoints.data()); } /// \copydoc codi::DataManagementTapeInterface::createVectorAccessCustomAdjoints() + template + VectorAccess* createVectorAccessCustomAdjoints(AdjointVector&& data) { + return new VectorAccess(data); + } + + /// \copydoc codi::DataManagementTapeInterface::createVectorAccessCustomAdjoints() + ///
Specialization for pointers passed as lvalues. Ensures that the pointer is copied, not referenced. template - VectorAccess* createVectorAccessCustomAdjoints(Adjoint* data) { - return new VectorAccess(data); + VectorAccess* createVectorAccessCustomAdjoints(Adjoint* data) { + return new VectorAccess(data); } /// \copydoc codi::DataManagementTapeInterface::deleteVectorAccess() @@ -821,12 +835,24 @@ namespace codi { evaluate(start, end, adjointsManagement); } + /// \copydoc codi::PreaccumulationEvaluationTapeInterface::evaluateKeepState() + template + void evaluateKeepState(Position const& start, Position const& end, AdjointVector&& data) { + evaluate(start, end, std::forward(data)); + } + /// \copydoc codi::PreaccumulationEvaluationTapeInterface::evaluateForwardKeepState() void evaluateForwardKeepState(Position const& start, Position const& end, AdjointsManagement adjointsManagement = AdjointsManagement::Automatic) { evaluateForward(start, end, adjointsManagement); } + /// \copydoc codi::PreaccumulationEvaluationTapeInterface::evaluateForwardKeepState() + template + void evaluateForwardKeepState(Position const& start, Position const& end, AdjointVector&& data) { + evaluateForward(start, end, std::forward(data)); + } + /// @} /*******************************************************************************/ /// @name Functions from PrimalEvaluationTapeInterface diff --git a/include/codi/tapes/jacobianLinearTape.hpp b/include/codi/tapes/jacobianLinearTape.hpp index e46ce4e9..edcdd001 100644 --- a/include/codi/tapes/jacobianLinearTape.hpp +++ b/include/codi/tapes/jacobianLinearTape.hpp @@ -42,6 +42,7 @@ #include "../expressions/logic/compileTimeTraversalLogic.hpp" #include "../expressions/logic/traversalLogic.hpp" #include "../misc/macros.hpp" +#include "../traits/adjointVectorTraits.hpp" #include "../traits/expressionTraits.hpp" #include "data/chunk.hpp" #include "indices/linearIndexManager.hpp" @@ -105,6 +106,18 @@ namespace codi { } } + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::clearCustomAdjoints + template + void clearCustomAdjoints(Position const& start, Position const& end, AdjointVector&& data) { + using IndexPosition = CODI_DD(typename IndexManager::Position, int); + IndexPosition startIndex = this->llfByteData.template extractPosition(start); + IndexPosition endIndex = this->llfByteData.template extractPosition(end); + + for (IndexPosition curPos = endIndex + 1; curPos <= startIndex; curPos += 1) { + data[curPos] = AdjointVectorTraits::Gradient(); + } + } + protected: /// \copydoc codi::JacobianBaseTape::pushStmtData

@@ -116,10 +129,10 @@ namespace codi { } /// \copydoc codi::JacobianBaseTape::internalEvaluateForward_EvalStatements - template + template CODI_INLINE static void internalEvaluateForward_EvalStatements( /* data from call */ - JacobianLinearTape& tape, Adjoint* adjointVector, + JacobianLinearTape& tape, AdjointVector&& adjointVector, /* data from low level function byte data vector */ size_t& curLLFByteDataPos, size_t const& endLLFByteDataPos, char* dataPtr, /* data from low level function info data vector */ @@ -134,7 +147,9 @@ namespace codi { size_t const& startAdjointPos, size_t const& endAdjointPos) { CODI_UNUSED(endJacobianPos, endStmtPos, endLLFByteDataPos, endLLFInfoDataPos); - typename Base::template VectorAccess vectorAccess(adjointVector); + using Adjoint = AdjointVectorTraits::Gradient; + + typename Base::template VectorAccess vectorAccess(adjointVector); size_t curAdjointPos = startAdjointPos; @@ -162,10 +177,10 @@ namespace codi { } /// \copydoc codi::JacobianBaseTape::internalEvaluateReverse_EvalStatements - template + template CODI_INLINE static void internalEvaluateReverse_EvalStatements( /* data from call */ - JacobianLinearTape& tape, Adjoint* adjointVector, + JacobianLinearTape& tape, AdjointVector&& adjointVector, /* data from low level function byte data vector */ size_t& curLLFByteDataPos, size_t const& endLLFByteDataPos, char* dataPtr, /* data from low level function info data vector */ @@ -180,7 +195,9 @@ namespace codi { size_t const& startAdjointPos, size_t const& endAdjointPos) { CODI_UNUSED(endJacobianPos, endStmtPos, endLLFByteDataPos, endLLFInfoDataPos); - typename Base::template VectorAccess vectorAccess(adjointVector); + using Adjoint = AdjointVectorTraits::Gradient; + + typename Base::template VectorAccess vectorAccess(adjointVector); size_t curAdjointPos = startAdjointPos; diff --git a/include/codi/tapes/jacobianReuseTape.hpp b/include/codi/tapes/jacobianReuseTape.hpp index 4ef2145d..8b146a41 100644 --- a/include/codi/tapes/jacobianReuseTape.hpp +++ b/include/codi/tapes/jacobianReuseTape.hpp @@ -118,6 +118,21 @@ namespace codi { } } + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::clearCustomAdjoints + template + void clearCustomAdjoints(Position const& start, Position const& end, AdjointVector&& data) { + auto clearFunc = [&data](Identifier* index, Config::ArgumentSize* stmtSize) { + CODI_UNUSED(stmtSize); + data[*index] = Gradient(); + }; + + using StmtPosition = typename StatementData::Position; + StmtPosition startStmt = this->llfByteData.template extractPosition(start); + StmtPosition endStmt = this->llfByteData.template extractPosition(end); + + this->statementData.forEachReverse(startStmt, endStmt, clearFunc); + } + /// @} protected: @@ -133,10 +148,10 @@ namespace codi { } /// \copydoc codi::JacobianBaseTape::internalEvaluateForward_EvalStatements - template + template CODI_INLINE static void internalEvaluateForward_EvalStatements( /* data from call */ - JacobianReuseTape& tape, Adjoint* adjointVector, + JacobianReuseTape& tape, AdjointVector&& adjointVector, /* data from low level function byte data vector */ size_t& curLLFByteDataPos, size_t const& endLLFByteDataPos, char* dataPtr, /* data from low level function info data vector */ @@ -150,7 +165,9 @@ namespace codi { Config::ArgumentSize const* const numberOfJacobians) { CODI_UNUSED(endJacobianPos, endLLFByteDataPos, endLLFInfoDataPos); - typename Base::template VectorAccess vectorAccess(adjointVector); + using Adjoint = AdjointVectorTraits::Gradient; + + typename Base::template VectorAccess vectorAccess(adjointVector); while (curStmtPos < endStmtPos) CODI_Likely { Config::ArgumentSize const argsSize = numberOfJacobians[curStmtPos]; @@ -160,7 +177,8 @@ namespace codi { tape, true, curLLFByteDataPos, dataPtr, curLLFInfoDataPos, tokenPtr, dataSizePtr, &vectorAccess); } else CODI_Likely { Adjoint lhsAdjoint = Adjoint(); - Base::incrementTangents(adjointVector, lhsAdjoint, argsSize, curJacobianPos, rhsJacobians, rhsIdentifiers); + Base::template incrementTangents(adjointVector, lhsAdjoint, argsSize, curJacobianPos, + rhsJacobians, rhsIdentifiers); adjointVector[lhsIdentifiers[curStmtPos]] = lhsAdjoint; @@ -174,10 +192,10 @@ namespace codi { } /// \copydoc codi::JacobianBaseTape::internalEvaluateReverse_EvalStatements - template + template CODI_INLINE static void internalEvaluateReverse_EvalStatements( /* data from call */ - JacobianReuseTape& tape, Adjoint* adjointVector, + JacobianReuseTape& tape, AdjointVector&& adjointVector, /* data from low level function byte data vector */ size_t& curLLFByteDataPos, size_t const& endLLFByteDataPos, char* dataPtr, /* data from low level function info data vector */ @@ -191,7 +209,9 @@ namespace codi { Config::ArgumentSize const* const numberOfJacobians) { CODI_UNUSED(endJacobianPos, endLLFByteDataPos, endLLFInfoDataPos); - typename Base::template VectorAccess vectorAccess(adjointVector); + using Adjoint = AdjointVectorTraits::Gradient; + + typename Base::template VectorAccess vectorAccess(adjointVector); while (curStmtPos > endStmtPos) CODI_Likely { curStmtPos -= 1; diff --git a/include/codi/tapes/misc/adjointVectorAccess.hpp b/include/codi/tapes/misc/adjointVectorAccess.hpp index f58aa149..9abd51d1 100644 --- a/include/codi/tapes/misc/adjointVectorAccess.hpp +++ b/include/codi/tapes/misc/adjointVectorAccess.hpp @@ -40,6 +40,7 @@ #include "../../config.h" #include "../../misc/macros.hpp" #include "../../tools/data/direction.hpp" +#include "../../traits/adjointVectorTraits.hpp" #include "../../traits/realTraits.hpp" #include "vectorAccessInterface.hpp" @@ -51,19 +52,22 @@ namespace codi { * * The adjoint vector is used as is, it is assumed to have the correct size. No bounds checking is performed. * - * @tparam T_Real The computation type of a tape, usually chosen as ActiveType::Real. - * @tparam T_Identifier The adjoint/tangent identification of a tape, usually chosen as ActiveType::Identifier. - * @tparam T_Gradient The gradient type of a tape, usually chosen as ActiveType::Gradient. + * @tparam T_Real The computation type of a tape, usually chosen as ActiveType::Real. + * @tparam T_Identifier The adjoint/tangent identification of a tape, usually chosen as ActiveType::Identifier. + * @tparam T_AdjointVector Either a pointer type, for example Gradient*, or a reference to something that can be + * accessed like a gradient array, for example std::vector&. */ - template + template struct AdjointVectorAccess : public VectorAccessInterface { - using Real = CODI_DD(T_Real, double); ///< See AdjointVectorAccess. - using Identifier = CODI_DD(T_Identifier, int); ///< See AdjointVectorAccess. - using Gradient = CODI_DD(T_Gradient, double); ///< See AdjointVectorAccess. + public: + using Real = CODI_DD(T_Real, double); ///< See AdjointVectorAccess. + using Identifier = CODI_DD(T_Identifier, int); ///< See AdjointVectorAccess. + using Gradient = CODI_DD(AdjointVectorTraits::Gradient, double); ///< Adjoint vector entry type. + using AdjointVector = CODI_DD(T_AdjointVector, double*); ///< See AdjointVectorAccess. protected: - Gradient* adjointVector; ///< Pointer to the gradient vector. + AdjointVector adjointVector; ///< Pointer/reference to an array-accessible collection of gradients. private: @@ -74,7 +78,7 @@ namespace codi { public: /// Constructor. See interface documentation for details about the adjoint vector. - AdjointVectorAccess(Gradient* adjointVector) : adjointVector(adjointVector), lhs(), buffer() {} + AdjointVectorAccess(AdjointVector adjointVector) : adjointVector(adjointVector), lhs(), buffer() {} /*******************************************************************************/ /// @name Misc diff --git a/include/codi/tapes/misc/internalAdjointsInterface.hpp b/include/codi/tapes/misc/internalAdjointsInterface.hpp index 6d2a5a3d..24d2d284 100644 --- a/include/codi/tapes/misc/internalAdjointsInterface.hpp +++ b/include/codi/tapes/misc/internalAdjointsInterface.hpp @@ -97,8 +97,12 @@ namespace codi { /// Constant reference access to the adjoint variable identified by identifier. CODI_INLINE Gradient const& operator[](Identifier const& identifier) const; - /// Pointer to an underlying array implementation. - CODI_INLINE Gradient* data(); + /** + * @brief Return an array-like object for data access, for example a pointer to an underlying array or a reference + * to something with overloaded operator[]. + */ + CODI_DD(CODI_T(template), ) + CODI_INLINE CODI_DD(ArrayAccess, Gradient*) data(); /// Returns the number of adjoint variables. Internally, declares usage of the adjoints. CODI_INLINE size_t size() const; diff --git a/include/codi/tapes/misc/localAdjoints.hpp b/include/codi/tapes/misc/localAdjoints.hpp index accea685..4f3c3b6d 100644 --- a/include/codi/tapes/misc/localAdjoints.hpp +++ b/include/codi/tapes/misc/localAdjoints.hpp @@ -37,6 +37,7 @@ #include #include +#include "../../traits/adjointVectorTraits.hpp" #include "internalAdjointsInterface.hpp" /** \copydoc codi::Namespace */ @@ -111,4 +112,16 @@ namespace codi { /// \copydoc InternalAdjointsInterface::endUse CODI_INLINE void endUse() {} }; + +#ifndef DOXYGEN_DISABLE + + /// Specialization of AdjointVectorTraits. + namespace AdjointVectorTraits { + template + struct GradientImplementation> { + public: + using Gradient = T_Gradient; + }; + } +#endif } diff --git a/include/codi/tapes/misc/primalAdjointVectorAccess.hpp b/include/codi/tapes/misc/primalAdjointVectorAccess.hpp index c2ceffba..f1155ff4 100644 --- a/include/codi/tapes/misc/primalAdjointVectorAccess.hpp +++ b/include/codi/tapes/misc/primalAdjointVectorAccess.hpp @@ -50,17 +50,19 @@ namespace codi { * * Inherits from AdjointVectorAccess and overwrites all methods specific to the primals. * - * @tparam T_Real The computation type of a tape, usually chosen as ActiveType::Real. - * @tparam T_Identifier The adjoint/tangent identification of a tape, usually chosen as ActiveType::Identifier. - * @tparam T_Gradient The gradient type of a tape, usually chosen as ActiveType::Gradient. + * @tparam T_Real The computation type of a tape, usually chosen as ActiveType::Real. + * @tparam T_Identifier The adjoint/tangent identification of a tape, usually chosen as ActiveType::Identifier. + * @tparam T_AdjointVector Either a pointer type, for example Gradient*, or a reference to something that can be + * accessed like a gradient array, for example std::vector&. */ - template - struct PrimalAdjointVectorAccess : public AdjointVectorAccess { + template + struct PrimalAdjointVectorAccess : public AdjointVectorAccess { using Real = CODI_DD(T_Real, double); ///< See PrimalAdjointVectorAccess. using Identifier = CODI_DD(T_Identifier, int); ///< See PrimalAdjointVectorAccess. - using Gradient = CODI_DD(T_Gradient, double); ///< See PrimalAdjointVectorAccess. + using Gradient = CODI_DD(AdjointVectorTraits::Gradient, double); ///< Adjoint vector entry type. + using AdjointVector = CODI_DD(T_AdjointVector, double*); ///< See PrimalAdjointVectorAccess. - using Base = AdjointVectorAccess; ///< Base class abbreviation. + using Base = AdjointVectorAccess; ///< Base class abbreviation. private: @@ -69,7 +71,7 @@ namespace codi { public: /// Constructor. See interface documentation for details about the vectors. - PrimalAdjointVectorAccess(Gradient* adjointVector, Real* primalVector) + PrimalAdjointVectorAccess(AdjointVector adjointVector, Real* primalVector) : Base(adjointVector), primalVector(primalVector) {} /*******************************************************************************/ diff --git a/include/codi/tapes/misc/threadSafeGlobalAdjoints.hpp b/include/codi/tapes/misc/threadSafeGlobalAdjoints.hpp index 2ab69293..cb846474 100644 --- a/include/codi/tapes/misc/threadSafeGlobalAdjoints.hpp +++ b/include/codi/tapes/misc/threadSafeGlobalAdjoints.hpp @@ -35,6 +35,7 @@ #pragma once #include "../../tools/parallel/parallelToolbox.hpp" +#include "../../traits/adjointVectorTraits.hpp" #include "internalAdjointsInterface.hpp" /** \copydoc codi::Namespace */ @@ -139,4 +140,16 @@ namespace codi { template typename CODI_DD(ParallelToolbox, CODI_DEFAULT_PARALLEL_TOOLBOX)::ReadWriteMutex ThreadSafeGlobalAdjoints::adjointsMutex; + +#ifndef DOXYGEN_DISABLE + + /// Specialization of AdjointVectorTraits. + namespace AdjointVectorTraits { + template + struct GradientImplementation> { + public: + using Gradient = T_Gradient; + }; + } +#endif } diff --git a/include/codi/tapes/primalValueBaseTape.hpp b/include/codi/tapes/primalValueBaseTape.hpp index 3172e734..a5fc0482 100644 --- a/include/codi/tapes/primalValueBaseTape.hpp +++ b/include/codi/tapes/primalValueBaseTape.hpp @@ -164,9 +164,9 @@ namespace codi { using NestedPosition = typename ConstantValueData::Position; ///< See PrimalValueTapeTypes. using Position = typename Base::Position; ///< See TapeTypesInterface. - template - using VectorAccess = - PrimalAdjointVectorAccess; ///< Vector access type generated by this tape. + /// Vector access type generated by this tape. + template + using VectorAccess = PrimalAdjointVectorAccess; static bool constexpr AllowJacobianOptimization = false; ///< See InternalStatementRecordingTapeInterface. static bool constexpr HasPrimalValues = true; ///< See PrimalEvaluationTapeInterface. @@ -588,14 +588,14 @@ namespace codi { */ /// Select the configured adjoint vector, see codi::Config::VariableAdjointInterfaceInPrimalTapes. - template - ADJOINT_VECTOR_TYPE* selectAdjointVector(VectorAccess* vectorAccess, Adjoint* data) { + template + ADJOINT_VECTOR_TYPE* selectAdjointVector(VectorAccess* vectorAccess, AdjointVector data) { CODI_UNUSED(vectorAccess, data); #if CODI_VariableAdjointInterfaceInPrimalTapes return vectorAccess; #else - CODI_STATIC_ASSERT(CODI_T(std::is_same::value), + CODI_STATIC_ASSERT(CODI_T(std::is_same::type, Gradient*>::value), "Please enable 'CODI_VariableAdjointInterfaceInPrimalTapes' in order" " to use custom adjoint vectors in the primal value tapes."); @@ -627,8 +627,14 @@ namespace codi { CODI_WRAP_FUNCTION(Wrap_internalEvaluateForward_EvalStatements, Impl::internalEvaluateForward_EvalStatements); /// Internal method for the forward evaluation of the whole tape. - template - CODI_NO_INLINE void internalEvaluateForward(Position const& start, Position const& end, Adjoint* data) { + template + CODI_NO_INLINE void internalEvaluateForward(Position const& start, Position const& end, AdjointVector&& data) { + CODI_STATIC_ASSERT( + Config::VariableAdjointInterfaceInPrimalTapes || + CODI_T(std::is_same::type, Gradient*>::value), + "Please enable 'CODI_VariableAdjointInterfaceInPrimalTapes' in order" + " to use custom adjoint vectors in the primal value tapes."); + std::vector primalsCopy(0); Real* primalData = primals.data(); @@ -637,9 +643,9 @@ namespace codi { primalData = primalsCopy.data(); } - VectorAccess vectorAccess(data, primalData); + VectorAccess vectorAccess(data, primalData); - ADJOINT_VECTOR_TYPE* dataVector = selectAdjointVector(&vectorAccess, data); + ADJOINT_VECTOR_TYPE* dataVector = selectAdjointVector(&vectorAccess, data); EventSystem::notifyTapeEvaluateListeners( cast(), start, end, &vectorAccess, EventHints::EvaluationKind::Forward, EventHints::Endpoint::Begin); @@ -675,8 +681,14 @@ namespace codi { CODI_WRAP_FUNCTION(Wrap_internalEvaluateReverse_EvalStatements, Impl::internalEvaluateReverse_EvalStatements); /// Internal method for the reverse evaluation of the whole tape. - template - CODI_INLINE void internalEvaluateReverse(Position const& start, Position const& end, Adjoint* data) { + template + CODI_INLINE void internalEvaluateReverse(Position const& start, Position const& end, AdjointVector&& data) { + CODI_STATIC_ASSERT( + Config::VariableAdjointInterfaceInPrimalTapes || + CODI_T(std::is_same::type, Gradient*>::value), + "Please enable 'CODI_VariableAdjointInterfaceInPrimalTapes' in order" + " to use custom adjoint vectors in the primal value tapes."); + Real* primalData = primals.data(); if (copyPrimal) { @@ -684,9 +696,9 @@ namespace codi { primalData = primalsCopy.data(); } - VectorAccess vectorAccess(data, primalData); + VectorAccess vectorAccess(data, primalData); - ADJOINT_VECTOR_TYPE* dataVector = selectAdjointVector(&vectorAccess, data); + ADJOINT_VECTOR_TYPE* dataVector = selectAdjointVector(&vectorAccess, data); EventSystem::notifyTapeEvaluateListeners( cast(), start, end, &vectorAccess, EventHints::EvaluationKind::Reverse, EventHints::Endpoint::Begin); @@ -706,15 +718,20 @@ namespace codi { using Base::evaluate; /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::evaluate() - template - CODI_INLINE void evaluate(Position const& start, Position const& end, Adjoint* data) { - internalEvaluateReverse(start, end, data); + template + CODI_INLINE void evaluate(Position const& start, Position const& end, AdjointVector&& data) { + internalEvaluateReverse(start, end, std::forward(data)); } /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::evaluateForward() - template - CODI_INLINE void evaluateForward(Position const& start, Position const& end, Adjoint* data) { - internalEvaluateForward(start, end, data); + template + CODI_INLINE void evaluateForward(Position const& start, Position const& end, AdjointVector&& data) { + internalEvaluateForward(start, end, std::forward(data)); + } + + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::getInternalAdjoints() + CODI_INLINE Gradient* getInternalAdjoints() { + return adjoints.data(); } /// @} @@ -814,14 +831,21 @@ namespace codi { } /// \copydoc codi::DataManagementTapeInterface::createVectorAccess() - VectorAccess* createVectorAccess() { + VectorAccess* createVectorAccess() { return createVectorAccessCustomAdjoints(adjoints.data()); } /// \copydoc codi::DataManagementTapeInterface::createVectorAccessCustomAdjoints() + template + VectorAccess* createVectorAccessCustomAdjoints(AdjointVector&& data) { + return new VectorAccess(data, primals.data()); + } + + /// \copydoc codi::DataManagementTapeInterface::createVectorAccessCustomAdjoints() + ///
Overload for pointers passed as lvalues. Ensures that the pointer is copied, not referenced. template - VectorAccess* createVectorAccessCustomAdjoints(Adjoint* data) { - return new VectorAccess(data, primals.data()); + VectorAccess* createVectorAccessCustomAdjoints(Adjoint* data) { + return new VectorAccess(data, primals.data()); } /// \copydoc codi::DataManagementTapeInterface::deleteVectorAccess() @@ -1100,7 +1124,13 @@ namespace codi { codiAssert(indexManager.get().getLargestCreatedIndex() < (Identifier)adjoints.size()); - internalEvaluateReverse(start, end, adjoints.data()); + evaluateKeepState(start, end, adjoints.data()); + } + + /// \copydoc codi::PreaccumulationEvaluationTapeInterface::evaluateKeepState() + template + void evaluateKeepState(Position const& start, Position const& end, AdjointVector&& data) { + internalEvaluateReverse(start, end, std::forward(data)); if (!TapeTypes::IsLinearIndexHandler) { evaluatePrimal(end, start); @@ -1118,11 +1148,17 @@ namespace codi { codiAssert(indexManager.get().getLargestCreatedIndex() < (Identifier)adjoints.size()); + evaluateForwardKeepState(start, end, adjoints.data()); + } + + /// \copydoc codi::PreaccumulationEvaluationTapeInterface::evaluateForwardKeepState() + template + void evaluateForwardKeepState(Position const& start, Position const& end, AdjointVector&& data) { if (!TapeTypes::IsLinearIndexHandler) { cast().internalResetPrimalValues(end); } - internalEvaluateForward(start, end, adjoints.data()); + internalEvaluateForward(start, end, std::forward(data)); } protected: @@ -1146,7 +1182,7 @@ namespace codi { /// \copydoc codi::PrimalEvaluationTapeInterface::evaluatePrimal() CODI_NO_INLINE void evaluatePrimal(Position const& start, Position const& end) { // TODO: implement primal value only accessor - PrimalAdjointVectorAccess primalAdjointAccess(adjoints.data(), primals.data()); + PrimalAdjointVectorAccess primalAdjointAccess(adjoints.data(), primals.data()); EventSystem::notifyTapeEvaluateListeners(cast(), start, end, &primalAdjointAccess, EventHints::EvaluationKind::Primal, EventHints::Endpoint::Begin); diff --git a/include/codi/tapes/primalValueLinearTape.hpp b/include/codi/tapes/primalValueLinearTape.hpp index 9ca9c95a..c48845ad 100644 --- a/include/codi/tapes/primalValueLinearTape.hpp +++ b/include/codi/tapes/primalValueLinearTape.hpp @@ -105,6 +105,18 @@ namespace codi { } } + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::clearCustomAdjoints + template + void clearCustomAdjoints(Position const& start, Position const& end, AdjointVector data) { + using IndexPosition = CODI_DD(typename IndexManager::Position, int); + IndexPosition startIndex = this->llfByteData.template extractPosition(start); + IndexPosition endIndex = this->llfByteData.template extractPosition(end); + + for (IndexPosition curPos = endIndex + 1; curPos <= startIndex; curPos += 1) { + data[curPos] = AdjointVectorTraits::Gradient(); + } + } + protected: /// \copydoc codi::PrimalValueBaseTape::internalEvaluateForward_EvalStatements @@ -133,7 +145,7 @@ namespace codi { size_t curAdjointPos = startAdjointPos; #if !CODI_VariableAdjointInterfaceInPrimalTapes - typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); + typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); #endif while (curAdjointPos < endAdjointPos) CODI_Likely { @@ -202,7 +214,7 @@ namespace codi { size_t curAdjointPos = startAdjointPos; - typename Base::template VectorAccess vectorAccess(nullptr, primalVector); + typename Base::template VectorAccess vectorAccess(nullptr, primalVector); while (curAdjointPos < endAdjointPos) CODI_Likely { curAdjointPos += 1; @@ -253,7 +265,7 @@ namespace codi { size_t curAdjointPos = startAdjointPos; #if !CODI_VariableAdjointInterfaceInPrimalTapes - typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); + typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); #endif while (curAdjointPos > endAdjointPos) CODI_Likely { diff --git a/include/codi/tapes/primalValueReuseTape.hpp b/include/codi/tapes/primalValueReuseTape.hpp index 81b8d1dc..737756a5 100644 --- a/include/codi/tapes/primalValueReuseTape.hpp +++ b/include/codi/tapes/primalValueReuseTape.hpp @@ -110,6 +110,23 @@ namespace codi { this->statementData.forEachReverse(startStmt, endStmt, clearFunc); } + /// \copydoc codi::CustomAdjointVectorEvaluationTapeInterface::clearCustomAdjoints + template + void clearCustomAdjoints(Position const& start, Position const& end, AdjointVector data) { + auto clearFunc = [&data](Identifier* lhsIndex, Config::ArgumentSize* passiveArgs, Real* oldPrimal, + EvalHandle* evalHandle) { + CODI_UNUSED(passiveArgs, oldPrimal, evalHandle); + + data[*lhsIndex] = AdjointVectorTraits::Gradient(); + }; + + using StmtPosition = typename StatementData::Position; + StmtPosition startStmt = this->llfByteData.template extractPosition(start); + StmtPosition endStmt = this->llfByteData.template extractPosition(end); + + this->statementData.forEachReverse(startStmt, endStmt, clearFunc); + } + protected: /// \copydoc codi::PrimalValueBaseTape::internalEvaluateForward_EvalStatements @@ -134,7 +151,7 @@ namespace codi { CODI_UNUSED(endLLFByteDataPos, endLLFInfoDataPos, endConstantPos, endPassivePos, endRhsIdentifiersPos); #if !CODI_VariableAdjointInterfaceInPrimalTapes - typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); + typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); #endif while (curStatementPos < endStatementPos) CODI_Likely { @@ -197,7 +214,7 @@ namespace codi { EvalHandle const* const stmtEvalhandle) { CODI_UNUSED(endLLFByteDataPos, endLLFInfoDataPos, endConstantPos, endPassivePos, endRhsIdentifiersPos); - typename Base::template VectorAccess vectorAccess(nullptr, primalVector); + typename Base::template VectorAccess vectorAccess(nullptr, primalVector); while (curStatementPos < endStatementPos) CODI_Likely { Config::ArgumentSize nPassiveValues = numberOfPassiveArguments[curStatementPos]; @@ -243,7 +260,7 @@ namespace codi { CODI_UNUSED(endLLFByteDataPos, endLLFInfoDataPos, endConstantPos, endPassivePos, endRhsIdentifiersPos); #if !CODI_VariableAdjointInterfaceInPrimalTapes - typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); + typename Base::template VectorAccess vectorAccess(adjointVector, primalVector); #endif while (curStatementPos > endStatementPos) CODI_Likely { diff --git a/include/codi/tools/algorithms.hpp b/include/codi/tools/algorithms.hpp index 462cf099..f9e70be0 100644 --- a/include/codi/tools/algorithms.hpp +++ b/include/codi/tools/algorithms.hpp @@ -38,6 +38,7 @@ #include "../expressions/lhsExpressionInterface.hpp" #include "../misc/exceptions.hpp" #include "../tapes/misc/tapeParameters.hpp" +#include "../traits/adjointVectorTraits.hpp" #include "../traits/gradientTraits.hpp" #include "data/dummy.hpp" #include "data/jacobian.hpp" @@ -142,77 +143,99 @@ namespace codi { Identifier const* input, size_t const inputSize, Identifier const* output, size_t const outputSize, Jac& jac, AdjointsManagement adjointsManagement = AdjointsManagement::Automatic) { - size_t constexpr gradDim = GT::dim; - // internally, automatic management is implemented in an optimized way that uses manual management if (AdjointsManagement::Automatic == adjointsManagement) { tape.resizeAdjointVector(); tape.beginUseAdjointVector(); } + computeJacobianCustomAdjoints(tape, start, end, input, inputSize, output, outputSize, jac, + tape.getInternalAdjoints()); + + if (AdjointsManagement::Automatic == adjointsManagement) { + tape.endUseAdjointVector(); + } + } + + // clang-format off + /** + * @brief Compute the Jacobian with multiple tape sweeps using a custom adjoint vector. + * + * See \ref computeJacobian(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac& jac, AdjointsManagement) + * for further details. + * + * @tparam Adjoint See CustomAdjointVectorEvaluationTapeInterface. + * @tparam AdjointVector See CustomAdjointVectorEvaluationTapeInterface. + */ + // clang-format on + template + static CODI_INLINE void computeJacobianCustomAdjoints(Tape& tape, Position const& start, Position const& end, + Identifier const* input, size_t const inputSize, + Identifier const* output, size_t const outputSize, Jac& jac, + AdjointVector&& adjoints) { + using Adjoint = AdjointVectorTraits::Gradient; + + using CustomGT = GradientTraits::TraitsImplementation; + + size_t constexpr gradDim = CustomGT::dim; + EvaluationType evalType = getEvaluationChoice(inputSize, outputSize); if (EvaluationType::Forward == evalType) { for (size_t j = 0; j < inputSize; j += gradDim) { - setGradientOnIdentifier(tape, j, input, inputSize, typename GT::Real(1.0), AdjointsManagement::Manual); + setGradientOnIdentifierCustomAdjoints(j, input, inputSize, typename CustomGT::Real(1.0), adjoints); if (keepState) { - tape.evaluateForwardKeepState(start, end, AdjointsManagement::Manual); + tape.evaluateForwardKeepState(start, end, std::forward(adjoints)); } else { - tape.evaluateForward(start, end, AdjointsManagement::Manual); + tape.evaluateForward(start, end, std::forward(adjoints)); } for (size_t i = 0; i < outputSize; i += 1) { for (size_t curDim = 0; curDim < gradDim && j + curDim < inputSize; curDim += 1) { - jac(outputSize - i - 1, j + curDim) = - GT::at(tape.getGradient(output[outputSize - i - 1], AdjointsManagement::Manual), curDim); + jac(outputSize - i - 1, j + curDim) = CustomGT::at(adjoints[output[outputSize - i - 1]], curDim); if (Gradient() != output[i]) { - GT::at(tape.gradient(output[outputSize - i - 1], AdjointsManagement::Manual), curDim) = - typename GT::Real(); + CustomGT::at(adjoints[output[outputSize - i - 1]], curDim) = typename GT::Real(); } } } - setGradientOnIdentifier(tape, j, input, inputSize, typename GT::Real(), AdjointsManagement::Manual); + setGradientOnIdentifierCustomAdjoints(j, input, inputSize, typename CustomGT::Real(), adjoints); } - tape.clearAdjoints(end, start, AdjointsManagement::Manual); + tape.clearCustomAdjoints(end, start, std::forward(adjoints)); } else if (EvaluationType::Reverse == evalType) { for (size_t i = 0; i < outputSize; i += gradDim) { - setGradientOnIdentifier(tape, i, output, outputSize, typename GT::Real(1.0), AdjointsManagement::Manual); + setGradientOnIdentifierCustomAdjoints(i, output, outputSize, typename CustomGT::Real(1.0), adjoints); if (keepState) { - tape.evaluateKeepState(end, start, AdjointsManagement::Manual); + tape.evaluateKeepState(end, start, std::forward(adjoints)); } else { - tape.evaluate(end, start, AdjointsManagement::Manual); + tape.evaluate(end, start, std::forward(adjoints)); } for (size_t j = 0; j < inputSize; j += 1) { for (size_t curDim = 0; curDim < gradDim && i + curDim < outputSize; curDim += 1) { - jac(i + curDim, j) = GT::at(tape.getGradient(input[j], AdjointsManagement::Manual), curDim); - GT::at(tape.gradient(input[j], AdjointsManagement::Manual), curDim) = typename GT::Real(); + jac(i + curDim, j) = CustomGT::at(adjoints[input[j]], curDim); + CustomGT::at(adjoints[input[j]], curDim) = typename CustomGT::Real(); } } - setGradientOnIdentifier(tape, i, output, outputSize, typename GT::Real(), AdjointsManagement::Manual); + setGradientOnIdentifierCustomAdjoints(i, output, outputSize, typename CustomGT::Real(), adjoints); if (!Config::ReversalZeroesAdjoints) { - tape.clearAdjoints(end, start, AdjointsManagement::Manual); + tape.clearCustomAdjoints(end, start, std::forward(adjoints)); } } } else { CODI_EXCEPTION("Evaluation mode not implemented. Mode is: %d.", (int)evalType); } - - if (AdjointsManagement::Automatic == adjointsManagement) { - tape.endUseAdjointVector(); - } } // clang-format off - /// \copybrief computeJacobian(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac& jac, AdjointsManagement) + /// \copybrief computeJacobian(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac&, AdjointsManagement) /// \n This method uses the global tape for the Jacobian evaluation. - /// \copydetails computeJacobian(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac& jac, AdjointsManagement) + /// \copydetails computeJacobian(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac&, AdjointsManagement) // clang-format on template static CODI_INLINE void computeJacobian(Position const& start, Position const& end, Identifier const* input, @@ -222,6 +245,20 @@ namespace codi { computeJacobian(Type::getTape(), start, end, input, inputSize, output, outputSize, jac, adjointsManagement); } + // clang-format off + /// \copybrief computeJacobianCustomAdjoints(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac&, AdjointVector&&) + /// \n This method uses the global tape for the Jacobian evaluation. + /// \copydetails computeJacobianCustomAdjoints(Tape&, Position const&, Position const&, Identifier const*, size_t const, Identifier const*, size_t const, Jac&, AdjointVector&&) + // clang-format on + template + static CODI_INLINE void computeJacobianCustomAdjoints(Position const& start, Position const& end, + Identifier const* input, size_t const inputSize, + Identifier const* output, size_t const outputSize, Jac& jac, + AdjointVector&& adjoints) { + computeJacobianCustomAdjoints(Type::getTape(), start, end, input, inputSize, output, + outputSize, jac, std::forward(adjoints)); + } + /** * @brief Compute the Hessian with multiple tape sweeps. * @@ -558,6 +595,18 @@ namespace codi { } } + template + static CODI_INLINE void setGradientOnIdentifierCustomAdjoints(size_t const pos, Identifier const* identifiers, + size_t const size, T value, Adjoints& adjoints) { + size_t constexpr gradDim = GT::dim; + + for (size_t curDim = 0; curDim < gradDim && pos + curDim < size; curDim += 1) { + if (CODI_ENABLE_CHECK(ActiveChecks, 0 != identifiers[pos + curDim])) { + GT::at(adjoints[identifiers[pos + curDim]], curDim) = value; + } + } + } + /// Sets the gradient for 2nd order vector modes. Seeds the next GT2nd:dim dimensions. template static CODI_INLINE void setGradient2ndOnIdentifier(Tape& tape, size_t const pos, Identifier const* identifiers, diff --git a/include/codi/tools/data/customAdjoints.hpp b/include/codi/tools/data/customAdjoints.hpp new file mode 100644 index 00000000..9bb0795a --- /dev/null +++ b/include/codi/tools/data/customAdjoints.hpp @@ -0,0 +1,90 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include + +#include "../../misc/macros.hpp" +#include "../../traits/adjointVectorTraits.hpp" + +/** \copydoc codi::Namespace */ +namespace codi { + + /** + * @brief Implementation of adjoints via a map. + * + * Useful for the evaluation of tape parts with non-contiguous, far-apart identifiers. Can be used as custom adjoints + * for tape evaluations, see CustomAdjointVectorEvaluationTapeInterface. Can also be used for Jacobian computations + * with custom adjoints, see Algorithms::computeJacobianCustomAdjoints(). + * + * The implementation ensures that any identifier can be used to access the map, both in constant and non-constant + * calling contexts. Entries that do not exist yet are created on the fly and default-initialized. + * + * @tparam T_Identifier Identifier type, usually chosen as Tape::Identifier. + * @tparam T_Gradient Gradient type, corresponds to the Adjoint template parameter in the referred-to functions. + */ + template + struct MappedAdjoints { + public: + using Identifier = CODI_DD(T_Identifier, int); ///< See MappedAdjoints. + using Gradient = CODI_DD(T_Gradient, double); ///< See MappedAdjoints. + + /// Internal map implementation, kept public for flexibility. + /// Mutable so that access in constant call contexts does not prevent the insertion of new elements. + mutable std::map adjoints; + + /// Access operator in constant call contexts. + Gradient const& operator[](Identifier const& i) const { + return adjoints[i]; + } + + /// Access operator in non-constant call contexts. + Gradient& operator[](Identifier const& i) { + return adjoints[i]; + } + }; + +#ifndef DOXYGEN_DISABLE + // Specialize adjoint vector traits. + namespace AdjointVectorTraits { + template + struct GradientImplementation> { + public: + using Gradient = T_Gradient; + }; + } +#endif +} diff --git a/include/codi/tools/helpers/customAdjointVectorHelper.hpp b/include/codi/tools/helpers/customAdjointVectorHelper.hpp index 3494f8ef..fb747bc4 100644 --- a/include/codi/tools/helpers/customAdjointVectorHelper.hpp +++ b/include/codi/tools/helpers/customAdjointVectorHelper.hpp @@ -171,7 +171,8 @@ namespace codi { Gradient zeroValue; ///< Temporary zero value. Gradient const constZeroValue; ///< Temporary constant zero value. - AdjointVectorAccess* adjointInterface; ///< Last created adjoint interface. + /// Last created adjoint interface. + AdjointVectorAccess* adjointInterface; public: @@ -226,7 +227,7 @@ namespace codi { } checkAdjointVectorSize(); - adjointInterface = new AdjointVectorAccess(adjointVector.data()); + adjointInterface = new AdjointVectorAccess(adjointVector.data()); return adjointInterface; } diff --git a/include/codi/tools/helpers/preaccumulationHelper.hpp b/include/codi/tools/helpers/preaccumulationHelper.hpp index 77de6db4..e25cde58 100644 --- a/include/codi/tools/helpers/preaccumulationHelper.hpp +++ b/include/codi/tools/helpers/preaccumulationHelper.hpp @@ -45,6 +45,7 @@ #include "../../traits/gradientTraits.hpp" #include "../../traits/tapeTraits.hpp" #include "../algorithms.hpp" +#include "../data/customAdjoints.hpp" #include "../data/jacobian.hpp" /** \copydoc codi::Namespace */ @@ -157,7 +158,8 @@ namespace codi { } tape.setPassive(); - doPreaccumulation(); + computeJacobian(); + storeJacobian(); tape.setActive(); if (storeAdjoints) { @@ -168,6 +170,24 @@ namespace codi { EventSystem::notifyPreaccFinishListeners(tape); } + /// Finish the preaccumulation region and perform the preaccumulation. Creates adjoints locally instead of using + /// adjoints from the tape. See `addOutput()` for outputs. + template + void finishLocalAdjoints(Outputs&... outputs) { + Tape& tape = Type::getTape(); + + if (tape.isActive()) { + addOutputRecursive(outputs...); + + tape.setPassive(); + computeJacobianLocalAdjoints(); + storeJacobian(); + tape.setActive(); + } + + EventSystem::notifyPreaccFinishListeners(tape); + } + private: void addInputLogic(Type const& input) { @@ -233,14 +253,18 @@ namespace codi { } } - void doPreaccumulation() { - // Perform the accumulation of the tape part. - Tape& tape = Type::getTape(); - - Position endPos = tape.getPosition(); + void resizeJacobian() { if (jacobian.getM() != outputData.size() || jacobian.getN() != inputData.size()) { jacobian.resize(outputData.size(), inputData.size()); } + } + + void computeJacobian() { + // Perform the accumulation of the tape part. + Tape& tape = Type::getTape(); + Position endPos = tape.getPosition(); + + resizeJacobian(); // Manage adjoints manually to reduce the impact of locking on the performance. tape.resizeAdjointVector(); @@ -250,10 +274,31 @@ namespace codi { outputData.data(), outputData.size(), jacobian, AdjointsManagement::Manual); - // Store the Jacobian matrix. tape.resetTo(startPos, true, AdjointsManagement::Manual); tape.endUseAdjointVector(); + } + + void computeJacobianLocalAdjoints() { + // Perform the accumulation of the tape part. + Tape& tape = Type::getTape(); + Position endPos = tape.getPosition(); + + resizeJacobian(); + + // Create a local map with adjoints. + using LocalMappedAdjoints = MappedAdjoints; + LocalMappedAdjoints mappedAdjoints; + + Algorithms::computeJacobianCustomAdjoints(startPos, endPos, inputData.data(), inputData.size(), + outputData.data(), outputData.size(), jacobian, + mappedAdjoints); + + tape.resetTo(startPos, false); + } + + void storeJacobian() { + Tape& tape = Type::getTape(); for (size_t curOut = 0; curOut < outputData.size(); ++curOut) { Type& value = *outputValues[curOut]; @@ -357,6 +402,13 @@ namespace codi { CODI_UNUSED(storeAdjoints, outputs...); // Do nothing. } + + /// Does nothing. + template + void finishLocalAdjoints(Outputs&... outputs) { + CODI_UNUSED(outputs...); + // Do nothing. + } }; /// Specialize PreaccumulationHelper for forward tapes. @@ -452,6 +504,12 @@ namespace codi { } } + /// Reverts the tags on all input and output values. + template + void finishLocalAdjoints(Outputs&... outputs) { + finish(false, outputs...); + } + private: /// Terminator for the recursive implementation. diff --git a/include/codi/tools/parallel/openmp/codiOpDiLibTool.hpp b/include/codi/tools/parallel/openmp/codiOpDiLibTool.hpp index 81a57bac..1038f407 100644 --- a/include/codi/tools/parallel/openmp/codiOpDiLibTool.hpp +++ b/include/codi/tools/parallel/openmp/codiOpDiLibTool.hpp @@ -165,16 +165,13 @@ struct CoDiOpDiLibTool : public opdi::ToolInterface { std::cerr << "Warning: OpDiLib evaluation of an active tape." << std::endl; } - typename Tape::Gradient* adjoints = &tape->gradient(0); using NonAtomicGradient = codi::AtomicTraits::RemoveAtomic; using AtomicGradient = codi::OpenMPReverseAtomic; if (useAtomics) { - AtomicGradient* safeAdjoints = (AtomicGradient*)adjoints; - tape->evaluate(*start, *end, safeAdjoints); + tape->evaluate(*start, *end, reinterpret_cast(&tape->gradient(0))); } else { - NonAtomicGradient* unsafeAdjoints = (NonAtomicGradient*)adjoints; - tape->evaluate(*start, *end, unsafeAdjoints); + tape->evaluate(*start, *end, reinterpret_cast(&tape->gradient(0))); } } diff --git a/include/codi/traits/adjointVectorTraits.hpp b/include/codi/traits/adjointVectorTraits.hpp index 4ebf0d1a..6cdb2387 100644 --- a/include/codi/traits/adjointVectorTraits.hpp +++ b/include/codi/traits/adjointVectorTraits.hpp @@ -42,8 +42,8 @@ namespace codi { template struct ThreadSafeGlobalAdjoints; - /// Traits for atomic types. - namespace AdjointVectorTraits { + /// Traits for the internal adjoint variables maintained by the tape. + namespace InternalAdjointVectorTraits { /// Whether the adjoint vector is global, that is, shared among different tapes. template @@ -53,5 +53,42 @@ namespace codi { template struct IsGlobal> : std::true_type {}; #endif + + } + + /// General traits of adjoint vectors. + namespace AdjointVectorTraits { + + /** + * @brief Trait implementation to deduce the entry type from an adjoint vector type. + * + * Default implementation for STL containers. + */ + template + struct GradientImplementation { + public: + using Gradient = typename AdjointVector::value_type; ///< Type of adjoint vector entries. + }; + +#ifndef DOXYGEN_DISABLE + /// Specialization for references. + template + struct GradientImplementation : public GradientImplementation {}; + + /// Specialization for pointers. + template + struct GradientImplementation { + public: + using Gradient = T_Gradient; + }; +#endif + + /** + * @brief Deduce the entry type from an adjoint vector type, usually identical to the gradient type of a tape. + * + * @tparam AdjointVector Type of the adjoint vector. + */ + template + using Gradient = typename GradientImplementation::Gradient; } } diff --git a/tests/general/Makefile.drivers b/tests/general/Makefile.drivers index 033f9d35..b0d1ce21 100644 --- a/tests/general/Makefile.drivers +++ b/tests/general/Makefile.drivers @@ -50,6 +50,9 @@ endef VECTOR_DIM = 5 +# filter out tests that require variable adjoint interfaces in primal tapes +PRIMAL_TAPE_TESTS_NO_VAI = $(filter-out TestPreaccumulationLocalAdjoints%, $(ALL_TESTS)) + EH_JACOBI_TAPE_TESTS = $(filter-out TestReset, $(ALL_TESTS)) EH_PRIMAL_TAPE_TESTS = $(filter-out TestPreaccumulation% TestReset TestStatementPushHelper, $(ALL_TESTS)) @@ -63,16 +66,16 @@ $(eval $(call define_codi_driver,D1_fwdVec,"drivers/codi/forward1stOrder.hpp",Co $(eval $(call define_codi_driver,D1_rwsJacLin,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverse,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_rwsJacInd,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverseIndex,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_rwsJacIndOmp,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverseIndexOpenMP,$(ALL_TESTS),-DREVERSE_TAPE -DCODI_EnableOpenMP -fopenmp, -fopenmp)) -$(eval $(call define_codi_driver,D1_rwsPrimLin,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimal,$(ALL_TESTS),-DREVERSE_TAPE,)) -$(eval $(call define_codi_driver,D1_rwsPrimInd,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalIndex,$(ALL_TESTS),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D1_rwsPrimLin,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimal,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D1_rwsPrimInd,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalIndex,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_rwsPrimLinInterface,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimal,$(ALL_TESTS),-DREVERSE_TAPE -DCODI_VariableAdjointInterfaceInPrimalTapes,)) $(eval $(call define_codi_driver,D1_rwsPrimIndInterface,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalIndex,$(ALL_TESTS),-DREVERSE_TAPE -DCODI_VariableAdjointInterfaceInPrimalTapes,)) $(eval $(call define_codi_driver,D1_rwsJacLinVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverseVec<$(VECTOR_DIM)>,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_rwsJacIndVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverseIndexVec<$(VECTOR_DIM)>,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_rwsJacIndVecOmp,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReverseIndexVecOpenMP<$(VECTOR_DIM)>,$(ALL_TESTS),-DREVERSE_TAPE -DCODI_EnableOpenMP -fopenmp, -fopenmp)) -$(eval $(call define_codi_driver,D1_rwsPrimLinVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalVec<$(VECTOR_DIM)>,$(ALL_TESTS),-DREVERSE_TAPE,)) -$(eval $(call define_codi_driver,D1_rwsPrimIndVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalIndexVec<$(VECTOR_DIM)>,$(ALL_TESTS),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D1_rwsPrimLinVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalVec<$(VECTOR_DIM)>,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D1_rwsPrimIndVec,"drivers/codi/reverse1stOrder.hpp",CoDiReverse1stOrder,codi::RealReversePrimalIndexVec<$(VECTOR_DIM)>,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D1_eh_fwd,"drivers/codi/evalHelper1stOrder.hpp",CoDiEvalHelper1stOrder,codi::RealForward,$(ALL_TESTS),,)) @@ -111,8 +114,8 @@ $(eval $(call define_codi_driver,D0_fwd,"drivers/codi/run0thOrder.hpp",CoDi0thOr $(eval $(call define_codi_driver,D0_rwsJacLin,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReverse,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D0_rwsJacInd,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReverseIndex,$(ALL_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D0_rwsJacIndOmp,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReverseIndexOpenMP,$(ALL_TESTS),-DREVERSE_TAPE -DCODI_EnableOpenMP -fopenmp, -fopenmp)) -$(eval $(call define_codi_driver,D0_rwsPrimLin,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReversePrimal,$(ALL_TESTS),-DREVERSE_TAPE,)) -$(eval $(call define_codi_driver,D0_rwsPrimInd,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReversePrimalIndex,$(ALL_TESTS),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D0_rwsPrimLin,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReversePrimal,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) +$(eval $(call define_codi_driver,D0_rwsPrimInd,"drivers/codi/run0thOrder.hpp",CoDi0thOrder,codi::RealReversePrimalIndex,$(PRIMAL_TAPE_TESTS_NO_VAI),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D0_eh_fwd,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::RealForward,$(ALL_TESTS),,)) $(eval $(call define_codi_driver,D0_eh_rwsJacLin,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::RealReverse,$(EH_JACOBI_TAPE_TESTS),-DREVERSE_TAPE,)) @@ -120,7 +123,7 @@ $(eval $(call define_codi_driver,D0_eh_rwsJacInd,"drivers/codi/evalHelper0thOrde $(eval $(call define_codi_driver,D0_eh_rwsJacIndOmp,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::RealReverseIndexOpenMP,$(EH_JACOBI_TAPE_TESTS),-DREVERSE_TAPE -DCODI_EnableOpenMP -fopenmp, -fopenmp)) $(eval $(call define_codi_driver,D0_eh_rwsPrimLin,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::RealReversePrimal,$(EH_PRIMAL_TAPE_TESTS),-DREVERSE_TAPE,)) $(eval $(call define_codi_driver,D0_eh_rwsPrimInd,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::RealReversePrimalIndex,$(EH_PRIMAL_TAPE_TESTS),-DREVERSE_TAPE,)) -$(eval $(call define_codi_driver,D0_eh_rwsPrim2nd,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::HessianComputationType,$(ALL_TESTS),,)) +$(eval $(call define_codi_driver,D0_eh_rwsPrim2nd,"drivers/codi/evalHelper0thOrder.hpp",CoDiEvalHelper0thOrder,codi::HessianComputationType,$(PRIMAL_TAPE_TESTS_NO_VAI),,)) # second order drivers VECTOR_ARG = codi::RealForwardVec<$(VECTOR_DIM)>,codi::Direction,$(VECTOR_DIM)> diff --git a/tests/general/include/tests/allTests.hpp b/tests/general/include/tests/allTests.hpp index 2fe30865..4ff6b015 100644 --- a/tests/general/include/tests/allTests.hpp +++ b/tests/general/include/tests/allTests.hpp @@ -64,6 +64,11 @@ #include "tools/helpers/testPreaccumulationForward.hpp" #include "tools/helpers/testPreaccumulationForwardInvalidAdjoint.hpp" #include "tools/helpers/testPreaccumulationLargeStatement.hpp" +#include "tools/helpers/testPreaccumulationLocalAdjointsForward.hpp" +#include "tools/helpers/testPreaccumulationLocalAdjointsForwardInvalidAdjoint.hpp" +#include "tools/helpers/testPreaccumulationLocalAdjointsLargeStatement.hpp" +#include "tools/helpers/testPreaccumulationLocalAdjointsPassiveValue.hpp" +#include "tools/helpers/testPreaccumulationLocalAdjointsZeroJacobi.hpp" #include "tools/helpers/testPreaccumulationPassiveValue.hpp" #include "tools/helpers/testPreaccumulationZeroJacobi.hpp" #include "tools/helpers/testReset.hpp" diff --git a/tests/general/include/tests/tools/helpers/basePreaccumulationForward.hpp b/tests/general/include/tests/tools/helpers/basePreaccumulationForward.hpp new file mode 100644 index 00000000..54e259c5 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/basePreaccumulationForward.hpp @@ -0,0 +1,76 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include "../../../testInterface.hpp" + +template +struct BasePreaccumulationForward : public TestInterface { + public: + IN(2) + OUT(4) + POINTS(1) = {{1.0, 0.5}}; + + template + static void evalFunc(Number* x, Number* y) { + y[0] = x[0]; + y[1] = x[1]; + for (int i = 0; i < 1000; ++i) { + Number xTemp = y[0]; + Number yTemp = y[1]; + + Number xSqr = xTemp * xTemp; + Number ySqr = yTemp * yTemp; + + y[0] = xSqr - ySqr - 0.65; + y[1] = 2.0 * yTemp * xTemp; + } + + y[2] = x[0] * x[0]; + y[3] = x[1] * x[1]; + } + + template + static void func(Number* x, Number* y) { + codi::PreaccumulationHelper ph; + + ph.start(x[0], x[1]); + + evalFunc(x, y); + + Impl::finish(ph, y); + } +}; diff --git a/tests/general/include/tests/tools/helpers/basePreaccumulationForwardInvalidAdjoint.hpp b/tests/general/include/tests/tools/helpers/basePreaccumulationForwardInvalidAdjoint.hpp new file mode 100644 index 00000000..adeca1f0 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/basePreaccumulationForwardInvalidAdjoint.hpp @@ -0,0 +1,80 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include "../../../testInterface.hpp" + +template +struct BasePreaccumulationForwardInvalidAdjoint : public TestInterface { + public: + IN(2) + OUT(4) + POINTS(1) = {{1.0, 0.5}}; + + template + static void evalFunc(Number* x, Number* y) { + Number temp1 = x[0] * x[1]; + Number temp2 = x[0] / x[1]; + Number temp3 = x[0] + x[1]; + Number temp4 = x[0] - x[1]; + Number temp5 = temp1 * temp3; + Number temp6 = temp2 * temp4; + + y[0] = temp5 * temp5; + y[1] = temp6 * temp6; + y[2] = temp5 * temp5; + y[3] = temp6 * temp6; + } + + template + static void func(Number* x, Number* y) { + codi::PreaccumulationHelper ph; + + ph.start(x[0], x[1]); + + evalFunc(x, y); + + Impl::finish(ph, y); + + Number temp1 = y[0] + y[1]; + Number temp2 = y[2] + y[3]; + + y[0] = temp1 + temp2; + y[1] = temp1 - temp2; + y[2] = temp1 * temp2; + y[3] = temp1 / temp2; + } +}; diff --git a/tests/general/include/tests/tools/helpers/basePreaccumulationLargeStatement.hpp b/tests/general/include/tests/tools/helpers/basePreaccumulationLargeStatement.hpp new file mode 100644 index 00000000..5aa1927f --- /dev/null +++ b/tests/general/include/tests/tools/helpers/basePreaccumulationLargeStatement.hpp @@ -0,0 +1,79 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include "../../../testInterface.hpp" + +template +struct BasePreaccumulationLargeStatement : public TestInterface { + public: + IN(2) + OUT(2) + POINTS(1) = {{1.0, 0.5}}; + + template + static void evalFunc(Number* x, Number* y, size_t size) { + y[0] = x[0]; + y[1] = x[0]; + for (size_t i = 1; i < size; ++i) { + y[0] += x[i]; + y[1] = max(y[1], x[i]); + } + } + + template + static void func(Number* x, Number* y) { + codi::PreaccumulationHelper ph; + + size_t const size = 256 * 3; + Number intermediate[size]; + + for (size_t i = 0; i < size; ++i) { + intermediate[i] = x[0] * (double)i + x[1]; + } + + ph.start(); + for (size_t i = 0; i < size; ++i) { + ph.addInput(intermediate[i]); + } + + evalFunc(intermediate, y, size); + + ph.addOutput(y[0]); + ph.addOutput(y[1]); + Impl::finish(ph); + } +}; diff --git a/tests/general/include/tests/tools/helpers/basePreaccumulationPassiveValue.hpp b/tests/general/include/tests/tools/helpers/basePreaccumulationPassiveValue.hpp new file mode 100644 index 00000000..59fa73ed --- /dev/null +++ b/tests/general/include/tests/tools/helpers/basePreaccumulationPassiveValue.hpp @@ -0,0 +1,73 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include "../../../testInterface.hpp" + +template +struct BasePreaccumulationPassiveValue : public TestInterface { + public: + IN(2) + OUT(2) + POINTS(1) = {{1.0, 0.5}}; + + template + static void evalFunc(Number* x, Number* y) { + y[0] = codi::RealTraits::getPassiveValue(x[0]); // kill x dependency + y[1] = x[1]; + + Number two = 2.0; + Number zeroSix = 0.65; + for (int i = 0; i < 5; ++i) { + Number xTemp = y[0]; + Number yTemp = y[1]; + + y[0] = xTemp * xTemp - yTemp * yTemp - zeroSix; + y[1] = two * yTemp * xTemp; + } + } + + template + static void func(Number* x, Number* y) { + codi::PreaccumulationHelper ph; + + ph.start(x[0], x[1]); + + evalFunc(x, y); + + Impl::finish(ph, y); + } +}; diff --git a/tests/general/include/tests/tools/helpers/basePreaccumulationZeroJacobi.hpp b/tests/general/include/tests/tools/helpers/basePreaccumulationZeroJacobi.hpp new file mode 100644 index 00000000..09659892 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/basePreaccumulationZeroJacobi.hpp @@ -0,0 +1,70 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ + +#pragma once + +#include "../../../testInterface.hpp" + +template +struct BasePreaccumulationZeroJacobi : public TestInterface { + public: + IN(2) + OUT(2) + POINTS(1) = {{1.0, 0.5}}; + + template + static void evalFunc(Number* x, Number* y) { + y[0] = codi::RealTraits::getPassiveValue(x[0]); // kill x dependency + y[1] = x[1]; + for (int i = 0; i < 5; ++i) { + Number xTemp = y[0]; + Number yTemp = y[1]; + + y[0] = xTemp * xTemp - yTemp * yTemp - 0.65; + y[1] = 2.0 * yTemp * xTemp; + } + } + + template + static void func(Number* x, Number* y) { + codi::PreaccumulationHelper ph; + + ph.start(x[0], x[1]); + + evalFunc(x, y); + + Impl::finish(ph, y); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationForward.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationForward.hpp index c276e42e..e6fd9621 100644 --- a/tests/general/include/tests/tools/helpers/testPreaccumulationForward.hpp +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationForward.hpp @@ -32,42 +32,14 @@ * - Former members: * - Tim Albring */ -#include "../../../testInterface.hpp" +#include "basePreaccumulationForward.hpp" -struct TestPreaccumulationForward : public TestInterface { +struct TestPreaccumulationForward : public BasePreaccumulationForward { public: NAME("PreaccumulationForward") - IN(2) - OUT(4) - POINTS(1) = {{1.0, 0.5}}; template - static void evalFunc(Number* x, Number* y) { - y[0] = x[0]; - y[1] = x[1]; - for (int i = 0; i < 1000; ++i) { - Number xTemp = y[0]; - Number yTemp = y[1]; - - Number xSqr = xTemp * xTemp; - Number ySqr = yTemp * yTemp; - - y[0] = xSqr - ySqr - 0.65; - y[1] = 2.0 * yTemp * xTemp; - } - - y[2] = x[0] * x[0]; - y[3] = x[1] * x[1]; - } - - template - static void func(Number* x, Number* y) { - codi::PreaccumulationHelper ph; - - ph.start(x[0], x[1]); - - evalFunc(x, y); - + static void finish(codi::PreaccumulationHelper& ph, Number* y) { ph.finish(false, y[0], y[1], y[2], y[3]); } }; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationForwardInvalidAdjoint.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationForwardInvalidAdjoint.hpp index b5417263..a258d434 100644 --- a/tests/general/include/tests/tools/helpers/testPreaccumulationForwardInvalidAdjoint.hpp +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationForwardInvalidAdjoint.hpp @@ -32,46 +32,15 @@ * - Former members: * - Tim Albring */ -#include "../../../testInterface.hpp" +#include "basePreaccumulationForwardInvalidAdjoint.hpp" -struct TestPreaccumulationForwardInvalidAdjoint : public TestInterface { +struct TestPreaccumulationForwardInvalidAdjoint + : public BasePreaccumulationForwardInvalidAdjoint { public: NAME("PreaccumulationForwardInvalidAdjoint") - IN(2) - OUT(4) - POINTS(1) = {{1.0, 0.5}}; template - static void evalFunc(Number* x, Number* y) { - Number temp1 = x[0] * x[1]; - Number temp2 = x[0] / x[1]; - Number temp3 = x[0] + x[1]; - Number temp4 = x[0] - x[1]; - Number temp5 = temp1 * temp3; - Number temp6 = temp2 * temp4; - - y[0] = temp5 * temp5; - y[1] = temp6 * temp6; - y[2] = temp5 * temp5; - y[3] = temp6 * temp6; - } - - template - static void func(Number* x, Number* y) { - codi::PreaccumulationHelper ph; - - ph.start(x[0], x[1]); - - evalFunc(x, y); - + static void finish(codi::PreaccumulationHelper& ph, Number* y) { ph.finish(false, y[0], y[1], y[2], y[3]); - - Number temp1 = y[0] + y[1]; - Number temp2 = y[2] + y[3]; - - y[0] = temp1 + temp2; - y[1] = temp1 - temp2; - y[2] = temp1 * temp2; - y[3] = temp1 / temp2; } }; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLargeStatement.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLargeStatement.hpp index 5164ee4d..d36e3ccf 100644 --- a/tests/general/include/tests/tools/helpers/testPreaccumulationLargeStatement.hpp +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLargeStatement.hpp @@ -32,45 +32,14 @@ * - Former members: * - Tim Albring */ -#include "../../../testInterface.hpp" +#include "basePreaccumulationLargeStatement.hpp" -struct TestPreaccumulationLargeStatement : public TestInterface { +struct TestPreaccumulationLargeStatement : public BasePreaccumulationLargeStatement { public: NAME("PreaccumulationLargeStatement") - IN(2) - OUT(2) - POINTS(1) = {{1.0, 0.5}}; - template - static void evalFunc(Number* x, Number* y, size_t size) { - y[0] = x[0]; - y[1] = x[0]; - for (size_t i = 1; i < size; ++i) { - y[0] += x[i]; - y[1] = max(y[1], x[i]); - } - } - - template - static void func(Number* x, Number* y) { - codi::PreaccumulationHelper ph; - - size_t const size = 256 * 3; - Number intermediate[size]; - - for (size_t i = 0; i < size; ++i) { - intermediate[i] = x[0] * (double)i + x[1]; - } - - ph.start(); - for (size_t i = 0; i < size; ++i) { - ph.addInput(intermediate[i]); - } - - evalFunc(intermediate, y, size); - - ph.addOutput(y[0]); - ph.addOutput(y[1]); + template + static void finish(PreaccHelper& ph) { ph.finish(false); } }; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForward.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForward.hpp new file mode 100644 index 00000000..386617c3 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForward.hpp @@ -0,0 +1,46 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ +#include "basePreaccumulationForward.hpp" + +struct TestPreaccumulationLocalAdjointsForward + : public BasePreaccumulationForward { + public: + NAME("PreaccumulationLocalAdjointsForward") + + template + static void finish(codi::PreaccumulationHelper& ph, Number* y) { + ph.finishLocalAdjoints(y[0], y[1], y[2], y[3]); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForwardInvalidAdjoint.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForwardInvalidAdjoint.hpp new file mode 100644 index 00000000..edf9a98e --- /dev/null +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsForwardInvalidAdjoint.hpp @@ -0,0 +1,46 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ +#include "basePreaccumulationForwardInvalidAdjoint.hpp" + +struct TestPreaccumulationLocalAdjointsForwardInvalidAdjoint + : public BasePreaccumulationForwardInvalidAdjoint { + public: + NAME("PreaccumulationLocalAdjointsForwardInvalidAdjoint") + + template + static void finish(codi::PreaccumulationHelper& ph, Number* y) { + ph.finishLocalAdjoints(y[0], y[1], y[2], y[3]); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsLargeStatement.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsLargeStatement.hpp new file mode 100644 index 00000000..d9e38c70 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsLargeStatement.hpp @@ -0,0 +1,46 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ +#include "basePreaccumulationLargeStatement.hpp" + +struct TestPreaccumulationLocalAdjointsLargeStatement + : public BasePreaccumulationLargeStatement { + public: + NAME("PreaccumulationLocalAdjointsLargeStatement") + + template + static void finish(PreaccHelper& ph) { + ph.finishLocalAdjoints(); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsPassiveValue.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsPassiveValue.hpp new file mode 100644 index 00000000..14aa9358 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsPassiveValue.hpp @@ -0,0 +1,46 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ +#include "basePreaccumulationPassiveValue.hpp" + +struct TestPreaccumulationLocalAdjointsPassiveValue + : public BasePreaccumulationPassiveValue { + public: + NAME("PreaccumulationLocalAdjointsPassiveValue") + + template + static void finish(codi::PreaccumulationHelper& ph, Number* y) { + ph.finishLocalAdjoints(y[0], y[1]); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsZeroJacobi.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsZeroJacobi.hpp new file mode 100644 index 00000000..d089c923 --- /dev/null +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationLocalAdjointsZeroJacobi.hpp @@ -0,0 +1,46 @@ +/* + * CoDiPack, a Code Differentiation Package + * + * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau + * Homepage: http://www.scicomp.uni-kl.de + * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de) + * + * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau) + * + * This file is part of CoDiPack (http://www.scicomp.uni-kl.de/software/codi). + * + * CoDiPack is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * CoDiPack is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * See the GNU General Public License for more details. + * You should have received a copy of the GNU + * General Public License along with CoDiPack. + * If not, see . + * + * For other licensing options please contact us. + * + * Authors: + * - SciComp, University of Kaiserslautern-Landau: + * - Max Sagebaum + * - Johannes Blühdorn + * - Former members: + * - Tim Albring + */ +#include "basePreaccumulationZeroJacobi.hpp" + +struct TestPreaccumulationLocalAdjointsZeroJacobi + : public BasePreaccumulationZeroJacobi { + public: + NAME("PreaccumulationLocalAdjointsZeroJacobi") + + template + static void finish(codi::PreaccumulationHelper& ph, Number* y) { + ph.finishLocalAdjoints(y[0], y[1]); + } +}; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationPassiveValue.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationPassiveValue.hpp index a63a509e..0bd6897b 100644 --- a/tests/general/include/tests/tools/helpers/testPreaccumulationPassiveValue.hpp +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationPassiveValue.hpp @@ -32,39 +32,14 @@ * - Former members: * - Tim Albring */ -#include "../../../testInterface.hpp" +#include "basePreaccumulationPassiveValue.hpp" -struct TestPreaccumulationPassiveValue : public TestInterface { +struct TestPreaccumulationPassiveValue : public BasePreaccumulationPassiveValue { public: NAME("PreaccumulationPassiveValue") - IN(2) - OUT(2) - POINTS(1) = {{1.0, 0.5}}; template - static void evalFunc(Number* x, Number* y) { - y[0] = codi::RealTraits::getPassiveValue(x[0]); // kill x dependency - y[1] = x[1]; - - Number two = 2.0; - Number zeroSix = 0.65; - for (int i = 0; i < 5; ++i) { - Number xTemp = y[0]; - Number yTemp = y[1]; - - y[0] = xTemp * xTemp - yTemp * yTemp - zeroSix; - y[1] = two * yTemp * xTemp; - } - } - - template - static void func(Number* x, Number* y) { - codi::PreaccumulationHelper ph; - - ph.start(x[0], x[1]); - - evalFunc(x, y); - + static void finish(codi::PreaccumulationHelper& ph, Number* y) { ph.finish(false, y[0], y[1]); } }; diff --git a/tests/general/include/tests/tools/helpers/testPreaccumulationZeroJacobi.hpp b/tests/general/include/tests/tools/helpers/testPreaccumulationZeroJacobi.hpp index 8ac5baec..1e84e1b8 100644 --- a/tests/general/include/tests/tools/helpers/testPreaccumulationZeroJacobi.hpp +++ b/tests/general/include/tests/tools/helpers/testPreaccumulationZeroJacobi.hpp @@ -32,36 +32,14 @@ * - Former members: * - Tim Albring */ -#include "../../../testInterface.hpp" +#include "basePreaccumulationZeroJacobi.hpp" -struct TestPreaccumulationZeroJacobi : public TestInterface { +struct TestPreaccumulationZeroJacobi : public BasePreaccumulationZeroJacobi { public: NAME("PreaccumulationZeroJacobi") - IN(2) - OUT(2) - POINTS(1) = {{1.0, 0.5}}; template - static void evalFunc(Number* x, Number* y) { - y[0] = codi::RealTraits::getPassiveValue(x[0]); // kill x dependency - y[1] = x[1]; - for (int i = 0; i < 5; ++i) { - Number xTemp = y[0]; - Number yTemp = y[1]; - - y[0] = xTemp * xTemp - yTemp * yTemp - 0.65; - y[1] = 2.0 * yTemp * xTemp; - } - } - - template - static void func(Number* x, Number* y) { - codi::PreaccumulationHelper ph; - - ph.start(x[0], x[1]); - - evalFunc(x, y); - + static void finish(codi::PreaccumulationHelper& ph, Number* y) { ph.finish(false, y[0], y[1]); } }; diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjoints.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjoints.out new file mode 100644 index 00000000..b3071481 --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjoints.out @@ -0,0 +1,3 @@ +Point 0 : {1.000000, 0.500000} + out_000 0.982476 + out_001 -15.3109 diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForward.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForward.out new file mode 100644 index 00000000..993623d8 --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForward.out @@ -0,0 +1,5 @@ +Point 0 : {1.000000, 0.500000} + out_000 -nan + out_001 -nan + out_002 1 + out_003 0.25 diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out new file mode 100644 index 00000000..72ad6fdd --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out @@ -0,0 +1,5 @@ +Point 0 : {1.000000, 0.500000} + out_000 3.125 + out_001 0 + out_002 2.44141 + out_003 1 diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjointsLargeStatement.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsLargeStatement.out new file mode 100644 index 00000000..1160aa96 --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsLargeStatement.out @@ -0,0 +1,3 @@ +Point 0 : {1.000000, 0.500000} + out_000 294912 + out_001 767.5 diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjointsPassiveValue.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsPassiveValue.out new file mode 100644 index 00000000..b3071481 --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsPassiveValue.out @@ -0,0 +1,3 @@ +Point 0 : {1.000000, 0.500000} + out_000 0.982476 + out_001 -15.3109 diff --git a/tests/general/results/deriv0th/PreaccumulationLocalAdjointsZeroJacobi.out b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsZeroJacobi.out new file mode 100644 index 00000000..b3071481 --- /dev/null +++ b/tests/general/results/deriv0th/PreaccumulationLocalAdjointsZeroJacobi.out @@ -0,0 +1,3 @@ +Point 0 : {1.000000, 0.500000} + out_000 0.982476 + out_001 -15.3109 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjoints.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjoints.out new file mode 100644 index 00000000..2efa6aa1 --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjoints.out @@ -0,0 +1,4 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 -354.168 339.417 + out_001 -339.417 -354.168 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForward.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForward.out new file mode 100644 index 00000000..51d8300f --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForward.out @@ -0,0 +1,6 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 0 0 + out_001 0 0 + out_002 2 0 + out_003 0 1 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out new file mode 100644 index 00000000..196a0b8b --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out @@ -0,0 +1,6 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 15.75 -10 + out_001 0 0 + out_002 24.6094 -15.625 + out_003 0 0 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjointsLargeStatement.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsLargeStatement.out new file mode 100644 index 00000000..d3cd5f27 --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsLargeStatement.out @@ -0,0 +1,4 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 294528 768 + out_001 767 1 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjointsPassiveValue.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsPassiveValue.out new file mode 100644 index 00000000..12a75e24 --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsPassiveValue.out @@ -0,0 +1,4 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 0 339.417 + out_001 0 -354.168 diff --git a/tests/general/results/deriv1st/PreaccumulationLocalAdjointsZeroJacobi.out b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsZeroJacobi.out new file mode 100644 index 00000000..12a75e24 --- /dev/null +++ b/tests/general/results/deriv1st/PreaccumulationLocalAdjointsZeroJacobi.out @@ -0,0 +1,4 @@ +Point 0 : {1.000000, 0.500000} + in_000 in_001 + out_000 0 339.417 + out_001 0 -354.168 diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjoints.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjoints.out new file mode 100644 index 00000000..8b59c301 --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjoints.out @@ -0,0 +1,9 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 -13829.1 -2559.17 + in_001 -2559.17 13829.1 + + out_001 in_000 in_001 + in_000 2559.17 -13829.1 + in_001 -13829.1 -2559.17 + diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForward.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForward.out new file mode 100644 index 00000000..dd54ba5a --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForward.out @@ -0,0 +1,17 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 0 0 + in_001 0 0 + + out_001 in_000 in_001 + in_000 0 0 + in_001 0 0 + + out_002 in_000 in_001 + in_000 2 0 + in_001 0 0 + + out_003 in_000 in_001 + in_000 0 0 + in_001 0 2 + diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out new file mode 100644 index 00000000..f9293c57 --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsForwardInvalidAdjoint.out @@ -0,0 +1,17 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 61.25 -61 + in_001 -61 150 + + out_001 in_000 in_001 + in_000 0 0 + in_001 0 0 + + out_002 in_000 in_001 + in_000 219.734 -174.062 + in_001 -174.062 284.375 + + out_003 in_000 in_001 + in_000 0 0 + in_001 0 -1.77636e-15 + diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsLargeStatement.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsLargeStatement.out new file mode 100644 index 00000000..e19b04a3 --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsLargeStatement.out @@ -0,0 +1,9 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 0 0 + in_001 0 0 + + out_001 in_000 in_001 + in_000 0 0 + in_001 0 0 + diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsPassiveValue.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsPassiveValue.out new file mode 100644 index 00000000..cf54d870 --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsPassiveValue.out @@ -0,0 +1,9 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 0 0 + in_001 0 13829.1 + + out_001 in_000 in_001 + in_000 0 0 + in_001 0 -2559.17 + diff --git a/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsZeroJacobi.out b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsZeroJacobi.out new file mode 100644 index 00000000..cf54d870 --- /dev/null +++ b/tests/general/results/deriv2nd/PreaccumulationLocalAdjointsZeroJacobi.out @@ -0,0 +1,9 @@ +Point 0 : {1.000000, 0.500000} + out_000 in_000 in_001 + in_000 0 0 + in_001 0 13829.1 + + out_001 in_000 in_001 + in_000 0 0 + in_001 0 -2559.17 +