CoDiPack  2.3.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
jacobianBaseTape.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://scicomp.rptu.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum, Johannes Blühdorn (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of CoDiPack (http://scicomp.rptu.de/software/codi).
11 *
12 * CoDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, either version 3 of the
15 * License, or (at your option) any later version.
16 *
17 * CoDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty
19 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU
23 * General Public License along with CoDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * For other licensing options please contact us.
27 *
28 * Authors:
29 * - SciComp, University of Kaiserslautern-Landau:
30 * - Max Sagebaum
31 * - Johannes Blühdorn
32 * - Former members:
33 * - Tim Albring
34 */
35#pragma once
36
37#include <algorithm>
38#include <cmath>
39#include <fstream>
40#include <type_traits>
41
42#include "../config.h"
43#include "../expressions/lhsExpressionInterface.hpp"
44#include "../expressions/logic/compileTimeTraversalLogic.hpp"
45#include "../expressions/logic/helpers/forEachLeafLogic.hpp"
46#include "../expressions/logic/helpers/jacobianComputationLogic.hpp"
47#include "../expressions/logic/traversalLogic.hpp"
48#include "../expressions/referenceActiveType.hpp"
49#include "../misc/macros.hpp"
50#include "../misc/mathUtility.hpp"
51#include "../misc/memberStore.hpp"
52#include "../traits/adjointVectorTraits.hpp"
53#include "../traits/computationTraits.hpp"
54#include "../traits/expressionTraits.hpp"
55#include "commonTapeImplementation.hpp"
56#include "data/chunk.hpp"
57#include "data/chunkedData.hpp"
58#include "indices/indexManagerInterface.hpp"
59#include "io/tapeReaderWriterInterface.hpp"
60#include "misc/adjointVectorAccess.hpp"
61#include "misc/duplicateJacobianRemover.hpp"
62#include "misc/localAdjoints.hpp"
63
65namespace codi {
66
76 template<typename T_Real, typename T_Gradient, typename T_IndexManager, template<typename, typename> class T_Data,
77 template<typename, typename, typename> class T_Adjoints = LocalAdjoints>
79 public:
80
81 using Real = CODI_DD(T_Real, double);
82 using Gradient = CODI_DD(T_Gradient, double);
84 template<typename Chunk, typename Nested>
85 using Data = CODI_DD(CODI_T(T_Data<Chunk, Nested>),
87
88 using Identifier = typename IndexManager::Index;
89
91 template<typename Impl>
92 using Adjoints = CODI_DD(CODI_T(T_Adjoints<Gradient, Identifier, Impl>),
94
95 static bool constexpr IsLinearIndexHandler = IndexManager::IsLinear;
96 static bool constexpr IsStaticIndexHandler =
97 IndexManager::NeedsStaticStorage;
98
101 using StatementChunk = typename std::conditional<IsLinearIndexHandler, Chunk1<Config::ArgumentSize>,
104
107
109 };
110
127 template<typename T_TapeTypes, typename T_Impl>
128 struct JacobianBaseTape : public CommonTapeImplementation<T_TapeTypes, T_Impl> {
129 public:
130
134 using Impl = CODI_DD(T_Impl, CODI_DEFAULT_TAPE);
135
137 friend Base;
138
139 using Real = typename TapeTypes::Real;
140 using Gradient = typename TapeTypes::Gradient;
141 using IndexManager = typename TapeTypes::IndexManager;
142 using Identifier = typename TapeTypes::Identifier;
143
144 using StatementData = typename TapeTypes::StatementData;
145 using JacobianData = typename TapeTypes::JacobianData;
146
147 using Adjoints = typename TapeTypes::template Adjoints<Impl>;
148
150
151 using NestedPosition = typename JacobianData::Position;
152 using Position = typename Base::Position;
153
155 template<typename AdjointVector>
157
158 static bool constexpr AllowJacobianOptimization = true;
159 static bool constexpr HasPrimalValues = false;
160
161 static bool constexpr LinearIndexHandling =
162 TapeTypes::IsLinearIndexHandler;
163 static bool constexpr RequiresPrimalRestore = false;
164
165 protected:
166
167#if CODI_RemoveDuplicateJacobianArguments
170#endif
171
175
177
178 private:
179
180 CODI_INLINE Impl const& cast() const {
181 return static_cast<Impl const&>(*this);
182 }
183
184 CODI_INLINE Impl& cast() {
185 return static_cast<Impl&>(*this);
186 }
187
188 protected:
189
190 /*******************************************************************************/
193
195 template<typename... Args>
196 static void internalEvaluateForward_EvalStatements(Args&&... args);
197
199 template<typename... Args>
200 static void internalEvaluateReverse_EvalStatements(Args&&... args);
201
203 void pushStmtData(Identifier const& index, Config::ArgumentSize const& numberOfArguments);
204
206
207 public:
208
211 : Base(),
213 jacobianSorter(),
214#endif
215 indexManager(0), // Reserve the zero index.
216 statementData(Config::ChunkSize),
217 jacobianData(std::max(Config::ChunkSize, Config::MaxArgumentSize)), // Chunk must be large enough to store
218 // data for all arguments of one
219 // statement.
220 adjoints(1) // Ensure that adjoint[0] exists, see its use in gradient() const.
221
222 {
223 statementData.setNested(&indexManager.get());
224 jacobianData.setNested(&statementData);
225
227
232 }
233
234 /*******************************************************************************/
237
241 if (AdjointsManagement::Automatic == adjointsManagement) {
242 checkAdjointSize(identifier);
243 }
244
245 codiAssert(identifier < (Identifier)adjoints.size());
246
247 return adjoints[identifier];
248 }
249
252 Identifier const& identifier, AdjointsManagement adjointsManagement = AdjointsManagement::Automatic) const {
253 codiAssert(identifier < (Identifier)adjoints.size());
254
255 if (AdjointsManagement::Automatic == adjointsManagement && identifier >= (Identifier)adjoints.size()) {
256 return adjoints[0];
257 } else {
258 return adjoints[identifier];
259 }
260 }
261
263 /*******************************************************************************/
266
268 template<typename Real>
269 CODI_INLINE void initIdentifier(Real& value, Identifier& identifier) {
270 CODI_UNUSED(value);
271
272 identifier = IndexManager::InactiveIndex;
273 }
274
276 template<typename Real>
277 CODI_INLINE void destroyIdentifier(Real& value, Identifier& identifier) {
278 CODI_UNUSED(value);
279
280 indexManager.get().template freeIndex<Impl>(identifier);
281 }
282
284
285 protected:
286
288 struct PushJacobianLogic : public JacobianComputationLogic<PushJacobianLogic> {
289 public:
291 template<typename Node, typename Jacobian, typename DataVector>
292 CODI_INLINE void handleJacobianOnActive(Node const& node, Jacobian jacobianExpr, DataVector& dataVector) {
293 Real jacobian = ComputationTraits::adjointConversion<Real>(jacobianExpr);
294
295 if (CODI_ENABLE_CHECK(Config::CheckZeroIndex, 0 != node.getIdentifier())) {
298 dataVector.pushData(jacobian, node.getIdentifier());
299 }
300 }
301 }
302 }
303
305 template<typename Type, typename Jacobian, typename DataVector>
307 DataVector& dataVector) {
308 CODI_UNUSED(dataVector);
309
310 Real jacobian = ComputationTraits::adjointConversion<Real>(jacobianExpr);
311
313 // Do a delayed push for these leaf nodes, accumulate the jacobian in the local member.
314 node.jacobian += jacobian;
315 }
316 }
317 };
318
320 struct PushDelayedJacobianLogic : public ForEachLeafLogic<PushDelayedJacobianLogic> {
321 public:
322
324 template<typename Type, typename DataVector>
325 CODI_INLINE void handleActive(ReferenceActiveType<Type> const& node, DataVector& dataVector) {
326 if (CODI_ENABLE_CHECK(Config::CheckZeroIndex, 0 != node.getIdentifier())) {
328 dataVector.pushData(node.jacobian, node.getIdentifier());
329
330 // Reset the jacobian here such that it is not pushed multiple times and ready for the next store.
331 node.jacobian = Real();
332 }
333 }
334 }
335
337 };
338
340 template<typename Rhs>
342 PushJacobianLogic pushJacobianLogic;
343 PushDelayedJacobianLogic pushDelayedJacobianLogic;
344
345#if CODI_RemoveDuplicateJacobianArguments
346 auto& insertVector = jacobianSorter;
347#else
348 auto& insertVector = jacobianData;
349#endif
350
351 pushJacobianLogic.eval(rhs.cast(), Real(1.0), insertVector);
352 pushDelayedJacobianLogic.eval(rhs.cast(), insertVector);
353
354#if CODI_RemoveDuplicateJacobianArguments
355 jacobianSorter.storeData(jacobianData);
356#endif
357 }
358
359 public:
360
362
364 template<typename Lhs, typename Rhs>
369
371
372 statementData.reserveItems(1);
373 typename JacobianData::InternalPosHandle jacobianStart = jacobianData.reserveItems(MaxArgs);
374
375 pushJacobians(rhs);
376
377 size_t numberOfArguments = jacobianData.getPushedDataCount(jacobianStart);
378 if (CODI_ENABLE_CHECK(Config::CheckEmptyStatements, 0 != numberOfArguments)) {
379 indexManager.get().template assignIndex<Impl>(lhs.cast().getIdentifier());
380 cast().pushStmtData(lhs.cast().getIdentifier(), (Config::ArgumentSize)numberOfArguments);
381
383 Real* jacobians;
384 Identifier* rhsIdentifiers;
385 jacobianData.getDataPointers(jacobians, rhsIdentifiers);
386 jacobians -= numberOfArguments;
387 rhsIdentifiers -= numberOfArguments;
388
390 rhs.cast().getValue(), numberOfArguments,
391 rhsIdentifiers, jacobians);
392 }
393 } else {
394 indexManager.get().template freeIndex<Impl>(lhs.cast().getIdentifier());
395 }
396 } else {
397 indexManager.get().template freeIndex<Impl>(lhs.cast().getIdentifier());
398 }
399
400 lhs.cast().value() = rhs.cast().getValue();
401 }
402
405 template<typename Lhs, typename Rhs>
409 if (IndexManager::CopyNeedsStatement || !Config::CopyOptimization) {
410 store<Lhs, Rhs>(lhs, static_cast<ExpressionInterface<Real, Rhs> const&>(rhs));
411 return;
412 } else {
413 indexManager.get().template copyIndex<Impl>(lhs.cast().getIdentifier(), rhs.cast().getIdentifier());
414 }
415 } else {
416 indexManager.get().template freeIndex<Impl>(lhs.cast().getIdentifier());
417 }
418
419 lhs.cast().value() = rhs.cast().getValue();
420 }
421
424 template<typename Lhs>
426 indexManager.get().template freeIndex<Impl>(lhs.cast().getIdentifier());
427
428 lhs.cast().value() = rhs;
429 }
430
432 /*******************************************************************************
433 * Protected helper function for ReverseTapeInterface
434 */
435
436 protected:
437
439 template<typename Lhs>
441 bool unusedIndex) {
442 if (TapeTypes::IsLinearIndexHandler) {
443 statementData.reserveItems(1);
444 }
445
446 if (unusedIndex) {
447 indexManager.get().template assignUnusedIndex<Impl>(value.cast().getIdentifier());
448 } else {
449 indexManager.get().template assignIndex<Impl>(value.cast().getIdentifier());
450 }
451
452 if (TapeTypes::IsLinearIndexHandler) {
453 cast().pushStmtData(value.cast().getIdentifier(), Config::StatementInputTag);
454 }
455 }
456
457 public:
458
459 /*******************************************************************************/
462
464 template<typename Lhs>
466 cast().internalRegisterInput(value, true);
467 EventSystem<Impl>::notifyTapeRegisterInputListeners(cast(), value.cast().value(), value.cast().getIdentifier());
468 }
469
472 if (AdjointsManagement::Automatic == adjointsManagement) {
473 adjoints.beginUse();
474 }
475
476 adjoints.zeroAll(indexManager.get().getLargestCreatedIndex());
477
478 if (AdjointsManagement::Automatic == adjointsManagement) {
479 adjoints.endUse();
480 }
481 }
482
484
485 protected:
486
489 std::string name;
490 if (TapeTypes::IsLinearIndexHandler) {
491 name = "CoDi Tape Statistics ( JacobianLinearTape )";
492 } else {
493 name = "CoDi Tape Statistics ( JacobianReuseTape )";
494 }
495 TapeValues values = TapeValues(name);
496
497 size_t nAdjoints = indexManager.get().getLargestCreatedIndex();
498 double memoryAdjoints = static_cast<double>(nAdjoints) * static_cast<double>(sizeof(Gradient));
499
500 bool constexpr globalAdjoints = InternalAdjointVectorTraits::IsGlobal<Adjoints>::value;
501 TapeValues::LocalReductionOperation constexpr operation =
502 globalAdjoints ? TapeValues::LocalReductionOperation::Max : TapeValues::LocalReductionOperation::Sum;
503
504 values.addSection("Adjoint vector");
505 values.addUnsignedLongEntry("Number of adjoints", nAdjoints, operation);
506 values.addDoubleEntry("Memory allocated", memoryAdjoints, operation, true, true);
507
508 values.addSection("Index manager");
509 indexManager.get().addToTapeValues(values);
510
511 values.addSection("Statement entries");
512 statementData.addToTapeValues(values);
513 values.addSection("Jacobian entries");
514 jacobianData.addToTapeValues(values);
515
516 return values;
517 }
518
519 /******************************************************************************
520 * Protected helper function for CustomAdjointVectorEvaluationTapeInterface
521 */
522
523 protected:
524
526 template<typename AdjointVector>
527 CODI_INLINE static void incrementAdjoints(AdjointVector& adjointVector,
529 Config::ArgumentSize const& numberOfArguments, size_t& curJacobianPos,
530 Real const* const rhsJacobians,
531 Identifier const* const rhsIdentifiers) {
532 size_t endJacobianPos = curJacobianPos - numberOfArguments;
533
535 while (endJacobianPos < curJacobianPos) CODI_Likely {
536 curJacobianPos -= 1;
537 adjointVector[rhsIdentifiers[curJacobianPos]] += rhsJacobians[curJacobianPos] * lhsAdjoint;
538 }
539 } else CODI_Unlikely {
540 curJacobianPos = endJacobianPos;
541 }
542 }
543
545 CODI_WRAP_FUNCTION_TEMPLATE(Wrap_internalEvaluateReverse_EvalStatements,
547
549 template<typename AdjointVector>
550 CODI_INLINE static void incrementTangents(AdjointVector const& adjointVector,
552 Config::ArgumentSize const& numberOfArguments, size_t& curJacobianPos,
553 Real const* const rhsJacobians,
554 Identifier const* const rhsIdentifiers) {
555 size_t endJacobianPos = curJacobianPos + numberOfArguments;
556
557 while (curJacobianPos < endJacobianPos) CODI_Likely {
558 lhsAdjoint += rhsJacobians[curJacobianPos] * adjointVector[rhsIdentifiers[curJacobianPos]];
559 curJacobianPos += 1;
560 }
561 }
562
564 CODI_WRAP_FUNCTION_TEMPLATE(Wrap_internalEvaluateForward_EvalStatements,
566
567 public:
568
571
572 using Base::evaluate;
573
575 template<typename AdjointVector>
576 CODI_NO_INLINE void evaluate(Position const& start, Position const& end, AdjointVector&& data) {
577 VectorAccess<AdjointVector> adjointWrapper(data);
578
580 cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Reverse, EventHints::Endpoint::Begin);
581
583 Base::llfByteData.evaluateReverse(start, end, evalFunc, cast(), std::forward<AdjointVector>(data));
584
585 EventSystem<Impl>::notifyTapeEvaluateListeners(cast(), start, end, &adjointWrapper,
586 EventHints::EvaluationKind::Reverse, EventHints::Endpoint::End);
587 }
588
590 template<typename AdjointVector>
591 CODI_NO_INLINE void evaluateForward(Position const& start, Position const& end, AdjointVector&& data) {
592 VectorAccess<AdjointVector> adjointWrapper(data);
593
595 cast(), start, end, &adjointWrapper, EventHints::EvaluationKind::Forward, EventHints::Endpoint::Begin);
596
598 Base::llfByteData.evaluateForward(start, end, evalFunc, cast(), std::forward<AdjointVector>(data));
599
600 EventSystem<Impl>::notifyTapeEvaluateListeners(cast(), start, end, &adjointWrapper,
601 EventHints::EvaluationKind::Forward, EventHints::Endpoint::End);
602 }
603
606 return adjoints.data();
607 }
608
610 /*******************************************************************************/
613
615 CODI_INLINE void swap(Impl& other) {
616 // Index manager does not need to be swapped, it is either static or swapped with the vector data.
617 // Vectors are swapped recursively in the base class.
618
619 adjoints.swap(other.adjoints);
620
621 Base::swap(other);
622 }
623
626 adjoints.resize(1);
627 }
628
631 checkAdjointSize(indexManager.get().getLargestCreatedIndex());
632 }
633
636 adjoints.beginUse();
637 }
638
641 adjoints.endUse();
642 }
643
645 size_t getParameter(TapeParameters parameter) const {
646 switch (parameter) {
648 return adjoints.size();
649 break;
651 return jacobianData.getDataSize();
652 break;
654 return indexManager.get().getLargestCreatedIndex();
655 break;
657 return statementData.getDataSize();
658 default:
659 return Base::getParameter(parameter);
660 break;
661 }
662 }
663
665 void setParameter(TapeParameters parameter, size_t value) {
666 switch (parameter) {
668 adjoints.resize(value);
669 break;
671 jacobianData.resize(value);
672 break;
674 CODI_EXCEPTION("Tried to set a get only parameter.");
675 break;
677 statementData.resize(value);
678 break;
679 default:
680 Base::setParameter(parameter, value);
681 break;
682 }
683 }
684
688 }
689
691 template<typename AdjointVector>
695
698 template<typename Adjoint>
702
705 delete access;
706 }
707
709 /*******************************************************************************/
712
714 template<typename Lhs>
716 cast().internalRegisterInput(value, false);
717
718 return Real();
719 }
720
722 /*******************************************************************************/
725
727
729 void evaluateForward(Position const& start, Position const& end,
731 if (AdjointsManagement::Automatic == adjointsManagement) {
732 checkAdjointSize(indexManager.get().getLargestCreatedIndex());
733 adjoints.beginUse();
734 }
735
736 codiAssert(indexManager.get().getLargestCreatedIndex() < (Identifier)adjoints.size());
737
738 cast().evaluateForward(start, end, adjoints.data());
739
740 if (AdjointsManagement::Automatic == adjointsManagement) {
741 adjoints.endUse();
742 }
743 }
744
746 /*******************************************************************************/
749
751 void pushJacobianManual(Real const& jacobian, Real const& value, Identifier const& index) {
752 CODI_UNUSED(value);
753
754 cast().incrementManualPushCounter();
755
756 jacobianData.pushData(jacobian, index);
757
759 if (this->manualPushCounter == this->manualPushGoal) {
760 // emit statement event
761 Real* jacobians;
762 Identifier* rhsIdentifiers;
763 jacobianData.getDataPointers(jacobians, rhsIdentifiers);
764 jacobians -= this->manualPushGoal;
765 rhsIdentifiers -= this->manualPushGoal;
766
769 rhsIdentifiers, jacobians);
770 }
771 }
772 }
773
775 void storeManual(Real const& lhsValue, Identifier& lhsIndex, Config::ArgumentSize const& size) {
776 CODI_UNUSED(lhsValue);
777 Impl& impl = cast();
778
780
781 statementData.reserveItems(1);
782 jacobianData.reserveItems(size);
783
784 indexManager.get().template assignIndex<Impl>(lhsIndex);
785 impl.pushStmtData(lhsIndex, (Config::ArgumentSize)size);
786
787 impl.initializeManualPushData(lhsValue, lhsIndex, size);
788 }
789
791 /*******************************************************************************/
794
798 void createStatementManual(Real const& lhsValue, Identifier& lhsIndex, Config::ArgumentSize const& size,
799 Real const* jacobians, Identifier const* rhsIdentifiers) {
800 CODI_UNUSED(lhsValue);
801 Impl& impl = cast();
802
803 statementData.reserveItems(1);
804
805 if (Config::StatementInputTag == size && TapeTypes::IsLinearIndexHandler) CODI_Unlikely {
806 impl.pushStmtData(lhsIndex, (Config::ArgumentSize)size);
807 } else CODI_Likely {
808 jacobianData.reserveItems(size);
809 impl.pushStmtData(lhsIndex, (Config::ArgumentSize)size);
810 impl.initializeManualPushData(lhsValue, lhsIndex, size);
811 // Record the rhs of the statement.
812 for (size_t rhsCount = 0; rhsCount < size; rhsCount++) {
813 cast().incrementManualPushCounter();
814 jacobianData.pushData(jacobians[rhsCount], rhsIdentifiers[rhsCount]);
815 }
816 }
817 }
818
819 using Base::writeTape;
820
823 template<typename Type>
825 Position const& end) {
826 Impl& impl = cast();
827 writer->start(impl);
828 Base::llfByteData.evaluateForward(start, end, Impl::template internalWriteTape<Type>, writer);
829 writer->finish();
830 }
831
833 /*******************************************************************************/
836
841
843 /*******************************************************************************/
846
849 statementData.reserveItems(1);
850
851 Base::internalStoreLowLevelFunction(token, size, data);
852
853 Identifier lhsIndex = Identifier();
855 indexManager.get().template assignIndex<Impl>(lhsIndex);
856 }
857 cast().pushStmtData(lhsIndex, Config::StatementLowLevelFunctionTag);
858 }
859
861 /*******************************************************************************/
864
866 CODI_INLINE void evaluate(Position const& start, Position const& end,
868 if (AdjointsManagement::Automatic == adjointsManagement) {
869 checkAdjointSize(indexManager.get().getLargestCreatedIndex());
870 adjoints.beginUse();
871 }
872
873 codiAssert(indexManager.get().getLargestCreatedIndex() < (Identifier)adjoints.size());
874
875 evaluate(start, end, adjoints.data());
876
877 if (AdjointsManagement::Automatic == adjointsManagement) {
878 adjoints.endUse();
879 }
880 }
881
883 /*******************************************************************************/
886
888 void evaluateKeepState(Position const& start, Position const& end,
890 evaluate(start, end, adjointsManagement);
891 }
892
894 template<typename AdjointVector>
895 void evaluateKeepState(Position const& start, Position const& end, AdjointVector&& data) {
896 evaluate(start, end, std::forward<AdjointVector>(data));
897 }
898
900 void evaluateForwardKeepState(Position const& start, Position const& end,
902 evaluateForward(start, end, adjointsManagement);
903 }
904
906 template<typename AdjointVector>
907 void evaluateForwardKeepState(Position const& start, Position const& end, AdjointVector&& data) {
908 evaluateForward(start, end, std::forward<AdjointVector>(data));
909 }
910
912 /*******************************************************************************/
915
917
919 void evaluatePrimal(Position const& start, Position const& end) {
920 CODI_UNUSED(start, end);
921
922 CODI_EXCEPTION("Accessing primal evaluation of an Jacobian tape.");
923 }
924
926 Real& primal(Identifier const& identifier) {
927 CODI_UNUSED(identifier);
928
929 CODI_EXCEPTION("Accessing primal vector of an Jacobian tape.");
930
931 static Real temp;
932 return temp;
933 }
934
936 Real const& primal(Identifier const& identifier) const {
937 CODI_UNUSED(identifier);
938
939 CODI_EXCEPTION("Accessing primal vector of an Jacobian tape.");
940
941 static Real temp;
942 return temp;
943 }
944
946
947 private:
948
949 CODI_INLINE void checkAdjointSize(Identifier const& identifier) {
950 if (identifier >= (Identifier)adjoints.size()) {
951 internalResizeAdjointsVector();
952 }
953 }
954
955 CODI_NO_INLINE void internalResizeAdjointsVector() {
956 // overallocate as next multiple of Config::ChunkSize
957 adjoints.resize(
958 getNextMultiple(indexManager.get().getLargestCreatedIndex() + 1, (Identifier)Config::ChunkSize));
959 }
960 };
961}
#define CODI_Unlikely
Declare unlikely evaluation of an execution path.
Definition config.h:399
#define CODI_NO_INLINE
See codi::Config::AvoidedInlines.
Definition config.h:417
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:457
#define CODI_Likely
Declare likely evaluation of an execution path.
Definition config.h:397
#define CODI_RemoveDuplicateJacobianArguments
See codi::Config::RemoveDuplicateJacobianArguments.
Definition config.h:229
#define codiAssert(x)
See codi::Config::EnableAssert.
Definition config.h:432
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:94
#define CODI_ENABLE_CHECK(option, condition)
Definition macros.hpp:53
#define CODI_WRAP_FUNCTION_TEMPLATE(NAME, FUNC)
Wrap a function in a function object. Used for performance optimizations.
Definition macros.hpp:167
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition macros.hpp:111
typename GradientImplementation< AdjointVector >::Gradient Gradient
Deduce the entry type from an adjoint vector type, usually identical to the gradient type of a tape.
Definition adjointVectorTraits.hpp:92
uint16_t LowLevelFunctionToken
Token type for low level functions in the tapes.
Definition config.h:108
const bool CheckEmptyStatements
Tapes push statements only if at least one Jacobian was pushed.
Definition config.h:154
size_t constexpr ChunkSize
Default size of chunks (ChunkBase) used in ChunkedData in reverse tape implementations.
Definition config.h:94
bool constexpr CheckZeroIndex
Ignore active types that are not dependent on any input value in Jacobian tapes.
Definition config.h:178
bool constexpr IgnoreInvalidJacobians
Ignore invalid Jacobians like NaN or Inf.
Definition config.h:240
bool constexpr CheckTapeActivity
Makes it possible to ignore certain code parts. If turned of everything will be recorded.
Definition config.h:170
size_t constexpr StatementLowLevelFunctionTag
Statement tag for low level functions.
Definition config.h:126
bool constexpr CheckJacobianIsZero
Ignore Jacobians that are zero in Jacobian based tapes.
Definition config.h:162
size_t constexpr MaxArgumentSize
Maximum number of arguments in a statement.
Definition config.h:120
bool constexpr StatementEvents
Enable statement events. Disabled by default.
Definition config.h:319
bool constexpr CopyOptimization
Do not store copy statements like a = b; if the identity handler allows it.
Definition config.h:186
uint8_t ArgumentSize
Type for the number of arguments in statements.
Definition config.h:117
size_t constexpr StatementInputTag
Tag for statements that are inputs. Used in linear index management context.
Definition config.h:123
bool constexpr SkipZeroAdjointEvaluation
Do not perform a reverse evaluation of a statement if the seeding adjoint is zero.
Definition config.h:256
bool isTotalFinite(Type const &v)
Function for checking if all values of the type are finite.
Definition realTraits.hpp:133
typename TraitsImplementation< Type >::PassiveReal PassiveReal
The original computation type, that was used in the application.
Definition realTraits.hpp:117
bool isTotalZero(Type const &v)
Function for checking if the value of the type is completely zero.
Definition realTraits.hpp:139
CoDiPack - Code Differentiation Package.
Definition codi.hpp:91
void CODI_UNUSED(Args const &...)
Disable unused warnings for an arbitrary number of arguments.
Definition macros.hpp:46
IntegralType getNextMultiple(IntegralType const &targetSize, IntegralType const &chunkSize)
Helper function for overallocation in multiples of a given chunk size.
Definition mathUtility.hpp:49
TapeParameters
Configuration options for a tape.
Definition tapeParameters.hpp:52
@ LargestIdentifier
[A: R] Largest identifier distributed by the index manger.
@ JacobianSize
[A: RW] Allocated number of entries in the argument Jacobian vector in Jacobian tapes.
@ StatementSize
[A: RW] Allocated number of entries in the statement vector in all tapes.
AdjointsManagement
Policies for management of the tape's interal adjoints.
Definition tapeParameters.hpp:98
@ Automatic
Manage internal adjoints automatically, including locking, bounds checking, and resizing.
Implementation of VectorAccessInterface for adjoint vectors.
Definition adjointVectorAccess.hpp:61
Definition byteDataView.hpp:51
Definition chunk.hpp:283
Data is stored chunk-wise in this DataInterface implementation. If a chunk runs out of space,...
Definition chunkedData.hpp:64
Implementation of all common tape functionality.
Definition commonTapeImplementation.hpp:131
Real manualPushLhsValue
For storeManual, remember the value assigned to the lhs.
Definition commonTapeImplementation.hpp:158
void setParameter(TapeParameters parameter, size_t value)
See Parameters functions.
Definition commonTapeImplementation.hpp:459
void evaluateForward(AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a forward evaluation of a part of the tape. It has to hold start <= end.
Definition commonTapeImplementation.hpp:592
size_t manualPushCounter
Count the pushes after storeManual, to identify the last push.
Definition commonTapeImplementation.hpp:161
Identifier manualPushLhsIdentifier
For storeManual, remember the identifier assigned to the lhs.
Definition commonTapeImplementation.hpp:159
bool isActive() const
Check if the tape is recording.
Definition commonTapeImplementation.hpp:320
size_t manualPushGoal
Store the number of expected pushes after a storeManual call.
Definition commonTapeImplementation.hpp:160
void init(typename ImplTapeTypes::NestedData *nested)
Initialize the base class.
Definition commonTapeImplementation.hpp:751
std::set< TapeParameters > options
All options.
Definition commonTapeImplementation.hpp:153
void writeTape(std::unique_ptr< TapeWriterInterface< Type > > writer)
For full-tape writers using a smart pointer.
Definition commonTapeImplementation.hpp:605
void evaluate(AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a full reverse evaluation of the tape.
Definition commonTapeImplementation.hpp:293
void swap(Impl &other)
Swap all data with an other tape.
Definition commonTapeImplementation.hpp:368
typename CommonTapeTypes< ImplTapeTypes >::Position Position
See TapeTypesInterface.
Definition commonTapeImplementation.hpp:145
LowLevelFunctionByteData llfByteData
Byte data for low level functions.
Definition commonTapeImplementation.hpp:156
size_t getParameter(TapeParameters parameter) const
See Parameters functions.
Definition commonTapeImplementation.hpp:431
void evaluatePrimal()
Perform a full (forward) reevaluation of the primals in the tape.
Definition commonTapeImplementation.hpp:726
void internalStoreLowLevelFunction(Config::LowLevelFunctionToken token, size_t size, ByteDataView &dataView)
Called by the implementing tapes to store a low level function. The size is reserved and allocated....
Definition commonTapeImplementation.hpp:494
Data stream interface for tape data. Encapsulates data that is written e.g. for each statement or arg...
Definition dataInterface.hpp:149
Combines entries of Jacobians with the same identifier.
Definition duplicateJacobianRemover.hpp:58
void storeData(Vec &vec)
Definition duplicateJacobianRemover.hpp:98
static void notifyStatementStoreOnTapeListeners(Tape &tape, Identifier const &lhsIdentifier, Real const &newValue, size_t numActiveVariables, Identifier const *rhsIdentifiers, Real const *jacobians)
Invoke callbacks for StatementStoreOnTape events.
Definition eventSystem.hpp:676
static void notifyTapeEvaluateListeners(Tape &tape, Position const &start, Position const &end, VectorAccess *adjoint, EventHints::EvaluationKind evalKind, EventHints::Endpoint endpoint)
Invoke callbacks for TapeEvaluate events.
Definition eventSystem.hpp:486
static void notifyTapeRegisterInputListeners(Tape &tape, Real &value, Identifier &identifier)
Invoke callbacks for TapeRegisterInput events.
Definition eventSystem.hpp:424
Base class for all CoDiPack expressions.
Definition expressionInterface.hpp:59
Impl const & cast() const
Cast to the implementation.
Definition expressionInterface.hpp:75
Counts the number of nodes that inherit from LhsExpressionInterface in the expression.
Definition expressionTraits.hpp:184
Implement logic for leaf nodes only.
Definition forEachLeafLogic.hpp:60
Indices enable the mapping of primal values to their adjoint counterparts.
Definition indexManagerInterface.hpp:78
Whether the adjoint vector is global, that is, shared among different tapes.
Definition adjointVectorTraits.hpp:50
Abstracts the internal set of adjoint variables provided as part of the tape.
Definition internalAdjointsInterface.hpp:80
Pushes all delayed Jacobians.
Definition jacobianBaseTape.hpp:320
void handleActive(ReferenceActiveType< Type > const &node, DataVector &dataVector)
Specialization for ReferenceActiveType nodes. Pushes the delayed Jacobian.
Definition jacobianBaseTape.hpp:325
Pushes Jacobians and indices to the tape.
Definition jacobianBaseTape.hpp:288
void handleJacobianOnActive(Node const &node, Jacobian jacobianExpr, DataVector &dataVector)
General implementation. Checks for invalid and passive values/Jacobians.
Definition jacobianBaseTape.hpp:292
void handleJacobianOnActive(ReferenceActiveType< Type > const &node, Jacobian jacobianExpr, DataVector &dataVector)
Specialization for ReferenceActiveType nodes. Delays Jacobian push.
Definition jacobianBaseTape.hpp:306
Wrapper helper for improved compiler optimizations.
Definition jacobianBaseTape.hpp:565
Wrapper helper for improved compiler optimizations.
Definition jacobianBaseTape.hpp:546
Base class for all standard Jacobian tape implementations.
Definition jacobianBaseTape.hpp:128
void evaluateKeepState(Position const &start, Position const &end, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a tape evaluation but restore the state afterwards such that it is the same as when the evalu...
Definition jacobianBaseTape.hpp:888
void pushJacobians(ExpressionInterface< Real, Rhs > const &rhs)
Push Jacobians and delayed Jacobians to the tape.
Definition jacobianBaseTape.hpp:341
IndexManager & getIndexManager()
Returns a reference to the Index Manager.
Definition jacobianBaseTape.hpp:838
JacobianData jacobianData
Data stream for argument specific data.
Definition jacobianBaseTape.hpp:174
typename Base::Position Position
See TapeTypesInterface.
Definition jacobianBaseTape.hpp:152
size_t getParameter(TapeParameters parameter) const
See Parameters functions.
Definition jacobianBaseTape.hpp:645
typename TapeTypes::Gradient Gradient
See TapeTypesInterface.
Definition jacobianBaseTape.hpp:140
typename TapeTypes::JacobianData JacobianData
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:145
static void internalEvaluateReverse_EvalStatements(Args &&... args)
Perform a reverse evaluation of the tape. Arguments are from the recursive eval methods of the DataIn...
void resizeAdjointVector()
Explicitly trigger resizing of the adjoint vector. See Adjoint vector management.
Definition jacobianBaseTape.hpp:630
Gradient const & gradient(Identifier const &identifier, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic) const
Constant reference access to gradient.
Definition jacobianBaseTape.hpp:251
StatementData statementData
Data stream for statement specific data.
Definition jacobianBaseTape.hpp:173
void store(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &lhs, LhsExpressionInterface< Real, Gradient, Impl, Rhs > const &rhs)
Has to be called by an AD variable every time it is assigned.
Definition jacobianBaseTape.hpp:406
Adjoints adjoints
Evaluation vector for AD.
Definition jacobianBaseTape.hpp:176
void beginUseAdjointVector()
Declare that the adjoint vector is being used. See Adjoint vector management.
Definition jacobianBaseTape.hpp:635
static void incrementTangents(AdjointVector const &adjointVector, AdjointVectorTraits::Gradient< AdjointVector > &lhsAdjoint, Config::ArgumentSize const &numberOfArguments, size_t &curJacobianPos, Real const *const rhsJacobians, Identifier const *const rhsIdentifiers)
Performs the AD forward equation for a statement.
Definition jacobianBaseTape.hpp:550
Real const & primal(Identifier const &identifier) const
Not implemented, raises an exception.
Definition jacobianBaseTape.hpp:936
void pushStmtData(Identifier const &index, Config::ArgumentSize const &numberOfArguments)
Add statement specific data to the data streams.
TapeValues internalGetTapeValues() const
Adds data from all streams, the size of the adjoint vector and index manager data.
Definition jacobianBaseTape.hpp:488
typename TapeTypes::IndexManager IndexManager
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:141
friend Base
Allow the base class to call protected and private methods.
Definition jacobianBaseTape.hpp:137
void clearAdjoints(AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Clear all adjoint values, that is, set them to zero.
Definition jacobianBaseTape.hpp:471
void evaluateKeepState(Position const &start, Position const &end, AdjointVector &&data)
Perform a tape evaluation but restore the state afterwards such that it is the same as when the evalu...
Definition jacobianBaseTape.hpp:895
typename TapeTypes::template Adjoints< Impl > Adjoints
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:147
VectorAccess< decltype(adjoints.data())> * createVectorAccess()
See Adjoint vector access.
Definition jacobianBaseTape.hpp:686
void pushLowLevelFunction(Config::LowLevelFunctionToken token, size_t size, ByteDataView &data)
Push a low level function to the tape.
Definition jacobianBaseTape.hpp:848
VectorAccess< AdjointVector > * createVectorAccessCustomAdjoints(AdjointVector &&data)
Definition jacobianBaseTape.hpp:692
void endUseAdjointVector()
Declare that the adjoint vector is no longer used. See Adjoint vector management.
Definition jacobianBaseTape.hpp:640
static void internalEvaluateForward_EvalStatements(Args &&... args)
Perform a forward evaluation of the tape. Arguments are from the recursive eval methods of the DataIn...
void deleteAdjointVector()
Delete the adjoint vector. See Adjoint vector management.
Definition jacobianBaseTape.hpp:625
void swap(Impl &other)
Swap all data with an other tape.
Definition jacobianBaseTape.hpp:615
void evaluateForward(Position const &start, Position const &end, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a forward evaluation of a part of the tape. It has to hold start <= end.
Definition jacobianBaseTape.hpp:729
typename TapeTypes::Real Real
See TapeTypesInterface.
Definition jacobianBaseTape.hpp:139
typename TapeTypes::StatementData StatementData
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:144
T_Impl Impl
See JacobianBaseTape.
Definition jacobianBaseTape.hpp:134
Real & primal(Identifier const &identifier)
Not implemented, raises an exception.
Definition jacobianBaseTape.hpp:926
JacobianBaseTape()
Constructor.
Definition jacobianBaseTape.hpp:210
void store(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &lhs, Real const &rhs)
Has to be called by an AD variable every time it is assigned.
Definition jacobianBaseTape.hpp:425
void store(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &lhs, ExpressionInterface< Real, Rhs > const &rhs)
Has to be called by an AD variable every time it is assigned.
Definition jacobianBaseTape.hpp:365
static void incrementAdjoints(AdjointVector &adjointVector, AdjointVectorTraits::Gradient< AdjointVector > const &lhsAdjoint, Config::ArgumentSize const &numberOfArguments, size_t &curJacobianPos, Real const *const rhsJacobians, Identifier const *const rhsIdentifiers)
Performs the AD reverse equation for a statement.
Definition jacobianBaseTape.hpp:527
void evaluateForwardKeepState(Position const &start, Position const &end, AdjointVector &&data)
Perform a tape evaluation but restore the state afterwards such that it is the same as when the evalu...
Definition jacobianBaseTape.hpp:907
void setParameter(TapeParameters parameter, size_t value)
See Parameters functions.
Definition jacobianBaseTape.hpp:665
void evaluateForward(Position const &start, Position const &end, AdjointVector &&data)
Perform a reverse evaluation for a part of the tape. It hast to hold start >= end.
Definition jacobianBaseTape.hpp:591
void evaluate(Position const &start, Position const &end, AdjointVector &&data)
Perform a reverse evaluation for a part of the tape. It hast to hold start >= end.
Definition jacobianBaseTape.hpp:576
typename JacobianData::Position NestedPosition
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:151
static bool constexpr HasPrimalValues
See PrimalEvaluationTapeInterface.
Definition jacobianBaseTape.hpp:159
static bool constexpr RequiresPrimalRestore
See PrimalEvaluationTapeInterface.
Definition jacobianBaseTape.hpp:163
void evaluateForwardKeepState(Position const &start, Position const &end, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a tape evaluation but restore the state afterwards such that it is the same as when the evalu...
Definition jacobianBaseTape.hpp:900
void registerInput(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &value)
Definition jacobianBaseTape.hpp:465
static bool constexpr AllowJacobianOptimization
See InternalStatementRecordingTapeInterface.
Definition jacobianBaseTape.hpp:158
void storeManual(Real const &lhsValue, Identifier &lhsIndex, Config::ArgumentSize const &size)
Definition jacobianBaseTape.hpp:775
void writeTape(codi::TapeWriterInterface< Type > *writer, Position const &start, Position const &end)
For full or partial tapes using a pointer to the writer.
Definition jacobianBaseTape.hpp:824
VectorAccess< Adjoint * > * createVectorAccessCustomAdjoints(Adjoint *data)
Definition jacobianBaseTape.hpp:699
void evaluate(Position const &start, Position const &end, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Perform a reverse evaluation for a part of the tape. It hast to hold start >= end.
Definition jacobianBaseTape.hpp:866
void initIdentifier(Real &value, Identifier &identifier)
Definition jacobianBaseTape.hpp:269
void pushJacobianManual(Real const &jacobian, Real const &value, Identifier const &index)
Definition jacobianBaseTape.hpp:751
void createStatementManual(Real const &lhsValue, Identifier &lhsIndex, Config::ArgumentSize const &size, Real const *jacobians, Identifier const *rhsIdentifiers)
Definition jacobianBaseTape.hpp:798
void evaluatePrimal(Position const &start, Position const &end)
Not implemented, raises an exception.
Definition jacobianBaseTape.hpp:919
static bool constexpr LinearIndexHandling
See IdentifierInformationTapeInterface.
Definition jacobianBaseTape.hpp:161
Real registerExternalFunctionOutput(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &value)
Definition jacobianBaseTape.hpp:715
void destroyIdentifier(Real &value, Identifier &identifier)
Has to be called for each identifier, before it is deallocated.
Definition jacobianBaseTape.hpp:277
Gradient & gradient(Identifier const &identifier, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Reference access to gradient.
Definition jacobianBaseTape.hpp:239
RealTraits::PassiveReal< Real > PassiveReal
Basic computation type.
Definition jacobianBaseTape.hpp:149
T_TapeTypes TapeTypes
See JacobianBaseTape.
Definition jacobianBaseTape.hpp:132
MemberStore< IndexManager, Impl, TapeTypes::IsStaticIndexHandler > indexManager
Index manager.
Definition jacobianBaseTape.hpp:172
typename TapeTypes::Identifier Identifier
See TapeTypesInterface.
Definition jacobianBaseTape.hpp:142
void deleteVectorAccess(VectorAccessInterface< Real, Identifier > *access)
See Adjoint vector access.
Definition jacobianBaseTape.hpp:704
void internalRegisterInput(LhsExpressionInterface< Real, Gradient, Impl, Lhs > &value, bool unusedIndex)
Add a new input to the tape.
Definition jacobianBaseTape.hpp:440
decltype(adjoints.data()) getInternalAdjoints()
Obtain a representation of the tape's internal adjoint vector that can be used as custom adjoints.
Definition jacobianBaseTape.hpp:605
Definition jacobianComputationLogic.hpp:53
Type definitions for the Jacobian tapes.
Definition jacobianBaseTape.hpp:78
T_Real Real
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:81
typename std::conditional< IsLinearIndexHandler, Chunk1< Config::ArgumentSize >, Chunk2< Identifier, Config::ArgumentSize > >::type StatementChunk
Definition jacobianBaseTape.hpp:101
Data< JacobianChunk, StatementData > JacobianData
Jacobian data vector.
Definition jacobianBaseTape.hpp:106
Data< StatementChunk, IndexManager > StatementData
Statement data vector.
Definition jacobianBaseTape.hpp:103
T_Data< Chunk, Nested > Data
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:85
T_Gradient Gradient
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:82
T_IndexManager IndexManager
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:83
static bool constexpr IsLinearIndexHandler
True if the index manager is linear.
Definition jacobianBaseTape.hpp:95
T_Adjoints< Gradient, Identifier, Impl > Adjoints
See JacobianTapeTypes.
Definition jacobianBaseTape.hpp:92
typename IndexManager::Index Identifier
See IndexManagerInterface.
Definition jacobianBaseTape.hpp:88
JacobianData NestedData
See TapeTypesInterface.
Definition jacobianBaseTape.hpp:108
static bool constexpr IsStaticIndexHandler
True if the index manager must be stored statically in the tape.
Definition jacobianBaseTape.hpp:96
Default implementation of the Jacobian interface.
Definition jacobian.hpp:60
Base class for all CoDiPack lvalue expression.
Definition lhsExpressionInterface.hpp:63
Impl & cast()
Cast to the implementation.
Definition lhsExpressionInterface.hpp:99
Defines a member that can either be static or local to the struct.
Definition memberStore.hpp:56
Type & get()
Get a reference to the actual member.
Definition memberStore.hpp:76
Holds a reference to an ActiveType for manual optimization of common arguments.
Definition referenceActiveType.hpp:59
Interface for the definition of tape types.
Definition commonTapeImplementation.hpp:64
Tape information that can be printed in a pretty print format or a table format.
Definition tapeValues.hpp:75
void addUnsignedLongEntry(std::string const &name, unsigned long const &value, LocalReductionOperation operation=LocalReductionOperation::Sum)
Add unsigned long entry.
Definition tapeValues.hpp:163
void addDoubleEntry(std::string const &name, double const &value, LocalReductionOperation operation=LocalReductionOperation::Sum, bool usedMem=false, bool allocatedMem=false)
Add double entry. If it is a memory entry, it should be in bytes.
Definition tapeValues.hpp:137
void addSection(std::string const &name)
Add section. All further entries are added under this section.
Definition tapeValues.hpp:158
The interface used by all the tape writers. The tape writers are used to generate text,...
Definition tapeReaderWriterInterface.hpp:128
virtual void start(Tape &tape)
Destructor.
Definition tapeReaderWriterInterface.hpp:143
virtual void finish()
After all the statements have been written, the finish method finalizes the writing process.
Definition tapeReaderWriterInterface.hpp:176
void eval(NodeInterface< Node > const &node, Args &&... args)
Start the evaluation of the logic on the given expression.
Definition traversalLogic.hpp:70
void node(Node const &node, Args &&... args)
Called for each node in the expression.
Definition traversalLogic.hpp:86
Unified access to the adjoint vector and primal vector in a tape evaluation.
Definition vectorAccessInterface.hpp:91