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));
116 template <
typename A,
typename B,
typename C>
120 std::forward<C>(t_delta_w_vee));
124 template <
typename T1,
typename T2,
typename T3>
125 inline static auto spatialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
127 std::forward<T3>(t_delta_w_vee));
131 template <
typename T1,
typename T2,
typename T3>
133 T3 &&t_delta_w_vee) {
135 std::forward<T3>(t_delta_w_vee));
139 template <
typename T1,
typename T2,
typename T3>
140 inline static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
142 std::forward<T3>(t_delta_w_vee));
146 template <
typename T1,
typename T2,
typename T3>
148 T3 &&t_delta_w_vee) {
150 std::forward<T3>(t_delta_w_vee));
154 template <
typename T1,
typename T2,
typename T3>
155 inline static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat) {
156 return deltaRImpl(std::forward<T1>(t_w_vee), theta,
157 std::forward<T3>(t_A_hat));
162 inline static constexpr int dim = 3;
170 template <
typename T>
174 t_w_vee(
k) = (levi_civita(
i,
j,
k) * t_w_hat(
i,
j)) / 2;
178 template <
typename T>
182 t_w_hat(
i,
j) = levi_civita(
i,
j,
k) * t_w_vee(
k);
186 template <
typename T1,
typename T2,
typename T3>
188 const T2 alpha,
const T3 beta) {
191 auto t_hat =
getHat(t_w_vee);
193 beta * (t_hat(
i,
k) * t_hat(
k,
j));
197 template <
typename T1,
typename T2>
200 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
203 const auto s = sin(theta);
204 const auto s_half = sin(theta / 2);
205 const auto a = s / theta;
206 const auto b = 2 * (s_half / theta) * (s_half / theta);
226 template <
typename T>
232 const T x = theta * theta;
233 constexpr int terms = 14;
236 for (
int n = 1;
n != terms; ++
n)
238 T *
a[4] = {&
c.a, &
c.diff_a, &
c.diff_diff_a, &
c.diff_diff_diff_a};
239 T *b[4] = {&
c.b, &
c.diff_b, &
c.diff_diff_b, &
c.diff_diff_diff_b};
240 for (
int m = 0;
m != 4; ++
m)
242 double factorial_odd = 1., factorial_even = 2., sign = 1.;
243 for (
int n = 0;
n != terms; ++
n) {
245 factorial_odd *= (2 *
n) * (2 *
n + 1);
246 factorial_even *= (2 *
n + 1) * (2 *
n + 2);
249 double falling = 1.,
scale = 1.;
250 for (
int m = 0;
m <= std::min(
n, 3); ++
m) {
252 *b[
m] += (sign *
scale * falling / factorial_even) *
power[
n -
m];
259 const auto s = sin(theta);
260 const auto cc = cos(theta);
261 const auto t2 = theta * theta;
262 const auto t3 = t2 * theta, t4 = t3 * theta, t5 = t4 * theta,
263 t6 = t5 * theta, t7 = t6 * theta, t8 = t7 * theta;
265 c.diff_a = (theta * cc - s) / t3;
266 c.diff_diff_a = (3. * s - 3. * theta * cc - t2 * s) / t5;
268 (-t3 * cc + 6. * t2 * s + 15. * theta * cc - 15. * s) / t7;
269 c.b = (1. - cc) / t2;
270 c.diff_b = (-2. + 2. * cc + theta * s) / t4;
271 c.diff_diff_b = (t2 * cc - 5. * theta * s - 8. * cc + 8.) / t6;
273 (-t3 * s - 9. * t2 * cc + 33. * theta * s + 48. * cc - 48.) / t8;
277 template <
typename T1,
typename T2>
281 auto get_tensor = [&t_w_vee](
auto a,
auto diff_a,
auto b,
auto diff_b) {
289 auto t_hat =
getHat(t_w_vee);
290 t_diff_exp(
i,
j,
k) =
292 a * FTensor::levi_civita<int>(
i,
j,
k)
296 diff_a * t_hat(
i,
j) * t_w_vee(
k)
300 b * (t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
301 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j))
305 diff_b * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k);
311 return get_tensor(
c.a,
c.diff_a,
c.b,
c.diff_b);
314 template <
typename T1,
typename T2>
318 auto get_tensor = [&t_w_vee](
auto a,
auto diff_a,
auto diff_diff_a,
auto b,
319 auto diff_b,
auto diff_diff_b) {
331 auto t_hat =
getHat(t_w_vee);
332 t_diff_diff_exp(
i,
j,
k,
m) =
334 diff_a * FTensor::levi_civita<int>(
i,
j,
k) * t_w_vee(
m)
341 FTensor::levi_civita<int>(
i,
j,
m) * t_w_vee(
k)
347 diff_diff_a * t_hat(
i,
j) * t_w_vee(
k) * t_w_vee(
m)
351 b * (FTensor::levi_civita<int>(
i,
l,
m) *
352 FTensor::levi_civita<int>(
l,
j,
k) +
353 FTensor::levi_civita<int>(
i,
l,
k) *
354 FTensor::levi_civita<int>(
l,
j,
m))
358 diff_b * ((t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
359 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j)) *
371 FTensor::levi_civita<int>(
i,
l,
m) * t_hat(
l,
j) * t_w_vee(
k)
375 t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
m) * t_w_vee(
k)
381 diff_diff_b * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k) * t_w_vee(
m);
383 return t_diff_diff_exp;
387 return get_tensor(
c.a,
c.diff_a,
c.diff_diff_a,
c.b,
c.diff_b,
399 template <
typename T1,
typename T2,
typename T3>
415 const auto t_hat =
getHat(t_w_vee);
416 const auto t_delta_hat =
getHat(t_delta_w_vee);
417 const D wd = t_w_vee(
n) * t_delta_w_vee(
n);
420 t_hat2(
i,
j) = t_hat(
i,
l) * t_hat(
l,
j);
423 t_hat(
i,
l) * t_delta_hat(
l,
j) + t_delta_hat(
i,
l) * t_hat(
l,
j);
426 t_G(
i,
j,
k) = t_hat(
i,
l) * t_eps(
l,
j,
k) + t_eps(
i,
l,
k) * t_hat(
l,
j);
428 t_delta_hat(
i,
l) * t_eps(
l,
j,
k) + t_eps(
i,
l,
k) * t_delta_hat(
l,
j);
431 t_eps(
i,
l,
m) * t_eps(
l,
j,
k) + t_eps(
i,
l,
k) * t_eps(
l,
j,
m);
437 c.diff_a *
t_kd(
k,
m) +
c.diff_diff_a * t_w_vee(
k) * t_w_vee(
m);
439 c.diff_b *
t_kd(
k,
m) +
c.diff_diff_b * t_w_vee(
k) * t_w_vee(
m);
441 c.diff_diff_a * (
t_kd(
k,
m) * wd + t_delta_w_vee(
k) * t_w_vee(
m) +
442 t_delta_w_vee(
m) * t_w_vee(
k)) +
443 c.diff_diff_diff_a * wd * t_w_vee(
k) * t_w_vee(
m);
445 c.diff_diff_b * (
t_kd(
k,
m) * wd + t_delta_w_vee(
k) * t_w_vee(
m) +
446 t_delta_w_vee(
m) * t_w_vee(
k)) +
447 c.diff_diff_diff_b * wd * t_w_vee(
k) * t_w_vee(
m);
449 c.diff_a * t_delta_w_vee(
k) +
c.diff_diff_a * wd * t_w_vee(
k);
451 c.diff_b * t_delta_w_vee(
k) +
c.diff_diff_b * wd * t_w_vee(
k);
454 t_result(
i,
j,
k,
m) =
456 t_ddda(
k,
m) * t_hat(
i,
j) + t_dda(
k,
m) * t_delta_hat(
i,
j) +
457 t_da_delta(
k) * t_eps(
i,
j,
m) + t_da_delta(
m) * t_eps(
i,
j,
k)
461 t_dddb(
k,
m) * t_hat2(
i,
j) + t_ddb(
k,
m) * t_hat_delta(
i,
j) +
462 t_db_delta(
k) * t_G(
i,
j,
m) + t_db_delta(
m) * t_G(
i,
j,
k) +
463 (
c.diff_b * wd) * t_K(
i,
j,
k,
m) +
465 (t_w_vee(
k) * t_G_delta(
i,
j,
m) + t_w_vee(
m) * t_G_delta(
i,
j,
k));
470 template <
typename T1,
typename T2>
473 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
476 const auto s = sin(theta);
477 const auto s_half = sin(theta / 2);
478 const auto a = 2 * (s_half / theta) * (s_half / theta);
479 const auto b = ((theta - s) / theta) / theta / theta;
483 template <
typename T1,
typename T2>
486 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
489 const auto s = sin(theta);
490 const auto s_half = sin(theta / 2);
491 const auto a = 2 * (s_half / theta) * (s_half / theta);
492 const auto b = ((theta - s) / theta) / theta / theta;
497 template <
typename T1,
typename T2,
typename T3,
typename T4,
typename T5>
500 const T3 diff_alpha,
const T4 beta,
const T5 diff_beta) {
509 auto t_hat =
getHat(t_w_vee);
513 alpha * FTensor::levi_civita<int>(
i,
j,
k)
517 diff_alpha * t_hat(
i,
j) * t_w_vee(
k)
521 beta * (t_hat(
i,
l) * FTensor::levi_civita<int>(
l,
j,
k) +
522 FTensor::levi_civita<int>(
i,
l,
k) * t_hat(
l,
j))
526 diff_beta * t_hat(
i,
l) * t_hat(
l,
j) * t_w_vee(
k);
531 template <
typename T1,
typename T2>
534 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
543 const auto s = sin(theta);
544 const auto c = cos(theta);
546 const auto theta2 = theta * theta;
547 const auto theta4 = theta2 * theta2;
548 const auto theta5 = theta4 * theta;
551 const auto a = (1. -
c) / theta2;
552 const auto diff_a = (theta * s + 2. *
c - 2.) / theta4;
554 const auto b = (theta - s) / (theta2 * theta);
555 const auto diff_b = (3. * s - theta *
c - 2. * theta) / theta5;
560 template <
typename T1,
typename T2>
563 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
572 const auto s = sin(theta);
573 const auto c = cos(theta);
575 const auto theta2 = theta * theta;
576 const auto theta4 = theta2 * theta2;
577 const auto theta5 = theta4 * theta;
581 const auto alpha = -(1. -
c) / theta2;
582 const auto diff_alpha = (2. - 2. *
c - theta * s) / theta4;
586 const auto beta = (theta - s) / (theta2 * theta);
587 const auto diff_beta = (3. * s - theta *
c - 2. * theta) / theta5;
592 template <
typename T1,
typename T2,
typename T3>
598 t_B(
i,
j) =
exp(t_w_vee, theta)(
i,
k) * t_A(
k,
j);
602 template <
typename T1,
typename T2,
typename T3>
608 auto t_Jl =
Jl(t_w_vee, theta);
609 t_w(
i) = t_Jl(
i,
j) * t_delta_w_vee(
j);
613 template <
typename T1,
typename T2,
typename T3>
621 template <
typename T1,
typename T2,
typename T3>
627 auto t_Jr =
Jr(t_w_vee, theta);
628 t_a(
i) = t_Jr(
i,
j) * t_delta_w_vee(
j);
632 template <
typename T1,
typename T2,
typename T3>
641 template <
typename T1,
typename T2,
typename T3>
647 auto t_R =
exp(t_w_vee, theta);
648 t_delta_R(
i,
j) = t_R(
i,
k) * t_A_hat(
k,
j);
653 template <
typename T1,
typename T2,
typename T3>
#define FTENSOR_INDEX(DIM, I)
adouble power(adouble x, int n)
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 diffDiffDiffExp(A &&t_w_vee, B &&theta, C &&t_delta_w_vee)
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 rodriguesCoefficients(const T theta)
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 diffDiffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
static auto diffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)