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;
123 template<
typename... Inputs>
125 Tape& tape = Type::getTape();
127 if (tape.isActive()) {
128 addInputRecursive(inputs...);
133 template<
typename... Inputs>
134 void start(Inputs
const&... inputs) {
135 Tape& tape = Type::getTape();
139 if (tape.isActive()) {
147 addInputRecursive(inputs...);
152 template<
typename... Outputs>
154 Tape& tape = Type::getTape();
156 if (tape.isActive()) {
157 addOutputRecursive(outputs...);
163 template<
typename Func,
typename... Outputs>
165 Tape& tape = Type::getTape();
167 if (tape.isActive()) {
168 addOutputRecursive(outputs...);
184 template<
typename... Outputs>
185 void finish(
bool const storeAdjoints, Outputs&... outputs) {
186 auto coreRoutine = [&storeAdjoints,
this]() {
188 storeInputAdjoints();
192 restoreInputAdjoints();
201 template<
typename... Outputs>
203 auto coreRoutine = [
this]() {
204 computeJacobianLocalMappedAdjoints();
214 template<
typename... Outputs>
216 auto coreRoutine = [
this]() {
217 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>();
227 template<
typename... Outputs>
229 auto coreRoutine = [
this]() {
231 computeJacobianLocalAdjointVectorPreprocessTapeIfAvailable<Tape>();
234 computeJacobianLocalMappedAdjoints();
243 template<
typename... Outputs>
245 auto coreRoutine = [
this]() {
246 computeJacobianLocalAdjointVector();
256 template<
typename... Outputs>
258 auto coreRoutine = [
this]() {
259 computeJacobianLocalAdjointVectorOffsetIfAvailable<Tape>();
269 template<
typename Tape>
271 computeJacobianLocalAdjointVectorPreprocessTape();
275 template<
typename Tape>
277 computeJacobianLocalMappedAdjoints();
281 template<
typename Tape>
283 computeJacobianLocalAdjointVectorOffset();
287 template<
typename Tape>
289 computeJacobianLocalAdjointVector();
292 void addInputLogic(
Type const& input) {
294 Identifier const& identifier = input.getIdentifier();
295 if (Type::getTape().getPassiveIndex() != identifier) {
302 void addInputRecursive() {
306 template<
typename... Inputs>
307 void addInputRecursive(
Type const& input, Inputs
const&... r) {
308 addInputLogic(input);
309 addInputRecursive(r...);
312 void addOutputLogic(
Type& output) {
314 Identifier const& identifier = output.getIdentifier();
315 if (Type::getTape().getPassiveIndex() != identifier) {
322 void addOutputRecursive() {
326 template<
typename... Outputs>
327 void addOutputRecursive(
Type& output, Outputs&... r) {
328 addOutputLogic(output);
329 addOutputRecursive(r...);
332 void storeInputAdjoints() {
333 Tape& tape = Type::getTape();
339 for (
size_t i = 0; i <
inputData.size(); ++i) {
341 Gradient& adjoint = tape.gradient(index);
347 void restoreInputAdjoints() {
348 Tape& tape = Type::getTape();
350 for (
size_t i = 0; i <
inputData.size(); ++i) {
356 void resizeJacobian() {
362 void computeJacobian() {
364 Tape& tape = Type::getTape();
365 Position endPos = tape.getPosition();
370 tape.resizeAdjointVector();
371 tape.beginUseAdjointVector();
379 tape.endUseAdjointVector();
382 void computeJacobianLocalAdjointVector() {
384 Tape& tape = Type::getTape();
385 Position endPos = tape.getPosition();
395 this->localAdjoints.data());
400 void computeJacobianLocalAdjointVectorOffset() {
402 Tape& tape = Type::getTape();
403 Position endPos = tape.getPosition();
409 Identifier minIdentifier = std::numeric_limits<Identifier>::max();
410 Identifier maxIdentifier = std::numeric_limits<Identifier>::min();
412 auto determineMinMaxIdentifier = [&minIdentifier, &maxIdentifier](
typename Tape::Identifier
const& identifier) {
413 minIdentifier = std::min(minIdentifier, identifier);
414 maxIdentifier = std::max(maxIdentifier, identifier);
418 for (
auto const& identifier :
inputData) {
419 determineMinMaxIdentifier(identifier);
423 determineMinMaxIdentifier(identifier);
427 tape.editIdentifiers(determineMinMaxIdentifier,
startPos, endPos);
430 size_t requiredVectorSize = maxIdentifier - minIdentifier + 1;
434 using LocalAdjointsOffset = AdjointVectorWithOffset<Identifier, Gradient>;
435 LocalAdjointsOffset localAdjointsOffset(this->
localAdjoints.data(), minIdentifier);
440 localAdjointsOffset);
445 void computeJacobianLocalMappedAdjoints() {
447 Tape& tape = Type::getTape();
448 Position endPos = tape.getPosition();
453 using LocalMappedAdjoints = MappedAdjoints<typename Tape::Identifier, typename Tape::Gradient>;
454 LocalMappedAdjoints mappedAdjoints;
463 void computeJacobianLocalAdjointVectorPreprocessTape() {
465 Tape& tape = Type::getTape();
466 Position endPos = tape.getPosition();
471 using IdentifierMap = std::map<typename Tape::Identifier, typename Tape::Identifier>;
474 auto nextIdentifier =
typename Tape::Identifier() + 1;
475 IdentifierMap oldToNewIdentifierMap;
479 auto accessOldToNewIdentifierMap = [&](
typename Tape::Identifier
const& oldIdentifier) ->
480 typename Tape::Identifier
const& {
481 auto result = oldToNewIdentifierMap.insert({oldIdentifier, nextIdentifier});
485 return result.first->second;
489 for (
auto const& oldIdentifier :
inputData) {
490 accessOldToNewIdentifierMap(oldIdentifier);
494 for (
auto const& oldIdentifier :
outputData) {
495 accessOldToNewIdentifierMap(oldIdentifier);
498 auto editIdentifier = [&](
typename Tape::Identifier& oldIdentifier) {
499 oldIdentifier = accessOldToNewIdentifierMap(oldIdentifier);
503 tape.editIdentifiers(editIdentifier,
startPos, endPos);
506 std::vector<typename Tape::Identifier> newInputData;
508 for (
auto const& identifier :
inputData) {
509 newInputData.push_back(oldToNewIdentifierMap[identifier]);
512 std::vector<typename Tape::Identifier> newOutputData;
515 newOutputData.push_back(oldToNewIdentifierMap[identifier]);
520 oldToNewIdentifierMap.clear();
523 std::vector<typename Tape::Gradient>
localAdjoints(nextIdentifier);
527 newInputData.size(), newOutputData.data(),
533 void storeJacobian() {
534 Tape& tape = Type::getTape();
536 for (
size_t curOut = 0; curOut <
outputData.size(); ++curOut) {
538 if (0 !=
jacobian.nonZerosRow(curOut)) {
539 int nonZerosLeft =
jacobian.nonZerosRow(curOut);
544 TapeData lastIdentifier = value.getTapeData();
545 bool staggeringActive =
false;
562 while (nonZerosLeft > 0) {
564 int jacobiansForStatement = nonZerosLeft;
567 if (staggeringActive) {
568 jacobiansForStatement -= 1;
571 nonZerosLeft -= jacobiansForStatement;
573 TapeData storedIdentifier = lastIdentifier;
576 tape.storeManual(value.getValue(), lastIdentifier, jacobiansForStatement + (
int)staggeringActive);
577 if (staggeringActive) {
578 tape.pushJacobianManual(1.0, 0.0, storedIdentifier);
582 while (jacobiansForStatement > 0) {
585 jacobiansForStatement -= 1;
590 staggeringActive =
true;
593 value.getTapeData() = lastIdentifier;
596 tape.destroyTapeData(value.value(), value.getTapeData());
602#ifndef DOXYGEN_DISABLE
608 struct PreaccumulationHelperNoOpBase {
612 template<
typename... Inputs>
613 void addInput(Inputs
const&... inputs) {
619 template<
typename... Inputs>
620 void start(Inputs
const&... inputs) {
626 template<
typename... Outputs>
627 void addOutput(Outputs&... outputs) {
633 template<
typename... Outputs>
634 void finish(
bool const storeAdjoints, Outputs&... outputs) {
640 template<
typename... Outputs>
641 void finishLocalMappedAdjoints(Outputs&... outputs) {
647 template<
typename... Outputs>
648 void finishLocalAdjointVectorPreprocessTape(Outputs&... outputs) {
654 template<
typename... Outputs>
655 void finishLocalAdjoints(Outputs&... outputs) {
661 template<
typename... Outputs>
662 void finishLocalAdjointVector(Outputs&... outputs) {
668 template<
typename... Outputs>
669 void finishLocalAdjointVectorOffset(Outputs&... outputs) {
676 template<
typename Type>
678 :
public PreaccumulationHelperNoOpBase {};
691 template<
typename T_Type>
695 using Type =
CODI_DD(T_Type, CODI_DEFAULT_LHS_EXPRESSION);
698 using Tag =
typename Tape::Tag;
702 std::vector<Type const*> inputLocations;
703 std::vector<Type*> outputLocations;
712 template<
typename... Inputs>
713 void addInput(Inputs
const&... inputs) {
714 Tape& tape = getTape();
716 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
717 addInputRecursive(inputs...);
722 template<
typename... Inputs>
723 void start(Inputs
const&... inputs) {
724 Tape& tape = getTape();
726 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
727 inputLocations.clear();
728 outputLocations.clear();
730 oldTag = tape.getCurTag();
731 tape.setCurTag(tape.getPreaccumulationHandlingTag());
733 addInputRecursive(inputs...);
738 template<
typename... Outputs>
740 Tape& tape = getTape();
742 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
743 addOutputRecursive(outputs...);
748 template<
typename... Outputs>
749 void finish(
bool const storeAdjoints, Outputs&... outputs) {
752 Tape& tape = getTape();
754 if (tape.isActive() && tape.isPreaccumulationHandlingEnabled()) {
755 addOutputRecursive(outputs...);
757 tape.setCurTag(oldTag);
758 for (
Type const* curInput : inputLocations) {
759 tape.setTagOnVariable(*curInput);
761 for (
Type* curOutput : outputLocations) {
762 tape.setTagOnVariable(*curOutput);
768 template<
typename... Outputs>
770 finish(
false, outputs...);
774 template<
typename... Outputs>
776 finish(
false, outputs...);
780 template<
typename... Outputs>
782 finish(
false, outputs...);
786 template<
typename... Outputs>
788 finish(
false, outputs...);
792 template<
typename... Outputs>
794 finish(
false, outputs...);
800 void addInputRecursive() {
804 template<
typename... Inputs>
805 void addInputRecursive(
Type const& input, Inputs
const&... r) {
807 addInputRecursive(r...);
810 void handleInput(
Type const& input) {
811 Tape& tape = getTape();
813 if (tape.getPassiveIndex() != input.getIdentifier()) {
814 inputLocations.push_back(&input);
815 tape.setTagOnVariable(input);
820 void addOutputRecursive() {
824 template<
typename... Outputs>
825 void addOutputRecursive(
Type& output, Outputs&... r) {
826 handleOutput(output);
827 addOutputRecursive(r...);
830 void handleOutput(
Type& value) {
831 outputLocations.push_back(&value);
835 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: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