29 #include "Fastor/Fastor.h"
35 #include <Fastor/config/macros.h>
36 #include <Fastor/tensor/Tensor.h>
40 namespace NumericalAlgorithms::Differentiation {
42 namespace ScalarToTensor {
44 template <
size_t... Rest >
46 const std::function< Fastor::Tensor< double, Rest... >(
const double ) >&
F,
51 Fastor::Tensor< double, Rest... > dF =
F( x + h ) -
F( x );
56 template <
size_t... Rest >
58 const std::function< Fastor::Tensor< double, Rest... >(
const double ) >&
F,
63 Fastor::Tensor< double, Rest... > dF =
F( x + h ) -
F( x - h );
69 namespace TensorToScalar {
71 template <
size_t... Rest >
96 template <
size_t dim >
98 const Fastor::Tensor< double, dim, dim >& T )
100 Fastor::Tensor< double, dim, dim > T_right( T );
101 Fastor::Tensor< double, dim, dim >
dF_dT( 0.0 );
102 const double f_ = f( T );
104 for (
size_t i = 0;
i < dim;
i++ ) {
105 for (
size_t j = 0;
j < dim;
j++ ) {
108 T_right(
i,
j ) += h;
109 dF_dT(
i,
j ) = ( f( T_right ) - f_ ) / ( 1. * h );
110 T_right(
i,
j ) -= h;
117 template <
size_t dim >
119 const Fastor::Tensor< double, dim, dim >& T )
122 Fastor::Tensor< double, dim, dim >
dF_dT;
123 Fastor::Tensor< double, dim, dim > T_right( T );
124 Fastor::Tensor< double, dim, dim > T_left( T );
126 for (
size_t i = 0;
i < dim;
i++ ) {
127 for (
size_t j = 0;
j < dim;
j++ ) {
132 T_right(
i,
j ) += h;
135 dF_dT(
i,
j ) = (
F( T_right ) -
F( T_left ) ) / ( 2. * h );
143 namespace TensorToTensor {
145 template <
size_t... RestF,
size_t... RestT >
147 const std::function< Fastor::Tensor< double, RestF... >(
const Fastor::Tensor< double, RestT... >& ) >&
F,
148 const Fastor::Tensor< double, RestT... >& T )
151 Fastor::Tensor< double, RestF..., RestT... >
dF_dT( 0.0 );
152 Fastor::Tensor< double, RestT... > T_right( T );
154 Fastor::Tensor< double, RestF... > F_at_T =
F( T );
155 Fastor::Tensor< double, RestF... > F_at_T_right( 0.0 );
157 double* dF_dT_data =
dF_dT.data();
158 double* T_right_data = T_right.data();
159 double* F_at_T_data = F_at_T.data();
160 double* F_at_T_right_data = F_at_T_right.data();
162 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
163 const int T_right_mem_idx = T_right.get_mem_index(
i );
164 double volatile h = std::max( 1.0, std::abs(
double( T.data()[T_right_mem_idx] ) ) ) *
167 T_right_data[T_right_mem_idx] += h;
168 F_at_T_right =
F( T_right );
170 for ( Fastor::FASTOR_INDEX
j = 0;
j < F_at_T_right.size(); ++
j ) {
171 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 )] -
172 F_at_T_data[F_at_T.get_mem_index(
j )] ) /
180 template <
size_t... Rest1,
size_t... Rest2 >
182 const std::function< Fastor::Tensor< double, Rest1... >(
const Fastor::Tensor< double, Rest2... >& ) >&
F,
183 const Fastor::Tensor< double, Rest2... >& T )
186 Fastor::Tensor< double, Rest1..., Rest2... >
dF_dT( 0.0 );
187 Fastor::Tensor< double, Rest2... > T_right( T );
188 Fastor::Tensor< double, Rest2... > T_left( T );
190 Fastor::Tensor< double, Rest1... > F_at_T_right( 0.0 );
191 Fastor::Tensor< double, Rest1... > F_at_T_left( 0.0 );
193 double* dF_dT_data =
dF_dT.data();
194 double* T_right_data = T_right.data();
195 double* T_left_data = T_left.data();
196 double* F_at_T_right_data = F_at_T_right.data();
197 double* F_at_T_left_data = F_at_T_left.data();
199 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
200 const int T_right_mem_idx = T_right.get_mem_index(
i );
201 const int T_left_mem_idx = T_left.get_mem_index(
i );
202 double volatile h = std::max( 1.0, std::abs(
double( T.data()[T_right_mem_idx] ) ) ) *
205 T_left_data[T_left_mem_idx] -= h;
206 F_at_T_left =
F( T_left );
209 T_right_data[T_right_mem_idx] += h;
210 F_at_T_right =
F( T_right );
212 for ( Fastor::FASTOR_INDEX
j = 0;
j < F_at_T_right.size(); ++
j ) {
213 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 )] -
214 F_at_T_left_data[F_at_T_left.get_mem_index(
j )] ) /
229 template <
size_t dim >
231 const Fastor::Tensor< std::complex< double >, dim, dim >& T ) >;
233 template <
size_t dim >
235 const Fastor::Tensor< double, dim, dim >& T )
237 Fastor::Tensor< double, dim, dim >
dF_dT;
238 Fastor::Tensor< std::complex< double >, dim, dim >
239 T_right = fastorTensorFromDoubleTensor< std::complex< double >, dim >( T );
241 for (
size_t i = 0;
i < dim;
i++ ) {
242 for (
size_t j = 0;
j < dim;
j++ ) {
253 namespace ScalarToTensor {
255 template <
size_t... Rest >
256 std::tuple< Fastor::Tensor< double, Rest... >, Fastor::Tensor< double, Rest... > >
forwardDifference(
257 const std::function< Fastor::Tensor< complexDouble, Rest... >(
const complexDouble ) >&
F,
262 Fastor::Tensor< double, Rest... > dF_dx( 0.0 );
263 Fastor::Tensor< double, Rest... > FReal( 0.0 );
265 double* dF_dx_data = dF_dx.data();
266 double* FReal_data = FReal.data();
268 for ( Fastor::FASTOR_INDEX
j = 0;
j < F_.size(); ++
j ) {
269 FReal_data[FReal.get_mem_index(
j )] = F_data[F_.get_mem_index(
j )].real();
273 return { FReal, dF_dx };
277 namespace TensorToScalar {
279 template <
size_t... Rest >
281 const Fastor::Tensor< complexDouble, Rest... >& T ) >;
283 template <
size_t dim >
285 const Fastor::Tensor< double, dim, dim >& T )
287 Fastor::Tensor< complexDouble, dim, dim > T_right = fastorTensorFromDoubleTensor< complexDouble >( T );
288 Fastor::Tensor< double, dim, dim >
dF_dT( 0.0 );
290 for (
size_t i = 0;
i < dim;
i++ ) {
291 for (
size_t j = 0;
j < dim;
j++ ) {
317 namespace TensorToTensor {
318 template <
size_t... RestF,
size_t... RestT >
321 Fastor::Tensor< complexDouble, RestF... >(
const Fastor::Tensor< complexDouble, RestT... >& ) >&
F,
322 const Fastor::Tensor< double, RestT... >& T )
325 Fastor::Tensor< double, RestF..., RestT... >
dF_dT( 0.0 );
326 Fastor::Tensor<
complexDouble, RestT... > T_right = fastorTensorFromDoubleTensor< complexDouble >( T );
328 Fastor::Tensor<
complexDouble, RestF... > F_at_T_right( 0.0 );
330 double* dF_dT_data =
dF_dT.data();
334 for ( Fastor::FASTOR_INDEX
i = 0;
i < T.size(); ++
i ) {
335 const int T_right_mem_idx = T_right.get_mem_index(
i );
338 F_at_T_right =
F( T_right );
340 for ( Fastor::FASTOR_INDEX
j = 0;
j < F_at_T_right.size(); ++
j ) {
341 dF_dT_data[
dF_dT.get_mem_index(
j * T.size() +
342 i )] = ( F_at_T_right_data[F_at_T_right.get_mem_index(
j )] ).imag() /