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"
76 template<
typename T_Type,
typename =
void>
83 using Real =
typename Type::Real;
111 template<
typename... Inputs>
113 Tape& tape = Type::getTape();
115 if (tape.isActive()) {
116 addInputRecursive(inputs...);
121 template<
typename... Inputs>
122 void start(Inputs
const&... inputs) {
123 Tape& tape = Type::getTape();
127 if (tape.isActive()) {
134 addInputRecursive(inputs...);
139 template<
typename... Outputs>
141 Tape& tape = Type::getTape();
143 if (tape.isActive()) {
144 addOutputRecursive(outputs...);
151 template<
typename... Outputs>
152 void finish(
bool const storeAdjoints, Outputs&... outputs) {
153 Tape& tape = Type::getTape();
155 if (tape.isActive()) {
156 addOutputRecursive(outputs...);
159 storeInputAdjoints();
168 restoreInputAdjoints();
177 template<
typename... Outputs>
179 Tape& tape = Type::getTape();
181 if (tape.isActive()) {
182 addOutputRecursive(outputs...);
185 computeJacobianLocalMappedAdjoints();
197 template<
typename... Outputs>
199 Tape& tape = Type::getTape();
201 if (tape.isActive()) {
202 addOutputRecursive(outputs...);
205 computeJacobianLocalAdjointsPreprocessTapeIfAvailable<Tape>();
217 template<
typename... Outputs>
219 Tape& tape = Type::getTape();
221 if (tape.isActive()) {
222 addOutputRecursive(outputs...);
226 computeJacobianLocalAdjointsPreprocessTapeIfAvailable<Tape>();
229 computeJacobianLocalMappedAdjoints();
242 template<
typename Tape>
244 computeJacobianLocalAdjointsPreprocessTape();
248 template<
typename Tape>
249 TapeTraits::EnableIfNoEditing<Tape> computeJacobianLocalAdjointsPreprocessTapeIfAvailable() {
250 computeJacobianLocalMappedAdjoints();
253 void addInputLogic(
Type const& input) {
255 Identifier
const& identifier = input.getIdentifier();
256 if (Type::getTape().getPassiveIndex() != identifier) {
262 void addInputRecursive() {
266 template<
typename... Inputs>
267 void addInputRecursive(
Type const& input, Inputs
const&... r) {
268 addInputLogic(input);
269 addInputRecursive(r...);
272 void addOutputLogic(
Type& output) {
274 Identifier
const& identifier = output.getIdentifier();
275 if (Type::getTape().getPassiveIndex() != identifier) {
282 void addOutputRecursive() {
286 template<
typename... Outputs>
287 void addOutputRecursive(
Type& output, Outputs&... r) {
288 addOutputLogic(output);
289 addOutputRecursive(r...);
292 void storeInputAdjoints() {
293 Tape& tape = Type::getTape();
299 for (
size_t i = 0; i <
inputData.size(); ++i) {
301 Gradient& adjoint = tape.gradient(index);
307 void restoreInputAdjoints() {
308 Tape& tape = Type::getTape();
310 for (
size_t i = 0; i <
inputData.size(); ++i) {
316 void resizeJacobian() {
322 void computeJacobian() {
324 Tape& tape = Type::getTape();
325 Position endPos = tape.getPosition();
330 tape.resizeAdjointVector();
331 tape.beginUseAdjointVector();
339 tape.endUseAdjointVector();
342 void computeJacobianLocalMappedAdjoints() {
344 Tape& tape = Type::getTape();
345 Position endPos = tape.getPosition();
350 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
351 LocalMappedAdjoints mappedAdjoints;
360 void computeJacobianLocalAdjointsPreprocessTape() {
362 Tape& tape = Type::getTape();
363 Position endPos = tape.getPosition();
368 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
371 auto nextIdentifier =
typename Tape::Identifier() + 1;
372 IdentifierMap oldToNewIdentifierMap;
374 auto addIdentifierToMapping = [&](
typename Tape::Identifier
const& oldIdentifier) {
375 if (tape.isIdentifierActive(oldIdentifier) &&
376 oldToNewIdentifierMap.find(oldIdentifier) == oldToNewIdentifierMap.end()) {
377 oldToNewIdentifierMap[oldIdentifier] = nextIdentifier++;
382 for (
auto const& oldIdentifier :
inputData) {
383 addIdentifierToMapping(oldIdentifier);
386 auto addAndEditIdentifier = [&](
typename Tape::Identifier& oldIdentifier) {
387 addIdentifierToMapping(oldIdentifier);
388 oldIdentifier = oldToNewIdentifierMap[oldIdentifier];
392 tape.template editIdentifiers(addAndEditIdentifier,
startPos, endPos);
395 std::vector<typename Tape::Identifier> newInputData;
397 for (
auto const& identifier :
inputData) {
398 newInputData.push_back(oldToNewIdentifierMap[identifier]);
401 std::vector<typename Tape::Identifier> newOutputData;
404 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
408 std::vector<typename Tape::Gradient> localAdjoints(nextIdentifier);
412 newInputData.size(), newOutputData.data(),
413 newOutputData.size(),
jacobian, localAdjoints.data());
418 void storeJacobian() {
419 Tape& tape = Type::getTape();
421 for (
size_t curOut = 0; curOut <
outputData.size(); ++curOut) {
429 Identifier lastIdentifier = value.getIdentifier();
430 bool staggeringActive =
false;
447 while (nonZerosLeft > 0) {
449 int jacobiansForStatement = nonZerosLeft;
452 if (staggeringActive) {
453 jacobiansForStatement -= 1;
456 nonZerosLeft -= jacobiansForStatement;
458 Identifier storedIdentifier = lastIdentifier;
461 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (int)staggeringActive);
462 if (staggeringActive) {
463 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
467 while (jacobiansForStatement > 0) {
470 jacobiansForStatement -= 1;
475 staggeringActive =
true;
478 value.getIdentifier() = lastIdentifier;
481 tape.destroyIdentifier(value.value(), value.getIdentifier());
487#ifndef DOXYGEN_DISABLE
493 struct PreaccumulationHelperNoOpBase {
497 template<
typename... Inputs>
498 void addInput(Inputs
const&... inputs) {
504 template<
typename... Inputs>
505 void start(Inputs
const&... inputs) {
511 template<
typename... Outputs>
512 void addOutput(Outputs&... outputs) {
518 template<
typename... Outputs>
519 void finish(
bool const storeAdjoints, Outputs&... outputs) {
525 template<
typename... Outputs>
526 void finishLocalMappedAdjoints(Outputs&... outputs) {
532 template<
typename... Outputs>
533 void finishLocalAdjointsPreprocessTape(Outputs&... outputs) {
539 template<
typename... Outputs>
540 void finishLocalAdjoints(Outputs&... outputs) {
547 template<
typename Type>
549 :
public PreaccumulationHelperNoOpBase {};
553 struct PreaccumulationHelper<double, void> :
public PreaccumulationHelperNoOpBase {};
562 template<
typename T_Type>
563 struct PreaccumulationHelper<
565 TagTapeReverse<typename T_Type::Real, typename T_Type::Tape::Tag>>::type> {
568 using Type =
CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
570 using Tape =
CODI_DD(
typename Type::Tape,
CODI_T(TagTapeReverse<Type, int>));
571 using Tag =
typename Tape::Tag;
575 std::vector<Type const*> inputLocations;
576 std::vector<Type*> outputLocations;
585 template<
typename... Inputs>
586 void addInput(Inputs
const&... inputs) {
587 Tape& tape = getTape();
589 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
590 addInputRecursive(inputs...);
595 template<
typename... Inputs>
596 void start(Inputs
const&... inputs) {
597 Tape& tape = getTape();
599 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
600 inputLocations.clear();
601 outputLocations.clear();
602 oldTag = tape.getCurTag();
603 tape.setCurTag(tape.getPreaccumulationHandlingTag());
605 addInputRecursive(inputs...);
610 template<
typename... Outputs>
612 Tape& tape = getTape();
614 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
615 addOutputRecursive(outputs...);
620 template<
typename... Outputs>
621 void finish(
bool const storeAdjoints, Outputs&... outputs) {
624 Tape& tape = getTape();
626 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
627 addOutputRecursive(outputs...);
629 tape.setCurTag(oldTag);
630 for (
Type const* curInput : inputLocations) {
631 tape.setTagOnVariable(*curInput);
633 for (
Type* curOutput : outputLocations) {
634 tape.setTagOnVariable(*curOutput);
640 template<
typename... Outputs>
642 finish(
false, outputs...);
646 template<
typename... Outputs>
648 finish(
false, outputs...);
652 template<
typename... Outputs>
654 finish(
false, outputs...);
660 void addInputRecursive() {
664 template<
typename... Inputs>
665 void addInputRecursive(
Type const& input, Inputs
const&... r) {
667 addInputRecursive(r...);
670 void handleInput(
Type const& input) {
671 inputLocations.push_back(&input);
672 getTape().setTagOnVariable(input);
676 void addOutputRecursive() {
680 template<
typename... Outputs>
681 void addOutputRecursive(
Type& output, Outputs&... r) {
682 handleOutput(output);
683 addOutputRecursive(r...);
686 void handleOutput(
Type& value) {
687 outputLocations.push_back(&value);
691 return Type::getTape();
#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