677{
678 ScalarT cxx = tensor[K_S_XX];
679 ScalarT cyy = tensor[K_S_YY];
680 ScalarT czz = tensor[K_S_ZZ];
681 const ScalarT& cxy = tensor[K_S_XY];
682 const ScalarT& cyz = tensor[K_S_YZ];
683 const ScalarT& czx = tensor[K_S_ZX];
684
685 const ScalarT c1 = (cxx + cyy + czz) / ScalarT(3.0);
686
687 cxx -= c1;
688 cyy -= c1;
689 czz -= c1;
690
691 const ScalarT cxy_cxy = cxy * cxy;
692 const ScalarT cyz_cyz = cyz * cyz;
693 const ScalarT czx_czx = czx * czx;
694 const ScalarT cxx_cyy = cxx * cyy;
695
696 const ScalarT c2 = cxx_cyy + cyy * czz + czz * cxx - cxy_cxy - cyz_cyz - czx_czx;
697
698 const ScalarT ThreeOverA = ScalarT(-3.0) / c2;
699 const ScalarT sqrtThreeOverA = std::sqrt(ThreeOverA);
700
701 const ScalarT c3 = cxx * cyz_cyz + cyy * czx_czx - ScalarT(2.0) * cxy * cyz * czx + czz * (cxy_cxy - cxx_cyy);
702
703 const ScalarT rr = ScalarT(-0.5) * c3 * ThreeOverA * sqrtThreeOverA;
704
705 const ScalarT arg =
Minimum(std::abs(rr), ScalarT(1.0));
706
708
709 const ScalarT two_cos_thd3 = ScalarT(2.0) *
MultiplySign(cos_thd3, rr);
710
711 eval2 = two_cos_thd3 / sqrtThreeOverA;
712
713 ScalarT crow0[3] = {cxx - eval2, cxy, czx};
714 ScalarT crow1[3] = {cxy, cyy - eval2, cyz};
715 ScalarT crow2[3] = {czx, cyz, czz - eval2};
716
717
718
719
720 const ScalarT k0 = crow0[0] * crow0[0] + cxy_cxy + czx_czx;
721 const ScalarT k1 = cxy_cxy + crow1[1] * crow1[1] + cyz_cyz;
722 const ScalarT k2 = czx_czx + cyz_cyz + crow2[2] * crow2[2];
723
724 ScalarT k_row1[3];
725 ScalarT row2[3];
726 ScalarT row3[3];
727
728
729 const bool k0gk1 = k1 <= k0;
730 const bool k0gk2 = k2 <= k0;
731 const bool k1gk2 = k2 <= k1;
732
733 const bool k0_largest = k0gk1 && k0gk2;
734 const bool k1_largest = k1gk2 && !k0gk1;
735 const bool k2_largest = !(k0_largest || k1_largest);
736
739
742
745
749
753
756
757 const ScalarT ki_dpr1 = ki_ki * (k_row1[0] * row2[0] + k_row1[1] * row2[1] + k_row1[2] * row2[2]);
758 const ScalarT ki_dpr2 = ki_ki * (k_row1[0] * row3[0] + k_row1[1] * row3[1] + k_row1[2] * row3[2]);
759
760 row2[0] -= ki_dpr1 * k_row1[0];
761 row2[1] -= ki_dpr1 * k_row1[1];
762 row2[2] -= ki_dpr1 * k_row1[2];
763
764 row3[0] -= ki_dpr2 * k_row1[0];
765 row3[1] -= ki_dpr2 * k_row1[1];
766 row3[2] -= ki_dpr2 * k_row1[2];
767
768 const ScalarT a0 = row2[0] * row2[0] + row2[1] * row2[1] + row2[2] * row2[2];
769 const ScalarT a1 = row3[0] * row3[0] + row3[1] * row3[1] + row3[2] * row3[2];
770
771 ScalarT a_row2[3];
772
773 const bool a0lea1 = a0 <= a1;
774
778 const ScalarT ai_ai = ScalarT(1.0) /
if_then_else(a0lea1, a1, a0);
779
780 evec2[K_X] = k_row1[1] * a_row2[2] - k_row1[2] * a_row2[1];
781 evec2[K_Y] = k_row1[2] * a_row2[0] - k_row1[0] * a_row2[2];
782 evec2[K_Z] = k_row1[0] * a_row2[1] - k_row1[1] * a_row2[0];
783
784 const ScalarT k_atr11 = cxx * k_row1[0] + cxy * k_row1[1] + czx * k_row1[2];
785 const ScalarT k_atr21 = cxy * k_row1[0] + cyy * k_row1[1] + cyz * k_row1[2];
786 const ScalarT k_atr31 = czx * k_row1[0] + cyz * k_row1[1] + czz * k_row1[2];
787
788 const ScalarT a_atr12 = cxx * a_row2[0] + cxy * a_row2[1] + czx * a_row2[2];
789 const ScalarT a_atr22 = cxy * a_row2[0] + cyy * a_row2[1] + cyz * a_row2[2];
790 const ScalarT a_atr32 = czx * a_row2[0] + cyz * a_row2[1] + czz * a_row2[2];
791
792 ScalarT rm2xx = (k_row1[0] * k_atr11 + k_row1[1] * k_atr21 + k_row1[2] * k_atr31) * ki_ki;
793 const ScalarT k_a_rm2xy = (k_row1[0] * a_atr12 + k_row1[1] * a_atr22 + k_row1[2] * a_atr32);
794 ScalarT rm2yy = (a_row2[0] * a_atr12 + a_row2[1] * a_atr22 + a_row2[2] * a_atr32) * ai_ai;
795 const ScalarT rm2xy_rm2xy = k_a_rm2xy * k_a_rm2xy * ai_ai * ki_ki;
796
797
798
799
800 const ScalarT b = ScalarT(0.5) * (rm2xx - rm2yy);
801 const ScalarT sqrtTerm =
MultiplySign(std::sqrt(b * b + rm2xy_rm2xy), b);
802 eval0 = rm2yy + b - sqrtTerm;
803
804 eval1 = rm2xx + rm2yy - eval0;
805
806 rm2xx -= eval0;
807 rm2yy -= eval0;
808
809 const ScalarT rm2xx2 = rm2xx * rm2xx;
810 const ScalarT rm2yy2 = rm2yy * rm2yy;
811
812 const ScalarT fac1 =
if_then_else(rm2xx2 < rm2yy2, k_a_rm2xy * ai_ai, rm2xx);
813 const ScalarT fac2 =
if_then_else(rm2xx2 < rm2yy2, rm2yy, ki_ki * k_a_rm2xy);
814
815 evec0[0] = fac1 * a_row2[0] - fac2 * k_row1[0];
816 evec0[1] = fac1 * a_row2[1] - fac2 * k_row1[1];
817 evec0[2] = fac1 * a_row2[2] - fac2 * k_row1[2];
818
819 const bool rm2xx2iszero = rm2xx2 == ScalarT(0.0);
820 const bool rm2xy_rm2xyiszero = rm2xy_rm2xy == ScalarT(0.0);
821 const bool both_zero = rm2xx2iszero && rm2xy_rm2xyiszero;
822
823
824 evec0[0] =
if_then_else(both_zero, a_row2[0], evec0[0]);
825 evec0[1] =
if_then_else(both_zero, a_row2[1], evec0[1]);
826 evec0[2] =
if_then_else(both_zero, a_row2[2], evec0[2]);
827
828 evec1[K_X] = evec2[K_Y] * evec0[K_Z] - evec2[K_Z] * evec0[K_Y];
829 evec1[K_Y] = evec2[K_Z] * evec0[K_X] - evec2[K_X] * evec0[K_Z];
830 evec1[K_Z] = evec2[K_X] * evec0[K_Y] - evec2[K_Y] * evec0[K_X];
831
832 eval0 += c1;
833 eval1 += c1;
834 eval2 += c1;
835
836 const ScalarT c2tol = (c1 * c1) * (-1.0e-30);
837
838 const bool c2lsmall_neg = c2 < c2tol;
839
843
844 evec0[0] =
if_then_else(c2lsmall_neg, evec0[0], ScalarT(1.0));
845 evec0[1] =
if_then_else(c2lsmall_neg, evec0[1], ScalarT(0.0));
846 evec0[2] =
if_then_else(c2lsmall_neg, evec0[2], ScalarT(0.0));
847
848 evec1[0] =
if_then_else(c2lsmall_neg, evec1[0], ScalarT(0.0));
849 evec1[1] =
if_then_else(c2lsmall_neg, evec1[1], ScalarT(1.0));
850 evec1[2] =
if_then_else(c2lsmall_neg, evec1[2], ScalarT(0.0));
851
852 evec2[0] =
if_then_else(c2lsmall_neg, evec2[0], ScalarT(0.0));
853 evec2[1] =
if_then_else(c2lsmall_neg, evec2[1], ScalarT(0.0));
854 evec2[2] =
if_then_else(c2lsmall_neg, evec2[2], ScalarT(1.0));
855
856 return;
857}
NIMBLE_INLINE_FUNCTION ScalarT Cos_Of_Acos_Divided_By_3(const ScalarT x)
Pade approximation to cos( acos(x)/3 )
Definition nimble_utils.h:652
NIMBLE_INLINE_FUNCTION ScalarT if_then_else(const bool b, const ScalarT v1, const ScalarT v2)
Definition nimble_utils.h:155
NIMBLE_INLINE_FUNCTION ScalarT if_then_else_zero(const bool b, const ScalarT v)
Definition nimble_utils.h:162
NIMBLE_INLINE_FUNCTION ScalarT Minimum(const ScalarT x, const ScalarT y)
Definition nimble_utils.h:141
NIMBLE_INLINE_FUNCTION ScalarT MultiplySign(const ScalarT x, const ScalarT y)
Return x times sign of y.
Definition nimble_utils.h:134