@@ -31,30 +31,49 @@ namespace tensorium_RG {
3131
3232 enum class DiffMode { PARTIAL, COV, COV2 };
3333
34- // ===================== RANK 0 (SCALAR) =====================
35- // Return type : Tensor<T,1> (i.e. un vecteur gradient)
36- template <typename T, typename ScalarFunc>
37- tensorium::Tensor<T, 1 > autodiff_rank0 (
38- const tensorium::Vector<T>& X,
39- T dx, T dy, T dz,
40- ScalarFunc&& func,
41- DiffMode mode,
42- const tensorium::Tensor<T, 3 >& christoffel)
43- {
44- using namespace tensorium ;
45- if (mode == DiffMode::PARTIAL) {
46- return partial_scalar (X, dx, dy, dz, std::forward<ScalarFunc>(func));
47- }
48- else if (mode == DiffMode::COV2) {
49- return covariant_scalar_second (X, dx, dy, dz, std::forward<ScalarFunc>(func), christoffel);
50- }
51- else {
52- throw std::invalid_argument (" autodiff_rank0: uniquement PARTIAL ou COV2 autorisés pour un champ scalaire" );
53- }
54- }
5534
56- // ===================== RANK 1 (VECTOR) =====================
57- // Return type : Tensor<T,2> (i.e. une matrice dérivée covariante ou jacobienne)
35+ template <typename T, typename ScalarFunc>
36+ tensorium::Vector<T> covariant_scalar (
37+ const tensorium::Vector<T>& X,
38+ T dx, T dy, T dz,
39+ ScalarFunc&& func,
40+ const tensorium::Tensor<T, 3 >& christoffel)
41+ {
42+ tensorium::Vector<T> grad = partial_scalar (X, dx, dy, dz, std::forward<ScalarFunc>(func));
43+ return grad;
44+ }
45+
46+ template <typename T, typename ScalarFunc>
47+ tensorium::Tensor<T, 2 > autodiff_scalar_second (
48+ const tensorium::Vector<T>& X,
49+ T dx, T dy, T dz,
50+ ScalarFunc&& func,
51+ const tensorium::Tensor<T, 3 >& christoffel)
52+ {
53+ return covariant_scalar_second (X, dx, dy, dz, std::forward<ScalarFunc>(func), christoffel);
54+ }
55+
56+ template <typename T, typename ScalarFunc>
57+ tensorium::Vector<T> autodiff_rank0 (
58+ const tensorium::Vector<T>& X,
59+ T dx, T dy, T dz,
60+ ScalarFunc&& func,
61+ DiffMode mode,
62+ const tensorium::Tensor<T, 3 >& christoffel)
63+ {
64+ using namespace tensorium ;
65+ if (mode == DiffMode::PARTIAL) {
66+ return partial_scalar (X, dx, dy, dz, std::forward<ScalarFunc>(func));
67+ }
68+ else if (mode == DiffMode::COV) {
69+ return covariant_scalar (X, dx, dy, dz, std::forward<ScalarFunc>(func), christoffel);
70+ }
71+ else {
72+ throw std::invalid_argument (" autodiff_rank0: PARTIAL ou COV uniquement. Utiliser `autodiff_scalar_second` pour COV2." );
73+ }
74+ }
75+
76+
5877 template <typename T, typename VectorFunc>
5978 tensorium::Tensor<T, 2 > autodiff_rank1 (
6079 const tensorium::Vector<T>& X,
@@ -75,9 +94,6 @@ namespace tensorium_RG {
7594 }
7695 }
7796
78- // ============== RANK 2 (TENSOR 2D) : PREMIÈRE DÉRIVÉE SEULEMENT ==============
79- // Nous n'implémentons ici que PARTIAL et COV. Si on demande COV2, on lève une exception.
80- // Return type : Tensor<T,3> (i.e. un tenseur à 3 indices : ∂_k T_{ij} ou ∇_k T_{ij})
8197 template <typename T, typename TensorFunc>
8298 tensorium::Tensor<T, 3 > autodiff_rank2_first (
8399 const tensorium::Vector<T>& X,
@@ -98,7 +114,6 @@ namespace tensorium_RG {
98114 }
99115 }
100116
101- // ===================== WRAPPER GÉNÉRIQUE =====================
102117 template <typename T, typename FieldFunc>
103118 auto autodiff (
104119 const tensorium::Vector<T>& X,
@@ -109,18 +124,18 @@ namespace tensorium_RG {
109124 {
110125 using namespace tensorium ;
111126 auto sample = func (X);
112- constexpr size_t rank = TensorTraits<std::decay_t <decltype (sample)>>::rank;
127+
128+ constexpr size_t rank = TensorTraits<std::decay_t <decltype (sample)>>::rank;
113129
114- if constexpr (rank == 0 ) {
115- return autodiff_rank0 (X, dx, dy, dz, std::forward<FieldFunc>(func), mode, christoffel);
116- }
117- else if constexpr (rank == 1 ) {
130+ if constexpr (rank == 0 ) {
131+ if (mode == DiffMode::COV2)
132+ return autodiff_scalar_second (X, dx, dy, dz, std::forward<FieldFunc>(func), christoffel); // <- nouveau chemin
133+ else
134+ return autodiff_rank0 (X, dx, dy, dz, std::forward<FieldFunc>(func), mode, christoffel);
135+ } else if constexpr (rank == 1 ) {
118136 return autodiff_rank1 (X, dx, dy, dz, std::forward<FieldFunc>(func), mode, christoffel);
119137 }
120138 else if constexpr (rank == 2 ) {
121- // On autorise ici PARTIAL et COV uniquement pour un champ « Tensor, rank2 ».
122- // Si on veut une dérivée covariante seconde d'un tenseur 2D, l'utilisateur
123- // devra appeler explicitement la fonction covariant_tensor2_second(...) par lui-même.
124139 return autodiff_rank2_first (X, dx, dy, dz, std::forward<FieldFunc>(func), mode, christoffel);
125140 }
126141 else {
0 commit comments