CoDiPack  3.0.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-2025 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
88 using Tape = CODI_DD(typename Type::Tape, CODI_DEFAULT_TAPE);
89 using Position = typename Tape::Position;
90
91 std::vector<Identifier> inputData;
93 std::vector<Identifier> outputData;
95 std::vector<Type*> outputValues;
97
98 std::vector<Gradient> localAdjoints;
100
101 protected:
102
104 std::vector<Gradient> storedAdjoints;
106
107 public:
108
112
114 template<typename... Inputs>
115 void addInput(Inputs const&... inputs) {
116 Tape& tape = Type::getTape();
117
118 if (tape.isActive()) {
119 addInputRecursive(inputs...);
120 }
121 }
122
124 template<typename... Inputs>
125 void start(Inputs const&... inputs) {
126 Tape& tape = Type::getTape();
127
129
130 if (tape.isActive()) {
131 inputData.clear();
132 outputData.clear();
133 outputValues.clear();
134
135 startPos = tape.getPosition();
136
137 addInputRecursive(inputs...);
138 }
139 }
140
142 template<typename... Outputs>
143 void addOutput(Outputs&... outputs) {
144 Tape& tape = Type::getTape();
145
146 if (tape.isActive()) {
147 addOutputRecursive(outputs...);
148 }
149 }
150
151 protected:
153 template<typename Func, typename... Outputs>
154 void finishInternal(Func& coreRoutine, Outputs&... outputs) {
155 Tape& tape = Type::getTape();
156
157 if (tape.isActive()) {
158 addOutputRecursive(outputs...);
159
160 tape.setPassive();
161 coreRoutine();
162 storeJacobian();
163 tape.setActive();
164 }
165
167 }
168
169 public:
174 template<typename... Outputs>
175 void finish(bool const storeAdjoints, Outputs&... outputs) {
176 auto coreRoutine = [&storeAdjoints, this]() {
177 if (storeAdjoints) {
178 storeInputAdjoints();
179 }
180 computeJacobian();
181 if (storeAdjoints) {
182 restoreInputAdjoints();
183 }
184 };
185
186 finishInternal(coreRoutine, outputs...);
187 }
188
191 template<typename... Outputs>
192 void finishLocalMappedAdjoints(Outputs&... outputs) {
193 auto coreRoutine = [this]() {
194 computeJacobianLocalMappedAdjoints();
195 };
196
197 finishInternal(coreRoutine, outputs...);
198 }
199
204 template<typename... Outputs>
205 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
206 auto coreRoutine = [this]() {
207 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>(); // otherwise
208 // computeJacobianLocalMappedAdjoints
209 };
210
211 finishInternal(coreRoutine, outputs...);
212 }
213
217 template<typename... Outputs>
218 void finishLocalAdjoints(Outputs&... outputs) {
219 auto coreRoutine = [this]() {
220 if (std::min(inputData.size(), outputData.size()) > 1) {
221 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>(); // otherwise
222 // computeJacobianLocalMappedAdjoints
223 } else {
224 computeJacobianLocalMappedAdjoints();
225 }
226 };
227
228 finishInternal(coreRoutine, outputs...);
229 }
230
233 template<typename... Outputs>
234 void finishLocalAdjointVector(Outputs&... outputs) {
235 auto coreRoutine = [this]() {
236 computeJacobianLocalAdjointVector();
237 };
238
239 finishInternal(coreRoutine, outputs...);
240 }
241
246 template<typename... Outputs>
247 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
248 auto coreRoutine = [this]() {
249 computeJacobianLocalAdjointVectorOffsetIfAvailable<Tape>(); // otherwise
250 // computeJacobianLocalAdjointVector
251 };
252
253 finishInternal(coreRoutine, outputs...);
254 }
255
256 private:
257
258 // Tape supports editing -> use a map to edit its identifiers. Disabled by SFINAE otherwise.
259 template<typename Tape>
260 TapeTraits::EnableIfSupportsEditing<Tape> computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable() {
261 computeJacobianLocalAdjointVectorPreprocessTape();
262 }
263
264 // Tape does not support editing -> use a map for the adjoints. Disabled by SFINAE otherwise.
265 template<typename Tape>
266 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable() {
267 computeJacobianLocalMappedAdjoints();
268 }
269
270 // Tape supports editing -> use a map to edit its identifiers. Disabled by SFINAE otherwise.
271 template<typename Tape>
272 TapeTraits::EnableIfSupportsEditing<Tape> computeJacobianLocalAdjointVectorOffsetIfAvailable() {
273 computeJacobianLocalAdjointVectorOffset();
274 }
275
276 // Tape does not support editing -> use a map for the adjoints. Disabled by SFINAE otherwise.
277 template<typename Tape>
278 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointVectorOffsetIfAvailable() {
279 computeJacobianLocalAdjointVector();
280 }
281
282 void addInputLogic(Type const& input) {
283 EventSystem<Tape>::notifyPreaccAddInputListeners(Type::getTape(), input.getValue(), input.getIdentifier());
284 Identifier const& identifier = input.getIdentifier();
285 if (Type::getTape().getPassiveIndex() != identifier) {
286 inputData.push_back(identifier);
287 }
288 }
289
291 void addInputRecursive() {
292 // Terminator implementation.
293 }
294
295 template<typename... Inputs>
296 void addInputRecursive(Type const& input, Inputs const&... r) {
297 addInputLogic(input);
298 addInputRecursive(r...);
299 }
300
301 void addOutputLogic(Type& output) {
302 EventSystem<Tape>::notifyPreaccAddOutputListeners(Type::getTape(), output.value(), output.getIdentifier());
303 Identifier const& identifier = output.getIdentifier();
304 if (Type::getTape().getPassiveIndex() != identifier) {
305 outputData.push_back(identifier);
306 outputValues.push_back(&output);
307 }
308 }
309
311 void addOutputRecursive() {
312 // Terminator implementation.
313 }
314
315 template<typename... Outputs>
316 void addOutputRecursive(Type& output, Outputs&... r) {
317 addOutputLogic(output);
318 addOutputRecursive(r...);
319 }
320
321 void storeInputAdjoints() {
322 Tape& tape = Type::getTape();
323
324 if (storedAdjoints.size() < inputData.size()) {
325 storedAdjoints.resize(inputData.size());
326 }
327
328 for (size_t i = 0; i < inputData.size(); ++i) {
329 Identifier index = inputData[i];
330 Gradient& adjoint = tape.gradient(index);
331 storedAdjoints[i] = adjoint;
332 adjoint = Gradient();
333 }
334 }
335
336 void restoreInputAdjoints() {
337 Tape& tape = Type::getTape();
338
339 for (size_t i = 0; i < inputData.size(); ++i) {
340 Identifier index = inputData[i];
341 tape.gradient(index) = storedAdjoints[i];
342 }
343 }
344
345 void resizeJacobian() {
346 if (jacobian.getM() != outputData.size() || jacobian.getN() != inputData.size()) {
347 jacobian.resize(outputData.size(), inputData.size());
348 }
349 }
350
351 void computeJacobian() {
352 // Perform the accumulation of the tape part.
353 Tape& tape = Type::getTape();
354 Position endPos = tape.getPosition();
355
356 resizeJacobian();
357
358 // Manage adjoints manually to reduce the impact of locking on the performance.
359 tape.resizeAdjointVector();
360 tape.beginUseAdjointVector();
361
363 outputData.data(), outputData.size(), jacobian,
365
366 tape.resetTo(startPos, true, AdjointsManagement::Manual);
367
368 tape.endUseAdjointVector();
369 }
370
371 void computeJacobianLocalAdjointVector() {
372 // Perform the accumulation of the tape part.
373 Tape& tape = Type::getTape();
374 Position endPos = tape.getPosition();
375
376 resizeJacobian();
377
378 size_t requiredVectorSize = tape.getParameter(TapeParameters::LargestIdentifier) + 1;
379
380 this->localAdjoints.resize(requiredVectorSize);
381
383 outputData.data(), outputData.size(), jacobian,
384 this->localAdjoints.data());
385
386 tape.resetTo(startPos, false);
387 }
388
389 void computeJacobianLocalAdjointVectorOffset() {
390 // Perform the accumulation of the tape part.
391 Tape& tape = Type::getTape();
392 Position endPos = tape.getPosition();
393
394 resizeJacobian();
395
396 // Determine minimum and maximum identifier used in the recording.
397
398 Identifier minIdentifier = std::numeric_limits<Identifier>::max();
399 Identifier maxIdentifier = std::numeric_limits<Identifier>::min();
400
401 auto determineMinMaxIdentifier = [&minIdentifier, &maxIdentifier](typename Tape::Identifier const& identifier) {
402 minIdentifier = std::min(minIdentifier, identifier);
403 maxIdentifier = std::max(maxIdentifier, identifier);
404 };
405
406 // Begin by processing inputs and outputs.
407 for (auto const& identifier : inputData) {
408 determineMinMaxIdentifier(identifier);
409 }
410
411 for (auto const& identifier : outputData) {
412 determineMinMaxIdentifier(identifier);
413 }
414
415 // Process the tape. Does not edit identifiers in the tape.
416 tape.editIdentifiers(determineMinMaxIdentifier, startPos, endPos);
417
418 // Plus one to cover the range [minIdentifier, maxIdentifier].
419 size_t requiredVectorSize = maxIdentifier - minIdentifier + 1;
420 this->localAdjoints.resize(requiredVectorSize);
421
422 // Define adjoints that take into account the offset when addressing into the vector.
423 using LocalAdjointsOffset = AdjointVectorWithOffset<Identifier, Gradient>;
424 LocalAdjointsOffset localAdjointsOffset(this->localAdjoints.data(), minIdentifier);
425
426 // Preaccumulation with a local adjoint vector and identifier offsets.
428 outputData.data(), outputData.size(), jacobian,
429 localAdjointsOffset);
430
431 tape.resetTo(startPos, false);
432 }
433
434 void computeJacobianLocalMappedAdjoints() {
435 // Perform the accumulation of the tape part.
436 Tape& tape = Type::getTape();
437 Position endPos = tape.getPosition();
438
439 resizeJacobian();
440
441 // Create a local map with adjoints.
442 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
443 LocalMappedAdjoints mappedAdjoints;
444
446 outputData.data(), outputData.size(), jacobian,
447 mappedAdjoints);
448
449 tape.resetTo(startPos, false);
450 }
451
452 void computeJacobianLocalAdjointVectorPreprocessTape() {
453 // Perform the accumulation of the tape part.
454 Tape& tape = Type::getTape();
455 Position endPos = tape.getPosition();
456
457 resizeJacobian();
458
459 // Used internally for remapping identifiers.
460 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
461
462 // Build a map of identifiers, remapping identifiers in the recording to contiguous ones.
463 auto nextIdentifier = typename Tape::Identifier() + 1;
464 IdentifierMap oldToNewIdentifierMap;
465
466 // If needed, inserts the old identifier into the map and associates it with the next identifier. Either way,
467 // returns the associated new identifier.
468 auto accessOldToNewIdentifierMap = [&](typename Tape::Identifier const& oldIdentifier) ->
469 typename Tape::Identifier const& {
470 auto result = oldToNewIdentifierMap.insert({oldIdentifier, nextIdentifier});
471 if (result.second) { // insertion took place
472 ++nextIdentifier;
473 }
474 return result.first->second;
475 };
476
477 // Remap input identifiers explicitly to account for inputs that are actually not used in the recording.
478 for (auto const& oldIdentifier : inputData) {
479 accessOldToNewIdentifierMap(oldIdentifier);
480 }
481
482 // Remap output identifiers explicitly to account for outputs that actually do not depend on the inputs.
483 for (auto const& oldIdentifier : outputData) {
484 accessOldToNewIdentifierMap(oldIdentifier);
485 }
486
487 auto editIdentifier = [&](typename Tape::Identifier& oldIdentifier) {
488 oldIdentifier = accessOldToNewIdentifierMap(oldIdentifier);
489 };
490
491 // Process the recording to complete the map, edit the tape on the fly.
492 tape.editIdentifiers(editIdentifier, startPos, endPos);
493
494 // Build new vectors of input and output identifiers.
495 std::vector<typename Tape::Identifier> newInputData;
496 newInputData.reserve(inputData.size());
497 for (auto const& identifier : inputData) {
498 newInputData.push_back(oldToNewIdentifierMap[identifier]);
499 }
500
501 std::vector<typename Tape::Identifier> newOutputData;
502 newOutputData.reserve(outputData.size());
503 for (auto const& identifier : outputData) {
504 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
505 }
506
507 // The association with the original input/output identifiers and Jacobian entries is made by position, so we no
508 // longer need the identifier map.
509 oldToNewIdentifierMap.clear();
510
511 // Create local adjoints. nextIdentifier holds the local adjoint vector size.
512 std::vector<typename Tape::Gradient> localAdjoints(nextIdentifier);
513
514 // Preaccumulation with remapped identifiers on local adjoints.
516 newInputData.size(), newOutputData.data(),
517 newOutputData.size(), jacobian, localAdjoints.data());
518
519 tape.resetTo(startPos, false);
520 }
521
522 void storeJacobian() {
523 Tape& tape = Type::getTape();
524
525 for (size_t curOut = 0; curOut < outputData.size(); ++curOut) {
526 Type& value = *outputValues[curOut];
527 if (0 != jacobian.nonZerosRow(curOut)) {
528 int nonZerosLeft = jacobian.nonZerosRow(curOut);
529 jacobian.nonZerosRow(curOut) = 0;
530
531 // We need to initialize with the output's current identifier such that it is correctly deleted in
532 // storeManual.
533 Identifier lastIdentifier = value.getIdentifier();
534 bool staggeringActive = false;
535 int curIn = 0;
536
537 // Push statements as long as there are nonzeros left.
538 // If there are more than MaxStatementIntValue nonzeros, then we need to stagger the
539 // statement pushes:
540 // 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
541 // separated into
542 // Statement 1:
543 // \bar u_i += df/du_i * \bar t_1 for i = 0 ... 253 (254 entries)
544 // Statement 2:
545 // \bar t_1 += \bar w (1 entry)
546 // \bar u_i += df/du_i * \bar t_2 for i = 254 ... 506 (253 entries)
547 // Statement 3:
548 // \bar t_2 += \bar w (1 entry)
549 // \bar u_i += df/du_i * \bar w for i = 507 ... 530 (24 entries)
550 //
551 while (nonZerosLeft > 0) {
552 // Calculate the number of Jacobians for this statement.
553 int jacobiansForStatement = nonZerosLeft;
554 if (jacobiansForStatement > (int)Config::MaxArgumentSize) {
555 jacobiansForStatement = (int)Config::MaxArgumentSize - 1;
556 if (staggeringActive) { // Except in the first round, one Jacobian is reserved for the staggering.
557 jacobiansForStatement -= 1;
558 }
559 }
560 nonZerosLeft -= jacobiansForStatement; // Update nonzeros so that we know if it is the last round.
561
562 Identifier storedIdentifier = lastIdentifier;
563 // storeManual creates a new identifier which is either the identifier of the output w or the temporary
564 // staggering variables t_1, t_2, ...
565 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (int)staggeringActive);
566 if (staggeringActive) { // Not the first staggering so push the last output.
567 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
568 }
569
570 // Push the rest of the Jacobians for the statement.
571 while (jacobiansForStatement > 0) {
572 if (Real() != (Real)jacobian(curOut, curIn)) {
573 tape.pushJacobianManual(jacobian(curOut, curIn), 0.0, inputData[curIn]);
574 jacobiansForStatement -= 1;
575 }
576 curIn += 1;
577 }
578
579 staggeringActive = true;
580 }
581
582 value.getIdentifier() = lastIdentifier; /* now set gradient data for the real output value */
583 } else {
584 // Disable tape index since there is no dependency.
585 tape.destroyIdentifier(value.value(), value.getIdentifier());
586 }
587 }
588 }
589 };
590
591#ifndef DOXYGEN_DISABLE
597 struct PreaccumulationHelperNoOpBase {
598 public:
599
601 template<typename... Inputs>
602 void addInput(Inputs const&... inputs) {
603 CODI_UNUSED(inputs...);
604 // Do nothing.
605 }
606
608 template<typename... Inputs>
609 void start(Inputs const&... inputs) {
610 CODI_UNUSED(inputs...);
611 // Do nothing.
612 }
613
615 template<typename... Outputs>
616 void addOutput(Outputs&... outputs) {
617 CODI_UNUSED(outputs...);
618 // Do nothing.
619 }
620
622 template<typename... Outputs>
623 void finish(bool const storeAdjoints, Outputs&... outputs) {
624 CODI_UNUSED(storeAdjoints, outputs...);
625 // Do nothing.
626 }
627
629 template<typename... Outputs>
630 void finishLocalMappedAdjoints(Outputs&... outputs) {
631 CODI_UNUSED(outputs...);
632 // Do nothing.
633 }
634
636 template<typename... Outputs>
637 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
638 CODI_UNUSED(outputs...);
639 // Do nothing.
640 }
641
643 template<typename... Outputs>
644 void finishLocalAdjoints(Outputs&... outputs) {
645 CODI_UNUSED(outputs...);
646 // Do nothing.
647 }
648
650 template<typename... Outputs>
651 void finishLocalAdjointVector(Outputs&... outputs) {
652 CODI_UNUSED(outputs...);
653 // Do nothing.
654 }
655
657 template<typename... Outputs>
658 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
659 CODI_UNUSED(outputs...);
660 // Do nothing.
661 }
662 };
663
665 template<typename Type>
666 struct PreaccumulationHelper<Type, TapeTraits::EnableIfForwardTape<typename Type::Tape>>
667 : public PreaccumulationHelperNoOpBase {};
668
670 template<>
671 struct PreaccumulationHelper<double, void> : public PreaccumulationHelperNoOpBase {};
672
680 template<typename T_Type>
681 struct PreaccumulationHelper<T_Type, TapeTraits::EnableIfTagTapeReverse<typename T_Type::Tape>> {
682 public:
683
684 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
685
686 using Tape = CODI_DD(typename Type::Tape, CODI_T(TagTapeReverse<Type, int>));
687 using Tag = typename Tape::Tag;
688
689 private:
690
691 std::vector<Type const*> inputLocations;
692 std::vector<Type*> outputLocations;
693 Tag oldTag;
694
695 public:
696
699
701 template<typename... Inputs>
702 void addInput(Inputs const&... inputs) {
703 Tape& tape = getTape();
704
705 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
706 addInputRecursive(inputs...);
707 }
708 }
709
711 template<typename... Inputs>
712 void start(Inputs const&... inputs) {
713 Tape& tape = getTape();
714
715 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
716 inputLocations.clear();
717 outputLocations.clear();
718 oldTag = tape.getCurTag();
719 tape.setCurTag(tape.getPreaccumulationHandlingTag());
720
721 addInputRecursive(inputs...);
722 }
723 }
724
726 template<typename... Outputs>
727 void addOutput(Outputs&... outputs) {
728 Tape& tape = getTape();
729
730 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
731 addOutputRecursive(outputs...);
732 }
733 }
734
736 template<typename... Outputs>
737 void finish(bool const storeAdjoints, Outputs&... outputs) {
738 CODI_UNUSED(storeAdjoints);
739
740 Tape& tape = getTape();
741
742 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
743 addOutputRecursive(outputs...);
744
745 tape.setCurTag(oldTag);
746 for (Type const* curInput : inputLocations) {
747 tape.setTagOnVariable(*curInput);
748 }
749 for (Type* curOutput : outputLocations) {
750 tape.setTagOnVariable(*curOutput);
751 }
752 }
753 }
754
756 template<typename... Outputs>
757 void finishLocalMappedAdjoints(Outputs&... outputs) {
758 finish(false, outputs...);
759 }
760
762 template<typename... Outputs>
763 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
764 finish(false, outputs...);
765 }
766
768 template<typename... Outputs>
769 void finishLocalAdjoints(Outputs&... outputs) {
770 finish(false, outputs...);
771 }
772
774 template<typename... Outputs>
775 void finishLocalAdjointVector(Outputs&... outputs) {
776 finish(false, outputs...);
777 }
778
780 template<typename... Outputs>
781 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
782 finish(false, outputs...);
783 }
784
785 private:
786
788 void addInputRecursive() {
789 // Terminator implementation.
790 }
791
792 template<typename... Inputs>
793 void addInputRecursive(Type const& input, Inputs const&... r) {
794 handleInput(input);
795 addInputRecursive(r...);
796 }
797
798 void handleInput(Type const& input) {
799 if (Type::getTape().getPassiveIndex() != input.getIdentifier()) {
800 inputLocations.push_back(&input);
801 getTape().setTagOnVariable(input);
802 }
803 }
804
806 void addOutputRecursive() {
807 // Terminator implementation.
808 }
809
810 template<typename... Outputs>
811 void addOutputRecursive(Type& output, Outputs&... r) {
812 handleOutput(output);
813 addOutputRecursive(r...);
814 }
815
816 void handleOutput(Type& value) {
817 outputLocations.push_back(&value);
818 }
819
820 Tape& getTape() {
821 return Type::getTape();
822 }
823 };
824#endif
825}
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:469
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:96
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition macros.hpp:116
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:94
@ 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:54
@ 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:218
void finishLocalAdjointVectorPreprocessTape(Outputs &... outputs)
Definition preaccumulationHelper.hpp:205
void finish(bool const storeAdjoints, Outputs &... outputs)
Definition preaccumulationHelper.hpp:175
std::vector< Gradient > storedAdjoints
If adjoints of inputs should be stored, before the preaccumulation.
Definition preaccumulationHelper.hpp:104
Position startPos
Starting position for the region.
Definition preaccumulationHelper.hpp:103
PreaccumulationHelper()
Constructor.
Definition preaccumulationHelper.hpp:110
typename Type::Tape Tape
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:88
void finishLocalAdjointVector(Outputs &... outputs)
Definition preaccumulationHelper.hpp:234
void addInput(Inputs const &... inputs)
Add multiple additional inputs. Inputs need to be of type Type. Called after start().
Definition preaccumulationHelper.hpp:115
std::vector< Identifier > inputData
Definition preaccumulationHelper.hpp:91
T_Type Type
See PreaccumulationHelper.
Definition preaccumulationHelper.hpp:81
void finishLocalMappedAdjoints(Outputs &... outputs)
Definition preaccumulationHelper.hpp:192
typename Tape::Position Position
See PositionalEvaluationTapeInterface.
Definition preaccumulationHelper.hpp:89
void finishInternal(Func &coreRoutine, Outputs &... outputs)
Internal implementation of workflow for preaccumulation with local adjoints.
Definition preaccumulationHelper.hpp:154
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:95
std::vector< Identifier > outputData
Definition preaccumulationHelper.hpp:93
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:125
void addOutput(Outputs &... outputs)
Add multiple additional outputs. Outputs need to be of type Type. Called before finish().
Definition preaccumulationHelper.hpp:143
std::vector< Gradient > localAdjoints
Definition preaccumulationHelper.hpp:98
JacobianCountNonZerosRow< Real > jacobian
Jacobian for the preaccumulation.
Definition preaccumulationHelper.hpp:105
void finishLocalAdjointVectorOffset(Outputs &... outputs)
Definition preaccumulationHelper.hpp:247