17 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
20template <
class T,
int I>
23 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
26template <
class T,
int G>
29 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
46 template <
typename T>
inline static auto getVee(T &&w1, T &&w2, T &&w3) {
49 std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3)
54 template <
typename T>
inline static auto getHat(T &&w1, T &&w2, T &&w3) {
56 getVee(std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3));
60 template <
typename A>
inline static auto getVee(
A &&t_w_hat) {
64 template <
typename A>
inline static auto getHat(
A &&t_w_vee) {
68 template <
typename A,
typename B>
69 inline static auto exp(
A &&t_w_vee,
B &&theta) {
70 return expImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
73 template <
typename A,
typename B>
74 inline static auto Jl(
A &&t_w_vee,
B &&theta) {
75 return JlImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
78 template <
typename A,
typename B>
79 inline static auto Jr(
A &&t_w_vee,
B &&theta) {
80 return JrImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
84 const auto theta = t_w_vee.l2();
85 return Jr(std::forward<A>(t_w_vee), theta);
88 template <
typename A,
typename B,
typename C>
89 inline static auto action(
A &&t_w_vee,
B &&theta, C &&t_A) {
90 return actionImpl(std::forward<A>(t_w_vee), std::forward<B>(theta),
91 std::forward<C>(t_A));
94 template <
typename A,
typename B>
95 inline static auto diffJl(
A &&t_w_vee,
B &&theta) {
96 return diffJlImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
99 template <
typename A,
typename B>
100 inline static auto diffJr(
A &&t_w_vee,
B &&theta) {
101 return diffJrImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
104 template <
typename A,
typename B>
106 return diffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
109 template <
typename A,
typename B>
111 return diffDiffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
115 template <
typename T1,
typename T2,
typename T3>
116 inline static auto spatialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
118 std::forward<T3>(t_delta_w_vee));
122 template <
typename T1,
typename T2,
typename T3>
124 T3 &&t_delta_w_vee) {
126 std::forward<T3>(t_delta_w_vee));
130 template <
typename T1,
typename T2,
typename T3>
131 inline static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
133 std::forward<T3>(t_delta_w_vee));
137 template <
typename T1,
typename T2,
typename T3>
139 T3 &&t_delta_w_vee) {
141 std::forward<T3>(t_delta_w_vee));
145 template <
typename T1,
typename T2,
typename T3>
146 inline static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat) {
147 return deltaRImpl(std::forward<T1>(t_w_vee), theta,
148 std::forward<T3>(t_A_hat));
153 inline static constexpr int dim = 3;
161 template <
typename T>
165 t_w_vee(
k) = (levi_civita(
i,
j,
k) * t_w_hat(
i,
j)) / 2;
169 template <
typename T>
173 t_w_hat(
i,
j) = levi_civita(
i,
j,
k) * t_w_vee(
k);
177 template <
typename T1,
typename T2,
typename T3>
179 const T2 alpha,
const T3 beta) {
182 auto t_hat =
getHat(t_w_vee);
184 beta * (t_hat(
i,
k) * t_hat(
k,
j));
188 template <
typename T1,
typename T2>
191 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
194 const auto s = sin(theta);
195 const auto s_half = sin(theta / 2);
196 const auto a = s / theta;
197 const auto b = 2 * (s_half / theta) * (s_half / theta);
201 template <
typename T1,
typename T2>
205 auto get_tensor = [&t_w_vee](
auto a,
auto diff_a,
auto b,
auto diff_b) {
213 auto t_hat =
getHat(t_w_vee);
214 t_diff_exp(
i,
j,
k) =
216 a * FTensor::levi_civita<int>(
i,
j,
k)
220 diff_a * t_hat(
i,
j) * t_w_vee(
k)
224 b * (t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
225 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j))
229 diff_b * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k);
234 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
235 return get_tensor(1., -1. / 3., 1. / 2., -1. / 12);
238 const auto ss = sin(theta);
239 const auto a = ss / theta;
241 const auto theta2 = theta * theta;
242 const auto cc = cos(theta);
243 const auto diff_a = (theta * cc - ss) / (theta2 * theta);
245 const auto ss_2 = sin(theta / 2.);
247 const auto b = 2. * ss_2 * ss_2 / theta2;
248 const auto diff_b = (-2 + 2 * cc + theta * ss) / (theta2 * theta2);
250 return get_tensor(
a, diff_a, b, diff_b);
253 template <
typename T1,
typename T2>
257 auto get_tensor = [&t_w_vee](
auto a,
auto diff_a,
auto diff_diff_a,
auto b,
258 auto diff_b,
auto diff_diff_b) {
270 auto t_hat =
getHat(t_w_vee);
271 t_diff_diff_exp(
i,
j,
k,
m) =
273 diff_a * FTensor::levi_civita<int>(
i,
j,
k) * t_w_vee(
m)
280 FTensor::levi_civita<int>(
i,
j,
m) * t_w_vee(
k)
286 diff_diff_a * t_hat(
i,
j) * t_w_vee(
k) * t_w_vee(
m)
290 b * (FTensor::levi_civita<int>(
i,
l,
m) *
291 FTensor::levi_civita<int>(
l,
j,
k) +
292 FTensor::levi_civita<int>(
i,
l,
k) *
293 FTensor::levi_civita<int>(
l,
j,
m))
297 diff_b * ((t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
298 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j)) *
310 FTensor::levi_civita<int>(
i,
l,
m) * t_hat(
l,
j) * t_w_vee(
k)
314 t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
m) * t_w_vee(
k)
320 diff_diff_b * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k) * t_w_vee(
m);
322 return t_diff_diff_exp;
325 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
326 return get_tensor(1., -1. / 3., 1. / 15, 1. / 2, -1. / 12, 1. / 90);
329 const auto ss = sin(theta);
330 const auto a = ss / theta;
332 const auto theta2 = theta * theta;
333 const auto cc = cos(theta);
334 const auto diff_a = (theta * cc - ss) / (theta2 * theta);
335 const auto diff_diff_a =
336 (3. * ss - 3. * theta * cc - theta2 * ss) / (theta2 * theta2 * theta);
338 const auto ss_2 = sin(theta / 2.);
339 const auto b = 2. * ss_2 * ss_2 / theta2;
340 const auto diff_b = (-2 + 2 * cc + theta * ss) / (theta2 * theta2);
341 const auto diff_diff_b = (theta2 * cc - 5. * theta * ss - 8. * cc + 8.) /
342 (theta2 * theta2 * theta2);
344 return get_tensor(
a, diff_a, diff_diff_a, b, diff_b, diff_diff_b);
347 template <
typename T1,
typename T2>
350 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
353 const auto s = sin(theta);
354 const auto s_half = sin(theta / 2);
355 const auto a = 2 * (s_half / theta) * (s_half / theta);
356 const auto b = ((theta - s) / theta) / theta / theta;
360 template <
typename T1,
typename T2>
363 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
366 const auto s = sin(theta);
367 const auto s_half = sin(theta / 2);
368 const auto a = 2 * (s_half / theta) * (s_half / theta);
369 const auto b = ((theta - s) / theta) / theta / theta;
374 template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
377 const T3 diff_alpha,
const T4 beta,
const T5 diff_beta) {
386 auto t_hat =
getHat(t_w_vee);
390 alpha * FTensor::levi_civita<int>(
i,
j,
k)
394 diff_alpha * t_hat(
i,
j) * t_w_vee(
k)
398 beta * (t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
399 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j))
403 diff_beta * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k);
408 template <
typename T1,
typename T2>
411 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
420 const auto s = sin(theta);
421 const auto c = cos(theta);
423 const auto theta2 = theta * theta;
424 const auto theta4 = theta2 * theta2;
425 const auto theta5 = theta4 * theta;
428 const auto a = (1. -
c) / theta2;
429 const auto diff_a = (theta * s + 2. *
c - 2.) / theta4;
431 const auto b = (theta - s) / (theta2 * theta);
432 const auto diff_b = (3. * s - theta *
c - 2. * theta) / theta5;
437 template <
typename T1,
typename T2>
440 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
449 const auto s = sin(theta);
450 const auto c = cos(theta);
452 const auto theta2 = theta * theta;
453 const auto theta4 = theta2 * theta2;
454 const auto theta5 = theta4 * theta;
458 const auto alpha = -(1. -
c) / theta2;
459 const auto diff_alpha = (2. - 2. *
c - theta * s) / theta4;
463 const auto beta = (theta - s) / (theta2 * theta);
464 const auto diff_beta = (3. * s - theta *
c - 2. * theta) / theta5;
469 template <
typename T1,
typename T2,
typename T3>
475 t_B(
i,
j) =
exp(t_w_vee, theta)(
i,
k) * t_A(
k,
j);
479 template <
typename T1,
typename T2,
typename T3>
485 auto t_Jl =
Jl(t_w_vee, theta);
486 t_w(
i) = t_Jl(
i,
j) * t_delta_w_vee(
j);
490 template <
typename T1,
typename T2,
typename T3>
498 template <
typename T1,
typename T2,
typename T3>
504 auto t_Jr =
Jr(t_w_vee, theta);
505 t_a(
i) = t_Jr(
i,
j) * t_delta_w_vee(
j);
509 template <
typename T1,
typename T2,
typename T3>
518 template <
typename T1,
typename T2,
typename T3>
524 auto t_R =
exp(t_w_vee, theta);
525 t_delta_R(
i,
j) = t_R(
i,
k) * t_A_hat(
k,
j);
530 template <
typename T1,
typename T2,
typename T3>
#define FTENSOR_INDEX(DIM, I)
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
const double n
refractive index of diffusive medium
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
Tensors class implemented by Walter Landry.
FTensor::Index< 'm', 3 > m
static auto diffDiffExp(A &&t_w_vee, B &&theta)
static auto spatialSpinHatImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto Jr(A &&t_w_vee, B &&theta)
static auto diffJlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
static auto genericFormImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 alpha, const T3 beta)
static auto genericDiffFormImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 alpha, const T3 diff_alpha, const T4 beta, const T5 diff_beta)
static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat)
static auto Jl(A &&t_w_vee, B &&theta)
static auto action(A &&t_w_vee, B &&theta, C &&t_A)
static auto actionImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor2_symmetric< T3, dim > &t_A)
static FTENSOR_INDEX(dim, l)
static FTENSOR_INDEX(dim, k)
static auto getVee(A &&t_w_hat)
static auto getHatImpl(const FTensor::Tensor1< T, dim > &t_w_vee)
static auto JlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 &theta)
static auto getHat(T &&w1, T &&w2, T &&w3)
static auto deltaRImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto deltaRImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor2< T3, dim, dim > &t_A_hat)
static auto JrImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
static auto diffJr(A &&t_w_vee, B &&theta)
static auto right_jacobian(A &&t_w_vee)
static FTENSOR_INDEX(dim, j)
static auto expImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
static auto diffJl(A &&t_w_vee, B &&theta)
static auto getVeeImpl(const FTensor::Tensor2< T, dim, dim > &t_w_hat)
static auto diffExp(A &&t_w_vee, B &&theta)
static auto spatialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
static auto spatialSpinHat(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
static auto materialSpinHatImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto diffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
static auto diffJrImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
static auto materialSpinHat(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
static auto spatialSpinImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto getHat(A &&t_w_vee)
static FTENSOR_INDEX(dim, n)
static FTENSOR_INDEX(dim, m)
static FTENSOR_INDEX(dim, i)
static auto materialSpinImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto getVee(T &&w1, T &&w2, T &&w3)
static auto exp(A &&t_w_vee, B &&theta)
static auto diffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)