v0.16.3
Loading...
Searching...
No Matches
Lie.hpp
Go to the documentation of this file.
1/**
2 * @file Lie.hpp
3 * @brief Lie algebra implementation
4 * @version 0.1
5 * @date 2024-12-22
6 *
7 * @copyright Copyright (c) 2024
8 *
9 */
10
11#pragma once
12
13namespace LieGroups {
14
15template <class T> struct TensorTypeExtractorBase {
16 using Type =
17 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
18};
19
20template <class T, int I>
21struct TensorTypeExtractorBase<FTensor::PackPtr<T, I>> {
22 using Type =
23 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
24};
25
26template <class T, int G>
27struct TensorTypeExtractorBase<FTensor::CursorPtr<T, G>> {
28 using Type =
29 std::remove_cv_t<std::remove_reference_t<std::remove_pointer_t<T>>>;
30};
31
32template <class T>
34 : TensorTypeExtractorBase<std::remove_cv_t<std::remove_reference_t<T>>> {};
35
36/**
37 * @brief SO3
38 *
39 * Note that: theta == norm(t_w_vee), and t_w_hat is the skew-symmetric matrix corresponding to t_w_vee.
40 */
41struct SO3 {
42
43 SO3() = delete;
44 ~SO3() = delete;
45
46 template <typename T> inline static auto getVee(T &&w1, T &&w2, T &&w3) {
48
49 std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3)
50
51 );
52 }
53
54 template <typename T> inline static auto getHat(T &&w1, T &&w2, T &&w3) {
55 auto t_w_vee =
56 getVee(std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3));
57 return getHatImpl(t_w_vee);
58 }
59
60 template <typename A> inline static auto getVee(A &&t_w_hat) {
61 return getVeeImpl(std::forward<A>(t_w_hat));
62 }
63
64 template <typename A> inline static auto getHat(A &&t_w_vee) {
65 return getHatImpl(std::forward<A>(t_w_vee));
66 }
67
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));
71 }
72
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));
76 }
77
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));
81 }
82
83 template <typename A> inline static auto right_jacobian(A &&t_w_vee) {
84 const auto theta = t_w_vee.l2();
85 return Jr(std::forward<A>(t_w_vee), theta);
86 }
87
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));
92 }
93
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));
97 }
98
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));
102 }
103
104 template <typename A, typename B>
105 inline static auto diffExp(A &&t_w_vee, B &&theta) {
106 return diffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
107 }
108
109 template <typename A, typename B>
110 inline static auto diffDiffExp(A &&t_w_vee, B &&theta) {
111 return diffDiffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
112 }
113
114 /** Third derivative of exp contracted with a direction,
115 * d^3 R_ij / d w_k d w_m d w_n delta_w_n. */
116 template <typename A, typename B, typename C>
117 inline static auto diffDiffDiffExp(A &&t_w_vee, B &&theta,
118 C &&t_delta_w_vee) {
119 return diffDiffDiffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta),
120 std::forward<C>(t_delta_w_vee));
121 }
122
123 // w = Jl(omega) * delta_omega (spatial infinitesimal rotation vector)
124 template <typename T1, typename T2, typename T3>
125 inline static auto spatialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
126 return spatialSpinImpl(std::forward<T1>(t_w_vee), theta,
127 std::forward<T3>(t_delta_w_vee));
128 }
129
130 // W = hat( Jl(omega) * delta_omega ) = deltaR * R^T
131 template <typename T1, typename T2, typename T3>
132 inline static auto spatialSpinHat(T1 &&t_w_vee, T2 theta,
133 T3 &&t_delta_w_vee) {
134 return spatialSpinHatImpl(std::forward<T1>(t_w_vee), theta,
135 std::forward<T3>(t_delta_w_vee));
136 }
137
138 // a = Jr(omega) * delta_omega (material/body infinitesimal rotation vector)
139 template <typename T1, typename T2, typename T3>
140 inline static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
141 return materialSpinImpl(std::forward<T1>(t_w_vee), theta,
142 std::forward<T3>(t_delta_w_vee));
143 }
144
145 // A = hat( Jr(omega) * delta_omega ) = R^T * deltaR
146 template <typename T1, typename T2, typename T3>
147 inline static auto materialSpinHat(T1 &&t_w_vee, T2 theta,
148 T3 &&t_delta_w_vee) {
149 return materialSpinHatImpl(std::forward<T1>(t_w_vee), theta,
150 std::forward<T3>(t_delta_w_vee));
151 }
152
153 // Intrinsic continuum variation: deltaR = R * A, with A in so(3)
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));
158 }
159
160
161private:
162 inline static constexpr int dim = 3;
163 inline static FTENSOR_INDEX(dim, i);
164 inline static FTENSOR_INDEX(dim, j);
165 inline static FTENSOR_INDEX(dim, k);
166 inline static FTENSOR_INDEX(dim, l);
167 inline static FTENSOR_INDEX(dim, m);
168 inline static FTENSOR_INDEX(dim, n);
169
170 template <typename T>
171 inline static auto getVeeImpl(const FTensor::Tensor2<T, dim, dim> &t_w_hat) {
172 using D = typename TensorTypeExtractor<T>::Type;
174 t_w_vee(k) = (levi_civita(i, j, k) * t_w_hat(i, j)) / 2;
175 return t_w_vee;
176 }
177
178 template <typename T>
179 inline static auto getHatImpl(const FTensor::Tensor1<T, dim> &t_w_vee) {
180 using D = typename TensorTypeExtractor<T>::Type;
182 t_w_hat(i, j) = levi_civita(i, j, k) * t_w_vee(k);
183 return t_w_hat;
184 }
185
186 template <typename T1, typename T2, typename T3>
187 inline static auto genericFormImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
188 const T2 alpha, const T3 beta) {
189 using D = typename TensorTypeExtractor<T1>::Type;
191 auto t_hat = getHat(t_w_vee);
192 t_X(i, j) = FTensor::Kronecker_Delta<int>()(i, j) + alpha * t_hat(i, j) +
193 beta * (t_hat(i, k) * t_hat(k, j));
194 return t_X;
195 }
196
197 template <typename T1, typename T2>
198 inline static auto expImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
199 const T2 theta) {
200 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
201 return genericFormImpl(t_w_vee, 1, 0.5);
202 }
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);
207 return genericFormImpl(t_w_vee, a, b);
208 }
209
210 /**
211 * Rodrigues coefficients a = sin(t)/t, b = (1 - cos t)/t^2 and the
212 * derivatives that appear in the derivatives of exp. With x = t^2 = w.w the
213 * chain rule gives d a/d w_k = diff_a w_k, d^2 a/d w_k d w_m = diff_a d_km
214 * + diff_diff_a w_k w_m and d^3 a/d w_k d w_m d w_n = diff_diff_a (d_km w_n
215 * + d_kn w_m + d_mn w_k) + diff_diff_diff_a w_k w_m w_n, i.e. diff_a =
216 * 2 da/dx, diff_diff_a = 4 d2a/dx2, diff_diff_diff_a = 8 d3a/dx3, and the
217 * same for b. For t < 1 the series in x is used: the closed forms cancel
218 * catastrophically there (the second derivative loses about eps/t^5, the
219 * third about eps/t^7).
220 */
225
226 template <typename T>
227 inline static auto rodriguesCoefficients(const T theta) {
229 if (theta < 1.) {
230 // a = sum (-x)^n/(2n+1)!, b = sum (-x)^n/(2n+2)!; the m-th x-derivative
231 // carries n!/(n-m)! x^(n-m) and the factor 2^m.
232 const T x = theta * theta;
233 constexpr int terms = 14;
234 T power[terms];
235 power[0] = 1.;
236 for (int n = 1; n != terms; ++n)
237 power[n] = power[n - 1] * x;
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)
241 *a[m] = *b[m] = 0.;
242 double factorial_odd = 1., factorial_even = 2., sign = 1.;
243 for (int n = 0; n != terms; ++n) {
244 if (n) {
245 factorial_odd *= (2 * n) * (2 * n + 1);
246 factorial_even *= (2 * n + 1) * (2 * n + 2);
247 sign = -sign;
248 }
249 double falling = 1., scale = 1.;
250 for (int m = 0; m <= std::min(n, 3); ++m) {
251 *a[m] += (sign * scale * falling / factorial_odd) * power[n - m];
252 *b[m] += (sign * scale * falling / factorial_even) * power[n - m];
253 falling *= (n - m);
254 scale *= 2.;
255 }
256 }
257 return c;
258 }
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;
264 c.a = s / theta;
265 c.diff_a = (theta * cc - s) / t3;
266 c.diff_diff_a = (3. * s - 3. * theta * cc - t2 * s) / t5;
267 c.diff_diff_diff_a =
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;
272 c.diff_diff_diff_b =
273 (-t3 * s - 9. * t2 * cc + 33. * theta * s + 48. * cc - 48.) / t8;
274 return c;
275 }
276
277 template <typename T1, typename T2>
278 inline static auto diffExpImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
279 const T2 theta) {
280
281 auto get_tensor = [&t_w_vee](auto a, auto diff_a, auto b, auto diff_b) {
282 FTENSOR_INDEX(3, i);
283 FTENSOR_INDEX(3, j);
284 FTENSOR_INDEX(3, k);
285 FTENSOR_INDEX(3, l);
286
287 using D = typename TensorTypeExtractor<T1>::Type;
289 auto t_hat = getHat(t_w_vee);
290 t_diff_exp(i, j, k) =
291
292 a * FTensor::levi_civita<int>(i, j, k)
293
294 +
295
296 diff_a * t_hat(i, j) * t_w_vee(k)
297
298 +
299
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))
302
303 +
304
305 diff_b * t_hat(i, l) * t_hat(l, j) * t_w_vee(k);
306
307 return t_diff_exp;
308 };
309
310 const auto c = rodriguesCoefficients(theta);
311 return get_tensor(c.a, c.diff_a, c.b, c.diff_b);
312 }
313
314 template <typename T1, typename T2>
315 inline static auto diffDiffExpImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
316 const T2 theta) {
317
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) {
320 FTENSOR_INDEX(3, i);
321 FTENSOR_INDEX(3, j);
322 FTENSOR_INDEX(3, k);
323 FTENSOR_INDEX(3, l);
324 FTENSOR_INDEX(3, m);
325
326 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
327
328 using D = typename TensorTypeExtractor<T1>::Type;
329 FTensor::Tensor4<D, 3, 3, 3, 3> t_diff_diff_exp;
330
331 auto t_hat = getHat(t_w_vee);
332 t_diff_diff_exp(i, j, k, m) =
333
334 diff_a * FTensor::levi_civita<int>(i, j, k) * t_w_vee(m)
335
336 +
337
338 diff_a * (
339
340 t_hat(i, j) * t_kd(k, m) +
341 FTensor::levi_civita<int>(i, j, m) * t_w_vee(k)
342
343 )
344
345 +
346
347 diff_diff_a * t_hat(i, j) * t_w_vee(k) * t_w_vee(m)
348
349 +
350
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))
355
356 +
357
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)) *
360 t_w_vee(m))
361
362 +
363
364 diff_b *
365 (
366
367 t_hat(i, l) * t_hat(l, j) * t_kd(k, m)
368
369 +
370
371 FTensor::levi_civita<int>(i, l, m) * t_hat(l, j) * t_w_vee(k)
372
373 +
374
375 t_hat(i, l) * FTensor::levi_civita<int>(l, j, m) * t_w_vee(k)
376
377 )
378
379 +
380
381 diff_diff_b * t_hat(i, l) * t_hat(l, j) * t_w_vee(k) * t_w_vee(m);
382
383 return t_diff_diff_exp;
384 };
385
386 const auto c = rodriguesCoefficients(theta);
387 return get_tensor(c.a, c.diff_a, c.diff_diff_a, c.b, c.diff_b,
388 c.diff_diff_b);
389 }
390
391 /**
392 * d^3 R_ij / d w_k d w_m d w_n delta_n with R = I + a hat + b hat^2,
393 * G_ijk = d(hat^2)_ij/d w_k = hat_il e_ljk + e_ilk hat_lj and
394 * K_ijkm = d^2(hat^2)_ij/d w_k d w_m = e_ilm e_ljk + e_ilk e_ljm; the third
395 * derivative of hat^2 vanishes. The derivative slots are distributed over
396 * the coefficient and the tensor factor and the last slot is contracted
397 * with delta.
398 */
399 template <typename T1, typename T2, typename T3>
400 inline static auto
401 diffDiffDiffExpImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
402 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
403 FTENSOR_INDEX(3, i);
404 FTENSOR_INDEX(3, j);
405 FTENSOR_INDEX(3, k);
406 FTENSOR_INDEX(3, l);
407 FTENSOR_INDEX(3, m);
408 FTENSOR_INDEX(3, n);
409
410 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
412
413 using D = typename TensorTypeExtractor<T1>::Type;
414 const auto c = rodriguesCoefficients(theta);
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);
418
419 FTensor::Tensor2<D, dim, dim> t_hat2, t_hat_delta;
420 t_hat2(i, j) = t_hat(i, l) * t_hat(l, j);
421 // d(hat^2)_ij/d w_n delta_n
422 t_hat_delta(i, j) =
423 t_hat(i, l) * t_delta_hat(l, j) + t_delta_hat(i, l) * t_hat(l, j);
424 // G_ijk and K_ijkn delta_n
426 t_G(i, j, k) = t_hat(i, l) * t_eps(l, j, k) + t_eps(i, l, k) * t_hat(l, j);
427 t_G_delta(i, j, k) =
428 t_delta_hat(i, l) * t_eps(l, j, k) + t_eps(i, l, k) * t_delta_hat(l, j);
430 t_K(i, j, k, m) =
431 t_eps(i, l, m) * t_eps(l, j, k) + t_eps(i, l, k) * t_eps(l, j, m);
432
433 // coefficient derivatives with the last slot contracted with delta
434 FTensor::Tensor2<D, dim, dim> t_dda, t_ddb, t_ddda, t_dddb;
435 FTensor::Tensor1<D, dim> t_da_delta, t_db_delta;
436 t_dda(k, m) =
437 c.diff_a * t_kd(k, m) + c.diff_diff_a * t_w_vee(k) * t_w_vee(m);
438 t_ddb(k, m) =
439 c.diff_b * t_kd(k, m) + c.diff_diff_b * t_w_vee(k) * t_w_vee(m);
440 t_ddda(k, 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);
444 t_dddb(k, 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);
448 t_da_delta(k) =
449 c.diff_a * t_delta_w_vee(k) + c.diff_diff_a * wd * t_w_vee(k);
450 t_db_delta(k) =
451 c.diff_b * t_delta_w_vee(k) + c.diff_diff_b * wd * t_w_vee(k);
452
454 t_result(i, j, k, m) =
455
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)
458
459 +
460
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) +
464 c.diff_b *
465 (t_w_vee(k) * t_G_delta(i, j, m) + t_w_vee(m) * t_G_delta(i, j, k));
466
467 return t_result;
468 }
469
470 template <typename T1, typename T2>
471 inline static auto JlImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
472 const T2 &theta) {
473 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
474 return genericFormImpl(t_w_vee, 0.5, 1. / 6.);
475 }
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;
480 return genericFormImpl(t_w_vee, a, b);
481 }
482
483 template <typename T1, typename T2>
484 inline static auto JrImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
485 const T2 theta) {
486 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
487 return genericFormImpl(t_w_vee, -0.5, 1. / 6.);
488 }
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;
493 return genericFormImpl(t_w_vee, -a, b);
494 }
495
496 // private helper
497 template <typename T1, typename T2, typename T3, typename T4, typename T5>
498 inline static auto
499 genericDiffFormImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 alpha,
500 const T3 diff_alpha, const T4 beta, const T5 diff_beta) {
501 FTENSOR_INDEX(3, i);
502 FTENSOR_INDEX(3, j);
503 FTENSOR_INDEX(3, k);
504 FTENSOR_INDEX(3, l);
505
506 using D = typename TensorTypeExtractor<T1>::Type;
508
509 auto t_hat = getHat(t_w_vee);
510
511 t_diff_X(i, j, k) =
512
513 alpha * FTensor::levi_civita<int>(i, j, k)
514
515 +
516
517 diff_alpha * t_hat(i, j) * t_w_vee(k)
518
519 +
520
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))
523
524 +
525
526 diff_beta * t_hat(i, l) * t_hat(l, j) * t_w_vee(k);
527
528 return t_diff_X;
529 }
530
531 template <typename T1, typename T2>
532 inline static auto diffJlImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
533 const T2 theta) {
534 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
535 // Taylor:
536 // a = 1/2 - theta^2/24 + ...
537 // diff_a = -1/12 + theta^2/180 + ...
538 // b = 1/6 - theta^2/120 + ...
539 // diff_b = -1/60 + theta^2/1260 + ...
540 return genericDiffFormImpl(t_w_vee, 0.5, -1. / 12., 1. / 6., -1. / 60.);
541 }
542
543 const auto s = sin(theta);
544 const auto c = cos(theta);
545
546 const auto theta2 = theta * theta;
547 const auto theta4 = theta2 * theta2;
548 const auto theta5 = theta4 * theta;
549
550 // Jl = I + a * hat + b * hat^2
551 const auto a = (1. - c) / theta2;
552 const auto diff_a = (theta * s + 2. * c - 2.) / theta4;
553
554 const auto b = (theta - s) / (theta2 * theta);
555 const auto diff_b = (3. * s - theta * c - 2. * theta) / theta5;
556
557 return genericDiffFormImpl(t_w_vee, a, diff_a, b, diff_b);
558 }
559
560 template <typename T1, typename T2>
561 inline static auto diffJrImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
562 const T2 theta) {
563 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
564 // Taylor:
565 // alpha = -1/2 + theta^2/24 + ...
566 // diff_alpha = 1/12 - theta^2/180 + ...
567 // beta = 1/6 - theta^2/120 + ...
568 // diff_beta = -1/60 + theta^2/1260 + ...
569 return genericDiffFormImpl(t_w_vee, -0.5, 1. / 12., 1. / 6., -1. / 60.);
570 }
571
572 const auto s = sin(theta);
573 const auto c = cos(theta);
574
575 const auto theta2 = theta * theta;
576 const auto theta4 = theta2 * theta2;
577 const auto theta5 = theta4 * theta;
578
579 // Jr = I + alpha * hat + beta * hat^2
580 // with alpha = -(1 - cos(theta)) / theta^2
581 const auto alpha = -(1. - c) / theta2;
582 const auto diff_alpha = (2. - 2. * c - theta * s) / theta4;
583 // equivalent:
584 // const auto diff_alpha = -(theta * s + 2. * c - 2.) / theta4;
585
586 const auto beta = (theta - s) / (theta2 * theta);
587 const auto diff_beta = (3. * s - theta * c - 2. * theta) / theta5;
588
589 return genericDiffFormImpl(t_w_vee, alpha, diff_alpha, beta, diff_beta);
590 }
591
592 template <typename T1, typename T2, typename T3>
593 inline static auto
594 actionImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
596 using D = typename TensorTypeExtractor<T3>::Type;
598 t_B(i, j) = exp(t_w_vee, theta)(i, k) * t_A(k, j);
599 return t_B;
600 }
601
602 template <typename T1, typename T2, typename T3>
603 inline static auto
604 spatialSpinImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
605 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
606 using D = typename TensorTypeExtractor<T1>::Type;
608 auto t_Jl = Jl(t_w_vee, theta);
609 t_w(i) = t_Jl(i, j) * t_delta_w_vee(j);
610 return t_w;
611 }
612
613 template <typename T1, typename T2, typename T3>
614 inline static auto
615 spatialSpinHatImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
616 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
617 auto t_w = spatialSpinImpl(t_w_vee, theta, t_delta_w_vee);
618 return getHat(t_w);
619 }
620
621 template <typename T1, typename T2, typename T3>
622 inline static auto
623 materialSpinImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
624 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
625 using D = typename TensorTypeExtractor<T1>::Type;
627 auto t_Jr = Jr(t_w_vee, theta);
628 t_a(i) = t_Jr(i, j) * t_delta_w_vee(j);
629 return t_a;
630 }
631
632 template <typename T1, typename T2, typename T3>
633 inline static auto
634 materialSpinHatImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
635 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
636 auto t_a = materialSpinImpl(t_w_vee, theta, t_delta_w_vee);
637 return getHat(t_a);
638 }
639
640 // deltaR = R * A
641 template <typename T1, typename T2, typename T3>
642 inline static auto deltaRImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
643 const T2 theta,
644 const FTensor::Tensor2<T3, dim, dim> &t_A_hat) {
645 using D = typename TensorTypeExtractor<T1>::Type;
647 auto t_R = exp(t_w_vee, theta);
648 t_delta_R(i, j) = t_R(i, k) * t_A_hat(k, j);
649 return t_delta_R;
650 }
651
652 // deltaR = R * hat( Jr(omega) * delta_omega )
653 template <typename T1, typename T2, typename T3>
654 inline static auto
656 const T2 theta,
657 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
658 auto t_A_hat = materialSpinHatImpl(t_w_vee, theta, t_delta_w_vee);
659 return deltaRImpl(t_w_vee, theta, t_A_hat);
660 }
661
662}; // namespace SO3
663
664}; // namespace LieGroups
SmartPetscObj< Mat > C
#define FTENSOR_INDEX(DIM, I)
adouble power(adouble x, int n)
constexpr double a
Kronecker Delta class.
Levi_Civita Classes.
constexpr auto t_kd
FTensor::Index< 'i', SPACE_DIM > i
const double c
speed of light (cm/ns)
double D
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.
Definition FTensor.hpp:51
constexpr AssemblyType A
double scale
Definition plastic.cpp:124
FTensor::Index< 'm', 3 > m
static auto diffDiffDiffExp(A &&t_w_vee, B &&theta, C &&t_delta_w_vee)
Definition Lie.hpp:117
static auto diffDiffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:110
static auto spatialSpinHatImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
Definition Lie.hpp:615
static auto Jr(A &&t_w_vee, B &&theta)
Definition Lie.hpp:79
static constexpr int dim
Definition Lie.hpp:162
static auto diffJlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:532
static auto genericFormImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 alpha, const T3 beta)
Definition Lie.hpp:187
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)
Definition Lie.hpp:499
static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat)
Definition Lie.hpp:155
static auto Jl(A &&t_w_vee, B &&theta)
Definition Lie.hpp:74
static auto action(A &&t_w_vee, B &&theta, C &&t_A)
Definition Lie.hpp:89
static auto actionImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor2_symmetric< T3, dim > &t_A)
Definition Lie.hpp:594
static FTENSOR_INDEX(dim, l)
static FTENSOR_INDEX(dim, k)
static auto getVee(A &&t_w_hat)
Definition Lie.hpp:60
static auto getHatImpl(const FTensor::Tensor1< T, dim > &t_w_vee)
Definition Lie.hpp:179
static auto JlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 &theta)
Definition Lie.hpp:471
static auto getHat(T &&w1, T &&w2, T &&w3)
Definition Lie.hpp:54
static auto rodriguesCoefficients(const T theta)
Definition Lie.hpp:227
static auto deltaRImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
Definition Lie.hpp:655
static auto deltaRImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor2< T3, dim, dim > &t_A_hat)
Definition Lie.hpp:642
static auto JrImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:484
static auto diffJr(A &&t_w_vee, B &&theta)
Definition Lie.hpp:100
static auto right_jacobian(A &&t_w_vee)
Definition Lie.hpp:83
static FTENSOR_INDEX(dim, j)
static auto expImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:198
static auto diffJl(A &&t_w_vee, B &&theta)
Definition Lie.hpp:95
static auto getVeeImpl(const FTensor::Tensor2< T, dim, dim > &t_w_hat)
Definition Lie.hpp:171
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:105
static auto spatialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:125
static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:140
static auto spatialSpinHat(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:132
static auto materialSpinHatImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
Definition Lie.hpp:634
static auto diffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:278
static auto diffJrImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:561
static auto materialSpinHat(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:147
static auto spatialSpinImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
Definition Lie.hpp:604
static auto getHat(A &&t_w_vee)
Definition Lie.hpp:64
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)
Definition Lie.hpp:623
static auto getVee(T &&w1, T &&w2, T &&w3)
Definition Lie.hpp:46
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:69
static auto diffDiffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta, const FTensor::Tensor1< T3, dim > &t_delta_w_vee)
Definition Lie.hpp:401
static auto diffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:315
std::remove_cv_t< std::remove_reference_t< std::remove_pointer_t< T > > > Type
Definition Lie.hpp:29
std::remove_cv_t< std::remove_reference_t< std::remove_pointer_t< T > > > Type
Definition Lie.hpp:23
std::remove_cv_t< std::remove_reference_t< std::remove_pointer_t< T > > > Type
Definition Lie.hpp:17