CoDiPack  2.3.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-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
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 protected:
99
101 std::vector<Gradient> storedAdjoints;
103
104 public:
105
109
111 template<typename... Inputs>
112 void addInput(Inputs const&... inputs) {
113 Tape& tape = Type::getTape();
114
115 if (tape.isActive()) {
116 addInputRecursive(inputs...);
117 }
118 }
119
121 template<typename... Inputs>
122 void start(Inputs const&... inputs) {
123 Tape& tape = Type::getTape();
124
126
127 if (tape.isActive()) {
128 inputData.clear();
129 outputData.clear();
130 outputValues.clear();
131
132 startPos = tape.getPosition();
133
134 addInputRecursive(inputs...);
135 }
136 }
137
139 template<typename... Outputs>
140 void addOutput(Outputs&... outputs) {
141 Tape& tape = Type::getTape();
142
143 if (tape.isActive()) {
144 addOutputRecursive(outputs...);
145 }
146 }
147
151 template<typename... Outputs>
152 void finish(bool const storeAdjoints, Outputs&... outputs) {
153 Tape& tape = Type::getTape();
154
155 if (tape.isActive()) {
156 addOutputRecursive(outputs...);
157
158 if (storeAdjoints) {
159 storeInputAdjoints();
160 }
161
162 tape.setPassive();
163 computeJacobian();
164 storeJacobian();
165 tape.setActive();
166
167 if (storeAdjoints) {
168 restoreInputAdjoints();
169 }
170 }
171
173 }
174
177 template<typename... Outputs>
178 void finishLocalMappedAdjoints(Outputs&... outputs) {
179 Tape& tape = Type::getTape();
180
181 if (tape.isActive()) {
182 addOutputRecursive(outputs...);
183
184 tape.setPassive();
185 computeJacobianLocalMappedAdjoints();
186 storeJacobian();
187 tape.setActive();
188 }
189
191 }
192
197 template<typename... Outputs>
198 void finishLocalAdjointsPreprocessTape(Outputs&... outputs) {
199 Tape& tape = Type::getTape();
200
201 if (tape.isActive()) {
202 addOutputRecursive(outputs...);
203
204 tape.setPassive();
205 computeJacobianLocalAdjointsPreprocessTapeIfAvailable<Tape>(); // otherwise
206 // computeJacobianLocalMappedAdjoints
207 storeJacobian();
208 tape.setActive();
209 }
210
212 }
213
217 template<typename... Outputs>
218 void finishLocalAdjoints(Outputs&... outputs) {
219 Tape& tape = Type::getTape();
220
221 if (tape.isActive()) {
222 addOutputRecursive(outputs...);
223
224 tape.setPassive();
225 if (std::min(inputData.size(), outputData.size()) > 1) {
226 computeJacobianLocalAdjointsPreprocessTapeIfAvailable<Tape>(); // otherwise
227 // computeJacobianLocalMappedAdjoints
228 } else {
229 computeJacobianLocalMappedAdjoints();
230 }
231
232 storeJacobian();
233 tape.setActive();
234 }
235
237 }
238
239 private:
240
241 // Tape supports editing -> use a map to edit its identifiers. Disabled by SFINAE otherwise.
242 template<typename Tape>
243 TapeTraits::EnableIfSupportsEditing<Tape> computeJacobianLocalAdjointsPreprocessTapeIfAvailable() {
244 computeJacobianLocalAdjointsPreprocessTape();
245 }
246
247 // Tape does not support editing -> use a map for the adjoints. Disabled by SFINAE otherwise.
248 template<typename Tape>
249 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointsPreprocessTapeIfAvailable() {
250 computeJacobianLocalMappedAdjoints();
251 }
252
253 void addInputLogic(Type const& input) {
254 EventSystem<Tape>::notifyPreaccAddInputListeners(Type::getTape(), input.getValue(), input.getIdentifier());
255 Identifier const& identifier = input.getIdentifier();
256 if (Type::getTape().getPassiveIndex() != identifier) {
257 inputData.push_back(identifier);
258 }
259 }
260
262 void addInputRecursive() {
263 // Terminator implementation.
264 }
265
266 template<typename... Inputs>
267 void addInputRecursive(Type const& input, Inputs const&... r) {
268 addInputLogic(input);
269 addInputRecursive(r...);
270 }
271
272 void addOutputLogic(Type& output) {
273 EventSystem<Tape>::notifyPreaccAddOutputListeners(Type::getTape(), output.value(), output.getIdentifier());
274 Identifier const& identifier = output.getIdentifier();
275 if (Type::getTape().getPassiveIndex() != identifier) {
276 outputData.push_back(identifier);
277 outputValues.push_back(&output);
278 }
279 }
280
282 void addOutputRecursive() {
283 // Terminator implementation.
284 }
285
286 template<typename... Outputs>
287 void addOutputRecursive(Type& output, Outputs&... r) {
288 addOutputLogic(output);
289 addOutputRecursive(r...);
290 }
291
292 void storeInputAdjoints() {
293 Tape& tape = Type::getTape();
294
295 if (storedAdjoints.size() < inputData.size()) {
296 storedAdjoints.resize(inputData.size());
297 }
298
299 for (size_t i = 0; i < inputData.size(); ++i) {
300 Identifier index = inputData[i];
301 Gradient& adjoint = tape.gradient(index);
302 storedAdjoints[i] = adjoint;
303 adjoint = Gradient();
304 }
305 }
306
307 void restoreInputAdjoints() {
308 Tape& tape = Type::getTape();
309
310 for (size_t i = 0; i < inputData.size(); ++i) {
311 Identifier index = inputData[i];
312 tape.gradient(index) = storedAdjoints[i];
313 }
314 }
315
316 void resizeJacobian() {
317 if (jacobian.getM() != outputData.size() || jacobian.getN() != inputData.size()) {
318 jacobian.resize(outputData.size(), inputData.size());
319 }
320 }
321
322 void computeJacobian() {
323 // Perform the accumulation of the tape part.
324 Tape& tape = Type::getTape();
325 Position endPos = tape.getPosition();
326
327 resizeJacobian();
328
329 // Manage adjoints manually to reduce the impact of locking on the performance.
330 tape.resizeAdjointVector();
331 tape.beginUseAdjointVector();
332
334 outputData.data(), outputData.size(), jacobian,
336
337 tape.resetTo(startPos, true, AdjointsManagement::Manual);
338
339 tape.endUseAdjointVector();
340 }
341
342 void computeJacobianLocalMappedAdjoints() {
343 // Perform the accumulation of the tape part.
344 Tape& tape = Type::getTape();
345 Position endPos = tape.getPosition();
346
347 resizeJacobian();
348
349 // Create a local map with adjoints.
350 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
351 LocalMappedAdjoints mappedAdjoints;
352
354 outputData.data(), outputData.size(), jacobian,
355 mappedAdjoints);
356
357 tape.resetTo(startPos, false);
358 }
359
360 void computeJacobianLocalAdjointsPreprocessTape() {
361 // Perform the accumulation of the tape part.
362 Tape& tape = Type::getTape();
363 Position endPos = tape.getPosition();
364
365 resizeJacobian();
366
367 // Used internally for remapping identifiers.
368 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
369
370 // Build a map of identifiers, remapping identifiers in the recording to contiguous ones.
371 auto nextIdentifier = typename Tape::Identifier() + 1;
372 IdentifierMap oldToNewIdentifierMap;
373
374 auto addIdentifierToMapping = [&](typename Tape::Identifier const& oldIdentifier) {
375 if (tape.isIdentifierActive(oldIdentifier) &&
376 oldToNewIdentifierMap.find(oldIdentifier) == oldToNewIdentifierMap.end()) {
377 oldToNewIdentifierMap[oldIdentifier] = nextIdentifier++;
378 }
379 };
380
381 // Begin by remapping input identifiers.
382 for (auto const& oldIdentifier : inputData) {
383 addIdentifierToMapping(oldIdentifier);
384 }
385
386 auto addAndEditIdentifier = [&](typename Tape::Identifier& oldIdentifier) {
387 addIdentifierToMapping(oldIdentifier);
388 oldIdentifier = oldToNewIdentifierMap[oldIdentifier];
389 };
390
391 // Process the recording to complete the map, edit the tape on the fly.
392 tape.template editIdentifiers(addAndEditIdentifier, startPos, endPos);
393
394 // Build new vectors of input and output identifiers.
395 std::vector<typename Tape::Identifier> newInputData;
396 newInputData.reserve(inputData.size());
397 for (auto const& identifier : inputData) {
398 newInputData.push_back(oldToNewIdentifierMap[identifier]);
399 }
400
401 std::vector<typename Tape::Identifier> newOutputData;
402 newOutputData.reserve(outputData.size());
403 for (auto const& identifier : outputData) {
404 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
405 }
406
407 // Create local adjoints. nextIdentifier holds the local adjoint vector size.
408 std::vector<typename Tape::Gradient> localAdjoints(nextIdentifier);
409
410 // Preaccumulation with remapped identifiers on local adjoints.
412 newInputData.size(), newOutputData.data(),
413 newOutputData.size(), jacobian, localAdjoints.data());
414
415 tape.resetTo(startPos, false);
416 }
417
418 void storeJacobian() {
419 Tape& tape = Type::getTape();
420
421 for (size_t curOut = 0; curOut < outputData.size(); ++curOut) {
422 Type& value = *outputValues[curOut];
423 if (0 != jacobian.nonZerosRow(curOut)) {
424 int nonZerosLeft = jacobian.nonZerosRow(curOut);
425 jacobian.nonZerosRow(curOut) = 0;
426
427 // We need to initialize with the output's current identifier such that it is correctly deleted in
428 // storeManual.
429 Identifier lastIdentifier = value.getIdentifier();
430 bool staggeringActive = false;
431 int curIn = 0;
432
433 // Push statements as long as there are nonzeros left.
434 // If there are more than MaxStatementIntValue nonzeros, then we need to stagger the
435 // statement pushes:
436 // 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
437 // separated into
438 // Statement 1:
439 // \bar u_i += df/du_i * \bar t_1 for i = 0 ... 253 (254 entries)
440 // Statement 2:
441 // \bar t_1 += \bar w (1 entry)
442 // \bar u_i += df/du_i * \bar t_2 for i = 254 ... 506 (253 entries)
443 // Statement 3:
444 // \bar t_2 += \bar w (1 entry)
445 // \bar u_i += df/du_i * \bar w for i = 507 ... 530 (24 entries)
446 //
447 while (nonZerosLeft > 0) {
448 // Calculate the number of Jacobians for this statement.
449 int jacobiansForStatement = nonZerosLeft;
450 if (jacobiansForStatement > (int)Config::MaxArgumentSize) {
451 jacobiansForStatement = (int)Config::MaxArgumentSize - 1;
452 if (staggeringActive) { // Except in the first round, one Jacobian is reserved for the staggering.
453 jacobiansForStatement -= 1;
454 }
455 }
456 nonZerosLeft -= jacobiansForStatement; // Update nonzeros so that we know if it is the last round.
457
458 Identifier storedIdentifier = lastIdentifier;
459 // storeManual creates a new identifier which is either the identifier of the output w or the temporary
460 // staggering variables t_1, t_2, ...
461 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (int)staggeringActive);
462 if (staggeringActive) { // Not the first staggering so push the last output.
463 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
464 }
465
466 // Push the rest of the Jacobians for the statement.
467 while (jacobiansForStatement > 0) {
468 if (Real() != (Real)jacobian(curOut, curIn)) {
469 tape.pushJacobianManual(jacobian(curOut, curIn), 0.0, inputData[curIn]);
470 jacobiansForStatement -= 1;
471 }
472 curIn += 1;
473 }
474
475 staggeringActive = true;
476 }
477
478 value.getIdentifier() = lastIdentifier; /* now set gradient data for the real output value */
479 } else {
480 // Disable tape index since there is no dependency.
481 tape.destroyIdentifier(value.value(), value.getIdentifier());
482 }
483 }
484 }
485 };
486
487#ifndef DOXYGEN_DISABLE
493 struct PreaccumulationHelperNoOpBase {
494 public:
495
497 template<typename... Inputs>
498 void addInput(Inputs const&... inputs) {
499 CODI_UNUSED(inputs...);
500 // Do nothing.
501 }
502
504 template<typename... Inputs>
505 void start(Inputs const&... inputs) {
506 CODI_UNUSED(inputs...);
507 // Do nothing.
508 }
509
511 template<typename... Outputs>
512 void addOutput(Outputs&... outputs) {
513 CODI_UNUSED(outputs...);
514 // Do nothing.
515 }
516
518 template<typename... Outputs>
519 void finish(bool const storeAdjoints, Outputs&... outputs) {
520 CODI_UNUSED(storeAdjoints, outputs...);
521 // Do nothing.
522 }
523
525 template<typename... Outputs>
526 void finishLocalMappedAdjoints(Outputs&... outputs) {
527 CODI_UNUSED(outputs...);
528 // Do nothing.
529 }
530
532 template<typename... Outputs>
533 void finishLocalAdjointsPreprocessTape(Outputs&... outputs) {
534 CODI_UNUSED(outputs...);
535 // Do nothing.
536 }
537
539 template<typename... Outputs>
540 void finishLocalAdjoints(Outputs&... outputs) {
541 CODI_UNUSED(outputs...);
542 // Do nothing.
543 }
544 };
545
547 template<typename Type>
548 struct PreaccumulationHelper<Type, TapeTraits::EnableIfForwardTape<typename Type::Tape>>
549 : public PreaccumulationHelperNoOpBase {};
550
552 template<>
553 struct PreaccumulationHelper<double, void> : public PreaccumulationHelperNoOpBase {};
554
562 template<typename T_Type>
563 struct PreaccumulationHelper<
564 T_Type, typename enable_if_same<typename T_Type::Tape,
565 TagTapeReverse<typename T_Type::Real, typename T_Type::Tape::Tag>>::type> {
566 public:
567
568 using Type = CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
569
570 using Tape = CODI_DD(typename Type::Tape, CODI_T(TagTapeReverse<Type, int>));
571 using Tag = typename Tape::Tag;
572
573 private:
574
575 std::vector<Type const*> inputLocations;
576 std::vector<Type*> outputLocations;
577 Tag oldTag;
578
579 public:
580
583
585 template<typename... Inputs>
586 void addInput(Inputs const&... inputs) {
587 Tape& tape = getTape();
588
589 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
590 addInputRecursive(inputs...);
591 }
592 }
593
595 template<typename... Inputs>
596 void start(Inputs const&... inputs) {
597 Tape& tape = getTape();
598
599 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
600 inputLocations.clear();
601 outputLocations.clear();
602 oldTag = tape.getCurTag();
603 tape.setCurTag(tape.getPreaccumulationHandlingTag());
604
605 addInputRecursive(inputs...);
606 }
607 }
608
610 template<typename... Outputs>
611 void addOutput(Outputs&... outputs) {
612 Tape& tape = getTape();
613
614 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
615 addOutputRecursive(outputs...);
616 }
617 }
618
620 template<typename... Outputs>
621 void finish(bool const storeAdjoints, Outputs&... outputs) {
622 CODI_UNUSED(storeAdjoints);
623
624 Tape& tape = getTape();
625
626 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
627 addOutputRecursive(outputs...);
628
629 tape.setCurTag(oldTag);
630 for (Type const* curInput : inputLocations) {
631 tape.setTagOnVariable(*curInput);
632 }
633 for (Type* curOutput : outputLocations) {
634 tape.setTagOnVariable(*curOutput);
635 }
636 }
637 }
638
640 template<typename... Outputs>
641 void finishLocalMappedAdjoints(Outputs&... outputs) {
642 finish(false, outputs...);
643 }
644
646 template<typename... Outputs>
647 void finishLocalAdjointsPreprocessTape(Outputs&... outputs) {
648 finish(false, outputs...);
649 }
650
652 template<typename... Outputs>
653 void finishLocalAdjoints(Outputs&... outputs) {
654 finish(false, outputs...);
655 }
656
657 private:
658
660 void addInputRecursive() {
661 // Terminator implementation.
662 }
663
664 template<typename... Inputs>
665 void addInputRecursive(Type const& input, Inputs const&... r) {
666 handleInput(input);
667 addInputRecursive(r...);
668 }
669
670 void handleInput(Type const& input) {
671 inputLocations.push_back(&input);
672 getTape().setTagOnVariable(input);
673 }
674
676 void addOutputRecursive() {
677 // Terminator implementation.
678 }
679
680 template<typename... Outputs>
681 void addOutputRecursive(Type& output, Outputs&... r) {
682 handleOutput(output);
683 addOutputRecursive(r...);
684 }
685
686 void handleOutput(Type& value) {
687 outputLocations.push_back(&value);
688 }
689
690 Tape& getTape() {
691 return Type::getTape();
692 }
693 };
694#endif
695}
#define CODI_INLINE
See codi::Config::ForcedInlines.
Definition config.h:457
#define CODI_DD(Type, Default)
Abbreviation for CODI_DECLARE_DEFAULT.
Definition macros.hpp:94
#define CODI_T(...)
Abbreviation for CODI_TEMPLATE.
Definition macros.hpp:111
size_t constexpr MaxArgumentSize
Maximum number of arguments in a statement.
Definition config.h:120
typename std::enable_if< SupportsEditing< Tape >::value >::type EnableIfSupportsEditing
Enable if wrapper for SupportsEditing.
Definition tapeTraits.hpp:180
typename std::enable_if< IsForwardTape< Tape >::value >::type EnableIfForwardTape
Enable if wrapper for IsForwardTape.
Definition tapeTraits.hpp:93
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
std::enable_if< std::is_same< T1, T2 >::value, R > enable_if_same
Enable if abbreviation for "std::is_same".
Definition enableIfHelpers.hpp:51
@ Manual
Do not perform any bounds checking, locking, or resizing.
static void computeJacobianCustomAdjoints(Tape &tape, Position const &start, Position const &end, Identifier const *input, size_t const inputSize, Identifier const *output, size_t const outputSize, Jac &jac, AdjointVector &&adjoints)
Compute the Jacobian with multiple tape sweeps using a custom adjoint vector.
Definition algorithms.hpp:172
static void 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 void notifyPreaccFinishListeners(Tape &tape)
Invoke callbacks for PreaccFinish events.
Definition eventSystem.hpp:579
static void notifyPreaccAddOutputListeners(Tape &tape, Real &value, Identifier &identifier)
Invoke callbacks for PreaccAddOutput events.
Definition eventSystem.hpp:636
static void notifyPreaccAddInputListeners(Tape &tape, Real const &value, Identifier const &identifier)
Invoke callbacks for PreaccAddInput events.
Definition eventSystem.hpp:607
static void notifyPreaccStartListeners(Tape &tape)
Invoke callbacks for PreaccStart events.
Definition eventSystem.hpp:553
Adds counting of nonzero entries.
Definition jacobian.hpp:129
int & nonZerosRow(size_t const i)
Reference to the number of nonzero entries for the specified row.
Definition jacobian.hpp:167
void resize(size_t const m, size_t const n)
Resize the Jacobian.
Definition jacobian.hpp:161
size_t getM() const
Get size of rows (output variables).
Definition jacobian.hpp:78
size_t getN() const
Get size of columns (input variables).
Definition jacobian.hpp:83
Stores the Jacobian matrix for a code section.
Definition preaccumulationHelper.hpp:77
void finishLocalAdjoints(Outputs &... outputs)
Definition preaccumulationHelper.hpp:218
void finish(bool const storeAdjoints, Outputs &... outputs)
Definition preaccumulationHelper.hpp:152
std::vector< Gradient > storedAdjoints
If adjoints of inputs should be stored, before the preaccumulation.
Definition preaccumulationHelper.hpp:101
Position startPos
Starting position for the region.
Definition preaccumulationHelper.hpp:100
PreaccumulationHelper()
Constructor.
Definition preaccumulationHelper.hpp:107
typename Type::Tape Tape
See LhsExpressionInterface.
Definition preaccumulationHelper.hpp:88
void addInput(Inputs const &... inputs)
Add multiple additional inputs. Inputs need to be of type Type. Called after start().
Definition preaccumulationHelper.hpp:112
std::vector< Identifier > inputData
Definition preaccumulationHelper.hpp:91
T_Type Type
See PreaccumulationHelper.
Definition preaccumulationHelper.hpp:81
void finishLocalMappedAdjoints(Outputs &... outputs)
Definition preaccumulationHelper.hpp:178
typename Tape::Position Position
See PositionalEvaluationTapeInterface.
Definition preaccumulationHelper.hpp:89
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
void finishLocalAdjointsPreprocessTape(Outputs &... outputs)
Definition preaccumulationHelper.hpp:198
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:122
void addOutput(Outputs &... outputs)
Add multiple additional outputs. Outputs need to be of type Type. Called before finish().
Definition preaccumulationHelper.hpp:140
JacobianCountNonZerosRow< Real > jacobian
Jacobian for the preaccumulation.
Definition preaccumulationHelper.hpp:102