v0.15.5
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>
28 : TensorTypeExtractorBase<std::remove_cv_t<std::remove_reference_t<T>>> {};
29
30/**
31 * @brief SO3
32 *
33 * Note that: theta == norm(t_w_vee), and t_w_hat is the skew-symmetric matrix corresponding to t_w_vee.
34 */
35struct SO3 {
36
37 SO3() = delete;
38 ~SO3() = delete;
39
40 template <typename T> inline static auto getVee(T &&w1, T &&w2, T &&w3) {
42
43 std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3)
44
45 );
46 }
47
48 template <typename T> inline static auto getHat(T &&w1, T &&w2, T &&w3) {
49 auto t_w_vee =
50 getVee(std::forward<T>(w1), std::forward<T>(w2), std::forward<T>(w3));
51 return getHatImpl(t_w_vee);
52 }
53
54 template <typename A> inline static auto getVee(A &&t_w_hat) {
55 return getVeeImpl(std::forward<A>(t_w_hat));
56 }
57
58 template <typename A> inline static auto getHat(A &&t_w_vee) {
59 return getHatImpl(std::forward<A>(t_w_vee));
60 }
61
62 template <typename A, typename B>
63 inline static auto exp(A &&t_w_vee, B &&theta) {
64 return expImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
65 }
66
67 template <typename A, typename B>
68 inline static auto Jl(A &&t_w_vee, B &&theta) {
69 return JlImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
70 }
71
72 template <typename A, typename B>
73 inline static auto Jr(A &&t_w_vee, B &&theta) {
74 return JrImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
75 }
76
77 template <typename A, typename B, typename C>
78 inline static auto action(A &&t_w_vee, B &&theta, C &&t_A) {
79 return actionImpl(std::forward<A>(t_w_vee), std::forward<B>(theta),
80 std::forward<C>(t_A));
81 }
82
83 template <typename A, typename B>
84 inline static auto dActionJl(A &&t_w_vee, B &&t_A) {
85 return dActionJlImpl(std::forward<A>(t_w_vee), std::forward<B>(t_A));
86 }
87
88 template <typename A, typename B>
89 inline static auto dActionJr(A &&t_w_vee, B &&t_A) {
90 return dActionJrImpl(std::forward<A>(t_w_vee), std::forward<B>(t_A));
91 }
92
93 template <typename A, typename B>
94 inline static auto diffJl(A &&t_w_vee, B &&theta) {
95 return diffJlImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
96 }
97
98 template <typename A, typename B>
99 inline static auto diffJr(A &&t_w_vee, B &&theta) {
100 return diffJrImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
101 }
102
103 template <typename A, typename B>
104 inline static auto diffExp(A &&t_w_vee, B &&theta) {
105 return diffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
106 }
107
108 template <typename A, typename B>
109 inline static auto diffDiffExp(A &&t_w_vee, B &&theta) {
110 return diffDiffExpImpl(std::forward<A>(t_w_vee), std::forward<B>(theta));
111 }
112
113 // a = Jr(omega) * delta_omega (material/body infinitesimal rotation vector)
114 template <typename T1, typename T2, typename T3>
115 inline static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee) {
116 return materialSpinImpl(std::forward<T1>(t_w_vee), theta,
117 std::forward<T3>(t_delta_w_vee));
118 }
119
120 // A = hat( Jr(omega) * delta_omega ) = R^T * deltaR
121 template <typename T1, typename T2, typename T3>
122 inline static auto materialSpinHat(T1 &&t_w_vee, T2 theta,
123 T3 &&t_delta_w_vee) {
124 return materialSpinHatImpl(std::forward<T1>(t_w_vee), theta,
125 std::forward<T3>(t_delta_w_vee));
126 }
127
128 // Intrinsic continuum variation: deltaR = R * A, with A in so(3)
129 template <typename T1, typename T2, typename T3>
130 inline static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat) {
131 return deltaRImpl(std::forward<T1>(t_w_vee), theta,
132 std::forward<T3>(t_A_hat));
133 }
134
135
136private:
137 inline static constexpr int dim = 3;
138 inline static FTENSOR_INDEX(dim, i);
139 inline static FTENSOR_INDEX(dim, j);
140 inline static FTENSOR_INDEX(dim, k);
141 inline static FTENSOR_INDEX(dim, l);
142 inline static FTENSOR_INDEX(dim, m);
143 inline static FTENSOR_INDEX(dim, n);
144
145 template <typename T>
146 inline static auto getVeeImpl(const FTensor::Tensor2<T, dim, dim> &t_w_hat) {
147 using D = typename TensorTypeExtractor<T>::Type;
149 t_w_vee(k) = (levi_civita(i, j, k) * t_w_hat(i, j)) / 2;
150 return t_w_vee;
151 }
152
153 template <typename T>
154 inline static auto getHatImpl(const FTensor::Tensor1<T, dim> &t_w_vee) {
155 using D = typename TensorTypeExtractor<T>::Type;
157 t_w_hat(i, j) = levi_civita(i, j, k) * t_w_vee(k);
158 return t_w_hat;
159 }
160
161 template <typename T1, typename T2, typename T3>
162 inline static auto genericFormImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
163 const T2 alpha, const T3 beta) {
164 using D = typename TensorTypeExtractor<T1>::Type;
166 auto t_hat = getHat(t_w_vee);
167 t_X(i, j) = FTensor::Kronecker_Delta<int>()(i, j) + alpha * t_hat(i, j) +
168 beta * (t_hat(i, k) * t_hat(k, j));
169 return t_X;
170 }
171
172 template <typename T1, typename T2>
173 inline static auto expImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
174 const T2 theta) {
175 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
176 return genericFormImpl(t_w_vee, 1, 0.5);
177 }
178 const auto s = sin(theta);
179 const auto s_half = sin(theta / 2);
180 const auto a = s / theta;
181 const auto b = 2 * (s_half / theta) * (s_half / theta);
182 return genericFormImpl(t_w_vee, a, b);
183 }
184
185 template <typename T1, typename T2>
186 inline static auto diffExpImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
187 const T2 theta) {
188
189 auto get_tensor = [&t_w_vee](auto a, auto diff_a, auto b, auto diff_b) {
190 FTENSOR_INDEX(3, i);
191 FTENSOR_INDEX(3, j);
192 FTENSOR_INDEX(3, k);
193 FTENSOR_INDEX(3, l);
194
195 using D = typename TensorTypeExtractor<T1>::Type;
197 auto t_hat = getHat(t_w_vee);
198 t_diff_exp(i, j, k) =
199
200 a * FTensor::levi_civita<int>(i, j, k)
201
202 +
203
204 diff_a * t_hat(i, j) * t_w_vee(k)
205
206 +
207
208 b * (t_hat(i, l) * FTensor::levi_civita<int>(l, j, k) +
209 FTensor::levi_civita<int>(i, l, k) * t_hat(l, j))
210
211 +
212
213 diff_b * t_hat(i, l) * t_hat(l, j) * t_w_vee(k);
214
215 return t_diff_exp;
216 };
217
218 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
219 return get_tensor(1., -1. / 3., 1. / 2., -1. / 12);
220 }
221
222 const auto ss = sin(theta);
223 const auto a = ss / theta;
224
225 const auto theta2 = theta * theta;
226 const auto cc = cos(theta);
227 const auto diff_a = (theta * cc - ss) / (theta2 * theta);
228
229 const auto ss_2 = sin(theta / 2.);
230 // const auto cc_2 = cos(theta / 2.);
231 const auto b = 2. * ss_2 * ss_2 / theta2;
232 const auto diff_b = (-2 + 2 * cc + theta * ss) / (theta2 * theta2);
233
234 return get_tensor(a, diff_a, b, diff_b);
235 }
236
237 template <typename T1, typename T2>
238 inline static auto diffDiffExpImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
239 const T2 theta) {
240
241 auto get_tensor = [&t_w_vee](auto a, auto diff_a, auto diff_diff_a, auto b,
242 auto diff_b, auto diff_diff_b) {
243 FTENSOR_INDEX(3, i);
244 FTENSOR_INDEX(3, j);
245 FTENSOR_INDEX(3, k);
246 FTENSOR_INDEX(3, l);
247 FTENSOR_INDEX(3, m);
248
249 constexpr auto t_kd = FTensor::Kronecker_Delta<double>();
250
251 using D = typename TensorTypeExtractor<T1>::Type;
252 FTensor::Tensor4<D, 3, 3, 3, 3> t_diff_diff_exp;
253
254 auto t_hat = getHat(t_w_vee);
255 t_diff_diff_exp(i, j, k, m) =
256
257 diff_a * FTensor::levi_civita<int>(i, j, k) * t_w_vee(m)
258
259 +
260
261 diff_a * (
262
263 t_hat(i, j) * t_kd(k, m) +
264 FTensor::levi_civita<int>(i, j, m) * t_w_vee(k)
265
266 )
267
268 +
269
270 diff_diff_a * t_hat(i, j) * t_w_vee(k) * t_w_vee(m)
271
272 +
273
274 b * (FTensor::levi_civita<int>(i, l, m) *
275 FTensor::levi_civita<int>(l, j, k) +
276 FTensor::levi_civita<int>(i, l, k) *
277 FTensor::levi_civita<int>(l, j, m))
278
279 +
280
281 diff_b * ((t_hat(i, l) * FTensor::levi_civita<int>(l, j, k) +
282 FTensor::levi_civita<int>(i, l, k) * t_hat(l, j)) *
283 t_w_vee(m))
284
285 +
286
287 diff_b *
288 (
289
290 t_hat(i, l) * t_hat(l, j) * t_kd(k, m)
291
292 +
293
294 FTensor::levi_civita<int>(i, l, m) * t_hat(l, j) * t_w_vee(k)
295
296 +
297
298 t_hat(i, l) * FTensor::levi_civita<int>(l, j, m) * t_w_vee(k)
299
300 )
301
302 +
303
304 diff_diff_b * t_hat(i, l) * t_hat(l, j) * t_w_vee(k) * t_w_vee(m);
305
306 return t_diff_diff_exp;
307 };
308
309 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
310 return get_tensor(1., -1. / 3., 1. / 15, 1. / 2, -1. / 12, 1. / 90);
311 }
312
313 const auto ss = sin(theta);
314 const auto a = ss / theta;
315
316 const auto theta2 = theta * theta;
317 const auto cc = cos(theta);
318 const auto diff_a = (theta * cc - ss) / (theta2 * theta);
319 const auto diff_diff_a =
320 (3. * ss - 3. * theta * cc - theta2 * ss) / (theta2 * theta2 * theta);
321
322 const auto ss_2 = sin(theta / 2.);
323 const auto cc_2 = cos(theta / 2.);
324 const auto b = 2. * ss_2 * ss_2 / theta2;
325 const auto diff_b = (-2 + 2 * cc + theta * ss) / (theta2 * theta2);
326 const auto diff_diff_b = (theta2 * cc - 5. * theta * ss - 8. * cc + 8.) /
327 (theta2 * theta2 * theta2);
328
329 return get_tensor(a, diff_a, diff_diff_a, b, diff_b, diff_diff_b);
330 }
331
332 template <typename T1, typename T2>
333 inline static auto JlImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
334 const T2 &theta) {
335 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
336 return genericFormImpl(t_w_vee, 0.5, 1. / 6.);
337 }
338 const auto s = sin(theta);
339 const auto s_half = sin(theta / 2);
340 const auto a = 2 * (s_half / theta) * (s_half / theta);
341 const auto b = ((theta - s) / theta) / theta / theta;
342 return genericFormImpl(t_w_vee, a, b);
343 }
344
345 template <typename T1, typename T2>
346 inline static auto JrImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
347 const T2 theta) {
348 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
349 return genericFormImpl(t_w_vee, -0.5, 1. / 6.);
350 }
351 const auto s = sin(theta);
352 const auto s_half = sin(theta / 2);
353 const auto a = 2 * (s_half / theta) * (s_half / theta);
354 const auto b = ((theta - s) / theta) / theta / theta;
355 return genericFormImpl(t_w_vee, -a, b);
356 }
357
358 // private helper
359 template <typename T1, typename T2, typename T3, typename T4, typename T5>
360 inline static auto
361 genericDiffFormImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 alpha,
362 const T3 diff_alpha, const T4 beta, const T5 diff_beta) {
363 FTENSOR_INDEX(3, i);
364 FTENSOR_INDEX(3, j);
365 FTENSOR_INDEX(3, k);
366 FTENSOR_INDEX(3, l);
367
368 using D = typename TensorTypeExtractor<T1>::Type;
370
371 auto t_hat = getHat(t_w_vee);
372
373 t_diff_X(i, j, k) =
374
375 alpha * FTensor::levi_civita<int>(i, j, k)
376
377 +
378
379 diff_alpha * t_hat(i, j) * t_w_vee(k)
380
381 +
382
383 beta * (t_hat(i, l) * FTensor::levi_civita<int>(l, j, k) +
384 FTensor::levi_civita<int>(i, l, k) * t_hat(l, j))
385
386 +
387
388 diff_beta * t_hat(i, l) * t_hat(l, j) * t_w_vee(k);
389
390 return t_diff_X;
391 }
392
393 template <typename T1, typename T2>
394 inline static auto diffJlImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
395 const T2 theta) {
396 if (fabs(theta) < std::numeric_limits<T2>::epsilon()) {
397 // Taylor:
398 // a = 1/2 - theta^2/24 + ...
399 // diff_a = -1/12 + theta^2/180 + ...
400 // b = 1/6 - theta^2/120 + ...
401 // diff_b = -1/60 + theta^2/1260 + ...
402 return genericDiffFormImpl(t_w_vee, 0.5, -1. / 12., 1. / 6., -1. / 60.);
403 }
404
405 const auto s = sin(theta);
406 const auto c = cos(theta);
407
408 const auto theta2 = theta * theta;
409 const auto theta4 = theta2 * theta2;
410 const auto theta5 = theta4 * theta;
411
412 // Jl = I + a * hat + b * hat^2
413 const auto a = (1. - c) / theta2;
414 const auto diff_a = (theta * s + 2. * c - 2.) / theta4;
415
416 const auto b = (theta - s) / (theta2 * theta);
417 const auto diff_b = (3. * s - theta * c - 2. * theta) / theta5;
418
419 return genericDiffFormImpl(t_w_vee, a, diff_a, b, diff_b);
420 }
421
422 template <typename T1, typename T2, typename T3>
423 inline static auto
424 actionImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
426 using D = typename TensorTypeExtractor<T3>::Type;
428 t_B(i, j) = exp(t_w_vee, theta)(i, k) * t_A(k, j);
429 return t_B;
430 }
431
432 template <typename T1, typename T2, typename T3>
433 inline static auto
434 materialSpinImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
435 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
436 using D = typename TensorTypeExtractor<T1>::Type;
438 auto t_Jr = Jr(t_w_vee, theta);
439 t_a(i) = t_Jr(i, j) * t_delta_w_vee(j);
440 return t_a;
441 }
442
443 template <typename T1, typename T2, typename T3>
444 inline static auto
445 materialSpinHatImpl(const FTensor::Tensor1<T1, dim> &t_w_vee, const T2 theta,
446 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
447 auto t_a = materialSpinImpl(t_w_vee, theta, t_delta_w_vee);
448 return getHat(t_a);
449 }
450
451 // deltaR = R * A
452 template <typename T1, typename T2, typename T3>
453 inline static auto deltaRImpl(const FTensor::Tensor1<T1, dim> &t_w_vee,
454 const T2 theta,
455 const FTensor::Tensor2<T3, dim, dim> &t_A_hat) {
456 using D = typename TensorTypeExtractor<T1>::Type;
458 auto t_R = exp(t_w_vee, theta);
459 t_delta_R(i, j) = t_R(i, k) * t_A_hat(k, j);
460 return t_delta_R;
461 }
462
463 // deltaR = R * hat( Jr(omega) * delta_omega )
464 template <typename T1, typename T2, typename T3>
465 inline static auto
467 const T2 theta,
468 const FTensor::Tensor1<T3, dim> &t_delta_w_vee) {
469 auto t_A_hat = materialSpinHatImpl(t_w_vee, theta, t_delta_w_vee);
470 return deltaRImpl(t_w_vee, theta, t_A_hat);
471 }
472
473}; // namespace SO3
474
475}; // namespace LieGroups
#define FTENSOR_INDEX(DIM, I)
constexpr double a
Kronecker Delta class.
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
FTensor::Index< 'm', 3 > m
static auto diffDiffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:109
static auto dActionJr(A &&t_w_vee, B &&t_A)
Definition Lie.hpp:89
static auto Jr(A &&t_w_vee, B &&theta)
Definition Lie.hpp:73
static constexpr int dim
Definition Lie.hpp:137
static auto diffJlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:394
static auto genericFormImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 alpha, const T3 beta)
Definition Lie.hpp:162
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:361
static auto deltaR(T1 &&t_w_vee, T2 theta, T3 &&t_A_hat)
Definition Lie.hpp:130
static auto Jl(A &&t_w_vee, B &&theta)
Definition Lie.hpp:68
static auto action(A &&t_w_vee, B &&theta, C &&t_A)
Definition Lie.hpp:78
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:424
static FTENSOR_INDEX(dim, l)
static FTENSOR_INDEX(dim, k)
static auto getVee(A &&t_w_hat)
Definition Lie.hpp:54
static auto getHatImpl(const FTensor::Tensor1< T, dim > &t_w_vee)
Definition Lie.hpp:154
static auto JlImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 &theta)
Definition Lie.hpp:333
static auto getHat(T &&w1, T &&w2, T &&w3)
Definition Lie.hpp:48
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:466
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:453
static auto JrImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:346
static auto diffJr(A &&t_w_vee, B &&theta)
Definition Lie.hpp:99
static FTENSOR_INDEX(dim, j)
static auto expImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:173
static auto diffJl(A &&t_w_vee, B &&theta)
Definition Lie.hpp:94
static auto getVeeImpl(const FTensor::Tensor2< T, dim, dim > &t_w_hat)
Definition Lie.hpp:146
static auto diffExp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:104
static auto materialSpin(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:115
static auto dActionJl(A &&t_w_vee, B &&t_A)
Definition Lie.hpp:84
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:445
static auto diffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:186
static auto materialSpinHat(T1 &&t_w_vee, T2 theta, T3 &&t_delta_w_vee)
Definition Lie.hpp:122
static auto getHat(A &&t_w_vee)
Definition Lie.hpp:58
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:434
static auto getVee(T &&w1, T &&w2, T &&w3)
Definition Lie.hpp:40
static auto exp(A &&t_w_vee, B &&theta)
Definition Lie.hpp:63
static auto diffDiffExpImpl(const FTensor::Tensor1< T1, dim > &t_w_vee, const T2 theta)
Definition Lie.hpp:238
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