diff --git a/NonLinearSolver/internalPoints/ipField.cpp b/NonLinearSolver/internalPoints/ipField.cpp
index cad06a1bdb708f3a9e133d133d7ee0a5286b3dd7..bbbe9e24b9763e827506ec81c5ea158c46b246a5 100644
--- a/NonLinearSolver/internalPoints/ipField.cpp
+++ b/NonLinearSolver/internalPoints/ipField.cpp
@@ -1041,6 +1041,16 @@ std::string IPField::ToString(const int i){
   else if (i == corKir_XY) return "corKir_XY";
   else if (i == corKir_XZ) return "corKir_XZ";
   else if (i == corKir_YZ) return "corKir_YZ";
+  else if (i == mandel_XX) return "mandel_XX";
+  else if (i == mandel_YY) return "mandel_YY";
+  else if (i == mandel_ZZ) return "mandel_ZZ";
+  else if (i == mandel_XY) return "mandel_XY";
+  else if (i == mandel_XZ) return "mandel_XZ";
+  else if (i == mandel_YZ) return "mandel_YZ";
+  else if (i == mandel_YX) return "mandel_YX";
+  else if (i == mandel_ZX) return "mandel_ZX";
+  else if (i == mandel_ZY) return "mandel_ZY";
+  else if (i == mandelCommuteChecker) return "mandelCommuteChecker";
   else if (i == corKirExtra_XX) return "corKirExtra_XX";
   else if (i == corKirExtra_YY) return "corKirExtra_YY";
   else if (i == corKirExtra_ZZ) return "corKirExtra_ZZ";
diff --git a/NonLinearSolver/internalPoints/ipField.h b/NonLinearSolver/internalPoints/ipField.h
index 9804de242a5b0f85fc8ddbf05bd849c3b8512d69..1c6bdb3b7a97bca82976ae75363f54807d21185f 100644
--- a/NonLinearSolver/internalPoints/ipField.h
+++ b/NonLinearSolver/internalPoints/ipField.h
@@ -323,7 +323,7 @@ class IPField : public elementsField {
                     Ee_XX, Ee_YY,  Ee_ZZ, Ee_XY, Ee_XZ, Ee_YZ,
                     Eve1_XX, Eve1_YY,  Eve1_ZZ, Eve1_XY, Eve1_XZ, Eve1_YZ,
                     Eve2_XX, Eve2_YY,  Eve2_ZZ, Eve2_XY, Eve2_XZ, Eve2_YZ,
-                    corKir_XX, corKir_YY, corKir_ZZ, corKir_XY, corKir_XZ, corKir_YZ,
+                    corKir_XX, corKir_YY, corKir_ZZ, corKir_XY, corKir_XZ, corKir_YZ, mandel_XX, mandel_YY, mandel_ZZ, mandel_XY, mandel_XZ, mandel_YZ, mandel_YX, mandel_ZX, mandel_ZY, mandelCommuteChecker,
                     corKirExtra_XX, corKirExtra_YY, corKirExtra_ZZ, corKirExtra_XY, corKirExtra_XZ, corKirExtra_YZ,
                     Dev_corKir_Inf_XX, Dev_corKir_Inf_YY, Dev_corKir_Inf_ZZ, Dev_corKir_Inf_XY, Dev_corKir_Inf_XZ, Dev_corKir_Inf_YZ, Tr_corKir_Inf,
                     hyperElastic_BulkScalar,hyperElastic_ShearScalar,
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.cpp b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
index 80e933732a4f4bbb42238953287a40a25a6707fd..dfabd5fc5a4c9b501aff7ec2b19f4d318985d4ef 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.cpp
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
@@ -15,14 +15,15 @@
 
 IPHyperViscoElastic::IPHyperViscoElastic(const int N):IPVariableMechanics(),_N(N),_elasticEnergy(0.),_Ee(0.),_kirchhoff(0.),
       _irreversibleEnergy(0.),_DirreversibleEnergyDF(0.), _viscousEnergyPart(0.), _dElasticEnergyPartdF(0.), _dViscousEnergyPartdF(0.), _elasticBulkPropertyScaleFactor(1.), _elasticShearPropertyScaleFactor(1.),
-	  _intA(0.), _intB(0.), _DintA(0.), _DintB(0.)
+	  _intA(0.), _intB(0.), _DintA(0.), _DintB(0.), _Re(0.), _Re0(0.), _Ee0(0.)
 {
-  _A.clear();
+  _A.clear(); _A_rot.clear();
   _B.clear();
   _psi_branch.clear();
   for (int i=0; i< N; i++){
     STensor3 el(0.);
     _A.push_back(el);
+    _A_rot.push_back(el);
     _B.push_back(0.);
     _psi_branch.push_back(0.);
   }
@@ -32,7 +33,7 @@ IPHyperViscoElastic::IPHyperViscoElastic(const IPHyperViscoElastic& src): IPVari
     _irreversibleEnergy(src._irreversibleEnergy),_DirreversibleEnergyDF(src._DirreversibleEnergyDF),
     _viscousEnergyPart(src._viscousEnergyPart), _dElasticEnergyPartdF(src._dElasticEnergyPartdF), 
     _dViscousEnergyPartdF(src._dViscousEnergyPartdF), _elasticBulkPropertyScaleFactor(src._elasticBulkPropertyScaleFactor), _elasticShearPropertyScaleFactor(src._elasticShearPropertyScaleFactor),
-	_intA(src._intA),_intB(src._intB), _psi_branch(src._psi_branch), _DintA(src._DintA),_DintB(src._DintB)
+	_intA(src._intA),_intB(src._intB), _psi_branch(src._psi_branch), _DintA(src._DintA),_DintB(src._DintB), _A_rot(src._A_rot), _Re(src._Re), _Re0(src._Re0), _Ee0(src._Ee0)
 
 {
 
@@ -60,6 +61,10 @@ IPHyperViscoElastic& IPHyperViscoElastic::operator =(const IPVariable& src){
     _DintA= psrc->_DintA;
     _DintB= psrc->_DintB;
     _psi_branch= psrc->_psi_branch;
+    _A_rot=psrc->_A_rot;
+    _Re=psrc->_Re;
+    _Re0=psrc->_Re0;
+    _Ee0=psrc->_Ee0;
   }
   return *this;
 };
@@ -84,6 +89,10 @@ void IPHyperViscoElastic::restart() {
   restartManager::restart(_DintA);
   restartManager::restart(_DintB);
   restartManager::restart(_psi_branch);
+  restartManager::restart(_A_rot);
+  restartManager::restart(_Re);
+  restartManager::restart(_Re0);
+  restartManager::restart(_Ee0);
 };
 
 void IPHyperViscoElastic::getViscoElasticStrain(int i, STensor3& Ev) const
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.h b/NonLinearSolver/internalPoints/ipHyperelastic.h
index e1ccba37b8d58702163381fc7aaf4aa286c91424..5ec1b777bb9234638dba16c5c106bcd665de384c 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.h
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.h
@@ -20,11 +20,14 @@ class IPHyperViscoElastic : public IPVariableMechanics{
   public:
     //viscoelastic history
     int _N; // number spring-Dashpot of element
-    std::vector<STensor3> _A; // N elements
+    std::vector<STensor3> _A, _A_rot; // N elements
     std::vector<double> _B; // N elements
     double _elasticEnergy; // elastic energy stored
     STensor3 _Ee; // elastic strain
     STensor3 _kirchhoff; // corotational Kirchhoff stress
+    STensor3 _Re; // rotation tensor: Fe = Re . Ue
+    STensor3 _Re0; // rotation tensor: Fe0 = Re0 . Ue0
+    STensor3 _Ee0; // rotation tensor: Fe0 = Re0 . Ue0
 
     double _irreversibleEnergy;
     STensor3 _DirreversibleEnergyDF;
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp
index be3d6fa710da72276bb524fffa4f80dee755e31a..2add8a286b6acb57644da770eb524c9b0daa8e65 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp
@@ -21,7 +21,8 @@ IPNonLinearTVM::IPNonLinearTVM(const J2IsotropicHardening* comp,
                      _psiMax(0.), _mullinsDamage(0.), _DpsiDT(0.), _DpsiDE(0.), _DmullinsDamage_Dpsi_cap(0.), _DmullinsDamage_DT(0.), _P_cap(0.),
                      _pressure(0.), _Av_TVE(1.), _Bd_TVE(1.), _dAv_dTrEe(0.), _dBd_dTrEe(0.), _dAv_dTrEe_TVE(0.), _intAv_TVE(0.), _intBd_TVE(0.), 
                      _intAv_1_TVE(0.), _intBd_1_TVE(0.), _intAv_2_TVE(0.), _intBd_2_TVE(0.), _dBd_dDevEe(0.), _dBd_dDevEe_TVE(0.),
-                     _viscousDissipatedEnergy(0.), _mullinsDissipatedEnergy(0.), _psiInfCorrector(0.){
+                     _viscousDissipatedEnergy(0.), _mullinsDissipatedEnergy(0.), _psiInfCorrector(0.), _ModMandel(0.), _mandelCommuteChecker(0.),
+					 _R(0.),_dRdEe(0.),_dRtdEe(0.){
         
     _DA_DT.clear(); _DDA_DTT.clear(); 
     _DA_DtrE.clear(); _DDA_DTDtrE.clear();
@@ -80,7 +81,8 @@ IPNonLinearTVM::IPNonLinearTVM(const IPNonLinearTVM& src): IPHyperViscoElastoPla
             _Av_TVE_vector(src._Av_TVE_vector), _Bd_TVE_vector(src._Bd_TVE_vector), _dAv_dTrEe_TVE_vector(src._dAv_dTrEe_TVE_vector), _dBd_dTrEe_TVE_vector(src._dBd_dTrEe_TVE_vector),
             _intAv_TVE_vector(src._intAv_TVE_vector), _intBd_TVE_vector(src._intBd_TVE_vector),_DintAv_TVE_vector(src._DintAv_TVE_vector), _DintBd_TVE_vector(src._DintBd_TVE_vector),
 			_dBd_dDevEe_TVE_vector(src._dBd_dDevEe_TVE_vector),
-            _viscousDissipatedEnergy(src._viscousDissipatedEnergy), _mullinsDissipatedEnergy(src._mullinsDissipatedEnergy), _psiInfCorrector(src._psiInfCorrector){
+            _viscousDissipatedEnergy(src._viscousDissipatedEnergy), _mullinsDissipatedEnergy(src._mullinsDissipatedEnergy), _psiInfCorrector(src._psiInfCorrector),
+			_ModMandel(src._ModMandel), _mandelCommuteChecker(src._mandelCommuteChecker),_R(src._R),_dRdEe(src._dRdEe),_dRtdEe(src._dRtdEe){
                 
     if (src._ipMullinsEffect != NULL)
         _ipMullinsEffect = dynamic_cast<IPMullinsEffect*>(src._ipMullinsEffect->clone());
@@ -153,6 +155,11 @@ IPNonLinearTVM& IPNonLinearTVM::operator=(const IPVariable& src)
     _viscousDissipatedEnergy = psrc->_viscousDissipatedEnergy;
     _mullinsDissipatedEnergy = psrc->_mullinsDissipatedEnergy;
     _psiInfCorrector = psrc->_psiInfCorrector;
+    _ModMandel = psrc->_ModMandel;
+    _mandelCommuteChecker = psrc->_mandelCommuteChecker;
+    _R = psrc->_R;
+    _dRdEe = psrc->_dRdEe;
+    _dRtdEe = psrc->_dRtdEe;
     
     if ( psrc->_ipMullinsEffect != NULL) {
       if (_ipMullinsEffect == NULL){
@@ -239,6 +246,11 @@ void IPNonLinearTVM::restart(){
   restartManager::restart(_viscousDissipatedEnergy);
   restartManager::restart(_mullinsDissipatedEnergy);
   restartManager::restart(_psiInfCorrector);
+  restartManager::restart(_ModMandel);
+  restartManager::restart(_mandelCommuteChecker);
+  restartManager::restart(_R);
+  restartManager::restart(_dRdEe);
+  restartManager::restart(_dRtdEe);
   
   if (_ipMullinsEffect != NULL)
    restartManager::restart(_ipMullinsEffect);
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVM.h b/NonLinearSolver/internalPoints/ipNonLinearTVM.h
index 755f0cdd36d5d89c68c2e58fa3701882acad9aa9..0d77fe80ea600c632c1f7aa3d8df92d21946524e 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVM.h
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVM.h
@@ -30,6 +30,10 @@ class IPNonLinearTVM : public IPHyperViscoElastoPlastic{
         double _DmechSrcTVEdT;
         STensor3 _DmechSrcTVEdE;
         
+        // mandel and commuteChecker
+        STensor3 _ModMandel;
+        double _mandelCommuteChecker;
+
         // CorKir - Inf and extraBranch TVE
         double _trCorKirinf_TVE;
         STensor3 _devCorKirinf_TVE;
@@ -74,6 +78,11 @@ class IPNonLinearTVM : public IPHyperViscoElastoPlastic{
         double _viscousDissipatedEnergy;
         double _mullinsDissipatedEnergy;
         
+        // Rotation tensors & derivatives
+        STensor3 _R;
+        STensor43 _dRdEe, _dRtdEe;
+
+
     public:
         IPNonLinearTVM(const J2IsotropicHardening* comp,
                     const J2IsotropicHardening* trac,
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
index aec94de8f42fb64858adc4c1ded5468450f67901..79f7847a74c358e5f607c4fdc858e8edbc9b5553 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
@@ -15,7 +15,7 @@ IPNonLinearTVP::IPNonLinearTVP(const J2IsotropicHardening* comp, const J2Isotrop
                                 const kinematicHardening* kin, const int N, const mullinsEffect* mullins):IPNonLinearTVM(comp,trac,kin,N,mullins),
                                 _DgammaDT(0.),_DGammaDT(0.), _DGammaDF(0.), _DirreversibleEnergyDT(0.),
                                 _psiTVM(0.), _DpsiTVMdT(0.), _DDpsiTVMdTT(0.),
-                                _ModMandel(0.),_DModMandelDT(0.), _DbackSigDT(0.), _DModMandelDF(0.), _DbackSigDF(0.), _DphiPDF(0.), _GammaN(0.), _dGammaNdT(0.), _dGammaNdF(0.),
+								_DModMandelDT(0.), _DbackSigDT(0.), _DModMandelDF(0.), _DbackSigDF(0.), _DphiPDF(0.), _GammaN(0.), _dGammaNdT(0.), _dGammaNdF(0.),
                                 _mechSrcTVP(0.),_DmechSrcTVPdT(0.),_DmechSrcTVPdF(0.),
                                 _dPlasticEnergyPartdT(0.),_dElasticEnergyPartdT(0.),_dViscousEnergyPartdT(0.),
                                 _IsoHardForce_simple(0.), _dIsoHardForcedT_simple(0.), _dIsoHardForcedF_simple(0.), _DphiDF(0.),_DphiDT(0.)
@@ -38,7 +38,7 @@ IPNonLinearTVP::IPNonLinearTVP(const IPNonLinearTVP& src):IPNonLinearTVM(src),
                                 _ddIsoHardForcedTT(src._ddIsoHardForcedTT),
                                 _psiTVM(src._psiTVM), _DpsiTVMdT(src._DpsiTVMdT), _DDpsiTVMdTT(src._DDpsiTVMdTT),
                                 _mechSrcTVP(src._mechSrcTVP),_DmechSrcTVPdT(src._DmechSrcTVPdT),_DmechSrcTVPdF(src._DmechSrcTVPdF),
-                                _ModMandel(src._ModMandel), _DModMandelDT(src._DModMandelDT), _DbackSigDT(src._DbackSigDT), _DphiPDF(src._DphiPDF),
+                                _DModMandelDT(src._DModMandelDT), _DbackSigDT(src._DbackSigDT), _DphiPDF(src._DphiPDF),
                                 _GammaN(src._GammaN), _dGammaNdT(src._dGammaNdT), _dGammaNdF(src._dGammaNdF),
                                 _DModMandelDF(src._DModMandelDF), _DbackSigDF(src._DbackSigDF),
                                 _dPlasticEnergyPartdT(src._dPlasticEnergyPartdT),_dElasticEnergyPartdT(src._dElasticEnergyPartdT),
@@ -69,7 +69,6 @@ IPNonLinearTVP& IPNonLinearTVP::operator =(const IPVariable &source){
     _mechSrcTVP = ps->_mechSrcTVP;
     _DmechSrcTVPdT = ps->_DmechSrcTVPdT;
     _DmechSrcTVPdF = ps->_DmechSrcTVPdF;
-    _ModMandel = ps->_ModMandel;
     _DModMandelDT = ps->_DModMandelDT;
     _DModMandelDF = ps->_DModMandelDF;
     _DbackSigDT = ps->_DbackSigDT;
@@ -111,7 +110,6 @@ void IPNonLinearTVP::restart() {
   restartManager::restart(_mechSrcTVP);
   restartManager::restart(_DmechSrcTVPdT);
   restartManager::restart(_DmechSrcTVPdF);
-  restartManager::restart(_ModMandel);
   restartManager::restart(_DModMandelDT);
   restartManager::restart(_DModMandelDF);
   restartManager::restart(_DbackSigDT);
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.h b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
index 8cc1e9aed6195f5003e2f9345e44321baec0b579..750c5bb400b4a38a029cef3a1a4ae8541f39d9cf 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVP.h
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
@@ -39,7 +39,6 @@ class IPNonLinearTVP : public IPNonLinearTVM{
         double _DDpsiTVMdTT; 
         
         STensor3 _DGammaDF;
-        STensor3 _ModMandel;
         STensor3 _DModMandelDT;
         STensor3 _DbackSigDT;
         STensor3 _DphiDT;
diff --git a/NonLinearSolver/materialLaw/CMakeLists.txt b/NonLinearSolver/materialLaw/CMakeLists.txt
index 341ace0e973297e1d0654f9ac325875f6b289b94..bed4818d58f43a62c966e84079fdc99d77bc8d92 100644
--- a/NonLinearSolver/materialLaw/CMakeLists.txt
+++ b/NonLinearSolver/materialLaw/CMakeLists.txt
@@ -107,6 +107,7 @@ set(SRC
   mlawNonLinearTVE.cpp
   mlawNonLinearTVP.cpp
   mlawNonLinearTVENonLinearTVP.cpp
+  mlawNonLinearTVENonLinearTVP2.cpp
   mlawCoupledThermoMechanics.cpp
   mullinsEffect.cpp
   mlawHyperelasticWithPotential.cpp
diff --git a/NonLinearSolver/materialLaw/STensorOperations.cpp b/NonLinearSolver/materialLaw/STensorOperations.cpp
index 528c234ad730164c81e23deca9458421b9d17b88..59c2e516af09e8daf095e5fa11ee9cbe3543b6e0 100644
--- a/NonLinearSolver/materialLaw/STensorOperations.cpp
+++ b/NonLinearSolver/materialLaw/STensorOperations.cpp
@@ -362,17 +362,17 @@ void STensorOperation::expSTensor3(const STensor3& a, const int order, STensor3&
 }
 
 void STensorOperation::getEigenDecomposition(const STensor3& a, double& x1, double& x2, double& x3, STensor3& E1, STensor3& E2, STensor3& E3, 
-                                    STensor3& dx1da, STensor3& dx2da, STensor3& dx3da, STensor43& dE1da, STensor43& dE2da, STensor43& dE3da)
-{
-   getEigenDecomposition(a, x1, x2, x3, E1, E2, E3);
+                                    STensor3& dx1da, STensor3& dx2da, STensor3& dx3da, STensor43& dE1da, STensor43& dE2da, STensor43& dE3da){
+
+	getEigenDecomposition(a, x1, x2, x3, E1, E2, E3);
    
+   /*
    double x1p,x2p,x3p,x1m,x2m,x3m;
    static STensor3 E1p,E2p,E3p, E1m,E2m, E3m, ap, am;
    double pert=1.e-9;
-   for(int i=0; i<3; i++)
-   {
-     for(int j=0; j<3; j++)
-     {
+
+   for(int i=0; i<3; i++){
+     for(int j=0; j<3; j++){
        ap=a;
        am=a;
        ap(i,j)=ap(i,j)+pert;
@@ -392,10 +392,231 @@ void STensorOperation::getEigenDecomposition(const STensor3& a, double& x1, doub
          }
        }
      }
-   }
+   }*/
+
+   double tr = a.trace();
+   double det = STensorOperation::determinantSTensor3(a);
+   static STensor3 ainv, dI3da;
+   STensorOperation::inverseSTensor3(a,ainv);
+   dI3da = ainv;
+   dI3da *= det;
+
+   const STensor43 I4(1.,1.);
+   static STensor43 dainvda;
+   for (int i=0; i<3; i++)
+       for (int s=0; s<3; s++)
+           for (int k=0; k<3; k++)
+               for (int l=0; l<3; l++){
+            	   dainvda(i,s,k,l) = 0.;
+                   for (int m=0; m<3; m++)
+                       for (int j=0; j<3; j++)
+                    	   dainvda(i,s,k,l) -= ainv(i,m)*I4(m,j,k,l)*ainv(j,s);
+     }
+
+   dx1da = E1;
+   dx2da = E2;
+   dx3da = E3;
+
+   double D1(0.),D2(0.),D3(0.);
+   static STensor3 dD1da, dD2da, dD3da;
+   STensorOperation::subMember_getEigenDecomposition_getDi(x1,tr,det,dx1da,dI3da,D1,dD1da);
+   STensorOperation::subMember_getEigenDecomposition_getDi(x2,tr,det,dx2da,dI3da,D2,dD2da);
+   STensorOperation::subMember_getEigenDecomposition_getDi(x3,tr,det,dx3da,dI3da,D3,dD3da);
+   STensorOperation::subMember_getEigenDecomposition_getdEidC(E1,x1,det,D1,ainv,dx1da,dainvda,dI3da,dD1da,dE1da);
+   STensorOperation::subMember_getEigenDecomposition_getdEidC(E2,x2,det,D2,ainv,dx2da,dainvda,dI3da,dD2da,dE2da);
+   STensorOperation::subMember_getEigenDecomposition_getdEidC(E3,x3,det,D3,ainv,dx3da,dainvda,dI3da,dD3da,dE3da);
+
 }                                  
 
+void STensorOperation::getBasisRotationTensor(const STensor3& A, const STensor3& B, STensor3& R, STensor43& dRdB, STensor43& dRtdB){
+
+	// Only for single-legged symmetric tensors A and B -> leftEigenVect = rightEigenVect and eigenvals are always real
+	// R rotates the bases of A to that of B, so R = R_(ba), i.e., R = sum (eb * ea)
+	// B = R*A*Rt
+
+  static fullMatrix<double> m1(3, 3), m2(3, 3);
+  static fullVector<double> eigenValReal1(3), eigenValReal2(3), AlignedEigenValReal1(3);
+  static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+  static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+  static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), AlignedRightEigenVect1(3,3);
+  m1.setAll(0.); m2.setAll(0.);
+  eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); AlignedEigenValReal1.setAll(0.);
+  eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+  leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+  rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+
+  // Get eigen values and vectors
+  A.getMat(m1); B.getMat(m2);
+  m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+  m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+  // Make sure rightEigenVect1 is aligned with rightEigenVect2
+  // STensorOperation::alignEigenDecomposition_EigenVectorDotProductBased(eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2,AlignedEigenValReal1,AlignedRightEigenVect1);
+  double a1_align, a2_align, a3_align;
+  STensorOperation::alignEigenDecomposition_NormBased(A,B,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2,  a1_align, a2_align, a3_align, AlignedRightEigenVect1);
+  rightEigenVect1 = AlignedRightEigenVect1;
+
+  STensorOperation::zero(R);
+  for(int i=0; i<3; i++)
+    for(int j=0; j<3; j++)
+      R(i,j) += rightEigenVect2(i,0)*rightEigenVect1(j,0) + rightEigenVect2(i,1)*rightEigenVect1(j,1) + rightEigenVect2(i,2)*rightEigenVect1(j,2);
+
+  static STensor33 de0dB, de1dB, de2dB;
+  STensorOperation::getEigenDecomposition_getdeidC(rightEigenVect2,eigenValReal2(0),eigenValReal2(1),eigenValReal2(2),de0dB,de1dB,de2dB);
+
+  STensorOperation::zero(dRdB); STensorOperation::zero(dRtdB);
+	for(int i=0; i<3; i++)
+	  for(int j=0; j<3; j++)
+		for (int k=0; k<3; k++)
+		  for (int l=0; l<3; l++){
+			dRdB(i,j,k,l) +=  de0dB(i,k,l)*rightEigenVect1(j,0) + de1dB(i,k,l)*rightEigenVect1(j,1) + de2dB(i,k,l)*rightEigenVect1(j,2);
+			dRtdB(i,j,k,l) += de0dB(j,k,l)*rightEigenVect1(i,0) + de1dB(j,k,l)*rightEigenVect1(i,1) + de2dB(j,k,l)*rightEigenVect1(i,2);
+	      }
+
+	/*
+	// checkers
+	static STensor3 B1,B2,B3;
+	double b1,b2,b3;
+	static STensor43 dBdB; // must be I4(1.,1.)
+	STensorOperation::zero(dBdB);
+	STensorOperation::getEigenDecomposition(B,b1,b2,b3,B1,B2,B3);
+	for(int i=0; i<3; i++)
+	  for(int j=0; j<3; j++)
+		for (int k=0; k<3; k++)
+		  for (int l=0; l<3; l++){
+			dBdB(i,j,k,l) += B1(i,j)*B1(k,l) + B2(i,j)*B2(k,l) + B3(i,j)*B3(k,l) +
+      						b1*(de0dB(i,k,l)*rightEigenVect2(j,0) + de0dB(j,k,l)*rightEigenVect2(i,0)) +
+								b2*(de1dB(i,k,l)*rightEigenVect2(j,1) + de1dB(j,k,l)*rightEigenVect2(i,1)) +
+								b3*(de2dB(i,k,l)*rightEigenVect2(j,2) + de2dB(j,k,l)*rightEigenVect2(i,2));
+		  }*/
+}
+
+void STensorOperation::alignEigenDecomposition_NormBased_indexOnly(const STensor3& A, const STensor3& B, fullVector<int>& alignedIndex){
+  	  // Align A to B, where B is fixed
+
+	  	  // Initialise 1
+		  alignedIndex(0) = 0; alignedIndex(1) = 1; alignedIndex(2) = 2;
+		  static fullVector<double> eigenValReal1(3); eigenValReal1.setAll(0.);
+		  double a1,a2,a3,b1,b2,b3; // eigenvalues
+		  static STensor3 A1,A2,A3,B1,B2,B3; // bases
+
+		  // Get eigen and assign
+		  STensorOperation::getEigenDecomposition(A,a1,a2,a3,A1,A2,A3);
+		  STensorOperation::getEigenDecomposition(B,b1,b2,b3,B1,B2,B3);
+		  eigenValReal1(0) = a1; eigenValReal1(1) = a2; eigenValReal1(2) = a3;
+
+		  // Initialise 2
+	  	  double norm(0.), norm_min(1.e+20);
+	  	  static STensor3 A_reformed;
 
+	  	  // Generate permutated eigVal vector
+	  	  static fullVector<double> eigenValReal1_permuted(3);
+	  	  static fullVector<int> eigenValReal1_permuted_Index(3);
+	  	  for (int p=0; p<3; p++)
+	  		for (int q=0; q<3; q++){
+	  		  if(q!=p){
+	  			for (int r=0; r<3; r++){
+	  			  if(r!=p && r!=q){
+
+	  				zero(A_reformed);
+	  				for (int k=0; k<3; k++)
+	  				  for (int l=0; l<3; l++)
+	  		  		    A_reformed(k,l) += eigenValReal1(p)*B1(k,l) + eigenValReal1(q)*B2(k,l) + eigenValReal1(r)*B3(k,l);
+	  		  	    A_reformed -= A;
+	  		  	    doubleContractionSTensor3(A_reformed,A_reformed,norm);
+	  		  	    norm = pow(norm,0.5);
+
+	  		  	    if(norm < norm_min){      // if( ( - norm + norm_min)>1.e-6 )
+	  		  	    		norm_min = norm;
+	  			  		  	eigenValReal1_permuted(0) = eigenValReal1(p);
+	  			  		  	eigenValReal1_permuted_Index(0) = p;
+	  			  		  	eigenValReal1_permuted(1) = eigenValReal1(q);
+	  			  		  	eigenValReal1_permuted_Index(1) = q;
+	  			  		  	eigenValReal1_permuted(2) = eigenValReal1(r);
+	  			  		  	eigenValReal1_permuted_Index(2) = r;
+	  		  	    }
+	  			  }
+	  			}
+
+	  		  }
+	  		}
+
+	  	  // Assign the aligned indices
+	  	  alignedIndex = eigenValReal1_permuted_Index;
+  }
+
+
+void STensorOperation::alignEigenDecomposition_NormBased(const STensor3& A, const STensor3& B,
+		  	  	  	  	  	  	  	  	  	  	const double& b1, const double& b2, const double& b3, const STensor3& B1, const STensor3& B2, const STensor3& B3,
+												const fullVector<double> eigenValReal1, int& index1, int& index2, int& index3,
+												double& a1_align, double& a2_align, double& a3_align){
+  	  // Align 1 to 2, where 2 is fixed
+
+	  	  // Form the tensor
+	  	  double norm(0.), norm_min(1.e+20);
+	  	  static STensor3 A_reformed;
+
+	  	  // Generate permutated eigVal vector
+	  	  static fullVector<double> eigenValReal1_permuted(3);
+	  	  static fullVector<int> eigenValReal1_permuted_Index(3);
+	  	  for (int p=0; p<3; p++)
+	  		for (int q=0; q<3; q++){
+	  		  if(q!=p){
+	  			for (int r=0; r<3; r++){
+	  			  if(r!=p && r!=q){
+
+	  				zero(A_reformed);
+	  				for (int k=0; k<3; k++)
+	  				  for (int l=0; l<3; l++)
+	  		  		    A_reformed(k,l) += eigenValReal1(p)*B1(k,l) + eigenValReal1(q)*B2(k,l) + eigenValReal1(r)*B3(k,l);
+	  		  	    A_reformed -= A;
+	  		  	    doubleContractionSTensor3(A_reformed,A_reformed,norm);
+	  		  	    norm = pow(norm,0.5);
+
+	  		  	    if(norm < norm_min){      // if( ( - norm + norm_min)>1.e-6 )
+	  		  	    		norm_min = norm;
+	  			  		  	eigenValReal1_permuted(0) = eigenValReal1(p);
+	  			  		  	eigenValReal1_permuted_Index(0) = p;
+	  			  		  	eigenValReal1_permuted(1) = eigenValReal1(q);
+	  			  		  	eigenValReal1_permuted_Index(1) = q;
+	  			  		  	eigenValReal1_permuted(2) = eigenValReal1(r);
+	  			  		  	eigenValReal1_permuted_Index(2) = r;
+	  		  	    }
+	  			  }
+	  			}
+
+	  		  }
+	  		}
+
+	  	  /*
+	  	  // Get dotproducts of Eigen Vectors -> 3C1*3C1 possibilities
+	  	  static STensor3 dot1, theta1;
+	  	  zero(dot1);
+		  for (int k=0; k<3; k++)
+			for (int l=0; l<3; l++)
+			  for(int i=0; i<3; i++){
+				 dot1(k,l) += rightEigenVect1(k,i)*rightEigenVect2(l,i);
+			  }
+
+		  // Get angles
+		  double pi = 3.14159265358979323846;
+		  zero(theta1);
+		  for (int k=0; k<3; k++)
+			for (int l=0; l<3; l++){
+			  theta1(k,l) = acos(dot1(k,l)); // /(abs1(k)*abs2(l)));
+			  if (theta1(k,l) > pi/2) {
+				  theta1(k,l) = pi - theta1(k,l);
+			  }
+			}*/
+
+	  	  // Align the eigVals and eigVecs
+	  	  index1 = eigenValReal1_permuted_Index(0);
+	  	  index2 = eigenValReal1_permuted_Index(1);
+	  	  index3 = eigenValReal1_permuted_Index(2);
+	  	  a1_align = eigenValReal1_permuted(0);
+	  	  a2_align = eigenValReal1_permuted(1);
+	  	  a3_align = eigenValReal1_permuted(2);
+  }
 
 void STensorOperation::VRDecomposition(const STensor3& a, STensor3& V, STensor3&R)
 {
@@ -469,4 +690,20 @@ void STensorOperation::RUDecomposition(const STensor3& a, STensor3& U, STensor3&
 
 }
 
+/* TBD
+void STensorOperation::rotateTensorBasesMinimumEnergy(const STensor3& A, const STensor3& B, const STensor3& stress, STensor3& C){
+
+	double a1,a2,a3,b1,b2,b3;
+	static STensor3 A1,A2,A3,B1,B2,B3;
+	STensorOperation::getEigenDecompositionExplicitBase(A,a1,a2,a3,A1,A2,A3);
+	STensorOperation::getEigenDecompositionExplicitBase(B,b1,b2,b3,B1,B2,B3);
+
+	double initialEnergy = 0.;
+	STensorOperation::doubleContractionSTensor3(stress,A,initialEnergy);
+
+	static fullVector<double> A_eigVal(3);
+	A(0)=a1; A(1)=a2; A(2)=a3;
+
+}
+*/
 
diff --git a/NonLinearSolver/materialLaw/STensorOperations.h b/NonLinearSolver/materialLaw/STensorOperations.h
index 6b8bd995a58862a5c741da8f4fce4ed6baecc801..f807f40517e088db52a1ae6cf1a1b7eb5bc967e9 100644
--- a/NonLinearSolver/materialLaw/STensorOperations.h
+++ b/NonLinearSolver/materialLaw/STensorOperations.h
@@ -8,7 +8,7 @@
 #include "STensor63.h"
 #include "fullMatrix.h"
 #include <cmath>
-
+#include <algorithm>
 
 namespace STensorOperation{
   inline void zero(double& a){
@@ -1613,11 +1613,317 @@ namespace STensorOperation{
     }
   }
   
+  inline void getBasisRotationTensor(const STensor3& A, const STensor3& B, STensor3& R){
   
+	// Only for single-legged symmetric tensors A and B -> leftEigenVect = rightEigenVect and eigenvals are always real
+	// R rotates the bases of A to that of B, so R = R_(ba), i.e., R = sum (eb * ea)
+	// B = R*A*Rt
+
+    static fullMatrix<double> m1(3, 3), m2(3, 3);
+    static fullVector<double> eigenValReal1(3), eigenValReal2(3);
+    static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+    static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+    static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3);
+    m1.setAll(0.); m2.setAll(0.);
+    eigenValReal1.setAll(0.); eigenValReal2.setAll(0.);
+    eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+    leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+    rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.);
+
+    // Get eigen values and vectors
+    A.getMat(m1); B.getMat(m2);
+    m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+    m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+    zero(R);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        R(i,j) += rightEigenVect2(i,0)*rightEigenVect1(j,0) + rightEigenVect2(i,1)*rightEigenVect1(j,1) + rightEigenVect2(i,2)*rightEigenVect1(j,2);
+
+    /*
+    // checkers
+    static STensor3 check;
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++){
+    	 check(i,j) = 0.;
+    	 for(int k=0; k<3; k++)
+    	   for(int l=0; l<3; l++)
+    	     check(i,j) +=  R(i,k)*A(k,l)*R(j,l);
+      }
+
+    static fullMatrix<double> m(3, 3);
+    static fullVector<double> eigenValReal(3);
+    static fullVector<double> eigenValImag(3);
+    static fullMatrix<double> leftEigenVect(3,3);
+    static fullMatrix<double> rightEigenVect(3,3);
+    m.setAll(0.);
+    eigenValReal.setAll(0.);
+    eigenValImag.setAll(0.);
+    leftEigenVect.setAll(0.);
+    rightEigenVect.setAll(0.);
+
+    // Get eigen values and vectors
+    check.getMat(m);
+    m.eig(eigenValReal,eigenValImag,leftEigenVect,rightEigenVect,false);
+    */
+  }
+
+  void getBasisRotationTensor(const STensor3& A, const STensor3& B, STensor3& R, STensor43& dRdB, STensor43& dRtdB);
 
   void getEigenDecomposition(const STensor3& a, double& x1, double& x2, double& x3, STensor3& E1, STensor3& E2, STensor3& E3, 
                                     STensor3& dx1da, STensor3& dx2da, STensor3& dx3da, STensor43& dE1da, STensor43& dE2da, STensor43& dE3da);
 
+  inline void subMember_getEigenDecomposition_getDi(const double& xi, const double& tr, const double& det, const STensor3& dxidC, const STensor3& dI3dC, double& Di, STensor3& dDidC){
+	  // C is 42 tensor
+	  Di = 2*pow(xi,2) - tr*xi + det/xi;
+
+	  STensor3 I(1.);
+
+	  zero(dDidC);
+	  for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++)
+			  dDidC(i,j) += 4*xi*dxidC(i,j) - xi*I(i,j) - tr*dxidC(i,j) + dI3dC(i,j)*1/xi - (det/pow(xi,2))*dxidC(i,j);
+  }
+
+  inline void subMember_getEigenDecomposition_getdEidC(const STensor3& Ei, const double& xi, const double& det, const double& Di, const STensor3& Cinv, const STensor3& dxidC, const STensor43& dCinvdC,
+		  	  	  	  	  	  	  	  	  	  	  const STensor3& dI3dC, const STensor3& dDidC, STensor43& dEidC){
+	  // C is 42 tensor
+	  STensor3 I(1.);
+	  STensor43 I4(1.,1.);
+
+	  zero(dEidC);
+	  if(abs(xi)>0. && abs(Di)>0.){
+		  for(int i=0; i<3; i++)
+			  for(int j=0; j<3; j++)
+				  for (int k=0; k<3; k++)
+					  for (int l=0; l<3; l++){
+						  dEidC(i,j,k,l) += Ei(i,j)*dxidC(k,l)/xi
+								  + xi/Di*(I4(i,j,k,l) - I(i,j)*I(k,l) + I(i,j)*dxidC(k,l) + det*(1/xi*dCinvdC(i,j,k,l) - (1/pow(xi,2))*Cinv(i,j)*dxidC(k,l)) + 1/xi * Cinv(i,j)*dI3dC(k,l))
+					  	  	  	  	  - Ei(i,j)/Di*dDidC(k,l);
+					  }
+	  }
+  }
+
+  inline void getEigenDecomposition_getdeidC(const fullMatrix<double>& rightEigenVect, const double& x0, const double& x1, const double& x2, STensor33& de0dC, STensor33& de1dC, STensor33& de2dC){
+	  // C is 42 tensor
+
+	  zero(de0dC); zero(de1dC); zero(de2dC);
+	  for(int i=0; i<3; i++)
+	    for (int k=0; k<3; k++)
+		  for (int l=0; l<3; l++){
+
+			 if (x0!=x1){
+				 de0dC(i,k,l) += 1/(x0-x1)/2.*(rightEigenVect(l,0)*rightEigenVect(k,1)+rightEigenVect(k,0)*rightEigenVect(l,1))*rightEigenVect(i,1);
+				 de1dC(i,k,l) += 1/(x1-x0)/2.*(rightEigenVect(l,1)*rightEigenVect(k,0)+rightEigenVect(k,1)*rightEigenVect(l,0))*rightEigenVect(i,0);
+			 }
+
+			 if (x0!=x2){
+				 de0dC(i,k,l) += 1/(x0-x2)/2.*(rightEigenVect(l,0)*rightEigenVect(k,2)+rightEigenVect(k,0)*rightEigenVect(l,2))*rightEigenVect(i,2);
+				 de2dC(i,k,l) += 1/(x2-x0)/2.*(rightEigenVect(l,2)*rightEigenVect(k,0)+rightEigenVect(k,2)*rightEigenVect(l,0))*rightEigenVect(i,0);
+			 }
+
+			 if (x1!=x2){
+				 de1dC(i,k,l) += 1/(x1-x2)/2.*(rightEigenVect(l,1)*rightEigenVect(k,2)+rightEigenVect(k,1)*rightEigenVect(l,2))*rightEigenVect(i,2);
+				 de2dC(i,k,l) += 1/(x2-x1)/2.*(rightEigenVect(l,2)*rightEigenVect(k,1)+rightEigenVect(k,2)*rightEigenVect(l,1))*rightEigenVect(i,1);
+			 }
+	      }
+  }
+
+  inline void alignEigenDecomposition_EigenVectorDotProductBased(const fullVector<double> eigenValReal1, const fullVector<double> eigenValReal2,
+		  	  	  	  	  	  	  	  const fullMatrix<double>& rightEigenVect1, const fullMatrix<double>& rightEigenVect2,
+									  double& a1_align, double& a2_align, double& a3_align, fullMatrix<double>& rightEigenVect){
+  	  // Align 1 to 2 where 2 is fixed
+
+
+	  // Get abs values of Eigenvectors
+	  static fullVector<double> abs1(3), abs2(3);
+	  double sumSquare1(0.), sumSquare2(0.);
+  	  for(int i=0; i<3; i++){
+    	for (int k=0; k<3; k++){
+    		sumSquare1 += rightEigenVect1(k,i)*rightEigenVect1(k,i);
+    		sumSquare2 += rightEigenVect2(k,i)*rightEigenVect2(k,i);
+    	}
+		abs1(i) = pow(sumSquare1,0.5);
+		abs2(i) = pow(sumSquare2,0.5);
+		sumSquare1 = 0.;
+		sumSquare2 = 0.;
+  	  }
+
+  	  // Get dotproducts of Eigen Vectors -> 3C1*3C1 possibilities
+  	  static STensor3 dot1, theta1;
+  	  zero(dot1);
+	  for (int k=0; k<3; k++)
+		for (int l=0; l<3; l++)
+		  for(int i=0; i<3; i++){
+			 dot1(k,l) += rightEigenVect1(k,i)*rightEigenVect2(l,i);
+		  }
+
+	  // Get angles
+	  double pi = 3.14159265358979323846;
+	  zero(theta1);
+	  for (int k=0; k<3; k++)
+		for (int l=0; l<3; l++){
+		  theta1(k,l) = acos(dot1(k,l)); // /(abs1(k)*abs2(l)));
+		  if (theta1(k,l) > pi/2) {
+			  theta1(k,l) = pi - theta1(k,l);
+		  }
+		}
+
+
+	  // Compare and pick the smallest theta1 for the 1st aligned Eigenvector wrt Eigenvectors2
+      double smol1 = theta1(0,0);
+      double smol2 = theta1(1,1);
+      double smol3 = theta1(2,2);
+      int index1 = 0, index2 = 1, index3 = 2;
+
+      // pick 1
+      int temp1 = 0;
+      for (int l=0; l<3; l++){
+    	  if(temp1==0){
+    		  smol1 = theta1(l,0);
+    		  index1 = l;
+    		  temp1 = 1;
+    	  }
+    	  else if(theta1(l,0)<smol1 && temp1!=0){
+    		  smol1 = theta1(l,0);
+    		  index1 = l;
+    		  temp1 = 1;
+    	  }
+      }
+
+      // pick 2
+      int temp2 = 0;
+      for (int l=0; l<3; l++){
+    	  if(l!=index1){
+    		  if(temp1==0){
+        		  smol2 = theta1(l,1);
+        		  index2 = l;
+        		  temp2 = 1;
+    		  }
+    		  if(theta1(l,1)<smol2 && temp2!=0){
+        		  smol2 = theta1(l,1);
+        		  index2 = l;
+        		  temp2 = 1;
+    		  }
+    	  }
+       }
+
+      // pick 3
+      for (int l=0; l<3; l++){
+       	  if(l!=index1 && l!=index2) index3 = l;
+      }
+
+      a1_align = eigenValReal1(index1);
+      a2_align = eigenValReal1(index2);
+      a3_align = eigenValReal1(index3);
+	  for(int i=0; i<3; i++){
+		  rightEigenVect(i,0) = rightEigenVect1(i,index1);
+		  rightEigenVect(i,1) = rightEigenVect1(i,index2);
+		  rightEigenVect(i,2) = rightEigenVect1(i,index3);
+	  }
+
+      // Convert to tensors
+	  static STensor3 eig1, eig2, eig_Align;
+	  for (int k=0; k<3; k++)
+		for (int l=0; l<3; l++){
+			eig1(k,l) = rightEigenVect1(k,l);
+			eig2(k,l) = rightEigenVect2(k,l);
+			eig_Align(k,l) = rightEigenVect(k,l);
+		}
+
+  }
+
+  inline void alignEigenDecomposition_NormBased(const STensor3& A, const STensor3& B, const fullVector<double> eigenValReal1, const fullVector<double> eigenValReal2,
+    		  	  	  	  	  	  	  	  const fullMatrix<double>& rightEigenVect1, const fullMatrix<double>& rightEigenVect2,
+    									  double& a1_align, double& a2_align, double& a3_align, fullMatrix<double>& rightEigenVect){
+      	  // Align 1 to 2 where 2 is fixed
+
+  	  	  // Get eigen bases
+  	  	  double b1, b2, b3;
+  	  	  static STensor3 B1, B2, B3;
+  	  	  getEigenDecomposition(B,b1,b2,b3,B1,B2,B3);
+
+  	  	  // Form the tensor
+  	  	  double norm(0.), norm_min(0.);
+  	  	  static STensor3 A_reformed;
+
+  	  	  // Generate permutated eigVal vector
+  	  	  static fullVector<double> eigenValReal1_permuted(3);
+  	  	  static fullVector<int> eigenValReal1_permuted_Index(3);
+  	  	  double l1(0.), l2(0.), l3(0.);
+  	  	  for (int p=0; p<3; p++){
+  	  		l1 = eigenValReal1(p);
+  	  		for (int q=0; q<3; q++){
+  	  		  if(q!=p){
+  	  			l2 = eigenValReal1(q);
+  	  			for (int r=0; r<3; r++){
+  	  			  if(r!=p && r!=q){
+  	  				l3 = eigenValReal1(r);
+
+  	  				zero(A_reformed);
+  	  				for (int k=0; k<3; k++)
+  	  				  for (int l=0; l<3; l++)
+  	  		  		    A_reformed(k,l) += l1*B1(k,l) + l2*B2(k,l) + l3*B3(k,l);
+  	  		  	    A_reformed -= A;
+  	  		  	    doubleContractionSTensor3(A_reformed,A_reformed,norm);
+  	  		  	    norm = pow(norm,0.5);
+
+  	  		  	    if(norm_min == 0.){
+  	  		  	     norm_min = norm; // initialise
+  		  		  	 eigenValReal1_permuted(0) = l1;
+  		  		  	 eigenValReal1_permuted_Index(0) = p;
+  		  		  	 eigenValReal1_permuted(1) = l2;
+  		  		  	 eigenValReal1_permuted_Index(1) = q;
+  		  		  	 eigenValReal1_permuted(2) = l3;
+  		  		  	 eigenValReal1_permuted_Index(2) = r;
+  	  		  	    }
+  	  		  	    else{
+  	  		  	    	if(norm < norm_min){      // if( ( - norm + norm_min)>1.e-6 )
+  	  		  	    		norm_min = norm;
+  	  			  		  	eigenValReal1_permuted(0) = l1;
+  	  			  		  	eigenValReal1_permuted_Index(0) = p;
+  	  			  		  	eigenValReal1_permuted(1) = l2;
+  	  			  		  	eigenValReal1_permuted_Index(1) = q;
+  	  			  		  	eigenValReal1_permuted(2) = l3;
+  	  			  		  	eigenValReal1_permuted_Index(2) = r;
+  	  		  	    	}
+  	  		  	    }
+  	  			  }
+  	  			}
+
+  	  		  }
+  	  		}
+  	  	  }
+
+  	  	  // Align the eigVals and eigVecs
+  	  	  a1_align = eigenValReal1_permuted(0);
+  	  	  a2_align = eigenValReal1_permuted(1);
+  	  	  a3_align = eigenValReal1_permuted(2);
+  		  for(int i=0; i<3; i++){
+  			  rightEigenVect(i,0) = rightEigenVect1(i,eigenValReal1_permuted_Index(0));
+  			  rightEigenVect(i,1) = rightEigenVect1(i,eigenValReal1_permuted_Index(1));
+  			  rightEigenVect(i,2) = rightEigenVect1(i,eigenValReal1_permuted_Index(2));
+  		  }
+
+
+  	      // Convert to tensors
+  		  static STensor3 eig1, eig2, eig_align;
+  		  for (int k=0; k<3; k++)
+  			for (int l=0; l<3; l++){
+  				eig1(k,l) = rightEigenVect1(k,l);
+  				eig2(k,l) = rightEigenVect2(k,l);
+  				eig_align(k,l) = rightEigenVect(k,l);
+  			}
+
+      }
+
+  void alignEigenDecomposition_NormBased_indexOnly(const STensor3& A, const STensor3& B, fullVector<int>& alignedIndex);
+
+  void alignEigenDecomposition_NormBased(const STensor3& A, const STensor3& B,
+		  	  	  	  	  	  	  	  	  	  	const double& b1, const double& b2, const double& b3, const STensor3& B1, const STensor3& B2, const STensor3& B3,
+												const fullVector<double> eigenValReal1, int& index1, int& index2, int& index3,
+												double& a1_align, double& a2_align, double& a3_align);
+
   inline void getEigenDecompositionExplicitBase(const STensor3& a, double& x1, double& x2, double& x3, STensor3& E1, STensor3& E2, STensor3& E3)
   {
     // a = x1*E1+x2*E2+x3*E3
diff --git a/NonLinearSolver/materialLaw/mlaw.h b/NonLinearSolver/materialLaw/mlaw.h
index d440e62ad6564f0ef2d6b6a55c84a982076529a0..4f2ed086c46255a0c2e818fbdd6f2e7383561547 100644
--- a/NonLinearSolver/materialLaw/mlaw.h
+++ b/NonLinearSolver/materialLaw/mlaw.h
@@ -35,7 +35,7 @@ class materialLaw{
                  ThermalConducter,AnIsotropicTherMech, localDamageJ2Hyper,linearElastic,nonLocalDamageGursonThermoMechanics,
                  localDamageJ2SmallStrain,nonLocalDamageJ2SmallStrain,cluster,tfa,ANN, DMN, torchANN, NonlocalDamageTorchANN, LinearElecMagTherMech, LinearElecMagInductor, hyperviscoelastic,
                  GenericThermoMechanics, ElecMagGenericThermoMechanics, ElecMagInductor,
-                 nonlineartvm,nonlinearTVE,nonlinearTVP,vevpmfh, VEVPUMAT, IMDEACPUMAT, Hill48,nonlinearTVEnonlinearTVP,
+                 nonlineartvm,nonlinearTVE,nonlinearTVP,vevpmfh, VEVPUMAT, IMDEACPUMAT, Hill48,nonlinearTVEnonlinearTVP,nonlinearTVEnonlinearTVP2,
                  MultipleLaws};
 
 
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
index e15627afd345e1775f0abda078bd5edca516a235..5ed49eeaa8254666715e054521cfd7c8481d2961 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
@@ -401,66 +401,6 @@ void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &de
             // Msg::Error(" Inside extraBranch_Hyper Type = TensionCompressionRegularisedType, D1 = 0. or D4 = 0., incompatibility with Mullin's effect");
         } 
     }
-    /*else if(_extraBranchNLType == hyper_exp_TCasymm_Type){
-
-            // Msg::Error(" Inside evaluatePhiPCorrection, A_v = %e, B_d = %e !!", A_v, B_d);
-            // Regularising function
-            double m = _tensionCompressionRegularisation;
-            double expmtr = exp(-m*tr);
-            // if (exp(-m*tr)<1.e+10){ expmtr = exp(-m*tr);}
-            double sigmoid = 1/(1.+expmtr);
-
-            double x1 = getXiVolumeCorrection()*tr*tr + getZetaVolumeCorrection();
-            double x2 = _xivolCorrection2*tr*tr + _zetavolCorrection2;
-
-            A_v = -1. + sigmoid*(getVolumeCorrection()/sqrt(x1)) + (1-sigmoid)*_compCorrection*(getVolumeCorrection()/sqrt(x1) + _volCorrection2*exp(x2));
-
-            dA_vdE = sigmoid*(-getVolumeCorrection()*getXiVolumeCorrection()*tr/pow(x1,1.5))
-             		   + (1.-sigmoid)*_compCorrection*( -getVolumeCorrection()*getXiVolumeCorrection()*tr/pow(x1,1.5) + 2*_volCorrection2*_xivolCorrection2*tr*exp(x2))
-                        + (m*expmtr/pow((1.+expmtr),2.))*getVolumeCorrection()*1./sqrt(x1) - (m*expmtr/pow((1.+expmtr),2.))*_compCorrection*(getVolumeCorrection()/sqrt(x1) + _volCorrection2*exp(x2)) ;
-
-             if(getXiVolumeCorrection()>0. && _xivolCorrection2>0.){
-                 double integrand1 = 1./getXiVolumeCorrection()*sqrt(x1); // integral of A_v * trEe
-                 integrand1 -= ( 1./getXiVolumeCorrection()*sqrt(getZetaVolumeCorrection()) ); // value at trEe = 0.
-                 integrand1 *= getVolumeCorrection();
-
-                 double integrand2 = exp(x2)/(2*_xivolCorrection2);
-                 integrand2 -= exp(_zetavolCorrection2)/(2*_xivolCorrection2);
-     			integrand2 *= _volCorrection2;
-
-                 intA = - tr*tr/2. + sigmoid*integrand1 + (1.-sigmoid)*_compCorrection*(integrand1 + integrand2);
-             }
-             else{
-                 intA = - tr*tr/2.;
-             }
-
-             double y1 = getThetaDevCorrection()*dev.dotprod() + getPiDevCorrection();
-             double y2 = _thetadevCorrection2*dev.dotprod() + _pidevCorrection2;
-             B_d = -1. + sigmoid*(getDevCorrection()/sqrt(y1)) + (1-sigmoid)*_compCorrection*(getDevCorrection()/sqrt(y1) + _devCorrection2*exp(y2));
-
-             STensorOperation::zero(dB_vddev);
-             dB_vddev = dev;
-             dB_vddev *= ( sigmoid*(-getDevCorrection()*getThetaDevCorrection()/pow(y1,1.5))
-             				+ (1.-sigmoid)*_compCorrection*( -getDevCorrection()*getThetaDevCorrection()/pow(y1,1.5) + 2*_devCorrection2*_thetadevCorrection2*exp(y2)) );
-             if(dB_dTrEe!=NULL){
-                  *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*getDevCorrection()*1./sqrt(y1) - (m*expmtr/pow((1.+expmtr),2.))*_compCorrection*(getDevCorrection()/sqrt(y1) + _devCorrection2*exp(y2));
-              }
-              if(getThetaDevCorrection()>0. && _thetadevCorrection2>0.){
-
-                  double integrand1 = 1./getThetaDevCorrection()*sqrt(y1);  // integral of B_d * devEe
-                  integrand1 -= (1./getThetaDevCorrection()*sqrt(getPiDevCorrection()) );  // value at devEe = 0.
-                  integrand1 *= getDevCorrection();
-
-                  double integrand2 = exp(y2)/(2*_thetadevCorrection2);
-                  integrand2 -= exp(_pidevCorrection2)/(2*_thetadevCorrection2);
-      			integrand2 *= _devCorrection2;
-
-      			intB = -dev.dotprod()/2. + sigmoid*integrand1 + (1.-sigmoid)*_compCorrection*(integrand1 + integrand2);
-              }
-              else{
-                  intB = -dev.dotprod()/2.;
-              }
-    }*/
     else if(_extraBranchNLType == hyper_exp_TCasymm_Type){ // hyper_TCasymm_Type2
 
     			// To make it simpler for the sake of it
@@ -485,24 +425,26 @@ void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &de
     	        double sigmoid = 1/(1.+expmtr);
 
     	        double x1 = V1*tr*tr + V2;
-    	        double x2 = V4*tr*tr + V5;
-    	        A_v = -1. + sigmoid*( (1./sqrt(x1)+V3*(1+tanh(x2))) ) + (1-sigmoid)*_compCorrection*( 1./sqrt(x1)+V3 );
+    	        double x2 = V4*tr*tr;
+    	        A_v = -1. + sigmoid*( (1./sqrt(x1)+V3*(V5 + tanh(x2))) ) + (1-sigmoid)*_compCorrection*( 1./sqrt(x1)+V0 );
 
     	        dA_vdE = -sigmoid*(V1*tr/pow(x1,1.5) - V3*(2*V4*tr*pow(1/cosh(x2),2))) - (1.-sigmoid)*(V1*_compCorrection*tr/pow(x1,1.5))
-                           + (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1)+ V3*(1+tanh(x2)))- (_compCorrection*m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + V3);
+                           + (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1)+ V3*(V5+tanh(x2)))- (_compCorrection*m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + V0);
 
                 if(V1>0.){
-                    double integrand1 = 1./V1*sqrt(x1) + V3*tr*tr/2.; // integral of A_v * trEe
+                    double integrand1 = 1./V1*sqrt(x1) + V3*V5*tr*tr/2.; // integral of A_v * trEe
                     double integrand2 = 0.;
+                    double integrand3 = 1./V1*sqrt(x1) + V0*tr*tr/2.; // integral of A_v * trEe
                     if(V4 != 0.){
                     	integrand2 = V3/(2.*V4)*log(cosh(x2));
                     }
                     integrand1 -= ( 1./V1*sqrt(V2) ); // value at trEe = 0.
-                    intA = - tr*tr/2. + sigmoid*(integrand1 + integrand2) + _compCorrection*(1.-sigmoid)*integrand1;
+                    integrand3 -= ( 1./V1*sqrt(V2) ); // value at trEe = 0.
+                    intA = - tr*tr/2. + sigmoid*(integrand1 + integrand2) + _compCorrection*(1.-sigmoid)*integrand3;
                     // intA *= getVolumeCorrection();
 
                     if(DintA!=NULL){
-                    	*DintA = (m*expmtr/pow((1.+expmtr),2.))*integrand1 - (Ci*m*expmtr/pow((1.+expmtr),2.))*integrand2;
+                    	*DintA = (m*expmtr/pow((1.+expmtr),2.))*(integrand1 + integrand2) - (Ci*m*expmtr/pow((1.+expmtr),2.))*integrand3;
                     }
                 }
                 else{
@@ -510,31 +452,33 @@ void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &de
                 }
 
     	        double y1 = D1*dev.dotprod() + D2;
-    	        double y2 = D4*dev.dotprod() + D5;
+    	        double y2 = D4*dev.dotprod();
 
-    	        B_d = -1. + sigmoid*(1./sqrt(y1) + D3*(1+tanh(y2))) + (1.-sigmoid)*(_compCorrection*(1./sqrt(y1) + D3)) ;
+    	        B_d = -1. + sigmoid*(1./sqrt(y1) + D3*(D5+tanh(y2))) + (1.-sigmoid)*(_compCorrection*(1./sqrt(y1) + D0)) ;
 
     	        STensorOperation::zero(dB_vddev);
     	        dB_vddev = dev;
     	        dB_vddev *= (-sigmoid*(D1/pow(y1,1.5) - D3*(2*D4*pow(1/cosh(y2),2))) - (1.-sigmoid)*(D1*_compCorrection/pow(y1,1.5)));
 
                 if(dB_dTrEe!=NULL){
-                    *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(y1) + D3*(1+tanh(y2))) - (m*expmtr/pow((1.+expmtr),2.))*(_compCorrection*(1./sqrt(y1) + D3));
+                    *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(y1) + D3*(D5+tanh(y2))) - (m*expmtr/pow((1.+expmtr),2.))*(_compCorrection*(1./sqrt(y1) + D0));
                     // *dB_dTrEe *= getDevCorrection();
                 }
 
                 if(D1>0.){
-                    double integrand1 = 1./D1*sqrt(y1) + D3*dev.dotprod()/2.;  // integral of B_d * devEe
+                    double integrand1 = 1./D1*sqrt(y1) + D3*D5*dev.dotprod()/2.;  // integral of B_d * devEe
                     double integrand2 = 0.;
+                    double integrand3 = 1./D1*sqrt(y1) + D0*dev.dotprod()/2.;  // integral of B_d * devEe
                     if(D4 != 0.){
                     	integrand2 = D3/(2.*D4)*log(cosh(y2));
                     }
                     integrand1 -= (1./D1*sqrt(D2) );  // value at devEe = 0.
-                    intB = -dev.dotprod()/2. + sigmoid*(integrand1 + integrand2) + _compCorrection*(1.-sigmoid)*integrand1;
+                    integrand3 -= (1./D1*sqrt(D2) );  // value at devEe = 0.
+                    intB = -dev.dotprod()/2. + sigmoid*(integrand1 + integrand2) + _compCorrection*(1.-sigmoid)*integrand3;
                     // intB *= getDevCorrection();
 
                     if(DintB!=NULL){
-                    	*DintB = (m*expmtr/pow((1.+expmtr),2.))*integrand1 - (Ci*m*expmtr/pow((1.+expmtr),2.))*integrand2;
+                    	*DintB = (m*expmtr/pow((1.+expmtr),2.))*(integrand1 + integrand2) - (Ci*m*expmtr/pow((1.+expmtr),2.))*integrand3;
                     }
                 }
                 else{
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.cpp
index 7db46ba61b9be195ea518d152d4eb08fc27de70f..8492c3f2c89c98c7a579c792b4f398b38b3c8993 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.cpp
@@ -474,18 +474,60 @@ void mlawNonLinearTVENonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow_nonL
   DlnDCe = DlnDCepr;
   
   // update A, B -> ExtraBranch calculations are within
-  double Ke(0.), Ge(0.), Ke_pr(0.), Ge_pr(0.), DKDTsum(0.), DGDTsum(0.);
+  double Ke(0.), Ge(0.), Ke_pr(0.), Ge_pr(0.);
   static STensor43 Ge_Tensor_pr, Ge_Tensor, Bd_stiffnessTerm, Ge_TrEeTensor_pr, Ge_TrEeTensor;
   STensorOperation::zero(Ge_Tensor_pr); STensorOperation::zero(Ge_Tensor);
   STensorOperation::zero(Ge_TrEeTensor_pr); STensorOperation::zero(Ge_TrEeTensor);
   
+  // NEW EIGEN
+  static fullVector<int> alignedIndex(3); alignedIndex(0) = 0; alignedIndex(1) = 1; alignedIndex(2) = 2;
+  static STensor3 Ee0_rot, R;
+  static STensor43 dRdEe, dRtdEe, rotationStiffness_pr ,rotationStiffness;
+  STensorOperation::zero(rotationStiffness_pr); STensorOperation::zero(rotationStiffness);
+  q1->_Ee0 = q0->_Ee;
+  mlawNonLinearTVM::rotationTensor_N_to_Nplus1(q0->_Ee0,q0->_Fe,Fe,Ce,Ee,q0->_Ee,R,dRdEe,dRtdEe);
+  for(int i=0; i<3; i++)
+    for(int j=0; j<3; j++){
+  	 Ee0_rot(i,j) = 0.;
+  	 for(int k=0; k<3; k++)
+  	   for(int l=0; l<3; l++)
+  	     Ee0_rot(i,j) += R(i,k)*q0->_Ee(k,l)*R(j,l);
+    }
+  // NEW EIGEN
+
+  // NEW EIGEN
+  if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+	  for (int i=0; i<_Gi.size(); i++){
+		  for(int k=0; k<3; k++)
+		 	for(int l=0; l<3; l++){
+			   q1->_A_rot[i](k,l) = 0.;
+   		  	   for(int p=0; p<3; p++)
+		 		 for(int q=0; q<3; q++)
+		 		  q1->_A_rot[i](k,l) += R(k,p)*q0->_A[i](p,q)*R(l,q);
+		 	   }
+	  }
+  }
+  // NEW EIGEN
+
   if (_extraBranchNLType == TensionCompressionRegularisedType  || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
-      // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3,',(
-	  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm,&Ge_TrEeTensor);
-        Ge_TrEeTensor_pr = Ge_TrEeTensor;
+      // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm,&Ge_TrEeTensor);
+	  }
+	  else{
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,stiff,alignedIndex,Bd_stiffnessTerm,&Ge_TrEeTensor,&rotationStiffness); // NEW EIGEN
+	  }
+      Ge_TrEeTensor_pr = Ge_TrEeTensor;
+      rotationStiffness_pr = rotationStiffness;
   }
   else{ 
-	  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm);
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
+	  }
+	  else{
+	      mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,stiff,alignedIndex,Bd_stiffnessTerm,NULL,&rotationStiffness); // NEW EIGEN
+	  }
+	  rotationStiffness_pr = rotationStiffness;
   }
     
   Ge_Tensor = _I4;
@@ -499,6 +541,27 @@ void mlawNonLinearTVENonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow_nonL
   Ge_Tensor_pr *= Ge_pr*2; // Because the function does not do it
   Ge_Tensor_pr += Bd_stiffnessTerm;
   
+  // NEW - EIGEN
+  static fullMatrix<double> m1(3, 3), m2(3, 3), m3(3, 3), m4(3, 3), m5(3, 3);
+  static fullVector<double> eigenValReal1(3), eigenValReal2(3), eigenValReal3(3), eigenValReal4(3), eigenValReal5(3);
+  static fullVector<double> eigenValImag1(3), eigenValImag2(3), eigenValImag3(3), eigenValImag4(3), eigenValImag5(3);
+  static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3), leftEigenVect3(3,3), leftEigenVect4(3,3), leftEigenVect5(3,3);
+  static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), rightEigenVect3(3,3), rightEigenVect4(3,3), rightEigenVect5(3,3);
+  m1.setAll(0.); m2.setAll(0.); m3.setAll(0.); m4.setAll(0.); m5.setAll(0.);
+  eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); eigenValReal3.setAll(0.); eigenValReal4.setAll(0.); eigenValReal5.setAll(0.);
+  eigenValImag1.setAll(0.); eigenValImag2.setAll(0.); eigenValImag3.setAll(0.); eigenValImag4.setAll(0.); eigenValImag5.setAll(0.);
+  leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.); leftEigenVect3.setAll(0.); leftEigenVect4.setAll(0.); leftEigenVect5.setAll(0.);
+  rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); rightEigenVect3.setAll(0.); rightEigenVect4.setAll(0.); rightEigenVect5.setAll(0.);
+
+  // Get eigen values and vectors
+  q1->_kirchhoff.getMat(m1); Ce.getMat(m2); Ee.getMat(m3); q0->_Ee.getMat(m4); Ee0_rot.getMat(m5);
+  m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+  m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+  m3.eig(eigenValReal3,eigenValImag3,leftEigenVect3,rightEigenVect3,false);
+  m4.eig(eigenValReal4,eigenValImag4,leftEigenVect4,rightEigenVect4,false);
+  m5.eig(eigenValReal5,eigenValImag5,leftEigenVect5,rightEigenVect5,false);
+  // NEW - EIGEN
+
   // get predictor - dKeprDT
   mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T);
   const STensor3& dKeprDT = q1->_DcorKirDT; // This has all extrabranches now
@@ -592,7 +655,7 @@ void mlawNonLinearTVENonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow_nonL
     }
     else{
         if (f>_tol){
-        	// Msg::Error("Plasticity");
+        	Msg::Error("Plasticity");
             q1->getRefToDissipationActive() = true;
          
             // plasticity
@@ -851,11 +914,37 @@ void mlawNonLinearTVENonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow_nonL
     mlawNonLinearTVP::getModifiedMandel(Ce, q0, q1); // update Mandel
     const STensor3& MS = q1->_ModMandel;
     Me = MS;
+
     // second Piola Kirchhoff stress
     static STensor3 S, Ceinv;
     STensorOperation::inverseSTensor3(Ce,Ceinv);
     STensorOperation::multSTensor3(Ceinv,q1->_ModMandel,S);
     
+    static STensor3 S2, M2;
+    for(int i=0; i<3; i++)
+        for(int j=0; j<3; j++){
+          S2(i,j) = 0.;
+          for(int k=0; k<3; k++)
+             S2(i,j) += 0.5* ( KS(i,k)*Ceinv(k,j) + Ceinv(k,i)*KS(j,k) );
+        }
+    STensorOperation::multSTensor3(Ce,S2,M2);
+
+
+    static STensor3 _temp1, _temp2, _temp3, _temp4, _temp6, commuteCheck;
+    STensorOperation::multSTensor3(Ce, S, _temp1);
+    STensorOperation::multSTensor3(S, Ce, _temp2);
+    STensorOperation::multSTensor3(KS, Ce, _temp3);
+    STensorOperation::multSTensor3(Ce, KS, _temp4);
+
+    // Check S
+    commuteCheck = _temp1;
+    commuteCheck -= _temp2;
+
+    // Check corKir (just for fun)
+    _temp6 = _temp3;
+    _temp6 -= _temp4;
+
+
     // first PK
     for(int i=0; i<3; i++)
         for(int j=0; j<3; j++){
@@ -947,6 +1036,11 @@ void mlawNonLinearTVENonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow_nonL
         DcorKirDEe_pr += Ge_TrEeTensor_pr; // TC Assymmetry
         DcorKirDEe += Ge_TrEeTensor; // TC Assymmetry
         
+        // NEW EIGEN
+        DcorKirDEe_pr += rotationStiffness_pr;
+        DcorKirDEe += rotationStiffness;
+        // NEW EIGEN
+
         static STensor43 DcorKir_pr_DCepr, DcorKirDCepr;
         STensorOperation::multSTensor43(DcorKirDEe_pr,DlnDCepr,DcorKir_pr_DCepr);
         STensorOperation::multSTensor43(DcorKirDEe,DlnDCepr,DcorKirDCepr);
@@ -2179,7 +2273,7 @@ void mlawNonLinearTVENonLinearTVP::getDho(const double& Gamma, const STensor3& C
 }
 
 void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
-                                            const double& Gamma, const double& Cxtr, const double& Cxdev,
+                                            double& Gamma, const double& Cxtr, const double& Cxdev,
                                             const STensor3& Cepr, const STensor3& Eepr,
                                             const double& trXn, const STensor3& devXn, 
                                             double& Ke, double& Ge, STensor43& Ge_Tensor, 
@@ -2230,14 +2324,13 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
   // Initialise corKir
   static STensor3 KS;
   static STensor43 Bd_stiffnessTerm;
-  double DKDTsum, DGDTsum;
   if (Ge_TrEeTensor == NULL){
     // mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
-    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm);
+    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
   }
   else{ // TC asymmetry
     // mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
-    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
+    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
   }
   Ge_Tensor = _I4;
   Ge_Tensor *= Ge*2; // *2 because the function doesnt do it
@@ -2299,7 +2392,7 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
   // Initialise numerical quantities
   static STensor3 Phi_plus, J_plus, devPhi_plus, N_plus, GammaN_plus, Ee_plus, Ce_plus, KS_plus, MS_plus, expGN_plus, Hinv_plus, devN_plus, devX_plus;
   double pPhi_plus,Ke_plus,Ge_plus, trN_plus, trX_plus;
-  static STensor43 dJdPhi_plus, dJdPhi_plus_inv, dexpAdA_plus, Bd_stiffnessTerm_plus,Ge_Tensor_plus;
+  static STensor43 dJdPhi_plus, dJdPhi_plus_inv, dexpAdA_plus, Bd_stiffnessTerm_plus,Ge_Tensor_plus, dJdPhi_plus2, dJdPhi_plus2_inv;
   STensor43* Ge_TrEeTensor_plus = NULL;
   static IPNonLinearTVP q1_plus(*q0);
 
@@ -2312,6 +2405,7 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
 
 	  // numerical Dho4inv (Jacobian dJ/dPhi)
 	  	  // _perturbationfactor = DPhi_numerical
+
 	  /*
 	  for (int i=0; i<3; i++){
 	     for (int j=0; j<3; j++){
@@ -2321,7 +2415,7 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
 	        STensorOperation::decomposeDevTr(Phi_plus,devPhi_plus,pPhi_plus);
 	        pPhi_plus = Phi_plus.trace()/3;
 	        N_plus = _I;
-	        N_plus *= 2.*_b/3;
+	        N_plus *= 2.*_b/3*pPhi_plus;
 	        N_plus += 3*devPhi_plus;
 	        GammaN_plus = N_plus;
 	        GammaN_plus *= Gamma;
@@ -2337,13 +2431,14 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
 	            	Ce_plus(ii,jj) += Hinv_plus(ii,kk)*Hinv_plus(kk,ll)*Cepr(ll,jj);
 	          }
 
-	        Ee_plus = - Gamma*N_plus;
-	        Ee_plus += Eepr(i,j);
+	        // Ee_plus = - Gamma*N_plus;
+	        // Ee_plus += Eepr(i,j);
+	        bool ok=STensorOperation::logSTensor3(Ce_plus,_order,Ee_plus);
 	        if (Ge_TrEeTensor_plus == NULL){
-	          mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm_plus);
+	          mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,Bd_stiffnessTerm_plus);
 	        }
 	        else{ // TC asymmetry
-	          mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm_plus,Ge_TrEeTensor_plus);
+	          mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,Bd_stiffnessTerm_plus,Ge_TrEeTensor_plus);
 	        }
 	        Ge_Tensor_plus = _I4;
 	        Ge_Tensor_plus *= Ge_plus*2; // *2 because the function doesnt do it
@@ -2427,6 +2522,7 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
       if(!ok)
       {
         Phi(0,0) = Phi(1,1) = Phi(2,2) = sqrt(-1.);
+    	// Gamma *= 0.1;
         return;
       }
       Ee *= 0.5;
@@ -2434,11 +2530,11 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
       // update corKir
       if (Ge_TrEeTensor == NULL){
         // mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
-        mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm);
+        mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
       }
       else{ // TC asymmetry
         // mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
-        mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,true,Bd_stiffnessTerm, Ge_TrEeTensor);
+        mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm, Ge_TrEeTensor);
       }  
       Ge_Tensor = _I4;
       Ge_Tensor *= Ge*2; // *2 because the function doesnt do it
@@ -2483,15 +2579,14 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
       }*/
 
       // debug
-      /*
 	  for (int i=0; i<3; i++)
 	     for (int j=0; j<3; j++)
 	        for (int k=0; k<3; k++)
 	          for (int l=0; l<3; l++)
-	            dJdPhi_plus(k,l,i,j) = (J(k,l) - J0(k,l))/(_perturbationfactor);
+	            // dJdPhi_plus2(k,l,i,j) = (J(k,l) - J0(k,l))/(_perturbationfactor);
 
-	   STensorOperation::inverseSTensor43(dJdPhi_plus,dJdPhi_plus_inv);
-	   J0 = J;*/
+	   // STensorOperation::inverseSTensor43(dJdPhi_plus2,dJdPhi_plus2_inv);
+	   // J0 = J;
 
 	   for (int i=0; i<3; i++)
 		 for (int j=0; j<3; j++)
@@ -2513,15 +2608,16 @@ void mlawNonLinearTVENonLinearTVP::getIterated_DPhi(const double& T0, const doub
       if (fabs(J_tol) <_tol) break;
 
       if(ite > maxite){
-    	  Msg::Error("No convergence for iterated Phi mlawNonLinearTVENonLinearTVP nonAssociatedFlow iter = %d, J_tol = %e!!",ite,J_tol);
+    	  // Msg::Error("No convergence for iterated Phi mlawNonLinearTVENonLinearTVP nonAssociatedFlow iter = %d, J_tol = %e!!",ite,J_tol);
     	  // Msg::Error("Exiting the function Iterated Phi!!");
     	  // Phi(0,0) = Phi(1,1) = Phi(2,2) = sqrt(-1.);
+    	  // Gamma *= 0.1;
        return;
        }
      } // while
 
 }
-
+/*
 void mlawNonLinearTVENonLinearTVP::TEST_predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(
                                         const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
                                         const STensor3& Fepr, const STensor3& Cepr,
@@ -2584,7 +2680,7 @@ void mlawNonLinearTVENonLinearTVP::TEST_predictorCorrector_TVP_nonAssociatedFlow
   static STensor43 Ge_Tensor_pr, Ge_Tensor, Bd_stiffnessTerm;
   STensorOperation::zero(Ge_Tensor_pr);
   STensorOperation::zero(Ge_Tensor);
-  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
+  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ce,Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
   Ge_Tensor = _I4;
   Ge_Tensor *= Ge*2; // Because the function does not do it
   Ge_Tensor += Bd_stiffnessTerm;
@@ -2815,11 +2911,11 @@ void mlawNonLinearTVENonLinearTVP::TEST_predictorCorrector_TVP_nonAssociatedFlow
                 // Update A
                 A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
 
-                /*
-                Dgamma = pow(kk,1)*Gamma*A;  // pow(kk,2) DEBUG
-                updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
-                hardening(q0,q1,T);
-                getYieldCoefficients(q1,a);*/
+
+                // Dgamma = pow(kk,1)*Gamma*A;  // pow(kk,2) DEBUG
+                // updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                // hardening(q0,q1,T);
+                // getYieldCoefficients(q1,a);
 
                 // Update f, g
                 f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.h b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.h
index 35e26d4bedf3070726ad9676bba1cae7b2b2f600..2ecb9c61a8d4d050d2c9eb925fc2f85c586512c2 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.h
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP.h
@@ -25,7 +25,7 @@ class mlawNonLinearTVENonLinearTVP : public mlawNonLinearTVP{
 		virtual void freeEnergyPlasticityDerivatives(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T, STensor3& dPsy_TVPdF, double& dPsy_TVPdT) const;
 
         virtual void getIterated_DPhi(const double& T0, const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
-                                            const double& Gamma, const double& Cxtr, const double& Cxdev,
+                                            double& Gamma, const double& Cxtr, const double& Cxdev,
                                             const STensor3& Cepr, const STensor3& Eepr,
                                             const double& trXn, const STensor3& devXn, 
                                             double& Ke, double& Ge, STensor43& Ge_Tensor, 
@@ -45,7 +45,7 @@ class mlawNonLinearTVENonLinearTVP : public mlawNonLinearTVP{
         virtual void TEST_predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(
                                         const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
                                         const STensor3& Fepr, const STensor3& Cepr,
-                                        double& ptilde, STensor3& devPhi, double& Gamma, double& Dgamma, double& A, double& f, STensor3& Me, STensor3& P) const;
+                                        double& ptilde, STensor3& devPhi, double& Gamma, double& Dgamma, double& A, double& f, STensor3& Me, STensor3& P) const{};
 
         virtual void predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0_, IPNonLinearTVP *q1,
                             STensor3&P, const bool stiff, STensor43& Tangent,  STensor43& dFedF, STensor43& dFpdF, STensor3& dFedT, STensor3& dFpdT,
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..02dc4d6696f2b68d326640e7f29ce30c8d99391a
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.cpp
@@ -0,0 +1,3056 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2024
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "nonLinearMechSolver.h"
+#include "mlawNonLinearTVENonLinearTVP2.h"
+
+
+mlawNonLinearTVENonLinearTVP2::mlawNonLinearTVENonLinearTVP2(const int num,const double E,const double nu, const double rho, const double tol,
+                                   const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                                   const bool matrixbyPerturbation, const double pert, const double stressIteratorTol, const bool thermalEstimationPreviousConfig):
+                                   mlawNonLinearTVP(num, E, nu, rho, tol, Tinitial, Alpha, KThCon, Cp, matrixbyPerturbation, pert, thermalEstimationPreviousConfig), _stressIteratorTol(stressIteratorTol) {
+};
+
+mlawNonLinearTVENonLinearTVP2::mlawNonLinearTVENonLinearTVP2(const mlawNonLinearTVENonLinearTVP2& src): mlawNonLinearTVP(src), _stressIteratorTol(src._stressIteratorTol) {
+};
+
+mlawNonLinearTVENonLinearTVP2& mlawNonLinearTVENonLinearTVP2::operator=(const materialLaw& source){
+
+    mlawNonLinearTVP::operator=(source);
+    const mlawNonLinearTVENonLinearTVP2* src =dynamic_cast<const mlawNonLinearTVENonLinearTVP2*>(&source);
+    if(src != NULL){
+    	_stressIteratorTol = src->_stressIteratorTol;
+    }
+    return *this;
+};
+
+mlawNonLinearTVENonLinearTVP2::~mlawNonLinearTVENonLinearTVP2(){
+};
+
+double mlawNonLinearTVENonLinearTVP2::freeEnergyPlasticity(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T) const{
+
+	double Psy_TVP(0.);
+
+	// 1. Kinematic Hardening
+    double Hb(0.);
+    if (q1->_ipKinematic != NULL){
+       Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+   	}
+
+    double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+    static STensor3 alpha;
+    STensorOperation::zero(alpha);
+    if(Hb>0.){
+    	alpha = q1->_backsig;
+    	alpha *= 1/(pow(kk,1)*Hb); //pow(kk,2) debug
+    }
+	STensorOperation::doubleContractionSTensor3(q1->_backsig,alpha,Psy_TVP);
+
+	// 2. Isotropic Hardening
+	double intR = q1->_ipCompression->getIntegR();
+	double sigc0 = q1->_ipCompression->getR0();
+	intR -= sigc0*q1->_epspbarre;
+
+	Psy_TVP += intR;
+
+    // If mullins, then calculate psi_VP derivatives
+    // if (_mullinsEffect != NULL && q._ipMullinsEffect != NULL){
+    //    *DpsiDT = 0.;
+    //    STensorOperation::zero(*DpsiDE);
+    // }
+    return Psy_TVP;
+}
+
+void mlawNonLinearTVENonLinearTVP2::freeEnergyPlasticityDerivatives(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T,
+                              STensor3& dPsy_TVPdF, double& dPsy_TVPdT) const{
+
+	STensorOperation::zero(dPsy_TVPdF);
+	dPsy_TVPdT = 0.;
+
+	// 1. Kinematic Hardening
+	double Hb(0.), dHb(0.), dHbdT(0.);
+	if (q1->_ipKinematic != NULL){
+	  Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+	  dHb = q1->_ipKinematic->getDR(); // kinematic hardening parameter derivative (dHb/dgamma)
+	  dHbdT = q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file
+	}
+
+    double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+    if(Hb>0.){
+
+    	static STensor3 term1, term2;
+    	STensorOperation::multSTensor3STensor43(q1->_backsig,q1->_DbackSigDF,term1);
+    	term2 = q1->_DgammaDF;
+    	term2 *= (-1./(2*Hb)*dHb*q1->_backsig.dotprod());
+
+    	dPsy_TVPdF = term1;
+    	dPsy_TVPdF += term2;
+    	dPsy_TVPdF *= 1./(pow(kk,1)*Hb); //pow(kk,2) debug
+
+    	double term3, term4;
+    	STensorOperation::doubleContractionSTensor3(q1->_backsig,q1->_DbackSigDT,term3);
+    	term4 = -(dHbdT + dHb*q1->_DgammaDT)/(2*Hb)*q1->_backsig.dotprod();
+    	dPsy_TVPdT = (term3+term4)/(pow(kk,1)*Hb); //pow(kk,2) debug
+
+    }
+
+
+	// 2. Isotropic Hardening
+
+    // Get Hc, etc.
+	double intR = q1->_ipCompression->getIntegR();
+	double sigc0 = q1->_ipCompression->getR0();  // Initial yield stress
+	intR -= sigc0*q1->_epspbarre;
+
+    double R(0.), dsigc0dT(0.), sigc(0.);
+    dsigc0dT = sigc0*_temFunc_Sy0->getDiff(T);
+    sigc = q1->_ipCompression->getR();
+
+    // Get R
+    R = sigc - sigc0;
+
+    dPsy_TVPdF += R*q1->_DgammaDF;
+    dPsy_TVPdT += (R*q1->_DgammaDT + _temFunc_Sy0->getDiff(T)/ _temFunc_Sy0->getVal(T)*intR - dsigc0dT*q1->_epspbarre);
+}
+
+void mlawNonLinearTVENonLinearTVP2::constitutive( // This function is just a placeholder, defined in the pure virtual class -> does nothing, its never called.
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& F1,         // current deformation gradient (input @ time n+1)
+                                  STensor3 &P1,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,       // array of previous internal variables
+                                  IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,         // tangents (output)
+                            const bool stiff,            // if true compute the tangents
+                                  STensor43* elasticTangent,
+                            const bool dTangent,
+                                  STensor63* dCalgdeps) const{
+    static SVector3 gradT, temp2;
+    static STensor3 temp3;
+    static STensor33 temp33;
+    static double tempVal;
+    static STensor43 dFpdF, dFedF;
+    static STensor3 dFpdT, dFedT;
+
+    const IPNonLinearTVP *q0 = dynamic_cast<const IPNonLinearTVP *> (q0i);
+          IPNonLinearTVP *q1 = dynamic_cast<IPNonLinearTVP *>(q1i);
+
+    if(elasticTangent != NULL) Msg::Error("mlawNonLinearTVENonLinearTVP2 elasticTangent not defined");
+    predictorCorrector_ThermoViscoPlastic(F0,F1,P1,q0,q1,Tangent,dFpdF, dFpdT, dFedF, dFedT,
+                                          _Tref,_Tref,gradT,gradT,temp2,temp3,temp3,temp2,temp33,
+                                          tempVal,tempVal,temp3,
+                                          tempVal,tempVal,temp3,
+                                          stiff, NULL);
+};
+
+void mlawNonLinearTVENonLinearTVP2::constitutive(
+                            const STensor3& F0,                     // initial deformation gradient (input @ time n)
+                            const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,                   // array of initial internal variable
+                                  IPVariable *q1i,                   // updated array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,               // constitutive mechanical tangents (output)
+                            const double& T0,                       // previous temperature
+                            const double& T,                        // temperature
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const{
+
+    const IPNonLinearTVP *q0 = dynamic_cast<const IPNonLinearTVP *>(q0i);
+          IPNonLinearTVP *q1 = dynamic_cast<IPNonLinearTVP *>(q1i);
+
+    // Declaring here, coz I dont know better.
+    static STensor43 dFedF, dFpdF;
+    static STensor3 dFpdT, dFedT;
+
+    if (!_tangentByPerturbation){
+
+        this->predictorCorrector_ThermoViscoPlastic(F0, F1, P, q0, q1, Tangent, dFpdF, dFpdT, dFedF, dFedT,
+                                                    T0, T, gradT0, gradT, fluxT, dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF,
+                                                    thermalSource, dthermalSourcedT, dthermalSourcedF,
+                                                    mechanicalSource, dmechanicalSourcedT, dmechanicalSourceF,
+                                                    stiff, elasticTangent);
+    }
+
+    else{
+
+        this->predictorCorrector_ThermoViscoPlastic(F0, F1, P, q0, q1, T0, T, gradT0, gradT, fluxT, thermalSource, mechanicalSource, elasticTangent);
+        if (stiff)
+            this->tangent_full_perturbation(F0,F1,P,q0,q1,T0, T, gradT0, gradT, fluxT, thermalSource, mechanicalSource,
+                                            Tangent, dFpdF, dFpdT, dFedF, dFedT,
+                                            dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF,
+                                            dthermalSourcedT, dthermalSourcedF,
+                                            dmechanicalSourcedT, dmechanicalSourceF);
+    }
+};
+
+
+void mlawNonLinearTVENonLinearTVP2::predictorCorrector_ThermoViscoPlastic(
+                                                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                                                    const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                                          STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                    const IPNonLinearTVP *q0,       // array of initial internal variable
+                                                          IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                                    const double& T0, // previous temperature
+                                                    const double& T, // temperature
+                                                    const SVector3 &gradT0, // previous temeprature gradient
+                                                    const SVector3 &gradT, // temeprature gradient
+                                                          SVector3 &fluxT, // temperature flux)
+                                                          double &thermalSource,
+                                                          double& mechanicalSource,
+                                                          STensor43* elasticTangent) const{
+  // temp variables
+  static STensor43 Tangent, dFpdF, dFedF;
+  static STensor3 dPdT, dfluxTdgradT, dthermalSourcedF, dmechanicalSourceF, dFpdT, dFedT;
+  static STensor33 dfluxTdF;
+  static SVector3 dfluxTdT;
+  static double dthermalSourcedT, dmechanicalSourcedT;
+  predictorCorrector_ThermoViscoPlastic(F0,F1,P,q0,q1,Tangent,dFpdF,dFpdT,dFedF,dFedT,
+                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,false,elasticTangent);
+};
+
+void mlawNonLinearTVENonLinearTVP2::tangent_full_perturbation(
+                            const STensor3& F0,
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const{
+
+    static STensor3 Fplus, Pplus;
+    static SVector3 fluxTPlus, gradTplus;
+    static double thermalSourcePlus;
+    static double mechanicalSourcePlus;
+    static IPNonLinearTVP qPlus(*q0);
+
+    // perturb F
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        Fplus = F1;
+        Fplus(i,j) += _perturbationfactor;
+
+        predictorCorrector_ThermoViscoPlastic(F0,Fplus,Pplus,q0,&qPlus,T0,T,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+
+        q1->_DgammaDF(i,j) = (qPlus._epspbarre - q1->_epspbarre)/_perturbationfactor;
+        q1->_DirreversibleEnergyDF(i,j) = (qPlus._irreversibleEnergy - q1->_irreversibleEnergy)/_perturbationfactor;
+
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            Tangent(k,l,i,j) = (Pplus(k,l) - P(k,l))/(_perturbationfactor);
+            dFpdF(k,l,i,j) = (qPlus._Fp(k,l)-q1->_Fp(k,l))/_perturbationfactor;
+            dFedF(k,l,i,j) = (qPlus._Fe(k,l)-q1->_Fe(k,l))/_perturbationfactor;
+          }
+          dfluxTdF(k,i,j) = (fluxTPlus(k) - fluxT(k))/_perturbationfactor;
+        }
+
+        q1->getRefToDElasticEnergyPartdF()(i,j)=(qPlus.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/_perturbationfactor;
+        q1->getRefToDViscousEnergyPartdF()(i,j)=(qPlus.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/_perturbationfactor;
+        q1->getRefToDPlasticEnergyPartdF()(i,j)=(qPlus.getConstRefToPlasticEnergyPart()-q1->getConstRefToPlasticEnergyPart())/_perturbationfactor;
+
+        dthermalSourcedF(i,j) = (thermalSourcePlus - thermalSource)/_perturbationfactor;
+        dmechanicalSourceF(i,j) = (mechanicalSourcePlus - mechanicalSource)/_perturbationfactor;
+      }
+    }
+
+    // perturb gradT
+    double gradTpert = _perturbationfactor*T0/1e-3;
+    for (int i=0; i<3; i++){
+      gradTplus = gradT;
+      gradTplus(i) += gradTpert;
+      predictorCorrector_ThermoViscoPlastic(F0,F1,Pplus,q0,&qPlus,T0,T,gradT0,gradTplus,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+      for (int k=0; k<3; k++){
+        dfluxTdgradT(k,i) = (fluxTPlus(k) - fluxT(k))/gradTpert;
+      }
+    }
+
+    // perturb T
+    double Tplus = T+ _perturbationfactor*T0;
+    predictorCorrector_ThermoViscoPlastic(F0,F1,Pplus,q0,&qPlus,T0,Tplus,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+
+    q1->_DgammaDT = (qPlus._epspbarre - q1->_epspbarre)/(_perturbationfactor*T0);
+    q1->_DirreversibleEnergyDT = (qPlus._irreversibleEnergy - q1->_irreversibleEnergy)/(_perturbationfactor*T0);
+
+    for (int k=0; k<3; k++){
+      for (int l=0; l<3; l++){
+        dFpdT(k,l) = (qPlus._Fp(k,l) - q1->_Fp(k,l))/(_perturbationfactor*T0);
+        dFedT(k,l) = (qPlus._Fe(k,l) - q1->_Fe(k,l))/(_perturbationfactor*T0);
+        dPdT(k,l) = (Pplus(k,l) - P(k,l))/(_perturbationfactor*T0);
+      }
+      dfluxTdT(k) = (fluxTPlus(k) - fluxT(k))/(_perturbationfactor*T0);
+    }
+
+    q1->getRefToDElasticEnergyPartdT() = (qPlus.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/(_perturbationfactor*T0);
+    q1->getRefToDViscousEnergyPartdT() = (qPlus.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/(_perturbationfactor*T0);
+    q1->getRefToDPlasticEnergyPartdT() = (qPlus.getConstRefToPlasticEnergyPart()-q1->getConstRefToPlasticEnergyPart())/(_perturbationfactor*T0);
+
+    dthermalSourcedT = (thermalSourcePlus - thermalSource)/(_perturbationfactor*T0);
+    dmechanicalSourcedT = (mechanicalSourcePlus - mechanicalSource)/(_perturbationfactor*T0);
+
+};
+
+void mlawNonLinearTVENonLinearTVP2::predictorCorrector_ThermoViscoPlastic(
+                                                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                                                    const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                                          STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                    const IPNonLinearTVP *q0,       // array of initial internal variable
+                                                          IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                                          STensor43 &Tangent,         // mechanical tangents (output)
+                                                          STensor43 &dFpdF, // plastic tangent
+                                                          STensor3 &dFpdT, // plastic tangent
+                                                          STensor43 &dFedF, // elastic tangent
+                                                          STensor3 &dFedT, // elastic tangent
+                                                    const double& T0, // previous temperature
+                                                    const double& T, // temperature
+                                                    const SVector3 &gradT0, // previoustemeprature gradient
+                                                    const SVector3 &gradT, // temeprature gradient
+                                                          SVector3 &fluxT, // temperature flux
+                                                          STensor3 &dPdT, // mechanical-thermal coupling
+                                                          STensor3 &dfluxTdgradT, // thermal tengent
+                                                          SVector3 &dfluxTdT,
+                                                          STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                                          double &thermalSource,   // - cp*dTdt
+                                                          double &dthermalSourcedT, // thermal source
+                                                          STensor3 &dthermalSourcedF,
+                                                          double &mechanicalSource, // mechanical source--> convert to heat
+                                                          double &dmechanicalSourcedT,
+                                                          STensor3 &dmechanicalSourceF,
+                                                    const bool stiff,
+                                                          STensor43* elasticTangent) const{
+
+  if (_tangentByPerturbation){
+    if (_nonAssociatedFlow){
+      this->predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(F0,F1,q0,q1,P,false,Tangent,dFedF,dFpdF,dFedT,dFpdT,
+                                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF);
+    }
+    else{
+      this->mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(F1,q0,q1,P,false,Tangent,dFedF,dFpdF,T0,T);
+    }
+
+  }
+  else{
+    if (_nonAssociatedFlow){
+      this->predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(F0,F1,q0,q1,P,stiff,Tangent,dFedF,dFpdF,dFedT,dFpdT,
+                                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF);
+    }
+    else{
+      this->mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(F1,q0,q1,P,stiff,Tangent,dFedF,dFpdF,T0,T);
+    }
+  }
+
+};
+
+
+void mlawNonLinearTVENonLinearTVP2::predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
+                            STensor3&P, const bool stiff, STensor43& Tangent, STensor43& dFedF, STensor43& dFpdF, STensor3& dFedT, STensor3& dFpdT,
+                            const double T0,
+                            const double T,
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const{
+
+  // compute elastic predictor
+  STensor3& Fp1 = q1->_Fp;
+  const STensor3& Fp0 = q0->_Fp;
+
+  // Update the Properties to the current temperature (see below which ones are being used)
+  double CpT, DCpDT; getCp(CpT,T,&DCpDT);
+
+  // Initialise predictor values
+  Fp1 = Fp0; // plastic deformation tensor
+  q1->_epspbarre = q0->_epspbarre; // plastic equivalent strain
+  q1->_epspCompression = q0->_epspCompression;
+  q1->_epspTraction = q0->_epspTraction;
+  q1->_epspShear = q0->_epspShear;
+  q1->_backsig = q0->_backsig; // backstress tensor
+  q1->_DbackSigDT = q0->_DbackSigDT; // DbackSigDT
+  q1->_DgammaDt = 0.;
+
+  // Get hardening parameters
+  this->mlawNonLinearTVP::hardening(q0,q1,T);
+  static fullVector<double> a(3), Da(3); // yield coefficients and derivatives with respect to plastic deformation
+  this->mlawNonLinearTVP::getYieldCoefficients(q1,a);
+  //a.print("a init");
+
+  double Hb(0.), dHb(0.), ddHb(0.), dHbdT(0.), ddHbdgammadT(0.), ddHbddT(0.);
+  if (q1->_ipKinematic != NULL){
+    Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+    dHb = q1->_ipKinematic->getDR(); // kinematic hardening parameter derivative (dHb/dgamma)
+    dHbdT = q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file
+    ddHbddT = q1->_ipKinematic->getDDRDTT();
+    ddHbdgammadT = q1->_ipKinematic->getDDRDT();
+  }
+
+  double eta(0.),Deta(0.),DetaDT(0.);
+  if (_viscosity != NULL)
+    _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+
+  // Get Cepr, Ceinvpr
+  static STensor3 Fpinv, Ce, Fepr;
+  STensorOperation::inverseSTensor3(Fp1,Fpinv);
+  STensorOperation::multSTensor3(F,Fpinv,Fepr);
+  STensorOperation::multSTensor3FirstTranspose(Fepr,Fepr,Ce);
+
+  static STensor3 Eepr, Cepr, Ceinvpr;
+  Cepr = Ce;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  static STensor3 invFp0; // plastic predictor
+  invFp0= Fpinv;
+  STensor3& Fe = q1->_Fe;
+  Fe = Fepr;
+
+  // Predictor - TVE
+  static STensor43 DlnDCepr, DlnDCe;
+  static STensor63 DDlnDDCe;
+  static STensor3 expGN, GammaN;
+  static STensor43 dexpAdA; // estimation of dexpA/dA
+  expGN = _I; // if Gamma = 0, expGN = _I
+  // dexpAdA = _I4;
+  STensorOperation::zero(dexpAdA); // CHECKERS
+
+  STensor3& Ee = q1->_Ee;
+  // STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  bool ok=STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  if(!ok)
+  {
+     P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
+     return;
+  }
+  Ee *= 0.5;
+  Eepr = Ee;
+  DlnDCe = DlnDCepr;
+
+  // update A, B -> ExtraBranch calculations are within
+  double Ke(0.), Ge(0.), Ke_pr(0.), Ge_pr(0.);
+  static STensor43 Ge_Tensor_pr, Ge_Tensor, Bd_stiffnessTerm, Ge_TrEeTensor_pr, Ge_TrEeTensor;
+  STensorOperation::zero(Ge_Tensor_pr); STensorOperation::zero(Ge_Tensor);
+  STensorOperation::zero(Ge_TrEeTensor_pr); STensorOperation::zero(Ge_TrEeTensor);
+
+  // NEW EIGEN
+  static fullVector<int> alignedIndex(3); alignedIndex(0) = 0; alignedIndex(1) = 1; alignedIndex(2) = 2;
+  STensor3& R = q1->_R;
+  STensor43& dRdEe = q1->_dRdEe;
+  STensor43& dRtdEe = q1->_dRtdEe;
+  static STensor3 Ee0_rot;
+  static STensor43 rotationStiffness_pr ,rotationStiffness;
+  STensorOperation::zero(rotationStiffness_pr); STensorOperation::zero(rotationStiffness);
+  q1->_Ee0 = q0->_Ee;
+  if (_rotationCorrectionScheme == 0 && _rotationCorrectionScheme == 1){
+	  mlawNonLinearTVM::rotationTensor_N_to_Nplus1(q0->_Ee0,q0->_Fp,Fp1,Ce,Ee,q0->_Ee,R,dRdEe,dRtdEe);
+	  for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++){
+			  Ee0_rot(i,j) = 0.;
+			  for(int k=0; k<3; k++)
+				  for(int l=0; l<3; l++)
+					  Ee0_rot(i,j) += R(i,k)*q0->_Ee(k,l)*R(j,l);
+		  }
+  }
+  else if(_rotationCorrectionScheme == 2){
+	  Ee0_rot = q0->_Ee;
+	  STensorOperation::alignEigenDecomposition_NormBased_indexOnly(q0->_Ee,Ee,alignedIndex);
+  }
+  // NEW EIGEN
+
+  if (_extraBranchNLType == TensionCompressionRegularisedType  || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
+      // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm,&Ge_TrEeTensor);
+	  }
+	  else{
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,stiff,alignedIndex,Bd_stiffnessTerm,&Ge_TrEeTensor,&rotationStiffness); // NEW EIGEN
+	  }
+      Ge_TrEeTensor_pr = Ge_TrEeTensor;
+      rotationStiffness_pr = rotationStiffness;
+  }
+  else{
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
+	  }
+	  else{
+	      mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,stiff,alignedIndex,Bd_stiffnessTerm,NULL,&rotationStiffness); // NEW EIGEN
+	  }
+	  rotationStiffness_pr = rotationStiffness;
+  }
+
+  Ge_Tensor = _I4;
+  Ge_Tensor *= Ge*2; // Because the function does not do it
+  Ge_Tensor += Bd_stiffnessTerm;
+
+  // Keep the predictor values of Ke and Ge for tangents later
+  Ke_pr = Ke;
+  Ge_pr = Ge;
+  Ge_Tensor_pr = _I4;
+  Ge_Tensor_pr *= Ge_pr*2; // Because the function does not do it
+  Ge_Tensor_pr += Bd_stiffnessTerm;
+
+/*
+  // NEW - EIGEN
+  static STensor3 Fp0inv, Ce0, Fe0;
+  STensorOperation::inverseSTensor3(Fp0,Fp0inv);
+  STensorOperation::multSTensor3(F0,Fpinv,Fe0);
+  STensorOperation::multSTensor3FirstTranspose(Fe0,Fe0,Ce0);
+
+  static fullMatrix<double> m1(3, 3), m2(3, 3), m3(3, 3), m4(3, 3), m5(3, 3);
+  static fullVector<double> eigenValReal1(3), eigenValReal2(3), eigenValReal3(3), eigenValReal4(3), eigenValReal5(3);
+  static fullVector<double> eigenValImag1(3), eigenValImag2(3), eigenValImag3(3), eigenValImag4(3), eigenValImag5(3);
+  static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3), leftEigenVect3(3,3), leftEigenVect4(3,3), leftEigenVect5(3,3);
+  static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), rightEigenVect3(3,3), rightEigenVect4(3,3), rightEigenVect5(3,3);
+  m1.setAll(0.); m2.setAll(0.); m3.setAll(0.); m4.setAll(0.); m5.setAll(0.);
+  eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); eigenValReal3.setAll(0.); eigenValReal4.setAll(0.); eigenValReal5.setAll(0.);
+  eigenValImag1.setAll(0.); eigenValImag2.setAll(0.); eigenValImag3.setAll(0.); eigenValImag4.setAll(0.); eigenValImag5.setAll(0.);
+  leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.); leftEigenVect3.setAll(0.); leftEigenVect4.setAll(0.); leftEigenVect5.setAll(0.);
+  rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); rightEigenVect3.setAll(0.); rightEigenVect4.setAll(0.); rightEigenVect5.setAll(0.);
+
+  // Get eigen values and vectors
+  q1->_kirchhoff.getMat(m1); Ce.getMat(m2); Ee.getMat(m3); q0->_Ee.getMat(m4); Ee0_rot.getMat(m5);
+  m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+  m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+  m3.eig(eigenValReal3,eigenValImag3,leftEigenVect3,rightEigenVect3,false);
+  m4.eig(eigenValReal4,eigenValImag4,leftEigenVect4,rightEigenVect4,false);
+  m5.eig(eigenValReal5,eigenValImag5,leftEigenVect5,rightEigenVect5,false);
+  // NEW - EIGEN
+*/
+
+  // get predictor - dKeprDT
+  mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T);
+  const STensor3& dKeprDT = q1->_DcorKirDT; // This has all extrabranches now
+
+  // Initialise Dho
+  static STensor43 Dho, Dho2inv, Dho2_u_inv;  // These will be important tensors.
+  double Dho2_v_inv(0.);
+
+  // Get Kepr
+  static STensor3 Kepr;  // Ke is corKir
+  Kepr = q1->_kirchhoff;
+
+  // Get Xn; Initialise X
+  static STensor3 devXn, devX;
+  static double trXn, pXn, eXn, trX;
+  STensorOperation::decomposeDevTr(q0->_backsig,devXn,trXn); // needed for chaboche model
+  pXn = 1./3.*trXn;  // 1st invariant of Xn
+  eXn = sqrt(1.5*devXn.dotprod()); // J2 invariant of Xn
+
+  // Initialise Phipr
+  static STensor3 PhiPr, Phi;
+  PhiPr = q1->_kirchhoff;
+  PhiPr -= q1->_backsig;
+  Phi = PhiPr;
+
+  static STensor3 devPhipr, devPhi; // effective dev stress predictor
+  double ptildepr(0.), ptilde(0.);
+  STensorOperation::decomposeDevTr(PhiPr,devPhipr,ptildepr);
+  ptildepr/= 3.;
+
+  // Initialise Normal
+  static STensor3 devN, N; // dev part of yield normal
+  double trN = 0.; // trace part of yield normal
+  STensorOperation::zero(devN);
+  STensorOperation::zero(N);
+
+  // Get plastic poisson ratio
+  q1->_nup = (9.-2.*_b)/(18.+2.*_b);
+  double kk = (1./sqrt(1.+2.*q1->_nup*q1->_nup));
+
+  // Initialise variables
+  double& Gamma = q1->_Gamma;   // flow rule parameter
+  Gamma = 0.;
+  double dDgammaDGamma = 0.;
+  double Dgamma = 0.; // eqplastic strain increment
+  static fullVector<double> m(2);
+  mlawNonLinearTVP::getChabocheCoeffs(m,0,q1);
+
+  double DfDGamma(0.), dfdDgamma(0.), dfdGamma(0.), dAdDgamma(0.), dAdGamma(0.);
+
+  // Initialise Cx
+  double Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;        // pow(kk,2) DEBUG
+  double Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+  double dCxdevdDgamma(0.), dCxtrdDgamma(0.);
+  if (Hb>0.){
+    Cxdev -= m(0)*dHb*Dgamma/Hb + 1./Hb * dHbdT * (T-T0);
+    Cxtr -= m(0)*dHb*Dgamma/Hb + 1./Hb * dHbdT * (T-T0);
+  }
+
+  // Initialise ptilde and devPhi
+  ptilde = ptildepr;
+  devPhi = devPhipr;
+
+  // Initialise the rest
+  if (_extraBranchNLType == TensionCompressionRegularisedType  || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
+    // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3
+    getDho(Gamma,Cepr,Ceinvpr,Kepr,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,&Ge_TrEeTensor,&rotationStiffness);
+  }
+  else{
+    getDho(Gamma,Cepr,Ceinvpr,Kepr,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,NULL,&rotationStiffness);
+  }
+
+  double PhiEqpr2 = 1.5*devPhi.dotprod();
+  double PhiEqpr = sqrt(PhiEqpr2);      // -> second invariant
+  double PhiEq = PhiEqpr;   // current effective deviator
+
+  // Get f and A
+  double f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+  double A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+  // Initialise g
+  double dgdDgamma(0.), dgdGamma(0.);
+  double g = Dgamma - kk*Gamma*A;
+
+  // NR Loop - Gamma and Dgamma
+    if (q1->dissipationIsBlocked()){
+        q1->getRefToDissipationActive() = false;
+    }
+    else{
+        if (f>_tol){
+        	// Msg::Error("Plasticity");
+            q1->getRefToDissipationActive() = true;
+
+            // plasticity
+            int ite = 0;
+            int maxite = 100; // maximal number of iters
+            // Msg::Error("plasticity occurs f = %e",f);
+            //double f0 = fabs(f);
+
+            while (fabs(f) >_tol or ite <1){
+
+                // Viscosity term
+                double etaOverDt = eta/this->getTimeStep();
+
+                // Get dCxdevdDgamma, dCxtrdDgamma
+                dCxdevdDgamma = 0.; dCxtrdDgamma = 0.;
+                if (Hb>0.){
+                    dCxdevdDgamma = -m(0)*1./Hb*dHb - m(0)*Dgamma*(-1./pow(Hb,2.)*pow(dHb,2.) + 1./Hb*ddHb) - (T-T0)*(-1./pow(Hb,2.)*dHb*dHbdT + 1./Hb*ddHbdgammadT);
+                    dCxtrdDgamma = dCxdevdDgamma;
+                }
+                dCxdevdDgamma += 3.*m(1)*pow(kk,1)*dHb;        // pow(kk,2) DEBUG
+                dCxtrdDgamma += (2.*_b/3.)*m(1)*pow(kk,1)*dHb; // pow(kk,2) DEBUG
+
+                // Get Hp = dPhiPdDgamma, dPhiPdGamma
+                double Hp =  ( 2*_b*pow(kk,1)*Gamma/3.*ptilde*(Hb/pow(Cxtr,2)*dCxtrdDgamma-1./Cxtr*dHb) + 1./3.*trXn/pow(Cxtr,2)*dCxtrdDgamma ) * Dho2_v_inv; // pow(kk,2) DEBUG
+                double dPhiPdGamma = -2*_b*ptilde*(Ke + pow(kk,1)*Hb/(3.*Cxtr)) * Dho2_v_inv; // pow(kk,2) DEBUG
+
+                // Get He = dPhiEdGamma
+                // Get DdevPhidGamma
+                static STensor3 DdevPhidDgamma, DdevPhidDgamma_RHS;
+                static STensor3 DdevPhidGamma, DdevPhidGamma_RHS;
+                STensorOperation::zero(DdevPhidDgamma); STensorOperation::zero(DdevPhidGamma);
+                STensorOperation::zero(DdevPhidDgamma_RHS); STensorOperation::zero(DdevPhidGamma_RHS);
+
+                for (int i=0; i<3; i++)
+                    for (int j=0; j<3; j++){
+                        DdevPhidDgamma_RHS(i,j) += ( 3*Gamma*pow(kk,1)*( Hb/pow(Cxdev,2.)*dCxdevdDgamma - dHb/Cxdev ) * devPhi(i,j)
+                                                    + devXn(i,j)/pow(Cxdev,2.)*dCxdevdDgamma ); // pow(kk,2) DEBUG
+                        DdevPhidGamma_RHS(i,j) += (- 3*pow(kk,1)*Hb/Cxdev*devPhi(i,j) ); // pow(kk,2) DEBUG
+                        for (int k=0; k<3; k++)
+                            for (int l=0; l<3; l++){
+                                DdevPhidDgamma_RHS(i,j) += 2.*_b/3.*Gamma*( - Ge_TrEeTensor(i,j,k,l) - rotationStiffness(i,j,k,l))*_I(k,l)*Hp; // EIGEN
+                                DdevPhidGamma_RHS(i,j) += ( -3.*Ge_Tensor(i,j,k,l)*devPhi(k,l) + 2.*_b/3.*Gamma*(- Ge_TrEeTensor(i,j,k,l) - rotationStiffness(i,j,k,l) )*_I(k,l)*dPhiPdGamma ); // EIGEN
+                                DdevPhidGamma_RHS(i,j) += (-Ge_TrEeTensor(i,j,k,l) - rotationStiffness(i,j,k,l) )*N(k,l); // DEBUG // EIGEN
+                            }
+                    }
+                for (int i=0; i<3; i++)
+                    for (int j=0; j<3; j++)
+                        for (int k=0; k<3; k++)
+                            for (int l=0; l<3; l++){
+                                DdevPhidDgamma(i,j) += Dho2_u_inv(i,j,k,l)*DdevPhidDgamma_RHS(k,l);
+                                DdevPhidGamma(i,j) += Dho2_u_inv(i,j,k,l)*DdevPhidGamma_RHS(k,l);
+                            }
+
+                double Stemp1 = STensorOperation::doubledot(devPhi,DdevPhidDgamma);
+                double Stemp2 = STensorOperation::doubledot(devPhi,DdevPhidGamma);
+                double He = 1.5*Stemp1/PhiEq;
+                double dPhiEdGamma = 1.5*Stemp2/PhiEq;
+
+
+                // dAdGamma and dDgammaDGamma
+                dAdDgamma = (12.*PhiEq*He + 8.*_b*_b*ptilde*Hp/3.)/(2.*A);
+                dAdGamma = (12.*PhiEq*dPhiEdGamma + 8.*_b*_b*ptilde*dPhiPdGamma/3.)/(2.*A);
+
+                dDgammaDGamma = pow(kk,1)*(A+Gamma*dAdGamma);  // mistake in the paper (VD 2016) // pow(kk,2) DEBUG
+
+                this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+
+                dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0);
+                dfdDgamma += a(2)*_n*pow(PhiEq,(_n-1.))*He - a(1)*Hp;
+
+                if (Gamma>0 and etaOverDt>0)
+                    dfdDgamma -= _p*pow(etaOverDt,_p-1.)*Deta/this->getTimeStep()*pow(Gamma,_p);  // THIS term is absent in the paper!!
+
+                dfdGamma = _n*a(2)*pow(PhiEq,(_n-1.))*dPhiEdGamma - a(1)*dPhiPdGamma;
+                if (Gamma>0 and etaOverDt>0)
+                    dfdGamma -= pow(etaOverDt,_p)*_p*pow(Gamma,(_p-1.));
+
+                DfDGamma = dfdDgamma*dDgammaDGamma + dfdGamma; // unused
+
+                dgdDgamma = 1. - kk*Gamma*dAdDgamma;
+                dgdGamma = - dDgammaDGamma;
+
+                double dGamma = (-f + dfdDgamma*g/dgdDgamma)/(-dfdDgamma*dgdGamma/dgdDgamma + dfdGamma); // NR
+                double dDgamma = -(g+dgdGamma*dGamma)/dgdDgamma; // NR
+
+                if (Gamma + dGamma <=0.){
+                    Gamma /= 2.;                // NR
+                }
+                else
+                    Gamma += dGamma;
+
+                // Dgammma_test += dDgamma;
+                if (Dgamma + dDgamma <=0.){
+                    Dgamma /= 2.;
+                }
+                else
+                    Dgamma += dDgamma;
+
+                //Msg::Error("Gamma = %e",Gamma);
+                //Msg::Error("Dgamma = %e",Dgamma);
+
+
+                // UPDATE FOR NEXT ITERATION
+
+                // Update gamma and all Hardening moduli
+                mlawNonLinearTVP::updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                mlawNonLinearTVP::hardening(q0,q1,T);
+                mlawNonLinearTVP::getYieldCoefficients(q1,a);
+                if (q1->_ipKinematic != NULL){
+                    Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+                    dHb = q1->_ipKinematic->getDR(); // kinematic hardening parameter derivative (dHb/dgamma ??)
+                    dHbdT = q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+                    ddHbddT = q1->_ipKinematic->getDDRDTT();
+                    ddHbdgammadT = q1->_ipKinematic->getDDRDT();
+                }
+                //a.print("a update");
+
+                // Update Viscosity -> NEW 23rd May,2024
+                if (_viscosity != NULL)
+                    _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+
+                // Update Cx
+                Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+                Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb; // pow(kk,2) DEBUG
+                if (Hb>0.){
+                    Cxdev -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                    Cxtr -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                }
+
+                // Update Phi
+                if (_extraBranchNLType == TensionCompressionRegularisedType  || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
+                    // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3
+                    getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                                    Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1,alignedIndex,&Ge_TrEeTensor,&rotationStiffness);
+                }
+                else{
+                    getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                                    Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1,alignedIndex,NULL,&rotationStiffness);
+                }
+
+                PhiEq = sqrt(1.5*devPhi.dotprod());
+
+                // Update A
+                A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+                /*
+                Dgamma = pow(kk,1)*Gamma*A;  // pow(kk,2) DEBUG
+                updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                hardening(q0,q1,T);
+                getYieldCoefficients(q1,a);*/
+
+                // Update f, g
+                f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+                double viscoTerm = etaOverDt*Gamma;
+                if (Gamma>0. and etaOverDt>0.) f-= pow(viscoTerm,_p);
+
+                g = Dgamma - kk*Gamma*A;
+
+                ite++;
+                // if (ite> maxite-5)
+                // Msg::Error("it = %d, DfDGamma = %e error = %e dGamma = %e, Gamma = %e",ite,DfDGamma,f,dGamma,Gamma);
+
+                if (fabs(f) <_tol) break;
+
+                if(ite > maxite){
+                    Msg::Error("No convergence for plastic correction in mlawNonLinearTVENonLinearTVP2 nonAssociatedFlow iter = %d, f = %e!!",ite,f);
+                    P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
+                    return;
+                }
+
+            } // while
+
+            q1->_DgammaDt = Dgamma/this->getTimeStep();
+
+            // Correct Cx
+            Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+            Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb; // pow(kk,2) DEBUG
+            if (Hb>0.){
+                Cxdev -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                Cxtr -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+            }
+
+            // Correct Phi
+            if (_extraBranchNLType == TensionCompressionRegularisedType || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
+                // TC asymmetry -> for either case of TensionCompressionRegularisedType and _ExtraBranch_TVE_option == 3
+                getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                    Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1,alignedIndex,&Ge_TrEeTensor,&rotationStiffness);
+            }
+            else{
+                getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                    Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1,alignedIndex,NULL,&rotationStiffness);
+            }
+            PhiEq = sqrt(1.5*devPhi.dotprod());
+
+            // Correct Normal, H = expGN
+            STensorOperation::decomposeDevTr(N,devN,trN);
+
+            // Get GammaN for mechSrcTVP -> done within the loop already
+            /*
+            STensorOperation::zero(GammaN);
+            GammaN = N;
+            GammaN *= Gamma;
+            q1->_GammaN = GammaN;*/
+
+            // Correct plastic deformation tensor
+            STensorOperation::multSTensor3(expGN,Fp0,Fp1);
+
+            // Correct IP gamma
+            updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                // Msg::Info("setting: gamma=%e ",q1->_epspbarre);
+
+            // Correct elastic deformation tensor, corotational stress
+            STensorOperation::inverseSTensor3(Fp1,Fpinv);
+            STensorOperation::multSTensor3(F,Fpinv,Fe);
+            STensorOperation::multSTensor3FirstTranspose(Fe,Fe,Ce);
+
+            bool ok=STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCe,&DDlnDDCe);
+            if(!ok)
+            {
+              P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
+              return;
+            }
+            Ee *= 0.5;
+
+            // Corrected corKir, mandel, backStress are already in the IP due to getIterated_DPhi
+            /*
+            // Correct A, B
+            mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
+            Ge_Tensor = _I4;
+            Ge_Tensor *= Ge*2; // *2 because the function doesnt do it
+            Ge_Tensor += Bd_stiffnessTerm;
+
+            // Correct backstress;
+            devX = (pow(kk,1)*Hb*Gamma*devN + devXn);  // pow(kk,2) DEBUG
+            devX *= 1./Cxdev;
+            trX = (pow(kk,1)*Hb*Gamma*trN + trXn)*1./Cxtr; // pow(kk,2) DEBUG
+            q1->_backsig = devX;
+            q1->_backsig(0,0) += trX/3.;
+            q1->_backsig(1,1) += trX/3.;
+            q1->_backsig(2,2) += trX/3.;
+
+            // Correct Mandel
+            q1->_ModMandel = devPhi;
+            q1->_ModMandel += q1->_backsig;
+            q1->_ModMandel(0,0) += (ptilde);
+            q1->_ModMandel(1,1) += (ptilde);
+            q1->_ModMandel(2,2) += (ptilde); */
+
+        } // 2nd if
+        else{
+            q1->getRefToDissipationActive() = false;
+        	// Msg::Error("Elasticity");
+        }
+    } // 1st if
+
+    // corKir
+    const STensor3& KS = q1->_kirchhoff;
+
+    // second Piola Kirchhoff stress
+    static STensor3 S, Ceinv;
+    STensorOperation::inverseSTensor3(Ce,Ceinv);
+    STensorOperation::multSTensor3STensor43(KS,DlnDCe,S);
+
+    // mandel_e
+    static STensor3 MS;
+    for(int i=0; i<3; i++)
+        for(int j=0; j<3; j++){
+        	MS(i,j) = 0.;
+            for(int k=0; k<3; k++)
+              MS(i,j) += Ce(i,k)*S(k,j);
+        }
+    q1->_ModMandel = MS;
+
+    // commuteChecker -> for commuting tensors Ce and Se, Me has to be symmetric ->
+    // 			For two cases, both in the case of viscoplasticity if Een and Ee dont share eigenvectors: 1. Due to plasticity (Rp)  2. Due to non-proportional loading
+    static STensor3 commuteChecker, MST;
+    STensorOperation::transposeSTensor3(MS,MST);
+    commuteChecker = MS;
+    commuteChecker -= MST;
+    q1->_mandelCommuteChecker = commuteChecker.norm0();
+    if(q1->_mandelCommuteChecker > 1.e-6){
+    	// Msg::Error("Mandel does not commute in mlawNonLinearTVENonLinearTVP2, norm = %e, tol = %e !!",q1->_mandelCommuteChecker,1.e-6);
+    }
+
+    // first PK
+    for(int i=0; i<3; i++)
+        for(int j=0; j<3; j++){
+            P(i,j) = 0.;
+            for(int k=0; k<3; k++)
+                for(int l=0; l<3; l++)
+                    P(i,j) += Fe(i,k)*S(k,l)*Fpinv(j,l);
+        }
+
+    // Msg::Error(" Inside TVP, after correction, after updating q1->_elasticEnergy = %e, eta = %e !!",q1->_elasticEnergy, eta_mullins);
+
+    // q1->getRefToElasticEnergy()=deformationEnergy(*q1);
+    q1->getRefToViscousEnergyPart()=viscousEnergy(*q0,*q1)+q0->getConstRefToViscousEnergyPart();
+    q1->getRefToPlasticEnergy() = q0->plasticEnergy();
+    if (Gamma > 0.){
+        double dotKSN = dot(KS,N);
+        q1->getRefToPlasticEnergy() += Gamma*dotKSN; // = Dp:Ke
+    }
+
+    // fluxT
+    double KThConT, DKThConDT;
+    mlawNonLinearTVM::getKTHCon(KThConT,T,&DKThConDT);
+    double J  = 1.;
+    STensor3 Finv(0.);
+    if (_thermalEstimationPreviousConfig){                                            // ADD  _thermalEstimationPreviousConfig
+        STensorOperation::inverseSTensor3(F0,Finv);
+        J = STensorOperation::determinantSTensor3(F0);
+    }
+    else{
+        STensorOperation::inverseSTensor3(F,Finv);
+        J = STensorOperation::determinantSTensor3(F);
+    }
+
+    static STensor3 Cinv;
+    STensorOperation::multSTensor3SecondTranspose(Finv,Finv,Cinv);
+    STensorOperation::multSTensor3SVector3(Cinv,gradT,fluxT);
+    fluxT *= (-KThConT*J);
+
+    // ThermSrc and MechSrc after dPdF and dPdT - But need the following tensors for the mechSrcTVP function call
+    static STensor3 DphiPDF;
+    STensorOperation::zero(DphiPDF);
+    STensorOperation::zero(dFpdF); //dFpdT
+    static STensor43 CeprToF, DEeDCepr, DEeDF, dGammaNdCepr; // conversion tensors
+    STensorOperation::zero(CeprToF);
+    STensorOperation::zero(DEeDCepr);
+    STensorOperation::zero(DEeDF);
+    STensorOperation::zero(dGammaNdCepr);
+
+    // I didnt make this
+    if (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DEFO_ENERGY){
+        q1->getRefToIrreversibleEnergy() = q1->defoEnergy();
+    }
+    else if ((this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::PLASTIC_ENERGY) or
+             (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DISSIPATION_ENERGY)){
+        q1->getRefToIrreversibleEnergy() = q1->plasticEnergy();
+    }
+    else{
+        q1->getRefToIrreversibleEnergy() = 0.;
+    }
+
+
+    if (stiff){
+
+        // dPdF
+
+        // 1. get Dp_pr_DCepr, DpDCepr
+        static STensor3 Dp_pr_DCepr, DpDCepr;
+        STensorOperation::multSTensor3STensor43(_I,DlnDCepr,Dp_pr_DCepr);
+        STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DpDCepr);
+        Dp_pr_DCepr*= (0.5*Ke_pr);
+        DpDCepr*= (0.5*Ke);
+
+        // Ke and Ge_Tensor are already corrected if Gamma>0. because of the NR loop on Phi - Reuse DcorKirDEe later
+        static STensor43 DcorKirDEe_pr, DcorKirDEe;
+        STensorOperation::zero(DcorKirDEe_pr);
+        STensorOperation::zero(DcorKirDEe);
+        for (int i=0; i<3; i++)
+            for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                    for (int l=0; l<3; l++){
+                        DcorKirDEe(i,j,k,l) += Ke*_I(i,j)*_I(k,l);
+                        DcorKirDEe_pr(i,j,k,l) += Ke_pr*_I(i,j)*_I(k,l);
+                        for (int p=0; p<3; p++)
+                            for (int q=0; q<3; q++){
+                                DcorKirDEe_pr(i,j,k,l) += Ge_Tensor_pr(i,j,p,q)*_Idev(p,q,k,l);
+                                DcorKirDEe(i,j,k,l) += Ge_Tensor(i,j,p,q)*_Idev(p,q,k,l);
+                            }
+                    }
+        DcorKirDEe_pr += Ge_TrEeTensor_pr; // TC Assymmetry
+        DcorKirDEe += Ge_TrEeTensor; // TC Assymmetry
+
+        // NEW EIGEN
+        DcorKirDEe_pr += rotationStiffness_pr;
+        DcorKirDEe += rotationStiffness;
+        // NEW EIGEN
+
+        static STensor43 DcorKir_pr_DCepr, DcorKirDCepr;
+        STensorOperation::multSTensor43(DcorKirDEe_pr,DlnDCepr,DcorKir_pr_DCepr);
+        STensorOperation::multSTensor43(DcorKirDEe,DlnDCepr,DcorKirDCepr);
+        DcorKir_pr_DCepr *= 0.5; // use for DMeprDCepr
+        DcorKirDCepr *= 0.5; // correct this one later
+
+        // 2. get DCeprDCepr = _I4 and DCeinvprDCepr
+        static STensor43 DCeinvprDCepr;
+
+        for (int i=0; i<3; i++)
+            for (int s=0; s<3; s++)
+                for (int k=0; k<3; k++)
+                    for (int l=0; l<3; l++){
+                        DCeinvprDCepr(i,s,k,l) = 0.;
+                        for (int m=0; m<3; m++)
+                            for (int j=0; j<3; j++)
+                                DCeinvprDCepr(i,s,k,l) -= Ceinvpr(i,m)*_I4(m,j,k,l)*Ceinvpr(j,s);
+          }
+
+        //
+        static STensor43 DdevCorKir_pr_DCepr;
+        STensorOperation::zero(DdevCorKir_pr_DCepr);
+        for (int i=0; i<3; i++)
+          for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+            	 DdevCorKir_pr_DCepr(i,s,k,l) += DcorKir_pr_DCepr(i,s,k,l) - _I(i,s)*Dp_pr_DCepr(k,l);
+
+        //4. get DdevphiDCepr and DphiPprDCepr; and DphiEprDCepr
+        static STensor3 DphiPDCepr, DphiEDCepr, DphiEDdevPhi;
+        static STensor43 DdevphiDCepr, DphiDCepr;
+
+        DphiPDCepr = Dp_pr_DCepr;
+        DdevphiDCepr = DdevCorKir_pr_DCepr;
+
+        if (PhiEq >0.){
+            DphiEDdevPhi = devPhi;
+            DphiEDdevPhi *= 1.5/(PhiEq);
+        }
+
+        STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+        DphiDCepr = DdevphiDCepr;
+        for (int i=0; i<3; i++)
+          for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+            	  DphiDCepr(i,s,k,l) += _I(i,s)*DphiPDCepr(k,l);
+
+        // 6. to 11. (inside if loop-> Gamma > 0.)
+        static STensor3 dAdCepr, dfDCepr, dgDCepr, DGDCepr, DgammaDCepr, DtrNDCepr, dTrXdCepr;
+        static STensor43 DdevNDCepr, dFpDCepr, dDevXdCepr, dXdCepr;
+
+        if (Gamma >0.){
+
+            //5.1 update DphiPDCepr to include the Gamma term
+            STensorOperation::zero(DphiPDCepr);
+            STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DphiPDCepr);
+            DphiPDCepr*= (0.5*Ke);
+            DphiPDCepr *= Dho2_v_inv;
+
+            // update DpDCepr (needed for DdevphiDCepr)
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                DpDCepr(i,j) -= Ke*2*_b*(Gamma*DphiPDCepr(i,j));
+
+            //5.2 update DdevphiDCepr to include the Gamma term
+            STensorOperation::zero(DdevphiDCepr);
+
+            // get G1 tensor
+            // static STensor43 G1;
+            // mlawNonLinearTVENonLinearTVP2::get_G1_Tensor(Cepr,expGN,DCeinvprDCepr,KS,G1);
+
+            // get RHS
+            static STensor43 DdevphiDCepr_RHS;
+            STensorOperation::zero(DdevphiDCepr_RHS);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++){
+
+                        DdevphiDCepr_RHS(i,j,k,l) +=  ( (Ge_TrEeTensor(i,j,p,q) + rotationStiffness(i,j,p,q) )*0.5*DlnDCepr(p,q,k,l) +
+                                        (-Ge_TrEeTensor(i,j,p,q) - rotationStiffness(i,j,p,q))* ( 2.*_b*Gamma/3.*_I(p,q)*DphiPDCepr(k,l) ) );  // EIGEN
+
+                        for (int r=0; r<3; r++)
+                          for (int s=0; s<3; s++){
+
+                            DdevphiDCepr_RHS(i,j,k,l) +=  ( Ge_Tensor(i,j,p,q)*_Idev(p,q,r,s)*0.5*DlnDCepr(r,s,k,l));
+                          }
+
+                      }
+                  } // DEBUG
+            // DdevphiDCepr = DdevMeprDCepr; // DEBUG
+            // STensorOperation::multSTensor43(Dho2_u_inv,DdevMeprDCepr,DdevphiDCepr); // DEBUG
+            STensorOperation::multSTensor43(Dho2_u_inv,DdevphiDCepr_RHS,DdevphiDCepr); // DEBUG
+            STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+            //6. get dAdCepr, dfDCepr
+            double fact = a(2)*_n*pow(PhiEq,_n-1.);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                dAdCepr(i,j) = ( 4./3.*_b*_b*ptilde*DphiPDCepr(i,j) + 6.*PhiEq*DphiEDCepr(i,j) )/A;
+                dfDCepr(i,j) = fact*DphiEDCepr(i,j)-a(1)*DphiPDCepr(i,j);
+                // dgDCepr(i,j) = -kk*Gamma*dAdCepr(i,j);
+              }
+            dgDCepr = dAdCepr;
+            dgDCepr *= (-kk*Gamma);
+
+            //7. get DGDCepr, DgammaDCepr
+            for (int i=0; i<3; i++)
+                for (int j=0; j<3; j++){
+                    DGDCepr(i,j) = (-dfDCepr(i,j) + dfdDgamma*dgDCepr(i,j)/dgdDgamma)/(dfdGamma - dfdDgamma*dgdGamma/dgdDgamma);
+                    DgammaDCepr(i,j) = (-dgdGamma*DGDCepr(i,j) - dgDCepr(i,j))/dgdDgamma;
+                }
+
+            //8.1 update DphiPDCepr
+            STensorOperation::zero(DphiPDCepr);
+            STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DphiPDCepr);
+            DphiPDCepr*= (0.5*Ke);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                DphiPDCepr(i,j) += ( - Ke* 2.*_b*ptilde*DGDCepr(i,j)
+                                    - 2.*_b*pow(kk,1)/3. * ( (dHb/Cxtr - Hb/pow(Cxtr,2)*dCxtrdDgamma)*DgammaDCepr(i,j)*Gamma*ptilde + Hb/Cxtr*DGDCepr(i,j)*ptilde )
+                                    + 1./3.*trXn/pow(Cxtr,2)*dCxtrdDgamma*DgammaDCepr(i,j));
+                                    // DEBUG pow(kk,2)
+              }
+            DphiPDCepr *= Dho2_v_inv;
+
+            // update DpDCepr (needed for DdevphiDCepr)
+            STensorOperation::zero(DpDCepr);
+            STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DpDCepr);
+            DpDCepr*= (0.5*Ke);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                DpDCepr(i,j) -= Ke*2*_b*( DGDCepr(i,j)*ptilde + Gamma*DphiPDCepr(i,j));
+
+            //8.2 update DdevphiDCepr and DphiEDCepr
+            STensorOperation::zero(DdevphiDCepr);
+
+            // get G1 tensor
+            // mlawNonLinearTVENonLinearTVP2::get_G1_Tensor(Cepr,expGN,DCeinvprDCepr,KS,G1);
+
+            // get RHS
+            // static STensor43 DdevphiDCepr_RHS;
+            STensorOperation::zero(DdevphiDCepr_RHS);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+
+                    DdevphiDCepr_RHS(i,j,k,l) += ( - 3.*pow(kk,1)*( ( dHb/Cxdev - Hb/pow(Cxdev,2)*dCxdevdDgamma )*Gamma*devPhi(i,j)*DgammaDCepr(k,l) + Hb/Cxdev*devPhi(i,j)*DGDCepr(k,l) )
+                            + 1./pow(Cxdev,2)*dCxdevdDgamma*devXn(i,j)*DgammaDCepr(k,l)); // DEBUG pow(kk,2)
+
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++){
+
+                        DdevphiDCepr_RHS(i,j,k,l) +=  ( - 3.*Ge_Tensor(i,j,p,q)*devPhi(p,q)*DGDCepr(k,l)
+                                                    + (-Ge_TrEeTensor(i,j,p,q) -rotationStiffness(i,j,p,q)) * ( N(p,q)*DGDCepr(k,l) + 2.*_b*Gamma/3.*_I(p,q)*DphiPDCepr(k,l) )
+                                                    +  (Ge_TrEeTensor(i,j,p,q) + rotationStiffness(i,j,p,q)) *0.5*DlnDCepr(p,q,k,l) ) ; // EIGEN
+                        for (int r=0; r<3; r++)
+                          for (int s=0; s<3; s++){
+
+                            DdevphiDCepr_RHS(i,j,k,l) +=  ( Ge_Tensor(i,j,p,q)*_Idev(p,q,r,s)*0.5*DlnDCepr(r,s,k,l) );
+                          }
+
+                      }
+                  }
+
+            STensorOperation::multSTensor43(Dho2_u_inv,DdevphiDCepr_RHS,DdevphiDCepr);
+            STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+            DphiDCepr = DdevphiDCepr;
+            for (int i=0; i<3; i++)
+              for (int s=0; s<3; s++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                	  DphiDCepr(i,s,k,l) += _I(i,s)*DphiPDCepr(k,l);
+
+            //9. get DtrNDCepr DdevNdCepr
+            DtrNDCepr = DphiPDCepr;
+            DtrNDCepr *= (2.*_b);
+
+            DdevNDCepr = DdevphiDCepr;
+            DdevNDCepr *= 3.;
+
+            /*
+            //0.0 Numerical Derivatives wrt Cepr
+            double ptilde_plus, Gamma_plus, Dgamma_plus, A_plus, f_plus;
+            static STensor3 devPhi_plus, Me_plus, P_plus;
+            static IPNonLinearTVP qPlus(*q0);
+
+            static STensor3 Cepr_plus, Fepr_plus, DphiPDCepr_plus, DGDCepr_plus, DgammaDCepr_plus, dAdCepr_plus, dfDCepr_plus;
+            static STensor43 DdevphiDCepr_plus;
+            Fepr_plus = Fepr;
+            for (int i=0; i<3; i++){
+              for (int j=0; j<3; j++){
+                Cepr_plus = Cepr;
+                Cepr_plus(i,j) += 0.5*_perturbationfactor;
+                Cepr_plus(j,i) += 0.5*_perturbationfactor;
+
+
+                TEST_predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(F0,F,q0,&qPlus,T0,T,
+                        Fepr_plus,Cepr_plus,ptilde_plus,devPhi_plus,Gamma_plus,Dgamma_plus,A_plus,f_plus,Me_plus,P_plus);
+
+
+                DGDCepr_plus(i,j) = (Gamma_plus-Gamma)/_perturbationfactor;
+                DgammaDCepr_plus(i,j) = (Dgamma_plus-Dgamma)/_perturbationfactor;
+                dAdCepr_plus(i,j) = (A_plus-A)/_perturbationfactor;
+                dfDCepr_plus(i,j) = (f_plus-f)/_perturbationfactor;
+                DphiPDCepr_plus(i,j) = (ptilde_plus-ptilde)/_perturbationfactor;
+
+                for (int k=0; k<3; k++){
+                  for (int l=0; l<3; l++){
+                      DdevphiDCepr_plus(k,l,i,j) = (devPhi_plus(k,l)-devPhi(k,l))/_perturbationfactor;
+                  }
+                }
+              }
+            }*/
+
+            // 10. get dFpDCepr
+            STensorOperation::zero(dGammaNdCepr);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    dGammaNdCepr(i,j,k,l) = N(i,j)*DGDCepr(k,l) + Gamma*DdevNDCepr(i,j,k,l) + Gamma/3.*_I(i,j)*DtrNDCepr(k,l);
+
+            static STensor43 CeprFp0;
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    CeprFp0(i,j,k,l) = 0.;
+                    for (int s=0; s<3; s++){
+                      CeprFp0(i,j,k,l) += dexpAdA(i,s,k,l)*Fp0(s,j);
+                    }
+                  }
+
+            STensorOperation::multSTensor43(CeprFp0,dGammaNdCepr,dFpDCepr);
+
+            // 10.1 get dXDCepr
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                dTrXdCepr(i,j) = pow(kk,1.)*( (dHb/Cxtr - Hb/pow(Cxtr,2)*dCxtrdDgamma)*Gamma*trN*DgammaDCepr(i,j) +
+                                        Hb/Cxtr*( trN*DGDCepr(i,j) + Gamma*DtrNDCepr(i,j) ) )
+                                        - trXn/pow(Cxtr,2)*dCxtrdDgamma*DgammaDCepr(i,j); // pow(kk,2.) DEBUG
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    dDevXdCepr(i,j,k,l) = pow(kk,1.)*( (dHb/Cxdev - Hb/pow(Cxdev,2)*dCxdevdDgamma)*Gamma*devN(i,j)*DgammaDCepr(k,l) +
+                                                Hb/Cxdev*( devN(i,j)*DGDCepr(k,l) + Gamma*DdevNDCepr(i,j,k,l) ) )
+                                                - 1./pow(Cxdev,2)*dCxdevdDgamma*devXn(i,j)*DgammaDCepr(k,l); // pow(kk,2.) DEBUG
+                  }
+                }
+
+            STensorOperation::zero(dXdCepr);
+            dXdCepr = dDevXdCepr;
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    dXdCepr(i,j,k,l) += 1./3. * _I(i,j)*dTrXdCepr(k,l);
+
+            // 11. update DcorKirDCepr
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++)
+                        DcorKirDCepr(i,j,k,l) -= DcorKirDEe(i,j,p,q)*dGammaNdCepr(p,q,k,l);
+        } // if Gamma
+        else{
+            // elastic
+            STensorOperation::zero(DgammaDCepr); STensorOperation::zero(DGDCepr); STensorOperation::zero(DtrNDCepr);
+            STensorOperation::zero(dFpDCepr); STensorOperation::zero(dTrXdCepr); STensorOperation::zero(DdevNDCepr);
+            STensorOperation::zero(dDevXdCepr); STensorOperation::zero(dXdCepr); STensorOperation::zero(dGammaNdCepr);
+        }
+
+        // 12. get  CeprToF conversion tensor
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                CeprToF(i,j,k,l) = 2.*Fepr(k,i)*invFp0(j,l);
+
+        // 13. get DcorKirDF
+        static STensor43 DKcorDF;
+        STensorOperation::multSTensor43(DcorKirDCepr,CeprToF,DKcorDF);
+
+        // 14. dXdF, dGammaNdF, DphiPDF for mechSrc
+        STensor43& dXdF = q1->getRefToDbackStressdF();
+        STensorOperation::zero(dXdF);
+        STensorOperation::multSTensor43(dXdCepr,CeprToF,dXdF);
+
+        STensor43& dGammaNdF = q1->_dGammaNdF;
+        STensorOperation::zero(dGammaNdF);
+        STensorOperation::multSTensor43(dGammaNdCepr,CeprToF,dGammaNdF);
+
+        // DphiPDCepr - use this for the pressure term in R
+        STensorOperation::zero(DphiPDF);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                DphiPDF(i,j) = DphiPDCepr(k,l)*CeprToF(k,l,i,j);
+
+        // 15. get DgammaDF
+        STensor3& DgammaDF = q1->_DgammaDF;
+        STensor3& DGammaDF = q1->_DGammaDF;
+        STensor43& DphiDF = q1->_DphiDF;
+        STensorOperation::zero(DgammaDF);
+        STensorOperation::zero(DGammaDF);
+        STensorOperation::zero(DphiDF);
+        if (Gamma > 0){
+          STensorOperation::multSTensor3STensor43(DgammaDCepr,CeprToF,DgammaDF);
+          STensorOperation::multSTensor3STensor43(DGDCepr,CeprToF,DGammaDF);
+          STensorOperation::multSTensor43(dFpDCepr,CeprToF,dFpdF);
+        }
+        STensorOperation::multSTensor43(DphiDCepr,CeprToF,DphiDF);
+
+        // 16. Everything else - Conversion Tensors
+        static STensor43 DinvFpDF, dCedF, dCeinvDF;
+        for (int i=0; i<3; i++)
+          for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                DinvFpDF(i,s,k,l) = 0.;
+                for (int m=0; m<3; m++)
+                  for (int j=0; j<3; j++)
+                    DinvFpDF(i,s,k,l) -= Fpinv(i,m)*dFpdF(m,j,k,l)*Fpinv(j,s);
+              }
+
+        for (int m=0; m<3; m++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dFedF(m,j,k,l) = _I(m,k)*Fpinv(l,j);
+                for (int s=0; s<3; s++)
+                  dFedF(m,j,k,l) += F(m,s)*DinvFpDF(s,j,k,l);
+              }
+
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dCedF(i,j,k,l) = 0.;
+                for (int p=0; p<3; p++){
+                    dCedF(i,j,k,l) += Fe(p,i)*dFedF(p,j,k,l) + dFedF(p,i,k,l)*Fe(p,j); // This Works!
+                }
+              }
+
+        for (int i=0; i<3; i++)
+          for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dCeinvDF(i,s,k,l) = 0.;
+                for (int m=0; m<3; m++)
+                  for (int j=0; j<3; j++)
+                    dCeinvDF(i,s,k,l) -= Ceinv(i,m)*dCedF(m,j,k,l)*Ceinv(j,s);
+              }
+
+        // 17. Tangent - dPdF
+        static STensor43 dSdCepr, dSdF, dMedCepr;
+        STensor43& dMedF = q1->getRefToDModMandelDF();
+        STensorOperation::zero(dMedF);
+
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                dMedF(i,j,k,l) = DKcorDF(i,j,k,l);  // KS is corKir
+
+
+        static STensor63 DlnDF;
+        if (_order != 1){
+          for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+              for (int k=0; k<3; k++){
+                for (int l=0; l<3; l++){
+                  for (int p=0; p<3; p++){
+                    for (int q=0; q<3; q++){
+                      DlnDF(i,j,k,l,p,q) = 0.;
+                      for (int r=0; r<3; r++){
+                        for (int s=0; s<3; s++){
+                          for (int a=0; a<3; a++){
+                            DlnDF(i,j,k,l,p,q) += DDlnDDCe(i,j,k,l,r,s)*2.*Fe(a,r)*dFedF(a,s,p,q);
+                          }
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+          }
+
+        }
+        else{
+          STensorOperation::zero(DlnDF);
+        }
+
+        STensorOperation::zero(dSdF);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                for (int m=0; m<3; m++)
+                  for (int n=0; n<3; n++){
+                    dSdF(i,j,k,l) += DKcorDF(m,n,k,l)*DlnDCe(m,n,i,j);
+                    dSdF(i,j,k,l) += KS(m,n)*DlnDF(m,n,i,j,k,l);
+                  }
+
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                Tangent(i,j,k,l) = 0.;
+                for (int m=0; m<3; m++){
+                  for (int n=0; n<3; n++){
+                    Tangent(i,j,k,l) += dFedF(i,m,k,l)*S(m,n)*Fpinv(j,n);
+                    Tangent(i,j,k,l) += Fe(i,m)*dSdF(m,n,k,l)*Fpinv(j,n);
+                    Tangent(i,j,k,l) += Fe(i,m)*S(m,n)*DinvFpDF(j,n,k,l);
+                  }
+                }
+              }
+
+
+        // dP/dT
+
+        // 1. get dMeprDT from dKeprDT  -> DcorKirprDT from TVE
+        static STensor3 dDevKeprDT, dDevCorKirDT, DcorKirDT;
+        double DpDT(0.), dpKeprDT(0.);
+
+        STensorOperation::decomposeDevTr(dKeprDT,dDevKeprDT,dpKeprDT);
+        dpKeprDT = dKeprDT.trace()/3.;
+
+        DcorKirDT = dKeprDT; // update later
+
+        // 2. initialise dXdT - > need this for DmechsourceDT -> initialise here (X is backStress)
+        STensor3& dXdT = q1->getRefToDbackStressdT();
+        STensorOperation::zero(dXdT);
+        STensor3& dGammaNdT =  q1->_dGammaNdT;
+        STensorOperation::zero(dGammaNdT);
+
+        // 3. get dPhipprDT and dDevPhiprDT
+        double dPhiPdT(0.);
+        static STensor3 dDevPhiDT;
+        STensor3& DphiDT = q1->_DphiDT;
+
+        dPhiPdT = dpKeprDT;
+        dDevPhiDT = dDevKeprDT;
+
+        DphiDT = dDevPhiDT;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+        	  DphiDT(i,j) +=  dPhiPdT*_I(i,j);
+
+        // 4. get dPhiEdT
+        double dPhiEdT(0.);
+        STensorOperation::doubleContractionSTensor3(DphiEDdevPhi,dDevPhiDT,dPhiEdT);
+
+        // 5. to 11. (inside if loop-> Gamma > 0.)
+        double& dGammaDT = q1->_DGammaDT;
+        double& DgammaDT = q1->_DgammaDT;
+        dGammaDT = 0.; DgammaDT =0.;
+
+        double dAdT(0.), dfdT(0.), dgdT(0.), DtrNdT(0.), DtrXdT(0.);
+        static STensor3 DdevNdT, dFpDT, DdevXdT;
+
+        // eta(0.), Deta(0.), DetaDT(0.);
+        if (_viscosity != NULL)
+            _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+        double etaOverDt = eta/this->getTimeStep();
+
+        if (Gamma >0){
+        // plastic
+
+            // =============================== ROUND 1 - Updates for dAdT, dfdT, dgdT ================================================== //
+
+            // 5.1 update dCxdT
+            double dCxdevdT(0.), dCxtrdT(0.);
+            // dHbdT+dHb*DgammaDT
+            if (Hb>0.){
+                dCxdevdT = -m(0)*( -1./pow(Hb,2.)*dHb*Dgamma*(dHbdT) + 1./Hb*(ddHbdgammadT*Dgamma + dHb*DgammaDT))
+                      + (1./pow(Hb,2.)*(dHbdT)*(dHbdT) - 1./Hb*ddHbddT)*(T-T0) -1./Hb*dHbdT;
+            }
+            dCxtrdT = dCxdevdT;
+            dCxdevdT += 3.*m(1)*pow(kk,1.)*(dHbdT); // pow(kk,2.) DEBUG
+            dCxtrdT += 2.*_b/3.*m(1)*pow(kk,1.)*(dHbdT); // pow(kk,2.) DEBUG
+
+            // 5.2 update DcorKirDT for shift factor derivatives - // dAdT and dBdT for maxwell elements are updated inside the loop for Phi
+            mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T);
+            DcorKirDT = q1->_DcorKirDT;
+            STensorOperation::decomposeDevTr(DcorKirDT,dDevCorKirDT,DpDT);
+            DpDT = DcorKirDT.trace()/3.;
+
+            // 5.2 update dPhiPdT, dDevPhiDT to get dAdT, dfdT, dgdT
+            dPhiPdT = DpDT + Ke*(-2*_b*ptilde*dGammaDT)
+                        - 2.*_b*pow(kk,1)/3.*( (dHbdT/Cxtr - Hb/pow(Cxtr,2)*dCxtrdT ) *Gamma*ptilde + Hb/Cxtr*dGammaDT*ptilde )
+                        + 1./3.*trXn/pow(Cxtr,2)*dCxtrdT ; // pow(kk,2.) DEBUG
+            dPhiPdT *= Dho2_v_inv;
+
+            // 5.3 update DpDT
+            DpDT += 2*_b*Ke*(-dGammaDT*ptilde - Gamma*dPhiPdT);
+
+            // 5.4 update DdevphiDT
+            static STensor3 DdevphiDT_RHS;
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                DdevphiDT_RHS(i,j) = ( dDevCorKirDT(i,j) )
+                                        - 3*pow(kk,1)*( (dHbdT/Cxdev - Hb/pow(Cxdev,2)*dCxdevdT)*Gamma*devPhi(i,j) + Hb/Cxdev*dGammaDT*devPhi(i,j) )
+                                        + 1./pow(Cxdev,2)*dCxdevdT*devXn(i,j);  // pow(kk,2.) DEBUG
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    DdevphiDT_RHS(i,j) += ( -3*dGammaDT*Ge_Tensor(i,j,k,l)*devPhi(k,l)
+                                                + (-Ge_TrEeTensor(i,j,k,l) -rotationStiffness(i,j,k,l))*( dGammaDT*N(k,l) + 2.*_b/3.*dPhiPdT*_I(k,l) ) ); // EIGEN
+                  }
+              }
+
+            STensorOperation::multSTensor3STensor43(DdevphiDT_RHS,Dho2_u_inv,dDevPhiDT);
+            STensorOperation::doubleContractionSTensor3(DphiEDdevPhi,dDevPhiDT,dPhiEdT);
+
+            // =============================== ROUND 1 - END ========================================================================= //
+
+            // 6. get dAdT, dfdT, dgdT
+            fullVector<double> DaDT(3), DDaDTT(3);
+            getYieldCoefficientTempDers(q1,T,DaDT,DDaDTT);
+
+            dAdT = (4./3.*_b*_b*ptilde*dPhiPdT + 6.*PhiEq*dPhiEdT)/A;
+            dfdT = DaDT(2)*pow(PhiEq,_n) + a(2)*_n*pow(PhiEq,_n-1.)*dPhiEdT - DaDT(1)*ptilde - a(1)*dPhiPdT - DaDT(0);
+            if (this->getTimeStep()>0){
+                dfdT -= (DetaDT*Gamma/this->getTimeStep())*_p*pow((eta*Gamma/this->getTimeStep()),(_p-1.));
+            }
+
+            dgdT = -kk*Gamma*dAdT;
+
+            // 7. get dGammaDT, DgammaDT
+            dGammaDT = (-dfdT + dfdDgamma*dgdT/dgdDgamma)/(dfdGamma - dfdDgamma*dgdGamma/dgdDgamma);
+            DgammaDT = (-dgdGamma*dGammaDT - dgdT)/dgdDgamma;
+
+            // =============================== ROUND 2 - Updates for dPhiPdT, DdevphiDT ================================================== //
+            // 8. update dCxdT
+            // dHbdT+dHb*DgammaDT
+            if (Hb>0.){
+                dCxdevdT = -m(0)*( -1./pow(Hb,2.)*dHb*Dgamma*(dHbdT) + 1./Hb*(ddHbdgammadT*Dgamma + dHb*DgammaDT))
+                      + (1./pow(Hb,2.)*(dHbdT)*(dHbdT) - 1./Hb*ddHbddT)*(T-T0) -1./Hb*dHbdT;
+            }
+            dCxtrdT = dCxdevdT;
+            dCxdevdT += 3.*m(1)*pow(kk,1.)*(dHbdT); // pow(kk,2.) DEBUG
+            dCxtrdT += 2.*_b/3.*m(1)*pow(kk,1.)*(dHbdT); // pow(kk,2.) DEBUG
+
+            // 9. update DpDT 1 - shift factor derivatives
+            DpDT = DcorKirDT.trace()/3.;
+
+            // 10. update dPhiPdT
+            dPhiPdT = DpDT + Ke*(-2*_b*ptilde*dGammaDT)
+                        - 2.*_b*pow(kk,1)/3.*( (dHbdT/Cxtr - Hb/pow(Cxtr,2)*dCxtrdT ) *Gamma*ptilde + Hb/Cxtr*dGammaDT*ptilde )
+                        + 1./3.*trXn/pow(Cxtr,2)*dCxtrdT ; // pow(kk,2.) DEBUG
+            dPhiPdT *= Dho2_v_inv;
+
+            // 10.1 update DpDT 2
+            DpDT += 2*_b*Ke*(-dGammaDT*ptilde - Gamma*dPhiPdT);
+
+            // 11. update DdevphiDT
+            STensorOperation::zero(DdevphiDT_RHS);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                DdevphiDT_RHS(i,j) = ( dDevCorKirDT(i,j) )
+                                    - 3*pow(kk,1)*( (dHbdT/Cxdev - Hb/pow(Cxdev,2)*dCxdevdT)*Gamma*devPhi(i,j) + Hb/Cxdev*dGammaDT*devPhi(i,j) )
+                                    + 1./pow(Cxdev,2)*dCxdevdT*devXn(i,j);   // pow(kk,2.) DEBUG
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    DdevphiDT_RHS(i,j) += ( -3*dGammaDT*Ge_Tensor(i,j,k,l)*devPhi(k,l)
+                                                + (-Ge_TrEeTensor(i,j,k,l) - rotationStiffness(i,j,k,l))*( dGammaDT*N(k,l) + 2.*_b/3.*Gamma*dPhiPdT*_I(k,l) ) ); // EIGEN
+                  }
+              }
+
+            STensorOperation::multSTensor3STensor43(DdevphiDT_RHS,Dho2_u_inv,dDevPhiDT);
+
+            DphiDT = dDevPhiDT;
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+            	  DphiDT(i,j) +=  dPhiPdT*_I(i,j);
+
+            // =============================== ROUND 2 - END ========================================================================= //
+
+            // 12. get DtrNdT, DdevNdT
+            DtrNdT = dPhiPdT;
+            DtrNdT *= (2.*_b);
+
+            DdevNdT = dDevPhiDT;
+            DdevNdT *= 3.;
+
+            // 13. get dFpdT
+            STensorOperation::zero(dGammaNdT);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                dGammaNdT(i,j) += N(i,j)*dGammaDT + Gamma*DdevNdT(i,j) + Gamma/3.*_I(i,j)*DtrNdT;
+
+            static STensor43 CeprFp0;
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    CeprFp0(i,j,k,l) = 0.;
+                    for (int s=0; s<3; s++)
+                      CeprFp0(i,j,k,l) += dexpAdA(i,s,k,l)*Fp0(s,j);
+                  }
+
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                dFpdT(i,j) = 0.;
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    dFpdT(i,j) += CeprFp0(i,j,k,l)*dGammaNdT(k,l);
+                }
+
+            // 14. dXdT - backstress temperature derivative -> correction - CHECK!!!
+            DtrXdT = pow(kk,1.)*( (dHbdT/Cxtr - Hb/pow(Cxtr,2)*dCxtrdT ) *Gamma*trN + Hb/Cxtr*(dGammaDT*trN + Gamma*DtrNdT) ) - trXn/pow(Cxtr,2)*dCxtrdT; // pow(kk,2.) DEBUG
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                DdevXdT(i,j) = pow(kk,1.)*( (dHbdT/Cxdev - Hb/pow(Cxdev,2)*dCxdevdT)*Gamma*devN(i,j) + Hb/Cxdev*( dGammaDT*devN(i,j) + Gamma*DdevNdT(i,j) ) )
+                                - 1./pow(Cxdev,2)*dCxdevdT * devXn(i,j);  // pow(kk,2.) DEBUG
+
+            STensorOperation::zero(dXdT);
+            dXdT = DdevXdT;
+            dXdT(0,0) = DtrXdT/3.;
+            dXdT(1,1) = DtrXdT/3.;
+            dXdT(2,2) = DtrXdT/3.;
+
+            // 15. update DcorKirDT
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++)
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                      DcorKirDT(i,j) -= DcorKirDEe(i,j,k,l)*dGammaNdT(k,l);
+
+            q1->_DcorKirDT = DcorKirDT; // update in IP
+
+        } // if Gamma
+        else{
+            // elastic
+            STensorOperation::zero(dFpDT); STensorOperation::zero(DdevXdT); STensorOperation::zero(DdevNdT);
+            }
+
+        // 16. get dKcorDT
+        // done above
+
+        // 17. get DinvFpdT, dFedT, dCedT, dCeinvDT
+        static STensor3 DinvFpdT, dFedT, dCedT, dCeinvdT;
+        STensorOperation::zero(DinvFpdT);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int p=0; p<3; p++)
+              for (int q=0; q<3; q++)
+                DinvFpdT(i,j) -= Fpinv(i,p)*dFpdT(p,q)*Fpinv(q,j);
+
+        STensorOperation::zero(dFedT);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              dFedT(i,j) += F(i,k)*DinvFpdT(k,j);
+
+        STensorOperation::zero(dCedT);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int p=0; p<3; p++)
+              dCedT(i,j) += Fe(p,i)*dFedT(p,j) + dFedT(p,i)*Fe(p,j); // This Works!
+
+        STensorOperation::zero(dCeinvdT);
+        for (int i=0; i<3; i++)
+          for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                dCeinvdT(i,s) -= Ceinv(i,k)*dCedT(k,l)*Ceinv(l,s);
+
+        // 18. get dMeDT -> needed for DmechSourceDT
+        STensor3& dMeDT = q1->getRefToDModMandelDT();
+        STensorOperation::zero(dMeDT);
+
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            dMeDT(i,j) = DcorKirDT(i,j);
+
+        // 19. get dSdT
+
+        static STensor43 DLDT;
+        STensorOperation::zero(DLDT);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++)
+                for (int r=0; r<3; r++)
+                  for (int s=0; s<3; s++)
+                    for (int a=0; a<3; a++)
+                      DLDT(i,j,k,l) += DDlnDDCe(i,j,k,l,r,s)*2.*Fe(a,r)*dFedT(a,s);
+
+        static STensor3 dSdT;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dSdT(i,j) = 0.;
+            for (int r=0; r<3; r++)
+              for (int s=0; s<3; s++){
+            	dSdT(i,j) += DcorKirDT(r,s)*DlnDCe(r,s,i,j) + KS(r,s)*DLDT(r,s,i,j);
+            }
+         }
+
+         // 20. Finally, get dPdT
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dPdT(i,j) = 0.;
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dPdT(i,j) += (dFedT(i,k)*S(k,l)*Fpinv(j,l) + Fe(i,k)*dSdT(k,l)*Fpinv(j,l) + Fe(i,k)*S(k,l)*DinvFpdT(j,l));
+              }
+          }
+
+        // TVP - flux derivatives
+        // fluxT
+        dfluxTdT = fluxT;
+        dfluxTdT *= (DKThConDT/KThConT);
+        dfluxTdgradT = Cinv;
+        dfluxTdgradT *= (-KThConT*J);
+        STensorOperation::zero(dfluxTdF);
+
+        if (!_thermalEstimationPreviousConfig){
+
+            static STensor3 DJDF;
+            static STensor43 DCinvDF;
+            for (int i=0; i<3; i++){
+              for (int j=0; j<3; j++){
+                DJDF(i,j) = J*Finv(j,i);
+                for (int k=0; k<3; k++){
+                  for (int l=0; l<3; l++){
+                    DCinvDF(i,j,k,l) = 0.;
+                    for (int p=0; p<3; p++){
+                      for (int a=0; a<3; a++){
+                        for (int b=0; b<3; b++){
+                          DCinvDF(i,j,k,l) -= 2.*F(k,p)*Cinv(i,a)*Cinv(j,b)*_I4(a,b,p,l);
+                        }
+                      }
+                    }
+                  }
+                }
+              }
+            }
+
+            for (int i=0; i<3; i++){
+              for (int j=0; j<3; j++){
+                for (int k=0; k<3; k++){
+                  dfluxTdF(i,j,k) += (DJDF(j,k)*fluxT(i)/J);
+                  for (int l=0; l<3; l++){
+                    dfluxTdF(i,j,k) -= (J*DCinvDF(i,l,j,k)*gradT(l)*KThConT);
+                  }
+                }
+              }
+            }
+        }
+
+    } // if stiff
+
+
+    // thermalEnergy
+    if (stiff){
+        double& DDpsiTVMdTT = q1->getRefToDDFreeEnergyTVMdTT();
+        // getFreeEnergyTVM(q0,q1,T0,T,NULL,NULL,&DDpsiTVMdTT);
+        // CpT = -T*DDpsiTVMdTT;
+        getCp(CpT,T);
+    }
+    else{
+        getCp(CpT,T);
+    }
+
+    q1->_thermalEnergy = CpT*T;
+
+    // thermalSource
+    if (this->getTimeStep() > 0.){
+        thermalSource = -CpT*(T-T0)/this->getTimeStep();
+    }
+    else
+        thermalSource = 0.;
+
+    // mechanical Source
+    double& Wm_TVP = q1->getRefToMechSrcTVP(); // TVP
+    double& Wm_TVE = q1->getRefToMechSrcTVE(); // TVE
+
+    mechanicalSource = 0.;
+    double mechanicalSource_cap = 0.; // in case of mullins, undamaged mechanicalSource
+
+    // 1) ThermoElastic Heat -> _DcorKirDT needs to corrected for plasticity ( DcorKirDT = dcorKir_dT + dCorKirDEe * dEeDT )
+    static STensor3 DEe;
+    DEe = q1->_Ee;
+    DEe -= q0->_Ee;
+    if (this->getTimeStep() > 0){
+        // mechanicalSource += (STensorOperation::doubledot(q1->_DcorKirDT,DEe)*T/this->getTimeStep());
+    }
+
+    // 2) Viscoelastic Contribution to mechSrc
+    double& dWmdT_TVE = q1->getRefTodMechSrcTVEdT();
+    STensor3& dWmdF_TVE = q1->getRefTodMechSrcTVEdF();
+    static STensor3 dWmdE_TVE;
+    mlawNonLinearTVM::getMechSource_nonLinearTVE_term(q0,q1,T0,T,Wm_TVE,stiff,dWmdE_TVE,dWmdT_TVE);
+    // mechanicalSource += Wm_TVE;
+
+    // 3) Viscoplastic Contribution to mechSrc
+    double& dWmdT_TVP = q1->getRefTodMechSrcTVPdT();
+    STensor3& dWmdF_TVP = q1->getRefTodMechSrcTVPdF();
+    mlawNonLinearTVP::getMechSourceTVP(F0,F,q0,q1,T0,T,Fepr,Cepr,DphiPDF,Wm_TVP,dWmdF_TVP,dWmdT_TVP);
+    mechanicalSource += Wm_TVP;
+
+    // --------------------------------------------------------------------------------------------
+    // TVE energy and derivatives
+    double& Dpsi_DT = q1->getRefTo_Dpsi_DT();
+    STensor3& Dpsi_TVEdE = q1->getRefTo_Dpsi_DE();
+    q1->_elasticEnergy = mlawNonLinearTVM::freeEnergyMechanical(*q0,*q1,T0,T,&Dpsi_DT,&Dpsi_TVEdE);
+
+    // TVP energy and derivatives
+    double psi_TVP = freeEnergyPlasticity(q0,q1,T0,T);
+    double Dpsi_TVPdT(0.);
+    static STensor3 Dpsi_TVPdF;
+    freeEnergyPlasticityDerivatives(q0,q1,T0,T,Dpsi_TVPdF,Dpsi_TVPdT);
+    // q1->_elasticEnergy += psi_TVP; // Mullins TVP
+    // Dpsi_DT += Dpsi_TVPdT;  // add plastic part // Mullins TVP
+    Dpsi_DT -= dot(Dpsi_TVEdE,q1->_dGammaNdT); // add plastic dependency of elastic strain // Mullins TVP
+
+    // Mullins Effect
+    if (_mullinsEffect != NULL && q1->_ipMullinsEffect != NULL){
+        mlawNonLinearTVM::calculateMullinsEffectScaler(q0, q1, T, &Dpsi_DT);
+    }
+    double eta_mullins = 1.;
+
+    if (q1->_ipMullinsEffect != NULL){
+
+        // Put Stress in IP
+        q1->_P_cap = P;
+
+        // Modify Stress for mullins
+        eta_mullins = q1->_ipMullinsEffect->getEta();
+        P *= eta_mullins;
+        // q1->_elasticEnergy *= eta_mullins;
+
+    	mechanicalSource_cap = mechanicalSource;
+        mechanicalSource *= q1->_ipMullinsEffect->getEta();
+        if (this->getTimeStep() > 0){
+            mechanicalSource -= q1->_ipMullinsEffect->getDpsiNew_DpsiMax()*(q1->_ipMullinsEffect->getpsiMax() - q0->_ipMullinsEffect->getpsiMax())/this->getTimeStep();
+        }
+    }
+
+
+    if(stiff){
+
+    	// --------------------------------------------------------------------------------------------
+        // Important conversion tensors
+        STensorOperation::zero(DEeDCepr);
+        STensorOperation::zero(DEeDF);
+
+        // DEeDCepr to DEeDF
+        // STensorOperation::multSTensor43(_I4, DlnDCepr, DEeDCepr);
+        DEeDCepr = DlnDCepr;
+        DEeDCepr *= 0.5;
+        DEeDCepr -= dGammaNdCepr;
+        STensorOperation::multSTensor43(DEeDCepr, CeprToF, DEeDF);
+
+        // Note: DEeDT = - dGammaNdT
+        // --------------------------------------------------------------------------------------------
+
+        // thermSrc and MechSrc Derivatives
+
+        // thermal source derivatives
+        double DCpDT(0.);
+        mlawNonLinearTVM::getCp(CpT,T,&DCpDT);
+        static STensor3 DCpDF;
+        STensorOperation::zero(DCpDF);                                                       // CHANGE for DCpDF
+
+        if (this->getTimeStep() > 0){
+            dthermalSourcedT = -DCpDT*(T-T0)/this->getTimeStep() - CpT/this->getTimeStep();
+            // dthermalSourcedT = -CpT/this->getTimeStep() - (CpT-CpT_0)/this->getTimeStep();
+            for(int i = 0; i< 3; i++){
+              for(int j = 0; j< 3; j++){
+                dthermalSourcedF(i,j) = -DCpDF(i,j)*(T-T0)/this->getTimeStep();
+              }
+            }
+        }
+        else{
+            dthermalSourcedT = 0.;
+            STensorOperation::zero(dthermalSourcedF);
+        }
+
+        // mechSourceTVP derivatives
+        dmechanicalSourcedT = 0.;
+        STensorOperation::zero(dmechanicalSourceF);
+        static STensor3 dmechanicalSourceE;
+        STensorOperation::zero(dmechanicalSourceE);
+
+          // DcorKirDT Term
+        STensor3& DDcorKirDTT = q1->getRefToDDcorKirDTT();
+        STensor43& DDcorKirDTDEe = q1->getRefToDDcorKirDTDE();
+
+        static STensor3 DcorKirDT_I;
+        STensorOperation::multSTensor3STensor43(q1->_DcorKirDT,_I4,DcorKirDT_I);
+        if (this->getTimeStep() > 0){
+            for (int i=0; i<3; i++){
+                for (int j=0; j<3; j++){
+                    dmechanicalSourceE(i,j) += T*DcorKirDT_I(i,j)/this->getTimeStep();
+                    for (int k=0; k<3; k++)
+                        for (int l=0; l<3; l++){
+                            dmechanicalSourceE(i,j) += T*DDcorKirDTDEe(k,l,i,j)*DEe(k,l)/this->getTimeStep();
+                            DDcorKirDTT(i,j) += - DDcorKirDTDEe(i,j,k,l)*q1->_dGammaNdT(k,l); // additional term due to TVP
+                        }
+                }
+            }
+            // STensorOperation::multSTensor3STensor43(dmechanicalSourceE,DEeDF,dmechanicalSourceF);
+
+            // dmechanicalSourcedT += (STensorOperation::doubledot(q1->_DcorKirDT,DEe)/this->getTimeStep());
+            // dmechanicalSourcedT += T*(STensorOperation::doubledot(DDcorKirDTT,DEe)/this->getTimeStep());
+            // dmechanicalSourcedT -= T*(STensorOperation::doubledot(q1->_DcorKirDT,q1->_dGammaNdT)/this->getTimeStep());
+        }
+
+        // TVE Term
+        STensorOperation::multSTensor3STensor43(dWmdE_TVE, DEeDF, dWmdF_TVE);
+        for (int i=0; i<3; i++)
+            for (int j=0; j<3; j++)
+                dWmdT_TVE += - dWmdE_TVE(i,j) *  q1->_dGammaNdT(i,j); // the second term in dWmdT_TVE from dependency of Ee on plasticity
+
+        // dmechanicalSourceF += dWmdF_TVE;
+        // dmechanicalSourcedT += dWmdT_TVE;
+
+
+        // TVP Term
+        dmechanicalSourceF += dWmdF_TVP;
+        dmechanicalSourcedT += dWmdT_TVP;
+
+    	// Mullins Effect Derivatives
+
+        // Compute Tangents for Mullin's Effect
+        if (_mullinsEffect != NULL && q1->_ipMullinsEffect != NULL){
+
+            // 1st Term
+            Tangent *= q1->_ipMullinsEffect->getEta();
+            dPdT *= q1->_ipMullinsEffect->getEta();
+            dmechanicalSourceF *= q1->_ipMullinsEffect->getEta();
+            dmechanicalSourcedT *= q1->_ipMullinsEffect->getEta();
+
+
+            // 2nd Term
+            double Deta_mullins_DT(0.);
+            static STensor3 Deta_mullins_DF, Deta_mullins_DEe;
+
+                // Deta_mullins_DF
+            STensorOperation::multSTensor3STensor43(q1->_DpsiDE,DEeDF,Deta_mullins_DF);
+            Deta_mullins_DF *= q1->_DmullinsDamage_Dpsi_cap; // elastic part
+            // Deta_mullins_DF += Dpsi_TVPdF*q1->_DmullinsDamage_Dpsi_cap; // plastic part // Mullins TVP
+
+                // Deta_mullins_DT
+            // STensorOperation::doubleContractionSTensor3(q1->_DpsiDE,q1->_dGammaNdT,Deta_mullins_DT); // Remove - Mullins TVP
+            // Deta_mullins_DT *= -q1->_DmullinsDamage_Dpsi_cap; // Remove - Mullins TVP
+            // Deta_mullins_DT += q1->_DmullinsDamage_DT; // Remove - Mullins TVP
+            Deta_mullins_DT = q1->_DmullinsDamage_DT; // + q1->_DmullinsDamage_Dpsi_cap*q1->_DpsiDT; // Mullins TVP
+
+            // 2nd Term - 1st PK
+            for (int i=0; i<3; i++)
+                for (int j=0; j<3; j++){
+                    dPdT(i,j) += q1->_P_cap(i,j) * Deta_mullins_DT;
+                        for (int k=0; k<3; k++)
+                            for (int l=0; l<3; l++)
+                                Tangent(i,j,k,l) += q1->_P_cap(i,j) * Deta_mullins_DF(k,l);
+                }
+
+
+            // 2nd Term - MechSrc
+            dmechanicalSourcedT += mechanicalSource_cap*Deta_mullins_DT;
+            for (int i=0; i<3; i++)
+                for (int j=0; j<3; j++){
+                    dmechanicalSourceF(i,j) += mechanicalSource_cap*Deta_mullins_DF(i,j);
+                }
+
+            static STensor3 DDpsiNew_DpsiMaxDF, DpsiMax_DF;
+            STensorOperation::multSTensor3STensor43(q1->_DpsiDE,DEeDF,DDpsiNew_DpsiMaxDF);
+            STensorOperation::multSTensor3STensor43(q1->_DpsiDE,DEeDF,DpsiMax_DF);
+            DDpsiNew_DpsiMaxDF *= q1->_ipMullinsEffect->getDDpsiNew_DpsiMaxDpsi();
+            DpsiMax_DF *= q1->_ipMullinsEffect->getDpsiMax_Dpsi();
+
+            if (this->getTimeStep() > 0){
+                dmechanicalSourcedT -= (q1->_ipMullinsEffect->getDDpsiNew_DpsiMaxDT()*(q1->_ipMullinsEffect->getpsiMax() - q0->_ipMullinsEffect->getpsiMax())/this->getTimeStep()
+                							+ q1->_ipMullinsEffect->getDpsiNew_DpsiMax()*q1->_ipMullinsEffect->getDpsiMax_Dpsi()*q1->_DpsiDT/this->getTimeStep());
+                for (int i=0; i<3; i++)
+                    for (int j=0; j<3; j++){
+                        dmechanicalSourceF(i,j) -= DDpsiNew_DpsiMaxDF(i,j)*(q1->_ipMullinsEffect->getpsiMax() - q0->_ipMullinsEffect->getpsiMax())/this->getTimeStep();
+                        dmechanicalSourceF(i,j) -= q1->_ipMullinsEffect->getDpsiNew_DpsiMax()*DpsiMax_DF(i,j)/this->getTimeStep();
+                    }
+            }
+
+        } // mullin's
+    }
+
+}
+
+void mlawNonLinearTVENonLinearTVP2::get_G1_Tensor(const STensor3& Cepr, const STensor3& expGN,
+                                    const STensor43& DCeinvprDCepr, const STensor3& KS, STensor43& G1) const{
+
+  static STensor3 Hinv;
+  STensorOperation::inverseSTensor3(expGN,Hinv);
+
+  static STensor3 Ceinvpr;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  static STensor43 term1, term2;
+
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+          term1(i,j,k,l) = 0.;
+          term2(i,j,k,l) = 0.;
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++)
+              for (int r=0; r<3; r++)
+                for (int s=0; s<3; s++)
+                  for (int m=0; m<3; m++)
+                    for (int o=0; o<3; o++){
+                      term1(i,j,k,l) += Hinv(i,p)*Hinv(p,q)*_I4(q,r,k,l)*KS(r,s)*Ceinvpr(s,m)*expGN(m,o)*expGN(o,j);
+                      term2(i,j,k,l) += Hinv(i,p)*Hinv(p,q)*Cepr(q,r)*KS(r,s)*DCeinvprDCepr(s,m,k,l)*expGN(m,o)*expGN(o,j);
+                    }
+         }
+  STensorOperation::zero(G1);
+  G1 = term1+term2;
+}
+
+void mlawNonLinearTVENonLinearTVP2::getDho(const double& Gamma, const STensor3& Cepr, const STensor3& Ceinvpr, const STensor3& KS,
+                                  const double& Ke, const STensor43& Ge_Tensor,
+                                  const double& kk, const double& Hb, const double& Cxtr, const double& Cxdev,
+                                  const STensor3& expGN, const STensor43& dexpAdA,
+                                  STensor43& Dho, STensor43& Dho2inv, STensor43& Dho2_u_inv, double& Dho2_v_inv, STensor43* Ge_TrEeTensor, STensor43* rotationStiffness) const{
+
+  // Ge_TrEeTensor -> Dependence of devCorKir on TrEe. DO NOT CHANGE ITS VALUE!
+
+ // Get DcorKirDEe for Dho 2nd term
+ static STensor43 DcorKirDEe;
+ STensorOperation::zero(DcorKirDEe);
+ for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+            DcorKirDEe(i,j,k,l) += Ke*_I(i,j)*_I(k,l);
+            for (int p=0; p<3; p++)
+                for (int q=0; q<3; q++)
+                    DcorKirDEe(i,j,k,l) += Ge_Tensor(i,j,p,q)*_Idev(p,q,k,l);
+        }
+ if (Ge_TrEeTensor!= NULL){
+    DcorKirDEe += (*Ge_TrEeTensor);
+ }
+
+ if (rotationStiffness!= NULL){
+    DcorKirDEe += (*rotationStiffness);
+ }
+
+  //
+  // Get Dho2 -> dJdPhi, Dho2_u -> LHS of dDevPhidDgamma, dDevPhidGamma, Dho2_v -> LHS
+  //
+
+  // Get dMeDphi
+  static STensor43 dMedGN, dMeDphi;
+  STensorOperation::zero(dMedGN);
+  STensorOperation::zero(dMeDphi);
+
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++)
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++)
+                dMedGN(i,j,k,l) += DcorKirDEe(i,j,p,q)*(-_I4(p,q,k,l));
+
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++)
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++)
+                dMeDphi(i,j,k,l) += dMedGN(i,j,p,q)*Gamma*(3.*_Idev(p,q,k,l) + 2.*_b/3 * 1./3 * _I(p,q)*_I(k,l));
+
+  // Get dXdPhi
+  static STensor43 dXdPhi;
+  STensorOperation::zero(dXdPhi);
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++)
+            dXdPhi(i,j,k,l) = pow(kk,1)*Hb*Gamma*(3./Cxdev*_Idev(i,j,k,l) + 2.*_b/(3.*Cxtr) * 1./3 * _I(i,j)*_I(k,l)); // DEBUG pow(kk,2)
+
+  // Get Dho2, Dho2inv
+  static STensor43 Dho2;
+  Dho2 = _I4;
+  Dho2 -= dMeDphi;
+  Dho2 += dXdPhi;
+  STensorOperation::inverseSTensor43(Dho2,Dho2inv);
+
+  // Get Dho2_u, Dho2_u_inv
+  static STensor43 Dho2_u;
+
+  Dho2_u = _I4;
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+          Dho2_u(i,j,k,l) += 3*Gamma*pow(kk,1)*Hb/Cxdev * _I4(i,j,k,l); // DEBUG pow(kk,2)
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++){
+                Dho2_u(i,j,k,l) += 3.*Gamma*(Ge_Tensor(i,j,p,q)*_Idev(p,q,k,l)); // Ge_Tensor(i,j,p,q)*_I4(p,q,k,l) - CHECKERS
+        }
+      }
+  if (Ge_TrEeTensor!= NULL){
+    static STensor43 Ge_TrEeTensor_temp;
+    STensorOperation::zero(Ge_TrEeTensor_temp);
+    Ge_TrEeTensor_temp = (*Ge_TrEeTensor);
+    Ge_TrEeTensor_temp *= (3*Gamma);
+    Dho2_u += Ge_TrEeTensor_temp;
+  }
+  if (rotationStiffness!= NULL){
+	static STensor43 rotationStiffness_Temp;
+	STensorOperation::zero(rotationStiffness_Temp);
+	rotationStiffness_Temp = (*rotationStiffness);
+	rotationStiffness_Temp *= (3*Gamma);
+	Dho2_u += rotationStiffness_Temp;
+  }
+  STensorOperation::inverseSTensor43(Dho2_u,Dho2_u_inv);
+
+  // Get Dho2_v, Dho2_v_inv
+  double Dho2_v = 1. + 2.*_b*Gamma*(Ke + pow(kk,1)*Hb/(3.*Cxtr)); // pow(kk,2) DEBUG
+  Dho2_v_inv = 1./Dho2_v;
+}
+
+void mlawNonLinearTVENonLinearTVP2::getIterated_DPhi(const STensor3& F, const double& T0, const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
+                                            double& Gamma, const double& Cxtr, const double& Cxdev,
+                                            const STensor3& Cepr, const STensor3& Eepr,
+                                            const double& trXn, const STensor3& devXn,
+                                            double& Ke, double& Ge, STensor43& Ge_Tensor,
+                                            double& ptilde, STensor3& devPhi,
+                                            STensor3& Phi, STensor3& N, STensor3& expGN, STensor43& dexpAdA,
+                                            STensor43& Dho, STensor43& Dho2inv, STensor43& Dho2_u_inv , double& Dho2_v_inv, STensor3& Fp1, const fullVector<int>& alignedIndex,
+                                            STensor43* Ge_TrEeTensor, STensor43* rotationStiffness) const{
+
+  // This function calculates Phi iteratively.
+    // At every iteration it will calculate Ee, corKir and N
+
+  // EIGEN NEW - Initialise Fe
+  static STensor3 Fpinv;
+  STensor3& Fe = q1->_Fe;
+  STensorOperation::multSTensor3(expGN,q0->_Fp,Fp1);
+  STensorOperation::inverseSTensor3(Fp1,Fpinv);
+  STensorOperation::multSTensor3(F,Fpinv,Fe);
+  // EIGEN NEW - Initialise Fe
+
+  // Initialise GammaN in IP -> for mechSrc later
+  STensor3& GammaN = q1->getRefToGammaN();
+
+  // Initialise Hinv
+  static STensor3 Hinv, Ceinvpr;
+  STensorOperation::inverseSTensor3(expGN,Hinv);
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  // Initialise Ce, Ceinv
+  static STensor3 Ce, Ceinv; // Temporary Local Variable
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++){
+      Ce(i,j) = 0.;
+      Ceinv(i,j) = 0.;
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+          Ce(i,j) += Hinv(i,k)*Hinv(k,l)*Cepr(l,j);
+          Ceinv(i,j) += Ceinvpr(i,k)*expGN(k,l)*expGN(l,j);
+     }
+   }
+
+  // Initialise Ee
+  static STensor3 Ee;
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      Ee(i,j) = Eepr(i,j) - Gamma*N(i,j);
+
+  // Initialise corKir
+  static STensor3 KS;
+  static STensor43 Bd_stiffnessTerm;
+
+  // NEW EIGEN
+  // double e1, e2, e3; static STensor3 E1, E2, E3; STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3);
+  static STensor3 Ee0_rot;
+  if (_rotationCorrectionScheme == 0 && _rotationCorrectionScheme == 1){
+	  for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++){
+			  Ee0_rot(i,j) = 0.;
+			  for(int k=0; k<3; k++)
+				  for(int l=0; l<3; l++)
+					  Ee0_rot(i,j) += q1->_R(i,k)*q0->_Ee(k,l)*q1->_R(j,l);
+		  }
+  }
+  else if(_rotationCorrectionScheme == 2){
+	  Ee0_rot = q0->_Ee;
+	  // mlawNonLinearTVM::getEe0s2(Ce,Ee,q0->_Ee,Ee0_rot,dEe0sdEe); // Dont do it here
+  }
+  // NEW EIGEN
+
+  if (Ge_TrEeTensor == NULL){
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
+	  }
+	  else{
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,true,alignedIndex,Bd_stiffnessTerm,NULL,rotationStiffness); // NEW EIGEN
+	  }
+  }
+  else{ // TC asymmetry
+	  if (!_useRotationCorrection){
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
+	  }
+	  else{
+		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,true,alignedIndex,Bd_stiffnessTerm,Ge_TrEeTensor,rotationStiffness); // NEW EIGEN
+	  }
+  }
+
+  Ge_Tensor = _I4;
+  Ge_Tensor *= Ge*2; // *2 because the function doesnt do it
+  Ge_Tensor += Bd_stiffnessTerm;
+  KS = q1->_kirchhoff;
+
+  // Get Hb
+  double Hb(0.);
+  if (q1->_ipKinematic != NULL)
+        Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+  double kk = (1./sqrt(1.+2.*q1->_nup*q1->_nup));
+
+  // Initialise backStress
+  static STensor3 devX, devN;
+  double trX, trN;
+  STensorOperation::decomposeDevTr(N,devN,trN);
+  devX = pow(kk,1)*Hb*Gamma*devN + devXn;      // pow(kk,2) DEBUG
+  devX *= 1./Cxdev;
+  trX = (pow(kk,1)*Hb*Gamma*trN + trXn)*1./Cxtr; // pow(kk,2) DEBUG
+  q1->_backsig = devX;
+  q1->_backsig(0,0) += trX/3.;
+  q1->_backsig(1,1) += trX/3.;
+  q1->_backsig(2,2) += trX/3.;
+
+  // Initialise J
+  static STensor3 J;
+  STensorOperation::zero(J);
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      J(i,j) += Phi(i,j) - KS(i,j) + q1->_backsig(i,j);
+
+  // static STensor3 J0; //debug
+  // J0 = J; //debug
+
+  // Initialise J_tol
+  double J_tol = 0.;
+  J_tol = J.norm0();
+  J_tol/=(_K+_G);
+  // for (int i=0; i<3; i++)
+    // for (int j=0; j<3; j++)
+      // J_tol += abs(J(i,j)) ;
+
+  // Initialise Dho, Dho2, Dho2inv
+  if (Ge_TrEeTensor == NULL){
+    getDho(Gamma,Cepr,Ceinvpr,KS,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,NULL,rotationStiffness);
+  }
+  else{ // TC asymmetry
+    getDho(Gamma,Cepr,Ceinvpr,KS,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Ge_TrEeTensor,rotationStiffness);
+  }
+
+  // Initialise DPhi
+  static STensor3 DPhi;
+
+  // Initialise numerical quantities
+  /*
+  static STensor3 Phi_plus, J_plus, devPhi_plus, N_plus, GammaN_plus, Ee_plus, Ce_plus, KS_plus, MS_plus, expGN_plus, Hinv_plus, devN_plus, devX_plus, Ee0_rot_plus;
+  double pPhi_plus,Ke_plus,Ge_plus, trN_plus, trX_plus;
+  static STensor43 dJdPhi_plus, dJdPhi_plus_inv, dexpAdA_plus, Bd_stiffnessTerm_plus,Ge_Tensor_plus, dJdPhi_plus2, dJdPhi_plus2_inv;
+  static STensor43 Ge_TrEeTensor_plus, rotationStiffness_plus;
+  static IPNonLinearTVP q1_plus(*q0);
+  STensor3& R_plus = q1_plus._R;
+  STensor43& dRdEe_plus = q1_plus._dRdEe;
+  STensor43& dRtdEe_plus = q1_plus._dRtdEe;
+  fullVector<int> alignedIndex_plus(3); alignedIndex_plus(0) = 0; alignedIndex_plus(1) = 1; alignedIndex_plus(2) = 2;*/
+
+  int ite = 0;
+  int maxite = 100;
+
+  double tol = _stressIteratorTol; // 1e-6;
+
+  while (fabs(J_tol) > tol or ite <1){
+
+	  /*
+	  // ##################################################################
+	  // numerical Dho4inv (Jacobian dJ/dPhi)
+	  	  // _perturbationfactor = DPhi_numerical
+
+
+	  for (int i=0; i<3; i++){
+	     for (int j=0; j<3; j++){
+	        Phi_plus = Phi;
+	        Phi_plus(i,j) += 0.5*_perturbationfactor;
+	        Phi_plus(j,i) += 0.5*_perturbationfactor;
+	        STensorOperation::decomposeDevTr(Phi_plus,devPhi_plus,pPhi_plus);
+	        pPhi_plus = Phi_plus.trace()/3;
+	        N_plus = _I;
+	        N_plus *= 2.*_b/3*pPhi_plus;
+	        N_plus += 3*devPhi_plus;
+	        GammaN_plus = N_plus;
+	        GammaN_plus *= Gamma;
+	        STensorOperation::expSTensor3(GammaN_plus,_order,expGN_plus,&dexpAdA_plus);
+	        STensorOperation::inverseSTensor3(expGN_plus,Hinv_plus);
+
+	        // update Ce, Ceinv
+	        for (int ii=0; ii<3; ii++)
+	          for (int jj=0; jj<3; jj++){
+	        	Ce_plus(ii,jj) = 0.;
+	            for (int kk=0; kk<3; kk++)
+	              for (int ll=0; ll<3; ll++)
+	            	Ce_plus(ii,jj) += Hinv_plus(ii,kk)*Hinv_plus(kk,ll)*Cepr(ll,jj);
+	          }
+
+	        Ee_plus = - Gamma*N_plus;
+	        Ee_plus += Eepr;
+	        // bool ok=STensorOperation::logSTensor3(Ce_plus,_order,Ee_plus);
+
+
+      	  q1_plus._Ee0 = q0->_Ee;
+      	  mlawNonLinearTVM::rotationTensor_N_to_Nplus1(q0->_Ee0,q0->_Fp,Fp1,Ce_plus,Ee_plus,q0->_Ee,q1_plus._R,q1_plus._dRdEe,q1_plus._dRtdEe);
+      	  for(int p=0; p<3; p++)
+        	for(int q=0; q<3; q++){
+      	 	  Ee0_rot_plus(p,q) = 0.;
+      	 	  for(int r=0; r<3; r++)
+      	   	    for(int m=0; m<3; m++)
+      	     	  Ee0_rot_plus(p,q) += q1_plus._R(p,r)*q0->_Ee(r,m)*q1_plus._R(q,m);
+        	}
+
+      	  // update corKir
+      	  if (Ge_TrEeTensor == NULL){
+    	  	  if (!_useRotationCorrection){
+    		  	  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,Bd_stiffnessTerm_plus);
+    	  	  }
+    	  	  else{
+    		  	  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce_plus,Ee_plus,Ee0_rot_plus,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,alignedIndex_plus,Bd_stiffnessTerm_plus,NULL,\
+    		  			  	  	  	  	  	  	  	  	  	  	  	  &rotationStiffness_plus); // NEW EIGEN
+    	  	  }
+      	  }
+      	  else{ // TC asymmetry
+    	  	  if (!_useRotationCorrection){
+    		  	  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee_plus,q0->_Ee,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,Bd_stiffnessTerm_plus,&Ge_TrEeTensor_plus);
+    	  	  }
+    	  	  else{
+    		  	  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce_plus,Ee_plus,Ee0_rot_plus,q0,&q1_plus,Ke_plus,Ge_plus,T0,T,true,alignedIndex_plus,Bd_stiffnessTerm_plus,&Ge_TrEeTensor_plus,\
+    		  			  	  	  	  	  	  	  	  	  	  	  	  &rotationStiffness_plus); // NEW EIGEN
+    	  	  }
+      	  }
+
+	        Ge_Tensor_plus = _I4;
+	        Ge_Tensor_plus *= Ge_plus*2; // *2 because the function doesnt do it
+	        Ge_Tensor_plus += Bd_stiffnessTerm_plus;
+	        KS_plus = q1_plus._kirchhoff;
+
+	        // update mandel
+	        // mlawNonLinearTVP::getModifiedMandel(Ce_plus, q0, &q1_plus);
+	        // MS_plus = q1_plus._ModMandel;
+
+	        STensorOperation::decomposeDevTr(N_plus,devN_plus,trN_plus);
+	        devX_plus = pow(kk,1)*Hb*Gamma*devN_plus + devXn;      // pow(kk,2) DEBUG
+	        devX_plus *= 1./Cxdev;
+	        trX_plus = (pow(kk,1)*Hb*Gamma*trN_plus + trXn)*1./Cxtr; // pow(kk,2) DEBUG
+	        q1_plus._backsig = devX_plus;
+	        q1_plus._backsig(0,0) += trX_plus/3.;
+	        q1_plus._backsig(1,1) += trX_plus/3.;
+	        q1_plus._backsig(2,2) += trX_plus/3.;
+
+	        for (int k=0; k<3; k++){
+	          for (int l=0; l<3; l++){
+	            J_plus(k,l) = Phi_plus(k,l) - KS_plus(k,l) + q1_plus._backsig(k,l);
+	            dJdPhi_plus(k,l,i,j) = (J_plus(k,l) - J(k,l))/(_perturbationfactor);
+	          }
+	        }
+	      }
+	    }
+	   STensorOperation::inverseSTensor43(dJdPhi_plus,dJdPhi_plus_inv);
+
+	   // END NUMERICAL
+	   // ##################################################################
+	   */
+
+     // update DPhi
+     for (int i=0; i<3; i++)
+       for (int j=0; j<3; j++){
+         DPhi(i,j) = 0.;
+         for (int k=0; k<3; k++)
+           for (int l=0; l<3; l++){
+             DPhi(i,j) -= Dho2inv(i,j,k,l)*J(k,l);
+           }
+         }
+
+      // update devPhi
+      for (int i=0; i<3; i++){
+        for (int j=0; j<3; j++){
+       		Phi(i,j) += DPhi(i,j);
+       	}
+      }
+
+      // update devPhi, ptilde
+      STensorOperation::decomposeDevTr(Phi,devPhi,ptilde);
+      ptilde = Phi.trace()/3;
+
+      // update N
+      STensorOperation::zero(N);
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++)
+          N(i,j) = 3.*devPhi(i,j) + 2.*_b/3.*ptilde*_I(i,j);
+
+      // update H = exp(GN) = A in dexpAdA; Hinv
+      GammaN = N;
+      GammaN *= Gamma;
+      STensorOperation::expSTensor3(GammaN,_order,expGN,&dexpAdA);
+      STensorOperation::inverseSTensor3(expGN,Hinv);
+
+      // update Ce, Ceinv
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++){
+          Ce(i,j) = 0.;
+          Ceinv(i,j) = 0.;
+          for (int k=0; k<3; k++)
+            for (int l=0; l<3; l++){
+              Ce(i,j) += Hinv(i,k)*Hinv(k,l)*Cepr(l,j);
+              Ceinv(i,j) += Ceinvpr(i,k)*expGN(k,l)*expGN(l,j);
+          }
+        }
+
+      // update Ee
+      STensorOperation::zero(Ee);
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++)
+          Ee(i,j) = Eepr(i,j) - Gamma*N(i,j);
+
+      // EIGEN NEW - update Fe
+      STensorOperation::multSTensor3(expGN,q0->_Fp,Fp1);
+      STensorOperation::inverseSTensor3(Fp1,Fpinv);
+      STensorOperation::multSTensor3(F,Fpinv,Fe);
+
+      // STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3);
+      // NEW EIGEN
+
+      // update corKir
+      if (Ge_TrEeTensor == NULL){
+    	  if (!_useRotationCorrection){
+    		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
+    	  }
+    	  else{
+    		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,true,alignedIndex,Bd_stiffnessTerm,NULL,rotationStiffness); // NEW EIGEN
+    	  }
+      }
+      else{ // TC asymmetry
+    	  if (!_useRotationCorrection){
+    		  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm,Ge_TrEeTensor);
+    	  }
+    	  else{
+    		  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,Ee0_rot,q0,q1,Ke,Ge,T0,T,true,alignedIndex,Bd_stiffnessTerm,Ge_TrEeTensor,rotationStiffness); // NEW EIGEN
+    	  }
+      }
+
+      Ge_Tensor = _I4;
+      Ge_Tensor *= Ge*2; // *2 because the function doesnt do it
+      Ge_Tensor += Bd_stiffnessTerm;
+      KS = q1->_kirchhoff;
+
+      // update backStress
+      STensorOperation::decomposeDevTr(N,devN,trN);
+      devX = pow(kk,1)*Hb*Gamma*devN + devXn;           // pow(kk,2) DEBUG
+      devX *= 1./Cxdev;
+      trX = (pow(kk,1)*Hb*Gamma*trN + trXn)*1./Cxtr;    // pow(kk,2) DEBUG
+      q1->_backsig = devX;
+      q1->_backsig(0,0) += trX/3.;
+      q1->_backsig(1,1) += trX/3.;
+      q1->_backsig(2,2) += trX/3.;
+
+      // update J
+      STensorOperation::zero(J);
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++)
+          J(i,j) += ( Phi(i,j) - KS(i,j) + q1->_backsig(i,j) );
+
+      // update Dho2, Dho2inv
+      if (Ge_TrEeTensor == NULL){
+        getDho(Gamma,Cepr,Ceinvpr,KS,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,NULL,rotationStiffness);
+      }
+      else{ // TC asymmetry
+        getDho(Gamma,Cepr,Ceinvpr,KS,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Ge_TrEeTensor,rotationStiffness);
+      }
+
+      // update J_tol
+      /*
+      J_tol = 0.;
+      for (int i=0; i<3; i++){
+        for (int j=0; j<3; j++){
+          J_tol += abs(J(i,j));
+        }
+      }*/
+
+      // debug
+	  /*
+      for (int i=0; i<3; i++)
+	     for (int j=0; j<3; j++)
+	        for (int k=0; k<3; k++)
+	          for (int l=0; l<3; l++)
+	            // dJdPhi_plus2(k,l,i,j) = (J(k,l) - J0(k,l))/(_perturbationfactor);
+
+	   // STensorOperation::inverseSTensor43(dJdPhi_plus2,dJdPhi_plus2_inv);
+	   // J0 = J;
+
+	   for (int i=0; i<3; i++)
+		 for (int j=0; j<3; j++)
+			for (int k=0; k<3; k++)
+		        for (int l=0; l<3; l++){
+		        	// Msg::Error(" Dho2inv(%d,%d,%d,%d)=%d",i,j,k,l,Dho2inv(i,j,k,l));
+		        	// Msg::Error(" dJdPhi_plus_inv(%d,%d,%d,%d)=%d",i,j,k,l,dJdPhi_plus_inv(i,j,k,l));
+		        }*/
+
+      J_tol = J.norm0();
+      J_tol/=(_K+_G);
+      // J_tol/=(1.e+10);
+
+      ite++;
+
+      // if (ite> maxite-5)
+      // Msg::Info("ite = %d, tol %e, J_tol = %e, Gamma = %e",ite,tol,J_tol,Gamma);
+
+      if (fabs(J_tol) <_tol) break;
+
+      if(ite > maxite){
+    	  Msg::Error("No convergence for iterated Phi mlawNonLinearTVENonLinearTVP2 nonAssociatedFlow iter = %d, J_tol = %e!!",ite,J_tol);
+    	  // Msg::Error("No convergence for iterated Phi mlawNonLinearTVENonLinearTVP2 nonAssociatedFlow iter = %d, e1 = %e, e2 = %e, e3 = %e !!",ite,e1,e2,e3);
+    	  // Msg::Error("Exiting the function Iterated Phi!!");
+    	  // Phi(0,0) = Phi(1,1) = Phi(2,2) = sqrt(-1.);
+    	  // Gamma *= 0.1;
+       return;
+       }
+     } // while
+
+}
+
+/*
+void mlawNonLinearTVENonLinearTVP2::TEST_predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(
+                                        const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
+                                        const STensor3& Fepr, const STensor3& Cepr,
+                                        double& ptilde, STensor3& devPhi, double& Gamma, double& Dgamma, double& A, double& f, STensor3& Me, STensor3& P) const{
+
+  // compute elastic predictor
+  static STensor3 Fp1, Fpinv, Fe, Ce, Ee; // = q1->_Fp;
+  const STensor3& Fp0 = q0->_Fp;
+
+  Fp1 = Fp0;
+  STensorOperation::inverseSTensor3(Fp1,Fpinv);
+
+  static STensor3 invFp0; // plastic predictor
+  invFp0 = Fpinv;
+
+  // Update the Properties to the current temperature (see below which ones are being used)
+  double CpT, DCpDT; getCp(CpT,T,&DCpDT);
+
+  // Get hardening parameters
+  this->mlawNonLinearTVP::hardening(q0,q1,T);
+  static fullVector<double> a(3), Da(3); // yield coefficients and derivatives in respect to plastic deformation
+  this->mlawNonLinearTVP::getYieldCoefficients(q1,a);
+  //a.print("a init");
+
+  double Hb(0.), dHb(0.), ddHb(0.), dHbdT(0.), ddHbdgammadT(0.), ddHbddT(0.);
+  if (q1->_ipKinematic != NULL){
+    Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+    dHb = q1->_ipKinematic->getDR(); // kinematic hardening parameter derivative (dHb/dgamma)
+    dHbdT = q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+    ddHbddT = q1->_ipKinematic->getDDRDTT();
+    ddHbdgammadT = q1->_ipKinematic->getDDRDT();
+  }
+
+  double eta(0.),Deta(0.),DetaDT(0.);
+  if (_viscosity != NULL)
+    _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+
+  // Get Cepr, Ceinvpr
+  static STensor3 Eepr, Ceinvpr;
+  Ce = Cepr;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  Fe = Fepr;
+
+  // Predictor - TVE
+  static STensor43 DlnDCepr, DlnDCe;
+  static STensor63 DDlnDDCe;
+  static STensor3 expGN, GammaN;
+  static STensor43 dexpAdA; // estimation of dexpA/dA
+  expGN = _I; // if Gamma = 0, expGN = _I
+  dexpAdA = _I4;
+
+  STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  Ee *= 0.5;
+  Eepr = Ee;
+  DlnDCe = DlnDCepr;
+
+  // update A, B -> ExtraBranch calculations are within
+  double Ke(0.), Ge(0.), Ke_pr(0.), Ge_pr(0.);
+  static STensor43 Ge_Tensor_pr, Ge_Tensor, Bd_stiffnessTerm;
+  STensorOperation::zero(Ge_Tensor_pr);
+  STensorOperation::zero(Ge_Tensor);
+  mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(Ce,Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,true,Bd_stiffnessTerm);
+  Ge_Tensor = _I4;
+  Ge_Tensor *= Ge*2; // Because the function does not do it
+  Ge_Tensor += Bd_stiffnessTerm;
+
+  // Keep the predictor values of Ke and Ge for tangents later
+  Ke_pr = Ke;
+  Ge_pr = Ge;
+  Ge_Tensor_pr = _I4;
+  Ge_Tensor_pr *= Ge_pr*2; // Because the function does not do it
+  Ge_Tensor_pr += Bd_stiffnessTerm;
+
+  // get predictor - dKeprDT
+  mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T);
+  const STensor3& dKeprDT = q1->_DcorKirDT;
+
+  // Initialise Dho
+  static STensor43 Dho, Dho2inv, Dho2_u_inv;  // This will be the final important tensor.
+  double Dho2_v_inv(0.);
+
+  // Get Mepr
+  static STensor3 Mepr, Kepr;  // Ke is corKir
+  mlawNonLinearTVP::getModifiedMandel(Ce,q0,q1);
+  Me = q1->_ModMandel;
+  Mepr = Me;
+  Kepr = q1->_kirchhoff;
+
+  // Get Xn; Initialise X
+  static STensor3 devXn, devX;
+  static double trXn, pXn, eXn, trX;
+  STensorOperation::decomposeDevTr(q0->_backsig,devXn,trXn); // needed for chaboche model
+  pXn = 1./3.*trXn;  // 1st invariant of Xn
+  eXn = sqrt(1.5*devXn.dotprod()); // J2 invariant of Xn
+
+    // Initialise Phipr
+  static STensor3 PhiPr, Phi;
+  PhiPr = q1->_ModMandel;
+  PhiPr -= q1->_backsig;
+  Phi = PhiPr;
+
+  static STensor3 devPhipr; // effective dev stress predictor
+  static double ptildepr;
+  STensorOperation::decomposeDevTr(PhiPr,devPhipr,ptildepr);
+  ptildepr/= 3.;
+
+  // Initialise Normal
+  static STensor3 devN; // dev part of yield normal
+  double trN = 0.; // trace part of yield normal
+  static STensor3 N; // yield normal
+  STensorOperation::zero(devN);
+  STensorOperation::zero(N);
+
+  // Get plastic poisson ratio
+  q1->_nup = (9.-2.*_b)/(18.+2.*_b);
+  double kk = (1./sqrt(1.+2.*q1->_nup*q1->_nup));
+
+  // Initialise variables
+  Gamma = 0.;
+  double dDgammaDGamma = 0.;
+  static fullVector<double> m(2);
+  mlawNonLinearTVP::getChabocheCoeffs(m,0,q1);
+
+  double DfDGamma(0.), dfdDgamma(0.), dfdGamma(0.), dAdDgamma(0.), dAdGamma(0.);
+
+  // Initialise Cx
+  double Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;        // pow(kk,2) DEBUG
+  double Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+  double dCxdevdDgamma(0.), dCxtrdDgamma(0.);
+  if (Hb>0.){
+    Cxdev -= m(0)*dHb*Dgamma/Hb + 1./Hb * dHbdT * (T-T0);
+    Cxtr -= m(0)*dHb*Dgamma/Hb + 1./Hb * dHbdT * (T-T0);
+  }
+
+  // Initialise ptilde and devPhi
+  ptilde = ptildepr;
+  devPhi = devPhipr;
+
+  // Initialise the rest
+  getDho(Gamma,Cepr,Ceinvpr,Kepr,Ke,Ge_Tensor,kk,Hb,Cxtr,Cxdev,expGN,dexpAdA,Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv);
+
+  double PhiEqpr2 = 1.5*devPhi.dotprod();
+  double PhiEqpr = sqrt(PhiEqpr2);      // -> second invariant
+  double PhiEq = PhiEqpr;   // current effective deviator
+
+  // Get f and A
+  f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+  A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+  // Initialise g
+  double dgdDgamma(0.), dgdGamma(0.);
+  double g = Dgamma - kk*Gamma*A;
+
+  // NR Loop - Gamma and Dgamma
+    if (q1->dissipationIsBlocked()){
+        q1->getRefToDissipationActive() = false;
+    }
+    else{
+        if (f>_tol){
+            q1->getRefToDissipationActive() = true;
+
+            // plasticity
+            int ite = 0;
+            int maxite = 100; // maximal number of iters
+            // Msg::Error("plasticity occurs f = %e",f);
+            //double f0 = fabs(f);
+
+            while (fabs(f) >_tol or ite <1){
+
+                // Viscosity term
+                double etaOverDt = eta/this->getTimeStep();
+
+                // Get dCxdevdDgamma, dCxtrdDgamma
+                dCxdevdDgamma = 0.; dCxtrdDgamma = 0.;
+                if (Hb>0.){
+                    dCxdevdDgamma = -m(0)*1./Hb*dHb - m(0)*Dgamma*(-1./pow(Hb,2.)*pow(dHb,2.) + 1./Hb*ddHb) - (T-T0)*(-1./pow(Hb,2.)*dHb*dHbdT + 1./Hb*ddHbdgammadT);
+                    dCxtrdDgamma = dCxdevdDgamma;
+                }
+                dCxdevdDgamma += 3.*m(1)*pow(kk,1)*dHb;        // pow(kk,2) DEBUG
+                dCxtrdDgamma += (2.*_b/3.)*m(1)*pow(kk,1)*dHb; // pow(kk,2) DEBUG
+
+                // Get Hp = dPhiPdDgamma, dPhiPdGamma
+                double Hp =  2*_b*pow(kk,1)*Gamma/3.*ptilde*( Hb/pow(Cxtr,2)*dCxtrdDgamma - 1./Cxtr*dHb ) * Dho2_v_inv; // pow(kk,2) DEBUG
+                double dPhiPdGamma = -2*_b*ptilde*(Ke + pow(kk,1)*Hb/(3.*Cxtr)) * Dho2_v_inv; // pow(kk,2) DEBUG
+
+                // Get He = dPhiEdGamma
+                // Get DdevPhidGamma
+                static STensor3 DdevPhidDgamma, DdevPhidDgamma_RHS;
+                static STensor3 DdevPhidGamma, DdevPhidGamma_RHS;
+                STensorOperation::zero(DdevPhidDgamma); STensorOperation::zero(DdevPhidGamma);
+                STensorOperation::zero(DdevPhidDgamma_RHS); STensorOperation::zero(DdevPhidGamma_RHS);
+
+                for (int i=0; i<3; i++)
+                    for (int j=0; j<3; j++){
+                        DdevPhidDgamma_RHS(i,j) += ( 0.5*2*_b*Gamma*Ke*Hp*_I(i,j) + 3*Gamma*pow(kk,1)*( Hb/pow(Cxdev,2.)*dCxdevdDgamma - dHb/Cxdev ) * devPhi(i,j) ); // pow(kk,2) DEBUG
+                        DdevPhidGamma_RHS(i,j) += ( -0.5*2*_b*Ke*(-ptilde-Gamma*dPhiPdGamma)*_I(i,j) - 3*pow(kk,1)*Hb/Cxdev*devPhi(i,j) ); // pow(kk,2) DEBUG
+                        for (int k=0; k<3; k++)
+                            for (int l=0; l<3; l++){
+                                DdevPhidDgamma_RHS(i,j) += 0.5* 2.*_b/3.*Gamma*Dho(i,j,k,l)*_I(k,l)*Hp;
+                                DdevPhidGamma_RHS(i,j) += 0.5* ( -3.*Ge_Tensor(i,j,k,l)*devPhi(k,l) + 2.*_b/3.*Gamma*Dho(i,j,k,l)*_I(k,l)*dPhiPdGamma );
+                                DdevPhidGamma_RHS(i,j) += 0.5*Dho(i,j,k,l)*N(k,l); // DEBUG
+                            }
+                    }
+                for (int i=0; i<3; i++)
+                    for (int j=0; j<3; j++)
+                        for (int k=0; k<3; k++)
+                            for (int l=0; l<3; l++){
+                                DdevPhidDgamma(i,j) += Dho2_u_inv(i,j,k,l)*DdevPhidDgamma_RHS(k,l);
+                                DdevPhidGamma(i,j) += Dho2_u_inv(i,j,k,l)*DdevPhidGamma_RHS(k,l);
+                            }
+
+                double Stemp1 = STensorOperation::doubledot(devPhi,DdevPhidDgamma);
+                double Stemp2 = STensorOperation::doubledot(devPhi,DdevPhidGamma);
+                double He = 1.5*Stemp1/PhiEq;
+                double dPhiEdGamma = 1.5*Stemp2/PhiEq;
+
+
+                // dAdGamma and dDgammaDGamma
+                dAdDgamma = (12.*PhiEq*He + 8.*_b*_b*ptilde*Hp/3.)/(2.*A);
+                dAdGamma = (12.*PhiEq*dPhiEdGamma + 8.*_b*_b*ptilde*dPhiPdGamma/3.)/(2.*A);
+
+                dDgammaDGamma = pow(kk,1)*(A+Gamma*dAdGamma);  // mistake in the paper (VD 2016) // pow(kk,2) DEBUG
+
+                this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+
+                dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0);
+                dfdDgamma += a(2)*_n*pow(PhiEq,(_n-1.))*He - a(1)*Hp;
+
+                if (Gamma>0 and etaOverDt>0)
+                    dfdDgamma -= _p*pow(etaOverDt,_p-1.)*Deta/this->getTimeStep()*pow(Gamma,_p);  // THIS term is absent in the paper!!
+
+                dfdGamma = _n*a(2)*pow(PhiEq,(_n-1.))*dPhiEdGamma - a(1)*dPhiPdGamma;
+                if (Gamma>0 and etaOverDt>0)
+                    dfdGamma -= pow(etaOverDt,_p)*_p*pow(Gamma,(_p-1.));
+
+                DfDGamma = dfdDgamma*dDgammaDGamma + dfdGamma;
+
+                dgdDgamma = 1. - kk*Gamma*dAdDgamma;
+                dgdGamma = - dDgammaDGamma;
+
+                double dGamma = (-f + dfdDgamma*g/dgdDgamma)/(-dfdDgamma*dgdGamma/dgdDgamma + dfdGamma); // NR
+                double dDgamma = -(g+dgdGamma*dGamma)/dgdDgamma; // NR
+
+                if (Gamma + dGamma <=0.){
+                    Gamma /= 2.;                // NR
+                }
+                else
+                    Gamma += dGamma;
+
+                // Dgammma_test += dDgamma;
+                if (Dgamma + dDgamma <=0.){
+                    Dgamma /= 2.;
+                }
+                else
+                    Dgamma += dDgamma;
+
+                //Msg::Error("Gamma = %e",Gamma);
+                //Msg::Error("Dgamma = %e",Dgamma);
+
+
+                // UPDATE FOR NEXT ITERATION
+
+                // Update gamma and all Hardening moduli
+                mlawNonLinearTVP::updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                mlawNonLinearTVP::hardening(q0,q1,T);
+                mlawNonLinearTVP::getYieldCoefficients(q1,a);
+                if (q1->_ipKinematic != NULL){
+                    Hb = q1->_ipKinematic->getR(); // kinematic hardening parameter
+                    dHb = q1->_ipKinematic->getDR(); // kinematic hardening parameter derivative (dHb/dgamma ??)
+                    dHbdT = q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+                    ddHbddT = q1->_ipKinematic->getDDRDTT();
+                    ddHbdgammadT = q1->_ipKinematic->getDDRDT();
+                }
+                //a.print("a update");
+
+
+                // Update Cx
+                Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+                Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb; // pow(kk,2) DEBUG
+                if (Hb>0.){
+                    Cxdev -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                    Cxtr -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                }
+
+                // Update Phi
+                getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                                Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1);
+                PhiEq = sqrt(1.5*devPhi.dotprod());
+
+                // Update A
+                A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+
+                // Dgamma = pow(kk,1)*Gamma*A;  // pow(kk,2) DEBUG
+                // updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                // hardening(q0,q1,T);
+                // getYieldCoefficients(q1,a);
+
+                // Update f, g
+                f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+                double viscoTerm = etaOverDt*Gamma;
+                if (Gamma>0. and etaOverDt>0.) f-= pow(viscoTerm,_p);
+
+                g = Dgamma - kk*Gamma*A;
+
+                ite++;
+                // if (ite> maxite-5)
+                // Msg::Error("it = %d, DfDGamma = %e error = %e dGamma = %e, Gamma = %e",ite,DfDGamma,f,dGamma,Gamma);
+
+                if (fabs(f) <_tol) break;
+
+                if(ite > maxite){
+                    Msg::Error("No convergence for plastic correction in mlawNonLinearTVP nonAssociatedFlow Maxwell iter = %d, f = %e!!",ite,f);
+                    P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
+                    return;
+                }
+
+            } // while
+
+            q1->_DgammaDt = Dgamma/this->getTimeStep();
+
+            // Correct Cx
+            Cxdev = 1. + 3.*m(1)*pow(kk,1)*Hb;  // pow(kk,2) DEBUG
+            Cxtr = 1. + 2.*_b/3. *m(1)*pow(kk,1)*Hb; // pow(kk,2) DEBUG
+            if (Hb>0.){
+                Cxdev -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+                Cxtr -= m(0)*dHb*Dgamma/Hb - 1./Hb * dHbdT * (T-T0);
+            }
+
+            // Correct Phi
+            getIterated_DPhi(F,T0,T,q0,q1,Gamma,Cxtr,Cxdev,Cepr,Eepr,trXn,devXn,Ke,Ge,Ge_Tensor,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                                Dho,Dho2inv,Dho2_u_inv,Dho2_v_inv,Fp1);
+            PhiEq = sqrt(1.5*devPhi.dotprod());
+
+            // Correct Normal, H = expGN
+            STensorOperation::decomposeDevTr(N,devN,trN);
+
+            // Get GammaN for mechSrcTVP
+            STensorOperation::zero(GammaN);
+            GammaN = N;
+            GammaN *= Gamma;
+            q1->_GammaN = GammaN;
+
+            // Correct plastic deformation tensor
+            STensorOperation::multSTensor3(expGN,Fp0,Fp1);
+
+            // Correct IP gamma
+            updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+                // Msg::Info("setting: gamma=%e ",q1->_epspbarre);
+
+            // Correct elastic deformation tensor, corotational stress
+            STensorOperation::inverseSTensor3(Fp1,Fpinv);
+            STensorOperation::multSTensor3(F,Fpinv,Fe);
+            STensorOperation::multSTensor3FirstTranspose(Fe,Fe,Ce);
+            STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCe,&DDlnDDCe);
+            Ee *= 0.5;
+
+        } // 2nd if
+        else{
+            q1->getRefToDissipationActive() = false;
+        }
+    } // 1st if
+
+    const STensor3& KS = q1->_kirchhoff;
+    mlawNonLinearTVP::getModifiedMandel(Ce, q0, q1); // update Mandel
+
+    const STensor3& MS = q1->_ModMandel;
+    Me = MS;
+    // second Piola Kirchhoff stress
+    static STensor3 S, Ceinv;
+    STensorOperation::inverseSTensor3(Ce,Ceinv);
+    STensorOperation::multSTensor3(Ceinv,q1->_ModMandel,S);
+
+    // first PK
+    for(int i=0; i<3; i++)
+        for(int j=0; j<3; j++){
+            P(i,j) = 0.;
+            for(int k=0; k<3; k++)
+                for(int l=0; l<3; l++)
+                    P(i,j) += Fe(i,k)*S(k,l)*Fpinv(j,l);
+        }
+}*/
+
+/*
+        //
+        // NUMERICAL phi ders wrt gamma, Gamma
+
+        double dPhiPdGamma_plus, dPhiPdDgamma_plus;
+        static STensor3 DdevPhidDgamma_plus, DdevPhidGamma_plus;
+        double Gamma_plus = Gamma + _perturbationfactor;
+        double Dgamma_plus = Dgamma; // + _perturbationfactor;
+
+        static IPNonLinearTVP qPlus1(*q0);
+
+
+        // Numerical update hardening stuff
+
+        static fullVector<double> a_plus(3), Da_plus(3);
+        updateEqPlasticDeformation(&qPlus1,q0,q1->_nup,Dgamma_plus);
+        hardening(q0,&qPlus1,T);
+        getYieldCoefficients(&qPlus1,a_plus);
+
+        double Hb_plus(0.), dHb_plus(0.), ddHb_plus(0.), dHbdT_plus(0.), ddHbdgammadT_plus(0.), ddHbddT_plus(0.);
+        if (qPlus1._ipKinematic != NULL){
+            Hb_plus = qPlus1._ipKinematic->getDR(); // kinematic hardening parameter
+            dHb_plus = qPlus1._ipKinematic->getDDR(); // kinematic hardening parameter derivative (dHb/dgamma)
+            dHbdT_plus = Hb_plus * qPlus1._ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+            // ddHbddT_plus = Hb_plus * qPlus1._ipKinematic->getDDRDDT();
+        }
+
+        double eta_plus(0.),Deta_plus(0.),DetaDT_plus(0.);
+        if (_viscosity != NULL)
+            _viscosity->get(qPlus1._epspbarre,T,eta_plus,Deta_plus,DetaDT_plus);
+
+        // Numerical Update Cx, u, v
+        double Cxdev_plus, Cxtr_plus, u_plus, v_plus, Gt_plus, Kt_plus;
+        double ptilde_plus, Dho4_v_inv_plus, DsigV_dTrEe_plus;
+        static STensor3 devPhi_plus, Phi_plus, N_plus, expGN_plus, sigExtra_plus;
+        static STensor43 dexpAdA_plus, Dho3_plus, Dho4inv_plus, Dho4_u_inv_plus;
+        static STensor43 DsigD_dDevEe_plus;
+
+        expGN_plus = _I; dexpAdA_plus = _I4;
+
+        Cxdev_plus = 1. + 3*m(1)*pow(kk,1)*Hb_plus;  // pow(kk,2) DEBUG
+        Cxtr_plus = 1. + 2*_b/3 *m(1)*pow(kk,1)*Hb_plus; // pow(kk,2) DEBUG
+        if (Hb_plus>0.){
+          Cxdev_plus -= m(0)*dHb_plus*Dgamma_plus/Hb_plus - 1/Hb_plus * dHbdT_plus * (T-T0);
+          Cxtr_plus -= m(0)*dHb_plus*Dgamma_plus/Hb_plus - 1/Hb_plus * dHbdT_plus * (T-T0);
+        }
+        Gt_plus = Ge + pow(kk,1) * Hb_plus/(2*Cxdev_plus); // pow(kk,2) DEBUG
+        Kt_plus = Ke + pow(kk,1) * Hb_plus/(3*Cxtr_plus); // pow(kk,2) DEBUG
+        u_plus = 1.+6.*Gt_plus*Gamma_plus;
+        v_plus = 1.+2.*_b*Kt_plus*Gamma_plus;
+
+        // Inititalise phi
+        ptilde_plus = ptilde;
+        devPhi_plus = devPhi;
+
+        // Numerical Update Phi
+        getIterated_DPhi(T,q0,&qPlus1,u_plus,v_plus,Gamma_plus,Cxtr_plus,Cxdev_plus,PhiPr,trXn,devXn,Cepr,Eepr,Kepr,ptilde_plus,devPhi_plus,Phi_plus,
+                            N_plus,expGN_plus,dexpAdA_plus,
+                            Dho3_plus,Dho4inv_plus,Dho4_u_inv_plus,Dho4_v_inv_plus,
+                            sigExtra_pr,sigExtra_plus,DsigV_dTrEe_plus,DsigD_dDevEe_plus);
+
+        dPhiPdGamma_plus = (ptilde_plus-ptilde)/_perturbationfactor;
+        dPhiPdDgamma_plus = (ptilde_plus-ptilde)/_perturbationfactor;
+
+
+        DdevPhidGamma_plus = devPhi_plus;
+        DdevPhidGamma_plus -= devPhi;
+        DdevPhidGamma_plus *= 1/_perturbationfactor;
+
+        DdevPhidDgamma_plus = devPhi_plus;
+        DdevPhidDgamma_plus -= devPhi;
+        DdevPhidDgamma_plus *= 1/_perturbationfactor;
+
+        /*for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                STensorOperation::inverseSTensor3(H_plus,Hinv_plus);
+                STensorOperation::multSTensor3(H_plus,H_plus,HH_plus);
+                STensorOperation::multSTensor3(Hinv_plus,Hinv_plus,HinvHinv_plus);
+                dHdH_plus(k,l,i,j) = (H_plus(k,l) - expGN(k,l))/(_perturbationfactor);
+                dHinvdH_plus(k,l,i,j) = (Hinv_plus(k,l) - Hinv(k,l))/(_perturbationfactor);
+                dHHdH_plus(k,l,i,j) = (HH_plus(k,l) - HH(k,l))/(_perturbationfactor);
+                dHinvHinvdH_plus(k,l,i,j) = (HinvHinv_plus(k,l) - HinvHinv(k,l))/(_perturbationfactor);
+           }
+*/
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.h b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.h
new file mode 100644
index 0000000000000000000000000000000000000000..11556db260dea8e631d9877757cd9b5ffbb33667
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVENonLinearTVP2.h
@@ -0,0 +1,201 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon....?)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2024
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MLAWNONLINEARTVENONLINEARTVP2_H_
+#define MLAWNONLINEARTVENONLINEARTVP2_H_
+
+#include "ipNonLinearTVP.h"
+#include "mlawNonLinearTVP.h"
+
+class mlawNonLinearTVENonLinearTVP2 : public mlawNonLinearTVP{
+
+    protected:
+		double _stressIteratorTol;
+
+    protected:
+		virtual double freeEnergyPlasticity(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T) const;
+
+		virtual void freeEnergyPlasticityDerivatives(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T, STensor3& dPsy_TVPdF, double& dPsy_TVPdT) const;
+
+        virtual void getIterated_DPhi(const STensor3& F, const double& T0, const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
+                                            double& Gamma, const double& Cxtr, const double& Cxdev,
+                                            const STensor3& Cepr, const STensor3& Eepr,
+                                            const double& trXn, const STensor3& devXn,
+                                            double& Ke, double& Ge, STensor43& Ge_Tensor,
+                                            double& ptilde, STensor3& devPhi,
+                                            STensor3& Phi, STensor3& N, STensor3& expGN, STensor43& dexpAdA,
+                                            STensor43& Dho, STensor43& Dho2inv, STensor43& Dho2_u_inv, double& Dho2_v_inv, STensor3& Fp1, const fullVector<int>& alignedIndex,
+                                            STensor43* Ge_TrEeTensor = NULL, STensor43* rotationStiffness = NULL) const;
+
+        virtual void getDho(const double& Gamma, const STensor3& Cepr, const STensor3& Ceinvpr, const STensor3& KS,
+                                  const double& Ke, const STensor43& Ge_Tensor,
+                                  const double& kk, const double& Hb, const double& Cxtr, const double& Cxdev,
+                                  const STensor3& expGN, const STensor43& dexpAdA,
+                                  STensor43& Dho, STensor43& Dho2inv, STensor43& Dho2_u_inv, double& Dho2_v_inv, STensor43* Ge_TrEeTensor = NULL, STensor43* rotationStiffness = NULL) const;
+
+        virtual void get_G1_Tensor(const STensor3& Cepr, const STensor3& expGN, const STensor43& DCeinvprDCepr, const STensor3& KS, STensor43& G1) const;
+
+        virtual void TEST_predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(
+                                        const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
+                                        const STensor3& Fepr, const STensor3& Cepr,
+                                        double& ptilde, STensor3& devPhi, double& Gamma, double& Dgamma, double& A, double& f, STensor3& Me, STensor3& P) const{};
+
+        virtual void predictorCorrector_TVP_nonAssociatedFlow_nonLinearTVE(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0_, IPNonLinearTVP *q1,
+                            STensor3&P, const bool stiff, STensor43& Tangent,  STensor43& dFedF, STensor43& dFpdF, STensor3& dFedT, STensor3& dFpdT,
+                            const double T0, const double T1,
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const;
+
+
+        virtual void predictorCorrector_ThermoViscoPlastic(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43* elasticTangent) const;
+
+        virtual void predictorCorrector_ThermoViscoPlastic(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previoustemeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &thermalSource,   // - cp*dTdt
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource, // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const; // tangent is used by pointer, if NULL->no compute
+
+        virtual void tangent_full_perturbation( // compute tangent by perturbation
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const;
+
+
+    public:
+        mlawNonLinearTVENonLinearTVP2(const int num, const double E, const double nu, const double rho, const double tol,
+                         const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                         const bool matrixbyPerturbation = false, const double pert = 1e-8, const double stressIteratorTol = 1.e-9, const bool thermalEstimationPreviousConfig = true);
+
+        #ifndef SWIG
+        mlawNonLinearTVENonLinearTVP2(const mlawNonLinearTVENonLinearTVP2& src);
+        mlawNonLinearTVENonLinearTVP2& operator=(const materialLaw& source);
+        virtual ~mlawNonLinearTVENonLinearTVP2();
+
+        virtual bool withEnergyDissipation() const {return true;};
+
+        virtual matname getType() const{return materialLaw::nonlinearTVEnonlinearTVP2;}
+        virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL,
+            const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const{
+            Msg::Error("mlawNonLinearTVENonLinearTVP2::createIPState has not been defined");
+        }
+        virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}; // this law is initialized so nothing to do
+
+        virtual void constitutive(
+                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                    const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                          STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                    const IPVariable *q0,       // array of initial internal variable
+                          IPVariable *q1,             // updated array of internal variable (in ipvcur on output),
+                          STensor43 &Tangent,         // constitutive tangents (output)
+                    const bool stiff,           // if true compute the tangents
+                          STensor43* elasticTangent = NULL,
+                    const bool dTangent =false,
+                          STensor63* dCalgdeps = NULL) const;
+
+        virtual void constitutive(
+                    const STensor3& F0,                     // initial deformation gradient (input @ time n)
+                    const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
+                          STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+                    const IPVariable *q0,                   // array of initial internal variable
+                          IPVariable *q1,                   // updated array of internal variable (in ipvcur on output),
+                          STensor43 &Tangent,               // constitutive mechanical tangents (output)
+                    const double& T0,                       // previous temperature
+                    const double& T,                        // temperature
+                    const SVector3 &gradT0,                 // previous temperature gradient
+                    const SVector3 &gradT,                  // temperature gradient
+                          SVector3 &fluxT,                  // temperature flux
+                          STensor3 &dPdT,                   // mechanical-thermal coupling
+                          STensor3 &dfluxTdgradT,           // thermal tengent
+                          SVector3 &dfluxTdT,
+                          STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                          double &thermalSource,            // - Cp*dTdt
+                          double &dthermalSourcedT,         // thermal source
+                          STensor3 &dthermalSourcedF,
+                          double &mechanicalSource,         // mechanical source--> convert to heat
+                          double &dmechanicalSourcedT,
+                          STensor3 &dmechanicalSourceF,
+                    const bool stiff,
+                          STensor43* elasticTangent = NULL) const;
+
+        virtual materialLaw* clone() const{return new mlawNonLinearTVENonLinearTVP2(*this);};
+        virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+        #endif // SWIG
+};
+
+#endif //mlawNonLinearTVENonLinearTVP2
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp
index 412ae54f97fa561f9c56149936fd8b353f0a2a95..c909e0c24a60f2b714144697e3d4d735b27631ea 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp
@@ -22,7 +22,7 @@ mlawNonLinearTVM::mlawNonLinearTVM(const int num,const double E,const double nu,
      _Tinitial(Tinitial),_scalarAlpha(Alpha),_scalarK(KThCon),_Cp(Cp),
      _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig), _mullinsEffect(NULL), _elasticPotential(NULL), 
      _useExtraBranch(false), _useExtraBranch_TVE(false), _ExtraBranch_TVE_option(2), _V0(0.),_V1(0.),_V2(0.),_D0(0.),_D1(0.),_D2(0.),_Ci(0.),
-	 _V3(0.),_V4(0.),_V5(0.),_D3(0.),_D4(0.),_D5(0.){
+	 _V3(0.),_V4(0.),_V5(0.),_D3(0.),_D4(0.),_D5(0.),_useRotationCorrection(false),_rotationCorrectionScheme(0){
 
 
   _G = _mu;
@@ -65,6 +65,8 @@ mlawNonLinearTVM::mlawNonLinearTVM(const mlawNonLinearTVM& src): mlawPowerYieldH
   _ExtraBranch_TVE_option = src._ExtraBranch_TVE_option;
   _V0 = src._V0; _V1 = src._V1; _V2 = src._V2; _D0 = src._D0; _D1 = src._D1; _D2 = src._D2; _Ci = src._Ci;
   _V3 = src._V3; _V4 = src._V4; _V5 = src._V5; _D3 = src._D3; _D4 = src._D4; _D5 = src._D5;
+  _useRotationCorrection = src._useRotationCorrection;
+  _rotationCorrectionScheme = src._rotationCorrectionScheme;
 
   _temFunc_K = NULL;                                                                    // bulk modulus
   if (src._temFunc_K != NULL){ _temFunc_K = src._temFunc_K->clone();}
@@ -116,8 +118,9 @@ mlawNonLinearTVM& mlawNonLinearTVM::operator=(const materialLaw &source){
     _ExtraBranch_TVE_option = src->_ExtraBranch_TVE_option;
     _V0 = src->_V0; _V1 = src->_V1; _V2 = src->_V2; _D0 = src->_D0; _D1 = src->_D1; _D2 = src->_D2; _Ci = src->_Ci;
     _V3 = src->_V3; _V4 = src->_V4; _V5 = src->_V5; _D3 = src->_D3; _D4 = src->_D4; _D5 = src->_D5;
+    _useRotationCorrection = src->_useRotationCorrection;
+    _rotationCorrectionScheme = src->_rotationCorrectionScheme;
 
-    
     if(_temFunc_K != NULL) delete _temFunc_K;                                                   // bulk modulus
     if (src->_temFunc_K != NULL){ _temFunc_K = src->_temFunc_K->clone();}
 
@@ -196,7 +199,7 @@ void mlawNonLinearTVM::setCorrectionsAllBranchesTVE(const int i, const double V0
   else{
 	  _V0[i-1] = V0; _V1[i-1] = V1; _V2[i-1] = V2; _D0[i-1] = D0; _D1[i-1] = D1; _D2[i-1] = D2;
 
-    Msg::Info("setting: element=%d, V0 = %e, V1 = %e, V2 = %e, D0 = %e, D1 = %e, D2 = %e",i-1,V0,V1,V2,D0,D1,D2);
+    // Msg::Info("setting: element=%d, V0 = %e, V1 = %e, V2 = %e, D0 = %e, D1 = %e, D2 = %e",i-1,V0,V1,V2,D0,D1,D2);
   }
 };
 
@@ -206,7 +209,7 @@ void mlawNonLinearTVM::setAdditionalCorrectionsAllBranchesTVE(const int i, const
   else{
     _V3[i-1] = V3; _D3[i-1] = D3;
 
-    Msg::Info("setting: element=%d, V3 = %e, D3 = %e",i-1,V3,D3);
+    //  Msg::Info("setting: element=%d, V3 = %e, D3 = %e",i-1,V3,D3);
   }
 };
 
@@ -216,7 +219,7 @@ void mlawNonLinearTVM::setAdditionalCorrectionsAllBranchesTVE(const int i, const
   else{
     _V3[i-1] = V3; _V4[i-1] = V4; _V5[i-1] = V5; _D3[i-1] = D3; _D4[i-1] = D4; _D5[i-1] = D5;
 
-    Msg::Info("setting: element=%d, V3 = %e, V4 = %e, V5 = %e, D3 = %e, D4 = %e, D5 = %e",i-1,V3,V4,V5,D3,D4,D5);
+    // Msg::Info("setting: element=%d, V3 = %e, V4 = %e, V5 = %e, D3 = %e, D4 = %e, D5 = %e",i-1,V3,V4,V5,D3,D4,D5);
   }
 };
 
@@ -226,7 +229,7 @@ void mlawNonLinearTVM::setCompressionCorrectionsAllBranchesTVE(const int i, cons
   else{
     _Ci[i-1] = Ci;
 
-    Msg::Info("setting: element=%d, Ci = %e",i-1,Ci);
+    // Msg::Info("setting: element=%d, Ci = %e",i-1,Ci);
   }
 };
 
@@ -602,11 +605,12 @@ double mlawNonLinearTVM::freeEnergyMechanical(const IPNonLinearTVM& q0, IPNonLin
                         //          Therefore, to derive CTasymm, first divide to remove it and then derive.
                             
                         // Regularising function
+                    	/*
                         double m = _tensionCompressionRegularisation;
                         double expmtr = exp(-m*q._B[i]);
                         double sigmoid = 1/(1.+expmtr);
                         double CTasymm = sigmoid + _compCorrection*(1.-sigmoid);
-                        double dCTasymmDtrE = m*expmtr/pow((1.+expmtr),2.)*(1.-_compCorrection);
+                        double dCTasymmDtrE = m*expmtr/pow((1.+expmtr),2.)*(1.-_compCorrection);*/
                         
                         (*DpsiDT) += (_Ki[i]*q._Av_TVE_vector[i]*q._B[i]*dTrEei_DT + 
                                         2.*_Gi[i]*q._Bd_TVE_vector[i]*STensorOperation::doubledot(q._A[i],dDevEei_DT)); // * CTasymm;
@@ -620,11 +624,22 @@ double mlawNonLinearTVM::freeEnergyMechanical(const IPNonLinearTVM& q0, IPNonLin
                                 // (*DpsiDE)(j,k) += (_Ki[i]*q._intAv_TVE_vector[i] + 2.*_Gi[i]*q._intBd_TVE_vector[i])/CTasymm * dCTasymmDtrE * exp_mid_k*_I(j,k);
                                 (*DpsiDE)(j,k) += (_Ki[i]*q._DintAv_TVE_vector[i] + 2.*_Gi[i]*q._DintBd_TVE_vector[i])* exp_mid_k*_I(j,k);
                                 for (int p=0; p<3; p++)
-                                    for (int r=0; r<3; r++)
+                                    for (int r=0; r<3; r++){
                                         (*DpsiDE)(j,k) += 2.*_Gi[i]*q._Bd_TVE_vector[i]*q._A[i](p,r)*exp_mid_g*_Idev(p,r,j,k); // * CTasymm; 
-                        }
-                        
-                    }
+
+                                // NEW EIGEN
+                                		if ( _useRotationCorrection == true && _rotationCorrectionScheme == 1){
+                                            for (int l=0; l<3; l++)
+                                              for (int s=0; s<3; s++){
+                                            	(*DpsiDE)(j,k) += 2.*_Gi[i]*q._Bd_TVE_vector[i]*q._A[i](p,r)*( exp_rec_g*( q._dRdEe(p,l,j,k)*q0._A[i](l,s)*q._R(s,r) + q._R(p,l)*q0._A[i](l,s)*q._dRtdEe(s,r,j,k) )
+                                            							+ exp_mid_g*( - q._dRdEe(p,l,j,k)*devEe0(l,s)*q._R(s,r) - q._R(p,l)*devEe0(l,s)*q._dRtdEe(s,r,j,k) ) );
+                                              }
+                                		}
+                                // NEW EIGEN
+                                    }
+                        } // for loop
+
+                    } // if
                 }
               }
 
@@ -674,6 +689,204 @@ void mlawNonLinearTVM::corKirInfinity(const IPNonLinearTVM *q1, const STensor3&
     CorKirTrInf = KT*(trEe - 3*AlphaT*(T1-_Tinitial));
 }
 
+void mlawNonLinearTVM::rotationTensor_N_to_Nplus1(const STensor3& Ee00, const STensor3& Fe0, const STensor3& Fe, const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0,
+													STensor3& R, STensor43& dRdEe, STensor43& dRtdEe) const{
+
+	STensorOperation::zero(R);
+
+	// Eigenvalue check
+	double e1, e2, e3;
+	static STensor3 E1, E2, E3;
+	STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3);
+
+	if (_rotationCorrectionScheme == 0){
+		STensorOperation::getBasisRotationTensor(Ee00,Ee0,R); // EIGEN 2
+		STensorOperation::zero(dRdEe); // EIGEN 2
+		STensorOperation::zero(dRtdEe); // EIGEN 2
+	}
+	else if (_rotationCorrectionScheme == 1){
+
+		double pert = _perturbationfactor/1.e-5;
+		static STensor3 Ee_plus, R_plus;
+		static STensor43 dRdEe_plus, dRtdEe_plus;
+		/*
+		for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++){
+		    Ee_plus = Ee;
+			Ee_plus(i,j) += 0.5*pert;
+			Ee_plus(j,i) += 0.5*pert;
+			STensorOperation::getBasisRotationTensor(Ee0,Ee_plus,R_plus);
+
+			for(int k=0; k<3; k++)
+			  for(int l=0; l<3; l++){
+				dRdEe_plus(k,l,i,j) = (R_plus(k,l)-R(k,l))/pert;
+				dRtdEe_plus(k,l,i,j) = (R_plus(l,k)-R(l,k))/pert;
+	     	  }
+		  }*/
+		/*
+		if (e1==e2 || e1==e3 || e2==e3){
+			STensorOperation::zero(dRdEe_plus); // EIGEN 2
+			STensorOperation::zero(dRtdEe_plus); // EIGEN 2
+		}
+		else{
+			STensorOperation::getBasisRotationTensor(Ee0,Ee,R,dRdEe_plus,dRtdEe_plus);
+		}*/
+
+		STensorOperation::getBasisRotationTensor(Ee0,Ee,R,dRdEe_plus,dRtdEe_plus); // R rotates the bases of Ee0 to that of E
+		dRdEe = dRdEe_plus;
+		dRtdEe = dRtdEe_plus;
+	}
+
+    // static STensor3 Ue, Re, Ue0, Re0, Vp0, Vp, Rp0, Rp;
+    // static STensor43 dEedFe, dEedCe, dRedEe;
+	// mlawNonLinearTVM::getdRedEe(Fe,Ce,dEedFe,dEedCe,Ue,Re,dRedEe);
+	// STensorOperation::VRDecomposition(Fe0,Vp0,Rp0); //EIGEN 2 - remove
+	// STensorOperation::VRDecomposition(Fe,Vp,Rp); //EIGEN 2 - remove
+    // STensorOperation::RUDecomposition(Fe0,Ue0,Re0);
+}
+
+void mlawNonLinearTVM::getdRedEe(const STensor3& Fe, const STensor3& Ce, const STensor43& dEedFe, const STensor43& dEedCe,
+									STensor3& Ue, STensor3& Re, STensor43& dRedEe) const{
+	STensorOperation::zero(Re);
+	STensorOperation::zero(Ue);
+	STensorOperation::RUDecomposition(Fe,Ue,Re);
+
+	static STensor43 dFedEe, dCedEe;
+	STensorOperation::inverseSTensor43(dEedFe,dFedEe);
+	STensorOperation::inverseSTensor43(dEedCe,dCedEe);
+
+	static STensor43 dFedFe;
+	STensorOperation::zero(dFedFe);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        for(int k=0; k<3; k++)
+          for(int l=0; l<3; l++)
+        	  dFedFe(i,j,k,l) += _I(i,k)*_I(j,l);
+
+	static STensor3 Ueinv;
+	STensorOperation::inverseSTensor3(Ue,Ueinv);
+	static STensor43 dUedCe, dUeinvdCe;
+	mlawNonLinearTVM::getdUedCe(Ce,Ue,dUedCe);
+    for (int i=0; i<3; i++)
+        for (int s=0; s<3; s++)
+            for (int k=0; k<3; k++)
+                for (int l=0; l<3; l++){
+                	dUeinvdCe(i,s,k,l) = 0.;
+                    for (int m=0; m<3; m++)
+                        for (int j=0; j<3; j++)
+                        	dUeinvdCe(i,s,k,l) -= Ueinv(i,m)*dUedCe(m,j,k,l)*Ueinv(j,s);
+      }
+
+    static STensor43 dUeinvdEe;
+    STensorOperation::multSTensor43(dUeinvdCe,dCedEe,dUeinvdEe);
+
+    STensorOperation::zero(dRedEe);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        for(int k=0; k<3; k++)
+          for(int l=0; l<3; l++)
+        	for(int r=0; r<3; r++)
+              dRedEe(i,j,k,l) += dFedEe(i,r,k,l)*Ueinv(r,j) + Fe(i,r)*dUeinvdEe(r,j,k,l);
+
+}
+void mlawNonLinearTVM::getdUedCe(const STensor3& Ce, const STensor3& Ue, STensor43& dUedCe) const{
+
+	double c1,c2,c3,x1,x2,x3; // eigenvalues
+	static STensor3 C1,C2,C3,E1,E2,E3; // bases
+	static STensor3 dc1da,dc2da,dc3da,dx1da,dx2da,dx3da; // eigenvalue derivatives
+	static STensor43 dC1da,dC2da,dC3da,dE1da,dE2da,dE3da; // bases derivatives
+
+	STensorOperation::getEigenDecomposition(Ce,c1,c2,c3,C1,C2,C3,dc1da,dc2da,dc3da,dC1da,dC2da,dC3da);
+	STensorOperation::getEigenDecomposition(Ue,x1,x2,x3,E1,E2,E3,dx1da,dx2da,dx3da,dE1da,dE2da,dE3da);
+
+	static STensor43 dCedCe;
+	STensorOperation::zero(dCedCe);
+	STensorOperation::zero(dUedCe);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        for(int k=0; k<3; k++)
+          for(int l=0; l<3; l++){
+        	  dCedCe(i,j,k,l) += dc1da(i,j)*C1(k,l) + dc2da(i,j)*C2(k,l) + dc3da(i,j)*C3(k,l) + c1*dC1da(i,j,k,l) + c2*dC2da(i,j,k,l) + c3*dC3da(i,j,k,l); // Should be equal to _I4
+        	  dUedCe(i,j,k,l) += dx1da(i,j)*E1(k,l) + dx2da(i,j)*E2(k,l) + dx3da(i,j)*E3(k,l) + x1*dE1da(i,j,k,l) + x2*dE2da(i,j,k,l) + x3*dE3da(i,j,k,l);
+          }
+
+    static STensor43 check;
+    check = dCedCe;
+    check -= _I4;
+}
+
+void mlawNonLinearTVM::getdEe0dEe(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, STensor43& dEe0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	double e01,e02,e03,c1,c2,c3; // eigenvalues
+	static STensor3 E01,E02,E03,C1,C2,C3; // bases
+	static STensor3 dc1da,dc2da,dc3da; // eigenvalue derivatives
+	static STensor43 dC1da,dC2da,dC3da; // bases derivatives
+
+	STensorOperation::getEigenDecomposition(Ee0,e01,e02,e03,E01,E02,E03);
+	STensorOperation::getEigenDecomposition(Ce,c1,c2,c3,C1,C2,C3,dc1da,dc2da,dc3da,dC1da,dC2da,dC3da);
+
+	// #####
+	// Align the eigenVals of Ee0 with Ee
+	static fullMatrix<double> m1(3, 3), m2(3, 3);
+	static fullVector<double> eigenValReal1(3), eigenValReal2(3), AlignedEigenValReal1(3);
+	static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+	static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+	static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), AlignedRightEigenVect1(3,3);
+	m1.setAll(0.); m2.setAll(0.);
+	eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); AlignedEigenValReal1.setAll(0.);
+	eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+	leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+	rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+
+	// Get eigen values and vectors
+	Ee0.getMat(m1); Ee.getMat(m2);
+	m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+	m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+	// for printing - Debug
+	e01 = eigenValReal1(0);
+	e02 = eigenValReal1(1);
+	e03 = eigenValReal1(2);
+
+	// Make sure rightEigenVect1 is aligned with rightEigenVect2
+	STensorOperation::alignEigenDecomposition_NormBased(Ee0,Ee,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+	// eigenValReal1 = AlignedEigenValReal1;
+	rightEigenVect1 = AlignedRightEigenVect1;
+	// e01 = AlignedEigenValReal1(0);
+	// e02 = AlignedEigenValReal1(1);
+	// e03 = AlignedEigenValReal1(2);
+	// #####
+
+	if(c1==0.) {STensorOperation::zero(dC1da);}
+	if(c2==0.) {STensorOperation::zero(dC2da);}
+	if(c3==0.) {STensorOperation::zero(dC3da);}
+
+	static STensor43 dEe0sdCe, dCedCe;
+	STensorOperation::zero(dEe0sdCe);
+	STensorOperation::zero(dCedCe);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++)
+        for(int k=0; k<3; k++)
+          for(int l=0; l<3; l++){
+        	  dEe0sdCe(i,j,k,l) += e01*dC1da(i,j,k,l) + e02*dC2da(i,j,k,l) + e03*dC3da(i,j,k,l);
+        	  dCedCe(i,j,k,l) += dc1da(i,j)*C1(k,l) + dc2da(i,j)*C2(k,l) + dc3da(i,j)*C3(k,l) + c1*dC1da(i,j,k,l) + c2*dC2da(i,j,k,l) + c3*dC3da(i,j,k,l);  // Should be equal to _I4
+          }
+
+    static STensor43 check;
+    check = dCedCe;
+    check -= _I4;
+
+    // convert to dEe0sdEe
+    static STensor3 Ee2, exp_Ee2;
+    static STensor43 dCedEe;
+	STensorOperation::zero(dCedEe);
+    Ee2 = Ee;
+    Ee2 *= 2;
+    STensorOperation::expSTensor3(Ee2,_order,exp_Ee2,&dCedEe);
+    STensorOperation::multSTensor43(dEe0sdCe,dCedEe,dEe0sdEe);
+}
 
 void mlawNonLinearTVM::evaluateElasticCorrection(const double trE, const STensor3 &devE, const double& T, 
                                                  double &A_v, double &dA_vdE, double &intA, double &dAdT,
@@ -1132,67 +1345,6 @@ void mlawNonLinearTVM::extraBranch_nonLinearTVE(const int i, const STensor3& Ee,
                 // Msg::Error(" Inside extraBranch_nonLinearTVE Type 4, _D1 = 0. or _D4 = 0., incompatibility with Mullin's effect");
             }
         }
-    /*else if (_ExtraBranch_TVE_option == 5){
-
-                // Sigmoid + Exponential + Tension-Compression Asymmetry
-                // Standard form => A_v = sigmoid*a/(sqrt(b*tr*tr+c)) + (1-sigmoid)* Comp* (a/(sqrt(b*tr*tr+c)) + d*exp(f*tr*tr+g))
-
-                // Regularising function
-                double m = _tensionCompressionRegularisation;
-                double expmtr = exp(-m*tr);
-                // if (exp(-m*tr)<1.e+10){ expmtr = exp(-m*tr);}
-                double sigmoid = 1/(1.+expmtr);
-
-                // Av
-                double x1 = _V1[i]*tr*tr + _V2[i];
-                double x2 = _V4[i]*tr*tr + _V5[i];
-                Av = sigmoid*(getVolumeCorrection()/sqrt(x1)) + (1-sigmoid)*_Ci[i]*(getVolumeCorrection()/sqrt(x1) + _V3[i]*exp(x2));
-
-                dA_dTrEe = sigmoid*(-getVolumeCorrection()*_V1[i]*tr/pow(x1,1.5)) + (1.-sigmoid)*_Ci[i]*( -getVolumeCorrection()*_V1[i]*tr/pow(x1,1.5) + 2*_V3[i]*_V4[i]*tr*exp(x2))
-                           + (m*expmtr/pow((1.+expmtr),2.))*getVolumeCorrection()*1./sqrt(x1) - (m*expmtr/pow((1.+expmtr),2.))*_Ci[i]*(getVolumeCorrection()/sqrt(x1) + _V3[i]*exp(x2)) ;
-
-                if(_V1[i]>0. && _V4[i]>0.){
-                    double integrand1 = 1./_V1[i]*sqrt(x1); // integral of A_v * trEe
-                    integrand1 -= ( 1./_V1[i]*sqrt(_V2[i]) ); // value at trEe = 0.
-                    integrand1 *= getVolumeCorrection();
-
-                    double integrand2 = exp(x2)/(2*_V4[i]);
-                    integrand2 -= exp(_V5[i])/(2*_V4[i]);
-					integrand2 *= _V3[i];
-
-                    intA = sigmoid*integrand1 + (1.-sigmoid)*_Ci[i]*(integrand1 + integrand2);
-                }
-                else{
-                    intA = 1.;
-                }
-
-                // Bd
-                double y1 = _D1[i]*dev.dotprod() + _D2[i];
-                double y2 = _D4[i]*dev.dotprod() + _D5[i];
-                Bd = sigmoid*(getDevCorrection()/sqrt(y1)) + (1-sigmoid)*_Ci[i]*(getDevCorrection()/sqrt(y1) + _D3[i]*exp(y2));
-
-                STensorOperation::zero(dB_dDevEe);
-                dB_dDevEe = dev;
-                dB_dDevEe *= ( sigmoid*(-getDevCorrection()*_D1[i]/pow(y1,1.5)) + (1.-sigmoid)*_Ci[i]*( -getDevCorrection()*_D1[i]/pow(y1,1.5) + 2*_D3[i]*_D4[i]*exp(y2)) );
-
-                if(dB_dTrEe!=NULL){
-                    *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*getDevCorrection()*1./sqrt(y1) - (m*expmtr/pow((1.+expmtr),2.))*_Ci[i]*(getDevCorrection()/sqrt(y1) + _D3[i]*exp(y2));
-                }
-                if(_D1[i]>0. && _D4[i]>0.){
-                    double integrand1 = 1./_D1[i]*sqrt(y1);  // integral of B_d * devEe
-                    integrand1 -= (1./_D1[i]*sqrt(_D2[i]) );  // value at devEe = 0.
-                    integrand1 *= getDevCorrection();
-
-                    double integrand2 = exp(y2)/(2*_D4[i]);
-                    integrand2 -= exp(_D5[i])/(2*_D4[i]);
-					integrand2 *= _D3[i];
-
-					intB = sigmoid*integrand1 + (1.-sigmoid)*_Ci[i]*(integrand1 + integrand2);
-                }
-                else{
-                    intB = 1.;
-                }
-            }*/
     else if (_ExtraBranch_TVE_option == 5){
 
             // Tension-Compression Asymmetry
@@ -1207,25 +1359,28 @@ void mlawNonLinearTVM::extraBranch_nonLinearTVE(const int i, const STensor3& Ee,
 
             // Av
             double x1 = _V1[i]*tr*tr + _V2[i];
-            double x2 = _V4[i]*tr*tr + _V5[i];
-            Av = sigmoid*(1./sqrt(x1)+ _V3[i]*(1+tanh(x2))) + (1.-sigmoid)*(_Ci[i]*(1./sqrt(x1) + _V3[i]));
+            double x2 = _V4[i]*tr*tr;
+            Av = sigmoid*(1./sqrt(x1)+ _V3[i]*(_V5[i]+tanh(x2))) + (1.-sigmoid)*(_Ci[i]*(1./sqrt(x1) + _V0[i]));
+            // Av = sigmoid*(1./sqrt(x1)+_V0[i]) + (1.-sigmoid)*_Ci[i]*(1/sqrt(x2)+_V3[i]); -> Type4
             // Av *= getVolumeCorrection();
 
             dA_dTrEe = -sigmoid*(_V1[i]*tr/pow(x1,1.5) - _V3[i]*(2*_V4[i]*tr*pow(1/cosh(x2),2))) - (1.-sigmoid)*(_V1[i]*_Ci[i]*tr/pow(x1,1.5))
-                       + (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + _V3[i]*(1+tanh(x2)))- (_Ci[i]*m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + _V3[i]);
+                       + (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + _V3[i]*(_V5[i]+tanh(x2)))- (_Ci[i]*m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(x1) + _V0[i]);
             // dA_dTrEe *= getVolumeCorrection();
 
             if(_V1[i]>0.){
-                double integrand1 = 1./_V1[i]*sqrt(x1) + _V3[i]*tr*tr/2.; // integral of A_v * trEe
+                double integrand1 = 1./_V1[i]*sqrt(x1) + _V3[i]*_V5[i]*tr*tr/2.; // integral of A_v * trEe
                 double integrand2 = 0.;
+                double integrand3 = 1./_V1[i]*sqrt(x1) + _V0[i]*tr*tr/2.;
                 if(_V4[i] != 0.){
                 	integrand2 = _V3[i]/(2.*_V4[i])*log(cosh(x2));
                 }
                 integrand1 -= ( 1./_V1[i]*sqrt(_V2[i]) ); // value at trEe = 0.
-                intA = sigmoid*(integrand1 + integrand2) + _Ci[i]*(1.-sigmoid)*integrand1;
+                integrand3 -= ( 1./_V1[i]*sqrt(_V2[i]) ); // value at trEe = 0.
+                intA = sigmoid*(integrand1 + integrand2) + _Ci[i]*(1.-sigmoid)*integrand3;
                 // intA *= getVolumeCorrection();
 
-                DintA = (m*expmtr/pow((1.+expmtr),2.))*integrand1 - _Ci[i]*(m*expmtr/pow((1.+expmtr),2.))*integrand2;
+                DintA = (m*expmtr/pow((1.+expmtr),2.))*(integrand1 + integrand2) - _Ci[i]*(m*expmtr/pow((1.+expmtr),2.))*integrand3;
             }
             else{
                 intA = 1.;
@@ -1233,8 +1388,8 @@ void mlawNonLinearTVM::extraBranch_nonLinearTVE(const int i, const STensor3& Ee,
 
             // Bd
             double y1 = _D1[i]*dev.dotprod() + _D2[i];
-            double y2 = _D4[i]*dev.dotprod() + _D5[i];
-            Bd = sigmoid* (1./sqrt(y1) + _D3[i]*(1+tanh(y2))) + (1.-sigmoid)*(_Ci[i]*(1./sqrt(y1) + _D3[i])) ;
+            double y2 = _D4[i]*dev.dotprod();
+            Bd = sigmoid* (1./sqrt(y1) + _D3[i]*(_D5[i] + tanh(y2))) + (1.-sigmoid)*(_Ci[i]*(1./sqrt(y1) + _D0[i])) ;
             // Bd *= getDevCorrection();
 
             STensorOperation::zero(dB_dDevEe);
@@ -1243,20 +1398,22 @@ void mlawNonLinearTVM::extraBranch_nonLinearTVE(const int i, const STensor3& Ee,
             // dB_dDevEe *= getDevCorrection();
 
             if(dB_dTrEe!=NULL){
-                *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(y1) + _D3[i]*(1+tanh(y2))) - (m*expmtr/pow((1.+expmtr),2.))*(_Ci[i]*(1./sqrt(y1) + _D3[i]));
+                *dB_dTrEe = (m*expmtr/pow((1.+expmtr),2.))*(1./sqrt(y1) + _D3[i]*(_D5[i] + tanh(y2))) - (m*expmtr/pow((1.+expmtr),2.))*(_Ci[i]*(1./sqrt(y1) + _D0[i]));
                 // *dB_dTrEe *= getDevCorrection();
             }
             if(_D1[i]>0.){
-                double integrand1 = 1./_D1[i]*sqrt(y1) + _D3[i]*dev.dotprod()/2.;  // integral of B_d * devEe
+                double integrand1 = 1./_D1[i]*sqrt(y1) + _D3[i]*_D5[i]*dev.dotprod()/2.;  // integral of B_d * devEe
                 double integrand2 = 0.;
+                double integrand3 = 1./_D1[i]*sqrt(y1) + _D0[i]*dev.dotprod()/2.;
                 if(_D4[i] != 0.){
                 	integrand2 = _D3[i]/(2.*_D4[i])*log(cosh(y2));
                 }
                 integrand1 -= (1./_D1[i]*sqrt(_D2[i]) );  // value at devEe = 0.
-                intB = sigmoid*(integrand1 + integrand2) + _Ci[i]*(1.-sigmoid)*integrand1;
+                integrand3 -= (1./_D1[i]*sqrt(_D2[i]) );  // value at devEe = 0.
+                intB = sigmoid*(integrand1 + integrand2) + _Ci[i]*(1.-sigmoid)*integrand3;
                 // intB *= getDevCorrection();
 
-                DintB = (m*expmtr/pow((1.+expmtr),2.))*integrand1 - _Ci[i]*(m*expmtr/pow((1.+expmtr),2.))*integrand2;
+                DintB = (m*expmtr/pow((1.+expmtr),2.))*(integrand1 + integrand2) - _Ci[i]*(m*expmtr/pow((1.+expmtr),2.))*integrand3;
             }
             else{
                 intB = 1.;
@@ -1301,7 +1458,7 @@ void mlawNonLinearTVM::extraBranch_nonLinearTVE(const int i, const STensor3& Ee,
                         
 void mlawNonLinearTVM::ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
           const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
-          double& Ke, double& Ge, double& DKDTsum, double& DGDTsum,
+          double& Ke, double& Ge,
           const double T0, const double T1, const bool stiff, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2) const{
 
     // NEW
@@ -1345,7 +1502,6 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
     
     // Initialise Moduli
     Ke = KT; Ge = GT;
-    DKDTsum = DKDT; DGDTsum = DGDT;
     
     if(_useExtraBranch){
         
@@ -1457,11 +1613,9 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
                 
                 // Ge for DcorKirDE
                 Ge += _Gi[i]*exp_mid_g; // 2* (..) - Dont multiply by 2 if using lambda and mu in Hooks tensor function
-                DGDTsum += -_Gi[i]/(_gi[i])*Ddt_shiftDT_mid*exp_mid_g;
             
                 // Ke for DcorKirDE
                 Ke += _Ki[i]*exp_mid_k;
-                DKDTsum += -_Ki[i]/(_ki[i])*Ddt_shiftDT_mid*exp_mid_k;
             
                 // Single Convolution
                 for (int k=0; k<3; k++)
@@ -1490,12 +1644,10 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
                 
                     // Ge for DcorKirDE
                     Ge += ( exp_mid_g *_Gi[i] * q0->_Bd_TVE ); // 2* (..) - Dont multiply by 2 if using lambda and mu in Hooks tensor function
-                    DGDTsum += ( -_Gi[i]/(_gi[i])*Ddt_shiftDT_mid*exp_mid_g );
             
                     // Ke for DcorKirDE
                     Ke += ( exp_mid_k *_Ki[i] * Av ) ; 
                     Ke += ( exp_mid_k *_Ki[i]* q0->_B[i]/Av * dA_dTrEe );
-                    DKDTsum += (-_Ki[i]/(_ki[i])*Ddt_shiftDT_mid*exp_mid_k);
             
                     // Single Convolution
                     double temp2(0.);
@@ -2454,18 +2606,42 @@ void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
     E *= 0.5; // strain
     
     // Stresses and Effective Moduli
-    double Ke(0.), Ge(0.), DKDTsum(0.), DGDTsum(0.);
+    double Ke(0.), Ge(0.);
     static STensor43 Bd_stiffnessTerm, Bd_stiffnessTerm2;
     STensorOperation::zero(Bd_stiffnessTerm);
     STensorOperation::zero(Bd_stiffnessTerm2);
+
+
     if(_extraBranchNLType == TensionCompressionRegularisedType || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
-        ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm,&Bd_stiffnessTerm2); 
+        ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm,&Bd_stiffnessTerm2);
                 // Updates the values of moduli to the current temperatures and calculate stresses.
     }
     else{
-        ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm); 
+        ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
     }
     
+
+    static fullMatrix<double> m1(3, 3), m2(3, 3);
+    static fullVector<double> eigenValReal1(3), eigenValReal2(3);
+    static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+    static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+    static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3);
+    m1.setAll(0.); m2.setAll(0.);
+    eigenValReal1.setAll(0.); eigenValReal2.setAll(0.);
+    eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+    leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+    rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.);
+
+    // Get eigen values and vectors
+    q1->_kirchhoff.getMat(m1); C.getMat(m2);
+    m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+    m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+    double eig1, eig2, eig3, eig10,eig20,eig30;
+    static STensor3 E1,E2,E3,E10,E20,E30;
+    STensorOperation::getEigenDecomposition(q1->_kirchhoff,eig1,eig2,eig3,E1,E2,E3);
+    STensorOperation::getEigenDecomposition(C,eig10,eig20,eig30,E10,E20,E30);
+
     // additional hyperelastic branch - NOt necessary anymore
     // NEW
     /*
@@ -2485,17 +2661,51 @@ void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
     STensorOperation::decomposeDevTr(corKir,devT,pT);
     q1->_pressure = pT/3.;
     
-    static STensor3 secondPK; // , Ceinv, Me, temp1_Me, temp2_Me;
-    /*
-    STensorOperation::inverseSTensor3(C,Ceinv);
-    STensorOperation::multSTensor3(C, q1->_kirchhoff, temp1_Me);
-    STensorOperation::multSTensor3(temp1_Me, Ceinv, temp2_Me);
-    Me = 0.5*(q1->_kirchhoff + temp2_Me);
-    STensorOperation::multSTensor3(Ceinv,Me,secondPK);*/
-    
+    static STensor3 secondPK;
     STensorOperation::multSTensor3STensor43(q1->_kirchhoff,dlnCdC,secondPK);
     STensorOperation::multSTensor3(F,secondPK,P);                  // 1st PK
     
+    static STensor3 M;
+    STensorOperation::multSTensor3(C,secondPK,M);
+    q1->_ModMandel = M;
+
+    // commuteChecker -> for commuting tensors Ce and Se, Me has to be symmetric ->
+    // 			For two cases, both in the case of viscoplasticity if Een and Ee dont share eigenvectors: 1. Due to plasticity (Rp)  2. Due to non-proportional loading
+    static STensor3 commuteChecker, MT;
+    STensorOperation::transposeSTensor3(M,MT);
+    commuteChecker = M;
+    commuteChecker -= MT;
+    q1->_mandelCommuteChecker = commuteChecker.norm0();
+    if(q1->_mandelCommuteChecker > 1.e-6){
+    	// Msg::Error("Mandel does not commute in mlawNonLinearTVM, norm = %e, tol = %e !!",q1->_mandelCommuteChecker,1.e-6);
+    }
+
+    //
+
+    // check
+    /*
+    double Ke_new, Ge_new;
+    static STensor3 Ee0_rot, R, secondPK_new, Me_new;
+    static STensor43 dRdEe, dRtdEe, Bd_stiffnessTerm_new, Bd_stiffnessTerm2_new;
+	mlawNonLinearTVM::rotationTensor_N_to_Nplus1(E,q0->_Ee,R,dRdEe,dRtdEe);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++){
+    	 Ee0_rot(i,j) = 0.;
+    	 for(int k=0; k<3; k++)
+    	   for(int l=0; l<3; l++)
+    	     Ee0_rot(i,j) += R(i,k)*q0->_Ee(k,l)*R(j,l);
+      }
+
+	static IPNonLinearTVM q1_test(*q0);
+	if(_extraBranchNLType == TensionCompressionRegularisedType || _extraBranchNLType == hyper_exp_TCasymm_Type || _ExtraBranch_TVE_option == 3 || _ExtraBranch_TVE_option == 4 || _ExtraBranch_TVE_option == 5){
+        ThermoViscoElasticPredictor(E,Ee0_rot,q0,&q1_test,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm_new,&Bd_stiffnessTerm2_new);
+    }
+    else{
+        ThermoViscoElasticPredictor(E,Ee0_rot,q0,&q1_test,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm2_new);
+    }
+    STensorOperation::multSTensor3STensor43(q1_test._kirchhoff,dlnCdC,secondPK_new);
+    STensorOperation::multSTensor3(C,secondPK_new,Me_new);*/
+
     // elastic energy and derivatives
     double& Dpsi_DT = q1->getRefTo_Dpsi_DT();
     STensor3& Dpsi_DE = q1->getRefTo_Dpsi_DE();
@@ -2784,12 +2994,12 @@ void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
                         }
                 }
             }
-            // dmechanicalSourceE += dWmdE_TVE; // TVE term
+            dmechanicalSourceE += dWmdE_TVE; // TVE term
             STensorOperation::multSTensor3STensor43(dmechanicalSourceE,DEeDFe,dmechanicalSourceF);
         
             dmechanicalSourcedT += (STensorOperation::doubledot(DcorKirDT,DEe)/this->getTimeStep());
             dmechanicalSourcedT += T*(STensorOperation::doubledot(DDcorKirDT,DEe)/this->getTimeStep());
-            // dmechanicalSourcedT += dWmdT_TVE; // TVE term
+            dmechanicalSourcedT += dWmdT_TVE; // TVE term
         }
         
         // Compute Tangents for Mullin's Effect
@@ -2839,10 +3049,325 @@ void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
     }
 };
 
-void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, const STensor3& Ee0,
-          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
-          double& Ke, double& Ge,
-          const double T0, const double T1, const bool stiff, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2) const{
+void mlawNonLinearTVM::getEe0s(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, STensor3& Ee0s, STensor43& dEe0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	double e01,e02,e03, e1,e2,e3, c1,c2,c3; // eigenvalues
+	static STensor3 E01,E02,E03,E1,E2,E3,C1,C2,C3; // bases
+	static STensor3 dc1da,dc2da,dc3da; // eigenvalue derivatives
+	static STensor43 dC1da,dC2da,dC3da; // bases derivatives
+
+	STensorOperation::getEigenDecomposition(Ee0,e01,e02,e03,E01,E02,E03);
+	STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3);
+	STensorOperation::getEigenDecomposition(Ce,c1,c2,c3,C1,C2,C3,dc1da,dc2da,dc3da,dC1da,dC2da,dC3da);
+
+	// #####
+	// Align the eigenVals of Ee0 with Ee
+	static fullMatrix<double> m1(3, 3), m2(3, 3);
+	static fullVector<double> eigenValReal1(3), eigenValReal2(3), AlignedEigenValReal1(3);
+	static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+	static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+	static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), AlignedRightEigenVect1(3,3);
+	m1.setAll(0.); m2.setAll(0.);
+	eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); AlignedEigenValReal1.setAll(0.);
+	eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+	leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+	rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+
+	// Get eigen values and vectors
+	Ee0.getMat(m1); Ce.getMat(m2);
+	m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+	m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+	// for printing - Debug
+	e01 = eigenValReal1(0);
+	e02 = eigenValReal1(1);
+	e03 = eigenValReal1(2);
+
+	// Make sure rightEigenVect1 is aligned with rightEigenVect2
+	STensorOperation::alignEigenDecomposition_NormBased(Ee0,Ce,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+	rightEigenVect1 = AlignedRightEigenVect1;
+	// #####
+
+	if(c1==0.) {STensorOperation::zero(dC1da);}
+	if(c2==0.) {STensorOperation::zero(dC2da);}
+	if(c3==0.) {STensorOperation::zero(dC3da);}
+
+	static STensor43 dEe0sdCe, dCedCe;
+	STensorOperation::zero(dEe0sdCe);
+	STensorOperation::zero(dCedCe);
+	STensorOperation::zero(Ee0s);
+    for(int i=0; i<3; i++)
+      for(int j=0; j<3; j++){
+    	Ee0s(i,j) += e01*C1(i,j) + e02*C2(i,j) + e03*C3(i,j);
+        for(int k=0; k<3; k++)
+          for(int l=0; l<3; l++){
+        	  dEe0sdCe(i,j,k,l) += e01*dC1da(i,j,k,l) + e02*dC2da(i,j,k,l) + e03*dC3da(i,j,k,l);
+        	  dCedCe(i,j,k,l) += dc1da(i,j)*C1(k,l) + dc2da(i,j)*C2(k,l) + dc3da(i,j)*C3(k,l) + c1*dC1da(i,j,k,l) + c2*dC2da(i,j,k,l) + c3*dC3da(i,j,k,l);  // Should be equal to _I4
+          }
+      }
+
+    static STensor43 check;
+    check = dCedCe;
+    check -= _I4;
+
+    // convert to dEe0sdEe
+    static STensor3 Ee2, exp_Ee2;
+    static STensor43 dCedEe;
+	STensorOperation::zero(dCedEe);
+    Ee2 = Ee;
+    Ee2 *= 2;
+    STensorOperation::expSTensor3(Ee2,_order,exp_Ee2,&dCedEe);
+    STensorOperation::multSTensor43(dEe0sdCe,dCedEe,dEe0sdEe);
+}
+
+void mlawNonLinearTVM::getEe0s2(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, int& index1, int& index2, int& index3, STensor3& Ee0s, STensor43& dEe0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	static fullVector<double> eigenValReal1(3); eigenValReal1.setAll(0.);
+	double e01,e02,e03,e1,e2,e3; // eigenvalues
+	static STensor3 E01,E02,E03,E1,E2,E3; // bases
+	static STensor3 de1da,de2da,de3da; // eigenvalue derivatives
+	static STensor43 dE1da,dE2da,dE3da; // bases derivatives
+	STensorOperation::getEigenDecomposition(Ee0,e01,e02,e03,E01,E02,E03);
+	eigenValReal1(0) = e01; eigenValReal1(1) = e02; eigenValReal1(2) = e03;
+
+
+	double det = STensorOperation::determinantSTensor3(Ee);
+	if(det!=0.){
+		STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3,de1da,de2da,de3da,dE1da,dE2da,dE3da);
+
+		// Make sure rightEigenVect1 is aligned with rightEigenVect2
+		// STensorOperation::alignEigenDecomposition_NormBased(Ee0,Ee,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+		// rightEigenVect1 = AlignedRightEigenVect1;
+		// STensorOperation::alignEigenDecomposition_EigenVectorDotProductBased(eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+		STensorOperation::alignEigenDecomposition_NormBased(Ee0,Ee,e1,e2,e3,E1,E2,E3,eigenValReal1,index1,index2,index3,e01,e02,e03);
+
+
+		static STensor43 dEedEe;
+		STensorOperation::zero(dEe0sdEe);
+		STensorOperation::zero(dEedEe);
+		STensorOperation::zero(Ee0s);
+		for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++){
+			Ee0s(i,j) += e01*E1(i,j) + e02*E2(i,j) + e03*E3(i,j);
+			for(int k=0; k<3; k++)
+			  for(int l=0; l<3; l++){
+				  dEe0sdEe(i,j,k,l) += e01*dE1da(i,j,k,l) + e02*dE2da(i,j,k,l) + e03*dE3da(i,j,k,l);
+				  dEedEe(i,j,k,l) += de1da(i,j)*E1(k,l) + de2da(i,j)*E2(k,l) + de3da(i,j)*E3(k,l) + e1*dE1da(i,j,k,l) + e2*dE2da(i,j,k,l) + e3*dE3da(i,j,k,l);  // Should be equal to _I4
+			  }
+		  }
+
+		static STensor43 check;
+		check = dEedEe;
+		check -= _I4;
+	}
+	else{
+		STensorOperation::zero(de1da); STensorOperation::zero(de2da); STensorOperation::zero(de3da); STensorOperation::zero(dE1da); STensorOperation::zero(dE2da); STensorOperation::zero(dE3da);
+		Ee0s=Ee0;
+	}
+
+}
+
+void mlawNonLinearTVM::getAi0s2(const STensor3& Ce, const STensor3& Ee, const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	double e01,e02,e03,e1,e2,e3; // eigenvalues
+	static STensor3 E01,E02,E03,E1,E2,E3; // bases
+	static STensor3 de1da,de2da,de3da; // eigenvalue derivatives
+	static STensor43 dE1da,dE2da,dE3da; // bases derivatives
+
+	double det = STensorOperation::determinantSTensor3(Ee);
+	if(det!=0.){
+		STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3,de1da,de2da,de3da,dE1da,dE2da,dE3da);
+	}
+	else{
+		STensorOperation::zero(de1da); STensorOperation::zero(de2da); STensorOperation::zero(de3da); STensorOperation::zero(dE1da); STensorOperation::zero(dE2da); STensorOperation::zero(dE3da);
+	}
+
+
+	// #####
+	// Align the eigenVals of Ee0 with Ee
+	static fullMatrix<double> m1(3, 3), m2(3, 3);
+	static fullVector<double> eigenValReal1(3), eigenValReal2(3), AlignedEigenValReal1(3);
+	static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+	static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+	static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), AlignedRightEigenVect1(3,3);
+	m1.setAll(0.); m2.setAll(0.);
+	eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); AlignedEigenValReal1.setAll(0.);
+	eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+	leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+	rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+
+	// Get eigen values and vectors
+	Ee.getMat(m2); m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+    // Loop
+    for (int i=0; i<_Gi.size(); i++){
+
+    	// Get eigen values and vectors
+    	m1.setAll(0.); eigenValReal1.setAll(0.); eigenValImag1.setAll(0.); leftEigenVect1.setAll(0.); rightEigenVect1.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+    	STensorOperation::getEigenDecomposition(Ai0[i],e01,e02,e03,E01,E02,E03);
+    	Ai0[i].getMat(m1);
+    	m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+
+
+    	// eigenvalues
+    	e01 = eigenValReal1(0);
+    	e02 = eigenValReal1(1);
+    	e03 = eigenValReal1(2);
+
+    	// Make sure rightEigenVect1 is aligned with rightEigenVect2
+    	STensorOperation::alignEigenDecomposition_NormBased(Ai0[i],Ee,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+    	// STensorOperation::alignEigenDecomposition_EigenVectorDotProductBased(eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+        rightEigenVect1 = AlignedRightEigenVect1;
+
+    	STensorOperation::zero(dAi0sdEe[i]);
+    	// STensorOperation::zero(dCedCe);
+    	STensorOperation::zero(Ai0s[i]);
+    	for(int p=0; p<3; p++)
+    		for(int j=0; j<3; j++){
+    			Ai0s[i](p,j) += e01*E1(p,j) + e02*E2(p,j) + e03*E3(p,j);
+    			for(int k=0; k<3; k++)
+    				for(int l=0; l<3; l++){
+    					dAi0sdEe[i](p,j,k,l) += e01*dE1da(p,j,k,l) + e02*dE2da(p,j,k,l) + e03*dE3da(p,j,k,l);
+    					// dCedCe(p,j,k,l) += dc1da(p,j)*C1(k,l) + dc2da(p,j)*C2(k,l) + dc3da(p,j)*C3(k,l) + c1*dC1da(p,j,k,l) + c2*dC2da(p,j,k,l) + c3*dC3da(p,j,k,l);  // Should be equal to _I4
+    				}
+    		}
+    }
+}
+
+void mlawNonLinearTVM::getAi0s2(const STensor3& Ce, const STensor3& Ee, const int& index1, const int& index2, const int& index3,
+								const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	static fullVector<double> eigenValReal1(3); eigenValReal1.setAll(0.);
+	double e01_s,e02_s,e03_s,e01,e02,e03,e1,e2,e3; // eigenvalues
+	static STensor3 E01,E02,E03,E1,E2,E3; // bases
+	static STensor3 de1da,de2da,de3da; // eigenvalue derivatives
+	static STensor43 dE1da,dE2da,dE3da; // bases derivatives
+
+	double det = STensorOperation::determinantSTensor3(Ee);
+	if(det!=0.){
+		STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3,de1da,de2da,de3da,dE1da,dE2da,dE3da);
+
+		// Loop
+		for (int i=0; i<_Gi.size(); i++){
+
+			// Assign
+			STensorOperation::getEigenDecomposition(Ai0[i],e01,e02,e03,E01,E02,E03);
+			eigenValReal1(0) = e01; eigenValReal1(1) = e02; eigenValReal1(2) = e03;
+
+			// Reassign
+			e01_s = eigenValReal1(index1); e02_s = eigenValReal1(index2); e03_s = eigenValReal1(index3);
+
+			STensorOperation::zero(dAi0sdEe[i]);
+			// STensorOperation::zero(dEedEe);
+			STensorOperation::zero(Ai0s[i]);
+			for(int p=0; p<3; p++)
+				for(int j=0; j<3; j++){
+					Ai0s[i](p,j) += e01_s*E1(p,j) + e02_s*E2(p,j) + e03_s*E3(p,j);
+					for(int k=0; k<3; k++)
+						for(int l=0; l<3; l++){
+							dAi0sdEe[i](p,j,k,l) += e01_s*dE1da(p,j,k,l) + e02_s*dE2da(p,j,k,l) + e03_s*dE3da(p,j,k,l);
+							// dEedEe(p,j,k,l) += de1da(p,j)*E1(k,l) + de2da(p,j)*E2(k,l) + de3da(p,j)*E3(k,l) + e1*dE1da(p,j,k,l) + e2*dE2da(p,j,k,l) + e3*dE3da(p,j,k,l);  // Should be equal to _I4
+						}
+				}
+		}
+
+	}
+	else{
+		STensorOperation::zero(de1da); STensorOperation::zero(de2da); STensorOperation::zero(de3da); STensorOperation::zero(dE1da); STensorOperation::zero(dE2da); STensorOperation::zero(dE3da);
+	}
+}
+
+void mlawNonLinearTVM::get_Ee0s_Ai0s_ders(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, const std::vector<STensor3>& Ai0, const fullVector<int>& alignedIndex,
+								STensor3& Ee0s, STensor43& dEe0sdEe, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee, Ai0 becomes Ai0s
+
+	static fullVector<double> eigenValReal1(3); eigenValReal1.setAll(0.);
+	double e01,e02,e03,ai1,ai2,ai3,e1,e2,e3; // eigenvalues
+	double e01_s,e02_s,e03_s,ai1_s,ai2_s,ai3_s; // eigenvalues_rotated
+	static STensor3 E01,E02,E03,Ai1,Ai2,Ai3,E1,E2,E3; // bases
+	static STensor3 de1da,de2da,de3da; // eigenvalue derivatives
+	static STensor43 dE1da,dE2da,dE3da; // bases derivatives
+
+	STensorOperation::getEigenDecomposition(Ee0,e01,e02,e03,E01,E02,E03);
+
+	double det = STensorOperation::determinantSTensor3(Ee);
+	if(det!=0.){
+		STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3,de1da,de2da,de3da,dE1da,dE2da,dE3da);
+
+		// Align Ee0 and get its derivative
+
+		// Assign
+		STensorOperation::getEigenDecomposition(Ee0,e01,e02,e03,E01,E02,E03);
+		eigenValReal1(0) = e01; eigenValReal1(1) = e02; eigenValReal1(2) = e03;
+
+		// Reassign aligned eigVal
+		e01_s = eigenValReal1(alignedIndex(0)); e02_s = eigenValReal1(alignedIndex(1)); e03_s = eigenValReal1(alignedIndex(2));
+
+		static STensor43 dEedEe;
+		STensorOperation::zero(dEe0sdEe);
+		STensorOperation::zero(dEedEe);
+		STensorOperation::zero(Ee0s);
+		for(int i=0; i<3; i++)
+		  for(int j=0; j<3; j++){
+			Ee0s(i,j) += e01_s*E1(i,j) + e02_s*E2(i,j) + e03_s*E3(i,j);
+			for(int k=0; k<3; k++)
+			  for(int l=0; l<3; l++){
+				  dEe0sdEe(i,j,k,l) += e01_s*dE1da(i,j,k,l) + e02_s*dE2da(i,j,k,l) + e03_s*dE3da(i,j,k,l);
+				  dEedEe(i,j,k,l) += de1da(i,j)*E1(k,l) + de2da(i,j)*E2(k,l) + de3da(i,j)*E3(k,l) + e1*dE1da(i,j,k,l) + e2*dE2da(i,j,k,l) + e3*dE3da(i,j,k,l);  // Should be equal to _I4
+			  }
+		  }
+
+		static STensor43 check;
+		check = dEedEe;
+		check -= _I4;
+
+		// Loop
+		for (int i=0; i<_Gi.size(); i++){
+
+			// Assign
+			STensorOperation::getEigenDecomposition(Ai0[i],ai1,ai2,ai3,Ai1,Ai2,Ai3);
+			eigenValReal1(0) = ai1; eigenValReal1(1) = ai2; eigenValReal1(2) = ai3;
+
+			// Reassign aligned eigVal
+			ai1_s = eigenValReal1(alignedIndex(0)); ai2_s = eigenValReal1(alignedIndex(1)); ai3_s = eigenValReal1(alignedIndex(2));
+
+			STensorOperation::zero(Ai0s[i]);
+			STensorOperation::zero(dAi0sdEe[i]);
+			for(int p=0; p<3; p++)
+				for(int j=0; j<3; j++){
+					Ai0s[i](p,j) += ai1_s*E1(p,j) + ai2_s*E2(p,j) + ai3_s*E3(p,j);
+					for(int k=0; k<3; k++)
+						for(int l=0; l<3; l++)
+							dAi0sdEe[i](p,j,k,l) += ai1_s*dE1da(p,j,k,l) + ai2_s*dE2da(p,j,k,l) + ai3_s*dE3da(p,j,k,l);
+				}
+		}
+
+	}
+	else{
+		STensorOperation::zero(de1da); STensorOperation::zero(de2da); STensorOperation::zero(de3da); STensorOperation::zero(dE1da); STensorOperation::zero(dE2da); STensorOperation::zero(dE3da);
+		STensorOperation::zero(dEe0sdEe);
+		Ee0s = Ee0;
+		for (int i=0; i<_Gi.size(); i++){
+			Ai0s[i] = Ai0[i];
+			STensorOperation::zero(dAi0sdEe[i]);
+		}
+	}
+}
+
+void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0,
+          	  							const IPNonLinearTVM *q0, IPNonLinearTVM *q1, double& Ke, double& Ge, const double T0, const double T1,
+										const bool stiff, const fullVector<int>& alignedIndex, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2, STensor43* rotationStiffness) const{
+
+	// Caution!! -> For _rotationCorrectionScheme == 0 and 1,  Ee0 is already rotated. _R and its derivatives are in the IP
 
     //
     STensorOperation::zero(Bd_stiffnessTerm);
@@ -2850,6 +3375,50 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
     if(Bd_stiffnessTerm2!= NULL){
         STensorOperation::zero(*Bd_stiffnessTerm2);
     }
+
+    // NEW EIGEN
+    static STensor3 devEe0, devEe0s; double trEe0;
+    STensorOperation::zero(devEe0s);
+    STensorOperation::decomposeDevTr(q0->_Ee,devEe0,trEe0);
+
+    static STensor43 dDevEe0sdEe;
+    STensorOperation::zero(dDevEe0sdEe);
+    std::vector<STensor43> rotationDer1, rotationDer2, dAi0sdEe;
+    rotationDer1.clear(); rotationDer2.clear(); dAi0sdEe.clear();
+    for (int i=0; i<_Gi.size(); i++){
+      STensor43 el43(0.);
+      dAi0sdEe.push_back(el43);
+      rotationDer1.push_back(el43);
+      rotationDer2.push_back(el43);
+    }
+
+    if (_rotationCorrectionScheme == 0 && _rotationCorrectionScheme == 1){
+    	if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+    		for (int i=0; i<_Gi.size(); i++){
+    			for(int k=0; k<3; k++)
+    				for(int l=0; l<3; l++){
+    					q1->_A_rot[i](k,l) = 0.;
+    					for(int p=0; p<3; p++)
+    						for(int q=0; q<3; q++)
+    							q1->_A_rot[i](k,l) += q1->_R(k,p)*q0->_A[i](p,q)*q1->_R(l,q);
+    				}
+    		}
+    	}
+    }
+    else if (_rotationCorrectionScheme == 2){
+        // devEe0.print("before");
+    	// mlawNonLinearTVM::getEe0s2(Ce,Ee,devEe0,devEe0s,dDevEe0sdEe);
+    	q1->_A_rot = q0->_A;
+    	// mlawNonLinearTVM::getAi0s2(Ce,Ee,q0->_A,q1->_A_rot,dAi0sdEe);
+    	mlawNonLinearTVM::get_Ee0s_Ai0s_ders(Ce,Ee,devEe0,q0->_A,alignedIndex,devEe0s,dDevEe0sdEe,q1->_A_rot,dAi0sdEe);
+        // devEe0s.print("after");
+        // Msg::Error("alignedIndex = %d, %d, %d",alignedIndex(0),alignedIndex(1),alignedIndex(2));
+    }
+
+    if(rotationStiffness!= NULL){
+        STensorOperation::zero(*rotationStiffness);
+    }
+    // NEW EIGEN
     
     // Set Temperature to calculate temperature updated properties
     double T_set = setTemp(T0,T1,1);  // 1->T1, 2->T_mid, 3->T_midshift
@@ -2868,6 +3437,10 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
     DE -= Ee0;
     STensorOperation::decomposeDevTr(DE,devDE,trDE);
     STensorOperation::decomposeDevTr(Ee,devEe,trEe);
+    if (_rotationCorrectionScheme == 2){
+    	devDE = devEe;
+    	devDE -= devEe0s;
+    }
 
     // Initialise effective trEe - include thermal expansion
     double eff_trEe(0.), eff_trDE(0.);
@@ -2885,7 +3458,7 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
     
     // Initialise Moduli
     Ke = KT; Ge = GT;
-    
+
     if(_useExtraBranch){
         
         double A(0.), B(0.), dA_dTrEe(0.), psiInfCorrector(0.);
@@ -2992,7 +3565,8 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
                 // Single Convolution
                 for (int k=0; k<3; k++)
                     for (int l=0; l<3; l++){
-                        q1->_A[i](k,l) = exp_rec_g*q0->_A[i](k,l) + exp_mid_g*devDE(k,l);
+                    	// q1->_A[i](k,l) = exp_rec_g*q0->_A[i](k,l) + exp_mid_g*devDE(k,l);
+                        q1->_A[i](k,l) = exp_rec_g*q1->_A_rot[i](k,l) + exp_mid_g*devDE(k,l); // NEW EIGEN
                     }
             
                 q1->_B[i] = exp_rec_k*q0->_B[i] + exp_mid_k*eff_trDE ; //*trDE; NEW
@@ -3002,6 +3576,39 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
             
                 // Add to volumetric stress
                 p += _Ki[i]*q1->_B[i];
+
+                // NEW EIGEN
+                // Add rotation derivatives
+                /*static STensor43 dAi0sdEe;
+                if (_rotationCorrectionScheme == 2){
+                	mlawNonLinearTVM::getdEe0dEe(Ce,Ee,q0->_A[i],dAi0sdEe);
+                }*/
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++){
+                    	if (_rotationCorrectionScheme == 2){
+                    		rotationDer1[i](k,l,p,q) += dAi0sdEe[i](k,l,p,q);
+                    		rotationDer2[i](k,l,p,q) += (-dDevEe0sdEe(k,l,p,q));
+                    		// (*rotationStiffness)(k,l,p,q) +=  2*_Gi[i]*( exp_rec_g*dAi0sdEe(k,l,p,q) - exp_mid_g*dDevEe0sdEe(k,l,p,q) );
+                    	}
+                        for (int r=0; r<3; r++)
+                          for (int s=0; s<3; s++){
+                            if (_rotationCorrectionScheme == 1){
+                            	rotationDer1[i](k,l,p,q) +=  ( q1->_dRdEe(k,r,p,q)*q0->_A[i](r,s)*q1->_R(l,s) + q1->_R(k,r)*q0->_A[i](r,s)*q1->_dRtdEe(s,l,p,q) );
+								rotationDer2[i](k,l,p,q) +=  ( - q1->_dRdEe(k,r,p,q)*devEe0(r,s)*q1->_R(l,s) - q1->_R(k,r)*devEe0(r,s)*q1->_dRtdEe(s,l,p,q) ) ;
+                            	/*(*rotationStiffness)(k,l,p,q) +=  2*_Gi[i]*( exp_rec_g*( q1->_dRdEe(k,r,p,q)*q0->_A[i](r,s)*q1->_R(l,s) + q1->_R(k,r)*q0->_A[i](r,s)*q1->_dRtdEe(s,l,p,q) )
+                            						+  exp_mid_g*( - q1->_dRdEe(k,r,p,q)*devEe0(r,s)*q1->_R(l,s) - q1->_R(k,r)*devEe0(r,s)*q1->_dRtdEe(s,l,p,q) ) );*/
+                            }
+                          }
+                      }
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++)
+                    	(*rotationStiffness)(k,l,p,q) +=  2*_Gi[i]*( exp_rec_g*rotationDer1[i](k,l,p,q) + exp_mid_g*rotationDer2[i](k,l,p,q) );
+                // NEW EIGEN
+
             }
             else{ // all extraBranches
                 
@@ -3041,8 +3648,10 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
                     
                 // Single Convolution - get branchElasticStrain
                 for (int k=0; k<3; k++)
-                    for (int l=0; l<3; l++)
-                        q1->_A[i](k,l) = exp_rec_g*q0->_A[i](k,l) + exp_mid_g*devDE(k,l);
+                    for (int l=0; l<3; l++){
+                    	// q1->_A[i](k,l) = exp_rec_g*q0->_A[i](k,l) + exp_mid_g*devDE(k,l);
+                        q1->_A[i](k,l) = exp_rec_g*q1->_A_rot[i](k,l) + exp_mid_g*devDE(k,l); // NEW EIGEN
+                    }
             
                 q1->_B[i] = exp_rec_k*q0->_B[i] + exp_mid_k*eff_trDE; // trDE; // NEW
                     
@@ -3093,6 +3702,57 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
             
                 // Add to volumetric stress
                 p += ( _Ki[i]*Av*q1->_B[i] );
+
+                // NEW EIGEN
+                // Add rotation derivatives
+                /*static STensor43 dAi0sdEe;
+                if (_rotationCorrectionScheme == 2){
+                	mlawNonLinearTVM::getdEe0dEe(Ce,Ee,q0->_A[i],dAi0sdEe);
+                }*/
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    for (int p=0; p<3; p++)
+                      for (int q=0; q<3; q++){
+                    	if (_rotationCorrectionScheme == 2){
+                    		rotationDer1[i](k,l,p,q) += dAi0sdEe[i](k,l,p,q);
+                    		rotationDer2[i](k,l,p,q) += (-dDevEe0sdEe(k,l,p,q));
+                    		// (*rotationStiffness)(k,l,p,q) +=  2*_Gi[i]*Bd*( exp_rec_g*dAi0sdEe(k,l,p,q) - exp_mid_g*dDevEe0sdEe(k,l,p,q) );
+                    	}
+                        for (int r=0; r<3; r++)
+                          for (int s=0; s<3; s++){
+                        	if (_rotationCorrectionScheme == 1){
+                            	rotationDer1[i](k,l,p,q) +=  ( q1->_dRdEe(k,r,p,q)*q0->_A[i](r,s)*q1->_R(l,s) + q1->_R(k,r)*q0->_A[i](r,s)*q1->_dRtdEe(s,l,p,q) );
+								rotationDer2[i](k,l,p,q) +=  ( - q1->_dRdEe(k,r,p,q)*devEe0(r,s)*q1->_R(l,s) - q1->_R(k,r)*devEe0(r,s)*q1->_dRtdEe(s,l,p,q) ) ;
+                        		/*(*rotationStiffness)(k,l,p,q) += 2.*_Gi[i]*Bd*( exp_rec_g*( q1->_dRdEe(k,r,p,q)*q0->_A[i](r,s)*q1->_R(l,s) + q1->_R(k,r)*q0->_A[i](r,s)*q1->_dRtdEe(s,l,p,q) )
+                            							+  exp_mid_g*( - q1->_dRdEe(k,r,p,q)*devEe0(r,s)*q1->_R(l,s) - q1->_R(k,r)*devEe0(r,s)*q1->_dRtdEe(s,l,p,q) ) );*/
+                        	}
+
+                        	if (_rotationCorrectionScheme == 2){
+                        		// Ignore this term - ADDED on 20/06
+                        		// (*rotationStiffness)(k,l,p,q) += 2.*_Gi[i]*q1->_A[i](k,l)*dB_dDevEe(r,s) * ( exp_rec_g*dAi0sdEe[i](r,s,p,q) - exp_mid_g*dDevEe0sdEe(r,s,p,q) );
+                        	}
+                            for (int m=0; m<3; m++)
+                              for (int n=0; n<3; n++){
+                            	if (_rotationCorrectionScheme == 1){
+                            		// Ignore this term - ADDED on 20/06
+                            		/*(*rotationStiffness)(k,l,p,q) += 2.*_Gi[i]*q1->_A[i](k,l)*dB_dDevEe(r,s) * (exp_rec_g*( q1->_dRdEe(r,m,p,q)*q0->_A[i](m,n)*q1->_R(s,n) + q1->_R(r,m)*q0->_A[i](m,n)*q1->_dRtdEe(n,s,p,q) )
+        								+  exp_mid_g*( - q1->_dRdEe(r,m,p,q)*devEe0(m,n)*q1->_R(s,n) - q1->_R(r,m)*devEe0(m,n)*q1->_dRtdEe(n,s,p,q) ));*/
+                            	}
+                              }
+                          }
+                      }
+
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++)
+                    for (int r=0; r<3; r++)
+                      for (int s=0; s<3; s++){
+                      	(*rotationStiffness)(k,l,r,s) +=  2*_Gi[i]*Bd*( exp_rec_g*rotationDer1[i](k,l,r,s) + exp_mid_g*rotationDer2[i](k,l,r,s) );
+                    	for (int p=0; p<3; p++)
+                          for (int q=0; q<3; q++){
+                        	(*rotationStiffness)(k,l,r,s) += 2.*_Gi[i]*q1->_A[i](k,l)*dB_dDevEe(p,q)*( exp_rec_g*rotationDer1[i](p,q,r,s) + exp_mid_g*rotationDer2[i](p,q,r,s) );
+                          }
+                      }
+                // NEW EIGEN
              }
              
             } // all extrabranches
@@ -3158,6 +3818,15 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
                                     // _Idev is pre-multiplied !!
                                     DA_DdevE[i](k,l,r,s) =  exp_mid_g*_Idev(k,l,r,s);  
                                     DDA_DTDdevE[i](k,l,r,s) =  Dexp_mid_g_DT*_Idev(k,l,r,s);  
+
+                                    // NEW EIGEN
+                                    if ( _useRotationCorrection == true){
+                                    	if(_rotationCorrectionScheme == 1 && _rotationCorrectionScheme == 2){
+                                    		DA_DdevE[i](k,l,r,s) += ( exp_rec_g*rotationDer1[i](k,l,r,s) + exp_mid_g*rotationDer2[i](k,l,r,s) );
+                                    		DDA_DTDdevE[i](k,l,r,s) += ( Dexp_rec_g_DT*rotationDer1[i](k,l,r,s) + Dexp_mid_g_DT*rotationDer2[i](k,l,r,s) );
+                                    	}
+                                    }
+                                    // NEW EIGEN
                                 }
                         }
                 }
@@ -3234,6 +3903,18 @@ void mlawNonLinearTVM::ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, co
                                     for (int p=0; p<3; p++)
                                         for (int q=0; q<3; q++){
                                             DDA_DTDdevE[i](k,l,r,s) += exp_mid_g * q1->_dBd_dDevEe_TVE_vector[i](p,q)*dDevEei_DT(p,q)*_I4(k,l,r,s);
+
+
+                                            // NEW EIGEN
+                                            if ( _useRotationCorrection == true){
+                                            	if(_rotationCorrectionScheme == 1 && _rotationCorrectionScheme == 2){
+                                            		DA_DdevE[i](k,l,r,s) +=  ( q1->_A[i](k,l)*q1->_dBd_dDevEe_TVE_vector[i](p,q) + q1->_Bd_TVE_vector[i] * _I4(k,l,p,q) ) *
+                                                									( exp_rec_g*rotationDer1[i](p,q,r,s) + exp_mid_g*rotationDer2[i](p,q,r,s) );
+                                            			DDA_DTDdevE[i](k,l,r,s) += ( q1->_A[i](k,l)*q1->_dBd_dDevEe_TVE_vector[i](p,q) + q1->_Bd_TVE_vector[i] * _I4(k,l,p,q) ) *
+                                                    								( Dexp_rec_g_DT*rotationDer1[i](p,q,r,s) + Dexp_mid_g_DT*rotationDer2[i](p,q,r,s) );
+                                            	}
+                                            }
+                                            // NEW EIGEN
                                         }
                                 }
                         }
@@ -3342,6 +4023,91 @@ double mlawNonLinearTVM::soundSpeed() const {   // Correct this for current temp
     return sqrt((_K+4.*_G/3.)/_rho);
 }
 
+void mlawNonLinearTVM::getAi0s(const STensor3& Ce, const STensor3& Ee, const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const{
+
+	// Ee0 becomes Ee0_star expressed in the same configuration as Ee
+
+	double e01,e02,e03, e1,e2,e3, c1,c2,c3; // eigenvalues
+	static STensor3 E01,E02,E03,E1,E2,E3,C1,C2,C3; // bases
+	static STensor3 dc1da,dc2da,dc3da; // eigenvalue derivatives
+	static STensor43 dC1da,dC2da,dC3da; // bases derivatives
+
+	STensorOperation::getEigenDecomposition(Ee,e1,e2,e3,E1,E2,E3);
+	STensorOperation::getEigenDecomposition(Ce,c1,c2,c3,C1,C2,C3,dc1da,dc2da,dc3da,dC1da,dC2da,dC3da);
+	if(c1==0.) {STensorOperation::zero(dC1da);}
+	if(c2==0.) {STensorOperation::zero(dC2da);}
+	if(c3==0.) {STensorOperation::zero(dC3da);}
+
+
+	// #####
+	// Align the eigenVals of Ee0 with Ee
+	static fullMatrix<double> m1(3, 3), m2(3, 3);
+	static fullVector<double> eigenValReal1(3), eigenValReal2(3), AlignedEigenValReal1(3);
+	static fullVector<double> eigenValImag1(3), eigenValImag2(3);
+	static fullMatrix<double> leftEigenVect1(3,3), leftEigenVect2(3,3);
+	static fullMatrix<double> rightEigenVect1(3,3), rightEigenVect2(3,3), AlignedRightEigenVect1(3,3);
+	m1.setAll(0.); m2.setAll(0.);
+	eigenValReal1.setAll(0.); eigenValReal2.setAll(0.); AlignedEigenValReal1.setAll(0.);
+	eigenValImag1.setAll(0.); eigenValImag2.setAll(0.);
+	leftEigenVect1.setAll(0.); leftEigenVect2.setAll(0.);
+	rightEigenVect1.setAll(0.); rightEigenVect2.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+
+	// Get eigen values and vectors
+	Ce.getMat(m2); m2.eig(eigenValReal2,eigenValImag2,leftEigenVect2,rightEigenVect2,false);
+
+	// conversion tensor to dEe0sdEe
+    static STensor3 Ee2, exp_Ee2;
+    static STensor43 dCedEe;
+	STensorOperation::zero(dCedEe);
+    Ee2 = Ee;
+    Ee2 *= 2;
+    STensorOperation::expSTensor3(Ee2,_order,exp_Ee2,&dCedEe);
+
+    // Loop
+    for (int i=0; i<_Gi.size(); i++){
+
+    	// Get eigen values and vectors
+    	m1.setAll(0.); eigenValReal1.setAll(0.); eigenValImag1.setAll(0.); leftEigenVect1.setAll(0.); rightEigenVect1.setAll(0.); AlignedRightEigenVect1.setAll(0.);
+    	STensorOperation::getEigenDecomposition(Ai0[i],e01,e02,e03,E01,E02,E03);
+    	Ai0[i].getMat(m1);
+    	m1.eig(eigenValReal1,eigenValImag1,leftEigenVect1,rightEigenVect1,false);
+
+
+    	// eigenvalues
+    	e01 = eigenValReal1(0);
+    	e02 = eigenValReal1(1);
+    	e03 = eigenValReal1(2);
+
+    	// Make sure rightEigenVect1 is aligned with rightEigenVect2
+    	STensorOperation::alignEigenDecomposition_NormBased(Ai0[i],Ce,eigenValReal1,eigenValReal2,rightEigenVect1,rightEigenVect2, e01, e02, e03, AlignedRightEigenVect1);
+        rightEigenVect1 = AlignedRightEigenVect1;
+
+    	static STensor43 dAi0sdCe; // , dCedCe;
+    	STensorOperation::zero(dAi0sdCe);
+    	// STensorOperation::zero(dCedCe);
+    	STensorOperation::zero(Ai0s[i]);
+    	for(int p=0; p<3; p++)
+    		for(int j=0; j<3; j++){
+    			Ai0s[i](p,j) += e01*C1(p,j) + e02*C2(p,j) + e03*C3(p,j);
+    			for(int k=0; k<3; k++)
+    				for(int l=0; l<3; l++){
+    					dAi0sdCe(p,j,k,l) += e01*dC1da(p,j,k,l) + e02*dC2da(p,j,k,l) + e03*dC3da(p,j,k,l);
+    					// dCedCe(p,j,k,l) += dc1da(p,j)*C1(k,l) + dc2da(p,j)*C2(k,l) + dc3da(p,j)*C3(k,l) + c1*dC1da(p,j,k,l) + c2*dC2da(p,j,k,l) + c3*dC3da(p,j,k,l);  // Should be equal to _I4
+    				}
+    		}
+
+    	// debug
+    	STensorOperation::getEigenDecomposition(Ai0s[i],e01,e02,e03,E01,E02,E03);
+
+    	/*
+    	static STensor43 check;
+    	check = dCedCe;
+    	check -= _I4;*/
+
+    	STensorOperation::multSTensor43(dAi0sdCe,dCedEe,dAi0sdEe[i]);
+    }
+}
+
 // Older definition of non-linear mechSrc
 /*
 void mlawNonLinearTVM::getMechSource_nonLinearTVE_term(const IPNonLinearTVM *q0, IPNonLinearTVM *q1, const double& T0, const double& T, 
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVM.h b/NonLinearSolver/materialLaw/mlawNonLinearTVM.h
index 245bf095e0800c64167a3399bab7340f385fc247..7d73767c0408284fe6bb1d36490c25e83f2d17e3 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVM.h
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVM.h
@@ -62,6 +62,8 @@ class mlawNonLinearTVM : public mlawPowerYieldHyper{
     elasticPotential* _elasticPotential; 
     bool _useExtraBranch;
     bool _useExtraBranch_TVE;
+    bool _useRotationCorrection;
+    int _rotationCorrectionScheme;
     int _ExtraBranch_TVE_option;
     scalarFunction* _temFunc_elasticCorrection_Bulk;
     scalarFunction* _temFunc_elasticCorrection_Shear;
@@ -117,15 +119,29 @@ class mlawNonLinearTVM : public mlawPowerYieldHyper{
 
     void corKirInfinity(const IPNonLinearTVM *q1, const STensor3& devEe, const double& trEe, const double T, STensor3& CorKirDevInf, double& CorKirTrInf) const;
     
+    void rotationTensor_N_to_Nplus1(const STensor3& Ee00, const STensor3& Fe0, const STensor3& Fe, const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0,
+    												STensor3& R, STensor43& dRdEe, STensor43& dRtdEe) const;
+
+    void getdRedEe(const STensor3& Fe, const STensor3& Ce, const STensor43& dEedFe, const STensor43& dEedCe, STensor3& Ue, STensor3& Re, STensor43& dRedEe) const;
+    void getdUedCe(const STensor3& Ce, const STensor3& Ue, STensor43& dUedCe) const;
+    void getEe0s(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, STensor3& Ee0s, STensor43& dEe0sdEe) const;
+    void getAi0s(const STensor3& Ce, const STensor3& Ee, const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const;
+
+    void getEe0s2(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, int& index1, int& index2, int& index3, STensor3& Ee0s, STensor43& dEe0sdEe) const;
+    void getAi0s2(const STensor3& Ce, const STensor3& Ee, const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const;
+    void getAi0s2(const STensor3& Ce, const STensor3& Ee, const int& index1, const int& index2, const int& index3, const std::vector<STensor3>& Ai0, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const;
+    void getdEe0dEe(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, STensor43& dEe0sdEe) const;
+    void get_Ee0s_Ai0s_ders(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0, const std::vector<STensor3>& Ai0, const fullVector<int>& alignedIndex,
+    								STensor3& Ee0s, STensor43& dEe0sdEe, std::vector<STensor3>& Ai0s, std::vector<STensor43>& dAi0sdEe) const;
+
     void ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
-          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
-          double& Ke, double& Ge, double& DKDTsum, double& DGDTsum,
-          const double T0, const double T1, const bool stiff, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2 = NULL) const;
-          
-    void ThermoViscoElasticPredictor_forTVP(const STensor3& Ee, const STensor3& Ee0,
           const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
           double& Ke, double& Ge,
           const double T0, const double T1, const bool stiff, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2 = NULL) const;
+          
+    void ThermoViscoElasticPredictor_forTVP(const STensor3& Ce, const STensor3& Ee, const STensor3& Ee0,
+          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,  double& Ke, double& Ge, const double T0, const double T1,
+		  const bool stiff,  const fullVector<int>& alignedIndex, STensor43& Bd_stiffnessTerm, STensor43* Bd_stiffnessTerm2 = NULL, STensor43* rotationStiffness = NULL) const;
               
     void isotropicHookTensor(const double K, const double G, STensor43& L) const;
                                   
@@ -214,6 +230,8 @@ class mlawNonLinearTVM : public mlawPowerYieldHyper{
     virtual void useExtraBranchBool(const bool useExtraBranch){_useExtraBranch = useExtraBranch;};
     virtual void useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option){
                                                 _useExtraBranch_TVE = useExtraBranch_TVE; _ExtraBranch_TVE_option = ExtraBranch_TVE_option;};
+    virtual void useRotationCorrectionBool(const bool useRotationCorrection, const int rotationCorrectionScheme){_useRotationCorrection = useRotationCorrection;
+    																						_rotationCorrectionScheme = rotationCorrectionScheme;};
     void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
      if (_temFunc_K != NULL) delete _temFunc_K;
       _temFunc_K = Tfunc.clone();
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
index 8c38474fb3228fbdaa1fe44c6cb93371ab87fa3e..0b0191953c5d0a561c9bdcbaf53255f873826972 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
@@ -471,7 +471,7 @@ void mlawNonLinearTVP::getMechSourceTVP(const STensor3& F0, const STensor3& F,
     const double& gamma0 = q0->_epspbarre;
     const double& gamma1 = q1->_epspbarre;
     const STensor3& Fp1 = q1->_Fp;
-    const STensor3& Me = q1->_ModMandel;
+    const STensor3& Me = q1->_kirchhoff; // q1->_ModMandel; // debug
     const STensor3& X = q1->_backsig;
     const STensor3& dXdT = q1->_DbackSigDT;
     const STensor43& dXdF  =  q1->_DbackSigDF;
@@ -920,7 +920,7 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;
   static STensor43 Bd_stiffnessTerm;
   // ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T);
-  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm);
+  mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
   mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T);
 
   // additional branch - update predictor
@@ -1257,10 +1257,10 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
     Ee *= 0.5;
 
     // Correct A, B
-    // ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); //,false);
-    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm); //,false);
+    // ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); //,false);  - DEPRECATED
+    mlawNonLinearTVM::ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm); //,false);
     mlawNonLinearTVM::getTVEdCorKirDT(q0,q1,T0,T); // update dCorKirdT - don't do this probably
-    // DKDTsum and DGDTsum = sum of bulk/shear moduli derivatives wrt T
+    // DKDTsum and DGDTsum = sum of bulk/shear moduli derivatives wrt T - DEPRECATED
 
     // Correct Extrabranch - update stress
     if (_useExtraBranch){
@@ -1417,7 +1417,7 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   }
   
   // 2) Viscoelastic Contribution to mechSrc
-  // mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,_I4,&Wm_TVE); // mechSourceTVE
+  // mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,_I4,&Wm_TVE); // mechSourceTVE
   double& dWmdT_TVE = q1->getRefTodMechSrcTVEdT();
   STensor3& dWmdF_TVE = q1->getRefTodMechSrcTVEdF();
   static STensor3 dWmdE_TVE;
@@ -2904,11 +2904,11 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
 
   // update A, B
   // double Ge, Ke;
-  double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
-  double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.; 
+  double Ke(0.), Ge(0.);
+  double DKDTsum, DGDTsum = 0.; // Deprecated
   static STensor43 Bd_stiffnessTerm;
   // ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T);
-  ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,stiff,Bd_stiffnessTerm);
+  ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,stiff,Bd_stiffnessTerm);
 
   static STensor3 devKpr; // dev corotational kirchoff stress predictor
   static double ppr; // pressure predictor
@@ -3088,7 +3088,7 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
 
       //
       // ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T,false);
-      ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,DKDTsum,DGDTsum,T0,T,false,Bd_stiffnessTerm);
+      ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,T0,T,false,Bd_stiffnessTerm);
     }
     else{
       q1->getRefToDissipationActive() = false;
diff --git a/NonLinearSolver/materialLaw/mullinsEffect.cpp b/NonLinearSolver/materialLaw/mullinsEffect.cpp
index 50ec2a4da39a0777d63dcd795314f19fe9937c33..8cc2aeaa3e65c83f8b31dc7f69362a104a662f38 100644
--- a/NonLinearSolver/materialLaw/mullinsEffect.cpp
+++ b/NonLinearSolver/materialLaw/mullinsEffect.cpp
@@ -100,140 +100,87 @@ void negativeExponentialScaler::mullinsEffectScaling(double _psi0, double _psi,
     
   // at unloading intitiation-> eta = 1.; unloading end-> eta = eta_min; reloading -> eta = eta_min;  
     
-  double eta0 = ipvprev.getEta();
-  double _psi_max0 = ipvprev.getpsiMax();
-  double psi_cap = _psi;
-  double eta = 1., DetaDpsi_cap = 0., DDetaDpsipsi = 0., DetaDT = 0., DDetaDTT = 0.;
-  double DpsiNew_DpsiMax(0.), DDpsiNew_DpsiMaxDpsi(0.), DDpsiNew_DpsiMaxDT(0.);
-  
-  double _psi_max = std::max(_psi,_psi_max0);
-  // Msg::Error(" Inside mullinsEffectScaling, _psi = %e, _psi_max = %e !!", _psi, _psi_max);
-  
-  double Dpsi_maxDpsi_cap = 1.; // Dpsi_maxDpsi_cap = 1. if _psi_max = _psi
-  double Term = sqrt(_m*(_psi_max-eta*psi_cap));  // Term = 0. if _psi_max = _psi
-  
-  if (Term!=0){
-    
-    int ite = 0;
-    int maxite = 100; 
-    double _tol = 1e-8;
-    double DfDeta(0.), Deta(0.);
-    double f = eta + _r*(1-exp(-Term)) - 1.;
-    
-    while (fabs(f) >_tol or ite <1){
-      
-      DfDeta = 1 + _r*(-_m*psi_cap*exp(-Term)/(2*Term));
-      Deta = - f/DfDeta;
-      
-      if (eta + Deta > 1.){
-            eta = 0.99;                // NR
-        }
-        else
-          eta += Deta;
-          
-      // eta += Deta;
-      // Msg::Error(" Inside iterator, ite = %d, f = %e, DfDeta = %e, Deta = %e, eta = %e !!", ite, f, DfDeta, Deta, eta);
-  
-      Term = sqrt(_m*(_psi_max-eta*psi_cap));  
-      f = eta + _r*(1-exp(-Term)) - 1.;
-      
-      ite++;
-      if (fabs(f) <_tol) break;
-      
-      if(ite > maxite){
-          // Msg::Error("No convergence for eta in mullinsEffectScaling: ite= %d, f = %e!!",ite,f);
-          eta = sqrt(-1.);
-          return;
-      }
-    }
-    
-    Dpsi_maxDpsi_cap = 0.;
-    
-    DetaDpsi_cap = (-_r*_m*exp(-Term)/(2*Term)) * (Dpsi_maxDpsi_cap - eta) / (1 - _r*_m*exp(-Term)/(2*Term)*psi_cap);
-  }
-  else{
-    eta = 1.; 
-    DetaDpsi_cap = 0.;
-  }
+	  double r = _r;
+	  double m = _m;
 
-  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT,DpsiNew_DpsiMax, DDpsiNew_DpsiMaxDpsi, DDpsiNew_DpsiMaxDT);
-  ipv.setPsiMax(_psi_max);
+	  double eta0 = ipvprev.getEta();
+	  double _psi_max0 = ipvprev.getpsiMax();
+	  double psi_cap = _psi;
+	  double eta = 1., DetaDpsi_cap = 0., DDetaDpsipsi = 0., DetaDT = 0., DDetaDTT = 0.;
+	  double DpsiNew_DpsiMax(0.), DDpsiNew_DpsiMaxDpsi(0.), DDpsiNew_DpsiMaxDT(0.);
+	  double Dpsi_max_Dpsi_cap(0.), Dpsi_max_DT(0.);
+
+	  double _psi_max = std::max(_psi,_psi_max0);
+	  // Msg::Error(" Inside mullinsEffectScaling, _psi = %e, _psi_max = %e !!", _psi, _psi_max);
+
+	  if (_psi_max>0.){
+
+		// eta
+		double temp = m*(_psi_max-psi_cap);
+		eta = (1-r*sqrt(tanh(temp)));
+
+	    // derivatives
+	    if (psi_cap >= _psi_max){
+	        Dpsi_max_Dpsi_cap = 1.;
+	    }
+
+	    DetaDpsi_cap = m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) * (1- Dpsi_max_Dpsi_cap);
+
+	    double DetaDpsi_max = -m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp));
+	    DpsiNew_DpsiMax = r*( sqrt(tanh(temp)) - sqrt(tanh(m*_psi_max)) ); // definition
+	    DDpsiNew_DpsiMaxDpsi = DetaDpsi_max + r*m/2.*(pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) - pow( 1/cosh(m*_psi_max) ,2)/sqrt(tanh(m*_psi_max)) ) * Dpsi_max_Dpsi_cap;
+	  }
+
+	  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT,DpsiNew_DpsiMax, DDpsiNew_DpsiMaxDpsi, DDpsiNew_DpsiMaxDT);
+	  ipv.setPsiMax(_psi_max);
+	  ipv.setDpsiMax_Dpsi(Dpsi_max_Dpsi_cap);
 }
 
 void negativeExponentialScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T, const double& dPsi_capDT) const{
    
   double r = _r*_temFunc_r->getVal(T);
   double m = _m*_temFunc_m->getVal(T);
+  double drdT = _r*_temFunc_r->getDiff(T);
+  double dmdT = _m*_temFunc_m->getDiff(T);
   
   double eta0 = ipvprev.getEta();
   double _psi_max0 = ipvprev.getpsiMax();
   double psi_cap = _psi;
   double eta = 1., DetaDpsi_cap = 0., DDetaDpsipsi = 0., DetaDT = 0., DDetaDTT = 0.;
   double DpsiNew_DpsiMax(0.), DDpsiNew_DpsiMaxDpsi(0.), DDpsiNew_DpsiMaxDT(0.);
+  double Dpsi_max_Dpsi_cap(0.), Dpsi_max_DT(0.);
   
   double _psi_max = std::max(_psi,_psi_max0);
   // Msg::Error(" Inside mullinsEffectScaling, _psi = %e, _psi_max = %e !!", _psi, _psi_max);
   
-  double Dpsi_maxDpsi_cap = 1.; // Dpsi_maxDpsi_cap = 1. if _psi_max = _psi
-  double Term = sqrt(m*(_psi_max-eta*psi_cap));  // Term = 0. if _psi_max = _psi
-  
-  if (Term!=0){
-    
-    int ite = 0;
-    int maxite = 100; 
-    double _tol = 1e-8;
-    double DfDeta(0.), Deta(0.);
-    double f = eta + r*(1-exp(-Term)) - 1.;
-    
-    while (fabs(f) >_tol or ite <1){
-      
-      DfDeta = 1 + r*(-m*psi_cap*exp(-Term)/(2*Term));
-      Deta = - f/DfDeta;
-      
-      if (eta + Deta > 1.){
-            eta = 0.99;                // NR
-        }
-        else
-          eta += Deta;
-          
-      // eta += Deta;
-      // Msg::Error(" Inside iterator, ite = %d, f = %e, DfDeta = %e, Deta = %e, eta = %e !!", ite, f, DfDeta, Deta, eta);
-  
-      Term = sqrt(m*(_psi_max-eta*psi_cap));
-      f = eta + r*(1-exp(-Term)) - 1.;
-      
-      ite++;
-      if (fabs(f) <_tol) break;
-      
-      if(ite > maxite){
-          // Msg::Error("No convergence for eta in mullinsEffectScaling: ite= %d, f = %e!!",ite,f);
-          eta = sqrt(-1.);
-          return;
-      }
+  if (_psi_max>0.){
+
+	// eta
+	double temp = m*(_psi_max-psi_cap);
+	eta = (1-r*sqrt(tanh(temp)));
+
+    // derivatives
+    if (psi_cap >= _psi_max){
+        Dpsi_max_Dpsi_cap = 1.;
+        Dpsi_max_DT = dPsi_capDT;
     }
     
-    Dpsi_maxDpsi_cap = 0.;
-    
-    DetaDpsi_cap = (-r*m*exp(-Term)/(2*Term)) * (Dpsi_maxDpsi_cap - eta) / (1 - r*m*exp(-Term)/(2*Term)*psi_cap);
-  }
-  else{
-    eta = 1.; 
-    DetaDpsi_cap = 0.;
+    DetaDpsi_cap = m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) * (1- Dpsi_max_Dpsi_cap);
+    DetaDT = -drdT*(sqrt(tanh(temp))) - dmdT*r/2.*(_psi_max-psi_cap)*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp))
+    		+ m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) * (1- Dpsi_max_Dpsi_cap)*dPsi_capDT
+			- m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) * Dpsi_max_DT;
+    
+    double DetaDpsi_max = -m*r/2.*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp));
+    DpsiNew_DpsiMax = r*( sqrt(tanh(temp)) - sqrt(tanh(m*_psi_max)) ); // definition
+    DDpsiNew_DpsiMaxDpsi = DetaDpsi_max + r*m/2.*(pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) - pow( 1/cosh(m*_psi_max) ,2)/sqrt(tanh(m*_psi_max)) ) * Dpsi_max_Dpsi_cap;
+    DDpsiNew_DpsiMaxDT = DDpsiNew_DpsiMaxDpsi*dPsi_capDT - drdT*( sqrt(tanh(temp)) - sqrt(tanh(m*_psi_max)) )
+    						+ r*dmdT/2.*( (_psi_max-psi_cap)*pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) - (_psi_max)*pow( 1/cosh(m*_psi_max) ,2)/sqrt(tanh(m*_psi_max)) )
+							+ r*m/2.*(pow( 1/cosh(temp) ,2)/sqrt(tanh(temp)) - pow( 1/cosh(m*_psi_max) ,2)/sqrt(tanh(m*_psi_max)) ) * Dpsi_max_DT;
   }
-  
-  /*
-  if (_psi<_psi_max){  // unloading
-    eta = 1. - _r*( 1. - exp( - sqrt(_m*(_psi_max-_psi)) ) );
-  }
-  else if (_psi<_psi0){  // reinitiate eta after reloading, before unloading
-    eta = 1.;
-  }
-  else{   // reloading
-    eta = 1.;
-  }*/
    
   ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT,DpsiNew_DpsiMax, DDpsiNew_DpsiMaxDpsi, DDpsiNew_DpsiMaxDT);
   ipv.setPsiMax(_psi_max);
+  ipv.setDpsiMax_Dpsi(Dpsi_max_Dpsi_cap);
 }
 
 mullinsEffect *negativeExponentialScaler::clone() const
diff --git a/NonLinearSolver/materialLaw/mullinsEffect.h b/NonLinearSolver/materialLaw/mullinsEffect.h
index 53f3b65578dc3aa1ed9bc8b958057d3ecb833591..c985389b31a4d97414eab0db273afa43763e2ae0 100644
--- a/NonLinearSolver/materialLaw/mullinsEffect.h
+++ b/NonLinearSolver/materialLaw/mullinsEffect.h
@@ -40,7 +40,8 @@ class mullinsEffect {
 
 };
 
-// eta = 1 - r* ( 1 - exp(-sqrt(m*(psi_max-psi))) ) -> Ricker et al, 2021 (modified Zuniga, 2005)
+// eta = 1 - r* ( 1 - exp(-sqrt(m*(psi_max-psi))) ) -> Ricker et al, 2021 (modified Zuniga, 2005) - OLD and deleted
+// eta = (1-r*sqrt(tanh(m*(_psi_max-psi_cap))) (modified Wrublescki Marczak, 2015) - NEW and correct
 class negativeExponentialScaler : public mullinsEffect{
   #ifndef SWIG
   protected:
diff --git a/dG3D/benchmarks/nonLinearTVP_allExtraBranches_cube/cubeTVP.py b/dG3D/benchmarks/nonLinearTVP_allExtraBranches_cube/cubeTVP.py
index f6b4f958964f031502eb52dc8f688ea8392b7a68..8c32626d8a6215703f66134de6960ae739555e5a 100644
--- a/dG3D/benchmarks/nonLinearTVP_allExtraBranches_cube/cubeTVP.py
+++ b/dG3D/benchmarks/nonLinearTVP_allExtraBranches_cube/cubeTVP.py
@@ -87,21 +87,22 @@ hardent = LinearExponentialJ2IsotropicHardening(2, sy0t, ht, 5., 20.)
 # hardent.setTemperatureFunction_hexp(ShiftFactor_tempfunc)
 
 hardenk = PolynomialKinematicHardening(3,3) # 1 -> PP
+hardenk.setCoefficients(0,1.) # 300.)
 hardenk.setCoefficients(1,1.) # 300.)
 hardenk.setCoefficients(2,2.) # 200.)
-hardenk.setCoefficients(3,5.)
+# hardenk.setCoefficients(3,5.)
 
-law1 = NonLinearTVENonLinearTVPDG3DMaterialLaw(lawnum,rho,E,nu,1e-6,Tinitial,Alpha,KThCon,Cp,False,1e-8,1e-8)
+law1 = NonLinearTVENonLinearTVPDG3DMaterialLaw(lawnum,rho,E,nu,1e-6,Tinitial,Alpha,KThCon,Cp,False,1e-8,1e-6)
 
 law1.setCompressionHardening(hardenc)
 law1.setTractionHardening(hardent)
-law1.setKinematicHardening(hardenk)
+# law1.setKinematicHardening(hardenk)
 
 law1.setYieldPowerFactor(3) # 3.5)
 law1.setNonAssociatedFlow(True)
 law1.nonAssociatedFlowRuleFactor(0.64) # 0.5
 
-law1.setStrainOrder(11)
+law1.setStrainOrder(-1)
 law1.setViscoelasticMethod(0)
 law1.setShiftFactorConstantsWLF(C1,C2)
 law1.setReferenceTemperature(Tref)
@@ -130,7 +131,7 @@ a = -0.9/(90.)
 x0 = 273.15-20
 linear_tempfunc = linearScalarFunction(x0,0.9,a)
 # mullins.setTemperatureFunction_r(linear_tempfunc)
-# law1.setMullinsEffect(mullins)
+law1.setMullinsEffect(mullins)
 
 eta = constantViscosityLaw(1,1000.) #(1,3e4)
 law1.setViscosityEffect(eta,0.1)
@@ -159,7 +160,7 @@ pertFactor = 1e-8
 pertLaw1 = dG3DMaterialLawWithTangentByPerturbation(law1,pertFactor)
 ThermoMechanicsEqRatio = 1.e1 # setConstitutiveExtraDofDiffusionEqRatio(ThermoMechanicsEqRatio)
 thermalSource = True
-mecaSource = False
+mecaSource = True
 myfield1 = ThermoMechanicsDG3DDomain(1000,nfield,space1,lawnum,fullDg,ThermoMechanicsEqRatio)
 myfield1.setConstitutiveExtraDofDiffusionAccountSource(thermalSource,mecaSource)
 myfield1.stabilityParameters(beta1)
@@ -191,7 +192,7 @@ mysolver.displacementBC("Face",32,2,0.)		    # face z = 0
 # thermal BC
 mysolver.initialBC("Volume","Position",nfield,3,Tinitial)
 fT = LinearFunctionTime(0,Tinitial,ftime,Tinitial)    # Linear Displacement with time
-mysolver.displacementBC("Volume",nfield,3,fT)
+# mysolver.displacementBC("Volume",nfield,3,fT)
 
 # Field-Output
 mysolver.internalPointBuildView("strain_zz", IPField.STRAIN_ZZ, 1, nstepArch);
diff --git a/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/CMakeLists.txt b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a0177858b739eed0c6a4bfbece73db3029b79186
--- /dev/null
+++ b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/CMakeLists.txt
@@ -0,0 +1,14 @@
+# test file
+
+set(PYFILE cubeTVP.py)
+
+set(FILES2DELETE
+  for*.csv
+  ene*.csv
+  Nod*.csv
+  disp*
+  stress*
+  IPVol*
+)
+
+add_cm3python_test(${PYFILE} "${FILES2DELETE}")
diff --git a/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cube.geo b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cube.geo
new file mode 100644
index 0000000000000000000000000000000000000000..7b69582119311ad0f199829d872fc7eb4f36c967
--- /dev/null
+++ b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cube.geo
@@ -0,0 +1,48 @@
+// Cube.geo
+mm=1.0;	// Units
+n=1;		// Number of layers (in thickness / along z)
+m = 1;		// Number of element + 1 along y
+p = 1; 		// Number of element + 1 along x
+L=1.*mm;	// Cube lenght
+sl1=L/n;
+
+// Face z = 0 (point in anti-clockwise order)
+Point(1)={0,0,0,sl1};
+Point(2)={L,0,0,sl1};
+Point(3)={L,L,0,sl1};
+Point(4)={0,L,0,sl1};
+Line(1)={1,2};
+Line(2)={2,3};
+Line(3)={3,4};
+Line(4)={4,1};
+Line Loop(5) = {3, 4, 1, 2};
+Plane Surface(6) = {5};
+
+// Cube extrusion
+Extrude {0, 0, L} {
+  Surface{6}; Layers{n}; Recombine;
+}
+
+// Physical entities
+	// Volume
+Physical Volume(29) = {1};
+	// Surface
+Physical Surface(30) = {19}; // Left face x = 0
+Physical Surface(31) = {27}; // Right face x = L
+Physical Surface(32) = {6};  // Back face z = 0
+Physical Surface(33) = {28}; // Front face z = L
+Physical Surface(34) = {15}; // Down face y = 0
+Physical Surface(35) = {23}; // Up face y = L
+
+// Mesh
+Transfinite Line {2, 4} = m Using Progression 1;
+Transfinite Line {1, 3} = p Using Progression 1;
+Transfinite Surface {6};
+Recombine Surface{6};
+
+
+// To save cube elongation
+Physical Point(41) = {1}; // Point on left face (0,0,0)
+Physical Point(42) = {4}; // Point on left face (0,L,0)
+Physical Point(43) = {2}; // Point on right face (L,0,0)
+Physical Point(44) = {3}; // Point on right face (L,L,0)
diff --git a/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cubeTVP.py b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cubeTVP.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f1c45498fe691be36a7150760c31290c3b07282
--- /dev/null
+++ b/dG3D/benchmarks/nonLinearTVP_cube_Rotation_biaxialShear/cubeTVP.py
@@ -0,0 +1,290 @@
+#coding-Utf-8-*-
+
+from gmshpy import *
+# from dG3Dpy import*
+from dG3DpyDebug import*
+from math import*
+import csv
+import numpy as np
+import pandas as pd
+import os
+
+# Load the csv data for relaxation spectrum
+with open('relaxationSpectrum_Einf_N27_05_12_23_Tref20.csv', newline='') as csvfile:
+# with open('../TPU_relaxationSpectrum_Et_N64_28_03_24_Trefm30.txt', newline='') as csvfile:
+    reader = csv.reader(csvfile, delimiter=';')
+    relSpec = np.zeros((1,))
+    i = 0
+    for row in reader:
+        if i == 0:
+            relSpec[i] = float(' '.join(row))
+        else:
+            relSpec = np.append(relSpec, float(' '.join(row)))
+        i += 1
+# print(relSpec)
+N = int(0.5*(i-1))
+relSpec[0:N+1] *= 1e-6    # convert to MPa
+
+# material law
+lawnum = 11 # unique number of law
+
+E = relSpec[0] #MPa # 2700
+nu = 0.33 #0.33
+K = E/3./(1.-2.*nu)	# Bulk mudulus
+mu = E/2./(1.+nu)	  # Shear mudulus
+rho = 905e-12 # Bulk mass   905 kg/m3 -> 905e-12 tonne/mm3
+Cp = rho*1900e+6 # 1900 J/kg/K -> 1900e+6 Nmm/tonne/K
+KThCon = 0.14  # 0.14 W/m/K -> 0.14 Nmm/s/mm/K
+Alpha = 0.6e-6 # 1/K
+
+Tinitial = 273.15 + 23 # K
+C1 = 112.94742152
+C2 = 176.44294359
+
+# Temp Settings
+Tref = 273.15+20.
+
+# Default tempfuncs
+Alpha_G = 0.2e-6
+Alpha_R = 1.e-6
+KThCon_G = 0.10
+KThCon_R = 1.5*0.12
+k_gibson = 3.36435338e-02
+m_gibson = 0.0
+Tg = Tref
+Alpha_tempfunc = GlassTransitionScalarFunction(1, Alpha_R/Alpha_G, Tg, k_gibson, m_gibson, 0)
+KThCon_tempfunc = GlassTransitionScalarFunction(1, KThCon_R/KThCon_G, Tg, k_gibson, m_gibson, 0)
+
+C = 0.0228422
+sy0c = 6.02534075/0.78
+negExp_tempfunc = negativeExponentialFunction(C,Tref)
+
+a = -0.9/(90.)
+x0 = 273.15-20
+linear_tempfunc = linearScalarFunction(x0,0.9,a)
+
+hardenc = LinearExponentialJ2IsotropicHardening(1, 5., 0.01, 0.01, 30.)
+hardent = LinearExponentialJ2IsotropicHardening(2, 5., 0.01, 0.01, 30.)
+# hardenc.setTemperatureFunction_h1(linear_tempfunc)
+# hardenc.setTemperatureFunction_h2(linear_tempfunc)
+# hardenc.setTemperatureFunction_hexp(ShiftFactor_tempfunc)
+# hardent.setTemperatureFunction_h1(linear_tempfunc)
+# hardent.setTemperatureFunction_h2(linear_tempfunc)
+# hardent.setTemperatureFunction_hexp(ShiftFactor_tempfunc)
+
+hardenk = PolynomialKinematicHardening(3,3) # 1 -> PP
+hardenk.setCoefficients(0,1.) # 300.)
+hardenk.setCoefficients(1,2.) # 200.)
+hardenk.setCoefficients(2,5.)
+# hardenk.setTemperatureFunction_K(linear_tempfunc)
+
+law1 = NonLinearTVENonLinearTVP2DG3DMaterialLaw(lawnum,rho,E,nu,1e-6,Tinitial,Alpha,KThCon,Cp,False,1e-5,1e-9)
+
+law1.setCompressionHardening(hardenc)
+law1.setTractionHardening(hardent)
+# law1.setKinematicHardening(hardenk)
+
+law1.setYieldPowerFactor(1.25) # .5)
+law1.setNonAssociatedFlow(True)
+law1.nonAssociatedFlowRuleFactor(0.64) # 5)
+
+law1.setStrainOrder(-1)
+law1.setViscoelasticMethod(0)
+law1.setShiftFactorConstantsWLF(C1,C2)
+law1.setReferenceTemperature(Tref)
+
+law1.useRotationCorrectionBool(True,2) # bool, int_Scheme = 0 -> R0, 1 -> R1
+
+"""
+law1.setExtraBranchNLType(5)
+law1.useExtraBranchBool(False)
+law1.useExtraBranchBool_TVE(False,4)
+V = 1.48385807e-02
+xi = 4.86512658e+00/V**2
+iota = 2.03662889e-04/V**2
+D = 5.47347064e-02
+theta = 6.57278720e+00/D**2
+pi = 2.77066402e-03/D**2
+# law1.setVolumeCorrection(1., xi, iota, 1., theta, pi) # at 23°C
+law1.setVolumeCorrection(0.0,1000,1.5,0.0,1000.,1.5) # at 23°C
+law1.setAdditionalVolumeCorrections(0.0,1000,1.5,0.0,1000.,1.5) # NEW
+law1.setExtraBranch_CompressionParameter(1.8,0.,0.) # 1.5
+law1.setTensionCompressionRegularisation(1000.)
+
+# law1.setViscoElasticNumberOfElement(1)
+# law1.setViscoElasticData(1,1000,1.)
+# law1.setCorrectionsAllBranchesTVE(1, xi, iota, theta, pi)
+# law1.setCompressionCorrectionsAllBranchesTVE(i, 1.5)
+extraTVE = np.ones((int(0.5*(relSpec.size-1)),13)) # 3 vol + 3 dev + 1 comp
+
+# tension
+extraTVE[:,0] = (np.concatenate((np.linspace(1.0,0.25,14),np.linspace(0.25,0.05,13)))) # (np.linspace(0,0.1,N))
+extraTVE[:,1] = np.flip(np.concatenate((np.linspace(1500,15500,13),np.linspace(15500,35000,14))))
+extraTVE[:,2] = (np.concatenate((np.linspace(12.5,1.25,14),np.linspace(1.25,1.5,13))))
+extraTVE[:,3] = (np.concatenate((np.linspace(1.0,0.25,14),np.linspace(0.25,0.05,13)))) # (np.linspace(0,0.1,N))
+extraTVE[:,4] =  np.flip(np.concatenate((np.linspace(1500,15500,13),np.linspace(15500,35000,14))))
+extraTVE[:,5] = (np.concatenate((np.linspace(12.5,1.25,14),np.linspace(1.25,1.5,13))))
+extraTVE[:,6] = np.flip(np.concatenate((np.linspace(1.8,1.8,13),np.linspace(1.8,7.,14)))) # 2.2,2.8,N
+
+# compression
+extraTVE[:,7] = (np.concatenate((np.linspace(1.0,0.1,14),np.linspace(0.1,0.05,13)))) # extraTVE[:,0]
+extraTVE[:,8] = np.flip(np.concatenate((np.linspace(4500,8500,13),np.linspace(8500,35000,14)))) # extraTVE[:,1]
+extraTVE[:,9] = (np.concatenate((np.linspace(12.5,1.25,14),np.linspace(1.25,1.35,13)))) # extraTVE[:,2]
+extraTVE[:,10] = (np.concatenate((np.linspace(1.0,0.1,14),np.linspace(0.1,0.05,13)))) # extraTVE[:,3]
+extraTVE[:,11] = np.flip(np.concatenate((np.linspace(4500,8500,13),np.linspace(8500,35000,14)))) # extraTVE[:,4]
+extraTVE[:,12] = (np.concatenate((np.linspace(12.5,1.25,14),np.linspace(1.25,1.35,13)))) # extraTVE[:,5]
+extraTVE.tolist()
+"""
+
+law1.setViscoElasticNumberOfElement(N)
+if N > 0:
+    for i in range(1, N+1):
+        law1.setViscoElasticData(i, relSpec[i], relSpec[i+N])
+        # law1.setCorrectionsAllBranchesTVE(i, extraTVE[i-1,0],extraTVE[i-1,1],extraTVE[i-1,2],extraTVE[i-1,3],extraTVE[i-1,4],extraTVE[i-1,5])
+        # law1.setCompressionCorrectionsAllBranchesTVE(i, extraTVE[i-1,6])
+        # law1.setAdditionalCorrectionsAllBranchesTVE(i, extraTVE[i-1,7],extraTVE[i-1,8],extraTVE[i-1,9],extraTVE[i-1,10],extraTVE[i-1,11],extraTVE[i-1,12])
+
+law1.setTemperatureFunction_ThermalDilationCoefficient(Alpha_tempfunc)
+law1.setTemperatureFunction_ThermalConductivity(KThCon_tempfunc)
+
+mullins = linearScaler(4, 0.99)
+a = -0.9/(90.)
+x0 = 273.15-20
+linear_tempfunc = linearScalarFunction(x0,0.99,a)
+# mullins.setTemperatureFunction_r(linear_tempfunc)
+# law1.setMullinsEffect(mullins)
+
+
+eta = constantViscosityLaw(1,10000.) # 3e4) #(1,3e4)
+law1.setViscosityEffect(eta,0.21) # 0.21)
+# eta.setTemperatureFunction(negExp_tempfunc)
+# law1.setIsotropicHardeningCoefficients(1.,1.,1.)
+
+
+# solver
+sol = 2  # Gmm=0 (default) Taucs=1 PETsc=2
+soltype = 1 # StaticLinear=0 (default) StaticNonLinear=1
+nstep = 100   # number of step (used only if soltype=1)
+# ftime = 2*np.sum(elongations[:,0])/2.78e-3 # 0.65/2.78e-3 # 4.8 4.   # Final time (used only if soltype=1)
+ftime = 50.#0.2/0.01 # 0.65/2.78e-3 # 4.8 4.   # Final time (used only if soltype=1)
+tol=1.e-5  # relative tolerance for NR scheme (used only if soltype=1)
+nstepArch=1 # Number of step between 2 archiving (used only if soltype=1)
+fullDg = 0 #O = CG, 1 = DG
+space1 = 0 # function space (Lagrange=0)
+beta1  = 100
+
+
+# geometry
+geofile = "cube.geo" # "line.geo"
+meshfile = "cube.msh" # "line.msh"
+nfield = 29
+
+
+pertLaw1 = dG3DMaterialLawWithTangentByPerturbation(law1,1e-8) # use with _pert*T0 (b/c In tangent_by_perturbation_TVP u use _pert*T0)
+ThermoMechanicsEqRatio = 1.e1 # setConstitutiveExtraDofDiffusionEqRatio(ThermoMechanicsEqRatio)
+thermalSource = True
+mecaSource = False
+myfield1 = ThermoMechanicsDG3DDomain(1000,nfield,space1,lawnum,fullDg,ThermoMechanicsEqRatio)
+myfield1.setConstitutiveExtraDofDiffusionAccountSource(thermalSource,mecaSource)
+myfield1.stabilityParameters(beta1)
+myfield1.ThermoMechanicsStabilityParameters(beta1,bool(1))
+# myfield1.strainSubstep(2, 10)
+
+# creation of Solver
+mysolver = nonLinearMechSolver(1000)
+mysolver.createModel(geofile,meshfile,3,2)
+mysolver.loadModel(meshfile)
+mysolver.addDomain(myfield1)
+mysolver.addMaterialLaw(law1)
+# mysolver.addMaterialLaw(pertLaw1)
+mysolver.Scheme(soltype)
+mysolver.Solver(sol)
+mysolver.snlData(nstep,ftime,tol)
+mysolver.stepBetweenArchiving(nstepArch)
+
+# BCs
+length = 1
+umax = 0.5*length # 0.65*length # 0.04 -> PP
+fu_L = LinearFunctionTime(0,0,ftime,umax);    # Linear Displacement with time
+
+"""
+strainRate = 1.e-2
+fu_P = PiecewiseLinearFunction()
+fu_P.put(0,0)
+fu_P.put(0.5e-2/strainRate,0.5e-2*length)
+fu_P.put(1.e-2/strainRate,0.00) # 1
+fu_P.put(2.e-2/strainRate,1.0e-2*length)
+fu_P.put(3.e-2/strainRate,0.00) # 2
+fu_P.put(5.e-2/strainRate,2.0e-2*length)
+fu_P.put(7.e-2/strainRate,0.00)
+fu_P.put(9.5e-2/strainRate,2.5e-2*length)
+fu_P.put(12.e-2/strainRate,0.00)
+fu_P.put(15.e-2/strainRate,3.0e-2*length)
+fu_P.put(18.e-2/strainRate,0.00)
+fu_P.put(21.5e-2/strainRate,3.5e-2*length)
+fu_P.put(24.e-2/strainRate,0.00)
+fu_P.put(28.e-2/strainRate,4.0e-2*length)
+"""
+
+mysolver.displacementBC("Face",30,0,0.)		        # face x = 0   - Left Face fixed
+mysolver.displacementBC("Face",30,1,0.)		        # face x = 0   - Left Face fixed
+mysolver.displacementBC("Face",30,2,0.)		        # face x = 0   - Left Face fixed
+mysolver.displacementBC("Face",31,1,fu_L)         # face x = L   - Right Face moving
+mysolver.displacementBC("Face",31,2,fu_L)         # face x = L   - Right Face moving
+# mysolver.displacementBC("Face",34,1,0.)		    # face y = 0
+# mysolver.displacementBC("Face",32,2,0.)		    # face z = 0
+
+# thermal BC
+mysolver.initialBC("Volume","Position",nfield,3,Tinitial)
+fT = LinearFunctionTime(0,Tinitial,ftime,Tinitial)    # Linear Displacement with time
+mysolver.displacementBC("Volume",nfield,3,fT)
+
+# Field-Output
+
+mysolver.internalPointBuildView("strain_zz", IPField.STRAIN_ZZ, 1, nstepArch);
+mysolver.internalPointBuildView("svm",IPField.SVM, 1, nstepArch)
+mysolver.internalPointBuildView("sig_xx",IPField.SIG_XX, 1, nstepArch)
+mysolver.internalPointBuildView("sig_yy",IPField.SIG_YY, 1, nstepArch)
+mysolver.internalPointBuildView("sig_zz",IPField.SIG_ZZ, 1, nstepArch)
+mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, nstepArch)
+mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, nstepArch)
+mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_xx",IPField.mandel_XX, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_yy",IPField.mandel_YY, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_zz",IPField.mandel_ZZ, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_xy",IPField.mandel_XY, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_yz",IPField.mandel_YZ, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_xz",IPField.mandel_XZ, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_yx",IPField.mandel_YX, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_zy",IPField.mandel_ZY, 1, nstepArch)
+mysolver.internalPointBuildView("mandel_zx",IPField.mandel_ZX, 1, nstepArch)
+mysolver.internalPointBuildView("epl",IPField.PLASTICSTRAIN, 1, nstepArch)
+
+# Print/Archive History Outputs
+mysolver.archivingAverageValue(IPField.hyperElastic_BulkScalar)
+mysolver.archivingAverageValue(IPField.hyperElastic_ShearScalar)
+mysolver.archivingAverageValue(IPField.mandel_XX)
+mysolver.archivingAverageValue(IPField.mandel_YY)
+mysolver.archivingAverageValue(IPField.mandel_ZZ)
+mysolver.archivingAverageValue(IPField.mandel_XY)
+mysolver.archivingAverageValue(IPField.mandel_XZ)
+mysolver.archivingAverageValue(IPField.mandel_YZ)
+mysolver.archivingAverageValue(IPField.mandel_YX)
+mysolver.archivingAverageValue(IPField.mandel_ZX)
+mysolver.archivingAverageValue(IPField.mandel_ZY)
+mysolver.archivingAverageValue(IPField.mandelCommuteChecker)
+
+# mysolver.archivingForceOnPhysicalGroup("Face", 31, 0, nstepArch)  # Force on the right force
+mysolver.archivingForceOnPhysicalGroup("Face", 30, 0, nstepArch)  # Force on the left face  === Reaction Force
+mysolver.archivingForceOnPhysicalGroup("Face", 30, 1, nstepArch)  # Force on the left face  === Reaction Force
+mysolver.archivingForceOnPhysicalGroup("Face", 30, 2, nstepArch)  # Force on the left face  === Reaction Force
+# mysolver.archivingForceOnPhysicalGroup("Node", 41, 0, nstepArch)  # Force on a point on the left face === Reaction Force
+mysolver.archivingNodeDisplacement(43, 0, nstepArch)              # Displacement of a point on the right face
+mysolver.archivingIPOnPhysicalGroup("Volume",nfield, IPField.PLASTICSTRAIN,IPField.MEAN_VALUE);
+
+# Solve
+mysolver.solve()
+
+# check = TestCheck()
+# check.equal(-2.323842427279116e-05,mysolver.getArchivedForceOnPhysicalGroup("Face", 30, 0),1.e-4) # TVM without mechSrc
+# check.equal(-1.512641578252656e-05,mysolver.getArchivedForceOnPhysicalGroup("Face", 30, 0),1.e-4) # sy = 1.e-5, without mechSrc
diff --git a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.msh b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.msh
index b0d6ad7b747dba6adae54a969c9d6bec368bce8f..09d89e4b0a67347beacc0e2483ee74663da474be 100644
--- a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.msh
+++ b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.msh
@@ -42,7 +42,7 @@ $Nodes
 13 2.296100600555804 5.543277192431141 0 0
 14 3.652568583266842 4.760120034676862 0 0
 15 4.760120048986037 3.652568564618763 0 0
-16 5.543277197488509 2.296100588346238 0 0
+16 5.543277197488512 2.296100588346232 0 0
 17 5.948669168522611 0.783157151195411 0 0
 18 0 4.500000000005166 0 0
 19 0 3.000000000008336 0 0
@@ -67,7 +67,7 @@ $Nodes
 38 2.296100600555804 5.543277192431141 6 0
 39 3.652568583266842 4.760120034676862 6 0
 40 4.760120048986037 3.652568564618763 6 0
-41 5.543277197488509 2.296100588346238 6 0
+41 5.543277197488512 2.296100588346232 6 0
 42 5.948669168522611 0.783157151195411 6 0
 43 4.499999999994237 0 6 0
 44 2.999999999988567 0 6 0
@@ -178,31 +178,31 @@ $Nodes
 149 5.795554958944408 1.552914266099346 3.6 0
 150 5.795554958944408 1.552914266099346 4.800000000000001 0
 151 0.7831571644793788 5.948669166773743 0.6000000000000079 0
-152 1.552914274817983 5.795554956608258 0.6000000000000001 0
-153 0.7831571554772518 5.948669167958895 1.2 0
-154 0.7831571554772518 5.948669167958895 1.8 0
-155 1.552914274817974 5.79555495660826 1.8 0
-156 0.7831571554772518 5.948669167958895 2.4 0
-157 0.7831571554772518 5.948669167958895 3 0
-158 1.552914274817974 5.79555495660826 3 0
-159 0.7831571554772518 5.948669167958895 3.6 0
-160 0.7831571554772518 5.948669167958895 4.199999999999999 0
-161 1.552914274817974 5.79555495660826 4.2 0
-162 0.7831571554772518 5.948669167958895 4.800000000000001 0
-163 0.7831571554772518 5.948669167958895 5.4 0
-164 1.552914274817982 5.795554956608258 5.4 0
-165 2.296100600342287 5.543277192519582 0.6000000000000001 0
+152 1.552914274817997 5.795554956608253 0.6000000000000001 0
+153 0.7831571554772612 5.948669167958894 1.2 0
+154 0.7831571554772612 5.948669167958894 1.8 0
+155 1.552914274818002 5.795554956608252 1.8 0
+156 0.7831571554772612 5.948669167958894 2.4 0
+157 0.7831571554772612 5.948669167958894 3 0
+158 1.552914274818002 5.795554956608252 3 0
+159 0.7831571554772612 5.948669167958894 3.6 0
+160 0.7831571554772612 5.948669167958894 4.199999999999999 0
+161 1.552914274818002 5.795554956608252 4.2 0
+162 0.7831571554772612 5.948669167958894 4.800000000000001 0
+163 0.7831571554772612 5.948669167958894 5.4 0
+164 1.552914274817997 5.795554956608253 5.4 0
+165 2.2961006003423 5.543277192519577 0.6000000000000001 0
 166 3.000000007764873 5.19615241822358 0.6000000000000001 0
-167 2.296100600342287 5.543277192519582 1.2 0
-168 2.296100600342287 5.543277192519582 1.8 0
+167 2.2961006003423 5.543277192519577 1.2 0
+168 2.2961006003423 5.543277192519577 1.8 0
 169 3.000000007764873 5.19615241822358 1.8 0
-170 2.296100600342287 5.543277192519582 2.4 0
-171 2.296100600342287 5.543277192519582 3 0
+170 2.2961006003423 5.543277192519577 2.4 0
+171 2.2961006003423 5.543277192519577 3 0
 172 3.000000007764873 5.19615241822358 3 0
-173 2.296100600342287 5.543277192519582 3.6 0
-174 2.296100600342287 5.543277192519582 4.2 0
+173 2.2961006003423 5.543277192519577 3.6 0
+174 2.2961006003423 5.543277192519577 4.2 0
 175 3.000000007764873 5.19615241822358 4.2 0
-176 2.296100600342287 5.543277192519582 4.800000000000001 0
+176 2.2961006003423 5.543277192519577 4.800000000000001 0
 177 2.296100600342296 5.543277192519579 5.4 0
 178 3.000000007764873 5.19615241822358 5.4 0
 179 3.652568583207426 4.760120034722454 0.6000000000000001 0
diff --git a/dG3D/src/dG3DIPVariable.cpp b/dG3D/src/dG3DIPVariable.cpp
index e0791bef702606109a245b0a6c5e573068acece5..b616ee77ed1fc0e0215627ab51c3881e67fbc603 100644
--- a/dG3D/src/dG3DIPVariable.cpp
+++ b/dG3D/src/dG3DIPVariable.cpp
@@ -5838,6 +5838,16 @@ double NonLinearTVMDG3DIPVariable::get(const int i) const{
   else if (i == IPField::corKir_YY){return _ipViscoElastic->_kirchhoff(1,1);}
   else if (i == IPField::corKir_YZ){return _ipViscoElastic->_kirchhoff(1,2);}
   else if (i == IPField::corKir_ZZ){return _ipViscoElastic->_kirchhoff(2,2);}
+  else if (i == IPField::mandel_XX){return _ipViscoElastic->_ModMandel(0,0);}
+  else if (i == IPField::mandel_XY){return _ipViscoElastic->_ModMandel(0,1);}
+  else if (i == IPField::mandel_YX){return _ipViscoElastic->_ModMandel(1,0);}
+  else if (i == IPField::mandel_XZ){return _ipViscoElastic->_ModMandel(0,2);}
+  else if (i == IPField::mandel_ZX){return _ipViscoElastic->_ModMandel(2,0);}
+  else if (i == IPField::mandel_YY){return _ipViscoElastic->_ModMandel(1,1);}
+  else if (i == IPField::mandel_YZ){return _ipViscoElastic->_ModMandel(1,2);}
+  else if (i == IPField::mandel_ZY){return _ipViscoElastic->_ModMandel(2,1);}
+  else if (i == IPField::mandel_ZZ){return _ipViscoElastic->_ModMandel(2,2);}
+  else if (i == IPField::mandelCommuteChecker){return _ipViscoElastic->_mandelCommuteChecker;}
   else if (i == IPField::hyperElastic_BulkScalar){return _ipViscoElastic->getConstRefToElasticBulkPropertyScaleFactor();}
   else if (i == IPField::hyperElastic_ShearScalar){return _ipViscoElastic->getConstRefToElasticShearPropertyScaleFactor();}
   else if (i == IPField::corKirExtra_XX){return _ipViscoElastic->_corKirExtra(0,0);}
@@ -6236,6 +6246,16 @@ double NonLinearTVPDG3DIPVariable::get(const int i) const{
   else if (i == IPField::corKir_YY){return _ipViscoElastoPlastic->_kirchhoff(1,1);}
   else if (i == IPField::corKir_YZ){return _ipViscoElastoPlastic->_kirchhoff(1,2);}
   else if (i == IPField::corKir_ZZ){return _ipViscoElastoPlastic->_kirchhoff(2,2);}
+  else if (i == IPField::mandel_XX){return _ipViscoElastoPlastic->_ModMandel(0,0);}
+  else if (i == IPField::mandel_XY){return _ipViscoElastoPlastic->_ModMandel(0,1);}
+  else if (i == IPField::mandel_YX){return _ipViscoElastoPlastic->_ModMandel(1,0);}
+  else if (i == IPField::mandel_XZ){return _ipViscoElastoPlastic->_ModMandel(0,2);}
+  else if (i == IPField::mandel_ZX){return _ipViscoElastoPlastic->_ModMandel(2,0);}
+  else if (i == IPField::mandel_YY){return _ipViscoElastoPlastic->_ModMandel(1,1);}
+  else if (i == IPField::mandel_YZ){return _ipViscoElastoPlastic->_ModMandel(1,2);}
+  else if (i == IPField::mandel_ZY){return _ipViscoElastoPlastic->_ModMandel(2,1);}
+  else if (i == IPField::mandel_ZZ){return _ipViscoElastoPlastic->_ModMandel(2,2);}
+  else if (i == IPField::mandelCommuteChecker){return _ipViscoElastoPlastic->_mandelCommuteChecker;}
   else if (i == IPField::hyperElastic_BulkScalar){return _ipViscoElastoPlastic->getConstRefToElasticBulkPropertyScaleFactor();}
   else if (i == IPField::hyperElastic_ShearScalar){return _ipViscoElastoPlastic->getConstRefToElasticShearPropertyScaleFactor();}
   else if (i == IPField::corKirExtra_XX){return _ipViscoElastoPlastic->_corKirExtra(0,0);}
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index 6ed9c64645d0c5bec195a60db135b56d76f3c012..029a582049e60db9ac4edb919164f03f5368e327 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -252,7 +252,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
   ipvcur->getConstRefToDeformationGradient().print("F Analytique"); // FLE
   ipvcur->getConstRefToFirstPiolaKirchhoffStress().print("P Analytique"); // FLE
   ipvcur->getConstRefToTangentModuli().print("dPdE Analytique");
-  for (int k=0; k< numNonLocalVars; k++)
+ /* for (int k=0; k< numNonLocalVars; k++)
   {
     ipvcur->getConstRefToDLocalVariableDStrain()[k].print("dpdE Analyique");
   }
@@ -336,7 +336,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
     {
         Msg::Info("dp dExtraDofDiffusionField Analytique: %e",ipvcur->getRefTodLocalVariableDExtraDofDiffusionField()(k,i));
     }
-  }
+  }*/
   for (unsigned int i = 0; i < numCurlDof; ++i)
   {
       ipvcur->getConstRefTodPdVectorPotential()[i].print("dPdMagneticVectorPotential Analytique");
@@ -636,7 +636,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         ipvcur->getConstRefToDIrreversibleEnergyDDeformationGradient().print("dEnedE Numerique");
       }
     }
-    for (int i=0; i< numNonLocalVars; i++)
+    /*for (int i=0; i< numNonLocalVars; i++)
     {
       for (int j=0; j< numNonLocalVars; j++)
       {
@@ -707,7 +707,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         {
             Msg::Info("dp dExtraDofDiffusionField Numerique: %e",ipvcur->getRefTodLocalVariableDExtraDofDiffusionField()(k,i));
         }
-    }
+    }*/
     for (unsigned int i = 0; i < numCurlDof; ++i)
     {
       const unsigned int extradof_T = 0; // Thermal field EM source
@@ -10541,6 +10541,9 @@ void NonLinearTVMDG3DMaterialLaw::useExtraBranchBool(const bool useExtraBranch){
 void NonLinearTVMDG3DMaterialLaw::useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option){
   _viscoLaw.useExtraBranchBool_TVE(useExtraBranch_TVE, ExtraBranch_TVE_option);
 };
+void NonLinearTVMDG3DMaterialLaw::useRotationCorrectionBool(const bool useRotationCorrection,  const int rotationCorrectionScheme){
+  _viscoLaw.useRotationCorrectionBool(useRotationCorrection,rotationCorrectionScheme);
+};
 void NonLinearTVMDG3DMaterialLaw::setVolumeCorrection(const double _vc, const double _xivc, const double _zetavc, const double _dc, const double _thetadc, const double _pidc){
   _viscoLaw.setVolumeCorrection(_vc,_xivc,_zetavc,_dc,_thetadc,_pidc);
 };
@@ -11372,6 +11375,9 @@ void NonLinearTVENonLinearTVPDG3DMaterialLaw::useExtraBranchBool(const bool useE
 void NonLinearTVENonLinearTVPDG3DMaterialLaw::useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option){
   _viscoLaw.useExtraBranchBool_TVE(useExtraBranch_TVE, ExtraBranch_TVE_option);
 };
+void NonLinearTVENonLinearTVPDG3DMaterialLaw::useRotationCorrectionBool(const bool useRotationCorrection,  const int rotationCorrectionScheme){
+  _viscoLaw.useRotationCorrectionBool(useRotationCorrection,rotationCorrectionScheme);
+};
 void NonLinearTVENonLinearTVPDG3DMaterialLaw::setVolumeCorrection(const double _vc, const double _xivc, const double _zetavc, const double _dc, const double _thetadc, const double _pidc){
   _viscoLaw.setVolumeCorrection(_vc,_xivc,_zetavc,_dc,_thetadc,_pidc);
 };
@@ -11513,3 +11519,299 @@ void NonLinearTVENonLinearTVPDG3DMaterialLaw::stress(IPVariable* ipv, const IPVa
 }
 
 // NonLinearTVENonLinearTVP Law Interface =================================================================== END
+
+
+// NonLinearTVENonLinearTVP2 Law Interface =================================================================== BEGIN
+
+NonLinearTVENonLinearTVP2DG3DMaterialLaw::NonLinearTVENonLinearTVP2DG3DMaterialLaw(const int num, const double rho, const double E, const double nu, const double tol,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation, const double pert, const double stressIteratorTol, const bool thermalEstimationPreviousConfig):
+                        dG3DMaterialLaw(num,rho), _viscoLaw(num,E,nu,rho,tol,Tinitial,Alpha, KThCon, Cp, matrixbyPerturbation,pert, stressIteratorTol, thermalEstimationPreviousConfig)
+{
+  fillElasticStiffness(E, nu, elasticStiffness);   // Why are some of the variables defined in this constructor?  --- WHAT??
+};
+
+NonLinearTVENonLinearTVP2DG3DMaterialLaw::NonLinearTVENonLinearTVP2DG3DMaterialLaw(const NonLinearTVENonLinearTVP2DG3DMaterialLaw& src):  dG3DMaterialLaw(src), _viscoLaw(src._viscoLaw){};
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setStrainOrder(const int order){
+  _viscoLaw.setStrainOrder(order);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoelasticMethod(const int method){
+  _viscoLaw.setViscoelasticMethod(method);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticNumberOfElement(const int N){
+  _viscoLaw.setViscoElasticNumberOfElement(N);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui){
+  _viscoLaw.setViscoElasticData(i,Ei,taui);
+};
+/*
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  _viscoLaw.setViscoElasticData(i,Ei,taui,Alphai);
+};*/
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  _viscoLaw.setViscoElasticData_Bulk(i,Ki,ki);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  _viscoLaw.setViscoElasticData_Shear(i,Gi,gi);
+};
+/*
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData_Alpha(const int i, const double Alphai){
+  _viscoLaw.setViscoElasticData_Alpha(i,Alphai);
+};
+*/
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscoElasticData(const std::string filename){
+  _viscoLaw.setViscoElasticData(filename);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3){
+  _viscoLaw.setIsotropicHardeningCoefficients(HR1,HR2,HR3);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setPolynomialOrderChabocheCoeffs(const int order){
+  _viscoLaw.setPolynomialOrderChabocheCoeffs(order);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setPolynomialCoeffsChabocheCoeffs(const int i, const double val){
+  _viscoLaw.setPolynomialCoeffsChabocheCoeffs(i,val);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setReferenceTemperature(const double Tref){
+  _viscoLaw.setReferenceTemperature(Tref);
+};
+/*
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTempFuncOption(const double TemFuncOpt){           // To be discarded
+  _viscoLaw.setTempFuncOption(TemFuncOpt);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setModelOption(const int modelFlag){
+  _viscoLaw.setModelOption(modelFlag);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTestOption(const int testFlag){
+  _viscoLaw.setTestOption(testFlag);
+};
+*/
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setShiftFactorConstantsWLF(const double C1, const double C2){
+  _viscoLaw.setShiftFactorConstantsWLF(C1,C2);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_BulkModulus(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ShearModulus(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalDilationCoefficient(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalConductivity(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_ElasticCorrection_Bulk(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ElasticCorrection_Bulk(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_ElasticCorrection_Shear(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ElasticCorrection_Shear(Tfunc);
+};
+/*
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchShearModuli(Tfunc,i);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchThermalDilationCoefficient(Tfunc,i);
+};
+*/
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setCompressionHardening(const J2IsotropicHardening& comp){
+  _viscoLaw.setCompressionHardening(comp);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTractionHardening(const J2IsotropicHardening& trac){
+  _viscoLaw.setTractionHardening(trac);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setKinematicHardening(const kinematicHardening& kin){
+  _viscoLaw.setKinematicHardening(kin);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setViscosityEffect(const viscosityLaw& v, const double p){
+  _viscoLaw.setViscosityEffect(v,p);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setMullinsEffect(const mullinsEffect& mullins){
+  _viscoLaw.setMullinsEffect(mullins);
+};
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setYieldPowerFactor(const double n){
+  _viscoLaw.setPowerFactor(n);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::nonAssociatedFlowRuleFactor(const double b){
+  _viscoLaw.nonAssociatedFlowRuleFactor(b);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setPlasticPoissonRatio(const double nup){
+  _viscoLaw.setPlasticPoissonRatio(nup);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setNonAssociatedFlow(const bool flag){
+  _viscoLaw.setNonAssociatedFlow(flag);
+};
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTaylorQuineyFactor(const double f, const bool flag){
+  _viscoLaw.setTaylorQuineyFactor(f, flag);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_InitialYieldStress(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_Hardening(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_Hardening(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_KinematicHardening(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_KinematicHardening(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTemperatureFunction_Viscosity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_Viscosity(Tfunc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::useExtraBranchBool(const bool useExtraBranch){
+  _viscoLaw.useExtraBranchBool(useExtraBranch);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option){
+  _viscoLaw.useExtraBranchBool_TVE(useExtraBranch_TVE, ExtraBranch_TVE_option);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::useRotationCorrectionBool(const bool useRotationCorrection,  const int rotationCorrectionScheme){
+  _viscoLaw.useRotationCorrectionBool(useRotationCorrection,rotationCorrectionScheme);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setVolumeCorrection(const double _vc, const double _xivc, const double _zetavc, const double _dc, const double _thetadc, const double _pidc){
+  _viscoLaw.setVolumeCorrection(_vc,_xivc,_zetavc,_dc,_thetadc,_pidc);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setAdditionalVolumeCorrections(const double V3, const double V4, const double V5, const double D3, const double D4, const double D5){
+  _viscoLaw.setAdditionalVolumeCorrections(V3,V4,V5,D3,D4,D5);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setExtraBranch_CompressionParameter(const double compCorrection, const double compCorrection_2, const double compCorrection_3){
+  _viscoLaw.setExtraBranch_CompressionParameter(compCorrection,compCorrection_2,compCorrection_3);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setExtraBranchNLType(const int method){
+  _viscoLaw.setExtraBranchNLType(method);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setTensionCompressionRegularisation(const double tensionCompressionRegularisation){
+  _viscoLaw.setTensionCompressionRegularisation(tensionCompressionRegularisation);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setCorrectionsAllBranchesTVE(const int i, const double V0,const double V1, const double V2, const double D0,const double D1, const double D2){
+  _viscoLaw.setCorrectionsAllBranchesTVE(i,V0,V1,V2,D0,D1,D2);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setAdditionalCorrectionsAllBranchesTVE(const int i, const double V3, const double V4, const double V5, const double D3, const double D4, const double D5){
+  _viscoLaw.setAdditionalCorrectionsAllBranchesTVE(i,V3,V4,V5,D3,D4,D5);
+};
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::setCompressionCorrectionsAllBranchesTVE(const int i, const double Ci){
+  _viscoLaw.setCompressionCorrectionsAllBranchesTVE(i,Ci);
+};
+
+// Added extra argument in the NonLinearTVEDG3DIPVariable contructor - Tinitial   (added from LinearThermoMech)
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  // check interface element
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele==NULL) inter=false;
+  IPVariable* ipvi = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);   // Why 3 times? --- WHAT??    Add getInitialTemperature in Material Law
+  IPVariable* ipv1 = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv2 = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  if(ipv !=NULL) delete ipv;
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele == NULL){
+    inter=false;
+  }
+  ipv = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+}
+
+// 2 Member Functions added from LinearThermoMechanicsDG3DMaterialLaw  --  Add these functions in the material law
+double NonLinearTVENonLinearTVP2DG3DMaterialLaw::getExtraDofStoredEnergyPerUnitField(double T) const{
+  return _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+double NonLinearTVENonLinearTVP2DG3DMaterialLaw::getInitialExtraDofStoredEnergyPerUnitField() const{
+	return _viscoLaw.getInitialExtraDofStoredEnergyPerUnitField();
+};
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvp) const{
+ // get ipvariable
+  NonLinearTVPDG3DIPVariable* ipvcur;
+  const NonLinearTVPDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvp);
+  }
+  _viscoLaw.checkInternalState(ipvcur->getInternalData(), ipvprev->getInternalData());
+};
+
+void NonLinearTVENonLinearTVP2DG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent){
+
+  // get ipvariable
+  NonLinearTVPDG3DIPVariable* ipvcur;
+  const NonLinearTVPDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvp);
+  }
+
+// All IP Variables passed to the Constitutive function defined in mlaw
+  const STensor3& F1       = ipvcur->getConstRefToDeformationGradient();
+  const STensor3& F0       = ipvprev->getConstRefToDeformationGradient();
+  const double T           = ipvcur->getConstRefToTemperature();
+  const double T0          = ipvprev->getConstRefToTemperature();
+  const SVector3& gradT0   = ipvprev->getConstRefToGradT();
+  const SVector3& gradT    = ipvcur->getConstRefToGradT();
+        STensor3& dPdT     = ipvcur->getRefTodPdT();
+        SVector3& fluxT    = ipvcur->getRefToThermalFlux();
+        STensor3& dqdgradT = ipvcur->getRefTodThermalFluxdGradT();
+        SVector3& dqdT     = ipvcur->getRefTodThermalFluxdT();
+        STensor33& dqdF    = ipvcur->getRefTodThermalFluxdF();
+
+        STensor3& P        = ipvcur->getRefToFirstPiolaKirchhoffStress();
+        STensor43& Tangent = ipvcur->getRefToTangentModuli();
+  const double& w0         = ipvprev->getConstRefToThermalSource();
+        double& w          = ipvcur->getRefToThermalSource();
+        double& dwdt       = ipvcur->getRefTodThermalSourcedField();
+        STensor3& dwdf     = ipvcur->getRefTodThermalSourcedF();
+  const SVector3& N        = ipvcur->getRefToReferenceOutwardNormal();
+  const SVector3& ujump    = ipvcur->getRefToJump()(0);
+  const double& Tjump      = ipvcur->getRefToFieldJump()(0);
+        double& Cp         = ipvcur->getRefToExtraDofFieldCapacityPerUnitField()(0);
+  const double& mechSource0 = ipvprev->getConstRefToMechanicalSource()(0);
+        double& mechSource = ipvcur->getRefToMechanicalSource()(0);
+        double& dmechSourcedt = ipvcur->getRefTodMechanicalSourcedField()(0,0);
+        STensor3& dmechSourcedf = ipvcur->getRefTodMechanicalSourcedF()[0];
+
+  // data for J2 law
+  IPNonLinearTVP* q1 = ipvcur->getIPNonLinearTVP();
+  const IPNonLinearTVP* q0 = ipvprev->getIPNonLinearTVP();
+  // static STensor63 dCalgdeps;
+  STensor43& elasticL = ipvcur->getRefToElasticTangentModuli();
+
+  // Compute Stress
+  _viscoLaw.constitutive(F0,F1,P,q0,q1,Tangent,T0,T,gradT0,gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w,dwdt,dwdf,mechSource,dmechSourcedt,dmechSourcedf,stiff,&elasticL);
+
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+  ipvcur->setRefToLinearConductivity(_viscoLaw.getConductivityTensor());
+  ipvcur->setRefToStiff_alphaDilatation(_viscoLaw.getStiff_alphaDilatation());
+
+  Cp = _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+// NonLinearTVENonLinearTVP2 Law Interface =================================================================== END
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index 9c805dd5dcec27e7224417f05bd3457e45bbe432..4ca7436a27e53ef31ba02cb8453b5ca8361e3104 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -58,6 +58,7 @@
 #include "mlawNonLinearTVE.h"
 #include "mlawNonLinearTVP.h"
 #include "mlawNonLinearTVENonLinearTVP.h"
+#include "mlawNonLinearTVENonLinearTVP2.h"
 #include "mullinsEffect.h"
 #include "mlawHyperelasticWithPotential.h"
 #endif
@@ -3335,6 +3336,7 @@ class NonLinearTVMDG3DMaterialLaw : public dG3DMaterialLaw{   // public Material
     void setShiftFactorConstantsWLF(const double C1, const double C2);
     void useExtraBranchBool(const bool useExtraBranch);
     void useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option);
+    void useRotationCorrectionBool(const bool useRotationCorrection, const int rotationCorrectionScheme);
     void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc);
     void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc);
     void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
@@ -3632,6 +3634,7 @@ class NonLinearTVENonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // pub
     // void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i);
     void useExtraBranchBool(const bool useExtraBranch);
     void useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option);
+    void useRotationCorrectionBool(const bool useRotationCorrection, const int rotationCorrectionScheme);
     void setVolumeCorrection(const double _vc, const double _xivc, const double _zetavc, const double _dc, const double _thetadc, const double _pidc);
     void setAdditionalVolumeCorrections(const double V3, const double V4, const double V5, const double D3, const double D4, const double D5);
     void setExtraBranch_CompressionParameter(const double compCorrection, const double compCorrection_2, const double compCorrection_3);
@@ -3700,4 +3703,115 @@ class NonLinearTVENonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // pub
 
 // NonLinearTVENonLinearTVP Law Interface =================================================================== END
 
+// NonLinearTVENonLinearTVP2 Law Interface =================================================================== START
+
+class NonLinearTVENonLinearTVP2DG3DMaterialLaw : public dG3DMaterialLaw{   // public MaterialLaw
+  #ifndef SWIG
+  protected:
+    mlawNonLinearTVENonLinearTVP2 _viscoLaw;
+
+  #endif //SWIG
+  public:
+    NonLinearTVENonLinearTVP2DG3DMaterialLaw(const int num, const double rho, const double E, const double nu, const double tol,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation = false, const double pert = 1e-8, const double stressIteratorTol = 1e-9, const bool thermalEstimationPreviousConfig = false);
+
+    void setStrainOrder(const int order);
+    void setViscoelasticMethod(const int method);
+    void setViscoElasticNumberOfElement(const int N);
+    void setViscoElasticData(const int i, const double Ei, const double taui);
+    // void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    // void setViscoElasticData_Alpha(const int i, const double Alphai);
+    void setViscoElasticData(const std::string filename);
+    void setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3);
+    void setPolynomialOrderChabocheCoeffs(const int order);
+    void setPolynomialCoeffsChabocheCoeffs(const int i, const double val);
+
+    void setReferenceTemperature(const double Tref);
+    // void setTempFuncOption(const double TemFuncOpt);
+    // void setModelOption(const int modelFlag);
+    // void setTestOption(const int testFlag);
+    void setShiftFactorConstantsWLF(const double C1, const double C2);
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc);
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ElasticCorrection_Bulk(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ElasticCorrection_Shear(const scalarFunction& Tfunc);
+    // void setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc,int i);
+    // void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i);
+    // void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i);
+    void useExtraBranchBool(const bool useExtraBranch);
+    void useExtraBranchBool_TVE(const bool useExtraBranch_TVE, const int ExtraBranch_TVE_option);
+    void useRotationCorrectionBool(const bool useRotationCorrection, const int rotationCorrectionScheme);
+    void setVolumeCorrection(const double _vc, const double _xivc, const double _zetavc, const double _dc, const double _thetadc, const double _pidc);
+    void setAdditionalVolumeCorrections(const double V3, const double V4, const double V5, const double D3, const double D4, const double D5);
+    void setExtraBranch_CompressionParameter(const double compCorrection, const double compCorrection_2, const double compCorrection_3);
+    void setExtraBranchNLType(const int type);
+    void setTensionCompressionRegularisation(const double tensionCompressionRegularisation);
+    void setCorrectionsAllBranchesTVE(const int i, const double V0,const double V1, const double V2, const double D0, const double D1, const double D2);
+    void setAdditionalCorrectionsAllBranchesTVE(const int i, const double V3, const double V4, const double V5, const double D3, const double D4, const double D5);
+    void setCompressionCorrectionsAllBranchesTVE(const int i, const double Ci);
+
+    void setCompressionHardening(const J2IsotropicHardening& comp);
+    void setTractionHardening(const J2IsotropicHardening& trac);
+    void setKinematicHardening(const kinematicHardening& kin);
+    void setViscosityEffect(const viscosityLaw& v, const double p);
+    void setMullinsEffect(const mullinsEffect& mullins);
+
+    void setYieldPowerFactor(const double n);
+    void nonAssociatedFlowRuleFactor(const double b);
+    void setPlasticPoissonRatio(const double nup);
+    void setNonAssociatedFlow(const bool flag);
+
+    void setTaylorQuineyFactor(const double f, const bool flag = false);
+    void setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc);
+    void setTemperatureFunction_Hardening(const scalarFunction& Tfunc);
+    void setTemperatureFunction_KinematicHardening(const scalarFunction& Tfunc);
+    void setTemperatureFunction_Viscosity(const scalarFunction& Tfunc);
+
+    #ifndef SWIG
+     NonLinearTVENonLinearTVP2DG3DMaterialLaw(const NonLinearTVENonLinearTVP2DG3DMaterialLaw &source);
+    virtual ~NonLinearTVENonLinearTVP2DG3DMaterialLaw(){}
+    // set the time of _j2law
+    virtual void setTime(const double t,const double dtime){
+      dG3DMaterialLaw::setTime(t,dtime);
+      _viscoLaw.setTime(t,dtime);
+    }
+    virtual materialLaw::matname getType() const {return _viscoLaw.getType();}
+    virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
+    virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}
+    virtual double soundSpeed() const{return _viscoLaw.soundSpeed();} // or change value ??
+    virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+    virtual const double bulkModulus() const {return _viscoLaw.bulkModulus();}
+    virtual double scaleFactor() const{return _viscoLaw.scaleFactor();}
+
+    virtual int getNumberOfExtraDofsDiffusion() const {return 1;}
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const;
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const;
+
+    virtual materialLaw* clone() const{return new NonLinearTVENonLinearTVP2DG3DMaterialLaw(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
+    virtual bool withEnergyDissipation() const {return _viscoLaw.withEnergyDissipation();};
+    virtual void setMacroSolver(const nonLinearMechSolver* sv){
+      dG3DMaterialLaw::setMacroSolver(sv);
+      _viscoLaw.setMacroSolver(sv);
+    };
+
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      return &_viscoLaw;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      return &_viscoLaw;
+    }
+    #endif //SWIG
+};
+
+// NonLinearTVENonLinearTVP2 Law Interface =================================================================== END
 #endif