v0.13.1
Levi_Civita.hpp
Go to the documentation of this file.
1// Fully Antisymmetric Levi-Civita Tensor
2
3#pragma once
4
5#include "Levi_Civita.hpp"
6
7namespace FTensor
8{
9 /// Levi_Civita Classes
10 template <class T = int> class Levi_Civita
11 {
12 public:
13 /// Rank 2
14 constexpr T operator()(const int N1, const int N2) const
15 {
16 return (N1 == N2) ? T(0) : ((N1 == 0) ? T(1) : T(-1));
17 }
18
19 template <char i, char j, int Dim0, int Dim1>
20 typename std::enable_if<
21 (Dim0 <= 2 && Dim1 <= 2),
22 Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>>::type
23 operator()(const Index<i, Dim0> &, const Index<j, Dim1> &)
24 {
25 return Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>(*this);
26 };
27
28 template <char i, int Dim0>
29 constexpr auto operator()(const Index<i, Dim0> &, const int &N1)
30 {
31 static_assert(
32 Dim0 <= 2,
33 "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor");
34#ifdef FTENSOR_DEBUG
35 if(N1 >= 2 || N1 < 0)
36 throw std::out_of_range(
37 "Bad index in Levi_Civita<T>::operator()(Index<"
38 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
39 + std::to_string(N1) + ")\n");
40#endif
41 auto TensorExpr
42 = [this, N1](const int &N0) { return this->operator()(N0, N1); };
44 };
45
46 template <char j, int Dim1>
47 constexpr auto operator()(const int &N0, const Index<j, Dim1> &)
48 {
49 static_assert(
50 Dim1 <= 2,
51 "Index dimension exceeds the maximum for Rank 2 Levi-Civita Tensor");
52#ifdef FTENSOR_DEBUG
53 if(N0 >= 2 || N0 < 0)
54 throw std::out_of_range("Bad index in Levi_Civita<T>::operator()("
55 + std::to_string(N0) + ", Index<"
56 + std::basic_string<char>{j} + ", "
57 + std::to_string(Dim1) + ">)\n");
58#endif
59 auto TensorExpr
60 = [this, N0](const int &N1) { return this->operator()(N0, N1); };
61 return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
62 };
63
64 /// Rank 3
65 constexpr T operator()(const int N1, const int N2, const int N3) const
66 {
67 return (N1 == N2 || N1 == N3 || N2 == N3)
68 ? T(0)
69 : (((N1 + 1) % 3 == N2) ? T(1) : T(-1));
70 }
71
72 template <char i, char j, char k, int Dim0, int Dim1, int Dim2>
73 typename std::enable_if<
74 (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3),
75 Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>>::type
76 operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
77 const Index<k, Dim2> &)
78 {
79 return Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>(*this);
80 };
81
82 template <char i, char j, int Dim0, int Dim1>
83 auto
84 operator()(const Index<i, Dim0> &, const Index<j, Dim1> &, const int &N2)
85 {
86 static_assert(
87 Dim0 <= 3 && Dim1 <= 3,
88 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
89#ifdef FTENSOR_DEBUG
90 if(N2 >= 3 || N2 < 0)
91 throw std::out_of_range(
92 "Bad index in Levi_Civita<T>::operator()("
93 "Index<"
94 + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
95 + ">, "
96 "Index<"
97 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
98 + std::to_string(N2) + ")\n");
99#endif
100 auto TensorExpr = [this, N2](const int &N0, const int &N1) {
101 return this->operator()(N0, N1, N2);
102 };
103 return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim1, i, j>{
104 TensorExpr};
105 }
106
107 template <char i, char k, int Dim0, int Dim2>
108 auto
109 operator()(const Index<i, Dim0> &, const int &N1, const Index<k, Dim2> &)
110 {
111 static_assert(
112 Dim0 <= 3 && Dim2 <= 3,
113 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
114#ifdef FTENSOR_DEBUG
115 if(N1 >= 3 || N1 < 0)
116 throw std::out_of_range(
117 "Bad index in Levi_Civita<T>::operator()("
118 "Index<"
119 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
120 + std::to_string(N1)
121 + ", "
122 "Index<"
123 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
124#endif
125 auto TensorExpr = [this, N1](const int &N0, const int &N2) {
126 return this->operator()(N0, N1, N2);
127 };
128 return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim2, i, k>{
129 TensorExpr};
130 }
131
132 template <char j, char k, int Dim1, int Dim2>
133 auto
134 operator()(const int &N0, const Index<j, Dim1> &, const Index<k, Dim2> &)
135 {
136 static_assert(
137 Dim1 <= 3 && Dim2 <= 3,
138 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
139#ifdef FTENSOR_DEBUG
140 if(N0 >= 3 || N0 < 0)
141 throw std::out_of_range(
142 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
143 + ", "
144 "Index<"
145 + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
146 + ">, "
147 "Index<"
148 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
149#endif
150 auto TensorExpr = [this, N0](const int &N1, const int &N2) {
151 return this->operator()(N0, N1, N2);
152 };
153 return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim2, j, k>{
154 TensorExpr};
155 }
156
157 template <char i, int Dim0>
158 auto operator()(const Index<i, Dim0> &, const int &N1, const int &N2)
159 {
160 static_assert(
161 Dim0 <= 3,
162 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
163#ifdef FTENSOR_DEBUG
164 if(N1 >= 3 || N1 < 0 || N2 >= 3 || N2 < 0)
165 throw std::out_of_range(
166 "Bad index in Levi_Civita<T>::operator()("
167 "Index<"
168 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
169 + std::to_string(N1) + ", " + std::to_string(N2) + ")\n");
170#endif
171 auto TensorExpr = [this, N1, N2](const int &N0) {
172 return this->operator()(N0, N1, N2);
173 };
174 return Tensor1_Expr<decltype(TensorExpr), T, Dim0, i>{TensorExpr};
175 }
176
177 template <char j, int Dim1>
178 auto operator()(const int &N0, const Index<j, Dim1> &, const int &N2)
179 {
180 static_assert(
181 Dim1 <= 3,
182 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
183#ifdef FTENSOR_DEBUG
184 if(N0 >= 3 || N0 < 0 || N2 >= 3 || N2 < 0)
185 throw std::out_of_range(
186 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
187 + ", "
188 "Index<"
189 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
190 + std::to_string(N2) + ")\n");
191#endif
192 auto TensorExpr = [this, N0, N2](const int &N1) {
193 return this->operator()(N0, N1, N2);
194 };
195 return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
196 }
197
198 template <char k, int Dim2>
199 auto operator()(const int &N0, const int &N1, const Index<k, Dim2> &)
200 {
201 static_assert(
202 Dim2 <= 3,
203 "Index dimension exceeds the maximum for Rank 3 Levi-Civita Tensor");
204#ifdef FTENSOR_DEBUG
205 if(N0 >= 3 || N0 < 0 || N1 >= 3 || N1 < 0)
206 throw std::out_of_range(
207 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
208 + ", " + std::to_string(N1)
209 + ", "
210 "Index<"
211 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">)\n");
212#endif
213 auto TensorExpr = [this, N0, N1](const int &N2) {
214 return this->operator()(N0, N1, N2);
215 };
216 return Tensor1_Expr<decltype(TensorExpr), T, Dim2, k>{TensorExpr};
217 }
218
219 /// Rank 4
220 constexpr T
221 operator()(const int N1, const int N2, const int N3, const int N4) const
222 {
223 return (N1 == N2 || N1 == N3 || N1 == N4 || N2 == N3 || N2 == N4
224 || N3 == N4)
225 ? T(0)
226 : ((N1 + N2 == 1 || N1 + N2 == 5)
227 ? (((N2 + N3) % 4 == 3) ? T(1) : T(-1))
228 : ((N1 + N2 == 2 || N1 + N2 == 4)
229 ? (((N2 + N3) % 4 == 1) ? T(1) : T(-1))
230 : (N1 + N2 == 3
231 ? (((N2 + N3) % 4 != 1) ? T(1) : T(-1))
232 : T(0))));
233 }
234
235 template <char i, char j, char k, char l, int Dim0, int Dim1, int Dim2,
236 int Dim3>
237 typename std::enable_if<
238 (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4),
239 Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
240 operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
241 const Index<k, Dim2> &, const Index<l, Dim3> &)
242 {
243 return Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k,
244 l>(*this);
245 }
246
247 template <char i, char j, char k, int Dim0, int Dim1, int Dim2>
248 constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
249 const Index<k, Dim2> &, const int &N3)
250 {
251 static_assert(
252 Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4,
253 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
254#ifdef FTENSOR_DEBUG
255 if(N3 >= 4 || N3 < 0)
256 throw std::out_of_range(
257 "Bad index in Levi_Civita<T>::operator()("
258 "Index<"
259 + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
260 + ">, "
261 "Index<"
262 + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
263 + ">, "
264 "Index<"
265 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
266 + std::to_string(N3) + ")\n");
267#endif
268 auto TensorExpr
269 = [this, N3](const int &N0, const int &N1, const int &N2) {
270 return this->operator()(N0, N1, N2, N3);
271 };
272 return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim1, Dim2, i, j, k>{
273 TensorExpr};
274 }
275
276 template <char i, char j, char l, int Dim0, int Dim1, int Dim3>
277 constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
278 const int &N2, const Index<l, Dim3> &)
279 {
280 static_assert(
281 Dim0 <= 4 && Dim1 <= 4 && Dim3 <= 4,
282 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
283#ifdef FTENSOR_DEBUG
284 if(N2 >= 4 || N2 < 0)
285 throw std::out_of_range(
286 "Bad index in Levi_Civita<T>::operator()("
287 "Index<"
288 + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
289 + ">, "
290 "Index<"
291 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
292 + std::to_string(N2)
293 + ", "
294 "Index<"
295 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
296#endif
297 auto TensorExpr
298 = [this, N2](const int &N0, const int &N1, const int &N3) {
299 return this->operator()(N0, N1, N2, N3);
300 };
301 return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim1, Dim3, i, j, l>{
302 TensorExpr};
303 }
304
305 template <char i, char k, char l, int Dim0, int Dim2, int Dim3>
306 constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
307 const Index<k, Dim2> &, const Index<l, Dim3> &)
308 {
309 static_assert(
310 Dim0 <= 4 && Dim2 <= 4 && Dim3 <= 4,
311 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
312#ifdef FTENSOR_DEBUG
313 if(N1 >= 4 || N1 < 0)
314 throw std::out_of_range(
315 "Bad index in Levi_Civita<T>::operator()("
316 "Index<"
317 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
318 + std::to_string(N1)
319 + ", "
320 "Index<"
321 + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
322 + ">, "
323 "Index<"
324 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
325#endif
326 auto TensorExpr
327 = [this, N1](const int &N0, const int &N2, const int &N3) {
328 return this->operator()(N0, N1, N2, N3);
329 };
330 return Tensor3_Expr<decltype(TensorExpr), T, Dim0, Dim2, Dim3, i, k, l>{
331 TensorExpr};
332 }
333
334 template <char j, char k, char l, int Dim1, int Dim2, int Dim3>
335 constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
336 const Index<k, Dim2> &, const Index<l, Dim3> &)
337 {
338 static_assert(
339 Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4,
340 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
341#ifdef FTENSOR_DEBUG
342 if(N0 >= 4 || N0 < 0)
343 throw std::out_of_range(
344 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
345 + ", "
346 "Index<"
347 + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
348 + ">, "
349 "Index<"
350 + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
351 + ">, "
352 "Index<"
353 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
354#endif
355 auto TensorExpr
356 = [this, N0](const int &N1, const int &N2, const int &N3) {
357 return this->operator()(N0, N1, N2, N3);
358 };
359 return Tensor3_Expr<decltype(TensorExpr), T, Dim1, Dim2, Dim3, j, k, l>{
360 TensorExpr};
361 }
362
363 template <char i, char j, int Dim0, int Dim1>
364 constexpr auto operator()(const Index<i, Dim0> &, const Index<j, Dim1> &,
365 const int &N2, const int &N3)
366 {
367 static_assert(
368 Dim0 <= 4 && Dim1 <= 4,
369 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
370#ifdef FTENSOR_DEBUG
371 if(N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
372 throw std::out_of_range(
373 "Bad index in Levi_Civita<T>::operator()("
374 "Index<"
375 + std::basic_string<char>{i} + ", " + std::to_string(Dim0)
376 + ">, "
377 "Index<"
378 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
379 + std::to_string(N2) + ", " + std::to_string(N3) + ")\n");
380#endif
381 auto TensorExpr = [this, N2, N3](const int &N0, const int &N1) {
382 return this->operator()(N0, N1, N2, N3);
383 };
384 return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim1, i, j>{
385 TensorExpr};
386 }
387
388 template <char i, char k, int Dim0, int Dim2>
389 constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
390 const Index<k, Dim2> &, const int &N3)
391 {
392 static_assert(
393 Dim0 <= 4 && Dim2 <= 4,
394 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
395#ifdef FTENSOR_DEBUG
396 if(N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0)
397 throw std::out_of_range(
398 "Bad index in Levi_Civita<T>::operator()("
399 "Index<"
400 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
401 + std::to_string(N1)
402 + ", "
403 "Index<"
404 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
405 + std::to_string(N3) + ")\n");
406#endif
407 auto TensorExpr = [this, N1, N3](const int &N0, const int &N2) {
408 return this->operator()(N0, N1, N2, N3);
409 };
410 return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim2, i, k>{
411 TensorExpr};
412 }
413
414 template <char j, char k, int Dim1, int Dim2>
415 constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
416 const Index<k, Dim2> &, const int &N3)
417 {
418 static_assert(
419 Dim1 <= 4 && Dim2 <= 4,
420 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
421#ifdef FTENSOR_DEBUG
422 if(N0 >= 4 || N0 < 0 || N3 >= 4 || N3 < 0)
423 throw std::out_of_range(
424 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
425 + ", "
426 "Index<"
427 + std::basic_string<char>{j} + ", " + std::to_string(Dim1)
428 + ">, "
429 "Index<"
430 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
431 + std::to_string(N3) + ")\n");
432#endif
433 auto TensorExpr = [this, N0, N3](const int &N1, const int &N2) {
434 return this->operator()(N0, N1, N2, N3);
435 };
436 return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim2, j, k>{
437 TensorExpr};
438 }
439
440 template <char i, char l, int Dim0, int Dim3>
441 constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
442 const int &N2, const Index<l, Dim3> &)
443 {
444 static_assert(
445 Dim0 <= 4 && Dim3 <= 4,
446 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
447#ifdef FTENSOR_DEBUG
448 if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0)
449 throw std::out_of_range(
450 "Bad index in Levi_Civita<T>::operator()("
451 "Index<"
452 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
453 + std::to_string(N1) + ", " + std::to_string(N2)
454 + ", "
455 "Index<"
456 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
457#endif
458 auto TensorExpr = [this, N1, N2](const int &N0, const int &N3) {
459 return this->operator()(N0, N1, N2, N3);
460 };
461 return Tensor2_Expr<decltype(TensorExpr), T, Dim0, Dim3, i, l>{
462 TensorExpr};
463 }
464
465 template <char j, char l, int Dim1, int Dim3>
466 constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
467 const int &N2, const Index<l, Dim3> &)
468 {
469 static_assert(
470 Dim1 <= 4 && Dim3 <= 4,
471 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
472#ifdef FTENSOR_DEBUG
473 if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0)
474 throw std::out_of_range(
475 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
476 + ", "
477 "Index<"
478 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
479 + std::to_string(N2)
480 + ", "
481 "Index<"
482 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
483#endif
484 auto TensorExpr = [this, N0, N2](const int &N1, const int &N3) {
485 return this->operator()(N0, N1, N2, N3);
486 };
487 return Tensor2_Expr<decltype(TensorExpr), T, Dim1, Dim3, j, l>{
488 TensorExpr};
489 }
490
491 template <char k, char l, int Dim2, int Dim3>
492 constexpr auto operator()(const int &N0, const int &N1,
493 const Index<k, Dim2> &, const Index<l, Dim3> &)
494 {
495 static_assert(
496 Dim2 <= 4 && Dim3 <= 4,
497 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
498#ifdef FTENSOR_DEBUG
499 if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0)
500 throw std::out_of_range(
501 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
502 + ", " + std::to_string(N1)
503 + ", "
504 "Index<"
505 + std::basic_string<char>{k} + ", " + std::to_string(Dim2)
506 + ">, "
507 "Index<"
508 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
509#endif
510 auto TensorExpr = [this, N0, N1](const int &N2, const int &N3) {
511 return this->operator()(N0, N1, N2, N3);
512 };
513 return Tensor2_Expr<decltype(TensorExpr), T, Dim2, Dim3, k, l>{
514 TensorExpr};
515 }
516
517 template <char i, int Dim0>
518 constexpr auto operator()(const Index<i, Dim0> &, const int &N1,
519 const int &N2, const int &N3)
520 {
521 static_assert(
522 Dim0 <= 4,
523 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
524#ifdef FTENSOR_DEBUG
525 if(N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
526 throw std::out_of_range(
527 "Bad index in Levi_Civita<T>::operator()("
528 "Index<"
529 + std::basic_string<char>{i} + ", " + std::to_string(Dim0) + ">, "
530 + std::to_string(N1) + ", " + std::to_string(N2) + ", "
531 + std::to_string(N3) + ")\n");
532#endif
533 auto TensorExpr = [this, N1, N2, N3](const int &N0) {
534 return this->operator()(N0, N1, N2, N3);
535 };
536 return Tensor1_Expr<decltype(TensorExpr), T, Dim0, i>{TensorExpr};
537 }
538
539 template <char j, int Dim1>
540 constexpr auto operator()(const int &N0, const Index<j, Dim1> &,
541 const int &N2, const int &N3)
542 {
543 static_assert(
544 Dim1 <= 4,
545 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
546#ifdef FTENSOR_DEBUG
547 if(N0 >= 4 || N0 < 0 || N2 >= 4 || N2 < 0 || N3 >= 4 || N3 < 0)
548 throw std::out_of_range(
549 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
550 + ", "
551 "Index<"
552 + std::basic_string<char>{j} + ", " + std::to_string(Dim1) + ">, "
553 + std::to_string(N2) + ", " + std::to_string(N3) + ")\n");
554#endif
555 auto TensorExpr = [this, N0, N2, N3](const int &N1) {
556 return this->operator()(N0, N1, N2, N3);
557 };
558 return Tensor1_Expr<decltype(TensorExpr), T, Dim1, j>{TensorExpr};
559 }
560
561 template <char k, int Dim2>
562 constexpr auto operator()(const int &N0, const int &N1,
563 const Index<k, Dim2> &, const int &N3)
564 {
565 static_assert(
566 Dim2 <= 4,
567 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
568#ifdef FTENSOR_DEBUG
569 if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N3 >= 4 || N3 < 0)
570 throw std::out_of_range(
571 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
572 + ", " + std::to_string(N1)
573 + ", "
574 "Index<"
575 + std::basic_string<char>{k} + ", " + std::to_string(Dim2) + ">, "
576 + std::to_string(N3) + ")\n");
577#endif
578 auto TensorExpr = [this, N0, N1, N3](const int &N2) {
579 return this->operator()(N0, N1, N2, N3);
580 };
581 return Tensor1_Expr<decltype(TensorExpr), T, Dim2, k>{TensorExpr};
582 }
583
584 template <char l, int Dim3>
585 constexpr auto operator()(const int &N0, const int &N1, const int &N2,
586 const Index<l, Dim3> &)
587 {
588 static_assert(
589 Dim3 <= 4,
590 "Index dimension exceeds the maximum for Rank 4 Levi-Civita Tensor");
591#ifdef FTENSOR_DEBUG
592 if(N0 >= 4 || N0 < 0 || N1 >= 4 || N1 < 0 || N2 >= 4 || N2 < 0)
593 throw std::out_of_range(
594 "Bad index in Levi_Civita<T>::operator()(" + std::to_string(N0)
595 + ", " + std::to_string(N1) + ", " + std::to_string(N2)
596 + ", "
597 "Index<"
598 + std::basic_string<char>{l} + ", " + std::to_string(Dim3) + ">)\n");
599#endif
600 auto TensorExpr = [this, N0, N1, N2](const int &N3) {
601 return this->operator()(N0, N1, N2, N3);
602 };
603 return Tensor1_Expr<decltype(TensorExpr), T, Dim3, l>{TensorExpr};
604 }
605 };
606
607 /// levi_civita functions to make for easy adhoc use
608
609 /// Normally, this should go in is own file levi_civita.hpp, but
610 /// not all filesystems can handle files that differ only in case :(
611
612 /// Rank 2
613 template <class T = int, char i, char j, int Dim0, int Dim1>
614 constexpr typename std::enable_if<
615 (Dim0 <= 2 && Dim1 <= 2),
616 Tensor2_Expr<Levi_Civita<T>, T, Dim0, Dim1, i, j>>::type
618 {
620 }
621
622 template <class T = int, char i, int Dim0>
623 constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1)
624 {
625 return Levi_Civita<T>()(Index<i, Dim0>(), N1);
626 }
627
628 template <class T = int, char j, int Dim1>
629 constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &)
630 {
631 return Levi_Civita<T>()(N0, Index<j, Dim1>());
632 }
633
634 /// Rank 3
635 template <class T = int, char i, char j, char k, int Dim0, int Dim1, int Dim2>
636 constexpr typename std::enable_if<
637 (Dim0 <= 3 && Dim1 <= 3 && Dim2 <= 3),
638 Tensor3_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, i, j, k>>::type
640 const Index<k, Dim2> &)
641 {
644 }
645
646 template <class T = int, char i, char j, int Dim0, int Dim1>
647 constexpr auto
648 levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &, const int &N2)
649 {
651 }
652
653 template <class T = int, char i, char k, int Dim0, int Dim2>
654 constexpr auto
655 levi_civita(const Index<i, Dim0> &, const int &N1, const Index<k, Dim2> &)
656 {
658 }
659
660 template <class T = int, char j, char k, int Dim1, int Dim2>
661 constexpr auto
662 levi_civita(const int &N0, const Index<j, Dim1> &, const Index<k, Dim2> &)
663 {
665 }
666
667 template <class T = int, char i, int Dim0>
668 constexpr auto
669 levi_civita(const Index<i, Dim0> &, const int &N1, const int &N2)
670 {
671 return Levi_Civita<T>()(Index<i, Dim0>(), N1, N2);
672 }
673
674 template <class T = int, char j, int Dim1>
675 constexpr auto
676 levi_civita(const int &N0, const Index<j, Dim1> &, const int &N2)
677 {
678 return Levi_Civita<T>()(N0, Index<j, Dim1>(), N2);
679 }
680
681 template <class T = int, char k, int Dim2>
682 constexpr auto
683 levi_civita(const int &N0, const int &N1, const Index<k, Dim2> &)
684 {
685 return Levi_Civita<T>()(N0, N1, Index<k, Dim2>());
686 }
687
688 /// Rank 4
689 template <class T = int, char i, char j, char k, char l, int Dim0, int Dim1,
690 int Dim2, int Dim3>
691 constexpr typename std::enable_if<
692 (Dim0 <= 4 && Dim1 <= 4 && Dim2 <= 4 && Dim3 <= 4),
693 Tensor4_Expr<Levi_Civita<T>, T, Dim0, Dim1, Dim2, Dim3, i, j, k, l>>::type
695 const Index<k, Dim2> &, const Index<l, Dim3> &)
696 {
699 }
700
701 template <class T = int, char i, char j, char k, int Dim0, int Dim1, int Dim2>
702 constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
703 const Index<k, Dim2> &, const int &N3)
704 {
706 Index<k, Dim2>(), N3);
707 }
708
709 template <class T = int, char i, char j, char l, int Dim0, int Dim1, int Dim3>
710 constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
711 const int &N2, const Index<l, Dim3> &)
712 {
715 }
716
717 template <class T = int, char i, char k, char l, int Dim0, int Dim2, int Dim3>
718 constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
719 const Index<k, Dim2> &, const Index<l, Dim3> &)
720 {
723 }
724
725 template <class T = int, char j, char k, char l, int Dim1, int Dim2, int Dim3>
726 constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
727 const Index<k, Dim2> &, const Index<l, Dim3> &)
728 {
731 }
732
733 template <class T = int, char i, char j, int Dim0, int Dim1>
734 constexpr auto levi_civita(const Index<i, Dim0> &, const Index<j, Dim1> &,
735 const int &N2, const int &N3)
736 {
738 }
739
740 template <class T = int, char i, char k, int Dim0, int Dim2>
741 constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
742 const Index<k, Dim2> &, const int &N3)
743 {
745 }
746
747 template <class T = int, char j, char k, int Dim1, int Dim2>
748 constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
749 const Index<k, Dim2> &, const int &N3)
750 {
752 }
753
754 template <class T = int, char i, char l, int Dim0, int Dim3>
755 constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
756 const int &N2, const Index<l, Dim3> &)
757 {
759 }
760
761 template <class T = int, char j, char l, int Dim1, int Dim3>
762 constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
763 const int &N2, const Index<l, Dim3> &)
764 {
766 }
767
768 template <class T = int, char k, char l, int Dim2, int Dim3>
769 constexpr auto levi_civita(const int &N0, const int &N1,
770 const Index<k, Dim2> &, const Index<l, Dim3> &)
771 {
773 }
774
775 template <class T = int, char i, int Dim0>
776 constexpr auto levi_civita(const Index<i, Dim0> &, const int &N1,
777 const int &N2, const int &N3)
778 {
779 return Levi_Civita<T>()(Index<i, Dim0>(), N1, N2, N3);
780 }
781
782 template <class T = int, char j, int Dim1>
783 constexpr auto levi_civita(const int &N0, const Index<j, Dim1> &,
784 const int &N2, const int &N3)
785 {
786 return Levi_Civita<T>()(N0, Index<j, Dim1>(), N2, N3);
787 }
788
789 template <class T = int, char k, int Dim2>
790 constexpr auto levi_civita(const int &N0, const int &N1,
791 const Index<k, Dim2> &, const int &N3)
792 {
793 return Levi_Civita<T>()(N0, N1, Index<k, Dim2>(), N3);
794 }
795
796 template <class T = int, char l, int Dim3>
797 constexpr auto levi_civita(const int &N0, const int &N1, const int &N2,
798 const Index<l, Dim3> &)
799 {
800 return Levi_Civita<T>()(N0, N1, N2, Index<l, Dim3>());
801 }
802}
static Number< 2 > N2
static Number< 1 > N1
static Number< 0 > N0
Levi_Civita Classes.
Definition: Levi_Civita.hpp:11
constexpr T operator()(const int N1, const int N2, const int N3) const
Rank 3.
Definition: Levi_Civita.hpp:65
auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const int &N3)
constexpr T operator()(const int N1, const int N2) const
Rank 2.
Definition: Levi_Civita.hpp:14
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
constexpr auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2, const Index< l, Dim3 > &)
auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2, const Index< l, Dim3 > &)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &, const int &N3)
auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2)
Definition: Levi_Civita.hpp:84
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const Index< k, Dim2 > &, const Index< l, Dim3 > &)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2, const Index< l, Dim3 > &)
auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2)
constexpr auto operator()(const int &N0, const int &N1, const int &N2, const Index< l, Dim3 > &)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &, const int &N2, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2, const int &N3)
constexpr auto operator()(const Index< i, Dim0 > &, const Index< j, Dim1 > &, const int &N2, const int &N3)
auto operator()(const Index< i, Dim0 > &, const int &N1, const int &N2)
constexpr auto operator()(const Index< i, Dim0 > &, const int &N1)
Definition: Levi_Civita.hpp:29
constexpr auto operator()(const int &N0, const int &N1, const Index< k, Dim2 > &, const int &N3)
constexpr auto operator()(const int &N0, const Index< j, Dim1 > &)
Definition: Levi_Civita.hpp:47
auto operator()(const int &N0, const Index< j, Dim1 > &, const Index< k, Dim2 > &)
constexpr T operator()(const int N1, const int N2, const int N3, const int N4) const
Rank 4.
FTensor::Index< 'i', SPACE_DIM > i
FTensor::Index< 'l', 3 > l
FTensor::Index< 'j', 3 > j
FTensor::Index< 'k', 3 > k
const double T
Tensors class implemented by Walter Landry.
Definition: FTensor.hpp:51
constexpr std::enable_if<(Dim0<=2 &&Dim1<=2), Tensor2_Expr< Levi_Civita< T >, T, Dim0, Dim1, i, j > >::type levi_civita(const Index< i, Dim0 > &, const Index< j, Dim1 > &)
levi_civita functions to make for easy adhoc use