criptic v1
Cosmic Ray Interstellar Propagation Tool using Itô Calculus
Loading...
Searching...
No Matches
RealTensor2.H
Go to the documentation of this file.
1
10#ifndef _REALTENSOR2_H_
11#define _REALTENSOR2_H_
12
13#include <algorithm>
14#include <cassert>
15#include <cmath>
16#include <vector>
17#include "Types.H"
18#include "Vec3.H"
19#include "gsl/gsl_eigen.h"
20#include "gsl/gsl_matrix.h"
21#include "gsl/gsl_vector.h"
22
23namespace criptic {
24
35
36 public:
37
39 // Storage
41
42 Real t[9];
48 t[0] = t[1] = t[2] = t[3] = t[4] = t[5] = t[6] = t[7] = t[8] = 0.0;
49 }
50
63 RealTensor2(const Real& xx, const Real& xy, const Real& xz,
64 const Real& yx, const Real& yy, const Real& yz,
65 const Real& zx, const Real& zy, const Real& zz)
66 {
67 t[0] = xx; t[1] = xy; t[2] = xz;
68 t[3] = yx; t[4] = yy; t[5] = yz;
69 t[6] = zx; t[7] = zy; t[8] = zz;
70 }
71
79 RealTensor2(const RealVec &a, const RealVec &b) {
80 for (int i=0; i<3; i++)
81 for (int j=0; j<3; j++)
82 t[3*i+j] = a[i] * b[j];
83 }
84
86 // Element access
88
96 Real& operator () (int i, int j) {
97 assert(i >= 0 && i < 3 && j >= 0 && j < 3);
98 return t[3*i+j];
99 }
107 const Real& operator () (int i, int j) const {
108 assert(i >= 0 && i < 3 && j >= 0 && j < 3);
109 return t[3*i+j];
110 }
118 assert(i >= 0 && i < 9);
119 return t[i];
120 }
127 const Real& operator [] (int i) const {
128 assert(i >= 0 && i < 9);
129 return t[i];
130 }
131
133 // Unary operators
135
142 RealTensor2 rt( -t[0], -t[1], -t[2],
143 -t[3], -t[4], -t[5],
144 -t[6], -t[7], -t[8] );
145 return rt;
146 }
147
149 // Unary operators with scalars
151
159 for (int i=0; i<9; i++) t[i] += a;
160 return *this;
161 }
169 for (int i=0; i<9; i++) t[i] -= a;
170 return *this;
171 }
179 for (int i=0; i<9; i++) t[i] *= a;
180 return *this;
181 }
189 for (int i=0; i<9; i++) t[i] /= a;
190 return *this;
191 }
192
194 // Unary operators with tensors
196
204 for (int i=0; i<9; i++) t[i] += a[i];
205 return *this;
206 }
214 for (int i=0; i<9; i++) t[i] -= a[i];
215 return *this;
216 }
224 for (int i=0; i<9; i++) t[i] *= a[i];
225 return *this;
226 }
234 for (int i=0; i<9; i++) t[i] /= a[i];
235 return *this;
236 }
237
239 // Binary operations with scalars
241
249 for (int i=0; i<9; i++) t[i] = a;
250 return *this;
251 }
252
259 RealTensor2 operator+(const Real a) const {
260 RealTensor2 rt(*this);
261 for (int i=0; i<9; i++) rt.t[i] += a;
262 return rt;
263 }
270 RealTensor2 operator-(const Real a) const {
271 RealTensor2 rt(*this);
272 for (int i=0; i<9; i++) rt.t[i] -= a;
273 return rt;
274 }
281 RealTensor2 operator*(const Real a) const {
282 RealTensor2 rt(*this);
283 for (int i=0; i<9; i++) rt.t[i] *= a;
284 return rt;
285 }
292 RealTensor2 operator/(const Real a) const {
293 RealTensor2 rt(*this);
294 for (int i=0; i<9; i++) rt.t[i] /= a;
295 return rt;
296 }
297
299 // Matrix-vector multiplication
301
308 RealVec operator*(const RealVec& v) const {
309 RealVec r;
310 for (int i=0; i<3; i++)
311 for (int j=0; j<3; j++) r[i] += (*this)(i,j) * v[j];
312 return r;
313 }
314
316 // Binary operations with tensors
318
326 RealTensor2 rt(*this);
327 for (int i=0; i<9; i++) rt.t[i] += a[i];
328 return rt;
329 }
337 RealTensor2 rt(*this);
338 for (int i=0; i<9; i++) rt.t[i] -= a[i];
339 return rt;
340 }
348 RealTensor2 rt(*this);
349 for (int i=0; i<9; i++) rt.t[i] *= a[i];
350 return rt;
351 }
359 RealTensor2 rt(*this);
360 for (int i=0; i<9; i++) rt.t[i] /= a[i];
361 return rt;
362 }
363
365 // Binary operations with vectors and tensors
367
373 RealVec contract1(const RealVec& v) const {
374 RealVec rv;
375 for (int j=0; j<3; j++)
376 for (int i=0; i<3; i++) rv(j) += v(i) * (*this)(i,j);
377 return rv;
378 }
379
385 RealVec contract2(const RealVec& v) const {
386 return (*this) * v;
387 }
388
395 Real contract(const RealVec& a, const RealVec& b) const {
396 Real c = 0.0;
397 for (int i=0; i<3; i++)
398 for (int j=0; j<3; j++)
399 c += a[i] * b[j] * (*this)(i,j);
400 return c;
401 }
402
408 Real contract(const RealTensor2& a) const {
409 Real c = 0.0;
410 for (int i=0; i<3; i++)
411 for (int j=0; j<3; j++) c += (*this)(i,j) * a(i,j);
412 return c;
413 }
414
425 Real divTangent(const RealVec& v) const {
426
427 // This routine makes use of the relation
428 // d/dx_i eT_i = d/dx_i (v_i / |v|)
429 // = (1 / |v|) [ (dv_i / dx_i) - (v_i v_j dv_j / dx_i) / |v| ]
430 Real divT = 0.0;
431 Real vmag = v.mag();
432 for (int i=0; i<3; i++) {
433 for (int j=0; j<3; j++) {
434 divT += -v[i] * v[j] * (*this)(j,i) / vmag;
435 }
436 divT += (*this)(i,i);
437 }
438 divT /= vmag;
439 return divT;
440 }
441
443 // Unary operations
445
449 Real trace() const {
450 Real tr = 0.0;
451 for (int i=0; i<3; i++) tr += (*this)(i,i);
452 return tr;
453 }
454
459 RealTensor2 T() const {
460 RealTensor2 rt;
461 for (int i=0; i<3; i++)
462 for (int j=0; j<3; j++) rt(i,j) = (*this)(j,i);
463 return rt;
464 }
465
469 void transpose() {
470 for (int i=1; i<3; i++)
471 for (int j=0; j<i; j++)
472 std::swap( (*this)(i,j), (*this)(j,i) );
473 }
474
480 Real m2 = 0.0;
481 for (int i=0; i<9; i++) m2 += t[i]*t[i];
482 return std::sqrt(m2);
483 }
484
489 Real det() const {
490 return (*this)(0,0) * ( (*this)(1,1) * (*this)(2,2) -
491 (*this)(1,2) * (*this)(2,1) ) +
492 (*this)(0,1) * ( (*this)(1,2) * (*this)(2,0) -
493 (*this)(1,0) * (*this)(2,2) ) +
494 (*this)(0,2) * ( (*this)(1,0) * (*this)(2,1) -
495 (*this)(1,1) * (*this)(2,0) );
496 }
497
505 RealVec eVal() const {
506
507 // Allocate workspace
508 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
509 gsl_matrix *T = gsl_matrix_alloc(3,3);
510 gsl_matrix *Q = gsl_matrix_alloc(3,3);
511 gsl_vector *D = gsl_vector_alloc(3);
512
513 // Create a GSL matrix corresponding to our tensor
514 for (int i=0; i<3; i++)
515 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
516
517 // Get eigenvalues and eigenvectors
518 gsl_eigen_symmv(T, D, Q, w);
519
520 // Pack the results into our vector
521 RealVec eV;
522 for (int i=0; i<3; i++) {
523 eV[i] = gsl_vector_get(D, i);
524 }
525
526 // Free workspace
527 gsl_matrix_free(T);
528 gsl_matrix_free(Q);
529 gsl_vector_free(D);
530 gsl_eigen_symmv_free(w);
531
532 // Return
533 return eV;
534 }
535
544
545 // Allocate workspace
546 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
547 gsl_matrix *T = gsl_matrix_alloc(3,3);
548 gsl_matrix *Q = gsl_matrix_alloc(3,3);
549 gsl_vector *D = gsl_vector_alloc(3);
550
551 // Create a GSL matrix corresponding to our tensor
552 for (int i=0; i<3; i++)
553 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
554
555 // Get eigenvalues and eigenvectors
556 gsl_eigen_symmv(T, D, Q, w);
557
558 // Pack the result into a new tensor
559 RealTensor2 ev;
560 for (int i=0; i<3; i++)
561 for (int j=0; j<3; j++) ev(i,j) = gsl_matrix_get(Q, i, j);
562
563 // Free workspace
564 gsl_matrix_free(T);
565 gsl_matrix_free(Q);
566 gsl_vector_free(D);
567 gsl_eigen_symmv_free(w);
568
569 // Return
570 return ev;
571 }
572
584
585 // Allocate workspace
586 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
587 gsl_matrix *T = gsl_matrix_alloc(3,3);
588 gsl_matrix *Q = gsl_matrix_alloc(3,3);
589 gsl_vector *D = gsl_vector_alloc(3);
590
591 // Create a GSL matrix corresponding to our tensor
592 for (int i=0; i<3; i++)
593 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
594
595 // Get eigenvalues and eigenvectors
596 gsl_eigen_symmv(T, D, Q, w);
597
598 // Pack the results into our vector and tensor structures
599 for (int i=0; i<3; i++) {
600 eVal[i] = gsl_vector_get(D, i);
601 for (int j=0; j<3; j++) eVec(i,j) = gsl_matrix_get(Q, i, j);
602 }
603
604 // Free workspace
605 gsl_matrix_free(T);
606 gsl_matrix_free(Q);
607 gsl_vector_free(D);
608 gsl_eigen_symmv_free(w);
609 }
610
618 RealTensor2 inv() const {
619 // This method works by finding the eigendecomposition of the
620 // matrix, as T = Q D Q^T, where Q is an orthogonal matrix whose
621 // columns are the eigenvalues of T, and D is a diagonal matrix
622 // whose diagonal elements are the corresponding
623 // eigenvalues. The inverse is then trivial to compute: since
624 // I = T T^-1 = (Q D Q^T) (Q D^-1 Q^T), it immeidately follows
625 // that T^-1 = Q D^-1 Q^T.
626
627 // Allocate workspace
628 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
629 gsl_matrix *T = gsl_matrix_alloc(3,3);
630 gsl_matrix *Q = gsl_matrix_alloc(3,3);
631 gsl_vector *D = gsl_vector_alloc(3);
632
633 // Create a GSL matrix corresponding to our tensor
634 for (int i=0; i<3; i++)
635 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
636
637 // Get eigenvalues and eigenvectors
638 gsl_eigen_symmv(T, D, Q, w);
639
640 // Get D^-1
641 for (int i=0; i<3; i++)
642 gsl_vector_set(D, i, 1/(gsl_vector_get(D, i)));
643
644 // Compute final tensor; note that we take advantage of the fact
645 // that D^(-1) is diagonal to simplify as follows:
646 // (Q D^(-1) Q^T)_ij = Q_in (D^(-1))_nm Q^T_mj
647 // = Q_in Q_jm (D^(-1))_nm
648 // = Q_in Q_jm (D^(-1))_nm delta_nm
649 // = Q_in Q_jn (D^(-1))_nn
650 // Also note that, since the final tensor is also symmetric, we
651 // can just compute the diagonal and lower triangular elements,
652 // then fill in the rest by symmetry.
653 RealTensor2 Tinv;
654 for (int i=0; i<3; i++) {
655 for (int j=0; j<=i; j++) {
656 for (int n=0; n<3; n++) {
657 Tinv(i,j) += gsl_vector_get(D, n) *
658 gsl_matrix_get(Q, i, n) *
659 gsl_matrix_get(Q, j, n);
660 }
661 }
662 }
663 for (int i=0; i<3; i++) {
664 for (int j=i+1; j<3; j++) {
665 Tinv(i,j) = Tinv(j,i);
666 }
667 }
668
669 // Free workspace
670 gsl_matrix_free(T);
671 gsl_matrix_free(Q);
672 gsl_vector_free(D);
673 gsl_eigen_symmv_free(w);
674
675 // Return
676 return Tinv;
677 }
678
687 // Note: this method computes the square root by finding the
688 // eigenvalue and eigenvectors of the tensor; for a real,
689 // symmetric matrix T, we can uniquely decomposite it as T = Q D
690 // Q^T, where Q is an orthogonal matrix whose columns are the
691 // eigenvalues of T, and D is a diagonal matrix whose diagonal
692 // elements are the corresponding eigenvalues. Then it
693 // immediately follows that T = (Q D^(1/2) Q^T) (Q D^(1/2) Q^T),
694 // since Q^T = Q^-1 for an orthogonal matrix, and therefore that
695 // Q D^(1/2) Q^T = T^(1/2).
696
697 // Allocate workspace
698 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
699 gsl_matrix *T = gsl_matrix_alloc(3,3);
700 gsl_matrix *Q = gsl_matrix_alloc(3,3);
701 gsl_vector *D = gsl_vector_alloc(3);
702
703 // Create a GSL matrix corresponding to our tensor
704 for (int i=0; i<3; i++)
705 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
706
707 // Get eigenvalues and eigenvectors
708 gsl_eigen_symmv(T, D, Q, w);
709
710 // Take square root of the eigenvalues to form D^(1/2)
711 for (int i=0; i<3; i++)
712 gsl_vector_set(D, i, std::sqrt(gsl_vector_get(D, i)));
713
714 // Compute final tensor; note that we take advantage of the fact
715 // that D^(1/2) is diagonal to simplify as follows:
716 // (Q D^(1/2) Q^T)_ij = Q_in (D^(1/2))_nm Q^T_mj
717 // = Q_in Q_jm (D^(1/2))_nm
718 // = Q_in Q_jm (D^(1/2))_nm delta_nm
719 // = Q_in Q_jn (D^(1/2))_nn
720 // Also note that, since the final tensor is also symmetric, we
721 // can just compute the diagonal and lower triangular elements,
722 // then fill in the rest by symmetry.
723 RealTensor2 Tsqrt;
724 for (int i=0; i<3; i++) {
725 for (int j=0; j<3; j++) {
726 for (int n=0; n<3; n++) {
727 Tsqrt(i,j) += gsl_vector_get(D, n) *
728 gsl_matrix_get(Q, i, n) *
729 gsl_matrix_get(Q, j, n);
730 }
731 }
732 }
733 for (int i=0; i<3; i++) {
734 for (int j=i+1; j<3; j++) {
735 Tsqrt(i,j) = Tsqrt(j,i);
736 }
737 }
738
739 // Free workspace
740 gsl_matrix_free(T);
741 gsl_matrix_free(Q);
742 gsl_vector_free(D);
743 gsl_eigen_symmv_free(w);
744
745 // Return
746 return Tsqrt;
747 }
748
757 // Note: this method computes the inverse of the square root by
758 // eigendecomposition, using a slight modification of the
759 // algorithm used to compute the square root. Given that T = Q D
760 // Q^T is the eigendecomposition of T, and further as shown
761 // above that T^(1/2) = Q D^(1/2) Q^T, it further follows that I
762 // = (Q D^(1/2) Q^T) (Q D^(-1/2) Q^T) = T^(1/2) (Q D^(-1/2) Q^T),
763 // and therefore that (Q D^(-1/2) Q^T) = (T^(1/2))^(-1).
764
765 // Allocate workspace
766 gsl_eigen_symmv_workspace *w = gsl_eigen_symmv_alloc(3);
767 gsl_matrix *T = gsl_matrix_alloc(3,3);
768 gsl_matrix *Q = gsl_matrix_alloc(3,3);
769 gsl_vector *D = gsl_vector_alloc(3);
770
771 // Create a GSL matrix corresponding to our tensor
772 for (int i=0; i<3; i++)
773 for (int j=0; j<3; j++) gsl_matrix_set(T, i, j, (*this)(i,j));
774
775 // Get eigenvalues and eigenvectors
776 gsl_eigen_symmv(T, D, Q, w);
777
778 // Compute D^(-1/2)
779 for (int i=0; i<3; i++)
780 gsl_vector_set(D, i, 1/std::sqrt(gsl_vector_get(D, i)));
781
782 // Compute final tensor; note that we take advantage of the fact
783 // that D^(1/2) is diagonal to simplify as follows:
784 // (Q D^(1/2) Q^T)_ij = Q_in (D^(-1/2))_nm Q^T_mj
785 // = Q_in Q_jm (D^(-1/2))_nm
786 // = Q_in Q_jm (D^(-1/2))_nm delta_nm
787 // = Q_in Q_jn (D^(-1/2))_nn
788 // Also note that, since the final tensor is also symmetric, we
789 // can just compute the diagonal and lower triangular elements,
790 // then fill in the rest by symmetry.
791 RealTensor2 TInvSqrt;
792 for (int i=0; i<3; i++) {
793 for (int j=0; j<=i; j++) {
794 for (int n=0; n<3; n++) {
795 TInvSqrt(i,j) += gsl_vector_get(D, n) *
796 gsl_matrix_get(Q, i, n) *
797 gsl_matrix_get(Q, j, n);
798 }
799 }
800 }
801 for (int i=0; i<3; i++) {
802 for (int j=i+1; j<3; j++) {
803 TInvSqrt(i,j) = TInvSqrt(j,i);
804 }
805 }
806
807 // Free workspace
808 gsl_matrix_free(T);
809 gsl_matrix_free(Q);
810 gsl_vector_free(D);
811 gsl_eigen_symmv_free(w);
812
813 // Return
814 return TInvSqrt;
815 }
816
817 };
818
819 // Define the zero and identity tensors
820 static const criptic::RealTensor2
821 zeroTensor(0,0,0,0,0,0,0,0,0);
822 static const criptic::RealTensor2
823 identityTensor(1,0,0,0,1,0,0,0,1);
825 // Overload the basic arithmetic operators for Real numbers to allow
826 // them to operate on RealTensor2's, so for example 0.5 * t works as
827 // well as t * 0.5.
835 const criptic::RealTensor2& t) {
836 RealTensor2 rt( a + t[0], a + t[1], a + t[2],
837 a + t[3], a + t[4], a + t[5],
838 a + t[6], a + t[7], a + t[8] );
839 return rt;
840 }
848 const criptic::RealTensor2& t) {
849 RealTensor2 rt( a - t[0], a - t[1], a - t[2],
850 a - t[3], a - t[4], a - t[5],
851 a - t[6], a - t[7], a - t[8] );
852 return rt;
853 }
861 const criptic::RealTensor2& t) {
862 RealTensor2 rt( a * t[0], a * t[1], a * t[2],
863 a * t[3], a * t[4], a * t[5],
864 a * t[6], a * t[7], a * t[8] );
865 return rt;
866 }
874 const criptic::RealTensor2& t) {
875 RealTensor2 rt( a / t[0], a / t[1], a / t[2],
876 a / t[3], a / t[4], a / t[5],
877 a / t[6], a / t[7], a / t[8] );
878 return rt;
879 }
880
888 const criptic::RealVec& v2) {
889 RealTensor2 rt(v1, v2);
890 return rt;
891 }
892
898 typedef struct {
902 } TNBBasis;
903
913 inline TNBBasis TNBVectors(const RealVec& v,
914 const RealTensor2& vGrad) {
915
916 // Basis object to return
917 TNBBasis b;
918
919 // First set tangent vector
920 Real vmag = v.mag();
921 b.eT = v/vmag;
922
923 // Next set normal vector, using the relation
924 // eN_i \propto eT_j (d eT_i / dx_j)
925 // \propto eT_j ( |v| dv_i / dx_j - v_i v_k dv_k / dx_j )
926 RealVec vDotGradv; // (vDotGradv)_j = v_k dv_k / dx_j
927 for (int j=0; j<3; j++) {
928 for (int k=0; k<3; k++) vDotGradv[j] += v[k] * vGrad[3*k + j];
929 }
930 Real norm = 0.0;
931 for (int i=0; i<3; i++) {
932 b.eN[i] = 0.0;
933 for (int j=0; j<3; j++)
934 b.eN[i] += b.eT[j] * (vmag*vmag * vGrad[3*i+j] - v[i] * vDotGradv[j]);
935 norm += b.eN[i] * b.eN[i];
936 }
937
938 // Handle special case where field is straight so grad(v) = 0, in
939 // which case eN is degenerate, and the calculation we have just
940 // done will yield a norm of zero
941 if (norm > 0.0) {
942 // Non-degerate case
943 b.eN.normalize();
944 } else {
945 // Degenerate case; break the degeneracy by choosing eN to be in
946 // the xy plane, unless eT = \hat{z}, in which case we just
947 // choose eN = \hat{x}
948 Real xynorm = std::sqrt( b.eT[0]*b.eT[0] + b.eT[1]*b.eT[1] );
949 if (xynorm == 0.0) {
950 b.eN[0] = 1.0;
951 b.eN[1] = b.eN[2] = 0.0;
952 } else {
953 b.eN[0] = b.eT[1] / xynorm;
954 b.eN[1] = -b.eT[0] / xynorm;
955 }
956 }
957
958 // Get binormal vector
959 b.eB = b.eT.cross(b.eN);
960
961 // Return
962 return b;
963 }
964}
965
966#endif
967// _REALTENSOR2_H_
Basic integer and real types.
Class that represents a mathematical vector in 3-space.
Class that represents a rank 2 tensor.
Definition RealTensor2.H:34
RealTensor2 operator/(const RealTensor2 &a) const
Divide two RealTensor2s elementwise.
Definition RealTensor2.H:358
RealTensor2 sqrt() const
Compute the square root of a symmetric tensor.
Definition RealTensor2.H:686
Real det() const
Compute the determinant.
Definition RealTensor2.H:489
RealTensor2 & operator+=(const RealTensor2 &a)
Add another RealTensor2 to the RealTensor2 elementwise.
Definition RealTensor2.H:203
RealTensor2 operator*(const RealTensor2 &a) const
Multiply two RealTensor2s elementwise.
Definition RealTensor2.H:347
RealVec operator*(const RealVec &v) const
Matrix-vector multiplication.
Definition RealTensor2.H:308
RealTensor2(const RealVec &a, const RealVec &b)
Construct a RealTensor2 as the outer product of two RealVecs.
Definition RealTensor2.H:79
RealTensor2 invSqrt() const
Compute the inverse of the square root of a symmetric tensor.
Definition RealTensor2.H:756
Real contract(const RealVec &a, const RealVec &b) const
Compute the tensor contraction a_i b_j T_ij.
Definition RealTensor2.H:395
RealVec contract2(const RealVec &v) const
Compute the tensor contraction v_j T_ij.
Definition RealTensor2.H:385
RealTensor2 & operator/=(const Real a)
Divide the RealTensor2 by a scalar elementwise.
Definition RealTensor2.H:188
Real mag()
Total magnitude.
Definition RealTensor2.H:479
Real t[9]
Definition RealTensor2.H:42
Real & operator()(int i, int j)
Return an element of the tensor.
Definition RealTensor2.H:96
RealTensor2(const Real &xx, const Real &xy, const Real &xz, const Real &yx, const Real &yy, const Real &yz, const Real &zx, const Real &zy, const Real &zz)
Construct a RealTensor2 from nine scalars.
Definition RealTensor2.H:63
Real trace() const
Return the trace of this tensor.
Definition RealTensor2.H:449
RealTensor2 operator-(const Real a) const
Subtract a scalar from a RealTensor2 elementwise.
Definition RealTensor2.H:270
RealVec eVal() const
Compute the eigenvalues of a symmetric tensor.
Definition RealTensor2.H:505
RealTensor2 inv() const
Compute the inverse of a symmetric tensor.
Definition RealTensor2.H:618
RealTensor2()
Construct a RealTensor2 of all zeros.
Definition RealTensor2.H:47
RealVec contract1(const RealVec &v) const
Compute the tensor contraction v_i T_ij.
Definition RealTensor2.H:373
RealTensor2 T() const
Return the transpose of this tensor.
Definition RealTensor2.H:459
void eigenDecompose(RealVec &eVal, RealTensor2 &eVec) const
Compute the eigendecomposition of a symmetric tensor.
Definition RealTensor2.H:583
RealTensor2 & operator/=(const RealTensor2 &a)
Divide this RealTensor2 by another RealTensor2 elementwise.
Definition RealTensor2.H:233
RealTensor2 operator/(const Real a) const
Divide a RealTensor2 by a scalar elementwise.
Definition RealTensor2.H:292
Real & operator[](int i)
Return an element of the tensor.
Definition RealTensor2.H:117
RealTensor2 & operator*=(const RealTensor2 &a)
Multiply another RealTensor2 by the RealTensor2 elementwise.
Definition RealTensor2.H:223
RealTensor2 operator*(const Real a) const
Multiply a scalar by a RealTensor2 elementwise.
Definition RealTensor2.H:281
RealTensor2 & operator=(const Real a)
Assign a scalar value to every element of a RealTensor2.
Definition RealTensor2.H:248
RealTensor2 & operator-=(const RealTensor2 &a)
Subtract another RealTensor2 from the RealTensor2 elementwise.
Definition RealTensor2.H:213
RealTensor2 & operator-=(const Real a)
Subtract a scalar from the RealTensor2 elementwise.
Definition RealTensor2.H:168
RealTensor2 eVec() const
Compute the eigenvectors of a symmetric tensor.
Definition RealTensor2.H:543
Real divTangent(const RealVec &v) const
Compute the divergence of the tangent vector.
Definition RealTensor2.H:425
RealTensor2 operator+(const RealTensor2 &a) const
Add two RealTensor2s elementwise.
Definition RealTensor2.H:325
RealTensor2 operator-(const RealTensor2 &a) const
Subtract two RealTensor2s elementwise.
Definition RealTensor2.H:336
RealTensor2 operator+(const Real a) const
Add a scalar and a RealTensor2 elementwise.
Definition RealTensor2.H:259
Real contract(const RealTensor2 &a) const
Compute the contraction of this tensor with another tensor.
Definition RealTensor2.H:408
RealTensor2 & operator+=(const Real a)
Add a scalar to the RealTensor2 elementwise.
Definition RealTensor2.H:158
RealTensor2 operator-() const
Return the negative of a RealTensor2.
Definition RealTensor2.H:141
RealTensor2 & operator*=(const Real a)
Multiply a scalar by the RealTensor2 elementwise.
Definition RealTensor2.H:178
void transpose()
Transpose this tensor in place.
Definition RealTensor2.H:469
Real mag() const
Computes the magnitude of the vector.
Definition Vec3.H:470
auto cross(const Vec3< U > &a) const -> Vec3< decltype(this->v[0]+a[0])>
Returns the cross product of this vector with another vector.
Definition Vec3.H:585
void normalize()
Normalizes this vector to have unit length.
Definition Vec3.H:491
The primary namespace for criptic objects.
Definition AdvancePacket.H:25
criptic::RealTensor2 operator-(const criptic::Real a, const criptic::RealTensor2 &t)
Subtract a scalar from a RealTensor2 elementwise.
Definition RealTensor2.H:847
static const criptic::RealTensor2 identityTensor(1, 0, 0, 0, 1, 0, 0, 0, 1)
TNBBasis TNBVectors(const RealVec &v, const RealTensor2 &vGrad)
Compute tangent, normal, and binormal vectors.
Definition RealTensor2.H:913
criptic::RealTensor2 outer(const criptic::RealVec &v1, const criptic::RealVec &v2)
Compute the outer product of two RealVec objects.
Definition RealTensor2.H:887
criptic::RealTensor2 operator+(const criptic::Real a, const criptic::RealTensor2 &t)
Add a scalar and a RealTensor2 elementwise.
Definition RealTensor2.H:834
criptic::RealTensor2 operator/(const criptic::Real a, const criptic::RealTensor2 &t)
Divide a RealTensor2 by a scalar elementwise.
Definition RealTensor2.H:873
double Real
Definition Types.H:38
static const criptic::RealTensor2 zeroTensor(0, 0, 0, 0, 0, 0, 0, 0, 0)
criptic::FieldQty operator*(const criptic::Real a, const criptic::FieldQty &fq)
Multiply a scalar by a FieldQty elementwise.
Definition FieldQty.H:250
Structure to hold TNB basis data.
Definition RealTensor2.H:898
RealVec eB
Definition RealTensor2.H:901
RealVec eN
Definition RealTensor2.H:900
RealVec eT
Definition RealTensor2.H:899