CoDiPack  3.1.0
A Code Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
preaccumulationHelper.hpp
1/*
2 * CoDiPack, a Code Differentiation Package
3 *
4 * Copyright (C) 2015-2026 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
36#pragma once
37
38#include <vector>
39
40#include "../../config.h"
41#include "../../expressions/lhsExpressionInterface.hpp"
42#include "../../misc/exceptions.hpp"
43#include "../../tapes/interfaces/fullTapeInterface.hpp"
44#include "../../tapes/tagging/tagTapeReverse.hpp"
45#include "../../traits/gradientTraits.hpp"
46#include "../../traits/tapeTraits.hpp"
47#include "../algorithms.hpp"
48#include "../data/customAdjoints.hpp"
49#include "../data/jacobian.hpp"
50
52namespace codi {
53
76 template<typename T_Type, typename = void>
78 public:
79
81 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
82
83 using Real = typename Type::Real;
84 using Identifier = typename Type::Identifier;
85 using Gradient = typename Type::Gradient;
86 using TapeData = typename Type::TapeData;
87
89 using Tape = CODI_DD(typename Type::Tape, CODI_DEFAULT_TAPE);
90 using Position = typename Tape::Position;
91
92 std::vector<Identifier> inputData;
94 std::vector<TapeData> inputTapeData;
95 std::vector<Identifier> outputData;
97 std::vector<Type*> outputValues;
99
100 std::vector<Gradient> localAdjoints;
102
103 protected:
104
106 std::vector<Gradient> storedAdjoints;
108
109 public:
110
113 : inputData(),
115 outputData(),
116 outputValues(),
118 startPos(),
120 jacobian(0, 0) {}
121
123 template<typename... Inputs>
124 void addInput(Inputs const&... inputs) {
125 Tape& tape = Type::getTape();
126
127 if (tape.isActive()) {
128 addInputRecursive(inputs...);
129 }
130 }
131
133 template<typename... Inputs>
134 void start(Inputs const&... inputs) {
135 Tape& tape = Type::getTape();
136
138
139 if (tape.isActive()) {
140 inputData.clear();
141 inputTapeData.clear();
142 outputData.clear();
143 outputValues.clear();
144
145 startPos = tape.getPosition();
146
147 addInputRecursive(inputs...);
148 }
149 }
150
152 template<typename... Outputs>
153 void addOutput(Outputs&... outputs) {
154 Tape& tape = Type::getTape();
155
156 if (tape.isActive()) {
157 addOutputRecursive(outputs...);
158 }
159 }
160
161 protected:
163 template<typename Func, typename... Outputs>
164 void finishInternal(Func& coreRoutine, Outputs&... outputs) {
165 Tape& tape = Type::getTape();
166
167 if (tape.isActive()) {
168 addOutputRecursive(outputs...);
169
170 tape.setPassive();
171 coreRoutine();
172 storeJacobian();
173 tape.setActive();
174 }
175
177 }
178
179 public:
184 template<typename... Outputs>
185 void finish(bool const storeAdjoints, Outputs&... outputs) {
186 auto coreRoutine = [&storeAdjoints, this]() {
187 if (storeAdjoints) {
188 storeInputAdjoints();
189 }
190 computeJacobian();
191 if (storeAdjoints) {
192 restoreInputAdjoints();
193 }
194 };
195
196 finishInternal(coreRoutine, outputs...);
197 }
198
201 template<typename... Outputs>
202 void finishLocalMappedAdjoints(Outputs&... outputs) {
203 auto coreRoutine = [this]() {
204 computeJacobianLocalMappedAdjoints();
205 };
206
207 finishInternal(coreRoutine, outputs...);
208 }
209
214 template<typename... Outputs>
215 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
216 auto coreRoutine = [this]() {
217 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>(); // otherwise
218 // computeJacobianLocalMappedAdjoints
219 };
220
221 finishInternal(coreRoutine, outputs...);
222 }
223
227 template<typename... Outputs>
228 void finishLocalAdjoints(Outputs&... outputs) {
229 auto coreRoutine = [this]() {
230 if (std::min(inputData.size(), outputData.size()) > 1) {
231 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>(); // otherwise
232 // computeJacobianLocalMappedAdjoints
233 } else {
234 computeJacobianLocalMappedAdjoints();
235 }
236 };
237
238 finishInternal(coreRoutine, outputs...);
239 }
240
243 template<typename... Outputs>
244 void finishLocalAdjointVector(Outputs&... outputs) {
245 auto coreRoutine = [this]() {
246 computeJacobianLocalAdjointVector();
247 };
248
249 finishInternal(coreRoutine, outputs...);
250 }
251
256 template<typename... Outputs>
257 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
258 auto coreRoutine = [this]() {
259 computeJacobianLocalAdjointVectorOffsetIfAvailable<Tape>(); // otherwise
260 // computeJacobianLocalAdjointVector
261 };
262
263 finishInternal(coreRoutine, outputs...);
264 }
265
266 private:
267
268 // Tape supports editing -> use a map to edit its identifiers. Disabled by SFINAE otherwise.
269 template<typename Tape>
270 TapeTraits::EnableIfSupportsEditing<Tape> computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable() {
271 computeJacobianLocalAdjointVectorPreprocessTape();
272 }
273
274 // Tape does not support editing -> use a map for the adjoints. Disabled by SFINAE otherwise.
275 template<typename Tape>
276 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable() {
277 computeJacobianLocalMappedAdjoints();
278 }
279
280 // Tape supports editing -> use a map to edit its identifiers. Disabled by SFINAE otherwise.
281 template<typename Tape>
282 TapeTraits::EnableIfSupportsEditing<Tape> computeJacobianLocalAdjointVectorOffsetIfAvailable() {
283 computeJacobianLocalAdjointVectorOffset();
284 }
285
286 // Tape does not support editing -> use a map for the adjoints. Disabled by SFINAE otherwise.
287 template<typename Tape>
288 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointVectorOffsetIfAvailable() {
289 computeJacobianLocalAdjointVector();
290 }
291
292 void addInputLogic(Type const& input) {
293 EventSystem<Tape>::notifyPreaccAddInputListeners(Type::getTape(), input.getValue(), input.getIdentifier());
294 Identifier const& identifier = input.getIdentifier();
295 if (Type::getTape().getPassiveIndex() != identifier) {
296 inputData.push_back(identifier);
297 inputTapeData.push_back(input.getTapeData());
298 }
299 }
300
302 void addInputRecursive() {
303 // Terminator implementation.
304 }
305
306 template<typename... Inputs>
307 void addInputRecursive(Type const& input, Inputs const&... r) {
308 addInputLogic(input);
309 addInputRecursive(r...);
310 }
311
312 void addOutputLogic(Type& output) {
313 EventSystem<Tape>::notifyPreaccAddOutputListeners(Type::getTape(), output.value(), output.getIdentifier());
314 Identifier const& identifier = output.getIdentifier();
315 if (Type::getTape().getPassiveIndex() != identifier) {
316 outputData.push_back(identifier);
317 outputValues.push_back(&output);
318 }
319 }
320
322 void addOutputRecursive() {
323 // Terminator implementation.
324 }
325
326 template<typename... Outputs>
327 void addOutputRecursive(Type& output, Outputs&... r) {
328 addOutputLogic(output);
329 addOutputRecursive(r...);
330 }
331
332 void storeInputAdjoints() {
333 Tape& tape = Type::getTape();
334
335 if (storedAdjoints.size() < inputData.size()) {
336 storedAdjoints.resize(inputData.size());
337 }
338
339 for (size_t i = 0; i < inputData.size(); ++i) {
340 Identifier index = inputData[i];
341 Gradient& adjoint = tape.gradient(index);
342 storedAdjoints[i] = adjoint;
343 adjoint = Gradient();
344 }
345 }
346
347 void restoreInputAdjoints() {
348 Tape& tape = Type::getTape();
349
350 for (size_t i = 0; i < inputData.size(); ++i) {
351 Identifier index = inputData[i];
352 tape.gradient(index) = storedAdjoints[i];
353 }
354 }
355
356 void resizeJacobian() {
357 if (jacobian.getM() != outputData.size() || jacobian.getN() != inputData.size()) {
358 jacobian.resize(outputData.size(), inputData.size());
359 }
360 }
361
362 void computeJacobian() {
363 // Perform the accumulation of the tape part.
364 Tape& tape = Type::getTape();
365 Position endPos = tape.getPosition();
366
367 resizeJacobian();
368
369 // Manage adjoints manually to reduce the impact of locking on the performance.
370 tape.resizeAdjointVector();
371 tape.beginUseAdjointVector();
372
374 outputData.data(), outputData.size(), jacobian,
376
377 tape.resetTo(startPos, true, AdjointsManagement::Manual);
378
379 tape.endUseAdjointVector();
380 }
381
382 void computeJacobianLocalAdjointVector() {
383 // Perform the accumulation of the tape part.
384 Tape& tape = Type::getTape();
385 Position endPos = tape.getPosition();
386
387 resizeJacobian();
388
389 size_t requiredVectorSize = tape.getParameter(TapeParameters::LargestIdentifier) + 1;
390
391 this->localAdjoints.resize(requiredVectorSize);
392
394 outputData.data(), outputData.size(), jacobian,
395 this->localAdjoints.data());
396
397 tape.resetTo(startPos, false);
398 }
399
400 void computeJacobianLocalAdjointVectorOffset() {
401 // Perform the accumulation of the tape part.
402 Tape& tape = Type::getTape();
403 Position endPos = tape.getPosition();
404
405 resizeJacobian();
406
407 // Determine minimum and maximum identifier used in the recording.
408
409 Identifier minIdentifier = std::numeric_limits<Identifier>::max();
410 Identifier maxIdentifier = std::numeric_limits<Identifier>::min();
411
412 auto determineMinMaxIdentifier = [&minIdentifier, &maxIdentifier](typename Tape::Identifier const& identifier) {
413 minIdentifier = std::min(minIdentifier, identifier);
414 maxIdentifier = std::max(maxIdentifier, identifier);
415 };
416
417 // Begin by processing inputs and outputs.
418 for (auto const& identifier : inputData) {
419 determineMinMaxIdentifier(identifier);
420 }
421
422 for (auto const& identifier : outputData) {
423 determineMinMaxIdentifier(identifier);
424 }
425
426 // Process the tape. Does not edit identifiers in the tape.
427 tape.editIdentifiers(determineMinMaxIdentifier, startPos, endPos);
428
429 // Plus one to cover the range [minIdentifier, maxIdentifier].
430 size_t requiredVectorSize = maxIdentifier - minIdentifier + 1;
431 this->localAdjoints.resize(requiredVectorSize);
432
433 // Define adjoints that take into account the offset when addressing into the vector.
434 using LocalAdjointsOffset = AdjointVectorWithOffset<Identifier, Gradient>;
435 LocalAdjointsOffset localAdjointsOffset(this->localAdjoints.data(), minIdentifier);
436
437 // Preaccumulation with a local adjoint vector and identifier offsets.
439 outputData.data(), outputData.size(), jacobian,
440 localAdjointsOffset);
441
442 tape.resetTo(startPos, false);
443 }
444
445 void computeJacobianLocalMappedAdjoints() {
446 // Perform the accumulation of the tape part.
447 Tape& tape = Type::getTape();
448 Position endPos = tape.getPosition();
449
450 resizeJacobian();
451
452 // Create a local map with adjoints.
453 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
454 LocalMappedAdjoints mappedAdjoints;
455
457 outputData.data(), outputData.size(), jacobian,
458 mappedAdjoints);
459
460 tape.resetTo(startPos, false);
461 }
462
463 void computeJacobianLocalAdjointVectorPreprocessTape() {
464 // Perform the accumulation of the tape part.
465 Tape& tape = Type::getTape();
466 Position endPos = tape.getPosition();
467
468 resizeJacobian();
469
470 // Used internally for remapping identifiers.
471 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
472
473 // Build a map of identifiers, remapping identifiers in the recording to contiguous ones.
474 auto nextIdentifier = typename Tape::Identifier() + 1;
475 IdentifierMap oldToNewIdentifierMap;
476
477 // If needed, inserts the old identifier into the map and associates it with the next identifier. Either way,
478 // returns the associated new identifier.
479 auto accessOldToNewIdentifierMap = [&](typename Tape::Identifier const& oldIdentifier) ->
480 typename Tape::Identifier const& {
481 auto result = oldToNewIdentifierMap.insert({oldIdentifier, nextIdentifier});
482 if (result.second) { // insertion took place
483 ++nextIdentifier;
484 }
485 return result.first->second;
486 };
487
488 // Remap input identifiers explicitly to account for inputs that are actually not used in the recording.
489 for (auto const& oldIdentifier : inputData) {
490 accessOldToNewIdentifierMap(oldIdentifier);
491 }
492
493 // Remap output identifiers explicitly to account for outputs that actually do not depend on the inputs.
494 for (auto const& oldIdentifier : outputData) {
495 accessOldToNewIdentifierMap(oldIdentifier);
496 }
497
498 auto editIdentifier = [&](typename Tape::Identifier& oldIdentifier) {
499 oldIdentifier = accessOldToNewIdentifierMap(oldIdentifier);
500 };
501
502 // Process the recording to complete the map, edit the tape on the fly.
503 tape.editIdentifiers(editIdentifier, startPos, endPos);
504
505 // Build new vectors of input and output identifiers.
506 std::vector<typename Tape::Identifier> newInputData;
507 newInputData.reserve(inputData.size());
508 for (auto const& identifier : inputData) {
509 newInputData.push_back(oldToNewIdentifierMap[identifier]);
510 }
511
512 std::vector<typename Tape::Identifier> newOutputData;
513 newOutputData.reserve(outputData.size());
514 for (auto const& identifier : outputData) {
515 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
516 }
517
518 // The association with the original input/output identifiers and Jacobian entries is made by position, so we no
519 // longer need the identifier map.
520 oldToNewIdentifierMap.clear();
521
522 // Create local adjoints. nextIdentifier holds the local adjoint vector size.
523 std::vector<typename Tape::Gradient> localAdjoints(nextIdentifier);
524
525 // Preaccumulation with remapped identifiers on local adjoints.
527 newInputData.size(), newOutputData.data(),
528 newOutputData.size(), jacobian, localAdjoints.data());
529
530 tape.resetTo(startPos, false);
531 }
532
533 void storeJacobian() {
534 Tape& tape = Type::getTape();
535
536 for (size_t curOut = 0; curOut < outputData.size(); ++curOut) {
537 Type& value = *outputValues[curOut];
538 if (0 != jacobian.nonZerosRow(curOut)) {
539 int nonZerosLeft = jacobian.nonZerosRow(curOut);
540 jacobian.nonZerosRow(curOut) = 0;
541
542 // We need to initialize with the output's current identifier such that it is correctly deleted in
543 // storeManual.
544 TapeData lastIdentifier = value.getTapeData();
545 bool staggeringActive = false;
546 int curIn = 0;
547
548 // Push statements as long as there are nonzeros left.
549 // If there are more than MaxStatementIntValue nonzeros, then we need to stagger the
550 // statement pushes:
551 // e.g. The reverse mode of w = f(u0, ..., u530) which is \bar u_i += df/du_i * \bar w for i = 0 ... 530 is
552 // separated into
553 // Statement 1:
554 // \bar u_i += df/du_i * \bar t_1 for i = 0 ... 253 (254 entries)
555 // Statement 2:
556 // \bar t_1 += \bar w (1 entry)
557 // \bar u_i += df/du_i * \bar t_2 for i = 254 ... 506 (253 entries)
558 // Statement 3:
559 // \bar t_2 += \bar w (1 entry)
560 // \bar u_i += df/du_i * \bar w for i = 507 ... 530 (24 entries)
561 //
562 while (nonZerosLeft > 0) {
563 // Calculate the number of Jacobians for this statement.
564 int jacobiansForStatement = nonZerosLeft;
565 if (jacobiansForStatement > (int)Config::MaxArgumentSize) {
566 jacobiansForStatement = (int)Config::MaxArgumentSize - 1;
567 if (staggeringActive) { // Except in the first round, one Jacobian is reserved for the staggering.
568 jacobiansForStatement -= 1;
569 }
570 }
571 nonZerosLeft -= jacobiansForStatement; // Update nonzeros so that we know if it is the last round.
572
573 TapeData storedIdentifier = lastIdentifier;
574 // storeManual creates a new identifier which is either the identifier of the output w or the temporary
575 // staggering variables t_1, t_2, ...
576 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (int)staggeringActive);
577 if (staggeringActive) { // Not the first staggering so push the last output.
578 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
579 }
580
581 // Push the rest of the Jacobians for the statement.
582 while (jacobiansForStatement > 0) {
583 if (Real() != (Real)jacobian(curOut, curIn)) {
584 tape.pushJacobianManual(jacobian(curOut, curIn), 0.0, inputTapeData[curIn]);
585 jacobiansForStatement -= 1;
586 }
587 curIn += 1;
588 }
589
590 staggeringActive = true;
591 }
592
593 value.getTapeData() = lastIdentifier; /* now set gradient data for the real output value */
594 } else {
595 // Disable tape index since there is no dependency.
596 tape.destroyTapeData(value.value(), value.getTapeData());
597 }
598 }
599 }
600 };
601
602#ifndef DOXYGEN_DISABLE
608 struct PreaccumulationHelperNoOpBase {
609 public:
610
612 template<typename... Inputs>
613 void addInput(Inputs const&... inputs) {
614 CODI_UNUSED(inputs...);
615 // Do nothing.
616 }
617
619 template<typename... Inputs>
620 void start(Inputs const&... inputs) {
621 CODI_UNUSED(inputs...);
622 // Do nothing.
623 }
624
626 template<typename... Outputs>
627 void addOutput(Outputs&... outputs) {
628 CODI_UNUSED(outputs...);
629 // Do nothing.
630 }
631
633 template<typename... Outputs>
634 void finish(bool const storeAdjoints, Outputs&... outputs) {
635 CODI_UNUSED(storeAdjoints, outputs...);
636 // Do nothing.
637 }
638
640 template<typename... Outputs>
641 void finishLocalMappedAdjoints(Outputs&... outputs) {
642 CODI_UNUSED(outputs...);
643 // Do nothing.
644 }
645
647 template<typename... Outputs>
648 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
649 CODI_UNUSED(outputs...);
650 // Do nothing.
651 }
652
654 template<typename... Outputs>
655 void finishLocalAdjoints(Outputs&... outputs) {
656 CODI_UNUSED(outputs...);
657 // Do nothing.
658 }
659
661 template<typename... Outputs>
662 void finishLocalAdjointVector(Outputs&... outputs) {
663 CODI_UNUSED(outputs...);
664 // Do nothing.
665 }
666
668 template<typename... Outputs>
669 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
670 CODI_UNUSED(outputs...);
671 // Do nothing.
672 }
673 };
674
676 template<typename Type>
677 struct PreaccumulationHelper<Type, TapeTraits::EnableIfForwardTape<typename Type::Tape>>
678 : public PreaccumulationHelperNoOpBase {};
679
681 template<>
682 struct PreaccumulationHelper<double, void> : public PreaccumulationHelperNoOpBase {};
683
691 template<typename T_Type>
692 struct PreaccumulationHelper<T_Type, TapeTraits::EnableIfTagTapeReverse<typename T_Type::Tape>> {
693 public:
694
695 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
696
697 using Tape = CODI_DD(typename Type::Tape, CODI_T(TagTapeReverse<Type, int>));
698 using Tag = typename Tape::Tag;
699
700 private:
701
702 std::vector<Type const*> inputLocations;
703 std::vector<Type*> outputLocations;
704 Tag oldTag;
705
706 public:
707
710
712 template<typename... Inputs>
713 void addInput(Inputs const&... inputs) {
714 Tape& tape = getTape();
715
716 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
717 addInputRecursive(inputs...);
718 }
719 }
720
722 template<typename... Inputs>
723 void start(Inputs const&... inputs) {
724 Tape& tape = getTape();
725
726 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
727 inputLocations.clear();
728 outputLocations.clear();
729
730 oldTag = tape.getCurTag();
731 tape.setCurTag(tape.getPreaccumulationHandlingTag());
732
733 addInputRecursive(inputs...);
734 }
735 }
736
738 template<typename... Outputs>
739 void addOutput(Outputs&... outputs) {
740 Tape& tape = getTape();
741
742 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
743 addOutputRecursive(outputs...);
744 }
745 }
746
748 template<typename... Outputs>
749 void finish(bool const storeAdjoints, Outputs&... outputs) {
750 CODI_UNUSED(storeAdjoints);
751
752 Tape& tape = getTape();
753
754 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
755 addOutputRecursive(outputs...);
756
757 tape.setCurTag(oldTag);
758 for (Type const* curInput : inputLocations) {
759 tape.setTagOnVariable(*curInput);
760 }
761 for (Type* curOutput : outputLocations) {
762 tape.setTagOnVariable(*curOutput);
763 }
764 }
765 }
766
768 template<typename... Outputs>
769 void finishLocalMappedAdjoints(Outputs&... outputs) {
770 finish(false, outputs...);
771 }
772
774 template<typename... Outputs>
775 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
776 finish(false, outputs...);
777 }
778
780 template<typename... Outputs>
781 void finishLocalAdjoints(Outputs&... outputs) {
782 finish(false, outputs...);
783 }
784
786 template<typename... Outputs>
787 void finishLocalAdjointVector(Outputs&... outputs) {
788 finish(false, outputs...);
789 }
790
792 template<typename... Outputs>
793 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
794 finish(false, outputs...);
795 }
796
797 private:
798
800 void addInputRecursive() {
801 // Terminator implementation.
802 }
803
804 template<typename... Inputs>
805 void addInputRecursive(Type const& input, Inputs const&... r) {
806 handleInput(input);
807 addInputRecursive(r...);
808 }
809
810 void handleInput(Type const& input) {
811 Tape& tape = getTape();
812
813 if (tape.getPassiveIndex() != input.getIdentifier()) {
814 inputLocations.push_back(&input);
815 tape.setTagOnVariable(input);
816 }
817 }
818
820 void addOutputRecursive() {
821 // Terminator implementation.
822 }
823
824 template<typename... Outputs>
825 void addOutputRecursive(Type& output, Outputs&... r) {
826 handleOutput(output);
827 addOutputRecursive(r...);
828 }
829
830 void handleOutput(Type& value) {
831 outputLocations.push_back(&value);
832 }
833
834 Tape& getTape() {
835 return Type::getTape();
836 }
837 };
838#endif
839}
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:469
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:97
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition macros.hpp:117
size_t constexpr MaxArgumentSize
Maximum number of arguments in a statement.
Definition config.h:120
Definition tapeTraits.hpp:63
typename std::enable_if< SupportsEditing< Tape >::value >::type EnableIfSupportsEditing
Enable if wrapper for SupportsEditing.
Definition tapeTraits.hpp:170
typename std::enable_if< IsTagTapeReverse< Tape >::value >::type EnableIfTagTapeReverse
Enable if wrapper for IsTagTape.
Definition tapeTraits.hpp:217
typename std::enable_if< IsForwardTape< Tape >::value >::type EnableIfForwardTape
Enable if wrapper for IsForwardTape.
Definition tapeTraits.hpp:91
typename std::enable_if<!SupportsEditing< Tape >::value >::type EnableIfNoEditing
Enable if wrapper for SupportsEditing.
Definition tapeTraits.hpp:174
CoDiPack - Code Differentiation Package.
Definition codi.hpp:97
@ LargestIdentifier
[A: R] Largest identifier distributed by the index manger.
Definition tapeParameters.hpp:60
inlinevoid CODI_UNUSED(Args const &...)
Disable unused warnings for an arbitrary number of arguments.
Definition macros.hpp:55
@ Manual
Do not perform any bounds checking, locking, or resizing.
Definition tapeParameters.hpp:101
static inlinevoid computeJacobian(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointsManagement adjointsManagement=AdjointsManagement::Automatic)
Compute the Jacobian with multiple tape sweeps.
Definition algorithms.hpp:142
static inlinevoid 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)
Compute the Jacobian with multiple tape sweeps using a custom adjoint vector.
Definition algorithms.hpp:172
static inlinevoid notifyPreaccAddInputListeners(Tape &tape, Real const &value, Identifier const &identifier)
Invoke callbacks for PreaccAddInput events.
Definition eventSystem.hpp:607
static inlinevoid notifyPreaccAddOutputListeners(Tape &tape, Real &value, Identifier &identifier)
Invoke callbacks for PreaccAddOutput events.
Definition eventSystem.hpp:636
static inlinevoid notifyPreaccFinishListeners(Tape &tape)
Invoke callbacks for PreaccFinish events.
Definition eventSystem.hpp:579
static inlinevoid notifyPreaccStartListeners(Tape &tape)
Invoke callbacks for PreaccStart events.
Definition eventSystem.hpp:553
Adds counting of nonzero entries.
Definition jacobian.hpp:129
Stores the Jacobian matrix for a code section.
Definition preaccumulationHelper.hpp:77
void finishLocalAdjoints(Outputs &... outputs)
Definition preaccumulationHelper.hpp:228
void finishLocalAdjointVectorPreprocessTape(Outputs &... outputs)
Definition preaccumulationHelper.hpp:215
void finish(bool const storeAdjoints, Outputs &... outputs)
Definition preaccumulationHelper.hpp:185
std::vector< Gradient > storedAdjoints
If adjoints of inputs should be stored, before the preaccumulation.
Definition preaccumulationHelper.hpp:106
Position startPos
Starting position for the region.
Definition preaccumulationHelper.hpp:105
PreaccumulationHelper()
Constructor.
Definition preaccumulationHelper.hpp:112
typename Type::Tape Tape
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:89
void finishLocalAdjointVector(Outputs &... outputs)
Definition preaccumulationHelper.hpp:244
void addInput(Inputs const &... inputs)
Add multiple additional inputs. Inputs need to be of type Type. Called after start().
Definition preaccumulationHelper.hpp:124
std::vector< Identifier > inputData
Definition preaccumulationHelper.hpp:92
T_Type Type
See PreaccumulationHelper.
Definition preaccumulationHelper.hpp:81
std::vector< TapeData > inputTapeData
List of input tape data. Used for the manual statement push.
Definition preaccumulationHelper.hpp:94
void finishLocalMappedAdjoints(Outputs &... outputs)
Definition preaccumulationHelper.hpp:202
typename Tape::Position Position
See PositionalEvaluationTapeInterface.
Definition preaccumulationHelper.hpp:90
void finishInternal(Func &coreRoutine, Outputs &... outputs)
Internal implementation of workflow for preaccumulation with local adjoints.
Definition preaccumulationHelper.hpp:164
typename Type::Identifier Identifier
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:84
typename Type::Gradient Gradient
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:85
std::vector< Type * > outputValues
Definition preaccumulationHelper.hpp:97
std::vector< Identifier > outputData
Definition preaccumulationHelper.hpp:95
typename Type::Real Real
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:83
void start(Inputs const &... inputs)
Starts a preaccumulation region. Resets the internal state. See addInputs() for inputs.
Definition preaccumulationHelper.hpp:134
void addOutput(Outputs &... outputs)
Add multiple additional outputs. Outputs need to be of type Type. Called before finish().
Definition preaccumulationHelper.hpp:153
std::vector< Gradient > localAdjoints
Definition preaccumulationHelper.hpp:100
typename Type::TapeData TapeData
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:86
JacobianCountNonZerosRow< Real > jacobian
Jacobian for the preaccumulation.
Definition preaccumulationHelper.hpp:107
void finishLocalAdjointVectorOffset(Outputs &... outputs)
Definition preaccumulationHelper.hpp:257