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;
114 template<
typename... Inputs>
116 Tape& tape = Type::getTape();
118 if (tape.isActive()) {
119 addInputRecursive(inputs...);
124 template<
typename... Inputs>
125 void start(Inputs
const&... inputs) {
126 Tape& tape = Type::getTape();
130 if (tape.isActive()) {
137 addInputRecursive(inputs...);
142 template<
typename... Outputs>
144 Tape& tape = Type::getTape();
146 if (tape.isActive()) {
147 addOutputRecursive(outputs...);
153 template<
typename Func,
typename... Outputs>
155 Tape& tape = Type::getTape();
157 if (tape.isActive()) {
158 addOutputRecursive(outputs...);
174 template<
typename... Outputs>
175 void finish(
bool const storeAdjoints, Outputs&... outputs) {
176 auto coreRoutine = [&storeAdjoints,
this]() {
178 storeInputAdjoints();
182 restoreInputAdjoints();
191 template<
typename... Outputs>
193 auto coreRoutine = [
this]() {
194 computeJacobianLocalMappedAdjoints();
204 template<
typename... Outputs>
206 auto coreRoutine = [
this]() {
207 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>();
217 template<
typename... Outputs>
219 auto coreRoutine = [
this]() {
221 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>();
224 computeJacobianLocalMappedAdjoints();
233 template<
typename... Outputs>
235 auto coreRoutine = [
this]() {
236 computeJacobianLocalAdjointVector();
246 template<
typename... Outputs>
248 auto coreRoutine = [
this]() {
249 computeJacobianLocalAdjointVectorOffsetIfAvailable<Tape>();
259 template<
typename Tape>
261 computeJacobianLocalAdjointVectorPreprocessTape();
265 template<
typename Tape>
267 computeJacobianLocalMappedAdjoints();
271 template<
typename Tape>
273 computeJacobianLocalAdjointVectorOffset();
277 template<
typename Tape>
279 computeJacobianLocalAdjointVector();
282 void addInputLogic(
Type const& input) {
284 Identifier const& identifier = input.getIdentifier();
285 if (Type::getTape().getPassiveIndex() != identifier) {
291 void addInputRecursive() {
295 template<
typename... Inputs>
296 void addInputRecursive(
Type const& input, Inputs
const&... r) {
297 addInputLogic(input);
298 addInputRecursive(r...);
301 void addOutputLogic(
Type& output) {
303 Identifier const& identifier = output.getIdentifier();
304 if (Type::getTape().getPassiveIndex() != identifier) {
311 void addOutputRecursive() {
315 template<
typename... Outputs>
316 void addOutputRecursive(
Type& output, Outputs&... r) {
317 addOutputLogic(output);
318 addOutputRecursive(r...);
321 void storeInputAdjoints() {
322 Tape& tape = Type::getTape();
328 for (
size_t i = 0; i <
inputData.size(); ++i) {
330 Gradient& adjoint = tape.gradient(index);
336 void restoreInputAdjoints() {
337 Tape& tape = Type::getTape();
339 for (
size_t i = 0; i <
inputData.size(); ++i) {
345 void resizeJacobian() {
351 void computeJacobian() {
353 Tape& tape = Type::getTape();
354 Position endPos = tape.getPosition();
359 tape.resizeAdjointVector();
360 tape.beginUseAdjointVector();
368 tape.endUseAdjointVector();
371 void computeJacobianLocalAdjointVector() {
373 Tape& tape = Type::getTape();
374 Position endPos = tape.getPosition();
384 this->localAdjoints.data());
389 void computeJacobianLocalAdjointVectorOffset() {
391 Tape& tape = Type::getTape();
392 Position endPos = tape.getPosition();
398 Identifier minIdentifier = std::numeric_limits<Identifier>::max();
399 Identifier maxIdentifier = std::numeric_limits<Identifier>::min();
401 auto determineMinMaxIdentifier = [&minIdentifier, &maxIdentifier](
typename Tape::Identifier
const& identifier) {
402 minIdentifier = std::min(minIdentifier, identifier);
403 maxIdentifier = std::max(maxIdentifier, identifier);
407 for (
auto const& identifier :
inputData) {
408 determineMinMaxIdentifier(identifier);
412 determineMinMaxIdentifier(identifier);
416 tape.editIdentifiers(determineMinMaxIdentifier,
startPos, endPos);
419 size_t requiredVectorSize = maxIdentifier - minIdentifier + 1;
423 using LocalAdjointsOffset = AdjointVectorWithOffset<Identifier, Gradient>;
424 LocalAdjointsOffset localAdjointsOffset(this->
localAdjoints.data(), minIdentifier);
429 localAdjointsOffset);
434 void computeJacobianLocalMappedAdjoints() {
436 Tape& tape = Type::getTape();
437 Position endPos = tape.getPosition();
442 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
443 LocalMappedAdjoints mappedAdjoints;
452 void computeJacobianLocalAdjointVectorPreprocessTape() {
454 Tape& tape = Type::getTape();
455 Position endPos = tape.getPosition();
460 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
463 auto nextIdentifier =
typename Tape::Identifier() + 1;
464 IdentifierMap oldToNewIdentifierMap;
468 auto accessOldToNewIdentifierMap = [&](
typename Tape::Identifier
const& oldIdentifier) ->
469 typename Tape::Identifier
const& {
470 auto result = oldToNewIdentifierMap.insert({oldIdentifier, nextIdentifier});
474 return result.first->second;
478 for (
auto const& oldIdentifier :
inputData) {
479 accessOldToNewIdentifierMap(oldIdentifier);
483 for (
auto const& oldIdentifier :
outputData) {
484 accessOldToNewIdentifierMap(oldIdentifier);
487 auto editIdentifier = [&](
typename Tape::Identifier& oldIdentifier) {
488 oldIdentifier = accessOldToNewIdentifierMap(oldIdentifier);
492 tape.editIdentifiers(editIdentifier,
startPos, endPos);
495 std::vector<typename Tape::Identifier> newInputData;
497 for (
auto const& identifier :
inputData) {
498 newInputData.push_back(oldToNewIdentifierMap[identifier]);
501 std::vector<typename Tape::Identifier> newOutputData;
504 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
509 oldToNewIdentifierMap.clear();
512 std::vector<typename Tape::Gradient>
localAdjoints(nextIdentifier);
516 newInputData.size(), newOutputData.data(),
522 void storeJacobian() {
523 Tape& tape = Type::getTape();
525 for (
size_t curOut = 0; curOut <
outputData.size(); ++curOut) {
527 if (0 !=
jacobian.nonZerosRow(curOut)) {
528 int nonZerosLeft =
jacobian.nonZerosRow(curOut);
533 Identifier lastIdentifier = value.getIdentifier();
534 bool staggeringActive =
false;
551 while (nonZerosLeft > 0) {
553 int jacobiansForStatement = nonZerosLeft;
556 if (staggeringActive) {
557 jacobiansForStatement -= 1;
560 nonZerosLeft -= jacobiansForStatement;
565 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (
int)staggeringActive);
566 if (staggeringActive) {
567 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
571 while (jacobiansForStatement > 0) {
574 jacobiansForStatement -= 1;
579 staggeringActive =
true;
582 value.getIdentifier() = lastIdentifier;
585 tape.destroyIdentifier(value.value(), value.getIdentifier());
591#ifndef DOXYGEN_DISABLE
597 struct PreaccumulationHelperNoOpBase {
601 template<
typename... Inputs>
602 void addInput(Inputs
const&... inputs) {
608 template<
typename... Inputs>
609 void start(Inputs
const&... inputs) {
615 template<
typename... Outputs>
616 void addOutput(Outputs&... outputs) {
622 template<
typename... Outputs>
623 void finish(
bool const storeAdjoints, Outputs&... outputs) {
629 template<
typename... Outputs>
630 void finishLocalMappedAdjoints(Outputs&... outputs) {
636 template<
typename... Outputs>
637 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
643 template<
typename... Outputs>
644 void finishLocalAdjoints(Outputs&... outputs) {
650 template<
typename... Outputs>
651 void finishLocalAdjointVector(Outputs&... outputs) {
657 template<
typename... Outputs>
658 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
665 template<
typename Type>
667 :
public PreaccumulationHelperNoOpBase {};
680 template<
typename T_Type>
684 using Type =
CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
687 using Tag =
typename Tape::Tag;
691 std::vector<Type const*> inputLocations;
692 std::vector<Type*> outputLocations;
701 template<
typename... Inputs>
702 void addInput(Inputs
const&... inputs) {
703 Tape& tape = getTape();
705 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
706 addInputRecursive(inputs...);
711 template<
typename... Inputs>
712 void start(Inputs
const&... inputs) {
713 Tape& tape = getTape();
715 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
716 inputLocations.clear();
717 outputLocations.clear();
718 oldTag = tape.getCurTag();
719 tape.setCurTag(tape.getPreaccumulationHandlingTag());
721 addInputRecursive(inputs...);
726 template<
typename... Outputs>
728 Tape& tape = getTape();
730 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
731 addOutputRecursive(outputs...);
736 template<
typename... Outputs>
737 void finish(
bool const storeAdjoints, Outputs&... outputs) {
740 Tape& tape = getTape();
742 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
743 addOutputRecursive(outputs...);
745 tape.setCurTag(oldTag);
746 for (
Type const* curInput : inputLocations) {
747 tape.setTagOnVariable(*curInput);
749 for (
Type* curOutput : outputLocations) {
750 tape.setTagOnVariable(*curOutput);
756 template<
typename... Outputs>
758 finish(
false, outputs...);
762 template<
typename... Outputs>
764 finish(
false, outputs...);
768 template<
typename... Outputs>
770 finish(
false, outputs...);
774 template<
typename... Outputs>
776 finish(
false, outputs...);
780 template<
typename... Outputs>
782 finish(
false, outputs...);
788 void addInputRecursive() {
792 template<
typename... Inputs>
793 void addInputRecursive(
Type const& input, Inputs
const&... r) {
795 addInputRecursive(r...);
798 void handleInput(
Type const& input) {
799 if (Type::getTape().getPassiveIndex() != input.getIdentifier()) {
800 inputLocations.push_back(&input);
801 getTape().setTagOnVariable(input);
806 void addOutputRecursive() {
810 template<
typename... Outputs>
811 void addOutputRecursive(
Type& output, Outputs&... r) {
812 handleOutput(output);
813 addOutputRecursive(r...);
816 void handleOutput(
Type& value) {
817 outputLocations.push_back(&value);
821 return Type::getTape();
#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