29 #include "Fastor/Fastor.h"
32 #include "autodiff/forward/dual.hpp"
33 #include "autodiff/forward/dual/eigen.hpp"
34 #include <autodiff/forward/dual/dual.hpp>
39 namespace AutomaticDifferentiation {
41 using namespace autodiff;
43 template <
size_t order,
size_t... Rest >
45 const Fastor::Tensor< HigherOrderDual< order, double >, Rest... >&
in )
47 using in_scalar_type = HigherOrderDual< order, double >;
48 using out_scalar_type = HigherOrderDual< order + 1, double >;
50 Fastor::Tensor< out_scalar_type, Rest... > out( 0.0 );
51 out_scalar_type* out_data = out.data();
52 in_scalar_type* in_data =
in.data();
54 for ( Fastor::FASTOR_INDEX
i = 0;
i <
in.size(); ++
i ) {
55 out_data[out.get_mem_index(
i )] = increaseDualOrderWithShift< order >( in_data[
in.get_mem_index(
i )] );
60 template <
size_t... Rest >
63 template <
size_t... Rest >
65 const Fastor::Tensor< double, Rest... >& T )
67 Fastor::Tensor< double, Rest... >
df_dT( 0.0 );
68 Fastor::Tensor< dual, Rest... > T_right =
makeDual( T );
70 double* df_dT_data =
df_dT.data();
71 dual* T_right_data = T_right.data();
73 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
74 const int T_right_mem_idx = T_right.get_mem_index(
i );
75 seed< 1 >( T_right_data[T_right_mem_idx], 1.0 );
76 df_dT_data[
df_dT.get_mem_index(
i )] = derivative< 1 >( f( T_right ) );
77 seed< 1 >( T_right_data[T_right_mem_idx], 0.0 );
83 template <
size_t order,
size_t... Rest >
85 const Fastor::Tensor< HigherOrderDual< order, double >, Rest... >& T ) >;
87 template <
size_t order,
size_t... Rest >
88 std::pair< HigherOrderDual< order, double >, Fastor::Tensor< HigherOrderDual< order, double >, Rest... > >
df_dT(
90 const Fastor::Tensor< HigherOrderDual< order, double >, Rest... >& T )
93 using scalartype = HigherOrderDual< order, double >;
94 using higherOrderScalartype = HigherOrderDual< order + 1, double >;
96 higherOrderScalartype f_;
97 Fastor::Tensor< scalartype, Rest... > df_dT_( 0.0 );
98 Fastor::Tensor< higherOrderScalartype, Rest... > T_right = increaseDualOrderWithShift< order >( T );
100 higherOrderScalartype* T_right_data = T_right.data();
101 scalartype* df_dT_data = df_dT_.data();
103 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
104 seed< 1 >( T_right_data[T_right.get_mem_index(
i )], 1.0 );
106 df_dT_data[df_dT_.get_mem_index(
i )] = decreaseDualOrderWithShift< order + 1 >( f_ );
107 seed< 1 >( T_right_data[T_right.get_mem_index(
i )], 0.0 );
110 return { decreaseDualOrder< order + 1 >( f_ ), df_dT_ };
113 template <
size_t... RestF,
size_t... RestT >
114 std::pair< Fastor::Tensor< double, RestF... >, Fastor::Tensor< double, RestF..., RestT... > >
dF_dT(
115 std::function< Fastor::Tensor< dual, RestF... >(
const Fastor::Tensor< dual, RestT... >& ) >&
F,
116 const Fastor::Tensor< double, RestT... >& T )
119 Fastor::Tensor< double, RestF... > F_( 0.0 );
120 Fastor::Tensor< double, RestF..., RestT... > dF_dT_( 0.0 );
121 Fastor::Tensor< dual, RestT... > T_right =
makeDual( T );
123 Fastor::Tensor< dual, RestF... > F_at_T_right( 0.0 );
125 double* dF_dT_data = dF_dT_.data();
126 dual* T_right_data = T_right.data();
127 dual* F_at_T_right_data = F_at_T_right.data();
129 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
130 const int T_right_mem_idx = T_right.get_mem_index(
i );
131 T_right_data[T_right_mem_idx].grad += 1.0;
132 F_at_T_right =
F( T_right );
134 for ( Fastor::FASTOR_INDEX
j = 0;
j < F_at_T_right.size(); ++
j ) {
135 dF_dT_data[dF_dT_.get_mem_index(
j * T.size() +
i )] = F_at_T_right_data[F_at_T_right.get_mem_index(
j )]
138 T_right_data[T_right_mem_idx].grad -= 1.0;
143 return { F_, dF_dT_ };
146 namespace SecondOrder {
148 template <
size_t dim >
151 template <
size_t dim >
152 std::tuple< double, Fastor::Tensor< double, dim, dim >, Fastor::Tensor< double, dim, dim, dim, dim > >
d2f_dT2(
154 const Fastor::Tensor< double, dim, dim >& T )
158 Fastor::Tensor< double, dim, dim > dF_dT_;
159 Fastor::Tensor< double, dim, dim, dim, dim > d2F_dT2;
160 Fastor::Tensor< dual2nd, dim, dim > T_right = makeHigherOrderDual< 2 >( T );
162 for (
size_t i = 0;
i < dim;
i++ ) {
163 for (
size_t j = 0;
j < dim;
j++ ) {
164 seed< 1 >( T_right(
i,
j ), 1.0 );
166 for (
size_t k = 0;
k < dim;
k++ ) {
167 for (
size_t l = 0;
l < dim;
l++ ) {
169 seed< 2 >( T_right(
k,
l ), 1.0 );
170 F_right =
F( T_right );
171 d2F_dT2(
i,
j,
k,
l ) = derivative< 2 >( F_right );
173 seed< 2 >( T_right(
k,
l ), 0.0 );
176 dF_dT_(
i,
j ) = derivative< 1 >( F_right );
177 F_ = double( F_right );
178 seed< 1 >( T_right(
i,
j ), 0.0 );
182 return { F_, dF_dT_, d2F_dT2 };
185 template <
size_t dim >
187 dual2nd(
const Fastor::Tensor< dual2nd, dim, dim >& T,
const dual2nd scalar ) >;
189 template <
size_t dim >
191 const Fastor::Tensor< double, dim, dim >& T,
192 const double scalar )
194 Fastor::Tensor< double, dim, dim > d2F_dTdScalar;
195 Fastor::Tensor< dual2nd, dim, dim > T_right = makeHigherOrderDual< 2 >( T );
197 dual2nd scalar_right( scalar );
198 seed< 2 >( scalar_right, 1.0 );
200 for (
size_t i = 0;
i < dim;
i++ ) {
201 for (
size_t j = 0;
j < dim;
j++ ) {
203 seed< 1 >( T_right(
i,
j ), 1.0 );
205 d2F_dTdScalar(
i,
j ) = derivative< 2 >(
F( T_right, scalar_right ) );
207 seed< 1 >( T_right(
i,
j ), 0.0 );
211 return d2F_dTdScalar;