diff --git a/NonLinearSolver/internalPoints/CMakeLists.txt b/NonLinearSolver/internalPoints/CMakeLists.txt
index 845ba8b53bab570c8fbfebcafdcd957c9c297dcd..83a0969341c50a3c734b7cbb0757e9641d220707 100644
--- a/NonLinearSolver/internalPoints/CMakeLists.txt
+++ b/NonLinearSolver/internalPoints/CMakeLists.txt
@@ -64,6 +64,7 @@ set(SRC
   ipNonLinearTVM.cpp
   ipNonLinearTVE.cpp
   ipNonLinearTVP.cpp
+  ipMullinsEffect.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
diff --git a/NonLinearSolver/internalPoints/ipField.cpp b/NonLinearSolver/internalPoints/ipField.cpp
index f653c6f9a7aa1a520305f97e89dca3a0ed71f24e..a1894e700547af65a0de4ff82478bd514c120171 100644
--- a/NonLinearSolver/internalPoints/ipField.cpp
+++ b/NonLinearSolver/internalPoints/ipField.cpp
@@ -1034,6 +1034,29 @@ std::string IPField::ToString(const int i){
   else if (i == Eve2_XY) return "Eve2_XY";
   else if (i == Eve2_XZ) return "Eve2_XZ";
   else if (i == Eve2_YZ) return "Eve2_YZ";
+  else if (i == corKir_XX) return "corKir_XX";
+  else if (i == corKir_YY) return "corKir_YY";
+  else if (i == corKir_ZZ) return "corKir_ZZ";
+  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 == corKirExtra_XX) return "corKirExtra_XX";
+  else if (i == corKirExtra_YY) return "corKirExtra_YY";
+  else if (i == corKirExtra_ZZ) return "corKirExtra_ZZ";
+  else if (i == corKirExtra_XY) return "corKirExtra_XY";
+  else if (i == corKirExtra_XZ) return "corKirExtra_XZ";
+  else if (i == corKirExtra_YZ) return "corKirExtra_YZ";
+  else if (i == Dev_corKir_Inf_XX) return "Dev_corKir_Inf_XX";
+  else if (i == Dev_corKir_Inf_YY) return "Dev_corKir_Inf_YY";
+  else if (i == Dev_corKir_Inf_ZZ) return "Dev_corKir_Inf_ZZ";
+  else if (i == Dev_corKir_Inf_XY) return "Dev_corKir_Inf_XY";
+  else if (i == Dev_corKir_Inf_XZ) return "Dev_corKir_Inf_XZ";
+  else if (i == Dev_corKir_Inf_YZ) return "Dev_corKir_Inf_YZ";
+  else if (i == Tr_corKir_Inf) return "Tr_corKir_Inf";
+  else if (i == hyperElastic_BulkScalar) return "hyperElastic_BulkScalar";
+  else if (i == hyperElastic_ShearScalar) return "hyperElastic_ShearScalar";
+  else if (i == MAX_DEFO_ENERGY) return "MAX_DEFO_ENERGY";
+  else if (i == MULLINS_DAMAGE) return "MULLINS_DAMAGE";
   else if (i == USER1) return "USER1";
   else if (i == USER2) return "USER2";
   else if (i == USER3) return "USER3";
diff --git a/NonLinearSolver/internalPoints/ipField.h b/NonLinearSolver/internalPoints/ipField.h
index 7fa320ea097e5cb372309c9542c2d041ff250087..ca42944b3d632f3efd0d158fff6687920b8e91d5 100644
--- a/NonLinearSolver/internalPoints/ipField.h
+++ b/NonLinearSolver/internalPoints/ipField.h
@@ -323,6 +323,10 @@ 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,
+                    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,
                     USER0,USER1,USER2,USER3,USER4,USER5,USER6,USER7,USER8,USER9,USER10,
                     MAGNETICVECTORPOTENTIAL_X, MAGNETICVECTORPOTENTIAL_Y, MAGNETICVECTORPOTENTIAL_Z,
                     MAGNETICINDUCTION_X, MAGNETICINDUCTION_Y, MAGNETICINDUCTION_Z,
@@ -333,6 +337,8 @@ class IPField : public elementsField {
                     EQUIVALENT_EIGENSTRESS,EQUIVALENT_EIGENSTRAIN, 
                     EIGENSTRESS_XX, EIGENSTRESS_YY, EIGENSTRESS_ZZ, EIGENSTRESS_XY, EIGENSTRESS_XZ, EIGENSTRESS_YZ,
                     EIGENSTRAIN_XX, EIGENSTRAIN_YY, EIGENSTRAIN_ZZ, EIGENSTRAIN_XY, EIGENSTRAIN_XZ, EIGENSTRAIN_YZ,
+                    // moduli scalers e.g. mullins effect
+                    MAX_DEFO_ENERGY, MULLINS_DAMAGE,
                     UNDEFINED};
     enum  Operator { MEAN_VALUE=1, MIN_VALUE, MAX_VALUE, CRUDE_VALUE};      
     static std::string ToString(const int i);
diff --git a/NonLinearSolver/internalPoints/ipHardening.cpp b/NonLinearSolver/internalPoints/ipHardening.cpp
index f71905e98f715f3a3c9779ed6777b9849601b507..423e11074a1029fca64b198e4f1d42931da42ec1 100644
--- a/NonLinearSolver/internalPoints/ipHardening.cpp
+++ b/NonLinearSolver/internalPoints/ipHardening.cpp
@@ -11,13 +11,14 @@
 #include "restartManager.h"
 
 IPJ2IsotropicHardening::IPJ2IsotropicHardening(const double R0_):
-      R0(R0_), R(R0_), dR(0.), ddR(0.), integR(0.),_isSaturated(false),dRdT(0.), ddRdTT(0.), wp(0.), dwp(0.)
+      R0(R0_), R(R0_), dR(0.), ddR(0.), integR(0.),_isSaturated(false),dRdT(0.), ddRdTT(0.), ddRdT(0.), wp(0.), dwp(0.)
 {
 
 }
 
 IPJ2IsotropicHardening::IPJ2IsotropicHardening(const IPJ2IsotropicHardening &source):
-      R0(source.R0), R(source.R), dR (source.dR), ddR (source.ddR),integR(source.integR),_isSaturated(source._isSaturated), dRdT(source.dRdT), ddRdTT(source.ddRdTT),
+      R0(source.R0), R(source.R), dR (source.dR), ddR (source.ddR),integR(source.integR),_isSaturated(source._isSaturated), 
+      dRdT(source.dRdT), ddRdTT(source.ddRdTT), ddRdT(source.ddRdT),
       wp(source.wp), dwp(source.dwp)
 {
 
@@ -33,6 +34,7 @@ IPJ2IsotropicHardening &IPJ2IsotropicHardening::operator=(const IPJ2IsotropicHar
   _isSaturated = src._isSaturated;
   dRdT = src.dRdT;
   ddRdTT = src.ddRdTT;
+  ddRdT = src.ddRdT;
   wp   = src.wp;
   dwp   = src.dwp;
   return *this;
@@ -48,6 +50,7 @@ void IPJ2IsotropicHardening::restart()
   restartManager::restart(_isSaturated);
   restartManager::restart(dRdT);
   restartManager::restart(ddRdTT);
+  restartManager::restart(ddRdT);
   restartManager::restart(wp);
   restartManager::restart(dwp);
   return;
diff --git a/NonLinearSolver/internalPoints/ipHardening.h b/NonLinearSolver/internalPoints/ipHardening.h
index c62fbf01b7df159e43d4b3176c4c94682ef4415d..be17f906b42440df05ba902269a11357292ce593 100644
--- a/NonLinearSolver/internalPoints/ipHardening.h
+++ b/NonLinearSolver/internalPoints/ipHardening.h
@@ -28,6 +28,7 @@ protected:
     bool _isSaturated; // harderning modulus become 0 under some conditions
     double dRdT; // temeprature dependence
     double ddRdTT; // 
+    double ddRdT; // ddR/dgdT 
 
     double wp;  //yield shrink because of plastic instability
     double dwp;
@@ -50,9 +51,11 @@ protected:
   virtual double getIntegR() const {return (1-wp)*integR;}
   virtual double getDRDT() const{ return (1-wp)*dRdT;};
   virtual double getDDRDTT() const{ return (1-wp)*ddRdTT;};
+  virtual double getDDRDT() const{ return (1-wp)*ddRdT;};
   virtual double getWp() const{ return wp;};
   virtual double getDWp() const{ return dwp;};
-  virtual void set(const double &_r0, const double &_r, const double &_dr, const double &_ddr, const double &_integR, const double& _dRdT, const double& _ddRdTT) final
+  virtual void set(const double &_r0, const double &_r, const double &_dr, const double &_ddr, const double &_integR, 
+                    const double& _dRdT, const double& _ddRdTT, const double& _ddRdT) final
   {
     R0 = _r0;
     R=_r;
@@ -61,6 +64,7 @@ protected:
     integR=_integR;
     dRdT = _dRdT;
     ddRdTT = _ddRdTT;
+    ddRdT = _ddRdT;
   }
   virtual void setScaleFactor(double _wp, double _dwp) final
   {
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.cpp b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
index deb6de3487d4ca5ae472debd166498fbd64f3acb..b7d279379c0b11218a0ae93c00c66ed0dfe43360 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.cpp
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
@@ -14,7 +14,7 @@
 #include "STensorOperations.h"
 
 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.)
+      _irreversibleEnergy(0.),_DirreversibleEnergyDF(0.), _viscousEnergyPart(0.), _dElasticEnergyPartdF(0.), _dViscousEnergyPartdF(0.), _elasticBulkPropertyScaleFactor(1.), _elasticShearPropertyScaleFactor(1.), _intA(0.), _intB(0.)
 {
   _A.clear();
   _B.clear();
@@ -28,7 +28,7 @@ IPHyperViscoElastic::IPHyperViscoElastic(const IPHyperViscoElastic& src): IPVari
     _N(src._N),_A(src._A),_B(src._B),_elasticEnergy(src._elasticEnergy), _kirchhoff(src._kirchhoff),
     _irreversibleEnergy(src._irreversibleEnergy),_DirreversibleEnergyDF(src._DirreversibleEnergyDF),
     _viscousEnergyPart(src._viscousEnergyPart), _dElasticEnergyPartdF(src._dElasticEnergyPartdF), 
-    _dViscousEnergyPartdF(src._dViscousEnergyPartdF), _elasticBulkPropertyScaleFactor(src._elasticBulkPropertyScaleFactor), _elasticShearPropertyScaleFactor(src._elasticShearPropertyScaleFactor)
+    _dViscousEnergyPartdF(src._dViscousEnergyPartdF), _elasticBulkPropertyScaleFactor(src._elasticBulkPropertyScaleFactor), _elasticShearPropertyScaleFactor(src._elasticShearPropertyScaleFactor),_intA(src._intA),_intB(src._intB)
 
 {
 
@@ -51,6 +51,8 @@ IPHyperViscoElastic& IPHyperViscoElastic::operator =(const IPVariable& src){
     _dViscousEnergyPartdF = psrc->_dViscousEnergyPartdF;
     _elasticBulkPropertyScaleFactor= psrc->_elasticBulkPropertyScaleFactor;
     _elasticShearPropertyScaleFactor= psrc->_elasticShearPropertyScaleFactor;
+    _intA= psrc->_intA;
+    _intB= psrc->_intB;
   }
   return *this;
 };
@@ -70,6 +72,8 @@ void IPHyperViscoElastic::restart() {
   restartManager::restart(_dViscousEnergyPartdF);
   restartManager::restart(_elasticBulkPropertyScaleFactor);
   restartManager::restart(_elasticShearPropertyScaleFactor);
+  restartManager::restart(_intA);
+  restartManager::restart(_intB);
 };
 
 void IPHyperViscoElastic::getViscoElasticStrain(int i, STensor3& Ev) const
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.h b/NonLinearSolver/internalPoints/ipHyperelastic.h
index e15a2742f16b6b43abeafc0ac32f111fc67f4f2e..8573370572505414133c3c7ee7d59fd248a1cd23 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.h
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.h
@@ -31,6 +31,8 @@ class IPHyperViscoElastic : public IPVariableMechanics{
     
     double _elasticBulkPropertyScaleFactor;
     double _elasticShearPropertyScaleFactor;
+    double _intA; // intA = psi_ExtraBranch/Kinf
+    double _intB; // intB = psi_ExtraBranch/Ginf
     
   protected:
     //For energy sources
diff --git a/NonLinearSolver/internalPoints/ipKinematicHardening.cpp b/NonLinearSolver/internalPoints/ipKinematicHardening.cpp
index 923b60aed8d69b75728abdc9d0f3199a14db3bb2..5b087c015900df0d8b35cc784fc9ed7ddf93f979 100644
--- a/NonLinearSolver/internalPoints/ipKinematicHardening.cpp
+++ b/NonLinearSolver/internalPoints/ipKinematicHardening.cpp
@@ -10,7 +10,7 @@
 
 #include "ipKinematicHardening.h"
 
-IPKinematicHardening::IPKinematicHardening(): R(0), dR(0), ddR(0), dRdT(0.), ddRddT(0.), _isSaturated(false)
+IPKinematicHardening::IPKinematicHardening(): R(0), dR(0), ddR(0), dRdT(0.), ddRdTT(0.), ddRdT(0.), _isSaturated(false)
 {
 
 }
@@ -21,7 +21,8 @@ IPKinematicHardening::IPKinematicHardening(const IPKinematicHardening &source)
   dR     = source.dR;
   ddR    = source.ddR;
   dRdT   = source.dRdT;
-  ddRddT   = source.ddRddT;
+  ddRdTT   = source.ddRdTT;
+  ddRdT   = source.ddRdT;
   _isSaturated= source._isSaturated;
 }
 
@@ -31,7 +32,8 @@ IPKinematicHardening &IPKinematicHardening::operator=(const IPKinematicHardening
   dR     = source.dR;
   ddR    = source.ddR;
   dRdT   = source.dRdT;
-  ddRddT   = source.ddRddT;
+  ddRdTT   = source.ddRdTT;
+  ddRdT   = source.ddRdT;
   _isSaturated = source._isSaturated;
   return *this;
 }
@@ -42,7 +44,8 @@ void IPKinematicHardening::restart()
   restartManager::restart(dR);
   restartManager::restart(ddR);
   restartManager::restart(dRdT);
-  restartManager::restart(ddRddT);
+  restartManager::restart(ddRdTT);
+  restartManager::restart(ddRdT);
   restartManager::restart(_isSaturated);
   return;
 }
diff --git a/NonLinearSolver/internalPoints/ipKinematicHardening.h b/NonLinearSolver/internalPoints/ipKinematicHardening.h
index f47257462cc9845ef513d2c273156b131e8ed6c3..29b49edd5762df0b3f76c2e9cb1a7e83a4f41050 100644
--- a/NonLinearSolver/internalPoints/ipKinematicHardening.h
+++ b/NonLinearSolver/internalPoints/ipKinematicHardening.h
@@ -16,10 +16,11 @@
 class IPKinematicHardening{
   protected:
     double R;
-    double dR;
-    double ddR;
-    double dRdT; // temeprature dependence
-    double ddRddT;
+    double dR;   // dR/dg  where, g = gamma (eqv. plastic strain)
+    double ddR;  // ddR/dgdg
+    double dRdT; // temperature dependence
+    double ddRdTT; // ddR/dTdT
+    double ddRdT; // ddR/dgdT
     bool _isSaturated;
     
 
@@ -39,14 +40,16 @@ class IPKinematicHardening{
     virtual double getDR() const {return dR;}
     virtual double getDDR() const {return ddR;};
     virtual double getDRDT() const{ return dRdT;};
-    virtual double getDDRDDT() const{ return ddRddT;};
-    virtual void set(const double &_r, const double &_dr, const double& _ddr, const double& _dRdT, const double& _ddRddT)
+    virtual double getDDRDTT() const{ return ddRdTT;};
+    virtual double getDDRDT() const{ return ddRdT;};
+    virtual void set(const double &_r, const double &_dr, const double& _ddr, const double& _dRdT, const double& _ddRdTT, const double& _ddRdT)
     {
       R=_r;
       dR=_dr;
       ddR = _ddr;
       dRdT = _dRdT;
-      ddRddT = _ddRddT;
+      ddRdTT = _ddRdTT;
+      ddRdT = _ddRdT;
     }
 };
 
diff --git a/NonLinearSolver/internalPoints/ipMullinsEffect.cpp b/NonLinearSolver/internalPoints/ipMullinsEffect.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b4bba50b44bd1a21b66e4ab886ec41bb20f8e9ba
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipMullinsEffect.cpp
@@ -0,0 +1,48 @@
+//
+// Description: storing class for Mullins Effect
+//
+//
+// Author:  <Ujwal Kishore J.>, (C) 2023
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "ipMullinsEffect.h"
+
+IPMullinsEffect::IPMullinsEffect(): eta(1.0), DetaDpsi(0.), DDetaDpsipsi(0.), DetaDT(0.), DDetaDTT(0.), psiMax(0.)
+{
+
+}
+
+IPMullinsEffect::IPMullinsEffect(const IPMullinsEffect &source)
+{
+  eta      = source.eta;
+  DetaDpsi     = source.DetaDpsi;
+  DDetaDpsipsi    = source.DDetaDpsipsi;
+  DetaDT   = source.DetaDT;
+  DDetaDTT   = source.DDetaDTT;
+  psiMax = source.psiMax;
+}
+
+IPMullinsEffect &IPMullinsEffect::operator=(const IPMullinsEffect &source)
+{
+  eta      = source.eta;
+  DetaDpsi     = source.DetaDpsi;
+  DDetaDpsipsi    = source.DDetaDpsipsi;
+  DetaDT   = source.DetaDT;
+  DDetaDTT   = source.DDetaDTT;
+  psiMax = source.psiMax;
+  return *this;
+}
+
+void IPMullinsEffect::restart()
+{
+  restartManager::restart(eta);
+  restartManager::restart(DetaDpsi);
+  restartManager::restart(DDetaDpsipsi);
+  restartManager::restart(DetaDT);
+  restartManager::restart(DDetaDTT);
+  restartManager::restart(psiMax);
+  return;
+}
diff --git a/NonLinearSolver/internalPoints/ipMullinsEffect.h b/NonLinearSolver/internalPoints/ipMullinsEffect.h
new file mode 100644
index 0000000000000000000000000000000000000000..1aa95461375b460ccedf28873e91bab4606aa62e
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipMullinsEffect.h
@@ -0,0 +1,55 @@
+//
+// Description: storing class for Mullins Effect
+//
+//
+// Author:  <Ujwal Kishore J.>, (C) 2023
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef IPMULLINSEFFECT_H_
+#define IPMULLINSEFFECT_H_
+
+#include "ipHardening.h"
+
+class IPMullinsEffect{
+    
+  protected:
+    double eta; // scaling variable
+    double DetaDpsi;   
+    double DDetaDpsipsi;  
+    double DetaDT; 
+    double DDetaDTT; 
+    double psiMax;
+
+  public:
+    IPMullinsEffect();
+    IPMullinsEffect(const IPMullinsEffect &source);
+    virtual IPMullinsEffect &operator=(const IPMullinsEffect &source);
+    virtual ~IPMullinsEffect(){}
+    virtual void restart();
+
+    virtual IPMullinsEffect * clone() const {return new IPMullinsEffect(*this);};
+
+    virtual double getEta() const {return eta;}
+    virtual double getDetaDpsi() const {return DetaDpsi;}
+    virtual double getDDetaDpsipsi() const {return DDetaDpsipsi;};
+    virtual double getDetaDT() const{ return DetaDT;};
+    virtual double getDDetaDTT() const{ return DDetaDTT;};
+    virtual double getpsiMax() const{ return psiMax;};
+    virtual void set(const double &_eta, const double &_DetaDpsi, const double& _DDetaDpsipsi, const double& _DetaDT, const double& _DDetaDTT)
+    {
+      eta=_eta;
+      DetaDpsi=_DetaDpsi;
+      DDetaDpsipsi = _DDetaDpsipsi;
+      DetaDT = _DetaDT;
+      DDetaDTT = _DDetaDTT;
+    }
+    virtual void setPsiMax(const double &_psiMax){
+      psiMax = _psiMax;  
+    }
+};
+
+
+#endif // IPMULLINSEFFECT_H_
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp
index 3b9e0ae670bb61dc0824d24e4a26401cff828c15..83eb3464878373fda590380408280cd5ef495a26 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp
@@ -15,10 +15,11 @@
 
 IPNonLinearTVE::IPNonLinearTVE(const J2IsotropicHardening* comp,
                     const J2IsotropicHardening* trac,
-                    const kinematicHardening* kin, const int N): IPHyperViscoElastoPlastic(comp,trac,kin,N), // IPHyperViscoElastic(N), 
+                    const kinematicHardening* kin, const int N, const mullinsEffect* mullins): IPHyperViscoElastoPlastic(comp,trac,kin,N), // IPHyperViscoElastic(N), 
                                         _T(298.15),_devDE(0.),_trDE(0.),_DE(0.),_DcorKirDT(0.),_DDcorKirDTT(0.),
                                         _mechSrcTVE(0.),_DmechSrcTVEdT(0.),_DmechSrcTVEdF(0.),
-                                        _thermalEnergy(0.),_dtShift(0.),_DdtShiftDT(0.),_DDdtShiftDDT(0.){
+                                        _thermalEnergy(0.),_dtShift(0.),_DdtShiftDT(0.),_DDdtShiftDDT(0.), _psiMax(0.), 
+                                        _trCorKirinf_TVE(0.), _devCorKirinf_TVE(0.), _corKirExtra(0.), _mullinsDamage(0.){
     _devOGammai.clear();
     _trOGammai.clear();
     _devDOGammaiDT.clear();
@@ -53,6 +54,9 @@ IPNonLinearTVE::IPNonLinearTVE(const J2IsotropicHardening* comp,
         _G.push_back(0.);
     }
     
+    _ipMullinsEffect = NULL;
+    if (mullins!= NULL)  mullins->createIPVariable(_ipMullinsEffect);
+    
 };
 
 IPNonLinearTVE::IPNonLinearTVE(const IPNonLinearTVE& src): IPHyperViscoElastoPlastic(src), //IPHyperViscoElastic(src), 
@@ -63,7 +67,15 @@ IPNonLinearTVE::IPNonLinearTVE(const IPNonLinearTVE& src): IPHyperViscoElastoPla
             _mechSrcTVE(src._mechSrcTVE),_DmechSrcTVEdT(src._DmechSrcTVEdT),_DmechSrcTVEdF(src._DmechSrcTVEdF),
             _C(src._C),_D(src._D), _E(src._E), _F(src._F), _G(src._G),
             _thermalEnergy(src._thermalEnergy),
-            _dtShift(src._dtShift),_DdtShiftDT(src._DdtShiftDT),_DDdtShiftDDT(src._DDdtShiftDDT){};
+            _dtShift(src._dtShift),_DdtShiftDT(src._DdtShiftDT),_DDdtShiftDDT(src._DDdtShiftDDT), _psiMax(src._psiMax),
+            _trCorKirinf_TVE(src._trCorKirinf_TVE), _devCorKirinf_TVE(src._devCorKirinf_TVE), _corKirExtra(src._corKirExtra), _mullinsDamage(src._mullinsDamage){
+                
+    if (src._ipMullinsEffect != NULL)
+        _ipMullinsEffect = dynamic_cast<IPMullinsEffect*>(src._ipMullinsEffect->clone());
+    else
+        _ipMullinsEffect = NULL;                
+                
+};
             
 IPNonLinearTVE& IPNonLinearTVE::operator=(const IPVariable& src)
 {
@@ -100,10 +112,30 @@ IPNonLinearTVE& IPNonLinearTVE::operator=(const IPVariable& src)
     _dtShift = psrc->_dtShift;
     _DdtShiftDT = psrc->_DdtShiftDT;
     _DDdtShiftDDT = psrc->_DDdtShiftDDT;
+    _psiMax = psrc->_psiMax;
+    _trCorKirinf_TVE = psrc->_trCorKirinf_TVE;
+    _devCorKirinf_TVE = psrc->_devCorKirinf_TVE;
+    _corKirExtra = psrc->_corKirExtra;
+    _mullinsDamage = psrc->_mullinsDamage;
+    
+    if ( psrc->_ipMullinsEffect != NULL) {
+      if (_ipMullinsEffect == NULL){
+        _ipMullinsEffect = dynamic_cast<IPMullinsEffect*>(psrc->_ipMullinsEffect->clone());
+      }
+      else{
+        _ipMullinsEffect->operator=(*dynamic_cast<const IPMullinsEffect*>(psrc->_ipMullinsEffect));
+      }
+    }
+    
   }
   return *this;
 }
 
+IPNonLinearTVE::~IPNonLinearTVE(){
+  if (_ipMullinsEffect != NULL) delete _ipMullinsEffect;
+  _ipMullinsEffect = NULL;
+};
+
 double IPNonLinearTVE::defoEnergy() const
 {
   return IPHyperViscoElastic::defoEnergy();
@@ -148,4 +180,23 @@ void IPNonLinearTVE::restart(){
   restartManager::restart(_dtShift);
   restartManager::restart(_DdtShiftDT);
   restartManager::restart(_DDdtShiftDDT);
-}
\ No newline at end of file
+  restartManager::restart(_psiMax);
+  restartManager::restart(_trCorKirinf_TVE);
+  restartManager::restart(_devCorKirinf_TVE);
+  restartManager::restart(_corKirExtra);
+  restartManager::restart(_mullinsDamage);
+  
+  if (_ipMullinsEffect != NULL)
+   restartManager::restart(_ipMullinsEffect);
+}
+
+const IPMullinsEffect& IPNonLinearTVE::getConstRefToIPMullinsEffect() const{
+  if(_ipMullinsEffect==NULL)
+      Msg::Error("IPNonLinearTVE: _ipMullinsEffect not initialized");
+  return *_ipMullinsEffect;
+};
+IPMullinsEffect& IPNonLinearTVE::getRefToIPMullinsEffect(){
+  if(_ipMullinsEffect==NULL)
+      Msg::Error("IPNonLinearTVE: _ipMullinsEffect not initialized");
+  return *_ipMullinsEffect;
+};
\ No newline at end of file
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVE.h b/NonLinearSolver/internalPoints/ipNonLinearTVE.h
index c6e6d68223f0ba862d0b726fac748d0acc7af394..25962478ae0eee79eeccc641903a4162fff5bc61 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVE.h
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVE.h
@@ -16,7 +16,7 @@
 #include "kinematicHardening.h"
 #include "STensor3.h"
 #include "STensor43.h"
-
+#include "mullinsEffect.h"
 
 // class IPNonLinearTVE : public IPHyperViscoElastic{
 class IPNonLinearTVE : public IPHyperViscoElastoPlastic{
@@ -32,6 +32,10 @@ class IPNonLinearTVE : public IPHyperViscoElastoPlastic{
         double _DmechSrcTVEdT;
         STensor3 _DmechSrcTVEdF;
         
+        double _trCorKirinf_TVE;
+        STensor3 _devCorKirinf_TVE;
+        STensor3 _corKirExtra;
+        
         // Viscoelastic Strain
         std::vector<STensor3> _devOGammai;   // dev viscoelastic strain for each branch
         std::vector<double> _trOGammai;      // tr viscoelastic strain for each branch
@@ -60,13 +64,18 @@ class IPNonLinearTVE : public IPHyperViscoElastoPlastic{
         double _DdtShiftDT;
         double _DDdtShiftDDT;
         
+        // Mullins Effect IP
+        IPMullinsEffect* _ipMullinsEffect;
+        double _mullinsDamage;
+        double _psiMax; // maximum strain energy
+        
     public:
         IPNonLinearTVE(const J2IsotropicHardening* comp,
                     const J2IsotropicHardening* trac,
-                    const kinematicHardening* kin, const int N);
+                    const kinematicHardening* kin, const int N, const mullinsEffect* mullins);
         IPNonLinearTVE(const IPNonLinearTVE& src);
         virtual IPNonLinearTVE& operator=(const IPVariable& src);
-        virtual ~IPNonLinearTVE(){};
+        virtual ~IPNonLinearTVE();
         
         virtual std::vector<STensor3>& getRefToDevViscoElasticOverStrain() {return _devOGammai;};
         virtual const std::vector<STensor3>& getConstRefToDevViscoElasticOverStrain() const {return _devOGammai;};
@@ -126,6 +135,9 @@ class IPNonLinearTVE : public IPHyperViscoElastoPlastic{
         virtual double& getShiftedTimeStepTempDoubleDerivative() {return _DDdtShiftDDT;};
         virtual const double& getConstShiftedTimeStepTempDoubleDerivative() const {return _DDdtShiftDDT;};
         
+        virtual const IPMullinsEffect& getConstRefToIPMullinsEffect() const;
+        virtual IPMullinsEffect& getRefToIPMullinsEffect();
+        
         virtual double defoEnergy() const;
         virtual double getThermalEnergy() const {return _thermalEnergy;};                       // Added _thermalEnergy
         // virtual double getConstRefToFractureEnergy() const {return _fracEnergy;};            // Added   - Unused (edit this because its neither "const" nor "ref" here)
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
index 97c878a547f7e4c43ab6d81cfe8eef0109c71076..4f6c567a7dff405c81df77cba1590959a832a913 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
@@ -12,12 +12,13 @@
 #include "ipNonLinearTVP.h"
 
 IPNonLinearTVP::IPNonLinearTVP(const J2IsotropicHardening* comp, const J2IsotropicHardening* trac,
-                                const kinematicHardening* kin, const int N):IPNonLinearTVE(comp,trac,kin,N),
+                                const kinematicHardening* kin, const int N, const mullinsEffect* mullins):IPNonLinearTVE(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.),
+                                _ModMandel(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.)
+                                _dPlasticEnergyPartdT(0.),_dElasticEnergyPartdT(0.),_dViscousEnergyPartdT(0.),
+                                _IsoHardForce_simple(0.), _dIsoHardForcedT_simple(0.), _dIsoHardForcedF_simple(0.)
 {
     
     _IsoHardForce.clear(); _dIsoHardForcedT.clear(); _dIsoHardForcedF.clear();
@@ -38,9 +39,12 @@ IPNonLinearTVP::IPNonLinearTVP(const IPNonLinearTVP& src):IPNonLinearTVE(src),
                                 _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),
+                                _GammaN(src._GammaN), _dGammaNdT(src._dGammaNdT), _dGammaNdF(src._dGammaNdF),
                                 _DModMandelDF(src._DModMandelDF), _DbackSigDF(src._DbackSigDF),
                                 _dPlasticEnergyPartdT(src._dPlasticEnergyPartdT),_dElasticEnergyPartdT(src._dElasticEnergyPartdT),
-                                _dViscousEnergyPartdT(src._dViscousEnergyPartdT)      
+                                _dViscousEnergyPartdT(src._dViscousEnergyPartdT), 
+                                _IsoHardForce_simple(src._IsoHardForce_simple), 
+                                _dIsoHardForcedT_simple(src._dIsoHardForcedT_simple), _dIsoHardForcedF_simple(src._dIsoHardForcedF_simple)      
 {
     
 };
@@ -71,9 +75,15 @@ IPNonLinearTVP& IPNonLinearTVP::operator =(const IPVariable &source){
     _DbackSigDT = ps->_DbackSigDT;
     _DbackSigDF = ps->_DbackSigDF;
     _DphiPDF = ps->_DphiPDF;
+    _GammaN = ps->_GammaN;
+    _dGammaNdT = ps->_dGammaNdT;
+    _dGammaNdF = ps->_dGammaNdF;
     _dPlasticEnergyPartdT = ps->_dPlasticEnergyPartdT;
     _dElasticEnergyPartdT = ps->_dElasticEnergyPartdT;
     _dViscousEnergyPartdT = ps->_dViscousEnergyPartdT;
+    _IsoHardForce_simple = ps->_IsoHardForce_simple;
+    _dIsoHardForcedT_simple = ps->_dIsoHardForcedT_simple;
+    _dIsoHardForcedF_simple = ps->_dIsoHardForcedF_simple;
 
   }
   return *this;
@@ -106,8 +116,14 @@ void IPNonLinearTVP::restart() {
   restartManager::restart(_DbackSigDT);
   restartManager::restart(_DbackSigDF);
   restartManager::restart(_DphiPDF);
+  restartManager::restart(_GammaN);
+  restartManager::restart(_dGammaNdT);
+  restartManager::restart(_dGammaNdF);
   restartManager::restart(_dPlasticEnergyPartdT);
   restartManager::restart(_dElasticEnergyPartdT);
   restartManager::restart(_dViscousEnergyPartdT);
+  restartManager::restart(_IsoHardForce_simple);
+  restartManager::restart(_dIsoHardForcedT_simple);
+  restartManager::restart(_dIsoHardForcedF_simple);
   return;
 }
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.h b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
index 7deb4ee21be3d96f7fc3c5c7dac93f5350588142..4f55f692d6b56310189f594d4849cde915247df1 100644
--- a/NonLinearSolver/internalPoints/ipNonLinearTVP.h
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
@@ -16,7 +16,7 @@
 #include "kinematicHardening.h"
 #include "STensor3.h"
 #include "STensor43.h"
-
+#include "mullinsEffect.h"
 
 class IPNonLinearTVP : public IPNonLinearTVE{
     
@@ -26,6 +26,9 @@ class IPNonLinearTVP : public IPNonLinearTVE{
         double _DirreversibleEnergyDT; 
         double _mechSrcTVP;
         double _DmechSrcTVPdT;
+        
+        double _IsoHardForce_simple;
+        double _dIsoHardForcedT_simple;
         std::vector<double> _IsoHardForce;
         std::vector<double> _dIsoHardForcedT;
         std::vector<double> _ddIsoHardForcedTT;
@@ -39,11 +42,16 @@ class IPNonLinearTVP : public IPNonLinearTVE{
         STensor3 _DModMandelDT;
         STensor3 _DbackSigDT;
         STensor3 _DmechSrcTVPdF;
+        STensor3 _dIsoHardForcedF_simple;
         std::vector<STensor3> _dIsoHardForcedF;
         
         STensor43 _DbackSigDF;
         STensor43 _DModMandelDF;
         STensor3 _DphiPDF; // need this for mechSrc
+        
+        STensor3 _GammaN;
+        STensor3 _dGammaNdT;
+        STensor43 _dGammaNdF;
 
         
     protected:
@@ -53,7 +61,7 @@ class IPNonLinearTVP : public IPNonLinearTVE{
     public:
         IPNonLinearTVP(const J2IsotropicHardening* comp,
                     const J2IsotropicHardening* trac,
-                    const kinematicHardening* kin, const int N);
+                    const kinematicHardening* kin, const int N, const mullinsEffect* mullins);
         IPNonLinearTVP(const IPNonLinearTVP& src);
         virtual IPNonLinearTVP& operator =(const IPVariable &source);
         virtual ~IPNonLinearTVP();
diff --git a/NonLinearSolver/materialLaw/CMakeLists.txt b/NonLinearSolver/materialLaw/CMakeLists.txt
index ae6e1f09840bdca319c41b24abf1ad70df618255..f0652edb953c17ee350e0eb36feee1c914817f8c 100644
--- a/NonLinearSolver/materialLaw/CMakeLists.txt
+++ b/NonLinearSolver/materialLaw/CMakeLists.txt
@@ -104,6 +104,7 @@ set(SRC
   mlawNonLinearTVM.cpp
   mlawNonLinearTVE.cpp
   mlawNonLinearTVP.cpp
+  mullinsEffect.cpp
   #  src/op_eshelby.cpp
    # Headers without cpp change this ??
   ID.h
diff --git a/NonLinearSolver/materialLaw/j2IsotropicHardening.cpp b/NonLinearSolver/materialLaw/j2IsotropicHardening.cpp
index 877081750e1f8bee4339d3918a72a83d1e05e020..2035b01297c78953b7a256c376f43a4612494682 100644
--- a/NonLinearSolver/materialLaw/j2IsotropicHardening.cpp
+++ b/NonLinearSolver/materialLaw/j2IsotropicHardening.cpp
@@ -86,7 +86,7 @@ void PerfectlyPlasticJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHardeni
 
 void PerfectlyPlasticJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT =0, ddRdTT=0.;
+  double dR=0, ddR=0, intR=0, dRdT =0, ddRdTT=0., ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -105,12 +105,12 @@ void PerfectlyPlasticJ2IsotropicHardening::hardening(double p0, const IPJ2Isotro
       intR=0.5*tol*p*p+getYield0()*p;
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-------------------------------------added
 void PerfectlyPlasticJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -129,9 +129,10 @@ void PerfectlyPlasticJ2IsotropicHardening::hardening(double p0, const IPJ2Isotro
       intR=0.5*tol*p*p+getYield0(T)*p;
       dRdT=getDYield0DT(T);
       ddRdTT=getDDYield0DTT(T);
+      ddRdT=0.;
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------end
 J2IsotropicHardening * PerfectlyPlasticJ2IsotropicHardening::clone() const
@@ -217,7 +218,7 @@ void PowerLawJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHardening* &ipv
 void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
  // double tol=1.e-16;
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0,ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -245,12 +246,12 @@ void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHarde
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //--------------------------------------------------added
 void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -288,22 +289,29 @@ void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHarde
     }
 
     double dhdT=_h*_temFunc_h->getDiff(T);
+    double ddhdTT=_h*_temFunc_h->getDoubleDiff(T);
     double dhexpdT=_hexp*_temFunc_hexp->getDiff(T);
+    double ddhexpdTT=_hexp*_temFunc_hexp->getDoubleDiff(T);
     if(p<tol && dhexpdT != 0)
     {
       dRdT=-1e20;
+      ddRdTT=-1e20;
     }
     else if (p<tol && dhexpdT == 0)
     {
       dRdT=getDYield0DT(T)+dhdT*pow(p,hexpT);
+      ddRdTT=getDDYield0DTT(T)+ddhdTT*pow(p,hexpT);
+      ddRdT = 0.;
     }
     else
     {
       dRdT=getDYield0DT(T)+dhdT*pow(p,hexpT)+hT*dhexpdT*log(p)*pow(p,hexpT);
+      ddRdTT=getDDYield0DTT(T)+ddhdTT*pow(p,hexpT)+2.*dhdT*dhexpdT*log(p)*pow(p,hexpT)+hT*( ddhexpdTT*log(p)*pow(p,hexpT) + pow(p,hexpT)*pow(dhexpdT*log(p),2) );
+      ddRdT=dhdT*hexpT*pow(p,hexpT-1) + hT*dhexpdT*( pow(p,hexpT-1) + hexpT*(hexpT-1)*pow(p,hexpT-1)*log(p) );
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //--------------------------------------------------------------------------end
 J2IsotropicHardening * PowerLawJ2IsotropicHardening::clone() const
@@ -388,7 +396,7 @@ void ExponentialJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHardening* &
 
 void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -416,12 +424,12 @@ void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHa
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------------added
 void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -459,14 +467,16 @@ void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHa
     {
       dRdT=getDYield0DT(T);
       ddRdTT=getDDYield0DTT(T);
+      ddRdT=0.;
     }
     else
     {
       dRdT=getDYield0DT(T)+dhdT*(1-exp(-hexpT*p))+hT*(dhexpdT*p*exp(-hexpT*p));
       ddRdTT=getDDYield0DTT(T)+ddhdTT*(1-exp(-hexpT*p))+dhdT*(dhexpdT*p*exp(-hexpT*p))+dhdT*(dhexpdT*p*exp(-hexpT*p))+hT*(ddhexpdTT*p*exp(-hexpT*p)-dhexpdT*dhexpdT*p*p*exp(-hexpT*p));
+      ddRdT=dhdT*hexpT*exp(-hexpT*p) + hT*dhexpdT*(exp(-hexpT*p)-pow(hexpT,2)*exp(-hexpT*p));
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 
@@ -558,7 +568,7 @@ void EnhancedExponentialJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHard
 
 void EnhancedExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -582,7 +592,7 @@ void EnhancedExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Iso
 
     intR= ipvprev.getIntegR()+ R*(p-p0);
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------------added
 void EnhancedExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
@@ -681,7 +691,7 @@ void ExponentialSeriesJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHarden
 
 void ExponentialSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0,ddRdT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -701,12 +711,12 @@ void ExponentialSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
       if(fabs(_hexp[i])!=0) intR+=_h[i]*(exp(-_hexp[i]*p)-exp(0))/(_hexp[i]);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------------added
 void ExponentialSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -733,7 +743,7 @@ void ExponentialSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
       dRdT += dhdT*(1-tmp)+hT*(dhexpdT*p*tmp);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 
@@ -821,7 +831,7 @@ void SwiftJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHardening* &ipv) c
 
 void SwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -847,12 +857,12 @@ void SwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardenin
       if(fabs(_hexp+1.)!=0 && fabs(_h)!=0.) intR=R*tmp/(_hexp+1.)/_h;
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //----------------------added
 void SwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0, ddRdT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -890,7 +900,7 @@ void SwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardenin
       dRdT= R*getDYield0DT(T)/getYield0(T) + R*dhexpdT*log(tmp) + R*hexpT*dhdT*(p-_p0)/tmp;
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //------------------------------end
@@ -943,7 +953,7 @@ void MultipleSwiftJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHardening*
 
 void MultipleSwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -968,13 +978,13 @@ void MultipleSwiftJ2IsotropicHardening::hardening(double p0, const IPJ2Isotropic
 			intR = ipvprev.getIntegR()+ 0.5*(R+ipvprev.getR())*(p-p0); // approximation
 		}
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //----------------------added
 void MultipleSwiftJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
 	// temperature dependence has not been implemented
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1011,7 +1021,7 @@ void MultipleSwiftJ2IsotropicHardening::hardening(double p0, const IPJ2Isotropic
       dRdT = DsigY1DT*pow(pp,_n1);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //------------------------------end
@@ -1120,7 +1130,7 @@ void LinearExponentialJ2IsotropicHardening::createIPVariable(IPJ2IsotropicHarden
 void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
 
-  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
+  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1148,13 +1158,13 @@ void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
       if(fabs(_hexp)!=0) intR+=_h2*(exp(-_hexp*p)-exp(0))/(_hexp);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------added
 void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
 
-  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
+  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1162,6 +1172,8 @@ void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
     dR = 0.;
     ddR = 0.;
     intR = ipvprev.getIntegR()+ R*(p-p0);
+    dRdT = 0.;
+    ddRdTT = 0.;
   }
   else {
     double tol=1.e-16;
@@ -1191,19 +1203,20 @@ void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
       ddRdTT = getDDYield0DTT(T);
     }
     else{
+      double tmp = exp(-hexpT*p);
       double dh1dT=_h1*_temFunc_h1->getDiff(T);
       double ddh1dTT=_h1*_temFunc_h1->getDoubleDiff(T);
       double dhexpdT=_hexp*_temFunc_hexp->getDiff(T);
       double ddhexpdTT=_hexp*_temFunc_hexp->getDoubleDiff(T);
       double dh2dT=_h2*_temFunc_h2->getDiff(T);
       double ddh2dTT=_h2*_temFunc_h2->getDoubleDiff(T);
-      dRdT=getDYield0DT(T)+dh1dT*p+dh2dT*(1-exp(-hexpT*p))+h2T*(dhexpdT*p*exp(-hexpT*p));
-      ddRdTT=getDDYield0DTT(T)+ddh1dTT*p+ddh2dTT*(1-exp(-hexpT*p))+dh2dT*(dhexpdT*p*exp(-hexpT*p))
-            +dh2dT*(dhexpdT*p*exp(-hexpT*p))+h2T*(ddhexpdTT*p*exp(-hexpT*p)-dhexpdT*p*dhexpdT*p*exp(-hexpT*p));
+      dRdT=getDYield0DT(T)+dh1dT*p+dh2dT*(1-tmp)+h2T*(dhexpdT*p*tmp);
+      ddRdTT=getDDYield0DTT(T)+ddh1dTT*p+ddh2dTT*(1-tmp)+dh2dT*(dhexpdT*p*tmp)
+            +dh2dT*(dhexpdT*p*tmp)+h2T*(ddhexpdTT*p*tmp-dhexpdT*p*dhexpdT*p*tmp);
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //----------------------------end
@@ -1256,7 +1269,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
     LinearExponentialJ2IsotropicHardening::hardening(p0,ipvprev,p,ipv);
   }
   else{
-    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
+    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0., ddRdT=0.;
     double R0 = getYield0();
     double R = R0;
     if (ipvprev.isSaturated()){
@@ -1274,7 +1287,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
       ddR = dR*_n3*_h3/(1+_h3*(p-_p3)) - R*_n3*_h3*_h3/((1+_h3*(p-_p3))*(1+_h3*(p-_p3)));
       intR = ipvprev.getIntegR()+ 0.5*(R+ipvprev.getR())*(p-p0); // approximation
     }
-    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
   }
 }
 //-----------------------------added
@@ -1284,7 +1297,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
     LinearExponentialJ2IsotropicHardening::hardening(p0,ipvprev,p,T,ipv);
   }
   else{
-    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
+    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.,ddRdT=0.;
     double R0 = getYield0(T);
     double R = R0;
     if (ipvprev.isSaturated()){
@@ -1309,7 +1322,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
       dRdT = getYield0(T)*pow(1+_h3*(p-_p3),_n3);
 
     }
-    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
   }
 }
 
@@ -1459,7 +1472,7 @@ void LinearFollowedByExponentialJ2IsotropicHardening::createIPVariable(IPJ2Isotr
 
 void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.);
+  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.), ddRdT(0.);
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1502,12 +1515,12 @@ void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const
       intR = ipvprev.getIntegR()+ R*(p-p0);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------added
 void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.);
+  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.),ddRdT(0.);
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1583,7 +1596,7 @@ void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //----------------------------end
@@ -1695,7 +1708,7 @@ void LinearFollowedByPowerLawJ2IsotropicHardening::createIPVariable(IPJ2Isotropi
 
 void LinearFollowedByPowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1725,12 +1738,12 @@ void LinearFollowedByPowerLawJ2IsotropicHardening::hardening(double p0, const IP
       intR += R*p /(_hexp+1.) -((getYield0()+_h1*_pexp)*_pexp/(_hexp+1.));
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------------------added
 void LinearFollowedByPowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1784,7 +1797,7 @@ void LinearFollowedByPowerLawJ2IsotropicHardening::hardening(double p0, const IP
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //--------------------------------end
@@ -1823,7 +1836,7 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::createIPVariable(IPJ2
 
 void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1856,12 +1869,12 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0,
       intR = getYield0()*_p1 + 0.5*_H*_p1*_p1 + sy2*_p2/(_n1+1) - sy1*_p1/(_n1+1) + R*p/(_n2+1) - sy2*_p2/(_n2+1);;
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------------------------------added
 void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.,ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1900,7 +1913,7 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0,
     }
   }
 
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 
 }
 
@@ -1949,7 +1962,7 @@ void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
   //_coefficients.print("_coefficients");
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -1978,12 +1991,12 @@ void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
     else
       Msg::Error("order %d is not implemented PolynomialJ2IsotropicHaderning::hardening",_order);
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.,ddRdT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -2018,7 +2031,7 @@ void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
     dRdT = getDYield0DT(T);
     dRdT = getDDYield0DTT(T);
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 };
 
 
@@ -2078,7 +2091,7 @@ void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardeni
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2091,14 +2104,14 @@ void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardeni
     ddR = _K*(exp(p)-4.*exp(-2.*p));
     intR = _yield0*p +_K*(exp(p)+0.5*exp(-2.*p));
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-------------------------------added
 void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
   double R0 = getYield0(T);
   double R = R0;
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2119,7 +2132,7 @@ void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardeni
     dRdT=getDYield0DT(T)+dKdT*(exp(p)-exp(-2.*p));
     ddRdTT=getDDYield0DTT(T)+ddKdTT*(exp(p)-exp(-2.*p));
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //-------------------------------------end
@@ -2199,7 +2212,7 @@ void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.,ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2213,14 +2226,14 @@ void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening
     ddR = _K*2.*th*(th*th-1.)/(_p0*_p0);
     intR = _yield0*p +_K*_p0*log(cosh(p/_p0));
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //------------------------------added
 void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
   double R0 = getYield0(T);
   double R = R0;
-  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0., ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2246,7 +2259,7 @@ void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening
     ddRdTT=getDDYield0DTT(T)+ddKdTT*tanh(p/p0T)+2*dKdT*(1-th*th)*(-p*dp0dT/p0T/p0T)
             +KT*(-2*th*(1-th*th)*(-p*dp0dT/p0T/p0T)*(-p*dp0dT/p0T/p0T)+(1-th*th)*(-p*ddp0dTT/p0T/p0T+2*p*dp0dT*dp0dT/pow(p0T,3)));
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //------------------------------------------end
@@ -2298,7 +2311,7 @@ void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT=0., ddRdTT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0., ddRdTT=0., ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2314,14 +2327,14 @@ void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
       intR += getYield0()*p +_K[i]*_p0[i]*log(cosh(p/_p0[i]));
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //------------------------------added
 void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
   double R0 = getYield0(T);
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.,ddRdT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2339,7 +2352,7 @@ void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
       dRdT = getDDYield0DTT(T);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //------------------------------------------end
@@ -2511,7 +2524,7 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
 {
   double R0 = getYield0();
   double R = R0;
-  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.);
+  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.),ddRdT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2554,14 +2567,14 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
 
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 //-----------------------------added
 void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
 {
   double R0 = getYield0(T);
   double R = R0;
-  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.);
+  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.),ddRdT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2638,7 +2651,7 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT,ddRdT);
 }
 
 //----------------------------end
diff --git a/NonLinearSolver/materialLaw/kinematicHardening.cpp b/NonLinearSolver/materialLaw/kinematicHardening.cpp
index 92ca0d92d520c202330a01a6901cf07060ca2603..ec2a7b7c2121eeba524895ff8dc89bf377a5f707 100644
--- a/NonLinearSolver/materialLaw/kinematicHardening.cpp
+++ b/NonLinearSolver/materialLaw/kinematicHardening.cpp
@@ -92,7 +92,7 @@ void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardeni
     p = tol; 
   }  
   //_coefficients.print("_coefficients");
-  double R=0., dR=0., ddR=0., dRdT = 0., ddRddT = 0.;
+  double R=0., dR=0., ddR=0., dRdT = 0., ddRdTT = 0., ddRdT = 0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -132,7 +132,7 @@ void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardeni
     else
       Msg::Error("order %d is not implemented PolynomialJ2IsotropicHaderning::hardening",_order);
   }
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const
@@ -144,14 +144,15 @@ void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardeni
   }
   
   //_coefficients.print("_coefficients");
-  double R=0., dR=0., ddR=0., dRdT=0., ddRddT=0.;
+  double R=0., dR=0., ddR=0., dRdT=0., ddRdTT=0., ddRdT = 0.;
   
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
     ddR = 0.;
     dRdT = 0.;
-    ddRddT = 0.;
+    ddRdTT = 0.;
+    ddRdT = 0.;
   }
   else{
     if (_order == 1){
@@ -192,9 +193,9 @@ void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardeni
   dR *= _temFunc_K->getVal(T);
   ddR *= _temFunc_K->getVal(T);
   dRdT = R*_temFunc_K->getDiff(T);
-  ddRddT = R*_temFunc_K->getDoubleDiff(T);
+  ddRdTT = R*_temFunc_K->getDoubleDiff(T);
   
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 kinematicHardening * PolynomialKinematicHardening::clone() const
@@ -231,7 +232,7 @@ void PowerKinematicHardening::createIPVariable(IPKinematicHardening* &ipv) const
 void PowerKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const
 {
   
-  double dR=0., ddR=0., dRdT=0., ddRddT=0.;
+  double dR=0., ddR=0., dRdT=0., ddRdTT=0., ddRdT = 0.;
   double R = 0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
@@ -261,15 +262,15 @@ void PowerKinematicHardening::hardening(double p0, const IPKinematicHardening &i
       ddR = (_exp-1.)*dR/p;
     }
   }
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 void PowerKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double p, double T, IPKinematicHardening &ipv) const
 {
   //_coefficients.print("_coefficients");
-  double R =0., dR=0., ddR=0., dRdT=0., ddRddT=0.;
+  double R =0., dR=0., ddR=0., dRdT=0., ddRdTT=0., ddRdT = 0.;
   
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 kinematicHardening * PowerKinematicHardening::clone() const
@@ -304,7 +305,7 @@ void CoshKinematicHardening::createIPVariable(IPKinematicHardening* &ipv) const
 
 void CoshKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const
 {
-  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRddT(0.);
+  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRdTT(0.), ddRdT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -316,15 +317,15 @@ void CoshKinematicHardening::hardening(double p0, const IPKinematicHardening &ip
     ddR = _K*cosh(p/_p0)/(_p0*_p0);
   }
 
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 void CoshKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double p, double T, IPKinematicHardening &ipv) const
 {
   //_coefficients.print("_coefficients");
-  double R =0., dR=0., ddR=0., dRdT=0.,ddRddT=0.;
+  double R =0., dR=0., ddR=0., dRdT=0., ddRdTT=0., ddRdT = 0.;
   
-  ipv.set(R,dR,ddR,dRdT,ddRddT);
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT);
 }
 
 kinematicHardening * CoshKinematicHardening::clone() const
@@ -386,8 +387,7 @@ void exponentialKinematicHardeningLaw::createIPVariable(IPKinematicHardening* &i
 
 void exponentialKinematicHardeningLaw::hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const
 {
-  double R(0.), dR(0.), ddR(0.); 
-  double dRdT=0., ddRddT=0.; // added
+  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRdTT(0.), ddRdT(0.); 
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -402,13 +402,13 @@ void exponentialKinematicHardeningLaw::hardening(double p0, const IPKinematicHar
     ddR = _h*_alpha*((_alpha-1.)* pow(p,_alpha-2.) *(_K-R) - pow(p,_alpha-1.)*dR);
   }
 
-  ipv.set(R,dR,ddR,dRdT,ddRddT); //added dRdT
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT); 
 }
 
 // added
 void exponentialKinematicHardeningLaw::hardening(double p0, const IPKinematicHardening &ipvprev, double p, double T, IPKinematicHardening &ipv) const
 {
-  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRddT(0.); 
+  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRdTT(0.), ddRdT(0.); 
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -419,16 +419,17 @@ void exponentialKinematicHardeningLaw::hardening(double p0, const IPKinematicHar
     double expTerm = exp(term);
     double KT = _K*_temFunc_K->getVal(T);
     double dKdT = _K*_temFunc_K->getDiff(T);
-    double ddKddT = _K*_temFunc_K->getDoubleDiff(T);
+    double ddKdTT = _K*_temFunc_K->getDoubleDiff(T);
     
     R = KT*(1.-expTerm);
     dR = _h*_alpha*pow(p,_alpha-1.)*(KT-R);
     ddR = _h*_alpha*((_alpha-1.)* pow(p,_alpha-2.) *(KT-R) - pow(p,_alpha-1.)*dR);
     dRdT = dKdT*(1.-expTerm);
-    ddRddT = ddKddT*(1.-expTerm);
+    ddRdTT = ddKdTT*(1.-expTerm);
+    ddRdT = dKdT*_h*_alpha*pow(p,_alpha-1.)*exp(-_h*pow(p,_alpha));
   }
 
-  ipv.set(R,dR,ddR,dRdT,ddRddT); //added dRdT
+  ipv.set(R,dR,ddR,dRdT,ddRdTT,ddRdT); //added dRdT
 } // 
 
 kinematicHardening * exponentialKinematicHardeningLaw::clone() const
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
index 7466910b767c71eee88a4199a9d6cae09edfca9b..1f8f2bcf8aadb40e20751c09e12f8b63dbcf3f91 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
@@ -105,7 +105,7 @@ void mlawHyperViscoElastic::setViscoElasticData(const std::string filename){
 
 void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &dev, double &A_v, double &dA_vdE, double &intA, double &B_d, STensor3 &dB_vddev, double &intB) const
 {
-  int method =1;
+  int method = 2;
   if(method ==0)
   {
     A_v = getVolumeCorrection()*pow(exp(getXiVolumeCorrection()/3.*tr*tr)-1.,getZetaVolumeCorrection());
@@ -115,13 +115,14 @@ void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &de
   
     B_d = getDevCorrection()*pow(exp(getThetaDevCorrection()*dev.dotprod())-1.,getPiDevCorrection());
     STensorOperation::zero(dB_vddev);
-
+    
+    // Msg::Error(" Inside evaluatePhiPCorrection, A_v = %e, B_d = %e !!", A_v, B_d);
  
     dB_vddev=dev;
     dB_vddev*=2.*getPiDevCorrection()*getDevCorrection()*pow(exp(getThetaDevCorrection()*dev.dotprod())-1.,getPiDevCorrection()-1.)* exp(getThetaDevCorrection()*dev.dotprod())*getThetaDevCorrection();
     Msg::Error("mlawHyperViscoElastic::evaluatePhiPCorrection: need to evaluate the volume energy");
   }
-  else
+  else if(method == 1)
   {
     A_v = getVolumeCorrection()*(tanh(getXiVolumeCorrection()/3.*tr*tr-getZetaVolumeCorrection())+tanh(getZetaVolumeCorrection()));  
     dA_vdE = getVolumeCorrection()*getXiVolumeCorrection()*2./3.*(1.-tanh(getXiVolumeCorrection()/3.*tr*tr-getZetaVolumeCorrection())*tanh(getXiVolumeCorrection()/3.*tr*tr-getZetaVolumeCorrection()));
@@ -146,12 +147,76 @@ void mlawHyperViscoElastic::evaluatePhiPCorrection(double tr, const STensor3 &de
       intB=0.5*getDevCorrection()*(1./getThetaDevCorrection()*(log(cosh(getThetaDevCorrection()*u-getPiDevCorrection())) -log(cosh(-getPiDevCorrection())) ) +tanh(getPiDevCorrection())*u ) ;
     
     }
+
+  }
+  
+    else if(method == 2){
+        
+        double x = getXiVolumeCorrection()/3.*tr*tr - getZetaVolumeCorrection();
+        A_v = getVolumeCorrection()*( x/sqrt(1+x*x) );
+        
+        if(A_v > -1.){    
+            dA_vdE = getVolumeCorrection()/pow((1.+x*x),1.5) * 2./3.*getXiVolumeCorrection()*tr;
+            
+            // Here, psi_extraBranch_Tr = Kinf*int(A_v*trEe) dtrEe = Kinf*intA
+            intA = getVolumeCorrection()*3./(2.*getXiVolumeCorrection()) * sqrt(1+x*x);
+        }
+        else{
+            A_v = -1. + 1.e-5; 
+            dA_vdE = 0.;
+            intA = 0.; // correct it inside extraBranchLaw
+        }
+        
+
+        
+        double y = getThetaDevCorrection()*dev.dotprod()-getPiDevCorrection();
+        B_d = getDevCorrection()*( y/sqrt(1+y*y) );
+        
+        if(B_d > -1.){ 
+            dB_vddev = dev;
+            dB_vddev *= getDevCorrection()*2*getThetaDevCorrection()/pow((1.+y*y),1.5);
+            intB = getDevCorrection()/(2.*getThetaDevCorrection()) * sqrt(1+y*y);
+            
+        }
+        else{
+            B_d = -1. + 1.e-5; 
+            STensorOperation::zero(dB_vddev);
+            intB = 0.; // correct it inside extraBranchLaw
+        }
+        // Msg::Error(" Inside evaluatePhiPCorrection, A_v = %e, B_d = %e !!", A_v, B_d);
+
     
+    }
     
+    else if(method == 3){
+        
+        double x = getXiVolumeCorrection()/3.*tr*tr - getZetaVolumeCorrection();
+        A_v = getVolumeCorrection()*( x/(1+x) );
+        if(A_v > -1.){    
+            dA_vdE = 0.;
+        }
+        else{
+            A_v = -0.999; 
+            dA_vdE = 0.;
+        }
+        intA=0.;
+        
+        double y = getThetaDevCorrection()*dev.dotprod()-getPiDevCorrection();
+        B_d = getDevCorrection()*( y/(1+y) );
+        
+        if(B_d > -1.){ 
+            STensorOperation::zero(dB_vddev);
+        }
+        else{
+            B_d = -0.999; 
+            STensorOperation::zero(dB_vddev);
+        }
+        intB=0.;  
+
+        // Msg::Error(" Inside evaluatePhiPCorrection, A_v = %e, B_d = %e !!", A_v, B_d);
+
     
-    
-    
-  }
+    }
 }
 
 
@@ -589,6 +654,7 @@ void mlawHyperViscoElastic::extraBranchLaw(const STensor3& Ee, const IPHyperVisc
     double intA; 
     double intB;
     evaluatePhiPCorrection(trEe, devE, A, dAvDtrEe, intA, B, dBDdevEe, intB);
+    // q1->_elasticShearPropertyScaleFactor = B; // FLE
     sig = devE;
     sig *= (2.*Gextra*B);  // deviatoric part
     double p  = trEe*Kextra*A; // pressure
@@ -1017,10 +1083,11 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
   q1->_DgammaDt = 0.;
 
 
-  static STensor3 Fpinv, Ce, Fepr;
+  static STensor3 Fpinv, Ce, Fepr,Cepr;
   STensorOperation::inverseSTensor3(Fp1,Fpinv);
   STensorOperation::multSTensor3(F,Fpinv,Fepr);
   STensorOperation::multSTensor3FirstTranspose(Fepr,Fepr,Ce);
+  STensorOperation::multSTensor3FirstTranspose(Fepr,Fepr,Cepr);
 
   static STensor3 invFp0; // plastic predictor
   invFp0= Fpinv;
@@ -1122,6 +1189,7 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
 
   double DfDGamma = 0.;
   double dfdDgamma = 0.;
+  double dfdGamma = 0.; //FLE
   double u = 1.;
   double v = 1.;
 
@@ -1151,8 +1219,12 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
         if (_viscosity != NULL)
           _viscosity->get(q1->_epspbarre,eta,Deta);
         double etaOverDt = eta/this->getTimeStep();
+        double dPhiPdGamma = -2*Kt*_b*ptilde/v;
+        double dPhiEdGamma = -6*Gt*PhiEq/u;
+        double dAdGamma_TVP = (12*PhiEq*dPhiEdGamma + 8*_b*_b*ptilde*dPhiPdGamma/3)/(2.*A);
         double dAdGamma = -(72.*Gt*PhiEq*PhiEq/u+ 16.*Kt*_b*_b*_b*ptilde*ptilde/(3.*v))/(2.*A);
         
+
         if (ite > 0)
         {
           // update if extra branch if plasticity occurs
@@ -1161,9 +1233,14 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
         dDgammaDGamma = kk*(A+Gamma*dAdGamma);
 
         this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
-        dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0);
+
+        dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0); //OK
         if (Gamma>0 and etaOverDt>0)
           dfdDgamma -= _p*pow(etaOverDt,_p-1.)*Deta/this->getTimeStep()*pow(Gamma,_p);
+          
+        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 - (_n*a(2)*6.*Gt)*pow(PhiEq,_n)/u + a(1)*ptilde*2.*_b*Kt/v;
         if (ite > 0)
@@ -1173,7 +1250,14 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
         }
         
         if (Gamma>0 and etaOverDt>0)
-          DfDGamma -=pow(etaOverDt,_p)*_p*pow(Gamma,_p-1.);
+          DfDGamma -= pow(etaOverDt,_p)*_p*pow(Gamma,_p-1.);
+         
+        /*Msg::Error("dDgammaDGamma = %e, iter = %d",dDgammaDGamma, ite);
+        Msg::Error("dfdDgamma = %e, iter = %d",dfdDgamma, ite);
+        Msg::Error("dfdGamma = %e, iter = %d",dfdGamma, ite);
+        Msg::Error("DfDGamma = %e, iter = %d",DfDGamma, ite);
+        Msg::Error("Gamma = %e, iter = %d",Gamma, ite);
+        Msg::Error("Dgamma = %e, iter = %d",Dgamma, ite);*/
 
         double dGamma = -f/DfDGamma;
 
@@ -1254,11 +1338,24 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
       GammaN = N;
       GammaN *= Gamma;
       STensorOperation::expSTensor3(GammaN,_order,expGN,&dexpAdA);
-
+      
+      // FLE
+      /*
+      static STensor3 Hinv, Hinv2, check1, check2, check3, check4;
+      STensorOperation::inverseSTensor3(expGN,Hinv);
+      STensorOperation::multSTensor3(Hinv,Hinv,Hinv2);
+      STensorOperation::multSTensor3(Hinv,Cepr,check1);
+      STensorOperation::multSTensor3(Cepr,Hinv,check2);     
+      STensorOperation::multSTensor3(Hinv2,Cepr,check3);
+      STensorOperation::multSTensor3(Cepr,Hinv2,check4);
+      */
+      // FLE
+      
       // update plastic deformation tensor
       STensorOperation::multSTensor3(expGN,Fp0,Fp1);
       // update IP
       updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+      // Msg::Info("setting: gamma=%e ",q1->_epspbarre);
 
       // update elastic deformation tensor, corotational stress
       STensorOperation::inverseSTensor3(Fp1,Fpinv);
@@ -1354,8 +1451,8 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
     if (Gamma >0){
       // plastic
       static STensor3 dAdCepr, dfDCepr;
-
-      double fact = 1.5*a(2)*_n*pow(PhiEq,_n-2.)/(u*u);
+      
+      double fact = 1.5*a(2)*_n*pow(PhiEq,_n-2.)/(u*u); 
       for (int i=0; i<3; i++){
         for (int j=0; j<3; j++){
           dAdCepr(i,j) = (4.*_b*_b*ptildepr/(A*3.*v*v))*DpprDCepr(i,j);
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.h b/NonLinearSolver/materialLaw/mlawHyperelastic.h
index e9d384d7a2d96296fa018d79fa34966055eccacf..330e6abbdc2d8ad432c17276dd35534ba6cd6007 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.h
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.h
@@ -89,13 +89,13 @@ class mlawHyperViscoElastic : public materialLaw{
     virtual void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
     virtual void setViscoElasticData(const std::string filename);
     virtual void setVolumeCorrection(double _vc, double _xivc, double _zetavc, double _dc, double _thetadc, double _pidc) {_volCorrection=_vc,_xivolCorrection=_xivc,_zetavolCorrection=_zetavc, _devCorrection=_dc,_thetadevCorrection=_thetadc,_pidevCorrection=_pidc;};
-    virtual double getVolumeCorrection() const {if (_volCorrection<1.e-5) return 0.; else return _volCorrection;};
-    virtual double getXiVolumeCorrection() const {if (_xivolCorrection<1.e-5) return 1.; else return _xivolCorrection;};
-    virtual double getZetaVolumeCorrection() const {if (_zetavolCorrection<1.e-5) return 1.; else return _zetavolCorrection;};
+    virtual double getVolumeCorrection() const {return _volCorrection;};
+    virtual double getXiVolumeCorrection() const {return _xivolCorrection;};
+    virtual double getZetaVolumeCorrection() const {return _zetavolCorrection;};
     
-    virtual double getDevCorrection() const {if (_devCorrection<1.e-5) return 0.; else return _devCorrection;};
-    virtual double getThetaDevCorrection() const {if (_thetadevCorrection<1.e-5) return 1.; else return _thetadevCorrection;};
-    virtual double getPiDevCorrection() const {if (_pidevCorrection<1.e-5) return 1.; else return _pidevCorrection;};
+    virtual double getDevCorrection() const {return _devCorrection;};
+    virtual double getThetaDevCorrection() const {return _thetadevCorrection;};
+    virtual double getPiDevCorrection() const {return _pidevCorrection;};
     virtual void setExtraBranchType(const int type);
 
     #ifndef SWIG
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp
index 30b6922b0243d71f0bc2a6bee8542d5be7f398df..87db501e6d5a8870d7483ad530b8e28dbcb16515 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp
@@ -20,7 +20,7 @@ mlawNonLinearTVE::mlawNonLinearTVE(const int num,const double E,const double nu,
                                     const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
      mlawPowerYieldHyper(num, E, nu, rho, tol, matrixbyPerturbation, pert),
      _Tinitial(Tinitial),_scalarAlpha(Alpha),_scalarK(KThCon),_Cp(Cp),
-     _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig), _Alphai(0){
+     _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig), _Alphai(0), _mullinsEffect(NULL), _elasticPotential(NULL), _useExtraBranch(false){
 
   _G = _mu;
 
@@ -44,6 +44,7 @@ mlawNonLinearTVE::mlawNonLinearTVE(const int num,const double E,const double nu,
   _temFunc_Alpha = new constantScalarFunction(1.);
   _temFunc_KThCon = new constantScalarFunction(1.);
   _temFunc_Cp = new constantScalarFunction(1.);
+  _temFunc_elasticCorrection = new constantScalarFunction(1.);
 
 };
 
@@ -61,6 +62,7 @@ mlawNonLinearTVE::mlawNonLinearTVE(const mlawNonLinearTVE& src): mlawPowerYieldH
   _C2 = src._C2;
   _tensorAlpha = src._tensorAlpha;
   _tensorK = src._tensorK;
+  _useExtraBranch = src._useExtraBranch;
 
   _temFunc_K = NULL;                                                                    // bulk modulus
   if (src._temFunc_K != NULL){ _temFunc_K = src._temFunc_K->clone();}
@@ -77,6 +79,9 @@ mlawNonLinearTVE::mlawNonLinearTVE(const mlawNonLinearTVE& src): mlawPowerYieldH
   _temFunc_Cp = NULL;                                                                   // specific heat
   if (src._temFunc_Cp!=NULL){ _temFunc_Cp = src._temFunc_Cp->clone();}
 
+  _temFunc_elasticCorrection = NULL;                                                    // elastic correction
+  if (src._temFunc_elasticCorrection!=NULL){ _temFunc_elasticCorrection = src._temFunc_elasticCorrection->clone();}
+  
   _temFunc_Ki.resize(_N,NULL);                                                          // branch bulk moduli
   for(int i=0;i<_N;i++){
     if (src._temFunc_Ki[i]!=NULL) {_temFunc_Ki[i] = src._temFunc_Ki[i]->clone();}
@@ -91,6 +96,13 @@ mlawNonLinearTVE::mlawNonLinearTVE(const mlawNonLinearTVE& src): mlawPowerYieldH
   for(int i=0;i<_N;i++){
     if (src._temFunc_Alphai[i]!=NULL) {_temFunc_Alphai[i] = src._temFunc_Alphai[i]->clone();}
   }
+  
+  _mullinsEffect= NULL;
+  if (src._mullinsEffect) _mullinsEffect = src._mullinsEffect->clone();
+  
+  _elasticPotential = NULL;
+  if (src._elasticPotential) _elasticPotential = src._elasticPotential->clone();
+  
 };
 
 
@@ -112,7 +124,8 @@ mlawNonLinearTVE& mlawNonLinearTVE::operator=(const materialLaw& source){
     _C2 = src->_C2;
     _tensorAlpha = src->_tensorAlpha;
     _tensorK = src->_tensorK;
-
+    _useExtraBranch = src->_useExtraBranch;
+    
     if(_temFunc_K != NULL) delete _temFunc_K;                                                   // bulk modulus
     if (src->_temFunc_K != NULL){ _temFunc_K = src->_temFunc_K->clone();}
 
@@ -127,6 +140,9 @@ mlawNonLinearTVE& mlawNonLinearTVE::operator=(const materialLaw& source){
 
     if(_temFunc_Cp != NULL) delete _temFunc_Cp;                                                 // specific heat
     if (src->_temFunc_Cp!=NULL){ _temFunc_Cp = src->_temFunc_Cp->clone();}
+    
+    if(_temFunc_elasticCorrection != NULL) delete _temFunc_elasticCorrection;                   // elastic correction
+    if (src->_temFunc_elasticCorrection!=NULL){ _temFunc_elasticCorrection = src->_temFunc_elasticCorrection->clone();}
 
     for(int i=0;i<_temFunc_Ki.size();i++){                                                          // branch bulk moduli
         if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
@@ -157,6 +173,12 @@ mlawNonLinearTVE& mlawNonLinearTVE::operator=(const materialLaw& source){
         if (src->_temFunc_Alphai[i]!=NULL)
         _temFunc_Alphai[i] = src->_temFunc_Alphai[i]->clone();
     }
+    
+    if(_mullinsEffect != NULL) delete _mullinsEffect;
+    if (src->_mullinsEffect!=NULL){ _mullinsEffect = src->_mullinsEffect->clone();}
+    
+    if(_elasticPotential != NULL) delete _elasticPotential;
+    if (src->_elasticPotential!=NULL){ _elasticPotential = src->_elasticPotential->clone();}
   }
   return *this;
 }
@@ -167,6 +189,7 @@ mlawNonLinearTVE::~mlawNonLinearTVE(){
     if(_temFunc_Alpha != NULL) delete _temFunc_Alpha; _temFunc_Alpha = NULL;        // thermal dilatation coeff;
     if(_temFunc_KThCon != NULL) delete _temFunc_KThCon; _temFunc_KThCon = NULL;     // thermal conductivity;
     if(_temFunc_Cp != NULL) delete _temFunc_Cp; _temFunc_Cp = NULL;                 // specific heat;
+    if(_temFunc_elasticCorrection != NULL) delete _temFunc_elasticCorrection; _temFunc_elasticCorrection = NULL;                 // elastic correction
     for(int i=0;i<_temFunc_Ki.size();i++){
         if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
         _temFunc_Ki[i]=NULL;
@@ -179,6 +202,9 @@ mlawNonLinearTVE::~mlawNonLinearTVE(){
         if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
         _temFunc_Alphai[i]=NULL;
     }
+    
+    if (_mullinsEffect) delete _mullinsEffect; _mullinsEffect = NULL;
+    if (_elasticPotential) delete _elasticPotential; _elasticPotential = NULL;
 };
 
 void mlawNonLinearTVE::setViscoElasticNumberOfElement(const int N){
@@ -525,10 +551,11 @@ double mlawNonLinearTVE::setTemp(const double T0, const double T1, const int par
     return T_set;
 }
 
-double mlawNonLinearTVE::freeEnergyMechanical(const IPNonLinearTVE& q, const double Tc) const{
+double mlawNonLinearTVE::freeEnergyMechanical(const IPNonLinearTVE& q, const double T0, const double T) const{
 
     // Update the Properties to the current temperature (see below which ones are being used)
-    double KT, GT, AlphaT; getK(KT,Tc); getG(GT,Tc); getAlpha(AlphaT,Tc);
+    double KT, GT, AlphaT; 
+    getK(&q,KT,T); getG(&q,GT,T); getAlpha(AlphaT,T);
 
     double Psy_mech = 0.;
 
@@ -538,41 +565,85 @@ double mlawNonLinearTVE::freeEnergyMechanical(const IPNonLinearTVE& q, const dou
     STensorOperation::decomposeDevTr(q._Ee,devEe,trEe);
 
     // Get thermal strain
-    double Eth = 3.*AlphaT*(Tc-_Tinitial);
+    double Eth = 3.*AlphaT*(T-_Tinitial);
 
     // Get Equilibrium freeEnergy_mech
     Psy_mech = KT*0.5*(trEe-Eth)*(trEe-Eth) + GT*STensorOperation::doubledot(devEe,devEe);
+    
+    // Get ExtraBranch freeEnergy
+    if (_useExtraBranch){
+        Psy_mech += KT*q._intA + 2.*GT*q._intB; 
+    }
 
     // Add Branch freeEnergy_mech
     if ((_Ki.size() > 0) or (_Gi.size() > 0)){
 
-        std::vector<double> KiT,GiT,AlphaiT; KiT.resize(_N,0.); GiT.resize(_N,0.); AlphaiT.resize(_N,0.); getKi(KiT,Tc); getGi(GiT,Tc); getAlphai(AlphaiT,Tc);
+        std::vector<double> KiT,GiT,AlphaiT; 
+        KiT.resize(_N,0.); GiT.resize(_N,0.); AlphaiT.resize(_N,0.); 
+        getKi(&q,KiT,T); getGi(&q,GiT,T); getAlphai(AlphaiT,T);
 
         for (int i=0; i<_N; i++){
             static STensor3 devEebranch;
             devEebranch = devEe;
+            
+            // viscous overstrain = _OGammai
+            // viscous strain (_Gammai) = viscous overstrain - Ee
+            double trGamma = q._trOGammai[i]; 
+            trGamma -= trEe; 
+            static STensor3 devGamma;
+            devGamma = q._devOGammai[i]; 
+            devGamma -= devEe; 
+            
+            devEebranch -= devGamma; // temporary tensor
 
-            // devEebranch -= q._A[i];
-            // Psy_mech += KiT[i]*0.5*(trEe-q._B[i])*(trEe-q._B[i])+GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
-
-            double trGamma = q._trOGammai[i];
-            static STensor3 devGamma = q._devOGammai[i];
-            devEebranch -= devGamma;
 
             if (_modelFlag == 2){  // Additional volumetric terms
-                trGamma += 3*(AlphaT-AlphaiT[i])*(Tc-_Tinitial);
+                trGamma += 3*(AlphaT-AlphaiT[i])*(T-_Tinitial);
             }
 
             Psy_mech += KiT[i]*0.5*(trEe-trGamma)*(trEe-trGamma) + GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
         }
     }
-
+    
+    // Get thermal Energy
+    // Psy_mech += _Cp*( (T-T0) - T*log(T/T0) ); // this probably does nothing since we are interested only in the elastic energy
+    
     return Psy_mech;
 }
 
-void mlawNonLinearTVE::corKirInfinity( const STensor3& devEe,  const double& trEe, const double T1, STensor3& CorKirDevInf, double& CorKirTrInf) const{
+void mlawNonLinearTVE::calculateMullinsEffectScaler(const IPNonLinearTVE* q0, IPNonLinearTVE *q1, const double T) const{
+    
+
+    // Msg::Error(" Inside calculateMullinsEffectScaler, before updating eta, q1->_elasticEnergy = %e!!",q1->_elasticEnergy);
+    // Msg::Error(" Inside calculateMullinsEffectScaler, before updating eta, q1->_psiMax = %e!!",q1->_psiMax);
+    
+    // Initialise
+    double eta = 1., DetaDpsi = 0., DDetaDpsipsi = 0., DetaDT = 0., DDetaDTT = 0.;
+    
+    // Msg::Error(" Inside calculateMullinsEffectScaler, before updating eta = %e!!",eta);
+    
+    // update eta - Mullins Effect Scalar
+    if (_mullinsEffect != NULL && q1->_ipMullinsEffect != NULL){
+    _mullinsEffect->mullinsEffectScaling(q0->_elasticEnergy, q1->_elasticEnergy, *q0->_ipMullinsEffect, *q1->_ipMullinsEffect);
+    }
+    
+    // get eta - Mullins Effect Scalar (at unloading intitiation-> eta = 1.; unloading end-> eta = eta_min; reloading -> eta = eta_min;)
+    if (q1->_ipMullinsEffect != NULL){
+        eta = q1->_ipMullinsEffect->getEta(); 
+        DetaDpsi = q1->_ipMullinsEffect->getDetaDpsi();
+        DetaDT = q1->_ipMullinsEffect->getDetaDT();
+        DDetaDTT = q1->_ipMullinsEffect->getDDetaDTT();
+    }
+    // Msg::Error(" Inside calculateMullinsEffectScaler, after getting and updating eta = %e!!",eta);
+    
+    // update mullinsDamage scalar
+    q1->_mullinsDamage = eta;
+  
+};
+
+void mlawNonLinearTVE::corKirInfinity(const IPNonLinearTVE *q1, const STensor3& devEe,  const double& trEe, const double T1, STensor3& CorKirDevInf, double& CorKirTrInf) const{
     double KT, GT, AlphaT;
-    getK(KT,T1); getG(GT,T1); getAlpha(AlphaT,T1);
+    getK(q1,KT,T1); getG(q1,GT,T1); getAlpha(AlphaT,T1);
     CorKirDevInf = 2*GT*devEe;
     CorKirTrInf = KT*(trEe - 3*AlphaT*(T1-_Tinitial));
 }
@@ -587,7 +658,7 @@ void mlawNonLinearTVE::getTVEdCorKirDT(const IPNonLinearTVE *q0, IPNonLinearTVE
 
     // Update the Properties to the current temperature (see below which ones are being used)
     double KT, GT, AlphaT, DKDT, DGDT, DAlphaDT, DDKDT, DDGDT, DDAlphaDT;
-    getK(KT,T,&DKDT,&DDKDT); getG(GT,T,&DGDT,&DDGDT); getAlpha(AlphaT,T,&DAlphaDT,&DDAlphaDT);
+    getK(q1,KT,T,&DKDT,&DDKDT); getG(q1,GT,T,&DGDT,&DDGDT); getAlpha(AlphaT,T,&DAlphaDT,&DDAlphaDT);
     
     // Add corKirinf terms to DcorKirDT
     STensor3 corKirDevInf, devEe;
@@ -604,7 +675,7 @@ void mlawNonLinearTVE::getTVEdCorKirDT(const IPNonLinearTVE *q0, IPNonLinearTVE
     STensorOperation::decomposeDevTr(DEe,devDE,trDE);
     
     // Add Infinity terms
-    corKirInfinity( devEe, trEe, T, corKirDevInf, corKirTrInf );
+    corKirInfinity(q1, devEe, trEe, T, corKirDevInf, corKirTrInf);
     for (int i=0; i<3; i++){
         DcorKirDT(i,i) += corKirTrInf*DKDT/KT - 3*KT*(DAlphaDT*(T-_Tinitial) + AlphaT);
         DDcorKirDT(i,i) += corKirTrInf*DDKDT/KT - 6*DKDT*(DAlphaDT*(T-_Tinitial) + AlphaT)- 3*KT*(DDAlphaDT*(T-_Tinitial) + 2*DAlphaDT);
@@ -672,10 +743,11 @@ void mlawNonLinearTVE::getTVEdCorKirDT(const IPNonLinearTVE *q0, IPNonLinearTVE
             STensorOperation::zero(DOGammai); STensorOperation::zero(DOGammaiDT); STensorOperation::zero(DDOGammaiDT);
 
             if (_TemFuncOpt == 0){ // Use Shift Factor
-                DKiDT[i] = -_Ki[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
-                DDKiDT[i] = -_Ki[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
-                DGiDT[i] = -_Gi[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
-                DDGiDT[i] = -_Gi[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
+                getKi(q1,KiT,T); getGi(q1,GiT,T);
+                DKiDT[i] = -KiT[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
+                DDKiDT[i] = -KiT[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
+                DGiDT[i] = -GiT[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
+                DDGiDT[i] = -GiT[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
             }
 
             for (int j=0; j<3; j++){
@@ -739,7 +811,7 @@ void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE
                                         const double& DKDTsum, const double& DGDTsum, const STensor43& DEeDFe,
                                         double *Wm, STensor3 *dWmdF, double *dWmdT) const{
                                           
-    // I am stupid
+    // Initialize
     double mechSrcTVE, dmechSrcTVEdT = 0.;
     STensor3 dmechSrcTVEdE(0.);
     STensor3 dmechSrcTVEdF(0.);
@@ -824,11 +896,11 @@ void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE
             STensorOperation::zero(DOGammai); STensorOperation::zero(DOGammaiDT); STensorOperation::zero(DDOGammaiDT);
 
             if (_TemFuncOpt == 0){ // Use Shift Factor
-                getKi(KiT,T); getGi(GiT,T);
-                DKiDT[i] = -_Ki[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
-                DDKiDT[i] = -_Ki[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
-                DGiDT[i] = -_Gi[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
-                DDGiDT[i] = -_Gi[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
+                getKi(q1,KiT,T); getGi(q1,GiT,T);
+                DKiDT[i] = -KiT[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
+                DDKiDT[i] = -KiT[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
+                DGiDT[i] = -GiT[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
+                DDGiDT[i] = -GiT[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
             }
 
             for (int j=0; j<3; j++){
@@ -878,9 +950,9 @@ void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE
             STensorOperation::zero(DGammai); STensorOperation::zero(DDGammaiDT);
             DQiDT -= DOiDT; DDQiDT -= DDOiDT; DDGammaiDT -= DDOGammaiDT;
             for (int j=0; j<3; j++){
-                Qi(j,j) += (_Ki[i]*trEe - trOi[i]);
+                Qi(j,j) += (KiT[i]*trEe - trOi[i]);
                 for (int k=0; k<3; k++){
-                    Qi(j,k) += (2*_Gi[i]*devEe(j,k) - devOi[i](j,k));
+                    Qi(j,k) += (2*GiT[i]*devEe(j,k) - devOi[i](j,k));
                 }
             }
             DGammai += DEe;
@@ -893,8 +965,8 @@ void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE
             static STensor43 temp_DDQiDTDE;
             static STensor43 temp_DDgammiDtDE;
 
-            double Ki_term = (_Ki[i]*(1-expdtkby2)+T*DKiDT[i]);
-            double Gi_term = (_Gi[i]*(1-expdtgby2)+T*DGiDT[i]);
+            double Ki_term = (KiT[i]*(1-expdtkby2)+T*DKiDT[i]);
+            double Gi_term = (GiT[i]*(1-expdtgby2)+T*DGiDT[i]);
             isotropicHookTensor( Ki_term, Gi_term , temp_DDQiDTDE );
 
             double Ki_term_2 = 1/3*expdtkby2;
@@ -988,6 +1060,141 @@ void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE
                                           
 };
 
+void mlawNonLinearTVE::evaluateElasticCorrection(const double trE, const STensor3 &devE, const double& T, 
+                                                 double &A_v, double &dA_vdE, double &intA, double &dAdT,
+                                                 double &B_d, STensor3 &dB_vddev, double &intB, double &dBdT,
+                                                 double *ddAdTT, double *ddBdTT) const{
+    
+    mlawHyperViscoElastic::evaluatePhiPCorrection(trE,devE,A_v,dA_vdE,intA,B_d,dB_vddev,intB);
+    
+    A_v *= _temFunc_elasticCorrection->getVal(T);
+    dA_vdE *= _temFunc_elasticCorrection->getVal(T);
+    intA *= _temFunc_elasticCorrection->getVal(T);
+    
+    dAdT = A_v*_temFunc_elasticCorrection->getDiff(T);
+    if(ddAdTT!=NULL){
+        *ddAdTT = A_v*_temFunc_elasticCorrection->getDoubleDiff(T);
+    }
+    
+    B_d *= _temFunc_elasticCorrection->getVal(T);
+    dB_vddev *= _temFunc_elasticCorrection->getVal(T);
+    intB *= _temFunc_elasticCorrection->getVal(T);
+    dBdT = B_d*_temFunc_elasticCorrection->getDiff(T);
+    if(ddBdTT!=NULL){
+        *ddBdTT = B_d*_temFunc_elasticCorrection->getDoubleDiff(T);
+    }
+    
+}
+
+void mlawNonLinearTVE::extraBranchLaw(const STensor3& Ee, const double& T, const IPNonLinearTVE *q0, IPNonLinearTVE *q1, 
+                        STensor3& sig, const bool stiff, STensor43* DsigDEe, STensor3* DsigDT, 
+                        double* DsigV_dTrEe, STensor43* DsigD_dDevEe,
+                        double* DsigV_dT, STensor3* DsigD_dT,
+                        double* DDsigV_dTT, STensor3* DDsigD_dTT) const
+{
+    // DsigDEe = DcorKirDE
+    
+  if (_extraBranchType == Bilogarithmic)
+  {
+    static STensor3 devEe;
+    double trEe;
+    STensorOperation::decomposeDevTr(Ee,devEe,trEe);
+    
+    double A(0.), B(0.);
+    double dA_dTrEe = 0.;
+    STensor3 dB_dDevEe;
+    double intA(0.), intB(0.), dA_dT(0.), dB_dT(0.), ddA_dTT(0.), ddB_dTT(0.);
+    evaluateElasticCorrection(trEe, devEe, T, A, dA_dTrEe, intA, dA_dT, B, dB_dDevEe, intB, dB_dT, &ddA_dTT, &ddB_dTT);
+    
+    if (A <= -1. + 1.e-5){ // saturated
+        double trEe_0 = q0->_Ee.trace();
+        intA = q0->_intA;
+        intA += A*0.5 *(trEe*trEe-trEe_0*trEe_0);
+    }
+    q1->_intA = intA;
+    
+    if (B <= -1. + 1.e-5){ // saturated
+        static STensor3 devEe_0;
+        double trEe_0;
+        STensorOperation::decomposeDevTr(q0->_Ee,devEe_0,trEe_0);
+        intA = q0->_intB;
+        intA += B*0.5 *(devEe.dotprod()-devEe_0.dotprod());
+    }
+    q1->_intB = intB;
+    
+    double check_1 = (1+A)*_K;
+    double check_2 = (1+B)*_G;
+    // Msg::Error(" Inside extraBranchLaw, Kinf = %e, Ginf = %e !!", _K, _G);
+    // Msg::Error(" Inside extraBranchLaw, (1+A)*Kinf = %e, (1+B)*Ginf = %e !!", check_1, check_2);
+    
+    q1->_elasticBulkPropertyScaleFactor = A; 
+    q1->_elasticShearPropertyScaleFactor = B; 
+    
+    double Gextra, dGex_dT, ddGex_dTT; 
+    getG(q1,Gextra,T, &dGex_dT, &ddGex_dTT); // getUpdatedShearModulus(q1); // We dont update here anymore
+    double Kextra, dKex_dT, ddKex_dTT;  
+    getK(q1,Kextra,T, &dKex_dT, &ddKex_dTT); // getUpdatedBulkModulus(q1);  // We dont update here anymore
+
+    sig = devEe;
+    sig *= (2.*Gextra*B);  // deviatoric part
+    double p = trEe*Kextra*A; // pressure
+    sig(0,0) += p;
+    sig(1,1) += p;
+    sig(2,2) += p;
+    
+    if (stiff)
+    {
+        // DsigDE
+        if(DsigDEe!=NULL){
+            STensorOperation::zero(*DsigDEe);
+            *DsigDEe = _Idev;
+            *DsigDEe *= (2.*Gextra*B);
+            STensorOperation::prodAdd(devEe, dB_dDevEe, 2.*Gextra,  *DsigDEe);            
+            STensorOperation::prodAdd(_I,_I,Kextra*(A+trEe*dA_dTrEe),*DsigDEe);
+        }
+        
+        // DsigDT
+        if(DsigDT!=NULL){
+            STensorOperation::zero(*DsigDT);
+        }
+        
+        // These can be used for plasticity
+        if(DsigV_dTrEe!=NULL){
+            *DsigV_dTrEe = Kextra*(A + trEe*dA_dTrEe);
+        }
+        if(DsigD_dDevEe!=NULL){
+            STensorOperation::zero(*DsigD_dDevEe);
+            *DsigD_dDevEe = _I4;
+            *DsigD_dDevEe *= (2.*Gextra*B);
+            STensorOperation::prodAdd(devEe, dB_dDevEe, 2.*Gextra, *DsigD_dDevEe);
+        }
+        
+        if(DsigV_dT!=NULL){
+            *DsigV_dT = dKex_dT*A*trEe + Kextra*dA_dT*trEe;
+        }
+        if(DsigD_dT!=NULL){
+            STensorOperation::zero(*DsigD_dT);
+            *DsigD_dT = devEe;
+            *DsigD_dT *= (2*dGex_dT*B + 2*Gextra*dB_dT);
+        }
+        
+        if(DDsigV_dTT!=NULL){
+            *DDsigV_dTT = ddKex_dTT*A*trEe + 2*dKex_dT*dA_dT*trEe + Kextra*ddA_dTT*trEe;
+        }
+        if(DDsigD_dTT!=NULL){
+            STensorOperation::zero(*DDsigD_dTT);
+            *DDsigD_dTT = devEe;
+            *DDsigD_dTT *= 2*(ddGex_dTT*B + 2*dGex_dT*dB_dT + Gextra*ddB_dTT);
+        }
+    };
+    
+  }
+  else
+  {
+    Msg::Error("extra branch type %d is not defined",_extraBranchType);
+  }
+};
+
 void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
           const IPNonLinearTVE *q0, IPNonLinearTVE *q1,
           double& Ke, double& Ge, double& Kde, double& Gde,
@@ -1000,7 +1207,7 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
 
     // Update the Properties to the current temperature (see below which ones are being used)
     double KT, GT, AlphaT_0, AlphaT, DKDT, DGDT, DAlphaDT;
-    getK(KT,T_set,&DKDT); getG(GT,T_set,&DGDT); getAlpha(AlphaT_0,T0); getAlpha(AlphaT,T_set,&DAlphaDT);
+    getK(q1,KT,T_set,&DKDT); getG(q1,GT,T_set,&DGDT); getAlpha(AlphaT_0,T0); getAlpha(AlphaT,T_set,&DAlphaDT);
 
     // Get LogStrain
     static STensor3 DE, devDE, devEe;
@@ -1014,15 +1221,20 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
     static STensor3 devK;
     STensorOperation::zero(devK);
     devK = 2*GT*devEe;
-
+    
     // Initialise CorKirStress - Tr
     static double p;
     p = KT*(trEe - 3*AlphaT*(T1-_Tinitial));
-
+    
     // Initialise Moduli
     Ke = KT; Ge = GT; KTsum = KT; GTsum = GT;
     DKe = DKDT; DGe = DGDT; DKDTsum = DKDT; DGDTsum = DGDT;
-
+    
+    // Kelvin-Voight
+    /*double invGe = 1./GT;
+    double invKe = 1./KT;
+    STensor3 D(0.);
+    double V= 0.;*/
 
     // Main Loop for Maxwell Branches
     if ((_Ki.size() > 0) or (_Gi.size() > 0)){
@@ -1041,7 +1253,7 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
         DKiDT.resize(_N,0.); DGiDT.resize(_N,0.); DAlphaiDT.resize(_N,0.); DDKiDT.resize(_N,0.); DDGiDT.resize(_N,0.);
 
         if (_TemFuncOpt == 1){ // Use Scalar Functions
-            getKi(KiT,T_set,&DKiDT,&DDKiDT); getGi(GiT,T_set,&DGiDT,&DDGiDT); getAlphai(AlphaiT_0,T0); getAlphai(AlphaiT,T_set,&DAlphaiDT);
+            getKi(q1,KiT,T_set,&DKiDT,&DDKiDT); getGi(q1,GiT,T_set,&DGiDT,&DDGiDT); getAlphai(AlphaiT_0,T0); getAlphai(AlphaiT,T_set,&DAlphaiDT);
         }
 
 
@@ -1056,11 +1268,14 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
             double expdtg = exp(-dtg);
             // double expdtgby2 = exp(-dtg/2.);
             double expdtgby2 = exp(-dtg2);
-
+            
+            // Maxwell
             if (_TemFuncOpt == 0){ // Use Shift Factor
-                getGi(GiT,T_set);  // Removed 2*_gi[i]
-                DGiDT[i] = -_Gi[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
-                DDGiDT[i] = -_Gi[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
+                getGi(q1,GiT,T_set);  // Removed 2*_gi[i]
+                // Msg::Error(" Inside TVE ThermoViscoElasticPredictor, _Gi[i] = %e", _Gi[i]);
+                // Msg::Error(" Inside TVE ThermoViscoElasticPredictor, GiT[i] = %e", GiT[i]);
+                DGiDT[i] = -GiT[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
+                DDGiDT[i] = -GiT[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
             }
 
             // For Single Convolution
@@ -1096,9 +1311,41 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
 
             devOi[i] = 2*GiT[i]*q1->_A[i]; // + q1->_C[i];
             devK += devOi[i];
+            
+            // Kelvin-Voight
+            /*
+            invGe += (1.-expdtgby2)/_Gi[i];
+            for (int k=0; k<3; k++){
+              for (int l=0; l<3; l++){
+                D(k,l) += q0->_A[i](k,l)*(expdtg-1.);
+              }
+            }*/
+            
          }
-
-
+         /*
+         // Kelvin-Voight
+         Ge = 1./invGe;
+         // stress increment
+         static STensor3 DdevK;
+         DdevK = devDE; // dev corotational kirchoff stress predictor
+         DdevK += D;
+         DdevK *= (2.*Ge);
+         for (int i=0; i< _Gi.size(); i++){
+            double dtg = dt_shift_1/(_gi[i]);
+            double dtg2 = dt_shift_2/(_gi[i]);
+            double expdtg = exp(-dtg);
+            double expdtgby2 = exp(-dtg2);
+            STensorOperation::zero(q1->_A[i]);
+            for (int k=0; k<3; k++){
+              for (int l=0; l<3; l++){
+                q1->_A[i](k,l) += expdtg*q0->_A[i](k,l) + expdtgby2*DdevK(k,l)/(2.*_Gi[i]);
+              }
+            }
+         }
+         STensorOperation::zero(devK);
+         devK += DdevK;*/
+        
+        
         // Tr Q_i
         std::vector<double>& trOi = q1 -> getRefToTrViscoElasticOverStress(); // trOi[i].resize(_N,0.);
         std::vector<double>& trOGammai = q1 -> getRefToTrViscoElasticOverStrain();
@@ -1110,11 +1357,12 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
             double expdtk = exp(-dtk);
             double expdtkby2 = exp(-dtk2);
             // double expdtkby2 = exp(-dtk/2.);
-
+            
+            // Maxwell 
             if (_TemFuncOpt == 0){ // Use Shift Factor
-                getKi(KiT,T_set); getAlphai(AlphaiT,T_set);  // Removed 2*_ki[i]
-                DKiDT[i] = -_Ki[i]/(_ki[i]) * Ddt_shiftDT *expdtkby2;
-                DDKiDT[i] = -_Ki[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2)) *expdtkby2;
+                getKi(q1,KiT,T_set); getAlphai(AlphaiT,T_set);  // Removed 2*_ki[i]
+                DKiDT[i] = -KiT[i]/(_ki[i]) * Ddt_shiftDT *expdtkby2;
+                DDKiDT[i] = -KiT[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2)) *expdtkby2;
             }
 
             // Single Convolution
@@ -1160,9 +1408,33 @@ void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STe
             }
 
             p += trOi[i];
+            
+            
+            /*
+            // Kelvin-Voight
+            invKe += (1.-expdtkby2)/_Ki[i];
+            V += q0->_B[i]*(expdtk-1.);
+             * */
+        }
+        /*
+        // Kelvin-Voight
+        Ke = 1./invKe;
+        double Dp = Ke*(trDE+ V); // pressure predictor
+        for (int i=0; i< _Ki.size(); i++){
+          double dtk = dt_shift_1/(_ki[i]);
+          double dtk2 = dt_shift_2/(_ki[i]);
+          double expdtk = exp(-dtk);
+          double expdtkby2 = exp(-dtk2);
+          q1->_B[i] = 0.;
+          q1->_B[i] += expdtk*q0->_B[i] + expdtkby2*Dp/(_Ki[i]);
         }
+        p = 0.;
+        p += Dp; 
+         * */
     }
 
+// Msg::Error(" Inside TVE_predictorCorrector, Ke = %e, Ge = %e !!", Ke, Ge);
+
     if (calculateStress){
         q1->_kirchhoff = devK;
         q1->_kirchhoff(0,0) += p;
@@ -1370,7 +1642,7 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
 
     // Update the Properties to the current temperature (see below which ones are being used)
     double KT, GT, AlphaT, KThConT, CpT, DKDT, DGDT, DAlphaDT, DKThConDT, DCpDT, DDKDT, DDGDT, DDAlphaDT;
-    getK(KT,T_set,&DKDT,&DDKDT); getG(GT,T_set,&DGDT,&DDGDT); getAlpha(AlphaT,T_set,&DAlphaDT,&DDAlphaDT); getKTHCon(KThConT,T_set,&DKThConDT); getCp(CpT,T_set,&DCpDT);
+    getK(q1,KT,T_set,&DKDT,&DDKDT); getG(q1,GT,T_set,&DGDT,&DDGDT); getAlpha(AlphaT,T_set,&DAlphaDT,&DDAlphaDT); getKTHCon(KThConT,T_set,&DKThConDT); getCp(CpT,T_set,&DCpDT);
 
     // Calculate/update Log Strain
     static STensor3 C;
@@ -1404,14 +1676,58 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
 
     ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); // Updates the values of moduli to the current temperatures and calculate stresses.
     Kde = 0.; Gde = 0.;
+    
+    // NEW
+    // additional branch
+    static STensor3 sigExtra, DsigExtraDT;
+    static STensor43 DsigExtraDE;
+    STensorOperation::zero(sigExtra);
+    STensorOperation::zero(DsigExtraDE);
+    STensorOperation::zero(DsigExtraDT);
+    if (_useExtraBranch){
+        mlawNonLinearTVE::extraBranchLaw(E,T,q0,q1,sigExtra,stiff,&DsigExtraDE,&DsigExtraDT);
+        q1->_corKirExtra = sigExtra;
+    }
+    q1->_kirchhoff += sigExtra;
+    // NEW
 
     const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
     static STensor3 secondPK;
     STensorOperation::multSTensor3STensor43(corKir,dlnCdC,secondPK);
     STensorOperation::multSTensor3(F,secondPK,P);                  // 1st PK
 
+    // P *= (1+q1->_elasticShearPropertyScaleFactor);
+    
     // elastic energy
-    q1->_elasticEnergy = freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+    q1->_elasticEnergy = freeEnergyMechanical(*q1,T0,T);
+    
+    /*
+    // Hyperelastic Potential
+    double psi_hyper(0.);
+    static STensor3 P_hyper;
+    static STensor43 dPdF_hyper;
+    static STensor63 d2PdFF_hyper;
+    const bool stiff_hyper = true;
+    const bool Dstiff_hyper = false;
+    STensorOperation::zero(P_hyper);
+    STensorOperation::zero(dPdF_hyper);
+    STensorOperation::zero(d2PdFF_hyper);
+    if (_elasticPotential != NULL){
+      psi_hyper = _elasticPotential->get(F);
+      _elasticPotential->constitutive(F,P_hyper,stiff_hyper,&dPdF_hyper,Dstiff_hyper,&d2PdFF_hyper);
+    }*/
+    
+    // Mullins Effect Scaler 
+    if (_mullinsEffect != NULL && q1->_ipMullinsEffect != NULL){
+        mlawNonLinearTVE::calculateMullinsEffectScaler(q0, q1, T);
+    }
+    double eta_mullins = 1.;
+    if (q1->_ipMullinsEffect != NULL){
+        eta_mullins = q1->_ipMullinsEffect->getEta(); 
+        P *= eta_mullins;
+        q1->_elasticEnergy *= eta_mullins;
+    }
+    // Msg::Error(" Inside TVE predCorr, after updating q1->_elasticEnergy = %e!!",q1->_elasticEnergy);
 
     // thermal energy
     q1->_thermalEnergy = CpT*T;
@@ -1469,7 +1785,17 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
     double& trDE = q1->getRefToTrDE();
     STensorOperation::decomposeDevTr(DEe,devDE,trDE);
 
-    corKirInfinity( devEe, trEe, T, corKirDevInf, corKirTrInf );
+    corKirInfinity(q1, devEe, trEe, T, corKirDevInf, corKirTrInf); // MISTAKE HERE -> corKirTrInf is the pressure  
+    
+    // Add extrabranch to corKir_inf
+    double tr_sigExtra(0.);
+    static STensor3 dev_sigExtra;
+    STensorOperation::decomposeDevTr(sigExtra,dev_sigExtra,tr_sigExtra);
+    corKirDevInf += dev_sigExtra;
+    corKirTrInf += 1/3*tr_sigExtra; // LHS is pressure
+    
+    q1->_trCorKirinf_TVE = 3*corKirTrInf;
+    q1->_devCorKirinf_TVE = corKirDevInf;
 
     for (int i=0; i<3; i++){
         // DcorKirDT(i,i) += corKirTr/3/(Ke+Kde*(T-T_temp))*(DKe + DKde*(T-T_temp)) - 3*KT*(DAlphaDT*(T-_Tinitial) + AlphaT);           // 1st formulation
@@ -1490,7 +1816,7 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
         KiT.resize(_N,0.);GiT.resize(_N,0.);AlphaiT.resize(_N,0.);DKiDT.resize(_N,0.);DGiDT.resize(_N,0.);DAlphaiDT.resize(_N,0.);DDKiDT.resize(_N,0.);DDGiDT.resize(_N,0.);DDAlphaiDT.resize(_N,0.);
 
         if (_TemFuncOpt == 1){
-            getKi(KiT,T_set,&DKiDT,&DDKiDT); getGi(GiT,T_set,&DGiDT,&DDGiDT); getAlphai(AlphaiT,T_set,&DAlphaiDT,&DDAlphaiDT);
+            getKi(q1,KiT,T_set,&DKiDT,&DDKiDT); getGi(q1,GiT,T_set,&DGiDT,&DDGiDT); getAlphai(AlphaiT,T_set,&DAlphaiDT,&DDAlphaiDT);
         }
 
         static STensor3 DOiDT;
@@ -1549,11 +1875,11 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
             STensorOperation::zero(DOGammai); STensorOperation::zero(DOGammaiDT); STensorOperation::zero(DDOGammaiDT);
 
             if (_TemFuncOpt == 0){ // Use Shift Factor
-                getKi(KiT,T_set); getGi(GiT,T_set); getAlphai(AlphaiT,T_set);
-                DKiDT[i] = -_Ki[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
-                DDKiDT[i] = -_Ki[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
-                DGiDT[i] = -_Gi[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
-                DDGiDT[i] = -_Gi[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
+                getKi(q1,KiT,T_set); getGi(q1,GiT,T_set); getAlphai(AlphaiT,T_set);
+                DKiDT[i] = -KiT[i]/(_ki[i]) * Ddt_shiftDT*expdtkby2;  // Removed _ki/2 and _gi/2
+                DDKiDT[i] = -KiT[i]/(_ki[i]) * (DDdt_shiftDT - 1/(_ki[i])*pow(Ddt_shiftDT,2))*expdtkby2;
+                DGiDT[i] = -GiT[i]/(_gi[i]) * Ddt_shiftDT*expdtgby2;
+                DDGiDT[i] = -GiT[i]/(_gi[i]) * (DDdt_shiftDT - 1/(_gi[i])*pow(Ddt_shiftDT,2))*expdtgby2;
             }
 
             for (int j=0; j<3; j++){
@@ -1609,9 +1935,9 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
             STensorOperation::zero(DGammai); STensorOperation::zero(DDGammaiDT);
             DQiDT -= DOiDT; DDQiDT -= DDOiDT; DDGammaiDT -= DDOGammaiDT;
             for (int j=0; j<3; j++){
-                Qi(j,j) += (_Ki[i]*trEe - trOi[i]);
+                Qi(j,j) += (KiT[i]*trEe - trOi[i]);
                 for (int k=0; k<3; k++){
-                    Qi(j,k) += (2*_Gi[i]*devEe(j,k) - devOi[i](j,k));
+                    Qi(j,k) += (2*GiT[i]*devEe(j,k) - devOi[i](j,k));
                 }
             }
             DGammai += DEe;
@@ -1627,8 +1953,8 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
             static STensor43 temp_DDQiDTDE;
             static STensor43 temp_DDgammiDtDE;
 
-            double Ki_term = (_Ki[i]*(1-expdtkby2)+T*DKiDT[i]);
-            double Gi_term = (_Gi[i]*(1-expdtgby2)+T*DGiDT[i]);
+            double Ki_term = (KiT[i]*(1-expdtkby2)+T*DKiDT[i]);
+            double Gi_term = (GiT[i]*(1-expdtgby2)+T*DGiDT[i]);
             isotropicHookTensor( Ki_term, Gi_term , temp_DDQiDTDE );
 
             double Ki_term_2 = 1/3*expdtkby2;
@@ -1695,8 +2021,11 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
         // Compute Mechanical Tangents - dSdC and dPdF
 
         static STensor43 DcorKDE;
-        // isotropicHookTensor(Ke,Ge,DcorKDE);                                      // Hookes tensor
-        isotropicHookTensor(Ke+Kde*(T-T_temp),Ge+Gde*(T-T_temp),DcorKDE);           // Reformulate
+        isotropicHookTensor(Ke,Ge,DcorKDE);                                      // Hookes tensor
+        // isotropicHookTensor(Ke+Kde*(T-T_temp),Ge+Gde*(T-T_temp),DcorKDE);           // Reformulate
+        
+        // extraBranch - zero by default
+        DcorKDE += DsigExtraDE;
 
         static STensor43 DCeDFe; //(0.);
         static STensor43 DEeDFe(0.);
@@ -1755,8 +2084,12 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
                 }
             }
         }
-
+        
         // Compute Mechano-thermal Tangents - dSdT and dPdT
+        
+        // extraBranch - zero by default
+        DcorKirDT += DsigExtraDT;
+        
         static STensor3 DSDT;
         STensorOperation::zero(DSDT);
         for (int i=0; i<3; i++){
@@ -1804,6 +2137,7 @@ void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
             for (int i=0; i<3; i++){
                 for (int j=0; j<3; j++){
                     for (int k=0; k<3; k++){
+                        // Msg::Info("dfluxTdF->J: Jacobian= %e",J);
                         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);
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVE.h b/NonLinearSolver/materialLaw/mlawNonLinearTVE.h
index 9afdddbf5a9a02afeeeb2245871a79f064fa7457..c97804a6925d4caeae3d719a6b10952da2ea9910 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVE.h
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVE.h
@@ -15,67 +15,19 @@
 #include "STensor3.h"
 #include "STensor43.h"
 #include "STensor63.h"
-// #include "ipHyperelastic.h"
 #include "ipNonLinearTVE.h"
 #include "viscosityLaw.h"
 #include "mlawHyperelasticFailureCriterion.h"
 #include "scalarFunction.h"
 #include "mlawHyperelastic.h"
+#include "elasticPotential.h"
 
-/* Patch Notes
-
-1)            23/12/21  - NonLinearTVE adopted from mlawHyperelastic; Pure ViscoElasticity with Temp Functions for Moduli and Thermal Props (latter Still Unused)
-                            [mLAW FORMED -- .h , .cpp]
-                            Changed mu to G
-.......1.0.1) 24/12/21  - Created new IPVariable, updated dG3DMaterialLaw, update dG3DIPVariable, updated mlaw.h,
-.......1.0.2) 28/12/21  - Added the mlaw.cpp and ip.cpp to the CMakeFiles.txt in materiallaw/ and internalpoints/ respectively.
-.......1.0.3) 28/12/21  - (Tested against previous results of mlawHyperelastic in Octave const Temp results --- Works fine!!).
-
-...1.1)       29/12/21  - Updated with ThermoMechanics - (UNTESTED so far).
-.......1.1.1) 29/12/21  - Updated dG3DIPVariable with inheritance from ThermoMechanicsDG3DIPVariableBase Pure virtual class (and LinearThermoMechanicsDG3DIPVariable).
-                             - Noted that the Pure virtual base class may cause problems when introducing nonLocal Variables.
-.......1.1.2) 29/12/21  - Updated dG3DMaterialLaw with adaptations from LinearThermoMechanicsDG3DMaterial.
-.......1.1.3) 29/12/21  - Updated ipNonLinearTVE with adaptations from LinearThermoMechanicsDG3DMaterial.
-.......1.1.4) 29/12/21  - Updated mlawNonLinearTVE with adaptations from LinearThermoMechanicsDG3DMaterial.
-
-...1.2)       30/12/21  - Add Temperature BCs, add temperature extradof from dG3DIpvariable (ThermoMechanicsDG3DIPVariableBase),
-                            change the Stress calculation Function in dG3DMaterialLaw;
-.......1.2.1) 05/01/22  - linearK and stiff_alphadilatation added to ipvcur pointer in dG3Dmateriallaw.cpp through direct member functions in mlaw....TVE.h
-                                - IC Working, ScalarFluxBC Not Working!!!!!!!!!
-.......1.2.2) 06/01/22  - CleanUp!
-                                - Removed thermal props unused member functions from everywhere.
-                            - Remember to add tempFunc multiplication where needed! Note that my Tg scalarFunctions will likely not be normalised functions.
-.......1.2.3) 06/01/22  - Attempted addition of coupled ThermoMech features from ThermoElastic part of FullJ2ThermoMech...dG3DMaterialLaw
-
-...1.3)       15/02/22  - Addition of TTSP
-.......1.3.1) 22/02/22  - Addition of WLF shift factor and shifted time member functions
-.......1.3.2) 04/03/22  - Addition of convolution single/double integrals in the predictor functions
-                        - CLEANUP 1.0 -> Making mlaw and ipvariable dependent classes of mlawHyperElastic
-.......1.3.3) 14/03/22  - Thermal and mechanical source code
-.......1.3.4) 24/03/22  - Tangent and mechanical source derivatives
-.......1.3.5) 13/04/22  - CLEANUP 2.0
-.......1.3.6) 25/04/22  - Fully Corrected TVE derivatives.
-...1.4)       03/06/22  - CLEANUP 3.0 Renamed class to mlawNonLinearTVE
-.......1.4.1) 04/06/22  - Removed all Unused Code
-.......1.4.2) 07/06/22  - Added calculateStress boolean in ThermoViscoElasticPredictor -> to just update TVE flow in TVP predictorCorrector functions
- *
-.......1.?.?) ??/??/22  - Addition of new class for Psi_ve
- *
-
-2)            04/06/22  - NonLinearTVP adopted from mlawPowerYieldHyper; Temp Functions for Hardening Moduli and Yield Strengths
-                            [mLAW FORMED -- .h , .cpp, in the mlawNonLinearTVE]
-*/
 
 class mlawNonLinearTVE : public mlawPowerYieldHyper{
   protected:
 
-  // Material Properties at Room Temp. - Mechanical
-    // double _rho;        // Density
-    // double _E;          // Youngs Modulus
-    // double _nu;         // Poissons Ratio
-    // double _lambda;     // 1st Lame parameter
+  // Renaming _mu to _G
     double _G;          // 2nd Lame parameter (=mu) Shear Modulus
-    // double _K;          // Bulk Modulus
 
   // Material Properties at Room Temp. - Thermal
     double _scalarAlpha;    // (scalar) Thermal Dilatation Coefficient (=alpha)                                   - Tensor exists for Anisotropic Dilatation
@@ -86,22 +38,12 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
     STensor3 _tensorK;      // (tensor3) Thermal Conductivity (K)
 
   // ViscoElastic Data
-    // viscoelasticType _viscoMethod; // viscoelastic method 0-Maxwell, 1-Kelvin-Voight   (ENUM type variable) - TVE only works with Maxwell
-    // int _N;                        // number of elements
-    // std::vector<double> _Ki;       // vector of branch bulk moduli
-    // std::vector<double> _ki;       // vector of branch relaxation times for bulk
-    // std::vector<double> _Gi;       // vector of branch shear moduli
-    // std::vector<double> _gi;       // vector of branch relaxation times for shear
     std::vector<double> _Alphai;      // vector of branch alpha
 
   // Misc.
-    // STensor43 Cel;                          // elastic hook tensor
-    // int _order ;                            // to approximate log and exp of a tensor
     bool _thermalEstimationPreviousConfig;  // flap for thermalEstimation using PreviousConfig
 
   // Testing
-    // double _perturbationfactor;             // perturbation factor
-    // bool _tangentByPerturbation;            // flag for tangent by perturbation
     int _testFlag;                          // for various solutions to convolution
 
   // Temperature Settings and Functions
@@ -124,6 +66,14 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
   // Shift factor - Everything related to it
     double _C1;                                     // WLF Universal Constant 1 - set in .py file
     double _C2;                                     // WLF Universal Constant 2 - set in .py file
+    
+  // Mullins Effect
+    mullinsEffect* _mullinsEffect;
+    
+  // Hyperelastic Potential - Non-linear elasticity
+    elasticPotential* _elasticPotential; 
+    bool _useExtraBranch;
+    scalarFunction* _temFunc_elasticCorrection;
 
   #ifndef SWIG
   protected:
@@ -133,10 +83,23 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
                              double *t_shift = NULL, double *Ddt_shiftDT = NULL, double *DDdt_shiftDT = NULL,
                              const int opt_time = 1, const int opt_order = 2) const;
     virtual double linearInterpTemp(const double t_interp, const double t0, const double t1, const double T0, const double T1) const;
-    virtual double freeEnergyMechanical(const IPNonLinearTVE& q, const double Tc) const ;
+    virtual double freeEnergyMechanical(const IPNonLinearTVE& q, const double T0, const double T) const ;
     virtual double setTemp(const double T0, const double T1, const int para) const ;
+    
+    virtual void calculateMullinsEffectScaler(const IPNonLinearTVE* q0, IPNonLinearTVE *q1, const double T) const;
 
-    void corKirInfinity( const STensor3& devEe, const double& trEe, const double T, STensor3& CorKirDevInf, double& CorKirTrInf) const;
+    void evaluateElasticCorrection(const double trE, const STensor3 &devE, const double& T, 
+                                                 double &A_v, double &dAdE, double &intA, double &dAdT,
+                                                 double &B_d, STensor3 &dB_vddev, double &intB, double &dBdT,
+                                                 double *ddAdTT = NULL, double *ddBdTT = NULL) const;
+    
+    void extraBranchLaw(const STensor3& Ee,  const double& T, const IPNonLinearTVE *q0, IPNonLinearTVE *q1, 
+                        STensor3& sig, const bool stiff = false, STensor43* DsigDEe = NULL, STensor3* DsigDT = NULL, 
+                        double* DsigV_dTrEe = NULL, STensor43* DsigD_dDevEe = NULL,
+                        double* DsigV_dT = NULL, STensor3* DsigD_dT = NULL,
+                        double* DDsigV_dTT = NULL, STensor3* DDsigD_dTT = NULL) const;
+
+    void corKirInfinity(const IPNonLinearTVE *q1, const STensor3& devEe, const double& trEe, const double T, STensor3& CorKirDevInf, double& CorKirTrInf) const;
     void ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
           const IPNonLinearTVE *q0, IPNonLinearTVE *q1,
           double& Ke, double& Ge, double& Kde, double& Gde,
@@ -206,6 +169,11 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
 
     // Virtual Destructor
     virtual ~mlawNonLinearTVE();
+    
+    void setMullinsEffect(const mullinsEffect& mullins){
+        if (_mullinsEffect) delete _mullinsEffect;
+            _mullinsEffect = mullins.clone();
+    };
 
   // Non-Const Functions for strain_order and VE data that are called from .py file.  ---- These WILL change the values of the variables defined in the class object.
     virtual void setViscoElasticNumberOfElement(const int N);
@@ -222,6 +190,7 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
     virtual void setModelOption(const int modelFlag){_modelFlag = modelFlag;};
     virtual void setTestOption(const int testFlag){_testFlag = testFlag;};
     void setShiftFactorConstantsWLF(const double C1, const double C2){_C1 = C1; _C2 = C2;};
+    virtual void useExtraBranchBool(const bool useExtraBranch){_useExtraBranch = useExtraBranch;};
     void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
      if (_temFunc_K != NULL) delete _temFunc_K;
       _temFunc_K = Tfunc.clone();
@@ -242,6 +211,10 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
       if (_temFunc_Cp != NULL) delete _temFunc_Cp;
       _temFunc_Cp = Tfunc.clone();
     }
+    void setTemperatureFunction_ElasticCorrection(const scalarFunction& Tfunc){
+      if (_temFunc_elasticCorrection != NULL) delete _temFunc_elasticCorrection;
+      _temFunc_elasticCorrection = Tfunc.clone();
+    }
     void setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc,int i){
        if (i> _N or i<1)
          Msg::Error("This setting is invalid %d > %d",i,_N);
@@ -265,6 +238,8 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
 
 // Const Functions to get temp-updated values of material properties - Args by reference, or return the variable.
 
+    virtual const mullinsEffect* getConstRefToMullinsEffect() const {return _mullinsEffect;};
+        
     virtual std::vector<double> getBetai(const double _K, const std::vector<double> _Ki) const{
         std::vector<double> Beta_i;
         Beta_i.resize(_N,0.);
@@ -274,22 +249,24 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
         return Beta_i;
     }
 
-    virtual void getK(double& KT, const double Tc, double *dK = NULL, double *ddK = NULL) const{
-        KT = _K*_temFunc_K->getVal(Tc);
+    virtual void getK(const IPNonLinearTVE *q1, double& KT, const double Tc, double *dK = NULL, double *ddK = NULL) const{
+        double K = _K; // *q1->getConstRefToElasticBulkPropertyScaleFactor();
+        KT = K*_temFunc_K->getVal(Tc);
         if(dK!=NULL){
-            *dK=_K*_temFunc_K->getDiff(Tc);  // Here, *dK can be imagined as *(dK+0) or dK[0] if dK were a vector. See dKi below.
+            *dK = K*_temFunc_K->getDiff(Tc);  // Here, *dK can be imagined as *(dK+0) or dK[0] if dK were a vector. See dKi below.
         }
         if(ddK!=NULL){
-            *ddK = _K*_temFunc_K->getDoubleDiff(Tc);
+            *ddK = K*_temFunc_K->getDoubleDiff(Tc);
         }
     }
-    virtual void getG(double& GT, const double Tc, double *dG = NULL, double *ddG = NULL) const{
-        GT = _G*_temFunc_G->getVal(Tc);
+    virtual void getG(const IPNonLinearTVE *q1, double& GT, const double Tc, double *dG = NULL, double *ddG = NULL) const{
+        double G = _G; // *q1->getConstRefToElasticShearPropertyScaleFactor();
+        GT = G*_temFunc_G->getVal(Tc);
         if(dG!=NULL){
-            *dG = _G*_temFunc_G->getDiff(Tc);
+            *dG = G*_temFunc_G->getDiff(Tc);
         }
         if(ddG!=NULL){
-            *ddG = _G*_temFunc_G->getDoubleDiff(Tc);
+            *ddG = G*_temFunc_G->getDoubleDiff(Tc);
         }
     }
      virtual void getAlpha(double& alphaT, const double Tc, double *dAlpha = NULL, double *ddAlpha = NULL) const{
@@ -318,29 +295,39 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
     }
 
     // The 3rd argument is a pointer to a vector.
-    virtual void getKi(std::vector<double>& Ki_T, const double Tc, std::vector<double>* dKi=NULL, std::vector<double>* ddKi=NULL) const{
+    virtual void getKi(const IPNonLinearTVE *q1, std::vector<double>& Ki_T, const double Tc, std::vector<double>* dKi=NULL, std::vector<double>* ddKi=NULL) const{
+        std::vector<double> Ki;
+        Ki.clear(); Ki.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+          Ki[i] = _Ki[i]; // *(1+q1->getConstRefToElasticBulkPropertyScaleFactor());  
+        }
         Ki_T.resize(_N,0.);
         for (int i=0; i<_Ki.size();i++){
-            Ki_T[i] = _Ki[i]*_temFunc_Ki[i]->getVal(Tc);
+            Ki_T[i] = Ki[i]*_temFunc_Ki[i]->getVal(Tc);
             if(dKi!=NULL){
-                dKi->at(i) = _Ki[i]*_temFunc_Ki[i]->getDiff(Tc);
+                dKi->at(i) = Ki[i]*_temFunc_Ki[i]->getDiff(Tc);
             }
             if(ddKi!=NULL){
-                ddKi->at(i) = _Ki[i]*_temFunc_Ki[i]->getDoubleDiff(Tc);
+                ddKi->at(i) = Ki[i]*_temFunc_Ki[i]->getDoubleDiff(Tc);
             }
         }
     }
 
     // The 3rd argument is a pointer to a vector.
-    virtual void getGi(std::vector<double>& Gi_T, const double Tc, std::vector<double>* dGi=NULL, std::vector<double>* ddGi=NULL) const{
+    virtual void getGi(const IPNonLinearTVE *q1, std::vector<double>& Gi_T, const double Tc, std::vector<double>* dGi=NULL, std::vector<double>* ddGi=NULL) const{
+        std::vector<double> Gi;
+        Gi.clear(); Gi.resize(_N,0.);
+        for (int i=0; i<_Gi.size();i++){
+          Gi[i] = _Gi[i]; // *(1+q1->getConstRefToElasticShearPropertyScaleFactor());  
+        }
         Gi_T.resize(_N,0.);
         for (int i=0; i<_Gi.size();i++){
-            Gi_T[i] = _Gi[i]*_temFunc_Gi[i]->getVal(Tc);
+            Gi_T[i] = Gi[i]*_temFunc_Gi[i]->getVal(Tc);
             if(dGi!=NULL){
-                dGi->at(i) = _Gi[i]*_temFunc_Gi[i]->getDiff(Tc); // *(dGi+i) is equivalent to dGi[i]
+                dGi->at(i) = Gi[i]*_temFunc_Gi[i]->getDiff(Tc); // *(dGi+i) is equivalent to dGi[i]
             }
             if(ddGi!=NULL){
-                ddGi->at(i) = _Gi[i]*_temFunc_Gi[i]->getDoubleDiff(Tc);
+                ddGi->at(i) = Gi[i]*_temFunc_Gi[i]->getDoubleDiff(Tc);
             }
         }
     }
@@ -389,7 +376,7 @@ class mlawNonLinearTVE : public mlawPowerYieldHyper{
 // Some more Member Functions
 
     virtual matname getType() const{return materialLaw::nonlinearTVE;}    // function of materialLaw
-    virtual void createIPState(IPStateBase* &ips,const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const{
+    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("mlawNonLinearTVE::createIPState has not been defined");
     };
     virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}; // this law is initialized so nothing to do
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
index 92c664607a4bf1bf4e8edd9a75bfb4b63c028c75..4cce52295a26180235091936ebd2fb047f7f8aa9 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
@@ -18,20 +18,27 @@ mlawNonLinearTVP::mlawNonLinearTVP(const int num,const double E,const double nu,
                                    const double Tinitial, const double Alpha, const double KThCon, const double Cp,
                                    const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
                                    mlawNonLinearTVE(num, E, nu, rho, tol, Tinitial, Alpha, KThCon, Cp, matrixbyPerturbation, pert, thermalEstimationPreviousConfig),
-                                   _TaylorQuineyFactor(0.9), _HR(1.){
+                                   _TaylorQuineyFactor(0.9), _TaylorQuineyFlag(false),_PolyOrderChaboche(0), _HR(1.){
+
+      _PolyCoeffsChaboche.resize(_PolyOrderChaboche+1);
+      _PolyCoeffsChaboche.setAll(0.);
+      _PolyCoeffsChaboche(0) = 1.;
 
       // by default, no temperature dependence
       _temFunc_Sy0 = new constantScalarFunction(1.);
       _temFunc_H = new constantScalarFunction(1.);
       _temFunc_Hb = new constantScalarFunction(1.);
       _temFunc_visc = new constantScalarFunction(1.);
-         
+
 };
 
 // , mlawPowerYieldHyper(src)
 mlawNonLinearTVP::mlawNonLinearTVP(const mlawNonLinearTVP& src): mlawNonLinearTVE(src) {
-    
+
     _TaylorQuineyFactor = src._TaylorQuineyFactor;
+    _TaylorQuineyFlag = src._TaylorQuineyFlag;
+    _PolyOrderChaboche = src._PolyOrderChaboche;
+    _PolyCoeffsChaboche = src._PolyCoeffsChaboche;
     _HR = src._HR;
 
   _temFunc_Sy0 = NULL; // temperature dependence of initial yield stress
@@ -42,23 +49,29 @@ mlawNonLinearTVP::mlawNonLinearTVP(const mlawNonLinearTVP& src): mlawNonLinearTV
   if (src._temFunc_H != NULL){
     _temFunc_H = src._temFunc_H->clone();
   }
-  
+
   _temFunc_Hb = NULL; // temperature dependence of kinematic hardening
   if (src._temFunc_Hb != NULL)
     _temFunc_Hb = src._temFunc_Hb->clone();
-    
+
   _temFunc_visc = NULL; // temperature dependence of viscosity
   if (src._temFunc_visc != NULL)
     _temFunc_visc = src._temFunc_visc->clone();
 };
 
 mlawNonLinearTVP& mlawNonLinearTVP::operator=(const materialLaw& source){
-    
+
     mlawNonLinearTVE::operator=(source);
     // mlawPowerYieldHyper::operator=(source);
     const mlawNonLinearTVP* src =dynamic_cast<const mlawNonLinearTVP*>(&source);
     if(src != NULL){
         _TaylorQuineyFactor = src->_TaylorQuineyFactor;
+        _TaylorQuineyFlag = src->_TaylorQuineyFlag;
+        _PolyOrderChaboche = src->_PolyOrderChaboche;
+
+        _PolyCoeffsChaboche.resize(src->_PolyCoeffsChaboche.size());
+        _PolyCoeffsChaboche.setAll(src->_PolyCoeffsChaboche);
+
         _HR = src->_HR;
         if(_temFunc_Sy0 != NULL) delete _temFunc_Sy0; // temperature dependence of initial yield stress
         if (src->_temFunc_Sy0!= NULL)
@@ -78,8 +91,8 @@ mlawNonLinearTVP& mlawNonLinearTVP::operator=(const materialLaw& source){
 
 mlawNonLinearTVP::~mlawNonLinearTVP(){
     if (_temFunc_Sy0 != NULL) delete _temFunc_Sy0;  _temFunc_Sy0 = NULL;
-    if (_temFunc_H != NULL) delete _temFunc_H; _temFunc_H= NULL;  
-    if (_temFunc_Hb != NULL) delete _temFunc_Hb; _temFunc_Hb= NULL;  
+    if (_temFunc_H != NULL) delete _temFunc_H; _temFunc_H= NULL;
+    if (_temFunc_Hb != NULL) delete _temFunc_Hb; _temFunc_Hb= NULL;
     if (_temFunc_visc != NULL) delete _temFunc_visc; _temFunc_visc= NULL;
 };
 
@@ -109,55 +122,83 @@ void mlawNonLinearTVP::hardening(const IPNonLinearTVP* q0, IPNonLinearTVP* q1, c
 };
 
 void mlawNonLinearTVP::getModifiedMandel(const STensor3& C, const IPNonLinearTVP *q0, IPNonLinearTVP *q1) const{
-    
+
     STensor3& M = q1->getRefToModifiedMandel();
     const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
-    
+
     STensor3 Cinv;
     STensorOperation::inverseSTensor3(C, Cinv);
-    
+
     STensor3 temp1, temp2;
     STensorOperation::multSTensor3(C, corKir, temp1);
     STensorOperation::multSTensor3(temp1, Cinv, temp2);
-    
+
     M = 0.5*(corKir + temp2);
 };
 
 void mlawNonLinearTVP::checkCommutavity(STensor3& commuteCheck,const STensor3& Ce, const STensor3& S, const IPNonLinearTVP *q1) const{
-    
+
     const STensor3& M = q1->getConstRefToModifiedMandel();
     const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
-    
+
     STensor3 temp1, temp2, temp3, temp4, temp6;
     STensorOperation::multSTensor3(Ce, S, temp1);
     STensorOperation::multSTensor3(S, Ce, temp2);
     STensorOperation::multSTensor3(corKir, Ce, temp3);
     STensorOperation::multSTensor3(Ce, corKir, temp4);
-    
-    // Check S 
+
+    // Check S
     commuteCheck = temp1;
     commuteCheck -= temp2;
-    
+
     // Check corKir (just for fun)
     temp6 = temp3;
     temp6 -= temp4;
-    
+
     // RANK OF A ZERO TENSOR is ZERO - maybe use this?
 };
 
-void mlawNonLinearTVP::getChabocheCoeffs(fullVector<double>& coeffs, const double& opt, const IPNonLinearTVP *q1) const{
+void mlawNonLinearTVP::setPolynomialOrderChabocheCoeffs(const int order){_PolyOrderChaboche = order;};
+
+void mlawNonLinearTVP::setPolynomialCoeffsChabocheCoeffs(const int i, const double val){
+    _PolyCoeffsChaboche(i) = val;
+    Msg::Info("setting: term=%d PolyCoeffsChaboche= %e",i,val);
+}
+
+void mlawNonLinearTVP::getChabocheCoeffs(fullVector<double>& coeffs, const double& opt, const IPNonLinearTVP *q1, std::vector<double>* dcoeffs) const{
 
-    double p = q1->_epspbarre; // eq.plastic strain
+    const double p = q1->_epspbarre; // eq.plastic strain
     coeffs.resize(2);
-    
-    coeffs(0) = 1; // 1; //DEBUGGING 
-    coeffs(1) = 0;
-    
-    // add dependency on p later
+
+    coeffs(0) = 1; // 0; //DEBUGGING
+    coeffs(1) = 0; // 0; //DEBUGGING
+
+
+    if(dcoeffs!=NULL){
+        dcoeffs->resize(2);
+        dcoeffs->at(0) = 1;
+        dcoeffs->at(1) = 0;
+    }
+    if (opt==1){
+        if (_PolyOrderChaboche == 1){
+            coeffs(0) += _PolyCoeffsChaboche(0)+ _PolyCoeffsChaboche(1)*p;
+            if(dcoeffs!=NULL){dcoeffs->at(0) += _PolyCoeffsChaboche(1);}
+        }
+        else if (_PolyOrderChaboche == 2){
+            coeffs(0) += _PolyCoeffsChaboche(0)+ _PolyCoeffsChaboche(1)*p + _PolyCoeffsChaboche(2)*p*p;
+            if(dcoeffs!=NULL){dcoeffs->at(0) += _PolyCoeffsChaboche(1)+2.*_PolyCoeffsChaboche(2)*p;}
+        }
+        else if (_PolyOrderChaboche == 3){
+            coeffs(0) += _PolyCoeffsChaboche(0)+ _PolyCoeffsChaboche(1)*p + _PolyCoeffsChaboche(2)*p*p+_PolyCoeffsChaboche(3)*p*p*p;
+            if(dcoeffs!=NULL){dcoeffs->at(0) +=  _PolyCoeffsChaboche(1)+2.*_PolyCoeffsChaboche(2)*p+ 3*_PolyCoeffsChaboche(3)*p*p;}
+        }
+        else
+            Msg::Error("order %d is not implemented in PolynomialChacbocheCoeffs of mlawNonLinearTVP::getChabocheCoeffs",_PolyOrderChaboche);
+    }
 };
 
 void mlawNonLinearTVP::getPlasticPotential(const double& phiP, const double& phiE, double& Px) const{
-    
+
     Px = pow(phiE,2) + _b*pow(phiP,2);
 };
 
@@ -167,7 +208,7 @@ void mlawNonLinearTVP::getYieldCoefficientTempDers(const IPNonLinearTVP *q1, con
   Hc = q1->_ipCompression->getDR();
   dsigcdT = q1->_ipCompression->getDRDT();
   ddsigcdTT = q1->_ipCompression->getDDRDTT();
-  
+
 
   double sigt(0.), Ht(0.), dsigtdT(0.), ddsigtdTT(0.);
   sigt = q1->_ipTraction->getR();
@@ -179,23 +220,23 @@ void mlawNonLinearTVP::getYieldCoefficientTempDers(const IPNonLinearTVP *q1, con
   DcoeffsDT.resize(3);
   DDcoeffsDTT.resize(3);
   double m = sigt/sigc;
-  double DmDT = (dsigtdT*sigc- sigt*dsigcdT)/(sigc*sigc); 
-  double DDmDTT = (ddsigtdTT*sigc - sigt*ddsigcdTT)/(sigc*sigc) - 2*(dsigtdT*sigc- sigt*dsigcdT)/(sigc*sigc*sigc)*dsigcdT;
+  double DmDT = (dsigtdT*sigc- sigt*dsigcdT)/(sigc*sigc);
+  double DDmDTT = (ddsigtdTT*sigc - sigt*ddsigcdTT)/(sigc*sigc) - 2.*(dsigtdT*sigc- sigt*dsigcdT)/(sigc*sigc*sigc)*dsigcdT;
   double Da1Dm = 3./sigc*(_n*pow(m,_n-1.)/(m+1.) - (pow(m,_n)-1.)/(m+1.)/(m+1.));
-  double DDa1Dmm = 3./sigc*(_n*(_n-1)*pow(m,_n-2.)/(m+1.) - _n*(pow(m,_n)-1.)/(m+1.)/(m+1.) - _n*pow(m,_n-1)/(m+1.)/(m+1.) + 2.*(pow(m,_n)-1.)/(m+1.)/(m+1.)/(m+1.));
+  double DDa1Dmm = 3./sigc*(_n*(_n-1.)*pow(m,_n-2.)/(m+1.) - _n*(pow(m,_n)-1.)/(m+1.)/(m+1.) - _n*pow(m,_n-1)/(m+1.)/(m+1.) + 2.*(pow(m,_n)-1.)/(m+1.)/(m+1.)/(m+1.));
   double term = _n*pow(m,_n) + _n*pow(m,_n-1.) - pow(m,_n);
-  double dterm = pow(_n,2)*pow(m,_n-1.) + _n*(_n-1)*pow(m,_n-2.) - _n*pow(m,_n-1);
+  double dterm = pow(_n,2.)*pow(m,_n-1.) + _n*(_n-1)*pow(m,_n-2.) - _n*pow(m,_n-1.);
 
   DcoeffsDT(2) = -_n*pow(sigc,-_n-1.)*dsigcdT;
-  DcoeffsDT(1) = Da1Dm*DmDT - 3.*(pow(m,_n)-1.)/(m+1.)/(sigc*sigc)*dsigcdT;
-  DcoeffsDT(0) = ((_n*pow(m,_n-1)+1.)/(m+1) - (pow(m,_n)+m)/(m+1.)/(m+1.))*DmDT;
-  
-  DDcoeffsDTT(2) = -_n*pow(sigc,-_n-1.)*ddsigcdTT -_n*(-_n-1)*pow(sigc,-_n-2.)*dsigcdT*dsigcdT;
-  DDcoeffsDTT(1) = -1/sigc*dsigcdT*DcoeffsDT(1) + 3/sigc*( (dterm/(m+1.)/(m+1.) -2*term/(m+1.)/(m+1.)/(m+1.))*DmDT*DmDT + term/(m+1.)/(m+1.)*DDmDTT
-                   + 1/sigc*( (1/sigc*pow(dsigtdT,2) - ddsigcdTT) * (pow(m,_n)-1.)/(m+1.)  + dsigtdT * term/(m+1.)/(m+1.) ) );
-  DDcoeffsDTT(0) = ((_n*pow(m,_n-1)+1.)/(m+1) - (pow(m,_n)+m)/(m+1.)/(m+1.))*DDmDTT 
-                    + ((_n*(_n-1)*pow(m,_n-2))/(m+1) + 2*(pow(m,_n)+m)/(m+1.)/(m+1.)/(m+1.))*DmDT*DmDT;
-    
+  DcoeffsDT(1) = Da1Dm*DmDT + 3.*(pow(m,_n)-1.)/(m+1.)/(sigc*sigc)*dsigcdT;
+  DcoeffsDT(0) = ((_n*pow(m,_n-1.)+1.)/(m+1.) - (pow(m,_n)+m)/(m+1.)/(m+1.))*DmDT;
+
+  DDcoeffsDTT(2) = -_n*pow(sigc,-_n-1.)*ddsigcdTT -_n*(-_n-1.)*pow(sigc,-_n-2.)*dsigcdT*dsigcdT;
+  DDcoeffsDTT(1) = -1./sigc*dsigcdT*DcoeffsDT(1) + 3./sigc*( (dterm/(m+1.)/(m+1.) -2.*term/(m+1.)/(m+1.)/(m+1.))*DmDT*DmDT + term/(m+1.)/(m+1.)*DDmDTT
+                   + 1./sigc*( (1./sigc*pow(dsigtdT,2.) - ddsigcdTT) * (pow(m,_n)-1.)/(m+1.)  + dsigtdT * term/(m+1.)/(m+1.) ) );
+  DDcoeffsDTT(0) = ((_n*pow(m,_n-1.)+1.)/(m+1) - (pow(m,_n)+m)/(m+1.)/(m+1.))*DDmDTT
+                    + ((_n*(_n-1.)*pow(m,_n-2.))/(m+1.) + 2.*(pow(m,_n)+m)/(m+1.)/(m+1.)/(m+1.))*DmDT*DmDT;
+
 };
 
 void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T,
@@ -208,30 +249,30 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
     const STensor3& Me = q1->_ModMandel;
     const STensor3& X = q1->_backsig;
     const STensor3& dXdT  = q1->_DbackSigDT;
-    
+
     STensor3 devMe, devX, dDevXdT, dDevMeDT;
     double trMe, trX, dTrXdT, dTrMeDT;
-    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,trMe); 
-    STensorOperation::decomposeDevTr(q1->_backsig,devX,trX); 
-    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dTrXdT); 
+    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,trMe);
+    STensorOperation::decomposeDevTr(q1->_backsig,devX,trX);
+    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dTrXdT);
     STensorOperation::decomposeDevTr(q1->_DModMandelDT,dDevMeDT,dTrMeDT);
-    
+
     // Start
     double psiVE, psiVP, psiT = 0.;
     double DpsiVEdT, DpsiVPdT, DpsiTdT = 0.;
     double DDpsiVEdTT, DDpsiVPdTT, DpsiTdTT = 0.;
-    
+
     double CpT, DCpDT, DDCpDTT;
     mlawNonLinearTVE::getCp(CpT,T,&DCpDT,&DDCpDTT);
-    
-    // psiT 
+
+    // psiT
     psiT = CpT*((T-_Tinitial)-T*log(T/_Tinitial));
     DpsiTdT = -CpT*log(T/_Tinitial) - psiT/CpT*DCpDT;
     DpsiTdTT = -CpT/T - psiT/CpT*DDCpDTT;
-    
+
     //
     // psiVP
-    
+
     // get R, dRdT
     fullVector<double> a(3), Da(3), DaDT(3), DDaDTT(3);
     getYieldCoefficients(q1,a);
@@ -242,31 +283,31 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
     Hc = q1->_ipCompression->getDR();
     dsigcdT = q1->_ipCompression->getDRDT();
     ddsigcdTT = q1->_ipCompression->getDDRDTT();
-    
+
     double R1(0.), R2(0.), R3(0.), dR1dT(0.), dR2dT(0.), dR3dT(0.), ddR1dTT(0.), ddR2dTT(0.), ddR3dTT(0.);
-    
+
     const std::vector<double>& IsoHardForce =  q1->_IsoHardForce;
     const std::vector<double>& dIsoHardForcedT =  q1->_dIsoHardForcedT;
     const std::vector<double>& ddIsoHardForcedTT =  q1->_ddIsoHardForcedTT;
-    
+
     R1 = IsoHardForce[0]; R2 = IsoHardForce[1]; R3 = IsoHardForce[2];
     dR1dT = dIsoHardForcedT[0]; dR2dT = dIsoHardForcedT[1]; dR3dT = dIsoHardForcedT[2];
     ddR1dTT = ddIsoHardForcedTT[0]; ddR2dTT = ddIsoHardForcedTT[1]; ddR3dTT = ddIsoHardForcedTT[2];
-    
+
      // get Kinematic Hardening stuff
     double Hb(0.), dHbdT(0.), ddHbddT(0.);
     if (q1->_ipKinematic != NULL){
         Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
         dHbdT = q1->_ipKinematic->getDRDT();
-        ddHbddT = q1->_ipKinematic->getDDRDDT();
+        ddHbddT = q1->_ipKinematic->getDDRDTT();
     }
 
     double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
     static STensor3 alpha;
     alpha = X;
     alpha *= 1/(pow(kk,2)*Hb);
-    
-    // ddXdTT 
+
+    // ddXdTT
     static STensor3 ddXdTT; // ddGammaDTT and ddQDTT are very difficult to estimate
     STensorOperation::zero(ddXdTT);
     double delT = T-T0;
@@ -276,12 +317,12 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
          ddXdTT(i,j) += 2*dXdT(i,j)/(T-T0) - 2*(X(i,j)-q0->_backsig(i,j))/pow((T-T0),2);
        }
     }
-    
+
     static STensor3 dAlphadT, ddAlphadTT;
     for (int i=0; i<3; i++)
       for (int j=0; j<3; j++){
         dAlphadT(i,j) = dXdT(i,j)*1/(pow(kk,2)*Hb) - X(i,j)*1/(pow(kk*Hb,2))*dHbdT;
-        ddAlphadTT(i,j) = ddXdTT(i,j)*1/(pow(kk,2)*Hb) - 2*dXdT(i,j)*1/(pow(kk*Hb,2))*dHbdT 
+        ddAlphadTT(i,j) = ddXdTT(i,j)*1/(pow(kk,2)*Hb) - 2*dXdT(i,j)*1/(pow(kk*Hb,2))*dHbdT
                         - X(i,j)*( -2/(pow(kk*Hb,3))*dHbdT*dHbdT +  1/(pow(kk*Hb,2))*ddHbddT);
       }
 
@@ -289,28 +330,28 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
     STensorOperation::doubleContractionSTensor3(X,alpha,psiVP);
     psiVP *= 0.5;
     psiVP += 0.5*( 1/_HR[0]*R1*a(1)*sigc + 1/_HR[1]*pow(R2,2) + 1/_HR[2]*pow(R3,2) );
-    
+
     for (int i=0; i<3; i++)
       for (int j=0; j<3; j++){
         DpsiVPdT += 0.5*(dXdT(i,j)*alpha(i,j)+X(i,j)*dAlphadT(i,j));
         DDpsiVPdTT += 0.5*(ddXdTT(i,j)*alpha(i,j) + 2*dXdT(i,j)*dAlphadT(i,j) + X(i,j)*ddAlphadTT(i,j));
       }
     DpsiVPdT += 0.5*( 1/_HR[0]*(dR1dT*a(1)*sigc + R1*(DaDT(1)*sigc + a(1)*dsigcdT)) + 2/_HR[1]*R2*dR2dT + 2/_HR[2]*R3*dR3dT );
-    
+
     DDpsiVPdTT += 0.5*( 1/_HR[0]*(ddR1dTT*a(1)*sigc + 2*dR1dT*(DaDT(1)*sigc + a(1)*dsigcdT) + R1*(DDaDTT(1)*sigc + 2*DaDT(1)*dsigcdT + a(1)*ddsigcdTT))
                 + 2/_HR[1]*R2*ddR2dTT + 2/_HR[2]*R3*ddR3dTT  + 2/_HR[1]*dR2dT*dR2dT + 2/_HR[2]*dR3dT*dR3dT); // CHANGE!!  2nd derivative of R and X are difficult
-    
+
     //
     // psiVE
-    
-    double KT, GT, cteT, dKdT, ddKdTT, dGdT, ddGdTT, DcteDT, DDcteDTT; getK(KT,T,&dKdT,&ddKdTT); getG(GT,T,&dGdT,&ddGdTT); getAlpha(cteT,T,&DcteDT,&DDcteDTT);
-    
+
+    double KT, GT, cteT, dKdT, ddKdTT, dGdT, ddGdTT, DcteDT, DDcteDTT; getK(q1,KT,T,&dKdT,&ddKdTT); getG(q1,GT,T,&dGdT,&ddGdTT); getAlpha(cteT,T,&DcteDT,&DDcteDTT);
+
     const STensor3& E = q1->getConstRefToElasticStrain();
     static STensor3 devKeinf, DdevKeinfDT, DDdevKeinfDTT, devEe;
     static double trKeinf, DtrKeinfDT, DDtrKeinfDTT, trEe;
     STensorOperation::decomposeDevTr(E,devEe,trEe);
-    mlawNonLinearTVE::corKirInfinity(devEe,trEe,T,devKeinf,trKeinf);
-    
+    mlawNonLinearTVE::corKirInfinity(q1,devEe,trEe,T,devKeinf,trKeinf);
+
     DtrKeinfDT = trKeinf*dKdT/KT - 3*KT*(DcteDT*(T-_Tinitial) + cteT);
     DDtrKeinfDTT = trKeinf*ddKdTT/KT - 6*dKdT*(DcteDT*(T-_Tinitial) + cteT)- 3*KT*(DDcteDTT*(T-_Tinitial) + 2*DcteDT);
     DdevKeinfDT = devKeinf;
@@ -324,31 +365,33 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
     const std::vector<double>& trDOiDT = q1->getConstRefToTrDOiDT();
     const std::vector<STensor3>& devDDOiDTT = q1->getConstRefToDevDDOiDTT();
     const std::vector<double>& trDDOiDTT = q1->getConstRefToTrDDOiDTT();
-        
-    psiVE = mlawNonLinearTVE::freeEnergyMechanical(*q1,T);
-    
+
+    psiVE = mlawNonLinearTVE::freeEnergyMechanical(*q1,T0,T);
+
     DpsiVEdT = 1/9 * (1/KT * trKeinf * DtrKeinfDT - 1/(2*pow(KT,2)) * dKdT * pow(trKeinf,2));
-    DDpsiVEdTT = 1/9 * (1/KT * (pow(DtrKeinfDT,2)+trKeinf*DDtrKeinfDTT) - 1/pow(KT,2)*dKdT*trKeinf*DtrKeinfDT 
-                        - 1/(2*pow(KT,2)) *(ddKdTT*pow(trKeinf,2) + 2*dKdT*trKeinf*DtrKeinfDT) 
-                        + 1/pow(KT,3)*pow(dKdT,2)*pow(trKeinf,2)); 
+    DDpsiVEdTT = 1/9 * (1/KT * (pow(DtrKeinfDT,2)+trKeinf*DDtrKeinfDTT) - 1/pow(KT,2)*dKdT*trKeinf*DtrKeinfDT
+                        - 1/(2*pow(KT,2)) *(ddKdTT*pow(trKeinf,2) + 2*dKdT*trKeinf*DtrKeinfDT)
+                        + 1/pow(KT,3)*pow(dKdT,2)*pow(trKeinf,2));
     for (int i=0; i<3; i++)
       for (int j=0; j<3; j++){
         DpsiVEdT += 2/GT * devKeinf(i,j)*DdevKeinfDT(i,j) - 1/pow(GT,2) * dGdT * devKeinf(i,j)*devKeinf(i,j);
-        DDpsiVEdTT += 2/GT*(DdevKeinfDT(i,j)*DdevKeinfDT(i,j) + devKeinf(i,j)*DDdevKeinfDTT(i,j) - dGdT*devKeinf(i,j)*DdevKeinfDT(i,j)) 
+        DDpsiVEdTT += 2/GT*(DdevKeinfDT(i,j)*DdevKeinfDT(i,j) + devKeinf(i,j)*DDdevKeinfDTT(i,j) - dGdT*devKeinf(i,j)*DdevKeinfDT(i,j))
                       - 1/pow(GT,2) * (ddGdTT*devKeinf(i,j)*devKeinf(i,j) + 2*dGdT*devKeinf(i,j)*DdevKeinfDT(i,j));
       }
     if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+      std::vector<double> KiT, GiT; KiT.resize(_N,0.); GiT.resize(_N,0.);
+      getKi(q1,KiT,T); getGi(q1,GiT,T);
       for (int k=0; k<_Gi.size(); k++){
-        DpsiVEdT += 1/9 * 1/_Ki[k] * trOi[k] * trDOiDT[k];
-        DDpsiVEdTT += 1/9 * 1/_Ki[k] * (trOi[k]*trDDOiDTT[k] + pow(trDOiDT[k],2));
+        DpsiVEdT += 1/9 * 1/KiT[k] * trOi[k] * trDOiDT[k];
+        DDpsiVEdTT += 1/9 * 1/KiT[k] * (trOi[k]*trDDOiDTT[k] + pow(trDOiDT[k],2));
         for (int i=0; i<3; i++)
           for (int j=0; j<3; j++){
-            DpsiVEdT += 2/_Gi[k] * devOi[k](i,j) * devDOiDT[k](i,j);
-            DDpsiVEdTT += 2/_Gi[k] * (devOi[k](i,j) * devDDOiDTT[k](i,j) + pow(devDOiDT[k](i,j),2));
-          }    
+            DpsiVEdT += 2/GiT[k] * devOi[k](i,j) * devDOiDT[k](i,j);
+            DDpsiVEdTT += 2/GiT[k] * (devOi[k](i,j) * devDDOiDTT[k](i,j) + pow(devDOiDT[k](i,j),2));
+          }
         }
     }
-    
+
     // FINALLY
     if(psiTVM!=NULL){
         *psiTVM = psiT + psiVE + psiVP;
@@ -363,285 +406,200 @@ void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP
 };
 
 void mlawNonLinearTVP::getIsotropicHardeningForce(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
-                                      const STensor3& DphiPDF, std::vector<double>* ddRdTT, std::vector<STensor3>* ddRdFdT) const{
-     
-    const double& Gamma_0 = q0->_Gamma;
-    const double& Gamma = q1->_Gamma;
+                                      double* ddRdTT, STensor3* ddRdFdT) const{
+
     const double& DgammaDT = q1->_DgammaDT;
-    const double& dGammaDT_0 = q0->_DGammaDT;
-    const double& dGammaDT = 0.; // q1->_DGammaDT; = 0. for debugging //DEBUGGING
     const STensor3& DgammaDF = q1->_DgammaDF;
-    const STensor3& DGammaDF = q1->_DGammaDF;
-    const double& gamma0 = q0->_epspbarre;
-    const double& gamma1 = q1->_epspbarre;
-    
-    static STensor3 devMe, devX1, dDevXdT, dDevMeDT;
-    static double trMe, trX1, dTrXdT, dTrMeDT;
-    static double trMe_0, trX1_0, dTrXdT_0, dTrMeDT_0;
-    
-    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,trMe); 
-    STensorOperation::decomposeDevTr(q0->_ModMandel,devMe,trMe_0); 
-    STensorOperation::decomposeDevTr(q1->_backsig,devX1,trX1); 
-    STensorOperation::decomposeDevTr(q0->_backsig,devX1,trX1_0); 
-    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dTrXdT); 
-    STensorOperation::decomposeDevTr(q0->_DbackSigDT,dDevXdT,dTrXdT_0); 
-    STensorOperation::decomposeDevTr(q1->_DModMandelDT,dDevMeDT,dTrMeDT);
-    STensorOperation::decomposeDevTr(q0->_DModMandelDT,dDevMeDT,dTrMeDT_0);
-    
-    trMe /= 3; trX1 /= 3; dTrMeDT /= 3; dTrXdT /= 3;  
-    trMe_0 /= 3; trX1_0 /= 3; dTrMeDT_0 /= 3; dTrXdT_0 /= 3;  
 
-    dTrMeDT = 0.; dTrXdT = 0.; // for debugging only //DEBUGGING 
-    
-    // get Dgamma
-    double Dgamma = gamma1 - gamma0;
-    
-    // get R
-    double eta(0.),Deta(0.),DetaDT(0.),DDetaDTT(0.);
-    fullVector<double> a(3), Da(3), DaDT(3), DDaDTT(3);
-    getYieldCoefficients(q1,a);
-    getYieldCoefficientDerivatives(q1,q1->_nup,Da);
-    getYieldCoefficientTempDers(q1,T,DaDT,DDaDTT);
-    
-    if (_viscosity != NULL)
-        _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT,DDetaDTT);
-    double etaOverDt = eta/this->getTimeStep();
-    double viscoTerm = etaOverDt*Gamma;
-    
-    const std::vector<double>& R0 = q0->_IsoHardForce;
-    std::vector<double>& R = q1->_IsoHardForce; 
-    const std::vector<double>& dRdT_0 = q0->_dIsoHardForcedT; 
-    std::vector<double>& dRdT = q1->_dIsoHardForcedT;
-    R.resize(3,0.);
-    dRdT.resize(3,0.);
-    
-    double sigc(0.), Hc(0.), dsigcdT(0.), ddsigcdTT(0.);
+    // Initialize
+    double& R = q1->_IsoHardForce_simple;
+    double& dRdT = q1->_dIsoHardForcedT_simple;
+    STensor3& dRdF = q1->_dIsoHardForcedF_simple;
+
+    // Get Hc, etc.
+    double sigc0(0.), dsigc0dT(0.), ddsigc0dTT(0.);
+    double sigc(0.), Hc(0.), dHcdT(0.), dsigcdT(0.), ddsigcdTT(0.);
+    sigc0 = q1->_ipCompression->getR0();         // Initial yield stress
+    dsigc0dT = sigc0*_temFunc_Sy0->getDiff(T);
+    ddsigc0dTT = sigc0*_temFunc_Sy0->getDoubleDiff(T);
     sigc = q1->_ipCompression->getR();
     Hc = q1->_ipCompression->getDR();
+    dHcdT = q1->_ipCompression->getDDRDT();
     dsigcdT = q1->_ipCompression->getDRDT();
     ddsigcdTT = q1->_ipCompression->getDDRDTT();
-    
-    R[0] = - a(1) * (trMe-trX1) * sigc; 
-    dRdT[0] = - DaDT(1)*(trMe-trX1)*sigc - a(1)*( (dTrMeDT-dTrXdT)*sigc + (trMe-trX1) * dsigcdT);
-    R[1] = - a(0) * sigc; 
-    dRdT[1] = - (DaDT(0) * sigc + a(0) * dsigcdT);
-    if (Gamma>0 and etaOverDt>0){
-       R[2] = - pow(eta*Gamma/this->getTimeStep(),_p) * sigc;
-       dRdT[2] = - _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep() * sigc - pow(eta*Gamma/this->getTimeStep(),_p) * dsigcdT; 
-    }
-     
+
+    // Get R
+    R = sigc - sigc0;
+
+    // dRdT
+    dRdT = dsigcdT - dsigc0dT;
+
     // dRdF
-    // static STensor3 dRdF;
-    const std::vector<STensor3>& dRdF_0 = q0->_dIsoHardForcedF;
-    std::vector<STensor3>& dRdF = q1->_dIsoHardForcedF;
-    dRdF.resize(3,0.);
-    
+    STensorOperation::zero(dRdF);
     for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
-        dRdF[0](i,j) = -Da(1)*(trMe-trX1)*DgammaDF(i,j)*sigc - a(1)*(DphiPDF(i,j)*sigc + (trMe-trX1)*Hc*DgammaDF(i,j));  
-        dRdF[1](i,j) = -Da(0)*DgammaDF(i,j)*sigc - a(0)*Hc*DgammaDF(i,j); 
-        }
-          
-    if (Gamma>0 and etaOverDt>0){
-      for (int i=0; i<3; i++)
-        for (int j=0; j<3; j++){
-          dRdF[2](i,j) = - _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(eta*DGammaDF(i,j)/this->getTimeStep())*sigc - pow(eta*Gamma/this->getTimeStep(),_p) * Hc*DgammaDF(i,j); 
-        }
-    }
-    
+      for (int j=0; j<3; j++)
+        dRdF(i,j) = Hc*DgammaDF(i,j);
+
+
     // ddRdTT
-    double delT = T-T0;
     if(ddRdTT!=NULL){
-       
-       ddRdTT->at(0) = - DDaDTT(1)*(trMe-trX1)*sigc - a(1)*( 2*(dTrMeDT-dTrXdT)*dsigcdT + (trMe-trX1) * ddsigcdTT );
-       ddRdTT->at(1) = -( DDaDTT(0)*sigc + 2*DaDT(0)*dsigcdT + a(0)*ddsigcdTT);
-       
-       if (Gamma>0 and etaOverDt>0){
-        ddRdTT->at(2) = - _p*(_p-1)*pow(eta*Gamma/this->getTimeStep(),_p-2)*pow(((DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep()),2) * sigc
-                        - _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*((DDetaDTT*Gamma + 2*DetaDT*dGammaDT)/this->getTimeStep() * sigc + 
-                        2*(DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep()* dsigcdT)
-                        - pow(eta*Gamma/this->getTimeStep(),_p) * ddsigcdTT;
-       }
-       
-       if (delT>1e-10){
-        double DphiPDT = dTrMeDT- dTrXdT;
-        double DDphiPDTT = 0.; // (DphiPDT - (trMe-trMe_0+trX1_0-trX1)/delT)/delT; // 2*DphiPDT/delT - 2*(trMe-trMe_0+trX1_0-trX1)/pow(delT,2); // DEBUGGING
-        ddRdTT->at(0) -= a(1) * DDphiPDTT * sigc;
-        
-        if (Gamma>0 and etaOverDt>0){
-         double DDGammaDTT =  0.; // 2*dGammaDT/delT - 2*(Gamma-Gamma_0)/pow(delT,2); // DEBUGGING
-         ddRdTT->at(2) -= _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(eta*DDGammaDTT)/this->getTimeStep() * sigc;
-        } 
-       }
-       q1->_ddIsoHardForcedTT = *ddRdTT;
+       *ddRdTT =  ddsigcdTT - ddsigc0dTT;
     }
-    // ddRdTT = 2*dRdT/(T-T0) - 2*(R-R0)/pow((T-T0),2); // ddGammaDTT is very difficult to estimate
-    
+
     // ddRdTF
     if(ddRdFdT!=NULL){
- 
-      for (int k=0; k<3; k++){
-        STensorOperation::zero(ddRdFdT->at(k));
-        if(delT>1e-10){
-          ddRdFdT->at(k) = dRdF[k];
-          ddRdFdT->at(k) -= dRdF_0[k];
-          ddRdFdT->at(k) *= 1/delT;
-        }
-      }  
+        STensor3 _ddRdFdT;
+        STensorOperation::zero(_ddRdFdT);
+
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++)
+            _ddRdFdT(i,j) = dHcdT*DgammaDF(i,j); // DDgammaDFDT = 0.
+
+        *ddRdFdT = _ddRdFdT;
     }
 };
-                                      
-void mlawNonLinearTVP::getMechSourceTVP(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
-                                        const STensor3& dFpdT, const STensor43& dFpdF, const STensor3& DphiPDF,
-                                        double *Wm, STensor3 *dWmdF, double *dWmdT) const{
-    
-    const double& Gamma = q1->_Gamma;                                        
+
+void mlawNonLinearTVP::getMechSourceTVP(const STensor3& F0, const STensor3& F,
+                                        const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T, const STensor3& Fepr,  const STensor3& Cepr,
+                                        const STensor3& DphiPDF, double *Wm, STensor3 *dWmdF, double *dWmdT) const{
+
     const double& DgammaDT = q1->_DgammaDT;
-    const double& dGammaDT = q1->_DGammaDT;
     const STensor3& DgammaDF = q1->_DgammaDF;
-    const STensor3& DGammaDF = q1->_DGammaDF;
     const double& gamma0 = q0->_epspbarre;
     const double& gamma1 = q1->_epspbarre;
-    const STensor3& Fp0 = q0->_Fp;
     const STensor3& Fp1 = q1->_Fp;
     const STensor3& Me = q1->_ModMandel;
     const STensor3& X1 = q1->_backsig;
     const STensor3& X0 = q0->_backsig;
-    const STensor3& dXdT(0.); //  = q1->_DbackSigDT; // Just for debugging = 0. //DEBUGGING
+    const STensor3& dXdT = q1->_DbackSigDT; // For debugging = 0. //DEBUGGING
     const STensor3& dXdT_0  = q0->_DbackSigDT;
     const STensor43& dXdF_0  = q0->_DbackSigDF;
-    const STensor43& dXdF  = q1->_DbackSigDF;
+    const STensor43& dXdF  =  q1->_DbackSigDF;
     const STensor3& dMeDT  = q1->_DModMandelDT;
-    const STensor3& dMeDT_0  = q0->_DModMandelDT;
     const STensor43& dMedF  = q1->_DModMandelDF;
-    const STensor43& dMedF_0  = q0->_DModMandelDF;
-    
-    static STensor3 devMe, devX1, dDevXdT, dDevMeDT;
-    static double trMe, trX1, dTrXdT, dTrMeDT;
-    
-    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,trMe); 
-    STensorOperation::decomposeDevTr(q1->_backsig,devX1,trX1); 
-    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dTrXdT); 
-    STensorOperation::decomposeDevTr(q1->_DModMandelDT,dDevMeDT,dTrMeDT);
-    
+    const STensor43& dGammaNdF = q1->_dGammaNdF;
+    const STensor3& dGammaNdT = q1->_dGammaNdT;
+
     // get Dgamma
     double Dgamma = gamma1 - gamma0;
-    
-    // get Hb
+
+    // get Hb - Kinematic hardening parameter
     double Hb(0.), dHb(0), dHbdT(0.), ddHbddT(0.);
     if (q1->_ipKinematic != NULL){
-        Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
+        Hb = q1->_ipKinematic->getDR();
         dHb = q1->_ipKinematic->getDDR();
         dHbdT = q1->_ipKinematic->getDRDT();
-        ddHbddT = q1->_ipKinematic->getDDRDDT();
+        ddHbddT = q1->_ipKinematic->getDDRDTT();
     }
 
-    // get Dp
-    static STensor3 Fpinv, Fp_dot, Dp;
-    STensorOperation::inverseSTensor3(Fp1,Fpinv);
-    Fp_dot = Fp1;
-    Fp_dot -= Fp0;
-    Fp_dot *= 1/this->getTimeStep();
-    STensorOperation::multSTensor3(Fp_dot,Fpinv,Dp);
-   
-    // get alpha 
+    // get Dp - dont use Dp = Fp_dot*Fpinv, USE Dp = Gamma*N/this->getTimeStep()
+    static STensor3 Dp;
+    STensorOperation::zero(Dp);
+    if (this->getTimeStep() > 0){
+        Dp = q1->_GammaN;
+        Dp *= 1/this->getTimeStep();
+    }
+
+    // get alpha
     double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
     static STensor3 alpha0, alpha1;
     alpha0 = X0; alpha1 = X1;
-    alpha0 *= 1/(pow(kk,2)*Hb); alpha1 *= 1/(pow(kk,2)*Hb); // how to get alpha0-current or previous Hb??? WHAT?  
+    if (Hb>0.){
+        alpha0 *= 1/(pow(kk,2)* (q0->_ipKinematic->getDR())) ; // using previous Hb for alpha0
+        alpha1 *= 1/(pow(kk,2)*Hb);
+    }
     alpha1 -= alpha0;
-    alpha1 *= 1/this->getTimeStep();
-    
+
     // get TempX - convenient backStress tensor
     STensor3 tempX;
     tempX = X1;
-    tempX -= T*dXdT; 
-    
+    tempX -= T*dXdT;
+
     // get R, dRdT, dRdF
+    double R(0.), dRdT(0.), ddRdTT(0.);
+    STensor3 dRdF, ddRdFdT; STensorOperation::zero(dRdF); STensorOperation::zero(ddRdFdT);
+
+    // Old Formulation
+    /*
     std::vector<double> ddIsoHardForcedTT; ddIsoHardForcedTT.resize(3,0.);
     std::vector<STensor3> ddIsoHardForcedFdT; ddIsoHardForcedFdT.resize(3,0.);
-    
-    getIsotropicHardeningForce(q0,q1,T0,T,DphiPDF,&ddIsoHardForcedTT,&ddIsoHardForcedFdT);
+
+    getIsotropicHardeningForce(q0,q1,T0,T,DphiPDF,&ddIsoHardForcedTT,&ddIsoHardForcedFdT); // For analytical derivatives; for numerical, put the last 2 args as NULL
     const std::vector<double>& IsoHardForce =  q1->_IsoHardForce;
     const std::vector<double>& dIsoHardForcedT =  q1->_dIsoHardForcedT;
     const std::vector<STensor3>& dIsoHardForcedF =  q1->_dIsoHardForcedF;
-    
-    double R(0.), dRdT(0.), ddRdTT(0.);
-    STensor3 dRdF, ddRdFdT; STensorOperation::zero(dRdF); STensorOperation::zero(ddRdFdT);
-    
+
     for (int i=0; i<3; i++){
-      R += IsoHardForce[i];
+      R += IsoHardForce[i]
       dRdT += dIsoHardForcedT[i];
-      ddRdTT += ddIsoHardForcedTT[i];
+      ddRdTT += ddIsoHardForcedTT[i]; // 0.;
       dRdF += dIsoHardForcedF[i];
-      ddRdFdT += 0.; // ddIsoHardForcedFdT[i]; //DEBUGGING
-    }
-    
+      ddRdFdT += ddIsoHardForcedFdT[i]; // 0.;
+    }*/
+
+    // New Formulation
+
+    double ddIsoHardForcedTT(0.);
+    STensor3 ddIsoHardForcedFdT;
+    STensorOperation::zero(ddIsoHardForcedFdT);
+
+    getIsotropicHardeningForce(q0,q1,T0,T,&ddIsoHardForcedTT,&ddIsoHardForcedFdT);
+    R = q1->_IsoHardForce_simple;
+    dRdT = q1->_dIsoHardForcedT_simple;
+    dRdF = q1->_dIsoHardForcedF_simple;
+
+    // for convenience
     R -= T*dRdT;
-    
+
     // mechSourceTVP
     if(Wm!=NULL){
         double mechSourceTVP = 0.;
-        if (this->getTimeStep() > 0){
-          mechSourceTVP += STensorOperation::doubledot(Me,Dp);
-          mechSourceTVP -= STensorOperation::doubledot(tempX,alpha1);
-          mechSourceTVP -= (R*Dgamma)/this->getTimeStep();
+
+        mechSourceTVP += STensorOperation::doubledot(Me,Dp);
+        if (!_TaylorQuineyFlag){
+            if (this->getTimeStep() > 0){
+                alpha1 *= 1/this->getTimeStep();
+                mechSourceTVP -= STensorOperation::doubledot(tempX,alpha1);
+                mechSourceTVP -= (R*Dgamma)/this->getTimeStep();
+            }
+        else{
+            mechSourceTVP *= _TaylorQuineyFactor;
         }
+
         *Wm = mechSourceTVP;
-        // Second Term TBD - need dXdT, dRdT -> added above
+        }
     }
-    
-    // Some Generic Conversion Tensors
-    static STensor43 dDpdFp, dFpinvdFp;
-    static STensor3 dFpinvdT;
-    
-    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++){
-             dFpinvdFp(i,j,k,l) = 0.;
-            for (int m=0; m<3; m++)
-              for (int s=0; s<3; s++)
-                dFpinvdFp(i,j,k,l) -= Fpinv(i,m)*_I4(m,s,k,l)*Fpinv(s,j);
-          }
-    
+
+    // dDpdF and dDpdT
+    // dDpdF = dGammaNdF/this->getTimeStep();
+    // dDpdT = dGammaNdT/this->getTimeStep();
+
+
+   // dAlphadF - from dXdF
+   static STensor43 dAlphadF;
+   STensorOperation::zero(dAlphadF);
+   if (Hb>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++){
-            dDpdFp(i,j,k,l) = 0.;
-            for (int m=0; m<3; m++)
-              dDpdFp(i,j,k,l) += 1/this->getTimeStep()*_I4(i,m,k,l)*Fpinv(m,j) + Fp_dot(i,m)*dFpinvdFp(m,j,k,l);
-          }
-    
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
-        dFpinvdT(i,j) = 0.;
-        for (int m=0; m<3; m++)
-          for (int s=0; s<3; s++)
-            dFpinvdT(i,j) -= Fpinv(i,m)*dFpdT(m,s)*Fpinv(s,j);
-          }
-          
-    // dDpdF and dDpdT
-    static STensor43 dDpdF;   
-    // STensorOperation::zero(dDpdF);
-    STensorOperation::multSTensor43(dDpdFp, dFpdF, dDpdF);
-          
-    static STensor3 dDpdT;
+            dAlphadF(i,j,k,l) += dXdF(i,j,k,l)*1/(pow(kk,2)*Hb) - X1(i,j)*DgammaDF(k,l)*1/(pow(kk*Hb,2))*dHb;
+    }
+   }
+
+   // dAlphadT - from dXdT
+   static STensor3 dAlphadT;
+   if (Hb>0.){
     for (int i=0; i<3; i++)
       for (int j=0; j<3; j++){
-        dDpdT(i,j) = 0.;
-        for (int m=0; m<3; m++){
-          dDpdT(i,j) += dFpdT(i,m)*Fpinv(m,j)*1/this->getTimeStep() + Fp_dot(i,m)*dFpinvdT(m,j); // dDpdFp(i,j,k,l)*dFpdT(k,l);  // maybe use Dp = Fp_dot Fpinv
-      }}
-      
-   // dXdF is available 
-   // const STensor43 dXdF = q1->_DbackSigDF;
-   
+        dAlphadT(i,j) = dXdT(i,j)*1/(pow(kk,2)*Hb) - X1(i,j)*DgammaDT*1/(pow(kk*Hb,2))*dHbdT;
+        }
+   }
+
    // ddXdTF -> make it -- CHANGE!!
-   static STensor43 ddXdTF; // ddGammaDTF and ddQDTF are very difficult to estimate
+   static STensor43 ddXdTdF; // ddGammaDTF and ddQDTF are very difficult to estimate
    static STensor3 ddXdTT; // ddGammaDTT and ddQDTT are very difficult to estimate
-   STensorOperation::zero(ddXdTF);
+   STensorOperation::zero(ddXdTdF);
    STensorOperation::zero(ddXdTT);
    double delT = T-T0;
    if (delT>1e-10){
@@ -650,63 +608,67 @@ void mlawNonLinearTVP::getMechSourceTVP(const IPNonLinearTVP *q0, IPNonLinearTVP
         // ddXdTT(i,j) += 2*dXdT(i,j)/(T-T0) - 2*(X1(i,j)-X0(i,j))/pow((T-T0),2); //DEBUGGING
         for (int k=0; k<3; k++)
           for (int l=0; l<3; l++){
-           // ddXdTF(i,j,k,l) += (dXdF(i,j,k,l)-dXdF_0(i,j,k,l))/(T-T0); //DEBUGGING
+           // ddXdTdF(i,j,k,l) += (dXdF(i,j,k,l)-dXdF_0(i,j,k,l))/(T-T0); //DEBUGGING
           }
         }
       }
-   
-   // dAlphadF - from dXdF
-   static STensor43 dAlphadF;
-   STensorOperation::zero(dAlphadF);
-    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++){
-            dAlphadF(i,j,k,l) += dXdF(i,j,k,l)*1/(pow(kk,2)*Hb) + X1(i,j)*DgammaDF(k,l)*1/(pow(kk*Hb,2))*dHb;
-          }
-          
-   // dAlphadT - from dXdT   
-   static STensor3 dAlphadT;
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
-        dAlphadT(i,j) = dXdT(i,j)*1/(pow(kk,2)*Hb) + X1(i,j)*DgammaDT*1/(pow(kk*Hb,2))*dHbdT;
-        }
-   
-   
-   // dMedF is available
-   // const STensor43 dMedF = q1->_DModMandelDF;
 
     if(dWmdF!=NULL){
         STensor3 dmechSourceTVPdF(0.);
         if (this->getTimeStep() > 0){
-          for (int i=0; i<3; i++)
-            for (int j=0; j<3; j++){
-              dmechSourceTVPdF(i,j) = - (dRdF(i,j) - T*ddRdFdT(i,j))*Dgamma/this->getTimeStep() - R*DgammaDF(i,j)/this->getTimeStep();
-              for (int k=0; k<3; k++)
-                for (int l=0; l<3; l++){
-                  dmechSourceTVPdF(i,j) += dMedF(i,j,k,l)*Dp(i,j) + Me(i,j)*dDpdF(i,j,k,l) 
-                                        - (dXdF(i,j,k,l) - T*ddXdTF(i,j,k,l))*alpha1(i,j) - tempX(i,j)*dAlphadF(i,j,k,l)/this->getTimeStep();
-                }
-            }
-        }  
+
+            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++){
+                    dmechSourceTVPdF(i,j) += dMedF(i,j,k,l)*Dp(i,j) + Me(i,j)*dGammaNdF(i,j,k,l)/this->getTimeStep();
+                  }
+              }
+
+          if (!_TaylorQuineyFlag){
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                dmechSourceTVPdF(i,j) = - (dRdF(i,j) - T*ddRdFdT(i,j))*Dgamma/this->getTimeStep() - R*DgammaDF(i,j)/this->getTimeStep();
+                for (int k=0; k<3; k++)
+                  for (int l=0; l<3; l++){
+                    dmechSourceTVPdF(i,j) += - (dXdF(i,j,k,l) - T*ddXdTdF(i,j,k,l))*alpha1(i,j) - tempX(i,j)*dAlphadF(i,j,k,l)/this->getTimeStep();
+                  }
+              }
+          }
+          else{
+              dmechSourceTVPdF *= _TaylorQuineyFactor;
+          }
+
+        }
         *dWmdF = dmechSourceTVPdF;
     }
-    
+
     if(dWmdT!=NULL){
         double dmechSourceTVPdT(0.);
         if (this->getTimeStep() > 0){
+
           for (int i=0; i<3; i++)
             for (int j=0; j<3; j++){
-              dmechSourceTVPdT += dMeDT(i,j)*Dp(i,j) + Me(i,j)*dDpdT(i,j) 
-                                        + T*ddXdTT(i,j)*alpha1(i,j) - tempX(i,j)*dAlphadT(i,j)/this->getTimeStep()
-                                        + T*ddRdTT*Dgamma/this->getTimeStep() - R*DgammaDT/this->getTimeStep() ;
+              dmechSourceTVPdT += dMeDT(i,j)*Dp(i,j) + Me(i,j)*dGammaNdT(i,j)/this->getTimeStep();
             }
+
+          if (!_TaylorQuineyFlag){
+
+            dmechSourceTVPdT += T*ddRdTT*Dgamma/this->getTimeStep() - R*DgammaDT/this->getTimeStep();
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                dmechSourceTVPdT += T*ddXdTT(i,j)*alpha1(i,j) - tempX(i,j)*dAlphadT(i,j)/this->getTimeStep();
+              }
+          }
+          else{
+              dmechSourceTVPdT *= _TaylorQuineyFactor;
+          }
+
         }
         *dWmdT = dmechSourceTVPdT;
     }
 };
 
-// NEW
 
 void mlawNonLinearTVP::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)
@@ -716,27 +678,27 @@ void mlawNonLinearTVP::constitutive( // This function is just a placeholder, def
                                   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, 
+                                  STensor43* elasticTangent,
                             const bool dTangent,
                                   STensor63* dCalgdeps) const{
     static SVector3 gradT, temp2;
     static STensor3 temp3;
-    static STensor33 temp33;    
+    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("mlawNonLinearTVP elasticTangent not defined"); 
+
+    if(elasticTangent != NULL) Msg::Error("mlawNonLinearTVP 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 mlawNonLinearTVP::constitutive(
                             const STensor3& F0,                     // initial deformation gradient (input @ time n)
                             const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
@@ -768,7 +730,7 @@ void mlawNonLinearTVP::constitutive(
     // 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,
@@ -777,7 +739,7 @@ void mlawNonLinearTVP::constitutive(
                                                     mechanicalSource, dmechanicalSourcedT, dmechanicalSourceF,
                                                     stiff, elasticTangent);
     }
-        
+
     else{
 
         this->predictorCorrector_ThermoViscoPlastic(F0, F1, P, q0, q1, T0, T, gradT0, gradT, fluxT, thermalSource, mechanicalSource, elasticTangent);
@@ -786,7 +748,7 @@ void mlawNonLinearTVP::constitutive(
                                             Tangent, dFpdF, dFpdT, dFedF, dFedT,
                                             dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF,
                                             dthermalSourcedT, dthermalSourcedF,
-                                            dmechanicalSourcedT, dmechanicalSourceF);            
+                                            dmechanicalSourcedT, dmechanicalSourceF);
     }
 };
 
@@ -856,12 +818,12 @@ void mlawNonLinearTVP::tangent_full_perturbation(
       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);
@@ -870,16 +832,16 @@ void mlawNonLinearTVP::tangent_full_perturbation(
           }
           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++){
@@ -894,10 +856,10 @@ void mlawNonLinearTVP::tangent_full_perturbation(
     // 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);
@@ -906,14 +868,14 @@ void mlawNonLinearTVP::tangent_full_perturbation(
       }
       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 mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
@@ -947,8 +909,8 @@ void mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
 
   if (_tangentByPerturbation){
     if (_nonAssociatedFlow){
-      this->predictorCorrector_TVP_nonAssociatedFlow(F0,F1,q0,q1,P,false,Tangent,dFedF,dFpdF,dFedT,dFpdT, 
-                                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,      
+      this->predictorCorrector_TVP_nonAssociatedFlow(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);
     }
@@ -963,8 +925,8 @@ void mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
   }
   else{
     if (_nonAssociatedFlow){
-      this->predictorCorrector_TVP_nonAssociatedFlow(F0,F1,q0,q1,P,stiff,Tangent,dFedF,dFpdF,dFedT,dFpdT, 
-                                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,      
+      this->predictorCorrector_TVP_nonAssociatedFlow(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);
     }
@@ -972,51 +934,14 @@ void mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
       this->predictorCorrector_TVP_AssociatedFlow(F1,q0,q1,P,stiff,Tangent,dFedF,dFpdF,T0,T);
     }
   }
-  
-  /*
-  // compute mechanical tengent
-  if (elasticTangent!= NULL)
-  {
-    STensor3 Ptmp(0.);
-    static IPNonLinearTVP q1tmp(*q1);
-    q1tmp.operator=(*(dynamic_cast<const IPVariable*> (q1)));
-    mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(q0->getConstRefToFe(), q1->getConstRefToFe(), Ptmp, q0, &q1tmp, *elasticTangent, dFedF, dFedT,
-                                                      T0, T, gradT0, gradT, fluxT, dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF, 
-                                                      thermalSource, dthermalSourcedT, dthermalSourcedF, 
-                                                      mechanicalSource, dmechanicalSourcedT, dmechanicalSourceF, 
-                                                      true);
-                                                      // mechSource requires taylorQuinney Term - CHANGE 
-    // UPDATE FOR TVP
-    // thermalSource derivatives -DEFINE LATER
-    
-    double CpT; 
-    if (!stiff){ // if stiff, we dont need this technically
-       getCp(CpT,T);
-    }
-    else{
-        // thermalSource TVP  
-        CpT = -T*q1->getConstRefToDDFreeEnergyTVMdTT();
-    }
-    
-    // thermalSource
-    if (this->getTimeStep() > 0.){
-        thermalSource = -CpT*(T-T0)/this->getTimeStep();
-    }
-    else{thermalSource = 0.;}
-  
-    // mechSource - TVP
-    mechanicalSource += q1->getConstRefToMechSrcTVP();
-    dmechanicalSourcedT += q1->getConstRefTodMechSrcTVPdT();
-    dmechanicalSourceF += q1->getConstRefTodMechSrcTVPdF();
-
-  }*/
 
 };
 
+
 void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(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,                     
+                            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
@@ -1030,8 +955,8 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
                                   double &mechanicalSource,         // mechanical source--> convert to heat
                                   double &dmechanicalSourcedT,
                                   STensor3 &dmechanicalSourceF) const{
-                                      
-  // compute elastic predictor 
+
+  // compute elastic predictor
   STensor3& Fp1 = q1->_Fp;
   const STensor3& Fp0 = q0->_Fp;
 
@@ -1049,27 +974,30 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   this->hardening(q0,q1,T);
   static fullVector<double> a(3), Da(3); // yield coefficients and derivatives in respect to plastic deformation
   this->getYieldCoefficients(q1,a);
+  //a.print("a init");
 
-  double Hb(0.), dHb(0.), dHbdT(0.), ddHbddT(0.);
+  double Hb(0.), dHb(0.), ddHb(0.), dHbdT(0.), ddHbdgammadT(0.), ddHbddT(0.);
   if (q1->_ipKinematic != NULL){
     Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
     dHb = q1->_ipKinematic->getDDR(); // kinematic hardening parameter derivative (dHb/dgamma)
     dHbdT = Hb * q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
-    ddHbddT = Hb * q1->_ipKinematic->getDDRDDT();
+    ddHbddT = Hb * q1->_ipKinematic->getDDRDTT();
   }
-  
-  //a.print("a init");
-  
+
+  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 Cepr, Ceinvpr;
+
+  static STensor3 Eepr, Cepr, Ceinvpr;
   Cepr = Ce;
   STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
-  
+
   static STensor3 invFp0; // plastic predictor
   invFp0= Fpinv;
   STensor3& Fe = q1->_Fe;
@@ -1078,25 +1006,42 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   // Predictor - TVE
   static STensor43 DlnDCepr, DlnDCe;
   static STensor63 DDlnDDCe;
-  static STensor3 expGN;
+  static STensor3 expGN, GammaN;
   static STensor43 dexpAdA; // estimation of dexpA/dA
+  expGN = _I; // if Gamma = 0, expGN = _I
+  dexpAdA = _I4;
 
   STensor3& Ee = q1->_Ee;
-  bool ok=STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
-  if(!ok)
-  {
-       P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
-       return; 
-  }
+  STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
   Ee *= 0.5;
+  Eepr = Ee;
   DlnDCe = DlnDCepr;
 
   // update A, B
   double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
   double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;
-  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,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T);
   getTVEdCorKirDT(q0,q1,T0,T);
-  
+
+  // additional branch - update predictor
+  double DsigV_dTrEe_pr(0.), DsigV_dTrEe(0.), DsigV_dT(0.);
+  static STensor3 sigExtra_pr, sigExtra, DsigD_dT;
+  static STensor43 DsigD_dDevEe_pr, DsigD_dDevEe;
+  STensorOperation::zero(sigExtra_pr);
+  STensorOperation::zero(sigExtra);
+  STensorOperation::zero(DsigD_dT);
+  STensorOperation::zero(DsigD_dDevEe_pr);
+  STensorOperation::zero(DsigD_dDevEe);
+  if (_useExtraBranch){
+    mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra_pr,stiff,NULL,NULL,&DsigV_dTrEe_pr,&DsigD_dDevEe_pr,&DsigV_dT,&DsigD_dT);
+  }
+  q1->_kirchhoff += sigExtra_pr;
+  const STensor3& dKeprDT = q1->_DcorKirDT; // Get the predicted value - dont add extra branch here
+
+  // Initialise Dho
+  static STensor43 Dho3, Dho4inv, Dho4_u_inv;  // This will be the final important tensor.
+  double Dho4_v_inv(0.);
+
   // Get Mepr
   static STensor3 Me, Mepr, Kepr;  // Ke is corKir
   getModifiedMandel(Ce,q0,q1);
@@ -1104,18 +1049,19 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   Mepr = Me;
   Kepr = q1-> _kirchhoff;
 
-  // Get Xn
-  static STensor3 devXn;
-  static double trXn, pXn, eXn; 
+  // 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
+  pXn = 1./3.*trXn;  // 1st invariant of Xn
   eXn = sqrt(1.5*devXn.dotprod()); // J2 invariant of Xn
-  
+
   // Initialise Phipr
-  static STensor3 PhiPr;
+  static STensor3 PhiPr, Phi;
   PhiPr = q1->_ModMandel;
   PhiPr -= q1->_backsig;
-  
+  Phi = PhiPr;
+
   static STensor3 devPhipr,devPhi; // effective dev stress predictor
   static double ptildepr,ptilde;
   STensorOperation::decomposeDevTr(PhiPr,devPhipr,ptildepr);
@@ -1127,129 +1073,161 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
   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
-  // double Gamma = 0.;  
-  double& Gamma = q1->_Gamma;   // flow rule parameter 
+  // double Gamma = 0.;
+  double& Gamma = q1->_Gamma;   // flow rule parameter
+  Gamma = 0.;
   double dDgammaDGamma = 0.;
   double Dgamma = 0.; // eqplastic strain
   static fullVector<double> m(2);
   getChabocheCoeffs(m,0,q1);
 
   double DfDGamma = 0.;
-  double dfdDgamma = 0.;  
-  double dAdDgamma = 0.;
-  double dAdGamma = 0.;
-  double dfdGamma = 0.;
+  double dfdDgamma(0.), dfdGamma(0.);
+  double dAdDgamma(0.), dAdGamma(0.);
   double u = 1.;
   double v = 1.;
-  
+
   // Initialise Cx, Gt, Kt
-  double Px(0.);
-  getPlasticPotential(pXn, eXn, Px);  // CHANGE -> this is wrong, change to backstress instead of phi 
-  double Cx = m(0)*Dgamma + m(1)*Px + 1;
-  if (Hb>0.){Cx -= 1/Hb * dHbdT * (T-T0);}
-  double Gt = Ge + pow(kk,1) * Hb/(2*Cx); // pow(kk,2) CHANGE
-  double Kt = Ke + pow(kk,1) * Hb/(3*Cx); // pow(kk,2) CHANGE
-  
+  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.), dudDgamma(0.), dvdDgamma(0.), dudGamma(0.), dvdGamma(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);
+  }
+  double Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2) DEBUG
+  double Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2) DEBUG
+
   // Initialise ptilde and devPhi (phi)
   ptilde = ptildepr; // current effective pressure  -> first invariant
   devPhi = devPhipr;
-  
+
+  // Initialise the rest
+  getDho3(u,v,Gamma,Cepr,Ceinvpr,Kepr,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,&DsigV_dTrEe,&DsigD_dDevEe);
+
   double PhiEqpr2 = 1.5*devPhi.dotprod();
   double PhiEqpr = sqrt(PhiEqpr2);      // -> second invariant
-  double PhiEq = PhiEqpr;   // current effective deviator 
- 
+  double PhiEq = PhiEqpr;   // current effective deviator
+
   // Get f and A
-  double f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0)); 
+  double f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
   double A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
 
-  // NR Loop
-  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  
-        double eta(0.),Deta(0.),DetaDT(0.);
-        if (_viscosity != NULL)
-          _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+  // Initialise g
+  double dgdDgamma=0., dgdGamma = 0.;
+  double g = Dgamma - kk*Gamma*A;
+
+  // Test
+  double Dgammma_test = 0.;
+
+  // 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();
-        
-        // dAdGamma and dDgammaDGamma
-        dAdGamma = -(72.*Gt*PhiEq*PhiEq/u + 16.*Kt*_b*_b*_b*ptilde*ptilde/(3.*v))/(2.*A);
-        dDgammaDGamma = kk*(A+Gamma*dAdGamma);  // mistake in the paper (VD 2016)
 
-        this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
-        dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0); 
-        
-        // Get He, Hp
-        double dCxdDgamma = m(0); // CHANGE to add derivatives of m(0) + dm0Ddgamma*Dgamma
+        // Get dCxdevdDgamma, dCxtrdDgamma, dudDgamma dvdDgamma, dudGamma, dvdGamma
+        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
+
+        dudDgamma = 6.*Gamma*( pow(kk,1.)/(2.*Cxdev)*dHb - (pow(kk,1.)*Hb)/(2.*pow(Cxdev,2.))*dCxdevdDgamma ); // pow(kk,2.) DEBUG
+        dvdDgamma = 2.*_b*Gamma*( pow(kk,1.)/(3.*Cxtr)*dHb - (pow(kk,1.)*Hb)/(3.*pow(Cxtr,2.))*dCxtrdDgamma ); // pow(kk,2.) DEBUG
+
+        dudGamma = 6.*(Ge + pow(kk,1.)*Hb/(2.*Cxdev)); // pow(kk,2.) DEBUG
+        dvdGamma = 2.*_b*(Ke + pow(kk,1.)*Hb/(3.*Cxtr)); // pow(kk,2.) DEBUG
+
+        // Get Hp = dPhiPdDgamma, dPhiPdGamma
+        double Hp =  (1./3.*trXn/(pow(Cxtr,2.))*dCxtrdDgamma - ptilde*dvdDgamma)*Dho4_v_inv;  // /v;
         
-        // double Stemp = STensorOperation::doubledot(devPhi,devXn);
-        // double He = (PhiEq*6*Gamma*kk*kk*Hb - Stemp*3.*1./PhiEq)/(2*Cx*Cx*u) * dCxdDgamma; // CHANGE THIS DERIVATIVE -> tensor subtracting scalar //CHECK
-        // double Hp = ptilde*(2*_b*Gamma*kk*kk*Hb - trXn)/(3*Cx*Cx*v) * dCxdDgamma; // CHECK
+        double dPhiPdGamma_RHS = - ptilde*dvdGamma;
+        if (_useExtraBranch){
+            dPhiPdGamma_RHS -= 2*_b*ptilde*DsigV_dTrEe;
+        }
+        double dPhiPdGamma = dPhiPdGamma_RHS*Dho4_v_inv;  // /v;
+
+        // Get He = dPhiEdGamma
+          // Get DdevPhidGamma
+        STensor3 DdevPhidDgamma, DdevPhidDgamma_RHS;
+        STensor3 DdevPhidGamma, DdevPhidGamma_RHS;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            DdevPhidDgamma_RHS(i,j) = devXn(i,j)/(pow(Cxdev,2.))*dCxdevdDgamma - dudDgamma*devPhi(i,j);
+            DdevPhidGamma_RHS(i,j) = -dudGamma*devPhi(i,j);
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                DdevPhidDgamma_RHS(i,j) += (2.*_b/3.)*Gamma*Dho3(i,j,k,l)*_I(k,l)*Hp; //ADD
+
+                DdevPhidGamma_RHS(i,j) += (2.*_b/3.)*Gamma*Dho3(i,j,k,l)*_I(k,l)*dPhiPdGamma; //ADD
+
+                DdevPhidGamma_RHS(i,j) += Dho3(i,j,k,l)*N(k,l);
+                
+                if (_useExtraBranch){
+                   DdevPhidGamma_RHS(i,j) -= DsigD_dDevEe(i,j,k,l)*3*devPhi(k,l);
+                }
+                
+              }
+            }
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            DdevPhidGamma(i,j) = 0.;
+            DdevPhidGamma(i,j) = 0.;
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                DdevPhidDgamma(i,j) += Dho4_u_inv(i,j,k,l)*DdevPhidDgamma_RHS(k,l);
+                DdevPhidGamma(i,j) += Dho4_u_inv(i,j,k,l)*DdevPhidGamma_RHS(k,l);
+              }
+          }
 
-        static STensor3 DdevPhidDgamma, term2;
-        STensorOperation::zero(DdevPhidDgamma);
-        // 1st term of He
-        DdevPhidDgamma = 3*Gamma*pow(kk,1)*Hb*devPhipr;  // pow(kk,2) CHANGE
-        DdevPhidDgamma -= devXn*(1 + 6*Gamma*(Ge + pow(kk,1)*Hb/2)); // pow(kk,2) CHANGE
-        DdevPhidDgamma *= 1/(Cx*Cx*u*u) * dCxdDgamma;
+        double Stemp1 = STensorOperation::doubledot(devPhi,DdevPhidDgamma);
+        double Stemp2 = STensorOperation::doubledot(devPhi,DdevPhidGamma);
+        double He = 1.5*Stemp1/PhiEq;
+        double dPhiEdGamma = 1.5*Stemp2/PhiEq;
 
-        // 2nd term of He
-        term2 = (3*Gamma*pow(kk,1)*Cx*devPhi);
-        term2 *= 1/(Cx*Cx*u)*dHb; // pow(kk,2) CHANGE
+        // 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);
 
-        DdevPhidDgamma -= term2;
+        dDgammaDGamma = kk*(A+Gamma*dAdGamma);  // mistake in the paper (VD 2016)
 
-        double Stemp = STensorOperation::doubledot(devPhi,DdevPhidDgamma);
-        double He = 1.5*Stemp/PhiEq;
+        this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
 
-        double Hp = ( 2*_b*Gamma*pow(kk,1)*Hb*ptildepr - trXn*(1 + 2*_b*Gamma*(Ke + pow(kk,1)*Hb/3)) )*1/(3*Cx*Cx*v*v)*dCxdDgamma;
-        Hp -= (2*_b*Gamma*pow(kk,1)*Cx*ptilde)*1/(3*Cx*Cx*v) * dHb;
+        dfdDgamma = Da(2)*pow(PhiEq,_n) - Da(1)*ptilde -Da(0);
+        dfdDgamma += a(2)*_n*pow(PhiEq,(_n-1.))*He - a(1)*Hp;
 
-        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!! WHAT??
+          dfdDgamma -= _p*pow(etaOverDt,_p-1.)*Deta/this->getTimeStep()*pow(Gamma,_p);  // THIS term is absent in the paper!! WHY??
 
-        DfDGamma = dfdDgamma*dDgammaDGamma - (_n*a(2)*6.*Gt)*pow(PhiEq,_n)/u + a(1)*ptilde*2.*_b*Kt/v;
+        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.);
-        
-        // OLD NR 
-        /*
-        double dGamma = -f/DfDGamma; // NR
+          dfdGamma -= pow(etaOverDt,_p)*_p*pow(Gamma,(_p-1.));
 
-        if (Gamma + dGamma <=0.){
-            Gamma /= 2.;                // NR
-        }
-        else
-          Gamma += dGamma;*/
+        DfDGamma = dfdDgamma*dDgammaDGamma + dfdGamma;
 
-        // NEW NR
-        dfdGamma = - (_n*a(2)*6.*Gt)*pow(PhiEq,_n)/u + a(1)*ptilde*2.*_b*Kt/v;
-        if (Gamma>0 and etaOverDt>0)
-          dfdGamma -= pow(etaOverDt,_p)*_p*pow(Gamma,(_p-1.));
-        
-        dAdDgamma = (12*PhiEq*He + 8/3*_b*_b*ptilde*Hp)/(2*A);
-        double dgdDgamma = 1 - kk*Gamma*dAdDgamma;
-        double dgdGamma = - dDgammaDGamma;
-        double g = Dgamma - kk*Gamma*A;
+        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
@@ -1260,18 +1238,19 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
         else
           Gamma += dGamma;
 
+        // Dgammma_test += dDgamma;
         if (Dgamma + dDgamma <=0.){
             Dgamma /= 2.;
             }
         else
-          Dgamma += dDgamma;  // Debugging
+          Dgamma += dDgamma;
 
         //Msg::Error("Gamma = %e",Gamma);
         //Msg::Error("Dgamma = %e",Dgamma);
-        
+
         
         // UPDATE FOR NEXT ITERATION
-        
+
         // Update gamma and all Hardening moduli
         updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
         hardening(q0,q1,T);
@@ -1280,41 +1259,42 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
             Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
             dHb = q1->_ipKinematic->getDDR(); // kinematic hardening parameter derivative (dHb/dgamma ??)
             dHbdT = Hb * q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
-            ddHbddT = Hb * q1->_ipKinematic->getDDRDDT();
+            ddHbddT = Hb * q1->_ipKinematic->getDDRDTT();
         }
         //a.print("a update");
 
-        // Update Normal and Backstress to get Px
-           // Can't use this because we Px needs backstress (n+1 step) which comes from normal -> which needs Phi -> which needs Cx -> which needs Px
-           // Have to put another rate equation in the NR for backstress to get it independently -> dX = kk*Hb*dalpha or something like that
-                                                // TBD -> also changes Phi definition and derivatives
-           // instead Px -> only as a function of backstress (nth step) is used.
-
         // Update Cx, u, v
-        Cx = m(0)*Dgamma + m(1)*Px + 1;
-        if (Hb>0.){Cx -= 1/Hb * dHbdT * (T-T0);}
-        Gt = Ge + pow(kk,1) * Hb/(2*Cx); // pow(kk,2) CHANGE
-        Kt = Ke + pow(kk,1) * Hb/(3*Cx); // pow(kk,2) CHANGE
+        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);
+        }
+        Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2) DEBUG
+        Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2) DEBUG
         u = 1.+6.*Gt*Gamma;
         v = 1.+2.*_b*Kt*Gamma;
 
         // Update Phi
-        devPhi = devPhipr + devXn*(1-1/Cx);
-        ptilde = ptildepr + 1/3*trXn*(1-1/Cx);
-        devPhi *= 1./u;
+        getIterated_DPhi(T,q0,q1,u,v,Gamma,Cxtr,Cxdev,PhiPr,trXn,devXn,Cepr,Eepr,Kepr,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                            Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,
+                            sigExtra_pr,sigExtra,DsigV_dTrEe,DsigD_dDevEe);
         PhiEq = sqrt(1.5*devPhi.dotprod());
-        ptilde /= v;
 
         // Update A
         A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
 
-        // Dgamma = kk*Gamma*A;
-        //Msg::Error("it = %d, u=%e, v=%e, Dgamma=%e",ite,u,v,Dgamma);
+        Dgamma = kk*Gamma*A;
+        updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+        hardening(q0,q1,T);
+        getYieldCoefficients(q1,a);
 
-        // Update f
+        // 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);
+        double viscoTerm = etaOverDt*Gamma;
+        if (Gamma>0. and etaOverDt>0.) f-= pow(viscoTerm,_p);
+
+        g = Dgamma - kk*Gamma*A;
 
         ite++;
         //if (ite> maxite-5)
@@ -1327,84 +1307,90 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
           P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
           return;
         }
-      };
-
-      q1->_DgammaDt = Dgamma/this->getTimeStep();
-
-      // Correct Phi (effective stress tensor)
-      devPhi = devPhipr + devXn*(1-1/Cx);
-      ptilde = ptildepr + 1/3*trXn*(1-1/Cx);
-      devPhi *= 1./u;
-      PhiEq = sqrt(1.5*devPhi.dotprod());
-      ptilde /= v;
-
-      // Correct normal
-      devN = devPhi;
-      devN *=  3.;
-      trN =  2.*_b*ptilde;
-      N = devN;
-      N(0,0) += trN/3.;
-      N(1,1) += trN/3.;
-      N(2,2) += trN/3.;
-
-      // estimate exp(GammaN)
-      // static STensor3 expGN;
-      static STensor3 GammaN;
-      GammaN = N;
-      GammaN *= Gamma;
-      STensorOperation::expSTensor3(GammaN,_order,expGN,&dexpAdA);
+    } // while
 
-      // Correct plastic deformation tensor
-      STensorOperation::multSTensor3(expGN,Fp0,Fp1);
-      // Correct IP gamma
-      updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma); 
+    q1->_DgammaDt = Dgamma/this->getTimeStep();
 
-      // 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; // Here We have assumed that, Ce commutes with Q (i.e. with M) 
-      
-      // Correct A, B
-      ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); //,false); 
-      getTVEdCorKirDT(q0,q1,T0,T); // update dCorKirdT
-      // DKDTsum and DGDTsum = sum of bulk/shear moduli derivatives wrt T 
-
-      // Correct backstress
-      static STensor3 DB; // increment
-      DB = (N); // increment
-      DB *= (kk*Hb*Gamma); // pow(kk,2) CHANGE
-      DB += q0->_backsig;
-      DB *= 1/Cx;
-      DB -= q0->_backsig;
-      q1->_backsig += DB; 
-
-      // Correct Mandel
-      q1->_ModMandel = devPhi;
-      q1->_ModMandel += q1->_backsig;
-
-      q1->_ModMandel(0,0) += (ptilde);
-      q1->_ModMandel(1,1) += (ptilde);
-      q1->_ModMandel(2,2) += (ptilde);
-      
+    // Correct Cx, u, v
+    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);
+    }
+    Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2.) DEBUG
+    Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2.) DEBUG
+    u = 1.+6.*Gt*Gamma;
+    v = 1.+2.*_b*Kt*Gamma;
+
+    // Correct Phi
+    getIterated_DPhi(T,q0,q1,u,v,Gamma,Cxtr,Cxdev,PhiPr,trXn,devXn,Cepr,Eepr,Kepr,ptilde,devPhi,Phi,N,expGN,dexpAdA,
+                        Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,
+                        sigExtra_pr,sigExtra,DsigV_dTrEe,DsigD_dDevEe);
+    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;
+
+    // Correct A, B
+    ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); //,false);
+    getTVEdCorKirDT(q0,q1,T0,T); // update dCorKirdT - don't do this probably
+    // DKDTsum and DGDTsum = sum of bulk/shear moduli derivatives wrt T
+
+    // Correct Extrabranch - update stress
+    if (_useExtraBranch){
+        mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra,stiff,NULL,NULL,&DsigV_dTrEe,&DsigD_dDevEe,&DsigV_dT,&DsigD_dT);
     }
+    q1->_kirchhoff += sigExtra;
+
+    // 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;
+        q1->getRefToDissipationActive() = false;
     }
-  }
+  } // 1st if
 
 
   const STensor3& KS = q1->_kirchhoff;
-  
-  getModifiedMandel(Ce, q0, q1); // update Mandel 
-  
+  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);
@@ -1419,8 +1405,24 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
           P(i,j) += Fe(i,k)*S(k,l)*Fpinv(j,l);
     }
 
-
   // defo energy
+
+  // Elastic energy and Mullin's effect
+  q1->_elasticEnergy = mlawNonLinearTVE::freeEnergyMechanical(*q1,T0,T);
+
+  // Mullins Effect
+  if (_mullinsEffect != NULL && q1->_ipMullinsEffect != NULL){
+     mlawNonLinearTVE::calculateMullinsEffectScaler(q0, q1, T);
+  }
+  double eta_mullins = 1.;
+  if (q1->_ipMullinsEffect != NULL){
+        eta_mullins = q1->_ipMullinsEffect->getEta();
+        P *= eta_mullins;
+        q1->_elasticEnergy *= eta_mullins;
+    }
+
+  // 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();
@@ -1429,950 +1431,1443 @@ void mlawNonLinearTVP::predictorCorrector_TVP_nonAssociatedFlow(const STensor3&
     q1->getRefToPlasticEnergy() += Gamma*dotMSN; // = Dp:Me
   }
 
-  
-   // fluxT
-   double KThConT, DKThConDT; mlawNonLinearTVE::getKTHCon(KThConT,T,&DKThConDT);
-   double J  = 1.;
-   STensor3 Finv(0.);
-   if (_thermalEstimationPreviousConfig){                                            // ADD  _thermalEstimationPreviousConfig
+  // fluxT
+  double KThConT, DKThConDT;
+  mlawNonLinearTVE::getKTHCon(KThConT,T,&DKThConDT);
+  double J  = 1.;
+  STensor3 Finv(0.);
+  if (_thermalEstimationPreviousConfig){                                            // ADD  _thermalEstimationPreviousConfig
     STensorOperation::inverseSTensor3(F0,Finv);
     J = STensorOperation::determinantSTensor3(F0);
-   }
-   else{
+  }
+  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(dFpdF);
-   // STensorOperation::zero(dFpdT);
-                                      
+  }
+
+  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(dFpdF);
+  // STensorOperation::zero(dFpdT);
+
   // 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();
+             (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DISSIPATION_ENERGY)){
+      q1->getRefToIrreversibleEnergy() = q1->plasticEnergy();
   }
   else{
     q1->getRefToIrreversibleEnergy() = 0.;
   }
 
-  if (stiff){  
-      
-      // dP/dF
-      
-      //1. get DtrKeprDCepr and DdevKeprDCepr, also DKeprDCepr
-      static STensor3 DpDCepr;
-      static STensor43 DdevKDCepr;
-      static STensor43 DdevKeprDCepr, DdevMeprDCepr, DKeprDCepr;  
-      static STensor3 DpKeprDCepr, DpMeprDCepr;      // K = corKir; pK -> pressure of corKir
-      STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DpKeprDCepr);
-      DpKeprDCepr*= (0.5*Ke);
-      STensorOperation::multSTensor43(_Idev,DlnDCepr,DdevKeprDCepr);
-      DdevKeprDCepr*= Ge;
-      
-      // DKeprDCepr
-      DKeprDCepr = DdevKeprDCepr;
-      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++){
-              DKeprDCepr(i,j,k,l) += _I(i,j)*DpKeprDCepr(k,l);
-            }
+  if (stiff){
 
-      // initiate here - corrected corKir derivatives wrt Cepr 
-      DpDCepr = DpKeprDCepr;
-      DdevKDCepr = DdevKeprDCepr;
-    
-      //2. get DCeprDCepr and DCeinvprDCepr
-      static STensor43 DCeprDCepr, DCeinvprDCepr;
-      DCeprDCepr = _I4;
+    // dP/dF
 
-      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);
-            }
-       
-      //3. get DtrMeprDCepr and DdevMeprDCepr
-      static STensor43 DMeprDCepr;
-      
-      static STensor3 temp1;
-      static STensor43 temp2, temp3;
-      STensorOperation::multSTensor3(Kepr,Ceinvpr,temp1);
-      
-      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++){
-              temp2(i,s,k,l) = 0.;
-              temp3(i,s,k,l) = 0.;
-              for (int m=0; m<3; m++){
-                  temp2(i,s,k,l) += _I4(i,m,k,l)*temp1(m,s);
-                  temp3(i,s,k,l) += DKeprDCepr(i,m,k,l)*Ceinvpr(m,s) + Kepr(i,m)*DCeinvprDCepr(m,s,k,l);
-              }
-          }
-      
-      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++){
-              DMeprDCepr(i,s,k,l) = 0.;
-              for (int m=0; m<3; m++)
-                DMeprDCepr(i,s,k,l) += Cepr(i,m)*temp3(m,s,k,l);
-            }
-       
-      DMeprDCepr += temp2;
-      DMeprDCepr += DKeprDCepr;
-      DMeprDCepr *= 0.5;
-      
-      // Because, TrMepr = TrKepr 
-      DpMeprDCepr = DpKeprDCepr;   
-      
-      // 
-      STensorOperation::zero(DdevMeprDCepr);
-      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++){
-              DdevMeprDCepr(i,s,k,l) += DMeprDCepr(i,s,k,l) - _I(i,s)*DpMeprDCepr(k,l);
-            }
-      
-      //4. get DdevphiDCepr and DphiPprDCepr
-      static STensor3 DphiPprDCepr, DphiPDCepr;
-      static STensor43 DdevphiprDCepr, DdevphiDCepr;
-      
-      STensorOperation::zero(DphiPprDCepr);
-      STensorOperation::zero(DphiPDCepr);
-      STensorOperation::zero(DdevphiprDCepr);
-      STensorOperation::zero(DdevphiDCepr);
-      
-      DphiPprDCepr = DpMeprDCepr;
-      DdevphiprDCepr = DdevMeprDCepr;
-      
-      DdevphiDCepr = DdevphiprDCepr;
-      DdevphiDCepr *= 1./u;
-      DphiPDCepr = DphiPprDCepr;
-      DphiPDCepr *= 1./v;
-      
-     //5. get DphiEprDCepr from DdevphiDCepr
-      static STensor3 DphiEDCepr, DphiEDdevPhi;
-      
-      STensorOperation::zero(DphiEDdevPhi);
-      DphiEDdevPhi = devPhi;
-      DphiEDdevPhi *= 1.5/(PhiEq);
-      
-      STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
-     
-     
-     // 6. to 11. (inside if loop-> Gamma > 0.)
-      static STensor3 dAdCepr, dfDCepr;
-      static STensor3 DGDCepr;
-      static STensor3 DgammaDCepr;
-      static STensor3 DtrNDCepr;
-      static STensor43 DdevNDCepr;
-      static STensor43 dFpDCepr;
-      static STensor43 dCedCepr, dCeinvdCepr;
-      static STensor43 dXdCepr;
-      static STensor3 dTrXdCepr;
-      
-      if (Gamma >0){
-          // plastic
-          
-      //6. get dAdCepr from DdevphiDCepr 
-        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.*_b*_b*ptilde/(A*3.))*DphiPDCepr(i,j);
-            dfDCepr(i,j) = -a(1)*DphiPDCepr(i,j);
-            dAdCepr(i,j) += (6./A)*PhiEq*DphiEDCepr(i,j);
-            dfDCepr(i,j) += fact*DphiEDCepr(i,j);
-          }
-        }
-        
-      //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*kk*Gamma*dAdCepr(i,j))/DfDGamma;
-            DGDCepr(i,j) = (-dfDCepr(i,j)-dfdDgamma*kk*Gamma*dAdCepr(i,j)/(1-kk*Gamma*dAdDgamma)) / (dfdDgamma*kk*(A+Gamma*dAdGamma)/(1.-kk*Gamma*dAdDgamma) + dfdGamma);
-          }
-        }
+    //1. get DtrKeprDCepr and DdevKeprDCepr, also DKeprDCepr
+    static STensor3 DpDCepr;
+    static STensor43 DdevKDCepr;
+    static STensor43 DdevKeprDCepr, DdevMeprDCepr, DKeprDCepr;
+    static STensor3 DpKeprDCepr, DpMeprDCepr;      // K = corKir; pK -> pressure of corKir
+    STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DpKeprDCepr);
+    DpKeprDCepr*= (0.5*Ke);
+    STensorOperation::multSTensor43(_Idev,DlnDCepr,DdevKeprDCepr);
+    DdevKeprDCepr*= Ge;
 
-        for (int i=0; i<3; i++){
-          for (int j=0; j<3; j++){
-            // DgammaDCepr(i,j) = kk*Gamma*dAdCepr(i,j)+ kk*dDgammaDGamma*DGDCepr(i,j);
-            DgammaDCepr(i,j) = (kk*Gamma*dAdCepr(i,j)+ (1.*kk*A+kk*Gamma*dAdDgamma)*DGDCepr(i,j))/(1.-kk*Gamma*dAdDgamma);
+    // DKeprDCepr
+    DKeprDCepr = DdevKeprDCepr;
+    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++){
+            DKeprDCepr(i,j,k,l) += _I(i,j)*DpKeprDCepr(k,l);
           }
-        }
-      
-     //8. update DdevphiDCepr and DphiEDCepr
-       static STensor3 dCxdCepr, dPxdCepr;
-       STensorOperation::zero(dPxdCepr);
-       STensorOperation::zero(dCxdCepr);
-       dPxdCepr *= m(1);
-       dCxdCepr = DgammaDCepr;
-       dCxdCepr *= m(0);
-       dCxdCepr += dPxdCepr;
-       
-       // DphiEDCepr
-       static STensor3 temp7, temp8, temp9;
-       STensorOperation::zero(temp7);
-       STensorOperation::zero(temp8);
-       STensorOperation::zero(temp9);
-       
-       temp7 = dCxdCepr;
-       temp7 *= (1/3*1/(pow(Cx,2))*trXn/v);
-       
-       temp9 = 2/3*_b*Gamma*pow(kk,1)*(-Hb/pow(Cx,2)*dCxdCepr + 1/Cx*dHb*DgammaDCepr); // pow(kk,2) CHANGE
-       
-       temp8 = DGDCepr;
-       temp8 *= (2*_b*(Ke+pow(kk,1)*Hb/(3*Cx))); // pow(kk,2) CHANGE
-       temp8 += temp9;
-       temp8 *= (ptildepr + 1/3*trXn*(1-1/Cx));
-       temp8 *= 1/pow(v,2);
-       
-       DphiPDCepr += temp7;
-       DphiPDCepr -= temp8;
-       
-       // DdevphiDCepr
-       static STensor43 temp10, temp11;
-       static STensor3 temp12, temp13, temp14;
-       // STensorOperation::zero(temp10);
-       // STensorOperation::zero(temp11);
-       STensorOperation::zero(temp12);
-       STensorOperation::zero(temp13);
-       STensorOperation::zero(temp14);
-       
-       temp12 = devXn;
-       temp12 *= 1/pow(Cx,2);
-       
-       STensorOperation::prod(temp12, dCxdCepr, 1., temp10);
-       temp10 *= 1/u;
-       
-       for (int i=0; i<3; i++){
-         for (int j=0; j<3; j++){
-           temp13(i,j) = devPhipr(i,j) + (1-1/Cx)*devXn(i,j);
-           temp14(i,j) = 6*DGDCepr(i,j)*( Ge + pow(kk,1)*Hb/(2*Cx) ) + 6*Gamma*pow(kk,1)*(-Hb/(2*pow(Cx,2))*dCxdCepr(i,j) + 1/Cx*dHb*DgammaDCepr(i,j)); // pow(kk,2) CHANGE
-         }
-       } 
-       
-       STensorOperation::prod(temp13, temp14, 1., temp11);
-       temp11 *= 1/pow(u,2);
-       
-       DdevphiDCepr += temp10;
-       DdevphiDCepr -= temp11;
-       
-       //9. get DtrNDCepr DdevNdCepr
-       DtrNDCepr = DphiPDCepr;
-       DtrNDCepr *= (2*_b);
-       
-       DdevNDCepr = DdevphiDCepr;
-       DdevNDCepr *= 3;
-       
-       // 10. get dFpDCepr and dCeinvdCepr
-       
-       // dFpDCepr
-       static STensor43 temp15;
-       static STensor3 temp15_tr;
-       for (int i=0; i<3; i++)
-         for (int j=0; j<3; j++){
-            temp15_tr(i,j) = Gamma/3.*DtrNDCepr(i,j);
-           for (int k=0; k<3; k++)
-             for (int l=0; l<3; l++)
-               temp15(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 EprFp0;
-       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++){
-                EprFp0(i,j,k,l) = 0.;
-                for (int s=0; s<3; s++){
-                  EprFp0(i,j,k,l) += dexpAdA(i,s,k,l)*Fp0(s,j);
-                }
-              }
-        
-       STensorOperation::multSTensor43(EprFp0,temp15,dFpDCepr);
-       
-       
-       // dCeinvdCepr; Here, A = GN
-       static STensor43 dexpAdCepr, dexpAinvdCepr;
-       STensorOperation::multSTensor43(dexpAdA,temp15,dexpAdCepr);
-       
-       static STensor3 expGNinv;
-       STensorOperation::inverseSTensor3(expGN,expGNinv);
-       
-       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++){
-               dexpAinvdCepr(i,s,k,l) = 0.;
-               for (int m=0; m<3; m++)
-                 for (int j=0; j<3; j++)
-                   dexpAinvdCepr(i,s,k,l) -= expGNinv(i,m)*dexpAdCepr(m,j,k,l)*expGNinv(j,s);
-             }  
-       
-       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++){
-               dCedCepr(i,s,k,l) = 0.;
-               for (int m=0; m<3; m++)
-                 for (int j=0; j<3; j++)
-                   dCedCepr(i,s,k,l) +=  expGNinv(m,i)*_I4(m,j,k,l)*expGNinv(j,s) - expGNinv(m,i)*Cepr(m,j)*dexpAinvdCepr(j,s,k,l)
-                                          - dexpAinvdCepr(m,i,k,l)*Cepr(m,j)*expGNinv(j,s); // assuming GN is symmetric
-             }    // This derivative is wrong somehow. Use d()/dF below instead.
-       
-             
-       // 10.1 get dXdCepr
-       const STensor3 backSig = q1->_backsig;
-       static double trX;
-       static STensor3 devX;
-       STensorOperation::decomposeDevTr(backSig,devX,trX);
-       
-       STensorOperation::zero(dXdCepr);
-       STensorOperation::zero(dTrXdCepr);
-       for (int i=0; i<3; i++)
-         for (int j=0; j<3; j++){
-           dTrXdCepr(i,j) = pow(kk,1)*Hb*temp15_tr(i,j)/Cx - trX*dCxdCepr(i,j)/Cx; // pow(kk,2) CHANGE
-           for (int k=0; k<3; k++)
-             for (int l=0; l<3; l++)
-               dXdCepr(i,j,k,l) = pow(kk,1)*(Hb*temp15(i,j,k,l) + dHb*Gamma*DgammaDCepr(i,j)*N(k,l))/Cx -  q1->_backsig(i,j)*dCxdCepr(k,l)/Cx;
-               // pow(kk,2) CHANGE
-       }
-        
-       // 11. update DpDCepr, DdevKDCepr
-       // (DpKeprDCepr DdevKeprDCepr)
-       // update
-       for (int i=0; i<3; i++){
-         for (int j=0; j<3; j++){
-           DpDCepr(i,j) -= Ke*(DGDCepr(i,j)*trN+Gamma*DtrNDCepr(i,j));
-           for (int k=0; k<3; k++){
-             for (int l=0; l<3; l++){
-               DdevKDCepr(i,j,k,l) -=  2.*Ge*(DGDCepr(k,l)*devN(i,j)+Gamma*DdevNDCepr(i,j,k,l));
-            }
-          }
-        }
-      }
-       
-    }
-    else{
-      // elastic
-      STensorOperation::zero(DgammaDCepr);
-      STensorOperation::zero(dFpDCepr);
-      STensorOperation::zero(DtrNDCepr);
-      STensorOperation::zero(DdevNDCepr);
-      STensorOperation::zero(DGDCepr);
-      STensorOperation::zero(dXdCepr);
-      STensorOperation::zero(dTrXdCepr);
-      
-      // STensorOperation::zero(dCedCepr);
-      dCedCepr = _I4;                                           // DOUBT _ CHECK
-    }
-    
+    // initiate here - corrected corKir derivatives wrt Cepr
+    DpDCepr = DpKeprDCepr;
+    DdevKDCepr = DdevKeprDCepr;
+
+    //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++){
-            dCeinvdCepr(i,s,k,l) = 0.;
+            DCeinvprDCepr(i,s,k,l) = 0.;
             for (int m=0; m<3; m++)
               for (int j=0; j<3; j++)
-                dCeinvdCepr(i,s,k,l) -= Ceinv(i,m)*dCedCepr(m,j,k,l)*Ceinv(j,s);
-             }
-    
-    // 12. get dKcorDcepr
-    static STensor43 dKcorDcepr;
-    dKcorDcepr = DdevKDCepr;
-    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++){
-            dKcorDcepr(i,j,k,l) += _I(i,j)*DpDCepr(k,l);
-          }
-        }
-      }
-    }
-    
-    //13. get  CeprToF conversion tensor
-    static STensor43 CeprToF;
-    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);
+                DCeinvprDCepr(i,s,k,l) -= Ceinvpr(i,m)*_I4(m,j,k,l)*Ceinvpr(j,s);
           }
-        }
-      }
-    }
-    
-    static STensor43 DKcorDF;
-    STensorOperation::multSTensor43(dKcorDcepr,CeprToF,DKcorDF);
-    
-    // 14. get dSdCepr and dSdF; also get dMedCepr and dMedF
-    // Done below -> need dCedF
-    
-    STensor43& dXdF = q1->getRefToDbackStressdF();
-    static STensor3 dTrXdF;
-    STensorOperation::multSTensor43(dXdCepr,CeprToF,dXdF); 
 
-    // DphiPDCepr - use this for the pressure term in R
-    // for the pressure term in R
+    //3. get DtrMeprDCepr and DdevMeprDCepr
+    static STensor43 DMeprDCepr;
+
+    static STensor3 temp1;
+    static STensor43 temp2, temp3;
+    STensorOperation::multSTensor3(Kepr,Ceinvpr,temp1);
+
     for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
-         DphiPDF(i,j) = 0.;
+      for (int s=0; s<3; s++)
         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);
+            temp2(i,s,k,l) = 0.;
+            temp3(i,s,k,l) = 0.;
+            for (int m=0; m<3; m++){
+              temp2(i,s,k,l) += _I4(i,m,k,l)*temp1(m,s);
+              temp3(i,s,k,l) += DKeprDCepr(i,m,k,l)*Ceinvpr(m,s) + Kepr(i,m)*DCeinvprDCepr(m,s,k,l);
+            }
           }
-      }
-    
-    // 15. get DgammaDF
-    STensor3& DgammaDF = q1->_DgammaDF;
-    STensor3& DGammaDF = q1->_DGammaDF;
-    if (Gamma > 0){
-      STensorOperation::multSTensor3STensor43(DgammaDCepr,CeprToF,DgammaDF);
-      STensorOperation::multSTensor3STensor43(DGDCepr,CeprToF,DGammaDF);
-      STensorOperation::multSTensor43(dFpDCepr,CeprToF,dFpdF);
-    }
-    else{
-      STensorOperation::zero(DgammaDF);
-      STensorOperation::zero(DGammaDF);
-      // STensorOperation::zero(dFpdF);
-    }
 
-    // 16. Everything else and Tangent 
-    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.;
+            DMeprDCepr(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);
+              DMeprDCepr(i,s,k,l) += Cepr(i,m)*temp3(m,s,k,l);
           }
 
-    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);
-          }
-    
+    DMeprDCepr += temp2;
+    DMeprDCepr += DKeprDCepr;
+    DMeprDCepr *= 0.5;
+
+    // Because, TrMepr = TrKepr
+    DpMeprDCepr = DpKeprDCepr;
+
+    //
+    STensorOperation::zero(DdevMeprDCepr);
     for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++)
+      for (int s=0; s<3; s++)
         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!
+            DdevMeprDCepr(i,s,k,l) += DMeprDCepr(i,s,k,l) - _I(i,s)*DpMeprDCepr(k,l);
+          }
+
+    //3.1 Add predicted tangents for extrabranch (the corrected values are independent so we can put predicted values here)
+    static STensor3 DsigV_DCepr;
+    static STensor43 DsigD_DCepr;
+    if (_useExtraBranch){
+
+        STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DsigV_DCepr);
+        DsigV_DCepr *= 0.5*DsigV_dTrEe_pr;
+        DpDCepr += DsigV_DCepr;
+        DpMeprDCepr += DsigV_DCepr; // goes to DphiPDCepr
+        
+        static STensor43 temp3; 
+        STensorOperation::multSTensor43(DsigD_dDevEe_pr,_Idev,temp3);
+        STensorOperation::multSTensor43(temp3,DlnDCepr,DsigD_DCepr);
+        DsigD_DCepr *= 0.5;
+        DdevKDCepr += DsigD_DCepr;
+        DdevMeprDCepr += DsigD_DCepr; // goes to DdevphiprDCepr
+       
+        // dMedF, dSdF come from dKcorDcepr directly
+    }
+
+    //4. get DdevphiDCepr and DphiPprDCepr
+    static STensor3 DphiPprDCepr, DphiPDCepr;
+    static STensor43 DdevphiprDCepr, DdevphiDCepr;
+
+    DphiPprDCepr = DpMeprDCepr;
+    DdevphiprDCepr = DdevMeprDCepr;
+
+    DphiPDCepr = DphiPprDCepr;
+    DphiPDCepr *= 1./v;
+    DdevphiDCepr = DdevphiprDCepr;
+    DdevphiDCepr *= 1./u;
+
+    //5. get DphiEprDCepr from DdevphiDCepr
+    static STensor3 DphiEDCepr, DphiEDdevPhi;
+    if (PhiEq >0.){
+        DphiEDdevPhi = devPhi;
+        DphiEDdevPhi *= 1.5/(PhiEq);
+    }
+
+    STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+
+    // 6. to 11. (inside if loop-> Gamma > 0.)
+      static STensor3 dAdCepr, dfDCepr, dgDCepr;
+      static STensor3 DGDCepr;
+      static STensor3 DgammaDCepr;
+      static STensor3 DtrNDCepr;
+      static STensor43 DdevNDCepr;
+      static STensor43 dFpDCepr;
+      static STensor43 dCedCepr, dCeinvdCepr;
+      static STensor43 dXdCepr;
+      static STensor3 dTrXdCepr;
+      static STensor43 dGammaNdCepr;
+
+      if (Gamma >0.){
+
+        //6. get dAdCepr from DdevphiDCepr
+        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
+        static STensor3 DGDCepr_test, DgammaDCepr_test;
+          for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+              // DGDCepr(i,j) = (-dfDCepr(i,j)-dfdDgamma*kk*Gamma*dAdCepr(i,j))/DfDGamma;
+              DGDCepr(i,j) = (-dfDCepr(i,j) + dfdDgamma*dgDCepr(i,j)/dgdDgamma)/(dfdGamma - dfdDgamma*dgdGamma/dgdDgamma);
             }
           }
-    
-    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();
-    
-    /* Something wrong with dCedCepr - good luck debugging
-     * 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++){
-            dMedCepr(i,j,k,l) = dKcorDcepr(i,j,k,l); // CHANGED
-            for (int m=0; m<3; m++)
-              for (int s=0; s<3; s++)
-                dMedCepr(i,j,k,l) += dCedCepr(i,m,k,l)*KS(m,s)*Ceinv(s,j) + Ce(i,m)*(dKcorDcepr(m,s,k,l)*Ceinv(s,j) + KS(m,s)*dCeinvdCepr(s,j,k,l));
-                                    // CHECK!! the last terms
+
+          for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+              // DgammaDCepr(i,j) = kk*Gamma*dAdCepr(i,j)+ dDgammaDGamma*DGDCepr(i,j);
+              DgammaDCepr(i,j) = (-dgdGamma*DGDCepr(i,j) - dgDCepr(i,j))/dgdDgamma;
+            }
           }
-    dMedCepr *= 0.5;
-    STensorOperation::multSTensor43(dMedCepr,CeprToF,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++){
-            dSdCepr(i,j,k,l) = 0.;
-            for (int m=0; m<3; m++){
-                // dSdCepr(i,j,k,l) += dKcorDcepr(i,m,k,l)*Ceinv(m,j) + KS(i,m)*dCeinvdCepr(m,j,k,l); 
-                // dSdCepr(i,j,k,l) += dCeinvdCepr(i,m,k,l)*KS(m,j) + Ceinv(i,m)*dKcorDcepr(m,j,k,l);
-                dSdCepr(i,j,k,l) += dCeinvdCepr(i,m,k,l)*MS(m,j) + Ceinv(i,m)*dMedCepr(m,j,k,l);
-                                 // KS is corKir
-            }}
-    // dSdCepr *= 0.5;
-    STensorOperation::multSTensor43(dSdCepr,CeprToF,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++){
-            dMedF(i,j,k,l) = DKcorDF(i,j,k,l); // CHANGED
-            for (int m=0; m<3; m++)
-              for (int s=0; s<3; s++)
-                dMedF(i,j,k,l) += dCedF(i,m,k,l)*KS(m,s)*Ceinv(s,j) + Ce(i,m)*(DKcorDF(m,s,k,l)*Ceinv(s,j) + KS(m,s)*dCeinvDF(s,j,k,l));
-                                    // CHECK!! the last terms
+
+        //8. update DdevphiDCepr and DphiEDCepr, DphiPDCepr
+        static STensor3 dCxdevdCepr, dCxtrdCepr;
+        dCxdevdCepr = DgammaDCepr;
+        dCxdevdCepr *= dCxdevdDgamma;
+        dCxtrdCepr = DgammaDCepr;
+        dCxdevdCepr *= dCxtrdDgamma;
+
+        static STensor3 dudCepr, dvdCepr;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dudCepr(i,j) = dudDgamma*DgammaDCepr(i,j) + dudGamma*DGDCepr(i,j);
+            dvdCepr(i,j) = dvdDgamma*DgammaDCepr(i,j) + dvdGamma*DGDCepr(i,j);
           }
-    dMedF *= 0.5;
-         
-    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++){
-            dSdF(i,j,k,l) = 0.;
-            for (int m=0; m<3; m++){
-                // dSdF(i,j,k,l) += DKcorDF(i,m,k,l)*Ceinv(m,j) + KS(i,m)*dCeinvDF(m,j,k,l); 
-                // dSdF(i,j,k,l) += dCeinvDF(i,m,k,l)*KS(m,j) + Ceinv(i,m)*DKcorDF(m,j,k,l);
-                dSdF(i,j,k,l) += dCeinvDF(i,m,k,l)*MS(m,j) + Ceinv(i,m)*dMedF(m,j,k,l);
-                                 // KS is corKir
-            }}
 
-    // dSdF *= 0.5;
-    
-    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);
+        //8.0 Do extraBranch stuff
+        if (_useExtraBranch){
+
+            // subtract predictor
+            DphiPprDCepr -= DsigV_DCepr;
+            DpDCepr -= DsigV_DCepr;
+
+            DdevphiprDCepr -= DsigD_DCepr;
+            DdevKDCepr -= DsigD_DCepr;
+       }
+
+       // update DphiPDCepr
+       STensorOperation::zero(DphiPDCepr);
+       DphiPDCepr += DphiPprDCepr;
+       for (int i=0; i<3; i++)
+         for (int j=0; j<3; j++){
+           DphiPDCepr(i,j) += ( -dvdCepr(i,j)*ptilde + 1./3.*trXn/(pow(Cxtr,2.))*dCxtrdCepr(i,j) );
+
+           if (_useExtraBranch){
+               DphiPDCepr(i,j) -= 0.5 * DsigV_dTrEe * 2*_b*DGDCepr(i,j)*ptilde;
+               for (int k=0; k<3; k++)
+                 for (int l=0; l<3; l++){
+                    DphiPDCepr(i,j) += 0.5 * DsigV_dTrEe * _I(k,l)*DlnDCepr(k,l,i,j);
+                 }
+           }
+         }
+       if (_useExtraBranch){
+           DphiPDCepr *= 1/(v + 0.5*2*_b*Gamma*DsigV_dTrEe); // 0.5 is because of 0.5*DlnDCepr. While,  Dho4_v_inv = 1/(v + 2*_b*Gamma*DsigV_dTrEe) 
+       }
+       else{
+           DphiPDCepr *= Dho4_v_inv;  // where, Dho4_v_inv = 1/v  
+       }
+       
+
+       // update DdevphiDCepr, DphiEDCepr
+       // Use Dho3 for DdevphiDCepr
+       static STensor43 G2, G3;
+       getG2Tensor(Cepr,Kepr,expGN,DCeinvprDCepr,DKeprDCepr,G2);
+       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++){
+               G3(i,j,k,l) = G2(i,j,k,l) + DdevphiprDCepr(i,j,k,l) + devXn(i,j)*dCxdevdCepr(k,l)/(pow(Cxdev,2.)) - devPhi(i,j) * dudCepr(k,l);
+               for (int p=0; p<3; p++)
+                 for (int q=0; q<3; q++){
+                    G3(i,j,k,l) +=  Dho3(i,j,p,q)* ( N(p,q)*DGDCepr(k,l) + 2.*_b*Gamma/3.*_I(p,q)*DphiPDCepr(k,l) );
+
+                    if (_useExtraBranch){
+                        G3(i,j,k,l) -= 0.5*DsigD_dDevEe(i,j,p,q)*3*devPhi(p,q)*DGDCepr(k,l);
+                        for (int r=0; r<3; r++)
+                          for (int s=0; s<3; s++){
+                            G3(i,j,k,l) += 0.5*DsigD_dDevEe(i,j,p,q)*_Idev(p,q,r,s)*DlnDCepr(r,s,k,l);
+                          }
+                    }
+                 }
+              }
+        
+       if (_useExtraBranch){
+           static STensor43 temp, temp_inv;
+           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++){
+                    temp(i,j,k,l) = u*_I4(i,j,k,l) - 3.*Gamma*Dho3(i,j,k,l) + 0.5*3.*Gamma*DsigD_dDevEe(i,j,k,l);
+           }
+           STensorOperation::inverseSTensor43(temp,temp_inv);
+           STensorOperation::multSTensor43(temp_inv,G3,DdevphiDCepr);
+       }
+       else{
+           STensorOperation::multSTensor43(Dho4_u_inv,G3,DdevphiDCepr);  
+       }
+        
+        STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+
+        //9. get DtrNDCepr DdevNdCepr
+        DtrNDCepr = DphiPDCepr;
+        DtrNDCepr *= (2.*_b);
+
+        DdevNDCepr = DdevphiDCepr;
+        DdevNDCepr *= 3.;
+
+        // 10. get dFpDCepr
+
+        // 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
+         static STensor3 DtrXdCepr;
+         static STensor43 DdevXdCepr;
+         for (int i=0; i<3; i++)
+           for (int j=0; j<3; j++){
+             DtrXdCepr(i,j) = pow(kk,1.)*dHb*Gamma*trN*DgammaDCepr(i,j) + pow(kk,1.)*Hb*( trN*DGDCepr(i,j) + Gamma*DtrNDCepr(i,j) ) - trX*dCxtrdCepr(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*Gamma*devN(i,j)*DgammaDCepr(k,l) + pow(kk,1.)*Hb*( devN(i,j)*DGDCepr(k,l) + Gamma*DdevNDCepr(i,j,k,l) ) -
+                                        devX(i,j)*dCxdevdCepr(k,l) ; // pow(kk,2.) DEBUG
+                }
+           }
+         DdevXdCepr *= 1./Cxdev;
+         DtrXdCepr *= 1./Cxtr;
+
+         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 DpDCepr, DdevKDCepr
+
+         //11.0 Correct extraBranch
+         if (_useExtraBranch){
+
+            // Dont do it like this
+            // correct DsigV_DCepr and DsigD_DCepr; Also add to DpDCepr and DdevKDCepr
+            // STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DsigV_DCepr);
+            // DsigV_DCepr *= DsigV_dTrEe;
+            // STensorOperation::multSTensor43(DsigD_dDevEe,DlnDCepr,DsigD_DCepr);
+
+            static STensor43 dDevEe_dCepr;
+            STensorOperation::zero(DsigV_DCepr);
+            STensorOperation::zero(DsigD_DCepr);
+            STensorOperation::zero(dDevEe_dCepr);
+
+            STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DsigV_DCepr);
+            STensorOperation::multSTensor43(_Idev,DlnDCepr,dDevEe_dCepr);
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                 DsigV_DCepr(i,j) -= 2*_b*(DGDCepr(i,j)*ptilde + Gamma*DphiPDCepr(i,j));
+                 for (int k=0; k<3; k++)
+                    for (int l=0; l<3; l++){
+                       dDevEe_dCepr(i,j,k,l) -= 3*(devPhi(i,j)*DGDCepr(k,l) + Gamma*DdevphiDCepr(i,j,k,l));
+                    }
+              }
+
+            DsigV_DCepr *= DsigV_dTrEe*0.5;
+            STensorOperation::multSTensor43(DsigD_dDevEe,dDevEe_dCepr,DsigD_DCepr);
+            DsigD_DCepr *= 0.5;
+
+            DpDCepr += DsigV_DCepr;
+            DdevKDCepr += DsigD_DCepr;
+
+          // dMedF, dSdF come from dKcorDcepr directly
+         }
+
+         // (DpKeprDCepr DdevKeprDCepr)
+         for (int i=0; i<3; i++){
+           for (int j=0; j<3; j++){
+             DpDCepr(i,j) -= Ke*(DGDCepr(i,j)*trN + Gamma*DtrNDCepr(i,j));
+             for (int k=0; k<3; k++){
+               for (int l=0; l<3; l++){
+                 DdevKDCepr(i,j,k,l) -=  2.*Ge*(DGDCepr(k,l)*devN(i,j) + Gamma*DdevNDCepr(i,j,k,l));
+               }
+             }
+           }
+         }
+
+      } // if Gamma
+      else{
+      // elastic
+        STensorOperation::zero(DgammaDCepr);
+        STensorOperation::zero(dFpDCepr);
+        STensorOperation::zero(DtrNDCepr);
+        STensorOperation::zero(DdevNDCepr);
+        STensorOperation::zero(DGDCepr);
+        STensorOperation::zero(dXdCepr);
+        STensorOperation::zero(dTrXdCepr);
+      }
+
+      // 12. get dKcorDcepr
+      static STensor43 dKcorDcepr;
+      dKcorDcepr = DdevKDCepr;
+      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++){
+              dKcorDcepr(i,j,k,l) += _I(i,j)*DpDCepr(k,l);
+            }
+          }
+        }
+      }
+
+      // 13. get  CeprToF conversion tensor
+      static STensor43 CeprToF;
+      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);
+            }
+          }
+        }
+      }
+
+      static STensor43 DKcorDF;
+      STensorOperation::multSTensor43(dKcorDcepr,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
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++){
+          DphiPDF(i,j) = 0.;
+          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;
+        STensorOperation::zero(DgammaDF);
+        STensorOperation::zero(DGammaDF);
+        if (Gamma > 0){
+          STensorOperation::multSTensor3STensor43(DgammaDCepr,CeprToF,DgammaDF);
+          STensorOperation::multSTensor3STensor43(DGDCepr,CeprToF,DGammaDF);
+          STensorOperation::multSTensor43(dFpDCepr,CeprToF,dFpdF);
+        }
+
+        // 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);
+                for (int m=0; m<3; m++)
+                  for (int s=0; s<3; s++)
+                    dMedF(i,j,k,l) += dCedF(i,m,k,l)*KS(m,s)*Ceinv(s,j) + Ce(i,m)*(DKcorDF(m,s,k,l)*Ceinv(s,j) + KS(m,s)*dCeinvDF(s,j,k,l));
+                                                     // KS is corKir
               }
-            }
-          }
-          
-          
+        dMedF *= 0.5;
+
+        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++){
+                dSdF(i,j,k,l) = 0.;
+                for (int m=0; m<3; m++){
+                  dSdF(i,j,k,l) += dCeinvDF(i,m,k,l)*MS(m,j) + Ceinv(i,m)*dMedF(m,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 dMeprDT, dDevMeprDT, DcorKirDT;
     static double dpMeprDT;
-    const STensor3& dKeprDT = q1->getConstRefToDcorKirDT();
+    // const STensor3& dKeprDT = q1->_DcorKirDT; // Get the predicted value
     STensorOperation::zero(dMeprDT);
-    
+
     static STensor3 temp16, temp17;
     STensorOperation::multSTensor3(dKeprDT, Ceinvpr, temp16);
     STensorOperation::multSTensor3(Cepr, temp16, temp17);
 
     dMeprDT = 0.5*(dKeprDT + temp17);
-    
+
     STensorOperation::decomposeDevTr(dMeprDT,dDevMeprDT,dpMeprDT);
-    // dpMeprDT *= 1/3; WHAT IS THE PROBLEM HERE? WHY DOES IT GIVE ZERO?
-    dpMeprDT = dMeprDT.trace()/3;
-    
+    // dpMeprDT *= 1./3.; WHAT IS THE PROBLEM HERE? WHY DOES IT GIVE ZERO?
+    dpMeprDT = dMeprDT.trace()/3.;
+
     DcorKirDT = dKeprDT; // update later
-    
+
+    // 1.1 add extraBranch DsigV_DT, DsigD_DT (these do not need to be corrected)
+    if (_useExtraBranch){
+
+        DcorKirDT += DsigD_dT;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+              DcorKirDT(i,j) += DsigV_dT*_I(i,j);
+          }
+
+        dpMeprDT += DsigV_dT; // goes to dPhipprDT
+        dDevMeprDT += DsigD_dT; // goes to dDevPhiprDT
+
+        // dMedT, dSdT come from DcorKirDT directly
+    }
+
     // 2. get dPhipprDT and dDevPhiprDT
     static double dPhipprDT;
     static STensor3 dDevPhiprDT;
-    
+
     dPhipprDT = dpMeprDT;
     dDevPhiprDT = dDevMeprDT;
-    
-    // 3. get dCxdT, dGxdT, dKxdT, dXdT
-    static double dCxdT, dGxdT, dKxdT;
-    dCxdT = 0.;
-    if (Hb>0.){dCxdT = 1/(pow(Hb,2))*pow(dHbdT,2)*(T-T0) - 1/Hb*ddHbddT*(T-T0) - 1/Hb*dHbdT;}
-    dGxdT = DGDTsum + pow(kk,1)/(2*Cx)*dHbdT - (pow(kk,1)*Hb)/(2*pow(Cx,2))*dCxdT; // pow(kk,2) CHANGE
-    dKxdT = DKDTsum + pow(kk,1)/(3*Cx)*dHbdT - (pow(kk,1)*Hb)/(3*pow(Cx,2))*dCxdT; // pow(kk,2) CHANGE
-    
+
+    // 3. get dCxdT, dXdT
+
     // need this for DmechsourceDT -> initialise here (X is backStress)
-    STensor3& dXdT = q1->getRefToDbackStressdT();  
+    STensor3& dXdT = q1->getRefToDbackStressdT();
     STensorOperation::zero(dXdT);
-    dXdT -= (q1->_backsig)*(dCxdT);
-    dXdT *= 1/Cx;
-    
+    STensor3& dGammaNdT =  q1->_dGammaNdT;
+    STensorOperation::zero(dGammaNdT);
+
     // 4. get dPhiPdT and dDevPhiDT
     static double dPhiPdT;
     static STensor3 dDevPhiDT;
-    STensorOperation::zero(dDevPhiDT);
-    
-    static double temp18;
-    static STensor3 temp19;
-     
-    dPhiPdT = dPhipprDT/v + 1/3*trXn/pow(Cx,2)*dCxdT/v; // no correction to this
-    temp18 = (ptildepr+1/3*trXn*(1-1/Cx))*(2*_b*Gamma*dKxdT)/pow(v,2); // Gamma derivatives will change this
-    dPhiPdT -= temp18;
-    
-    temp19 = (devPhipr+devXn*(1-1/Cx))*(6*Gamma*dGxdT);
-    temp19 *= 1/pow(u,2);
-    for (int i=0; i<3; i++){
-      for (int j=0; j<3; j++){
-        dDevPhiDT(i,j) = (dDevPhiprDT(i,j) + devXn(i,j)/pow(Cx,2)*dCxdT)/u - temp19(i,j);
-      }
-    }
-   
+
+    dPhiPdT = dPhipprDT;
+    dPhiPdT /= v;
+
+    dDevPhiDT = dDevPhiprDT;
+    dDevPhiDT *= 1./u;
+
     // 5. get dPhiEdT
     static double dPhiEdT;
     STensorOperation::doubleContractionSTensor3(DphiEDdevPhi,dDevPhiDT,dPhiEdT);
-    
+
     // 6. to 11. (inside if loop-> Gamma > 0.)
-    static double dAdT, dfdT;
+    static double dAdT, dfdT, dgdT;
     static double dGammaDT;
     static double DgammaDT;
     static double DtrNdT;
     static STensor3 DdevNdT;
     static STensor3 dFpDT;
-    
+
     double eta(0.),Deta(0.),DetaDT(0.);
     if (_viscosity != NULL)
         _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
-    double etaOverDt = eta/this->getTimeStep();    
+    double etaOverDt = eta/this->getTimeStep();
 
     if (Gamma >0){
         // plastic
-        
-        // 6. get DaDT, dAdT and dfdT
+
+        // 6. get dAdT, dfdT, dgdT
         fullVector<double> DaDT(3), DDaDTT(3);
         getYieldCoefficientTempDers(q1,T,DaDT,DDaDTT);
-        
-        dAdT = (4.*_b*_b*ptilde/(A*3.))*dPhiPdT + (6./A)*PhiEq*dPhiEdT;
-        dfdT = DaDT(2)*pow(PhiEq,_n) + a(2)*_n*pow(PhiEq,_n-1)*dPhiEdT - DaDT(1)*ptilde - a(1)*dPhiPdT - DaDT(0);
+
+        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));
+          dfdT -= (DetaDT*Gamma/this->getTimeStep())*_p*pow((eta*Gamma/this->getTimeStep()),(_p-1.));
         }
-        
+
+        dgdT = -kk*Gamma*dAdT;
+
         // 7. get dGammaDT, DgammaDT
-        // dGammaDT = (-dfdT-dfdDgamma*kk*Gamma*dAdT)/DfDGamma;
-        dGammaDT = (-dfdT-dfdDgamma*kk*Gamma*dAdT/(1.-kk*Gamma*dAdDgamma))/(dfdDgamma*(1.*kk*A+kk*Gamma*dAdGamma)/(1.-kk*Gamma*dAdDgamma) + dfdGamma);
-        // DgammaDT = kk*Gamma*dAdT + kk*dDgammaDGamma*dGammaDT;
-        DgammaDT = (kk*Gamma*dAdT + (1*kk*A+kk*Gamma*dAdDgamma)*dGammaDT)/(1.-kk*Gamma*dAdDgamma);
-        
-        // 8.0 update dCxdT, dKxdT, dGxdT
-        static double dHxdT;
-        dHxdT = dHbdT + dHb*DgammaDT;
-        if (Hb>0.){dCxdT = 1/(pow(Hb,2))*pow(dHxdT,2)*(T-T0) - 1/Hb*ddHbddT*(T-T0) - 1/Hb*dHxdT;} // -> assuming this is OK
-        dGxdT = DGDTsum + pow(kk,1)/(2*Cx)*dHxdT - (pow(kk,1)*Hb)/(2*pow(Cx,2))*dCxdT; // pow(kk,2) CHANGE
-        dKxdT = DKDTsum + pow(kk,1)/(3*Cx)*dHxdT - (pow(kk,1)*Hb)/(3*pow(Cx,2))*dCxdT; // pow(kk,2) CHANGE
-        
+        // double dGammaDT_old = (-dfdT-dfdDgamma*kk*Gamma*dAdT)/DfDGamma;
+        dGammaDT = (-dfdT + dfdDgamma*dgdT/dgdDgamma)/(dfdGamma - dfdDgamma*dgdGamma/dgdDgamma);
+        // double DgammaDT_old = kk*Gamma*dAdT + dDgammaDGamma*dGammaDT;
+        DgammaDT = (-dgdGamma*dGammaDT - dgdT)/dgdDgamma;
+
+
+        // 8.0 update dCxdT, dudT, dvdT
+        static double dCxdevdT, dCxtrdT;
+        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
+
+        static double dudT, dvdT;
+        dudT = 6.*Gamma*(DGDTsum + pow(kk,1.)/(2.*Cxdev)*(dHbdT) - (pow(kk,1.)*Hb)/(2.*pow(Cxdev,2))*dCxdevdT); // pow(kk,2.) DEBUG
+        dvdT = 2.*_b*Gamma*(DKDTsum + pow(kk,1.)/(3.*Cxtr)*(dHbdT) - (pow(kk,1.)*Hb)/(3.*pow(Cxtr,2))*dCxtrdT); // pow(kk,2.) DEBUG
+
+        dudT += 6.*dGammaDT*(Ge+pow(kk,1)*Hb/(2.*Cxdev));  // pow(kk,2) DEBUG
+        dvdT += 2.*_b*dGammaDT*(Ke+pow(kk,1)*Hb/(3.*Cxtr));  // pow(kk,2) DEBUG
+
         // 8. update DdevphiDT and DphiPDT
-        static double dPxdT, temp18_2;
-        static STensor3 temp19_2;
-        
-        dPxdT = 0.*m(1);
-        dCxdT += m(0)*DgammaDT;
-        dCxdT += dPxdT; 
-        
-        dPhiPdT += temp18;
-        temp18_2 = (ptildepr+1/3*trXn*(1-1/Cx))*(2*_b*(dGammaDT*(Ke+pow(kk,1)*Hb/(3*Cx)) + Gamma*dKxdT))/pow(v,2); // pow(kk,2) CHANGE
-        dPhiPdT -= temp18_2;
-        
-        dDevPhiDT += temp19;
-        temp19_2 = (devPhipr+devXn*(1-1/Cx))*(6*(dGammaDT*(Ge+pow(kk,1)*Hb/(2*Cx)) + Gamma*dGxdT)); // pow(kk,2) CHANGE
-        temp19_2 *= 1/pow(u,2);
-        dDevPhiDT -= temp19_2;
-        
+        dPhiPdT = (dPhipprDT - dvdT*ptilde + 1./3.*trXn/(pow(Cxtr,2.))*dCxtrdT);
+        if (_useExtraBranch){
+            dPhiPdT -= 2*_b*DsigV_dTrEe*dGammaDT*ptilde;
+        }
+        dPhiPdT *= Dho4_v_inv;
+
+        static STensor3 G2T, G3T;
+        getG2TTensor(Cepr,expGN,dKeprDT,G2T);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            G3T(i,j) = G2T(i,j) + dDevPhiprDT(i,j) + devXn(i,j)/pow(Cxdev,2.)*dCxdevdT - dudT*devPhi(i,j);
+            for (int p=0; p<3; p++)
+              for (int q=0; q<3; q++){
+                G3T(i,j) += Dho3(i,j,p,q)*(dGammaDT*N(p,q) + 2.*_b*Gamma/3.*dPhiPdT*_I(p,q));
+
+                if (_useExtraBranch){
+                    G3T(i,j) -= 3*DsigD_dDevEe(i,j,p,q)*dGammaDT*devPhi(p,q);
+                }
+              }
+          }
+
+        STensorOperation::multSTensor3STensor43(G3T,Dho4_u_inv,dDevPhiDT);
+
         // 9. get DtrNdT DdevNdT
         DtrNdT = dPhiPdT;
-        DtrNdT *= (2*_b);
+        DtrNdT *= (2.*_b);
 
         DdevNdT = dDevPhiDT;
-        DdevNdT *= 3;
-        
+        DdevNdT *= 3.;
+
         // 10. get dFpdT
-        static STensor3 temp20;
-        STensorOperation::zero(temp20);
+        STensorOperation::zero(dGammaNdT);
         for (int i=0; i<3; i++)
           for (int j=0; j<3; j++)
-            temp20(i,j) += N(i,j)*dGammaDT + Gamma*DdevNdT(i,j) + Gamma/3.*_I(i,j)*DtrNdT;
-            
-        static STensor43 EprFp0;
+            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++){
-                EprFp0(i,j,k,l) = 0.;
+                CeprFp0(i,j,k,l) = 0.;
                 for (int s=0; s<3; s++){
-                  EprFp0(i,j,k,l) += dexpAdA(i,s,k,l)*Fp0(s,j);
-                }
-              }
-        
-        for (int i=0; i<3; i++){
+                  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 k=0; k<3; k++)
               for (int l=0; l<3; l++){
-                  dFpdT(i,j) += EprFp0(i,j,k,l)*temp20(k,l);
+                dFpdT(i,j) += CeprFp0(i,j,k,l)*dGammaNdT(k,l);
               }
             }
-          }
-        }
-        
-        // 10.1 dXdT - backstress temperature derivative -> correction
-        
-        for (int i=0; i<3; i++){
+
+        // 10.1 dXdT - backstress temperature derivative -> correction - CHECK!!!
+        static double DtrXdT;
+        static STensor3 DdevXdT;
+        DtrXdT = pow(kk,1.)*Gamma*(dHbdT)*trN + pow(kk,1.)*Hb*(dGammaDT*trN + Gamma*DtrNdT) - dCxtrdT*trX; // pow(kk,2.) DEBUG
+        for (int i=0; i<3; i++)
           for (int j=0; j<3; j++){
-            dXdT(i,j) += 1/Cx*((pow(kk,1)*(dHbdT*Gamma*N(i,j) + Hb*temp20(i,j)))); // pow(kk,2) CHANGE
-          }
+                DdevXdT(i,j) = pow(kk,1.)*Gamma*(dHbdT)*devN(i,j) + pow(kk,1.)*Hb*( dGammaDT*devN(i,j) + Gamma*DdevNdT(i,j) ) - dCxdevdT*devX(i,j) ; // pow(kk,2.) DEBUG
         }
-        
+        DdevXdT *= 1./Cxdev;
+        DtrXdT *= 1./Cxtr;
+
+        STensorOperation::zero(dXdT);
+        dXdT = DdevXdT;
+        dXdT(0,0) = DtrXdT/3.;
+        dXdT(1,1) = DtrXdT/3.;
+        dXdT(2,2) = DtrXdT/3.;
+
         // 11. DcorKirDT
+
+         //11.0 Correct extraBranch
+         if (_useExtraBranch){
+
+            for (int i=0; i<3; i++)
+              for (int j=0; j<3; j++){
+                 DcorKirDT(i,j) -= DsigV_dTrEe*2*_b*(dGammaDT*ptilde + Gamma*dPhiPdT)*_I(i,j);
+                 for (int k=0; k<3; k++)
+                    for (int l=0; l<3; l++){
+                       DcorKirDT(i,j) -= DsigD_dDevEe(i,j,k,l)*3*(devPhi(k,l)*dGammaDT + Gamma*dDevPhiDT(k,l));
+                    }
+              }
+
+          // dMedT, dSdT come from dKcorDcepr directly
+         }
+
         for (int i=0; i<3; i++){
           for (int j=0; j<3; j++){
             DcorKirDT(i,j) -= ( DKDTsum*Gamma*trN + Ke*(dGammaDT*trN+Gamma*DtrNdT))*_I(i,j);
             DcorKirDT(i,j) -=  2.*( DGDTsum*Gamma*devN(i,j) + Ge*(dGammaDT*devN(i,j)+Gamma*DdevNdT(i,j)));
           }
         }
-        
+        q1->_DcorKirDT = DcorKirDT; // update in IP
+
+      } // if Gamma
+      else{
+          // elastic
+          STensorOperation::zero(DgammaDT);
+          STensorOperation::zero(dFpDT);
+          STensorOperation::zero(DtrNdT);
+          STensorOperation::zero(DdevNdT);
+          STensorOperation::zero(dGammaDT);
+          }
+
+      // 12. get dKcorDT
+      // done above
+
+      // 13. 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);
+             }
+
+        // 13.1 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);
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dMeDT(i,j) += dCedT(i,k)*KS(k,l)*Ceinv(l,j) + Ce(i,k)*(DcorKirDT(k,l)*Ceinv(l,j) + KS(k,l)*dCeinvdT(l,j));
+              }
+            }
+        dMeDT *= 0.5;
+
+        // 14. get dSdT
+        static STensor3 dSdT;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dSdT(i,j) = 0.;
+            for (int m=0; m<3; m++){
+              dSdT(i,j) += Ceinv(i,m)*dMeDT(m,j) + dCeinvdT(i,m)*MS(m,j);
+            }
+         }
+
+         // 15. 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));
+              }
+          }
+
+        double a100 = 0.; // DEBUG ONLY
+
+  } // stiff
+
+  if(stiff){
+
+    // 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);
+           }
+         }
+       }
+      }
+    }
+ }
+
+ // thermSrc and MechSrc
+
+ // thermalEnergy
+ double CpT;
+ 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.;
+
+  // mechSource
+  double& Wm_TVP = q1->getRefToMechSrcTVP(); // TVP
+  double& Wm_TVE = q1->getRefToMechSrcTVE(); // TVE
+
+  mechanicalSource = 0.;
+  mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,_I4,&Wm_TVE); // mechSourceTVE
+  mechanicalSource += Wm_TVE;
+
+  getMechSourceTVP(F0,F,q0,q1,T0,T,Fepr,Cepr,DphiPDF,&Wm_TVP);
+  mechanicalSource += Wm_TVP;
+
+  // freeEnergy and elastic energy
+  double& psiTVM = q1->getRefToFreeEnergyTVM();
+  // getFreeEnergyTVM(q0,q1,T0,T,&psiTVM,NULL);
+
+
+  if (stiff){
+
+    // const double& DDpsiTVMdTT_0 = q0->getConstRefToDDFreeEnergyTVMdTT();
+    // double& DDpsiTVMdTT = q1->getRefToDDFreeEnergyTVMdTT();
+    // getFreeEnergyTVM(q0,q1,T0,T,NULL,NULL,&DDpsiTVMdTT);
+    // double CpT = -T*DDpsiTVMdTT;
+    // double CpT_0 = -T0*DDpsiTVMdTT_0;
+
+    // thermal source derivatives
+    double DCpDT(0.);
+    mlawNonLinearTVE::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
+/*
+    // Numerical Derivatives
+    double T_plus(0.), Wm_TVE_plus(0.), Wm_TVP_plus(0.), dWm_TVEdT_plus(0.), dWm_TVPdT_plus(0.), DKDTsum_plus(0.), DGDTsum_plus(0.);
+    static STensor3 F_plus, Kepr_plus, Mepr_plus, Ke_plus, Me_plus, N_plus, P_plus, DphiPDF_plus, dWm_TVEdF_plus, dWm_TVPdF_plus;
+    static STensor43 ddXdTdF_plus;
+
+    static IPNonLinearTVP q_Plus(*q0);
+
+    // Thermal Derivatives
+    T_plus = T + _perturbationfactor*T0;
+
+    plasticCorrector_TVP(F0,F,q0,&q_Plus,T0,T_plus,Kepr_plus,Mepr_plus,DKDTsum_plus,DGDTsum_plus,Ke_plus,Me_plus,N_plus,P_plus,true,&DphiPDF_plus);
+    mlawNonLinearTVE::getMechSourceTVE(q0,&q_Plus,T0,T_plus,DKDTsum_plus,DGDTsum_plus,_I4,&Wm_TVE_plus);
+    mlawNonLinearTVP::getMechSourceTVP(F0,F,q0,q1,T0,T_plus,Fepr,Cepr,DphiPDF_plus,&Wm_TVP_plus);
+
+    dWm_TVEdT_plus = (Wm_TVE_plus-Wm_TVE)/(_perturbationfactor*T0);
+    dWm_TVPdT_plus = (Wm_TVP_plus-Wm_TVP)/(_perturbationfactor*T0);
+
+    // Deformation Derivatives
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        F_plus = (F);
+        F_plus(i,j) += _perturbationfactor;
+
+        plasticCorrector_TVP(F0,F_plus,q0,&q_Plus,T0,T,Kepr_plus,Mepr_plus,DKDTsum_plus,DGDTsum_plus,Ke_plus,Me_plus,N_plus,P_plus,true,&DphiPDF_plus);
+        mlawNonLinearTVE::getMechSourceTVE(q0,&q_Plus,T0,T,DKDTsum_plus,DGDTsum_plus,_I4,&Wm_TVE_plus);
+        mlawNonLinearTVP::getMechSourceTVP(F0,F_plus,q0,&q_Plus,T0,T,Fepr,Cepr,DphiPDF_plus,&Wm_TVP_plus); // F_plus here doesnt change anything
+
+        dWm_TVEdF_plus(i,j) = (Wm_TVE_plus - Wm_TVE)/_perturbationfactor;
+        dWm_TVPdF_plus(i,j) = (Wm_TVP_plus - Wm_TVP)/_perturbationfactor;
+      }
+    }*/
+
+  // conversion tensor for mechSourceTVE Terms
+  static STensor43 DCeDFe, DEeDFe;
+  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++){
+          DCeDFe(i,j,k,l) = 0.;
+          for (int p=0; p<3; p++){
+            DCeDFe(i,j,k,l) += 2.*F(p,i)*dFedF(p,j,k,l);
+          }
+        }
+
+  STensorOperation::multSTensor43(DlnDCe,DCeDFe,DEeDFe);
+  DEeDFe *= 0.5;
+
+  double& dWmdT_TVE = q1->getRefTodMechSrcTVEdT();
+  STensor3& dWmdF_TVE = q1->getRefTodMechSrcTVEdF();
+  mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,DEeDFe,NULL,&dWmdF_TVE,&dWmdT_TVE);
+
+  double& dWmdT_TVP = q1->getRefTodMechSrcTVPdT();
+  STensor3& dWmdF_TVP = q1->getRefTodMechSrcTVPdF();
+  getMechSourceTVP(F0,F,q0,q1,T0,T,Fepr,Cepr,DphiPDF,NULL,&dWmdF_TVP,&dWmdT_TVP);
+
+  dmechanicalSourcedT = 0.;
+  STensorOperation::zero(dmechanicalSourceF);
+  dmechanicalSourceF += dWmdF_TVE;
+  dmechanicalSourcedT += dWmdT_TVE;
+  dmechanicalSourceF += dWmdF_TVP; // dWmdF_TVP;
+  dmechanicalSourcedT += dWmdT_TVP; // dWmdF_TVP;
+
+  /*
+  dmechanicalSourceF += dWm_TVEdF_plus; // dWmdF_TVP;
+  dmechanicalSourceF += dWm_TVPdF_plus; // dWmdF_TVP;
+  dmechanicalSourcedT += dWm_TVEdT_plus;
+  dmechanicalSourcedT += dWm_TVPdT_plus;  */
+
+ }
+}
+
+void mlawNonLinearTVP::getG2Tensor(const STensor3& Cepr, const STensor3& Kepr, const STensor3& expGN,
+                                    const STensor43& DCeinvprDCepr, const STensor43& DKeprDCepr, STensor43& G2) const{
+
+  static STensor3 Hinv;
+  STensorOperation::inverseSTensor3(expGN,Hinv);
+
+  static STensor3 Ceinvpr;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  static STensor43 term1, term2, term3;
+
+  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.;
+          term3(i,j,k,l) = 0.;
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++){
+                term2(i,j,k,l) -= _I4(i,p,k,l)*Kepr(p,q)*Ceinvpr(q,j);
+                term3(i,j,k,l) -= (Cepr(i,p)*DKeprDCepr(p,q,k,l)*Ceinvpr(q,j) + Cepr(i,p)*Kepr(p,q)*DCeinvprDCepr(q,j,k,l));
+              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)*Kepr(r,s)*Ceinvpr(s,m)*expGN(m,o)*expGN(o,j) +
+                                        Hinv(i,p)*Hinv(p,q)*Cepr(q,r)*DKeprDCepr(r,s,k,l)*Ceinvpr(s,m)*expGN(m,o)*expGN(o,j) );
+                      term2(i,j,k,l) += Hinv(i,p)*Hinv(p,q)*Cepr(q,r)*Kepr(r,s)*DCeinvprDCepr(s,m,k,l)*expGN(m,o)*expGN(o,j);
+                    }
+            }
+         }
+  STensorOperation::zero(G2);
+  G2 = term1+term2+term3;
+  G2 *= 0.5;
+
+}
+
+void mlawNonLinearTVP::getG2TTensor(const STensor3& Cepr, const STensor3& expGN, const STensor3& dKeprDT, STensor3& G2T) const{
+
+  static STensor3 Hinv;
+  STensorOperation::inverseSTensor3(expGN,Hinv);
+
+  static STensor3 Ceinvpr;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++){
+      G2T(i,j) = 0.;
+      for (int p=0; p<3; p++)
+        for (int q=0; q<3; q++){
+          G2T(i,j) -= Cepr(i,p)*dKeprDT(p,q)*Ceinvpr(q,j);
+          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++){
+                  G2T(i,j) += Hinv(i,p)*Hinv(p,q)*Cepr(q,r)*dKeprDT(r,s)*Ceinvpr(s,m)*expGN(m,o)*expGN(o,j);
+                }
+        }
     }
-    else{
-        // elastic
-        STensorOperation::zero(DgammaDT);
-        // STensorOperation::zero(dFpDT);
-        STensorOperation::zero(DtrNdT);
-        STensorOperation::zero(DdevNdT);
-        STensorOperation::zero(dGammaDT);
-        }
-        
-    // 12. get dKcorDT
-    // done above 
-    
-    // 13. 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);
+    G2T *= 0.5;
+}
+
+void mlawNonLinearTVP::getDho3(const double& u, const double& v, const double& Gamma, const STensor3& Cepr, const STensor3& Ceinvpr, const STensor3& Kepr,
+                                  const STensor3& expGN, const STensor43& dexpAdA, STensor43& Dho3, STensor43& Dho4inv, STensor43& Dho4_u_inv , double& Dho4_v_inv,
+                                  const double* DsigV_dTrEe, const STensor43* DsigD_dDevEe) const{
+
+  static STensor3 HT, Hinv, HTinv; // H = expGN is a symmetric tensor
+  STensorOperation::inverseSTensor3(expGN,Hinv);
+  STensorOperation::transposeSTensor3(expGN,HT);
+  STensorOperation::transposeSTensor3(Hinv,HTinv);
+
+  static STensor43 dHinvdH;
+  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++){
+          dHinvdH(i,s,k,l) = 0.;
+          for (int m=0; m<3; m++)
+            for (int j=0; j<3; j++){
+              dHinvdH(i,s,k,l) -= Hinv(i,m)*_I4(m,j,k,l)*Hinv(j,s);
+            }
         }
-    
-    STensorOperation::zero(dCedT);
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
+
+  static STensor43 dHHdH, dHinvHinvdH;
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++)
+      for (int m=0; m<3; m++)
+        for (int n=0; n<3; n++){
+          dHHdH(i,j,m,n) = 0.5*( _I(i,m)*expGN(j,n) + _I(i,n)*expGN(j,m) + _I(j,n)*expGN(i,m) + _I(j,m)*expGN(i,n));
+          dHinvHinvdH(i,j,m,n) = 0.;
           for (int p=0; p<3; p++){
-            dCedT(i,j) += Fe(p,i)*dFedT(p,j) + dFedT(p,i)*Fe(p,j); // This Works!
+              dHinvHinvdH(i,j,m,n) += dHinvdH(i,p,m,n)*Hinv(p,j) + Hinv(i,p)*dHinvdH(p,j,m,n);
           }
         }
 
-    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);
-          }
-    
-    // 13.1 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);
-        for (int k=0; k<3; k++)
-          for (int l=0; l<3; l++){
-            dMeDT(i,j) += dCedT(i,k)*KS(k,l)*Ceinv(l,j) + Ce(i,k)*(DcorKirDT(k,l)*Ceinv(l,j) + KS(k,l)*dCeinvdT(l,j));
-          }
-      }
-    dMeDT *= 0.5; 
-    
-    // 14. get dSdT
-    static STensor3 dSdT;
-    for (int i=0; i<3; i++)
-      for (int j=0; j<3; j++){
-        dSdT(i,j) = 0.;
-        for (int m=0; m<3; m++){
-              // dSdT(i,j) += DcorKirDT(i,m)*Ceinv(m,j) + KS(i,m)*dCeinvdT(m,j) + dCeinvdT(i,m)*KS(m,j) + Ceinv(i,m)*DcorKirDT(m,j);
-              dSdT(i,j) += Ceinv(i,m)*dMeDT(m,j) + dCeinvdT(i,m)*MS(m,j);
+  static STensor3 CeprKeprCeinvpr;
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++){
+      CeprKeprCeinvpr(i,j) = 0.;
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+          CeprKeprCeinvpr(i,j) += Cepr(i,k)*Kepr(k,l)*Ceinvpr(l,j);
+     }
+   }
+
+  static STensor43 dDhoHdH;
+  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++){
+          dDhoHdH(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++)
+                    dDhoHdH(i,j,k,l) += 0.5*(dHinvHinvdH(i,p,k,l)*CeprKeprCeinvpr(p,q)*expGN(r,s)*expGN(s,j) +
+                                               Hinv(i,p)*Hinv(p,q)*CeprKeprCeinvpr(q,r)*dHHdH(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++){
+          Dho3(i,j,k,l) = 0.;
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++)
+              Dho3(i,j,k,l) += dDhoHdH(i,j,p,q)*dexpAdA(p,q,k,l);
         }
-      }
-    // dSdT *= 0.5;
-    
-    // 15. Finally, get dPdT
-    // static STensor3 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));
+
+  static STensor43 Dho4, Dho4_u;
+  static STensor3 Dho4_v; // The implementation below is incorrect
+  double Dho4_v_scalar_correct = 0.;
+  STensorOperation::zero(Dho4_u);
+  STensorOperation::zero(Dho4_v);
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++){
+      Dho4_v(i,j) += v*_I(i,j);
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+
+          Dho4(i,j,k,l) = 0.;
+          Dho4_u(i,j,k,l) += u*_I4(i,j,k,l) - 3.*Gamma*Dho3(i,j,k,l);
+          Dho4_v(i,j) -= 2.*_b/3.*Gamma*Dho3(i,j,k,l)*_I(k,l);
+
+          if (_useExtraBranch){
+             Dho4_u(i,j,k,l) += 3.*Gamma* (*DsigD_dDevEe)(i,j,k,l);
           }
-      }
-  
-  }  
-  
-  if(stiff){
 
-  // TVP - flux, thermalEnergy, thermalSource
-    if (!_thermalEstimationPreviousConfig){
+          for (int p=0; p<3; p++)
+            for (int q=0; q<3; q++){
+              Dho4(i,j,k,l) += (u*_I4(i,j,p,q) - 3.*Gamma*Dho3(i,j,p,q))*_Idev(p,q,k,l) + (v*_I4(i,j,p,q) - 2.*_b/3.*Gamma*Dho3(i,j,p,q))*(_I4(p,q,k,l) -_Idev(p,q,k,l));
 
-      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);
-                  }
-                }
+              if (_useExtraBranch){
+                  Dho4(i,j,k,l) += ( 3.*Gamma* (*DsigD_dDevEe)(i,j,p,q) )*_Idev(p,q,k,l) + (2.*_b*Gamma*(*DsigV_dTrEe)*_I4(i,j,p,q))*(_I4(p,q,k,l) -_Idev(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++){
-            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);
-            }
-          }
         }
       }
     }
+
+
+  STensorOperation::inverseSTensor43(Dho4,Dho4inv);
+  STensorOperation::inverseSTensor43(Dho4_u,Dho4_u_inv);
+  // STensorOperation::inverseSTensor3(Dho4_v,Dho4_v_inv);
+
+  Dho4_v_scalar_correct = v;
+  if (_useExtraBranch){
+    Dho4_v_scalar_correct += 2.*_b*Gamma* (*DsigV_dTrEe);
   }
+  if(abs(Dho4_v_scalar_correct)>0.){
+    Dho4_v_inv = 1./Dho4_v_scalar_correct;
+  }
+
+}
+
+void mlawNonLinearTVP::getIterated_DPhi(const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
+                                            const double& u, const double& v, const double& Gamma, const double& Cxtr, const double& Cxdev, const STensor3& Phipr,
+                                            const double& trXn, const STensor3& devXn, const STensor3& Cepr, const STensor3& Eepr, const STensor3& Kepr,
+                                            double& ptilde, STensor3& devPhi,
+                                            STensor3& Phi, STensor3& N, STensor3& expGN, STensor43& dexpAdA,
+                                            STensor43& Dho3, STensor43& Dho4inv, STensor43& Dho4_u_inv , double& Dho4_v_inv,
+                                            STensor3& sigExtra_pr, STensor3& sigExtra, double& DsigV_dTrEe, STensor43& DsigD_dDevEe) const{
+
+  static STensor3 Hinv, GammaN;
+  static STensor3 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);
+     }
+   }
 
-  // thermSrc and MechSrc
+  // Initialise D
+  static STensor3 D;
+  for (int i=0; i<3; i++)
+    for (int j=0; j<3; j++){
+      D(i,j) = 0.;
+      for (int k=0; k<3; k++)
+        for (int l=0; l<3; l++){
+          D(i,j) += 0.5*( Ce(i,k)*Kepr(k,l)*Ceinv(l,j) - Cepr(i,k)*Kepr(k,l)*Ceinvpr(l,j) );
+     }
+   }
 
-   // thermalEnergy
-   double CpT;
-   if (stiff){
-       double& DDpsiTVMdTT = q1->getRefToDDFreeEnergyTVMdTT();
-       getFreeEnergyTVM(q0,q1,T0,T,NULL,NULL,&DDpsiTVMdTT);
-       // CpT = -T*DDpsiTVMdTT;
-       getCp(CpT,T);
+  // Initialise J
+  static STensor3 J, J_constant;
+  STensorOperation::zero(J);
+  STensorOperation::zero(J_constant);
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      J_constant(i,j) += Phipr(i,j) + 1./3.*trXn*(1.-1./Cxtr)*_I(i,j) + devXn(i,j)*(1.-1./Cxdev);
+      J(i,j) +=  devPhi(i,j)*u + ptilde*_I(i,j)*v - D(i,j);
     }
-   else{
-       getCp(CpT,T);
+  }
+  if (_useExtraBranch){
+      J_constant -= sigExtra_pr;
+  }
+  J -= J_constant;
+
+  // Initialise Extra Branch, save sigExtra_pr
+    static STensor3 Ee;
+    DsigV_dTrEe = 0.;
+    STensorOperation::zero(Ee);
+    STensorOperation::zero(DsigD_dDevEe);
+    if (_useExtraBranch){
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            Ee(i,j) = Eepr(i,j) - Gamma*N(i,j);
+        }
+        mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra,true,NULL,NULL,&DsigV_dTrEe,&DsigD_dDevEe);
+        J -= sigExtra;
     }
 
-   q1->_thermalEnergy = CpT*T;
-
-   // thermalSource
-   if (this->getTimeStep() > 0.){
-    thermalSource = -CpT*(T-T0)/this->getTimeStep();
+  // Initialise J_tol
+  double J_tol = 0.;
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      J_tol += abs(J(i,j)) ;
     }
-   else
-    thermalSource = 0.;
+  }
 
-  // mechSourceTVP
-  double& Wm = q1->getRefToMechSrcTVP();
-  double& Wm_TVE = q1->getRefToMechSrcTVE();
+  // Initialise Dho3, Dho4inv
+  getDho3(u,v,Gamma,Cepr,Ceinvpr,Kepr,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,&DsigV_dTrEe,&DsigD_dDevEe);
 
-  mechanicalSource = 0.;
-  mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,_I4,&Wm_TVE); // mechSourceTVE
-  mechanicalSource += Wm_TVE; // DEBUGGING
+  // Initialise DPhi
+  static STensor3 DPhi;
 
-  getMechSourceTVP(q0,q1,T0,T,dFpdT,dFpdF,DphiPDF,&Wm);
-  mechanicalSource += Wm;    // DEBUGGING
+  // Initialise numerical quantities
+  static STensor3 Phi_plus, J_plus, devPhi_plus;
+  double pPhi_plus, perturbation_factor;
+  static STensor43 dJdPhi_plus, dJdPhi_plus_inv;
 
-  // freeEnergy and elastic energy
-  double& psiTVM = q1->getRefToFreeEnergyTVM();
-  getFreeEnergyTVM(q0,q1,T0,T,&psiTVM,NULL);
+  int ite = 0;
+  int maxite = 1000;
 
-  q1->_elasticEnergy = mlawNonLinearTVE::freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+  double tol = 1e-9;
+  while (fabs(J_tol) > tol or ite <1){
+    
+      /*
+     // numerical Dho4inv (Jacobian dJ/dPhi)
+     perturbation_factor = _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*perturbation_factor;
+         Phi_plus(j,i) += 0.5*perturbation_factor;
+         STensorOperation::decomposeDevTr(Phi_plus,devPhi_plus,pPhi_plus);
+         pPhi_plus = Phi_plus.trace()/3;
+         for (int k=0; k<3; k++){
+           for (int l=0; l<3; l++){
+             J_plus(k,l) = devPhi_plus(k,l)*u + pPhi_plus*_I(k,l)*v - D(k,l) - J_constant(k,l) - sigExtra(k,l);
+             dJdPhi_plus(k,l,i,j) = (J_plus(k,l) - J(k,l))/(perturbation_factor);
+           }
+         }
+       }
+     }
+     STensorOperation::inverseSTensor43(dJdPhi_plus,dJdPhi_plus_inv);*/
 
-if (stiff){
+     // 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) -= Dho4inv(i,j,k,l)*J(k,l);
+           }
+         }
 
-    const double& DDpsiTVMdTT_0 = q0->getConstRefToDDFreeEnergyTVMdTT();
-    double& DDpsiTVMdTT = q1->getRefToDDFreeEnergyTVMdTT();
-    getFreeEnergyTVM(q0,q1,T0,T,NULL,NULL,&DDpsiTVMdTT);
-    // double CpT = -T*DDpsiTVMdTT;
-    // double CpT_0 = -T0*DDpsiTVMdTT_0;
+      // update devPhi
+      for (int i=0; i<3; i++){
+        for (int j=0; j<3; j++){
+       		Phi(i,j) += DPhi(i,j);
+       	}
+      }
 
-    // thermal source derivatives
-    double DCpDT(0.);
-    mlawNonLinearTVE::getCp(CpT,T,&DCpDT);
-    static STensor3 DCpDF;
-    STensorOperation::zero(DCpDF);                                                       // CHANGE for DCpDF
+      // update devPhi, ptilde
+      STensorOperation::decomposeDevTr(Phi,devPhi,ptilde);
+      ptilde = Phi.trace()/3;
 
-    if (this->getTimeStep() > 0){
-     dthermalSourcedT = -DCpDT*(T-T0)/this->getTimeStep() - CpT/this->getTimeStep();
-     // dthermalSourcedT = -CpT/this->getTimeStep() - (CpT-CpT_0)/this->getTimeStep(); // thermalSource = -CpT*(T-T0)/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);
-    }
+      // 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);
 
-    // mechSourceTVP derivatives
+      // 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);
+          }
+        }
 
-    // conversion tensor for mechSourceTVE Terms
-    static STensor43 DCeDFe, DEeDFe;
-    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++){
-            DCeDFe(i,j,k,l) = 0.;
-            for (int p=0; p<3; p++){
-              DCeDFe(i,j,k,l) += 2*F(p,i)*dFedF(p,j,k,l);
+      // update D
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++){
+          D(i,j) = 0.;
+          for (int k=0; k<3; k++)
+            for (int l=0; l<3; l++){
+              D(i,j) += 0.5*( Ce(i,k)*Kepr(k,l)*Ceinv(l,j) - Cepr(i,k)*Kepr(k,l)*Ceinvpr(l,j) );
             }
           }
 
-    STensorOperation::multSTensor43(DlnDCe,DCeDFe,DEeDFe);
-    DEeDFe *= 0.5;
 
-    double& dWmdT_TVE = q1->getRefTodMechSrcTVEdT();
-    STensor3& dWmdF_TVE = q1->getRefTodMechSrcTVEdF();
-    mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,DEeDFe,NULL,&dWmdF_TVE,&dWmdT_TVE);
+      // update J
+      STensorOperation::zero(J);
+      for (int i=0; i<3; i++){
+        for (int j=0; j<3; j++){
+          J(i,j) +=  devPhi(i,j)*u + ptilde*_I(i,j)*v - D(i,j);
+         }
+      }
+      J -= J_constant;
+
+      // update Extra Branch
+      STensorOperation::zero(Ee);
+      STensorOperation::zero(sigExtra);
+      STensorOperation::zero(DsigD_dDevEe);
+      if (_useExtraBranch){
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            Ee(i,j) = Eepr(i,j) - Gamma*N(i,j);
+        }
+        mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra,true,NULL,NULL,&DsigV_dTrEe,&DsigD_dDevEe);
+        J -= sigExtra;
+      }
+
+      // update Dho3, Dho4inv
+      getDho3(u,v,Gamma,Cepr,Ceinvpr,Kepr,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,&DsigV_dTrEe,&DsigD_dDevEe);
+
+      // 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));
+        }
+      }*/
+
+      J_tol = J.norm0();
+      J_tol/=(_K+_G);
+
+      ite++;
 
-    dmechanicalSourcedT = 0.;
-    STensorOperation::zero(dmechanicalSourceF);
-    dmechanicalSourceF += dWmdF_TVE; // DEBUGGING
-    dmechanicalSourcedT += dWmdT_TVE; // DEBUGGING
+      //if (ite> maxite-5)
+      // Msg::Info("it = %d, tol %e, J_tol = %e, Gamma = %e",ite,tol,J_tol,Gamma);
 
-    double& dWmdT = q1->getRefTodMechSrcTVPdT();
-    STensor3& dWmdF = q1->getRefTodMechSrcTVPdF();
+      if (fabs(J_tol) <_tol) break;
 
-    getMechSourceTVP(q0,q1,T0,T,dFpdT,dFpdF,DphiPDF,NULL,&dWmdF,&dWmdT);
+      if(ite > maxite){
+        Msg::Error("No convergence for iterated Phi mlawNonLinearTVP nonAssociatedFlow Maxwell iter = %d, J_tol = %e!!",ite,J_tol);
+        Phi(0,0) = Phi(1,1) = Phi(2,2) = sqrt(-1.);
+       return;
+       }
+     } // while
 
-    dmechanicalSourceF += dWmdF;   // DEBUGGING
-    dmechanicalSourcedT += dWmdT;  // DEBUGGING
 }
-};
-  
 
 void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
                             STensor3&P, const bool stiff, STensor43& Tangent, STensor43& dFedF, STensor43& dFpdF, const double T0, const double T) const{
-  // compute elastic predictor 
+  // compute elastic predictor
   STensor3& Fp1 = q1->_Fp;
   const STensor3& Fp0 = q0->_Fp;
 
@@ -2403,7 +2898,7 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
   if(!ok)
   {
      P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
-     return; 
+     return;
   }
   Ee *= 0.5;
   DlnDCe = DlnDCepr;
@@ -2412,7 +2907,7 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
   // 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.;
-  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,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T);
 
   static STensor3 devKpr; // dev corotational kirchoff stress predictor
   static double ppr; // pressure predictor
@@ -2586,12 +3081,12 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
       if(!ok)
       {
          P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
-         return; 
+         return;
       }
       Ee *= 0.5;
 
-      // 
-      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,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T,false);
     }
     else{
       q1->getRefToDissipationActive() = false;
@@ -2644,4 +3139,137 @@ void mlawNonLinearTVP::predictorCorrector_TVP_AssociatedFlow(const STensor3& F,
   if (stiff){
      // FILL THIS
       }
-};   
+};
+
+// Old IsotropicHardeningForce formulation
+void mlawNonLinearTVP::getIsotropicHardeningForce(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
+                                      const STensor3& DphiPDF, std::vector<double>* ddRdTT, std::vector<STensor3>* ddRdFdT) const{
+
+    const double& Gamma_0 = q0->_Gamma;
+    const double& Gamma = q1->_Gamma;
+    const double& DgammaDT = q1->_DgammaDT;
+    const double& dGammaDT_0 = q0->_DGammaDT;
+    const double& dGammaDT = q1->_DGammaDT; // = 0. for debugging //DEBUGGING
+    const STensor3& DgammaDF = q1->_DgammaDF;
+    const STensor3& DGammaDF = q1->_DGammaDF;
+    const double& gamma0 = q0->_epspbarre;
+    const double& gamma1 = q1->_epspbarre;
+
+    static STensor3 devMe, devX1, dDevXdT, dDevMeDT;
+    static double pMe, pX1, dpXdT, dpMeDT;
+    static double pMe_0, pX1_0, dpXdT_0, dpMeDT_0;
+
+    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,pMe);
+    STensorOperation::decomposeDevTr(q0->_ModMandel,devMe,pMe_0);
+    STensorOperation::decomposeDevTr(q1->_backsig,devX1,pX1);
+    STensorOperation::decomposeDevTr(q0->_backsig,devX1,pX1_0);
+    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dpXdT);
+    STensorOperation::decomposeDevTr(q0->_DbackSigDT,dDevXdT,dpXdT_0);
+    STensorOperation::decomposeDevTr(q1->_DModMandelDT,dDevMeDT,dpMeDT);
+    STensorOperation::decomposeDevTr(q0->_DModMandelDT,dDevMeDT,dpMeDT_0);
+
+    pMe /= 3.; pX1 /= 3.; dpMeDT /= 3.; dpXdT /= 3.;
+    pMe_0 /= 3.; pX1_0 /= 3.; dpMeDT_0 /= 3.; dpXdT_0 /= 3.;
+
+    // dpMeDT = 0.; dpXdT = 0.; // for debugging only //DEBUGGING
+
+    // get R
+    double eta(0.),Deta(0.),DetaDT(0.),DDetaDTT(0.),DDetaDT(0.);
+    fullVector<double> a(3), Da(3), DaDT(3), DDaDTT(3), DDaDT(3);
+    getYieldCoefficients(q1,a);
+    getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+    getYieldCoefficientTempDers(q1,T,DaDT,DDaDTT);
+
+    if (_viscosity != NULL)
+        _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT,DDetaDTT,DDetaDT);
+    double etaOverDt = eta/this->getTimeStep();
+    double viscoTerm = etaOverDt*Gamma;
+
+    const std::vector<double>& R0 = q0->_IsoHardForce;
+    std::vector<double>& R = q1->_IsoHardForce;
+    const std::vector<double>& dRdT_0 = q0->_dIsoHardForcedT;
+    std::vector<double>& dRdT = q1->_dIsoHardForcedT;
+    R.resize(3,0.);
+    dRdT.resize(3,0.);
+
+    double sigc(0.), Hc(0.), dsigcdT(0.), ddsigcdTT(0.);
+    sigc = q1->_ipCompression->getR();
+    Hc = q1->_ipCompression->getDR();
+    dsigcdT = q1->_ipCompression->getDRDT();
+    ddsigcdTT = q1->_ipCompression->getDDRDTT();
+
+    R[0] = sigc * a(1) * (pMe-pX1);
+    dRdT[0] = dsigcdT*a(1)*(pMe-pX1) + sigc*( DaDT(1)*(pMe-pX1) + a(1)*(dpMeDT-dpXdT) );
+    R[1] =  sigc * a(0);
+    dRdT[1] = dsigcdT * a(0) + sigc * DaDT(0) ;
+    if (Gamma>0. and etaOverDt>0.){
+       R[2] = sigc * pow(eta*Gamma/this->getTimeStep(),_p) ;
+       dRdT[2] =  dsigcdT * pow(eta*Gamma/this->getTimeStep(),_p) +
+                  sigc * _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep() ;
+    }
+
+    // dRdF
+    const std::vector<STensor3>& dRdF_0 = q0->_dIsoHardForcedF;
+    std::vector<STensor3>& dRdF = q1->_dIsoHardForcedF;
+    dRdF.resize(3,0.);
+
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        dRdF[0](i,j) = Hc*DgammaDF(i,j)*a(1)*(pMe-pX1) + sigc*( Da(1)*DgammaDF(i,j)*(pMe-pX1) + a(1)*DphiPDF(i,j) );
+        dRdF[1](i,j) = Hc*DgammaDF(i,j)*a(0) + sigc*Da(0)*DgammaDF(i,j);
+        }
+
+    if (Gamma>0 and etaOverDt>0){
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++){
+          dRdF[2](i,j) = Hc*DgammaDF(i,j) *pow(eta*Gamma/this->getTimeStep(),_p) +
+                            sigc* _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(Deta*DgammaDF(i,j) *Gamma + eta* DGammaDF(i,j))/this->getTimeStep() ;
+        }
+    }
+
+    // ddRdTT
+    double delT = T-T0;
+    if(ddRdTT!=NULL){
+
+       ddRdTT->at(0) =  ddsigcdTT *a(1)*(pMe-pX1) + 2.*dsigcdT *( DaDT(1)*(pMe-pX1) + a(1)*(dpMeDT-dpXdT) ) + sigc*( DDaDTT(1)*(pMe-pX1) + 2.*DaDT(1)*(dpMeDT-dpXdT) );
+       ddRdTT->at(1) =  ddsigcdTT *a(0) +  2.*dsigcdT *DaDT(0) + sigc* DDaDTT(0) ;
+
+       if (Gamma>0 and etaOverDt>0){
+        ddRdTT->at(2) = ddsigcdTT * pow(eta*Gamma/this->getTimeStep(),_p)
+                        + 2.*dsigcdT *_p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep()
+                        + sigc* _p*(_p-1)*pow(eta*Gamma/this->getTimeStep(),_p-2)*pow( ((DetaDT*Gamma + eta*dGammaDT)/this->getTimeStep()) ,2)
+                        + sigc* _p*pow(eta*Gamma/this->getTimeStep(),_p-1)* (DDetaDTT*Gamma + 2.*DetaDT*dGammaDT )/this->getTimeStep() ;
+       }
+
+       if (delT>1e-10){
+        double DphiPDT = dpMeDT- dpXdT;
+        double DDphiPDTT = 0.; // (DphiPDT - (trMe-trMe_0+trX1_0-trX1)/delT)/delT; // 2*DphiPDT/delT - 2*(trMe-trMe_0+trX1_0-trX1)/pow(delT,2); // DEBUGGING
+        ddRdTT->at(0) += sigc * a(1) * DDphiPDTT ;
+
+        if (Gamma>0 and etaOverDt>0){
+         double DDGammaDTT =  0.; // 2*dGammaDT/delT - 2*(Gamma-Gamma_0)/pow(delT,2); // DEBUGGING
+         ddRdTT->at(2) += sigc* _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(eta*DDGammaDTT)/this->getTimeStep() ;
+        }
+       }
+       q1->_ddIsoHardForcedTT = *ddRdTT;
+    }
+    // ddRdTT = 2*dRdT/(T-T0) - 2*(R-R0)/pow((T-T0),2); // ddGammaDTT is very difficult to estimate
+
+    // ddRdTF
+    if(ddRdFdT!=NULL){
+        /*
+      for (int i=0; i<3; i++)
+        for (int j=0; j<3; j++){
+          ddRdFdT->at(0)(i,j) = 0.;
+        }*/
+
+      for (int k=0; k<3; k++){
+        STensorOperation::zero(ddRdFdT->at(k));
+        if(delT>1e-10){
+          ddRdFdT->at(k) = dRdF[k];
+          ddRdFdT->at(k) -= dRdF_0[k];
+          ddRdFdT->at(k) *= 1/delT;
+        }
+      }
+    }
+};
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVP.h b/NonLinearSolver/materialLaw/mlawNonLinearTVP.h
index 922286a716d4ae3e6cbc8f83a340f0379460d07f..7fa218150b02500b05062c5f48756da85281c148 100644
--- a/NonLinearSolver/materialLaw/mlawNonLinearTVP.h
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVP.h
@@ -19,6 +19,9 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
     protected:
         // double _tol; // for plasticity convergence
         double _TaylorQuineyFactor; // for heat conversion
+        bool _TaylorQuineyFlag;
+        double _PolyOrderChaboche; // polynomial order of Chaboche Coeffs
+        fullVector<double> _PolyCoeffsChaboche; // coeff of polymonial _coefficients(0)+_coefficients(1)*eps+...
         
         scalarFunction* _temFunc_Sy0; // temperature dependence of initial yield stress
         scalarFunction* _temFunc_H; // temperature dependence of hardening stress    
@@ -32,19 +35,46 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
         virtual void hardening(const IPNonLinearTVP* q0, IPNonLinearTVP* q1, const double& T) const;
         virtual void getModifiedMandel(const STensor3& C, const IPNonLinearTVP *q0_, IPNonLinearTVP *q1) const;
         virtual void checkCommutavity(STensor3& commuteCheck, const STensor3& Ce, const STensor3& S, const IPNonLinearTVP *q1) const;
-        virtual void getChabocheCoeffs(fullVector<double>& coeffs, const double& opt, const IPNonLinearTVP *q1) const;
+        virtual void getChabocheCoeffs(fullVector<double>& coeffs, const double& opt, const IPNonLinearTVP *q1, std::vector<double>* dcoeffs=NULL) const;
         virtual void getPlasticPotential(const double& phiP, const double& phiE, double& Px) const;
         virtual void getYieldCoefficientTempDers(const IPNonLinearTVP *q1, const double& T, fullVector<double>& DcoeffsDT, fullVector<double>& DDcoeffsDTT) const;
+        
+        virtual void getIsotropicHardeningForce(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
+                                      double* ddRdTT = NULL, STensor3* ddRdFdT = NULL) const;
         virtual void getIsotropicHardeningForce(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
                                       const STensor3& DphiPDF, std::vector<double>* ddRdTT = NULL, std::vector<STensor3>* ddRdFdT = NULL) const;
         
-        virtual void getMechSourceTVP(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double& T,
-                                      const STensor3& dFpdT, const STensor43& dFpdF, const STensor3& DphiPDF,
-                                      double *Wm = NULL, STensor3 *dWmdF = NULL, double *dWmdT = NULL) const;
+        virtual void getMechSourceTVP(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1,
+                                      const double T0, const double& T, const STensor3& Fepr, const STensor3& Cepr,
+                                      const STensor3& DphiPDF, double *Wm = NULL, STensor3 *dWmdF = NULL, double *dWmdT = NULL) const;
                                       
         virtual void getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T,
                                       double *psiTVM = NULL, double *DpsiTVMdT = NULL, double *DDpsiTVMdTT = NULL) const;
-        
+                                      
+        virtual void getIterated_DPhi(const double& T, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, 
+                                      const double& u, const double& v, const double& Gamma, const double& Cxtr, const double& Cxdev, const STensor3& Phipr, 
+                                            const double& trXn, const STensor3& devXn, const STensor3& Cepr, const STensor3& Eepr, const STensor3& Kepr, 
+                                            double& ptilde, STensor3& devPhi,
+                                            STensor3& Phi, STensor3& N, STensor3& expGN, STensor43& dexpAdA, 
+                                            STensor43& Dho3, STensor43& Dho4inv, STensor43& Dho4_u_inv, double& Dho4_v_inv, 
+                                            STensor3& sigExtra_pr, STensor3& sigExtra, double& DsigV_dTrEe, STensor43& DsigD_dDevEe) const;
+                                
+        virtual void getDho3(const double& u, const double& v, const double& Gamma, const STensor3& Cepr, const STensor3& Ceinvpr, const STensor3& Kepr,
+                                  const STensor3& expGN, const STensor43& dexpAdA, STensor43& Dho3, STensor43& Dho4inv, 
+                                  STensor43& Dho4_u_inv, double& Dho4_v_inv, const double* DsigV_dTrEe = NULL, const STensor43* DsigD_dDevEe = NULL) const;
+                                  
+        virtual void getG2Tensor(const STensor3& Cepr, const STensor3& Kepr, const STensor3& expGN,
+                                   const STensor43& DCeinvprDCepr, const STensor43& DKeprDCepr, STensor43& G2) const;
+                                   
+        virtual void getG2TTensor(const STensor3& Cepr, const STensor3& expGN, const STensor3& dKeprDT, STensor3& G2T) const;
+
+                                  
+        virtual void plasticCorrector_TVP(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
+                                          STensor3& Kepr, STensor3& Mepr,
+                                          double& DKDTsum, double& DGDTsum,
+                                          STensor3& corKir_e, STensor3& Me, STensor3& N, STensor3& P,
+                                          const bool stiff = false, STensor3 *DphiPDF = NULL) const{};
+                                          
         virtual void predictorCorrector_TVP_nonAssociatedFlow(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,
@@ -61,7 +91,7 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
                                   double &mechanicalSource,         // mechanical source--> convert to heat
                                   double &dmechanicalSourcedT,
                                   STensor3 &dmechanicalSourceF) const;
-
+                                  
         virtual void predictorCorrector_TVP_AssociatedFlow(const STensor3& F, const IPNonLinearTVP *q0_, IPNonLinearTVP *q1,
                             STensor3&P, const bool stiff, STensor43& Tangent, STensor43& dFedF, STensor43& dFpdF,
                             const double T0, const double T1) const;
@@ -152,6 +182,9 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
         
         virtual void setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3);
         
+        virtual void setPolynomialOrderChabocheCoeffs(const int order);
+        virtual void setPolynomialCoeffsChabocheCoeffs(const int i, const double val);
+        
         void setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc){
             if (_temFunc_Sy0 != NULL) delete _temFunc_Sy0;
             _temFunc_Sy0 = Tfunc.clone();
@@ -174,7 +207,7 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
             // _viscosity->setTemperatureFunction(Tfunc);
         }
         
-        void setTaylorQuineyFactor(const double f){_TaylorQuineyFactor = f;};
+        void setTaylorQuineyFactor(const double f, const bool flag){_TaylorQuineyFactor = f; _TaylorQuineyFlag = flag;};
         
         virtual matname getType() const{return materialLaw::nonlinearTVP;}
         virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, 
@@ -225,4 +258,1100 @@ class mlawNonLinearTVP : public mlawNonLinearTVE{
         #endif // SWIG
 };
 
-#endif //mlawNonLinearTVP
\ No newline at end of file
+#endif //mlawNonLinearTVP
+
+/*
+void mlawNonLinearTVP::plasticCorrector_TVP(const STensor3& F0, const STensor3& F, const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double T0, const double T,
+                                          STensor3& Kepr, STensor3& Mepr, double& DKDTsum, double& DGDTsum,
+                                          STensor3& corKir_e, STensor3& Me, STensor3& N, STensor3& P,
+                                          const bool stiff, STensor3 *DphiPDF) const{
+
+
+// compute elastic predictor
+  STensor3& Fp1 = q1->_Fp;
+  const STensor3& Fp0 = q0->_Fp;
+
+  // 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->hardening(q0,q1,T);
+  static fullVector<double> a(3), Da(3); // yield coefficients and derivatives in respect to plastic deformation
+  this->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->getDR(); // kinematic hardening parameter
+    dHb = q1->_ipKinematic->getDDR(); // kinematic hardening parameter derivative (dHb/dgamma)
+    dHbdT = Hb * q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+    ddHbddT = Hb * q1->_ipKinematic->getDDRDTT();
+  }
+
+  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;
+
+  STensor3& Ee = q1->_Ee;
+  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
+  double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
+  double DKe, DGe = 0.; double DKde, DGde = 0.; // double DKDTsum, DGDTsum = 0.;
+  ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T);
+  getTVEdCorKirDT(q0,q1,T0,T);
+
+  // additional branch - update predictor
+  double DsigV_dTrEe_pr(0.), DsigV_dTrEe(0.);
+  static STensor3 sigExtra_pr, sigExtra, DsigExtraDT_pr, DsigExtraDT;
+  static STensor43 DsigD_dDevEe_pr, DsigD_dDevEe;
+  STensorOperation::zero(sigExtra_pr);
+  STensorOperation::zero(sigExtra);
+  STensorOperation::zero(DsigExtraDT_pr);
+  STensorOperation::zero(DsigExtraDT);
+  STensorOperation::zero(DsigD_dDevEe_pr);
+  STensorOperation::zero(DsigD_dDevEe);
+  if (_useExtraBranch){
+    mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra_pr,stiff,NULL,&DsigExtraDT_pr, &DsigV_dTrEe_pr, &DsigD_dDevEe_pr);
+  }
+  q1->_kirchhoff += sigExtra_pr;
+  q1->_DcorKirDT += DsigExtraDT_pr;
+
+  const STensor3& dKeprDT = q1->_DcorKirDT; // Get the predicted value
+
+  // Initialise Dho
+  static STensor43 Dho3, Dho4inv, Dho4_u_inv;  // This will be the final important tensor.
+  double Dho4_v_inv(0.);
+
+  // Get Mepr
+  // static STensor3 Me, Mepr, Kepr;  // Ke is corKir
+  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,devPhi; // effective dev stress predictor
+  static double ptildepr,ptilde;
+  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
+  // double Gamma = 0.;
+  double& Gamma = q1->_Gamma;   // flow rule parameter
+  Gamma = 0.;
+  double dDgammaDGamma = 0.;
+  double Dgamma = 0.; // eqplastic strain
+  static fullVector<double> m(2);
+  getChabocheCoeffs(m,0,q1);
+
+  double DfDGamma = 0.;
+  double dfdDgamma(0.), dfdGamma(0.);
+  double dAdDgamma(0.), dAdGamma(0.);
+  double u = 1.;
+  double v = 1.;
+
+  // Initialise Cx, Gt, Kt
+  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.), dudDgamma(0.), dvdDgamma(0.), dudGamma(0.), dvdGamma(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);
+  }
+  double Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2) DEBUG
+  double Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2) DEBUG
+
+  // Initialise ptilde and devPhi (phi)
+  ptilde = ptildepr; // current effective pressure  -> first invariant
+  devPhi = devPhipr;
+
+  // Initialise the rest
+  getDho3(u,v,Gamma,Cepr,Ceinvpr,Kepr,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv);
+
+  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;
+
+  // Test
+  double Dgammma_test = 0.;
+
+  // 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, dudDgamma dvdDgamma, dudGamma, dvdGamma
+        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
+
+        dudDgamma = 6.*Gamma*( pow(kk,1.)/(2.*Cxdev)*dHb - (pow(kk,1.)*Hb)/(2.*pow(Cxdev,2.))*dCxdevdDgamma ); // pow(kk,2.) DEBUG
+        dvdDgamma = 2.*_b*Gamma*( pow(kk,1.)/(3.*Cxtr)*dHb - (pow(kk,1.)*Hb)/(3.*pow(Cxtr,2.))*dCxtrdDgamma ); // pow(kk,2.) DEBUG
+
+        dudGamma = 6.*(Ge + pow(kk,1.)*Hb/(2.*Cxdev)); // pow(kk,2.) DEBUG
+        dvdGamma = 2.*_b*(Ke + pow(kk,1.)*Hb/(3.*Cxtr)); // pow(kk,2.) DEBUG
+
+        // Get Hp = dPhiPdDgamma, dPhiPdGamma
+        double Hp =  (1./3.*trXn/(pow(Cxtr,2.))*dCxtrdDgamma - ptilde*dvdDgamma)/v;
+        double dPhiPdGamma = - ptilde*dvdGamma/v;
+
+        // Get He = dPhiEdGamma
+          // Get DdevPhidGamma
+        STensor3 DdevPhidDgamma, DdevPhidDgamma_RHS;
+        STensor3 DdevPhidGamma, DdevPhidGamma_RHS;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            DdevPhidDgamma_RHS(i,j) = devXn(i,j)/(pow(Cxdev,2.))*dCxdevdDgamma - dudDgamma*devPhi(i,j);
+            DdevPhidGamma_RHS(i,j) = -dudGamma*devPhi(i,j);
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                DdevPhidDgamma_RHS(i,j) += (2.*_b/3.)*Gamma*Dho3(i,j,k,l)*_I(k,l)*Hp; //ADD
+
+                DdevPhidGamma_RHS(i,j) += (2.*_b/3.)*Gamma*Dho3(i,j,k,l)*_I(k,l)*dPhiPdGamma; //ADD
+
+                DdevPhidGamma_RHS(i,j) += Dho3(i,j,k,l)*N(k,l);
+              }
+            }
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            DdevPhidGamma(i,j) = 0.;
+            DdevPhidGamma(i,j) = 0.;
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                DdevPhidDgamma(i,j) += Dho4_u_inv(i,j,k,l)*DdevPhidDgamma_RHS(k,l);
+                DdevPhidGamma(i,j) += Dho4_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 = kk*(A+Gamma*dAdGamma);  // mistake in the paper (VD 2016)
+
+        this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+
+        // DEBUG FLE
+        double a0 = a(0);
+        double a1 = a(1);
+        double a2 = a(2);
+        double da0 = Da(0);
+        double da1 = Da(1);
+        double da2 = Da(2);
+
+        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!! WHY??
+
+        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
+        updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+        hardening(q0,q1,T);
+        getYieldCoefficients(q1,a);
+        if (q1->_ipKinematic != NULL){
+            Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
+            dHb = q1->_ipKinematic->getDDR(); // kinematic hardening parameter derivative (dHb/dgamma ??)
+            dHbdT = Hb * q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+            ddHbddT = Hb * q1->_ipKinematic->getDDRDTT();
+        }
+        //a.print("a update");
+
+        // Update Cx, u, v
+        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);
+        }
+        Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2) DEBUG
+        Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2) DEBUG
+        u = 1.+6.*Gt*Gamma;
+        v = 1.+2.*_b*Kt*Gamma;
+
+        // Update Phi
+        // ptilde = ptildepr + 1/3*trXn*(1-1/Cxtr);
+        // ptilde /= v;
+        getIterated_DPhi(T,q0,q1,u,v,Gamma,Cxtr,Cxdev,PhiPr,trXn,devXn,Cepr,Eepr,Kepr,ptilde,devPhi,Phi,N,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv,
+                            sigExtra,DsigV_dTrEe,DsigD_dDevEe);
+        PhiEq = sqrt(1.5*devPhi.dotprod());
+
+        // Update A
+        A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+        Dgamma = kk*Gamma*A;
+        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, u, v
+    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);
+    }
+    Gt = Ge + pow(kk,1.) * Hb/(2.*Cxdev); // pow(kk,2.) DEBUG
+    Kt = Ke + pow(kk,1.) * Hb/(3.*Cxtr); // pow(kk,2.) DEBUG
+    u = 1.+6.*Gt*Gamma;
+    v = 1.+2.*_b*Kt*Gamma;
+
+    // Correct Phi
+    // ptilde = ptildepr + 1/3*trXn*(1-1/Cxtr);
+    // ptilde /= v;
+    getIterated_DPhi(T,q0,q1,u,v,Gamma,Cxtr,Cxdev,PhiPr,trXn,devXn,Cepr,Eepr,Kepr,ptilde,devPhi,Phi,N,expGN,dexpAdA,Dho3,Dho4inv,Dho4_u_inv,Dho4_v_inv, 
+                        sigExtra,DsigV_dTrEe,DsigD_dDevEe);
+    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);
+    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;
+
+    // Correct A, B
+    ThermoViscoElasticPredictor(Ee,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); //,false);
+    getTVEdCorKirDT(q0,q1,T0,T); // update dCorKirdT - don't do this probably
+    // DKDTsum and DGDTsum = sum of bulk/shear moduli derivatives wrt T
+
+    // Correct Extrabranch - update stress
+    if (_useExtraBranch){
+        mlawNonLinearTVE::extraBranchLaw(Ee,T,q0,q1,sigExtra_pr,stiff,NULL,&DsigExtraDT,&DsigV_dTrEe,&DsigD_dDevEe);
+    }
+    q1->_kirchhoff += sigExtra_pr;
+    q1->_DcorKirDT += DsigExtraDT_pr;
+
+    // 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;
+    }
+  } // 1st if
+
+  corKir_e = q1->_kirchhoff;
+  const STensor3& KS = q1->_kirchhoff;
+  // const STensor3& DcorKirDT_TVEcorrection = q1->_DcorKirDT; // Get the corrected value directly from TVE
+  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);
+    }
+
+if (stiff){
+
+    // DECLARE UNDECLARED HERE
+    static STensor3 dFpdT;
+    static STensor43 dFpdF, dFedF;
+    STensorOperation::zero(dFpdT);
+    STensorOperation::zero(dFpdF);
+    STensorOperation::zero(dFedF);
+
+    // dP/dF
+
+    //1. get DtrKeprDCepr and DdevKeprDCepr, also DKeprDCepr
+    static STensor3 DpDCepr;
+    static STensor43 DdevKDCepr;
+    static STensor43 DdevKeprDCepr, DdevMeprDCepr, DKeprDCepr;
+    static STensor3 DpKeprDCepr, DpMeprDCepr;      // K = corKir; pK -> pressure of corKir
+    STensorOperation::multSTensor3STensor43(_I,DlnDCepr,DpKeprDCepr);
+    DpKeprDCepr*= (0.5*Ke);
+    STensorOperation::multSTensor43(_Idev,DlnDCepr,DdevKeprDCepr);
+    DdevKeprDCepr*= Ge;
+
+    // DKeprDCepr
+    DKeprDCepr = DdevKeprDCepr;
+    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++){
+            DKeprDCepr(i,j,k,l) += _I(i,j)*DpKeprDCepr(k,l);
+          }
+
+    // initiate here - corrected corKir derivatives wrt Cepr
+    DpDCepr = DpKeprDCepr;
+    DdevKDCepr = DdevKeprDCepr;
+
+    //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);
+          }
+
+    //3. get DtrMeprDCepr and DdevMeprDCepr
+    static STensor43 DMeprDCepr;
+
+    static STensor3 temp1;
+    static STensor43 temp2, temp3;
+    STensorOperation::multSTensor3(Kepr,Ceinvpr,temp1);
+
+    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++){
+            temp2(i,s,k,l) = 0.;
+            temp3(i,s,k,l) = 0.;
+            for (int m=0; m<3; m++){
+              temp2(i,s,k,l) += _I4(i,m,k,l)*temp1(m,s);
+              temp3(i,s,k,l) += DKeprDCepr(i,m,k,l)*Ceinvpr(m,s) + Kepr(i,m)*DCeinvprDCepr(m,s,k,l);
+            }
+          }
+
+    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++){
+            DMeprDCepr(i,s,k,l) = 0.;
+            for (int m=0; m<3; m++)
+              DMeprDCepr(i,s,k,l) += Cepr(i,m)*temp3(m,s,k,l);
+          }
+
+    DMeprDCepr += temp2;
+    DMeprDCepr += DKeprDCepr;
+    DMeprDCepr *= 0.5;
+
+    // Because, TrMepr = TrKepr
+    DpMeprDCepr = DpKeprDCepr;
+
+    //
+    STensorOperation::zero(DdevMeprDCepr);
+    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++){
+            DdevMeprDCepr(i,s,k,l) += DMeprDCepr(i,s,k,l) - _I(i,s)*DpMeprDCepr(k,l);
+          }
+
+    //4. get DdevphiDCepr and DphiPprDCepr
+    static STensor3 DphiPprDCepr, DphiPDCepr;
+    static STensor43 DdevphiprDCepr, DdevphiDCepr;
+
+    DphiPprDCepr = DpMeprDCepr;
+    DdevphiprDCepr = DdevMeprDCepr;
+
+    DphiPDCepr = DphiPprDCepr;
+    DphiPDCepr *= 1./v;
+    DdevphiDCepr = DdevphiprDCepr;
+    DdevphiDCepr *= 1./u;
+
+    //5. get DphiEprDCepr from DdevphiDCepr
+    static STensor3 DphiEDCepr, DphiEDdevPhi;
+    if (PhiEq >0.){
+        DphiEDdevPhi = devPhi;
+        DphiEDdevPhi *= 1.5/(PhiEq);
+    }
+
+    STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+    // 6. to 11. (inside if loop-> Gamma > 0.)
+      static STensor3 dAdCepr, dfDCepr, dgDCepr;
+      static STensor3 DGDCepr;
+      static STensor3 DgammaDCepr;
+      static STensor3 DtrNDCepr;
+      static STensor43 DdevNDCepr;
+      static STensor43 dFpDCepr;
+      static STensor43 dCedCepr, dCeinvdCepr;
+      static STensor43 dXdCepr;
+      static STensor3 dTrXdCepr;
+      static STensor43 dGammaNdCepr;
+
+      if (Gamma >0.){
+
+        //6. get dAdCepr from DdevphiDCepr
+        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
+        static STensor3 DGDCepr_test, DgammaDCepr_test;
+          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);
+            }
+          }
+
+          for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+              DgammaDCepr(i,j) = (-dgdGamma*DGDCepr(i,j) - dgDCepr(i,j))/dgdDgamma;
+            }
+          }
+
+        //8. update DdevphiDCepr and DphiEDCepr, DphiPDCepr
+        static STensor3 dCxdevdCepr, dCxtrdCepr;
+        dCxdevdCepr = DgammaDCepr;
+        dCxdevdCepr *= dCxdevdDgamma;
+        dCxtrdCepr = DgammaDCepr;
+        dCxdevdCepr *= dCxtrdDgamma;
+
+        static STensor3 dudCepr, dvdCepr;
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dudCepr(i,j) = dudDgamma*DgammaDCepr(i,j) + dudGamma*DGDCepr(i,j);
+            dvdCepr(i,j) = dvdDgamma*DgammaDCepr(i,j) + dvdGamma*DGDCepr(i,j);
+          }
+
+       // update DphiPDCepr
+       for (int i=0; i<3; i++)
+         for (int j=0; j<3; j++){
+           DphiPDCepr(i,j) += ( -dvdCepr(i,j)*ptilde + 1./3.*trXn/(pow(Cxtr,2.))*dCxtrdCepr(i,j) )/v;
+         }
+
+       // update DdevphiDCepr, DphiEDCepr
+       // Use Dho for DdevphiDCepr
+       static STensor43 G2, G3;
+       getG2Tensor(Cepr,Kepr,expGN,DCeinvprDCepr,DKeprDCepr,G2);
+       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++){
+               G3(i,j,k,l) = G2(i,j,k,l) + DdevphiprDCepr(i,j,k,l) + devXn(i,j)*dCxdevdCepr(k,l)/(pow(Cxdev,2.)) - devPhi(i,j) * dudCepr(k,l);
+               for (int p=0; p<3; p++)
+                 for (int q=0; q<3; q++)
+                    G3(i,j,k,l) +=  Dho3(i,j,p,q)* ( N(p,q)*DGDCepr(k,l) + 2.*_b*Gamma/3.*_I(p,q)*DphiPDCepr(k,l) );
+              }
+
+        STensorOperation::multSTensor43(Dho4_u_inv,G3,DdevphiDCepr);
+        STensorOperation::multSTensor3STensor43(DphiEDdevPhi,DdevphiDCepr,DphiEDCepr);
+
+
+        //9. get DtrNDCepr DdevNdCepr
+        DtrNDCepr = DphiPDCepr;
+        DtrNDCepr *= (2.*_b);
+
+        DdevNDCepr = DdevphiDCepr;
+        DdevNDCepr *= 3.;
+
+        // 10. get dFpDCepr
+
+        // 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
+         static STensor3 DtrXdCepr;
+         static STensor43 DdevXdCepr;
+         for (int i=0; i<3; i++)
+           for (int j=0; j<3; j++){
+             DtrXdCepr(i,j) = pow(kk,1.)*dHb*Gamma*trN*DgammaDCepr(i,j) + pow(kk,1.)*Hb*( trN*DGDCepr(i,j) + Gamma*DtrNDCepr(i,j) ) - trX*dCxtrdCepr(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*Gamma*devN(i,j)*DgammaDCepr(k,l) + pow(kk,1.)*Hb*( devN(i,j)*DGDCepr(k,l) + Gamma*DdevNDCepr(i,j,k,l) ) -
+                                        devX(i,j)*dCxdevdCepr(k,l) ; // pow(kk,2.) DEBUG
+                }
+           }
+         DdevXdCepr *= 1./Cxdev;
+         DtrXdCepr *= 1./Cxtr;
+
+         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 DpDCepr, DdevKDCepr
+         // (DpKeprDCepr DdevKeprDCepr)
+         for (int i=0; i<3; i++){
+           for (int j=0; j<3; j++){
+             DpDCepr(i,j) -= Ke*(DGDCepr(i,j)*trN + Gamma*DtrNDCepr(i,j));
+             for (int k=0; k<3; k++){
+               for (int l=0; l<3; l++){
+                 DdevKDCepr(i,j,k,l) -=  2.*Ge*(DGDCepr(k,l)*devN(i,j) + Gamma*DdevNDCepr(i,j,k,l));
+               }
+             }
+           }
+         }
+
+      } // if Gamma
+      else{
+      // elastic
+        STensorOperation::zero(DgammaDCepr);
+        STensorOperation::zero(dFpDCepr);
+        STensorOperation::zero(DtrNDCepr);
+        STensorOperation::zero(DdevNDCepr);
+        STensorOperation::zero(DGDCepr);
+        STensorOperation::zero(dXdCepr);
+        STensorOperation::zero(dTrXdCepr);
+      }
+
+      // 12. get dKcorDcepr
+      static STensor43 dKcorDcepr;
+      dKcorDcepr = DdevKDCepr;
+      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++){
+              dKcorDcepr(i,j,k,l) += _I(i,j)*DpDCepr(k,l);
+            }
+          }
+        }
+      }
+
+      // 13. get  CeprToF conversion tensor
+      static STensor43 CeprToF;
+      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);
+            }
+          }
+        }
+      }
+
+      static STensor43 DKcorDF;
+      STensorOperation::multSTensor43(dKcorDcepr,CeprToF,DKcorDF);
+
+      // 14. get dSdCepr and dSdF; also get dMedCepr and dMedF
+      // Done below -> need dCedF
+
+      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
+      if(DphiPDF!=NULL){
+        STensor3 _DphiPDF(0.);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            _DphiPDF(i,j) = 0.;
+            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);
+              }
+          }
+        *DphiPDF = _DphiPDF;
+      }
+        // 15. get DgammaDF
+        STensor3& DgammaDF = q1->_DgammaDF;
+        STensor3& DGammaDF = q1->_DGammaDF;
+        STensorOperation::zero(DgammaDF);
+        STensorOperation::zero(DGammaDF);
+        if (Gamma > 0){
+          STensorOperation::multSTensor3STensor43(DgammaDCepr,CeprToF,DgammaDF);
+          STensorOperation::multSTensor3STensor43(DGDCepr,CeprToF,DGammaDF);
+          STensorOperation::multSTensor43(dFpDCepr,CeprToF,dFpdF);
+        }
+
+        // 16. Everything else
+        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);
+                for (int m=0; m<3; m++)
+                  for (int s=0; s<3; s++)
+                    dMedF(i,j,k,l) += dCedF(i,m,k,l)*KS(m,s)*Ceinv(s,j) + Ce(i,m)*(DKcorDF(m,s,k,l)*Ceinv(s,j) + KS(m,s)*dCeinvDF(s,j,k,l));
+                                                     // KS is corKir
+              }
+        dMedF *= 0.5;
+
+    // dP/dT
+
+    // 1. get dMeprDT from dKeprDT  -> DcorKirprDT from TVE
+    static STensor3 dMeprDT, dDevMeprDT, DcorKirDT;
+    static double dpMeprDT;
+    // const STensor3& dKeprDT = q1->getConstRefToDcorKirDT(); // Predictor DcorKirDT
+    STensorOperation::zero(dMeprDT);
+
+    static STensor3 temp16, temp17;
+    STensorOperation::multSTensor3(dKeprDT, Ceinvpr, temp16);
+    STensorOperation::multSTensor3(Cepr, temp16, temp17);
+
+    dMeprDT = 0.5*(dKeprDT + temp17);
+
+    STensorOperation::decomposeDevTr(dMeprDT,dDevMeprDT,dpMeprDT);
+    dpMeprDT = dMeprDT.trace()/3.;
+
+    DcorKirDT = dKeprDT; // update later
+
+    // 2. get dPhipprDT and dDevPhiprDT
+    static double dPhipprDT;
+    static STensor3 dDevPhiprDT;
+
+    dPhipprDT = dpMeprDT;
+    dDevPhiprDT = dDevMeprDT;
+
+    // 3. get dXdT
+    // need this for DmechsourceDT -> initialise here (X is backStress)
+    STensor3& dXdT = q1->getRefToDbackStressdT();
+    STensorOperation::zero(dXdT);
+    STensor3& dGammaNdT =  q1->_dGammaNdT;
+    STensorOperation::zero(dGammaNdT);
+
+    // 4. get dPhiPdT and dDevPhiDT
+    static double dPhiPdT;
+    static STensor3 dDevPhiDT;
+
+    dPhiPdT = dPhipprDT;
+    dPhiPdT /= v;
+
+    dDevPhiDT = dDevPhiprDT;
+    dDevPhiDT *= 1./u;
+
+    // 5. get dPhiEdT
+    static double dPhiEdT;
+    STensorOperation::doubleContractionSTensor3(DphiEDdevPhi,dDevPhiDT,dPhiEdT);
+
+    // 6. to 11. (inside if loop-> Gamma > 0.)
+    static double dAdT, dfdT, dgdT;
+    static double dGammaDT;
+    static double DgammaDT;
+    static double DtrNdT;
+    static STensor3 DdevNdT;
+    static STensor3 dFpDT;
+
+    double 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
+
+        // 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;
+
+        // 8.0 update dCxdT, dudT, dvdT
+        static double dCxdevdT, dCxtrdT;
+        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
+
+        static double dudT, dvdT;
+        dudT = 6.*Gamma*(DGDTsum + pow(kk,1.)/(2.*Cxdev)*(dHbdT) - (pow(kk,1.)*Hb)/(2.*pow(Cxdev,2))*dCxdevdT); // pow(kk,2.) DEBUG
+        dvdT = 2.*_b*Gamma*(DKDTsum + pow(kk,1.)/(3.*Cxtr)*(dHbdT) - (pow(kk,1.)*Hb)/(3.*pow(Cxtr,2))*dCxtrdT); // pow(kk,2.) DEBUG
+
+        dudT += 6.*dGammaDT*(Ge+pow(kk,1)*Hb/(2.*Cxdev));  // pow(kk,2) DEBUG
+        dvdT += 2.*_b*dGammaDT*(Ke+pow(kk,1)*Hb/(3.*Cxtr));  // pow(kk,2) DEBUG
+
+        // 8. update DdevphiDT and DphiPDT
+        dPhiPdT = (dPhipprDT - dvdT*ptilde + 1./3.*trXn/(pow(Cxtr,2.))*dCxtrdT)/v;
+
+        static STensor3 G2T, G3T;
+        getG2TTensor(Cepr,expGN,dKeprDT,G2T);
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            G3T(i,j) = G2T(i,j) + dDevPhiprDT(i,j) + devXn(i,j)/pow(Cxdev,2.)*dCxdevdT - dudT*devPhi(i,j);
+            for (int p=0; p<3; p++)
+              for (int q=0; q<3; q++)
+                G3T(i,j) += Dho3(i,j,p,q)*(dGammaDT*N(p,q) + 2.*_b*Gamma/3.*dPhiPdT*_I(p,q));
+          }
+
+        STensorOperation::multSTensor3STensor43(G3T,Dho4_u_inv,dDevPhiDT);
+
+        // 9. get DtrNdT DdevNdT
+        DtrNdT = dPhiPdT;
+        DtrNdT *= (2.*_b);
+
+        DdevNdT = dDevPhiDT;
+        DdevNdT *= 3.;
+
+        // 10. get dFpdT
+        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);
+              }
+            }
+
+        // 10.1 dXdT - backstress temperature derivative -> correction - CHECK!!!
+        static double DtrXdT;
+        static STensor3 DdevXdT;
+        DtrXdT = pow(kk,1.)*Gamma*(dHbdT)*trN + pow(kk,1.)*Hb*(dGammaDT*trN + Gamma*DtrNdT) - dCxtrdT*trX; // pow(kk,2.) DEBUG
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+                DdevXdT(i,j) = pow(kk,1.)*Gamma*(dHbdT)*devN(i,j) + pow(kk,1.)*Hb*( dGammaDT*devN(i,j) + Gamma*DdevNdT(i,j) ) - dCxdevdT*devX(i,j) ; // pow(kk,2.) DEBUG
+        }
+        DdevXdT *= 1./Cxdev;
+        DtrXdT *= 1./Cxtr;
+
+        STensorOperation::zero(dXdT);
+        dXdT = DdevXdT;
+        dXdT(0,0) = DtrXdT/3.;
+        dXdT(1,1) = DtrXdT/3.;
+        dXdT(2,2) = DtrXdT/3.;
+
+        // 11. DcorKirDT
+        for (int i=0; i<3; i++){
+          for (int j=0; j<3; j++){
+            DcorKirDT(i,j) -= ( DKDTsum*Gamma*trN + Ke*(dGammaDT*trN+Gamma*DtrNdT))*_I(i,j);
+            DcorKirDT(i,j) -=  2.*( DGDTsum*Gamma*devN(i,j) + Ge*(dGammaDT*devN(i,j)+Gamma*DdevNdT(i,j)));
+          }
+        }
+        q1->_DcorKirDT = DcorKirDT; // Update in IP for mechSrcTVE
+
+      } // if Gamma
+      else{
+          // elastic
+          STensorOperation::zero(DgammaDT);
+          // STensorOperation::zero(dFpDT);
+          STensorOperation::zero(DtrNdT);
+          STensorOperation::zero(DdevNdT);
+          STensorOperation::zero(dGammaDT);
+          }
+
+      // 12. get dKcorDT
+      // done above
+
+      // 13. 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);
+             }
+
+        // 13.1 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);
+            for (int k=0; k<3; k++)
+              for (int l=0; l<3; l++){
+                dMeDT(i,j) += dCedT(i,k)*KS(k,l)*Ceinv(l,j) + Ce(i,k)*(DcorKirDT(k,l)*Ceinv(l,j) + KS(k,l)*dCeinvdT(l,j));
+              }
+            }
+        dMeDT *= 0.5;
+
+  } // stiff
+
+};*/
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/mullinsEffect.cpp b/NonLinearSolver/materialLaw/mullinsEffect.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d85d26768ca6df91f1874dc3648ba169dfc13a9
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mullinsEffect.cpp
@@ -0,0 +1,539 @@
+//
+// Description: Define mullins effect for softening in polymers in (pseudo-)hyperelastic regime 
+//
+//
+// Author:  <Ujwal Kishore J.>, (C) 2023
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#include "mullinsEffect.h"
+
+mullinsEffect::mullinsEffect(const int num,const bool init): _num(num), _initialized(init){}
+
+mullinsEffect::mullinsEffect(const mullinsEffect &source)
+{
+  _num = source._num;
+  _initialized = source._initialized;
+}
+
+mullinsEffect& mullinsEffect::operator=(const mullinsEffect &source)
+{
+  _num = source._num;
+  _initialized = source._initialized;
+  return *this;
+}
+
+
+negativeExponentialScaler::negativeExponentialScaler(const int num, double r, double m, bool init):
+  mullinsEffect(num,init),_r(r),_m(m){
+      
+    _temFunc_r= new constantScalarFunction(1.);
+    _temFunc_m= new constantScalarFunction(1.);
+};
+
+negativeExponentialScaler::negativeExponentialScaler(const negativeExponentialScaler& src):
+  mullinsEffect(src), _r(src._r), _m(src._m){
+      
+    _temFunc_r = NULL;
+    if (src._temFunc_r != NULL){
+        _temFunc_r = src._temFunc_r->clone();
+    }
+    
+    _temFunc_m = NULL;
+    if (src._temFunc_m != NULL){
+        _temFunc_m = src._temFunc_m->clone();
+    }
+};
+
+negativeExponentialScaler& negativeExponentialScaler::operator =(const mullinsEffect& src){
+  mullinsEffect::operator=(src);
+  const negativeExponentialScaler* psrc = dynamic_cast<const negativeExponentialScaler*>(&src);
+  if(psrc != NULL)
+  {
+    _r = psrc->_r;
+    _m = psrc->_m;
+    
+    if (psrc->_temFunc_r != NULL){
+      if (_temFunc_r != NULL){
+        _temFunc_r->operator=(*psrc->_temFunc_r);
+      }
+      else{
+        _temFunc_r = psrc->_temFunc_r->clone();
+      }
+    }
+    
+    if (psrc->_temFunc_m != NULL){
+      if (_temFunc_m != NULL){
+        _temFunc_m->operator=(*psrc->_temFunc_m);
+      }
+      else{
+        _temFunc_m = psrc->_temFunc_m->clone();
+      }
+    }
+  }
+  return *this;
+};
+
+negativeExponentialScaler::~negativeExponentialScaler(){
+  if (_temFunc_r != NULL) {delete _temFunc_r; _temFunc_r = NULL;};
+  if (_temFunc_m != NULL) {delete _temFunc_m; _temFunc_m = NULL;};
+};
+
+void negativeExponentialScaler::setTemperatureFunction_r(const scalarFunction& Tfunc){
+  if (_temFunc_r != NULL) delete _temFunc_r;
+  _temFunc_r = Tfunc.clone();
+}
+
+void negativeExponentialScaler::setTemperatureFunction_m(const scalarFunction& Tfunc){
+  if (_temFunc_m != NULL) delete _temFunc_m;
+  _temFunc_m = Tfunc.clone();
+}
+
+void negativeExponentialScaler::createIPVariable(IPMullinsEffect* &ipv) const
+{
+  if(ipv != NULL) delete ipv;
+  ipv = new IPMullinsEffect();
+}
+
+void negativeExponentialScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const{
+    
+  // 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 _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.;
+  }
+
+  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT);
+  ipv.setPsiMax(_psi_max);
+}
+
+void negativeExponentialScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const{
+   
+  double r = _r*_temFunc_r->getVal(T);
+  double m = _m*_temFunc_m->getVal(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 _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.;
+  }
+  
+  /*
+  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);
+  ipv.setPsiMax(_psi_max);
+}
+
+mullinsEffect *negativeExponentialScaler::clone() const
+{
+  return new negativeExponentialScaler(*this);
+}
+
+// #############
+
+linearScaler::linearScaler(const int num, double r, bool init):
+  mullinsEffect(num,init),_r(r){
+      
+    _temFunc_r= new constantScalarFunction(1.);
+};
+
+linearScaler::linearScaler(const linearScaler& src):
+  mullinsEffect(src), _r(src._r){
+      
+    _temFunc_r = NULL;
+    if (src._temFunc_r != NULL){
+        _temFunc_r = src._temFunc_r->clone();
+    }
+};
+
+linearScaler& linearScaler::operator =(const mullinsEffect& src){
+  mullinsEffect::operator=(src);
+  const linearScaler* psrc = dynamic_cast<const linearScaler*>(&src);
+  if(psrc != NULL)
+  {
+    _r = psrc->_r;
+    
+    if (psrc->_temFunc_r != NULL){
+      if (_temFunc_r != NULL){
+        _temFunc_r->operator=(*psrc->_temFunc_r);
+      }
+      else{
+        _temFunc_r = psrc->_temFunc_r->clone();
+      }
+    }
+  }
+  return *this;
+};
+
+linearScaler::~linearScaler(){
+  if (_temFunc_r != NULL) {delete _temFunc_r; _temFunc_r = NULL;};
+};
+
+void linearScaler::setTemperatureFunction_r(const scalarFunction& Tfunc){
+  if (_temFunc_r != NULL) delete _temFunc_r;
+  _temFunc_r = Tfunc.clone();
+}
+
+void linearScaler::createIPVariable(IPMullinsEffect* &ipv) const
+{
+  if(ipv != NULL) delete ipv;
+  ipv = new IPMullinsEffect();
+}
+
+void linearScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const{
+    
+  // 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 _psi_max = std::max(_psi,_psi_max0);
+  Msg::Error(" Inside mullinsEffectScaling, _psi = %e, _psi_max = %e !!", _psi, _psi_max);
+
+  eta = (1-_r)/(1-_r*psi_cap/_psi_max);
+
+  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT);
+  ipv.setPsiMax(_psi_max);
+}
+
+void linearScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const{
+   
+  double r = _r*_temFunc_r->getVal(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 _psi_max = std::max(_psi,_psi_max0);
+  Msg::Error(" Inside mullinsEffectScaling, _psi = %e, _psi_max = %e !!", _psi, _psi_max);
+  
+  eta = (1-_r)/(1-_r*psi_cap/_psi_max);
+   
+  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT);
+  ipv.setPsiMax(_psi_max);
+}
+
+mullinsEffect *linearScaler::clone() const
+{
+  return new linearScaler(*this);
+}
+
+// ######
+
+positiveExponentialScaler::positiveExponentialScaler(const int num, double r, double m, bool init):
+  mullinsEffect(num,init),_r(r),_m(m){
+      
+    _temFunc_r= new constantScalarFunction(1.);
+    _temFunc_m= new constantScalarFunction(1.);
+};
+
+positiveExponentialScaler::positiveExponentialScaler(const positiveExponentialScaler& src):
+  mullinsEffect(src), _r(src._r), _m(src._m){
+      
+    _temFunc_r = NULL;
+    if (src._temFunc_r != NULL){
+        _temFunc_r = src._temFunc_r->clone();
+    }
+    
+    _temFunc_m = NULL;
+    if (src._temFunc_m != NULL){
+        _temFunc_m = src._temFunc_m->clone();
+    }
+};
+
+positiveExponentialScaler& positiveExponentialScaler::operator =(const mullinsEffect& src){
+  mullinsEffect::operator=(src);
+  const positiveExponentialScaler* psrc = dynamic_cast<const positiveExponentialScaler*>(&src);
+  if(psrc != NULL)
+  {
+    _r = psrc->_r;
+    _m = psrc->_m;
+    
+    if (psrc->_temFunc_r != NULL){
+      if (_temFunc_r != NULL){
+        _temFunc_r->operator=(*psrc->_temFunc_r);
+      }
+      else{
+        _temFunc_r = psrc->_temFunc_r->clone();
+      }
+    }
+    
+    if (psrc->_temFunc_m != NULL){
+      if (_temFunc_m != NULL){
+        _temFunc_m->operator=(*psrc->_temFunc_m);
+      }
+      else{
+        _temFunc_m = psrc->_temFunc_m->clone();
+      }
+    }
+  }
+  return *this;
+};
+
+positiveExponentialScaler::~positiveExponentialScaler(){
+  if (_temFunc_r != NULL) {delete _temFunc_r; _temFunc_r = NULL;};
+  if (_temFunc_m != NULL) {delete _temFunc_m; _temFunc_m = NULL;};
+};
+
+void positiveExponentialScaler::setTemperatureFunction_r(const scalarFunction& Tfunc){
+  if (_temFunc_r != NULL) delete _temFunc_r;
+  _temFunc_r = Tfunc.clone();
+}
+
+void positiveExponentialScaler::setTemperatureFunction_m(const scalarFunction& Tfunc){
+  if (_temFunc_m != NULL) delete _temFunc_m;
+  _temFunc_m = Tfunc.clone();
+}
+
+void positiveExponentialScaler::createIPVariable(IPMullinsEffect* &ipv) const
+{
+  if(ipv != NULL) delete ipv;
+  ipv = new IPMullinsEffect();
+}
+
+void positiveExponentialScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const{
+    
+  // 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 _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 = (_m*(1.-eta*psi_cap/_psi_max));  // 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*exp(Term)*psi_cap/_psi_max;
+      Deta = - f/DfDeta;
+      
+      if (eta + Deta > 1.){
+          eta = 0.99;                // NR
+        }
+        else
+          eta += Deta;
+          
+      Msg::Error(" Inside iterator: ite = %d, f = %e, DfDeta = %e, Deta = %e, eta = %e !!", ite, f, DfDeta, Deta, eta);
+  
+      Term = (_m*(1.-eta*psi_cap/_psi_max));  
+      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;
+      }
+    }
+    
+    // eta = 1+_r*(1-exp(_m*(1 - psi_cap/_psi_max)));
+    
+    Dpsi_maxDpsi_cap = 0.;
+    
+    // DetaDpsi_cap = ;
+  }
+  else{
+    eta = 1.; 
+    DetaDpsi_cap = 0.;
+  }
+
+  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT);
+  ipv.setPsiMax(_psi_max);
+}
+
+void positiveExponentialScaler::mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const{
+   
+  double r = _r*_temFunc_r->getVal(T);
+  double m = _m*_temFunc_m->getVal(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 _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;
+          
+      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;
+      }
+    }
+    // eta = 1+_r*(1-exp(_m*(1 - psi_cap/_psi_max)));
+    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.;
+  }
+  
+  ipv.set(eta,DetaDpsi_cap,DDetaDpsipsi,DetaDT,DDetaDTT);
+  ipv.setPsiMax(_psi_max);
+}
+
+mullinsEffect *positiveExponentialScaler::clone() const
+{
+  return new positiveExponentialScaler(*this);
+}
+
+// #############
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/mullinsEffect.h b/NonLinearSolver/materialLaw/mullinsEffect.h
new file mode 100644
index 0000000000000000000000000000000000000000..6ff7b654ce864354742f0bf5db9119f5abf5e29f
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mullinsEffect.h
@@ -0,0 +1,148 @@
+//
+// Description: Define mullins effect for softening in polymers in (pseudo-)hyperelastic regime 
+//
+//
+// Author:  <Ujwal Kishore J.>, (C) 2023
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MULLINSEFFECT_H_
+#define MULLINSEFFECT_H_
+
+#include "ipMullinsEffect.h"
+#include "fullMatrix.h"
+#include "scalarFunction.h"
+
+class mullinsEffect {
+  public:
+    enum scalingFunction{negativeExponentialScaler,linearScaler,positiveExponentialScaler};
+
+  protected:
+    int _num; // number of law (must be unique !)
+    bool _initialized; // to initialize law
+
+  public:
+  #ifndef SWIG
+    mullinsEffect(const int num, const bool init=true);
+    virtual ~mullinsEffect(){}
+    mullinsEffect(const mullinsEffect &source);
+    virtual mullinsEffect& operator=(const mullinsEffect &source);
+    virtual int getNum() const{return _num;}
+    virtual scalingFunction getType() const=0;
+    virtual void createIPVariable(IPMullinsEffect* &ipv) const=0;
+    virtual void initLaws(const std::map<int,mullinsEffect*> &maplaw)=0;
+    virtual const bool isInitialized() {return _initialized;}
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const=0;
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const=0;
+    virtual mullinsEffect * clone() const=0;
+  #endif
+
+};
+
+// eta = 1 - r* ( 1 - exp(-sqrt(m*(psi_max-psi))) ) -> Ricker et al, 2021 (modified Zuniga, 2005)
+class negativeExponentialScaler : public mullinsEffect{
+  #ifndef SWIG
+  protected:
+    double _r; 
+    double _m; 
+    scalarFunction* _temFunc_r;
+    scalarFunction* _temFunc_m;
+  #endif // SWIG
+
+  public:
+    negativeExponentialScaler(const int num, double r, double m, bool init = true);
+    void setTemperatureFunction_r(const scalarFunction& Tfunc);
+    void setTemperatureFunction_m(const scalarFunction& Tfunc);
+    #ifndef SWIG
+    virtual ~negativeExponentialScaler();
+    negativeExponentialScaler(const negativeExponentialScaler& src);
+    virtual negativeExponentialScaler& operator =(const mullinsEffect& src);
+    virtual scalingFunction getType() const{return mullinsEffect::negativeExponentialScaler; };
+    virtual void createIPVariable(IPMullinsEffect* &ipv) const;
+    virtual void initLaws(const std::map<int,mullinsEffect*> &maplaw) {}; //nothing now, we will see if we use the mapping
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const;
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const;
+    virtual mullinsEffect * clone() const;
+    #endif // SWIG
+};
+
+// eta = 1 - r* ( 1 - psi/psi_max ) -> linear
+class linearScaler : public mullinsEffect{
+  #ifndef SWIG
+  protected:
+    double _r; 
+    scalarFunction* _temFunc_r;
+  #endif // SWIG
+
+  public:
+    linearScaler(const int num, double r, bool init = true);
+    void setTemperatureFunction_r(const scalarFunction& Tfunc);
+    #ifndef SWIG
+    virtual ~linearScaler();
+    linearScaler(const linearScaler& src);
+    virtual linearScaler& operator =(const mullinsEffect& src);
+    virtual scalingFunction getType() const{return mullinsEffect::linearScaler; };
+    virtual void createIPVariable(IPMullinsEffect* &ipv) const;
+    virtual void initLaws(const std::map<int,mullinsEffect*> &maplaw) {}; //nothing now, we will see if we use the mapping
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const;
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const;
+    virtual mullinsEffect * clone() const;
+    #endif // SWIG
+};
+
+// eta = 1 + r* ( 1 - exp((m*(1-psi/psi_max))) ) 
+class positiveExponentialScaler : public mullinsEffect{
+  #ifndef SWIG
+  protected:
+    double _r; 
+    double _m; 
+    scalarFunction* _temFunc_r;
+    scalarFunction* _temFunc_m;
+  #endif // SWIG
+
+  public:
+    positiveExponentialScaler(const int num, double r, double m, bool init = true);
+    void setTemperatureFunction_r(const scalarFunction& Tfunc);
+    void setTemperatureFunction_m(const scalarFunction& Tfunc);
+    #ifndef SWIG
+    virtual ~positiveExponentialScaler();
+    positiveExponentialScaler(const positiveExponentialScaler& src);
+    virtual positiveExponentialScaler& operator =(const mullinsEffect& src);
+    virtual scalingFunction getType() const{return mullinsEffect::positiveExponentialScaler; };
+    virtual void createIPVariable(IPMullinsEffect* &ipv) const;
+    virtual void initLaws(const std::map<int,mullinsEffect*> &maplaw) {}; //nothing now, we will see if we use the mapping
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const;
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const;
+    virtual mullinsEffect * clone() const;
+    #endif // SWIG
+};
+/*
+// eta = 1 + r* ( 1 - exp((m*(1-psi))) ) 
+class arbitraryScaler : public mullinsEffect{
+  #ifndef SWIG
+  protected:
+    double _r; 
+    double _m; 
+    scalarFunction* _temFunc_r;
+    scalarFunction* _temFunc_m;
+  #endif // SWIG
+
+  public:
+    positiveExponentialScaler(const int num, double r, double m, bool init = true);
+    void setTemperatureFunction_r(const scalarFunction& Tfunc);
+    void setTemperatureFunction_m(const scalarFunction& Tfunc);
+    #ifndef SWIG
+    virtual ~positiveExponentialScaler();
+    positiveExponentialScaler(const positiveExponentialScaler& src);
+    virtual positiveExponentialScaler& operator =(const mullinsEffect& src);
+    virtual scalingFunction getType() const{return mullinsEffect::positiveExponentialScaler; };
+    virtual void createIPVariable(IPMullinsEffect* &ipv) const;
+    virtual void initLaws(const std::map<int,mullinsEffect*> &maplaw) {}; //nothing now, we will see if we use the mapping
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv) const;
+    virtual void mullinsEffectScaling(double _psi0, double _psi, const IPMullinsEffect &ipvprev, IPMullinsEffect &ipv, const double T) const;
+    virtual mullinsEffect * clone() const;
+    #endif // SWIG
+};*/
+
+#endif // MULLINSEFFECT_H_
diff --git a/NonLinearSolver/materialLaw/viscosityLaw.cpp b/NonLinearSolver/materialLaw/viscosityLaw.cpp
index bc7aa3c5aafd3d89a3c65a48a8e177ed3a468348..7b94b7413cf96da803d38ab64b52df9811f04995 100644
--- a/NonLinearSolver/materialLaw/viscosityLaw.cpp
+++ b/NonLinearSolver/materialLaw/viscosityLaw.cpp
@@ -73,6 +73,14 @@ void constantViscosityLaw::get(const double p, const double T, double& R, double
     ddRdTT = _eta0*_temFunc->getDoubleDiff(T);    
 };
 
+void constantViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const {
+    R = _eta0*_temFunc->getVal(T);
+    dR = 0.;
+    dRdT = _eta0*_temFunc->getDiff(T);    
+    ddRdTT = _eta0*_temFunc->getDoubleDiff(T);    
+    ddRdT = 0.;
+};
+
 saturatePowerViscosityLaw::saturatePowerViscosityLaw(const int num, const double eta0, const double q, const bool init):
                 viscosityLaw(num,init), _eta0(eta0), _q(q){
                 _temFunc_eta0 = new constantScalarFunction(1.);
@@ -197,6 +205,37 @@ void saturatePowerViscosityLaw::get(const double p, const double T, double& R, d
   
 };
 
+void saturatePowerViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const{
+  
+  double eta = _eta0*_temFunc_eta0->getVal(T);
+  double DetaDT = _eta0*_temFunc_eta0->getDiff(T);
+  double DDetaDTT = _eta0*_temFunc_eta0->getDoubleDiff(T);
+  double q = _q*_temFunc_q->getVal(T);
+  double DqDT = _q*_temFunc_q->getDiff(T);
+  double DDqDTT = _q*_temFunc_q->getDoubleDiff(T);
+  
+  R = eta * pow(p,q);
+  if(p <1.e-6 and q < 1.)
+  {
+    R =  eta * pow(1.e-6,q)*(p/1.e-6); 
+    dR = eta * pow(1.e-6,q)   /1.e-6;
+    dRdT = DetaDT * pow(1.e-6,q)*(p/1.e-6) + eta * pow(1.e-6,_q)*(p/1.e-6)*DqDT*log(1.e-6);
+    ddRdTT = DDetaDTT * pow(1.e-6,q)*(p/1.e-6) + 2*DetaDT * pow(1.e-6,_q)*(p/1.e-6)*DqDT*log(1.e-6)
+            + eta*(p/1.e-6)*pow(1.e-6,_q)*(pow(log(1.e-6)*DqDT,2) + log(1.e-6)*DDqDTT);
+    ddRdT = DetaDT * pow(1.e-6,q)   /1.e-6;
+  }
+  else
+  {
+    R = eta * pow(p,q);
+    dR = eta * pow(p,q-1.) * q;
+    dRdT = DetaDT * pow(p,q) + eta *pow(p,_q)*DqDT*log(p);
+    ddRdTT = DDetaDTT * pow(p,q) + 2*DetaDT*pow(p,_q)*DqDT*log(p)
+            + eta*pow(p,_q)*(pow(log(p)*DqDT,2) + log(p)*DDqDTT);
+    ddRdT = DetaDT * pow(p,q-1.) * q + eta * (DqDT*pow(p,q-1.) + q*pow(p,q-1.)*DqDT*log(p));
+  }
+  
+};
+
 saturateSinhViscosityLaw::saturateSinhViscosityLaw(const int num, const double eta0, const double eta1, const double g0, const bool init):
                 viscosityLaw(num,init),_eta0(eta0),_eta1(eta1),_g0(g0){
             _temFunc_eta0 = new constantScalarFunction(1.);
@@ -318,4 +357,22 @@ void saturateSinhViscosityLaw::get(const double p, const double T, double& R, do
     dRdT = 0.; // correct it yourselves
     ddRdTT = 0.; // correct it yourselves
   }
+};
+void saturateSinhViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const{
+  double pa = p/_g0;
+  if (pa< 1e-6){
+    R = _eta0;
+    dR = 0.;
+    dRdT = 0.; // correct it by yourselves
+    ddRdTT = 0.; // correct it by yourselves
+    ddRdT = 0.; // correct it by yourselves
+  }
+  else
+  {
+    R = _eta1 + (_eta0-_eta1)*pa/sinh(pa);
+    dR = (_eta0-_eta1)*(1./sinh(pa) - (pa*cosh(pa))/(sinh(pa)*sinh(pa)))/_g0 ;
+    dRdT = 0.; // correct it yourselves
+    ddRdTT = 0.; // correct it yourselves
+    ddRdT = 0.; // correct it yourselves
+  }
 };
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/viscosityLaw.h b/NonLinearSolver/materialLaw/viscosityLaw.h
index 3ba88cc9eba7795565a0bb721ad9492c0d1bfc59..977081ee6e5416ebd686684dfe235bab0dcbc245 100644
--- a/NonLinearSolver/materialLaw/viscosityLaw.h
+++ b/NonLinearSolver/materialLaw/viscosityLaw.h
@@ -29,6 +29,7 @@ class viscosityLaw {
     virtual void get(const double p, double& R, double& dR) const = 0;
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT) const = 0;
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) const = 0;
+    virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const = 0;
     virtual viscosityLaw* clone() const = 0;
   #endif // SWIG
 };
@@ -48,6 +49,7 @@ class constantViscosityLaw : public viscosityLaw{
     virtual void get(const double p, double& R, double& dR) const{R = _eta0; dR = 0.;};
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT) const; 
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) const; 
+    virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const; 
     virtual viscosityLaw* clone() const {return new constantViscosityLaw(*this);};
     #endif // SWIG
 };
@@ -70,6 +72,7 @@ class saturatePowerViscosityLaw : public viscosityLaw{
     virtual void get(const double p, double& R, double& dR) const;
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT) const; 
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) const; 
+    virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const; 
     virtual viscosityLaw* clone() const {return new saturatePowerViscosityLaw(*this);};
     #endif // SWIG
 };
@@ -97,6 +100,7 @@ class saturateSinhViscosityLaw : public viscosityLaw{
     virtual void get(const double p, double& R, double& dR) const;
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT) const; 
     virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) const; 
+    virtual void get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT, double& ddRdT) const; 
     virtual viscosityLaw* clone() const {return new saturateSinhViscosityLaw(*this);};
     #endif // SWIG
 };
diff --git a/NonLinearSolver/nlmechsolpy.i b/NonLinearSolver/nlmechsolpy.i
index 4370ab66e1fde7031bca507a0c3a56c700ec79e8..99fca14ad7f8e591b61bd716a4917a90fcd0bb26 100644
--- a/NonLinearSolver/nlmechsolpy.i
+++ b/NonLinearSolver/nlmechsolpy.i
@@ -15,6 +15,7 @@
   #include "j2IsotropicHardening.h"
   #include "kinematicHardening.h"
   #include "viscosityLaw.h"
+  #include "mullinsEffect.h"
   #include "CLengthLaw.h"
   #include "NucleationLaw.h"
   #include "nucleationCriterionLaw.h"
@@ -84,6 +85,7 @@
 %nodefaultctor J2IsotropicHardening;
 %nodefaultctor kinematicHardening;
 %nodefaultctor viscosityLaw;
+%nodefaultctor mullinsEffect;
 %nodefaultctor RateFailureLaw;
 %nodefaultctor CLengthLaw;
 %nodefaultctor DamageLaw;
@@ -164,6 +166,7 @@
 %include "j2IsotropicHardening.h"
 %include "kinematicHardening.h"
 %include "viscosityLaw.h"
+%include "mullinsEffect.h"
 %include "CLengthLaw.h"
 %include "NucleationLaw.h"
 %include "nucleationCriterionLaw.h"
diff --git a/NonLinearSolver/nlsolver/scalarFunction.h b/NonLinearSolver/nlsolver/scalarFunction.h
index 94ee94541c0d4f5afee402805e59385f04056510..036483209c26c0123296cca7a4cef03806d3b329 100644
--- a/NonLinearSolver/nlsolver/scalarFunction.h
+++ b/NonLinearSolver/nlsolver/scalarFunction.h
@@ -574,6 +574,38 @@ class negExpWLFshiftFactor : public scalarFunction
     #endif // SWIG
 };
 
+// function y = exp(- C(x-Tref) ) 
+class negativeExponentialFunction : public scalarFunction
+{
+  protected:
+    double _C, _Tref;
+    
+  public:
+    negativeExponentialFunction(double C, double Tref) : scalarFunction(),_C(C),_Tref(Tref){}
+    #ifndef SWIG
+    negativeExponentialFunction(const negativeExponentialFunction& src) : _C(src._C),_Tref(src._Tref){}
+    virtual negativeExponentialFunction& operator = (const scalarFunction& src){
+      scalarFunction::operator=(src);
+      const negativeExponentialFunction* psrc = dynamic_cast<const negativeExponentialFunction*>(&src);
+      if (psrc!= NULL){
+        _C = psrc->_C;
+        _Tref = psrc->_Tref;
+      }
+      return *this;
+    }
+    virtual ~negativeExponentialFunction(){};
+    virtual double getVal(const double x) const {
+      return exp(-_C*(x-_Tref));
+    };
+    virtual double getDiff(const double x) const {
+      return (-_C*exp(-_C*(x-_Tref)));
+    };
+    virtual double getDoubleDiff(const double x) const {
+      return (pow(_C,2)*exp(-_C*(x-_Tref)));
+    };
+    virtual scalarFunction* clone() const {return new negativeExponentialFunction(*this);};
+    #endif // SWIG
+};
 
 
 #endif // SCALARFUNCTION_H_
diff --git a/NonLinearSolver/nlsolver/timeFunction.h b/NonLinearSolver/nlsolver/timeFunction.h
index 7c72ae9ce19abe20603c34b45b95b081e7f83665..112852d63ce00aa8da6c4803230874fab397ee1d 100644
--- a/NonLinearSolver/nlsolver/timeFunction.h
+++ b/NonLinearSolver/nlsolver/timeFunction.h
@@ -62,6 +62,24 @@ class sinusoidalFunctionTime : public simpleFunctionTime<double>{
     };
     #endif // SWIG
 };
+
+//f = Asin(wt+phi)
+class sinusoidalwithPhaseAngleFunctionTime : public simpleFunctionTime<double>{
+  protected:
+    double _A;
+    double _w;
+    double _phi;
+
+  public:
+    sinusoidalwithPhaseAngleFunctionTime(const double A, const double w, const double phi):simpleFunctionTime<double>(),_A(A),_w(w),_phi(phi){};
+    #ifndef SWIG
+    virtual ~sinusoidalwithPhaseAngleFunctionTime(){};
+    virtual double operator () (double x, double y, double z) const{
+      return _A*sin(_w*time+_phi);
+    };
+    #endif // SWIG
+};
+
 //f = A(1-cos(wt))
 class cosinusoidalFunctionTime : public simpleFunctionTime<double>{
   protected:
diff --git a/dG3D/README.txt b/dG3D/README.txt
index 89b4b36521a5927217786a965b6bfec0dd31e804..be574cf38c9132b1c0fc1b8e0e254b5f1345eb7d 100644
--- a/dG3D/README.txt
+++ b/dG3D/README.txt
@@ -44,9 +44,9 @@ git clone https://username@gitlab.onelab.info/cm3/cm3Libraries.git cm3Libraries
 cd $CM3_DIR/cm3Libraries/dG3D && mkdir release && cd release
 
 # configuring
-cmake -DCMAKE_BUILD_TYPE=Release \  (ccmake ..)
+cmake -DCMAKE_BUILD_TYPE=Release \
 -DENABLE_MPI=ON \
--DENABLE_FLTK=OFF \
+-DENABLE_FLTK=ON \
 -DENABLE_EIGEN=OFF \
 -DENABLE_BLAS_LAPACK=ON \
 -DENABLE_PETSC=ON \
@@ -55,6 +55,8 @@ cmake -DCMAKE_BUILD_TYPE=Release \  (ccmake ..)
 -DPETSC_DIR=$PETSC_DIR \
 -DPETSC_ARCH=$PETSC_ARCH ..
 
+otherwise use "ccmake .." and configure manually
+
 # if there are conflicts with python library, include directory
 # python include dir and library must be found
 export PYTHON_INCLUDE_DIR=path-to-python-include
diff --git a/dG3D/benchmarks/nonLinearTVE_uniaxial/runTVE.py b/dG3D/benchmarks/nonLinearTVE_uniaxial/runTVE.py
index 7f23125ba483929747a12350dcb24d4bfcb6aef1..5f68be1b5651b1380a1151508ddfdb1d1b8a390a 100644
--- a/dG3D/benchmarks/nonLinearTVE_uniaxial/runTVE.py
+++ b/dG3D/benchmarks/nonLinearTVE_uniaxial/runTVE.py
@@ -2,7 +2,7 @@
 
 from gmshpy import *
 from dG3Dpy import*
-#from dG3DpyDebug import*
+# from dG3DpyDebug import*
 from math import*
 import csv
 import numpy as np
@@ -71,6 +71,7 @@ law1.setTestOption(3)
 law1.setShiftFactorConstantsWLF(C1,C2)
 law1.setReferenceTemperature(Tref)
 law1.setTempFuncOption(0)
+
 law1.setViscoElasticNumberOfElement(N)
 if N > 0:
     for i in range(1, N+1):
@@ -78,7 +79,7 @@ if N > 0:
 
 law1.setTemperatureFunction_ThermalDilationCoefficient(Alpha_tempfunc)
 law1.setTemperatureFunction_ThermalConductivity(KThCon_tempfunc)
-law1.setTemperatureFunction_SpecificHeat(Cp_tempfunc)
+# law1.setTemperatureFunction_SpecificHeat(Cp_tempfunc)
 
 # geometry
 geofile = "line.geo"
@@ -159,7 +160,7 @@ else:
 # mysolver.displacementBC("Node",2,0,7e-2*L)
 mysolver.initialBC("Volume","Position",11,3,Tinitial)
 fT = LinearFunctionTime(0,Tinitial,ftime,Tinitial);    # Linear Displacement with time
-# mysolver.displacementBC("Volume",11,3,fT)
+mysolver.displacementBC("Volume",11,3,fT)
 
 """
 mysolver.internalPointBuildView("P_xx",IPField.P_XX, 1, 1)
diff --git a/dG3D/benchmarks/nonLinearTVP_cube/cubeTVP.py b/dG3D/benchmarks/nonLinearTVP_cube/cubeTVP.py
index d08bc850856e0655378442db67e8a6bd97189f23..c20fae26819beec7b17fe0069c9de5cb11e84eeb 100644
--- a/dG3D/benchmarks/nonLinearTVP_cube/cubeTVP.py
+++ b/dG3D/benchmarks/nonLinearTVP_cube/cubeTVP.py
@@ -26,16 +26,16 @@ relSpec[0:N+1] *= 1e-6    # convert to MPa
 # material law
 lawnum = 11 # unique number of law
 
-E = relSpec[0] #MPa
-nu = 0.3 #0.33
+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 = 7850e-9 #905e-12 # Bulk mass   905 kg/m3 -> 905e-12 tonne/mm3
+rho = 7850e-12 #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 + 70 # K
+Tinitial = 273.15 + 20 # K
 C1 = 136.17201827
 C2 = 256.58268053 # K
 
@@ -55,30 +55,46 @@ KThCon_R = 1.5*0.12
 k_gibson = 3.36435338e-02
 m_gibson = 0.0
 Tg = Tref
-E_tempfunc = GlassTransitionScalarFunction(1, E_R/E_G, Tg, k_gibson, m_gibson, 0)  # can't be used
 Alpha_tempfunc = GlassTransitionScalarFunction(1, Alpha_R/Alpha_G, Tg, k_gibson, m_gibson, 0)
 Cp_tempfunc = GlassTransitionScalarFunction(1, Cp_R/Cp_G, Tg, k_gibson, m_gibson, 0)
 KThCon_tempfunc = GlassTransitionScalarFunction(1, KThCon_R/KThCon_G, Tg, k_gibson, m_gibson, 0)
 ShiftFactor_tempfunc = negExpWLFshiftFactor(C1,C2,Tref)
 
-sy0c = 10. #MPa
-hc = 300.
+C = 0.0228422
+# sy0c = 6.02534075/0.78
+negExp_tempfunc = negativeExponentialFunction(C,Tref)
 
-sy0t = sy0c*0.78
-ht = 300.
+a = -0.9/(90.)
+x0 = 273.15-20
+linear_tempfunc = linearScalarFunction(x0,0.9,a)
 
-hardenc = LinearExponentialJ2IsotropicHardening(1, sy0c, hc, 0., 10.)
-hardent = LinearExponentialJ2IsotropicHardening(2, sy0t, ht, 0., 10.)
+sy0c = 5.75/0.78 #MPa
+hc = 30.
+sy0t = sy0c*0.78
+ht = 30.
+
+hardenc = LinearExponentialJ2IsotropicHardening(1, sy0c, hc, 48., 200)
+hardent = LinearExponentialJ2IsotropicHardening(2, sy0t, ht, 48., 200)
+hardenc.setTemperatureFunction_h1(negExp_tempfunc)
+hardenc.setTemperatureFunction_h2(negExp_tempfunc)
+# hardenc.setTemperatureFunction_hexp(ShiftFactor_tempfunc)
+hardent.setTemperatureFunction_h1(negExp_tempfunc)
+hardent.setTemperatureFunction_h2(negExp_tempfunc)
+# hardent.setTemperatureFunction_hexp(ShiftFactor_tempfunc)
+
+# hardenk = exponentialKinematicHardeningLaw(3,10000,100,1000)
 hardenk = PolynomialKinematicHardening(3,1)
-hardenk.setCoefficients(1,370)
+hardenk.setCoefficients(1,370.)
+hardenk.setCoefficients(2,200.)
+# hardenk.setTemperatureFunction_K(negExp_tempfunc)
 
-law1 = NonLinearTVPDG3DMaterialLaw(lawnum,rho,E,nu,1e-6,Tinitial,Alpha,KThCon,Cp) # ,True,1e-8)
+# law1 = NonLinearTVEDG3DMaterialLaw(lawnum,rho,E,nu,Tinitial,Alpha,KThCon,Cp)
+law1 = NonLinearTVPDG3DMaterialLaw(lawnum,rho,E,nu,1e-6,Tinitial,Alpha,KThCon,Cp) #,True,1e-8)
 
 law1.setCompressionHardening(hardenc)
 law1.setTractionHardening(hardent)
 law1.setKinematicHardening(hardenk)
 
-
 law1.setStrainOrder(11)
 
 law1.setYieldPowerFactor(3.5)
@@ -91,24 +107,27 @@ law1.setShiftFactorConstantsWLF(C1,C2)
 law1.setReferenceTemperature(Tref)
 law1.setTempFuncOption(0)
 
+
 law1.setViscoElasticNumberOfElement(N)
 if N > 0:
     for i in range(1, N+1):
         law1.setViscoElasticData(i, relSpec[i], relSpec[i+N])
 
+
 law1.setTemperatureFunction_ThermalDilationCoefficient(Alpha_tempfunc)
 law1.setTemperatureFunction_ThermalConductivity(KThCon_tempfunc)
-law1.setTemperatureFunction_SpecificHeat(Cp_tempfunc)
+# law1.setTemperatureFunction_SpecificHeat(Cp_tempfunc)
 
 eta = constantViscosityLaw(1,3e4) #(1,3e4)
-law1.setViscosityEffect(eta,0.15) # 0.21)
+law1.setViscosityEffect(eta,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)
+nstep = 1000   # number of step (used only if soltype=1)
 ftime = 1   # 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)
@@ -122,7 +141,8 @@ geofile = "cube.geo" # "line.geo"
 meshfile = "cube.msh" # "line.msh"
 nfield = 29
 
-pertLaw1 = dG3DMaterialLawWithTangentByPerturbation(law1,1e-8*(Tinitial)) # use with _pert*T0 (b/c In tangent_by_perturbation_TVP u use _pert*T0)
+pertFactor = 1e-8 #*Tinitial
+pertLaw1 = dG3DMaterialLawWithTangentByPerturbation(law1,pertFactor) # use with _pert*T0 (b/c In tangent_by_perturbation_TVP u use _pert*T0)
 ThermoMechanicsEqRatio = 1.e1 # setConstitutiveExtraDofDiffusionEqRatio(ThermoMechanicsEqRatio); WHAT is this parameter?
 thermalSource = True
 mecaSource = True
@@ -130,11 +150,12 @@ myfield1 = ThermoMechanicsDG3DDomain(1000,nfield,space1,lawnum,fullDg,ThermoMech
 myfield1.setConstitutiveExtraDofDiffusionAccountSource(thermalSource,mecaSource)
 myfield1.stabilityParameters(beta1)
 myfield1.ThermoMechanicsStabilityParameters(beta1,bool(1))    # Added
+# myfield1 = dG3D1DDomain(11,11,space1,lawnum, False) #for non local
 
 
 # creation of Solver
 mysolver = nonLinearMechSolver(1000)
-mysolver.createModel(geofile,meshfile,3,1)
+mysolver.createModel(geofile,meshfile,3,2)
 mysolver.loadModel(meshfile)
 mysolver.addDomain(myfield1)
 mysolver.addMaterialLaw(law1)
@@ -145,42 +166,36 @@ mysolver.snlData(nstep,ftime,tol)
 mysolver.stepBetweenArchiving(nstepArch)
 
 # BCs
-umax = 0.001
+umax = 0.1e-2
 fu_L = LinearFunctionTime(0,0,ftime,umax);    # Linear Displacement with time
-fu_L_2 = LinearFunctionTime(0,0,ftime,2*umax);
-fu_L_3 = LinearFunctionTime(0,0,ftime,0.6*umax);
-mysolver.displacementBC("Face",30,0,0.)		  # face x = 0   - Left Face fixed
-mysolver.displacementBC("Face",31,0,fu_L)     # face x = L   - Right Face displaced - compression direction
-mysolver.displacementBC("Face",31,1,fu_L_2)
-mysolver.displacementBC("Face",31,1,fu_L_3)
-mysolver.displacementBC("Face",34,1,0.)		  # face y = 0
-mysolver.displacementBC("Face",32,2,0.)		  # face z = 0
+mysolver.displacementBC("Face",30,0,0.)		        # face x = 0   - Left Face fixed
+mysolver.displacementBC("Face",31,0,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)
-qmax = 0 #5.19e5                                # Heat Flux in kN(ms)⁻¹(mm)⁻¹  [5.19e-1 W/m²]
+qmax = 1e+1 #5.19e5                                # Heat Flux in kN(ms)⁻¹(mm)⁻¹  [5.19e-1 W/m²]
 fq_L = LinearFunctionTime(0,0,ftime,qmax);    # Linear Flux with time
 # mysolver.scalarFluxBC("Face",31,3,fq_L)
-fT = LinearFunctionTime(0,Tinitial,ftime,70+Tinitial);    # Linear Displacement with time
-# fT = LinearFunctionTime(0,Tinitial,ftime,Tinitial);    # Linear Displacement with time
-mysolver.displacementBC("Volume",nfield,3,fT)
+# fT = LinearFunctionTime(0,Tinitial,ftime,70+Tinitial);    # Linear Displacement with time
+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, 1);
-mysolver.internalPointBuildView("svm",IPField.SVM, 1, 1)
-mysolver.internalPointBuildView("sig_xx",IPField.SIG_XX, 1, 1)
-mysolver.internalPointBuildView("sig_yy",IPField.SIG_YY, 1, 1)
-mysolver.internalPointBuildView("sig_zz",IPField.SIG_ZZ, 1, 1)
-mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1)
-mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1)
-mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1)
-mysolver.internalPointBuildView("epl",IPField.PLASTICSTRAIN, 1, 1)
-mysolver.internalPointBuildView("temperature",IPField.TEMPERATURE, 1, 1)
-mysolver.internalPointBuildView("qx",IPField.THERMALFLUX_X, 1, 1)
-mysolver.internalPointBuildView("qy",IPField.THERMALFLUX_Y, 1, 1)
-mysolver.internalPointBuildView("qz",IPField.THERMALFLUX_Z, 1, 1)
+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("epl",IPField.PLASTICSTRAIN, 1, nstepArch)
+mysolver.internalPointBuildView("temperature",IPField.TEMPERATURE, 1, nstepArch)
+mysolver.internalPointBuildView("qx",IPField.THERMALFLUX_X, 1, nstepArch)
+mysolver.internalPointBuildView("qy",IPField.THERMALFLUX_Y, 1, nstepArch)
+mysolver.internalPointBuildView("qz",IPField.THERMALFLUX_Z, 1, nstepArch)
 
 
 # Print/Archive History Outputs
diff --git a/dG3D/benchmarks/nonLinearTVP_uniaxial/runTVP.py b/dG3D/benchmarks/nonLinearTVP_uniaxial/runTVP.py
index 9d739b6f2310d7c14911c6bbb8e6302f56f145d2..67b08e6cb70004201861a73d0dad108e515341fb 100644
--- a/dG3D/benchmarks/nonLinearTVP_uniaxial/runTVP.py
+++ b/dG3D/benchmarks/nonLinearTVP_uniaxial/runTVP.py
@@ -245,4 +245,4 @@ mysolver.archivingAverageValue(IPField.F_XX)
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-3.089706e+01,mysolver.getArchivedForceOnPhysicalGroup("Node", 1, 0),1.e-4)
+check.equal(-3.093203e+01,mysolver.getArchivedForceOnPhysicalGroup("Node", 1, 0),1.e-4)
diff --git a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
index 235e187dae9ecefbd17d88bfec3a716d21e51a8a..be503f1fb1a242c7d61ce258ba3ce1f025ad52d3 100644
--- a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
+++ b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
@@ -2,6 +2,7 @@
 
 from gmshpy import *
 from dG3Dpy import*
+# from dG3DpyDebug import*
 from math import*
 
 #script to launch PBC problem with a python script
@@ -95,7 +96,7 @@ mysolver.displacementBC('Face',4,0,0.)
 
 mysolver.displacementBC('Face',1,0,0)
 mysolver.displacementBC('Face',1,1,0)
-mysolver.displacementBC('Face',2,2,1.)
+mysolver.displacementBC('Face',2,2,10.)
 
 # build view
 mysolver.internalPointBuildView("Strain_xx",IPField.STRAIN_XX, 1, 1);
diff --git a/dG3D/src/dG3DIPVariable.cpp b/dG3D/src/dG3DIPVariable.cpp
index e70aeb7737e9a65502beffa03e1032a7e09d5342..9bb8fff93510130c1ef56e3152685b1d852d9223 100644
--- a/dG3D/src/dG3DIPVariable.cpp
+++ b/dG3D/src/dG3DIPVariable.cpp
@@ -2359,6 +2359,8 @@ double HyperViscoElasticdG3DIPVariable::get(const int i) const
   {
     return _ipViscoElastic->_Ee(2,2);
   }
+  else if (i == IPField::hyperElastic_BulkScalar){return _ipViscoElastic->getConstRefToElasticBulkPropertyScaleFactor();}
+  else if (i == IPField::hyperElastic_ShearScalar){return _ipViscoElastic->getConstRefToElasticShearPropertyScaleFactor();}
   else if (i == IPField::Eve1_XX)
   {
     if (_ipViscoElastic->_A.size() > 0)
@@ -2432,6 +2434,30 @@ double HyperViscoElasticdG3DIPVariable::get(const int i) const
       return _ipViscoElastic->_A[1](2,2) + _ipViscoElastic->_B[1]/3.;
     else return 0.;
   }
+  else if (i == IPField::corKir_XX)
+  {
+    return _ipViscoElastic->_kirchhoff(0,0);
+  }
+  else if (i == IPField::corKir_XY)
+  {
+    return _ipViscoElastic->_kirchhoff(0,1);
+  }
+  else if (i == IPField::corKir_XZ)
+  {
+    return _ipViscoElastic->_kirchhoff(0,2);
+  }
+  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
   {
     return dG3DIPVariable::get(i);
@@ -2508,6 +2534,8 @@ double HyperViscoElastoPlasticdG3DIPVariable::get(const int comp) const
   {
     return _ipViscoElastoPlastic->_Ee(2,2);
   }
+  else if (comp == IPField::hyperElastic_BulkScalar){return _ipViscoElastoPlastic->getConstRefToElasticBulkPropertyScaleFactor();}
+  else if (comp == IPField::hyperElastic_ShearScalar){return _ipViscoElastoPlastic->getConstRefToElasticShearPropertyScaleFactor();}
   else if (comp == IPField::Eve1_XX)
   {
     if (_ipViscoElastoPlastic->_A.size() >0)
@@ -2580,6 +2608,30 @@ double HyperViscoElastoPlasticdG3DIPVariable::get(const int comp) const
       return _ipViscoElastoPlastic->_A[1](2,2) + _ipViscoElastoPlastic->_B[1]/3.;
     else return 0.;
   }
+  else if (comp == IPField::corKir_XX)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(0,0);
+  }
+  else if (comp == IPField::corKir_XY)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(0,1);
+  }
+  else if (comp == IPField::corKir_XZ)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(0,2);
+  }
+  else if (comp == IPField::corKir_YY)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(1,1);
+  }
+  else if (comp == IPField::corKir_YZ)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(1,2);
+  }
+  else if (comp == IPField::corKir_ZZ)
+  {
+    return _ipViscoElastoPlastic->_kirchhoff(2,2);
+  }
   else if(comp == IPField::PLASTICSTRAIN)
   {
     return _ipViscoElastoPlastic->getConstRefToEqPlasticStrain();
@@ -5672,7 +5724,8 @@ NonLinearTVEDG3DIPVariable::NonLinearTVEDG3DIPVariable(const mlawNonLinearTVE& v
   _ipViscoElastic = new IPNonLinearTVE(viscoLaw.getConstRefToCompressionHardening(),
                                        viscoLaw.getConstRefToTractionHardening(),
                                        viscoLaw.getConstRefToKinematicHardening(),
-                                       viscoLaw.getViscoElasticNumberOfElement());
+                                       viscoLaw.getViscoElasticNumberOfElement(),
+                                       viscoLaw.getConstRefToMullinsEffect());
   this->getRefToTemperature()=Tinitial;
 };
 
@@ -5741,6 +5794,27 @@ double NonLinearTVEDG3DIPVariable::get(const int i) const{
   else if (i == IPField::Ee_YY){return _ipViscoElastic->_Ee(1,1);}
   else if (i == IPField::Ee_YZ){return _ipViscoElastic->_Ee(1,2);}
   else if (i == IPField::Ee_ZZ){return _ipViscoElastic->_Ee(2,2);}
+  else if (i == IPField::corKir_XX){return _ipViscoElastic->_kirchhoff(0,0);}
+  else if (i == IPField::corKir_XY){return _ipViscoElastic->_kirchhoff(0,1);}
+  else if (i == IPField::corKir_XZ){return _ipViscoElastic->_kirchhoff(0,2);}
+  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::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);}
+  else if (i == IPField::corKirExtra_XY){return _ipViscoElastic->_corKirExtra(0,1);}
+  else if (i == IPField::corKirExtra_XZ){return _ipViscoElastic->_corKirExtra(0,2);}
+  else if (i == IPField::corKirExtra_YY){return _ipViscoElastic->_corKirExtra(1,1);}
+  else if (i == IPField::corKirExtra_YZ){return _ipViscoElastic->_corKirExtra(1,2);}
+  else if (i == IPField::corKirExtra_ZZ){return _ipViscoElastic->_corKirExtra(2,2);}
+  else if (i == IPField::Tr_corKir_Inf){return _ipViscoElastic->_trCorKirinf_TVE;}
+  else if (i == IPField::Dev_corKir_Inf_XX){return _ipViscoElastic->_devCorKirinf_TVE(0,0);}
+  else if (i == IPField::Dev_corKir_Inf_XY){return _ipViscoElastic->_devCorKirinf_TVE(0,1);}
+  else if (i == IPField::Dev_corKir_Inf_XZ){return _ipViscoElastic->_devCorKirinf_TVE(0,2);}
+  else if (i == IPField::Dev_corKir_Inf_YY){return _ipViscoElastic->_devCorKirinf_TVE(1,1);}
+  else if (i == IPField::Dev_corKir_Inf_YZ){return _ipViscoElastic->_devCorKirinf_TVE(1,2);}
+  else if (i == IPField::Dev_corKir_Inf_ZZ){return _ipViscoElastic->_devCorKirinf_TVE(2,2);}
   else if (i == IPField::Eve1_XX){
     if (_ipViscoElastic->_A.size() > 0)
       return _ipViscoElastic->_A[0](0,0) + _ipViscoElastic->_B[0]/3.;
@@ -5810,6 +5884,18 @@ double NonLinearTVEDG3DIPVariable::get(const int i) const{
   else if (i == IPField::THERMALFLUX_Z){return getConstRefToFlux()[0](2);}
   else if (i == IPField::FIELD_SOURCE){return getConstRefToFieldSource()(0);}
   else if (i == IPField::MECHANICAL_SOURCE){return getConstRefToMechanicalSource()(0);}
+  else if (i == IPField::DEFO_ENERGY)
+  {
+    return _ipViscoElastic->_elasticEnergy;
+  }
+  else if (i == IPField::MAX_DEFO_ENERGY)
+  {
+    return _ipViscoElastic->_psiMax;
+  }
+  else if (i == IPField::MULLINS_DAMAGE)
+  {
+    return _ipViscoElastic->_mullinsDamage;
+  }
 
   else
   {
@@ -5846,7 +5932,8 @@ NonLinearTVPDG3DIPVariable::NonLinearTVPDG3DIPVariable(const mlawNonLinearTVP& v
   _ipViscoElastoPlastic = new IPNonLinearTVP(viscoEPLaw.getConstRefToCompressionHardening(),
                                               viscoEPLaw.getConstRefToTractionHardening(),
                                               viscoEPLaw.getConstRefToKinematicHardening(),
-                                              viscoEPLaw.getViscoElasticNumberOfElement());
+                                              viscoEPLaw.getViscoElasticNumberOfElement(),
+                                              viscoEPLaw.getConstRefToMullinsEffect());
   this->getRefToTemperature()=Tinitial;
 };
 
@@ -5886,6 +5973,27 @@ double NonLinearTVPDG3DIPVariable::get(const int i) const{
   else if (i == IPField::Ee_YY){return _ipViscoElastoPlastic->_Ee(1,1);}
   else if (i == IPField::Ee_YZ){return _ipViscoElastoPlastic->_Ee(1,2);}
   else if (i == IPField::Ee_ZZ){return _ipViscoElastoPlastic->_Ee(2,2);}
+  else if (i == IPField::corKir_XX){return _ipViscoElastoPlastic->_kirchhoff(0,0);}
+  else if (i == IPField::corKir_XY){return _ipViscoElastoPlastic->_kirchhoff(0,1);}
+  else if (i == IPField::corKir_XZ){return _ipViscoElastoPlastic->_kirchhoff(0,2);}
+  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::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);}
+  else if (i == IPField::corKirExtra_XY){return _ipViscoElastoPlastic->_corKirExtra(0,1);}
+  else if (i == IPField::corKirExtra_XZ){return _ipViscoElastoPlastic->_corKirExtra(0,2);}
+  else if (i == IPField::corKirExtra_YY){return _ipViscoElastoPlastic->_corKirExtra(1,1);}
+  else if (i == IPField::corKirExtra_YZ){return _ipViscoElastoPlastic->_corKirExtra(1,2);}
+  else if (i == IPField::corKirExtra_ZZ){return _ipViscoElastoPlastic->_corKirExtra(2,2);}
+  else if (i == IPField::Tr_corKir_Inf){return _ipViscoElastoPlastic->_trCorKirinf_TVE;}
+  else if (i == IPField::Dev_corKir_Inf_XX){return _ipViscoElastoPlastic->_devCorKirinf_TVE(0,0);}
+  else if (i == IPField::Dev_corKir_Inf_XY){return _ipViscoElastoPlastic->_devCorKirinf_TVE(0,1);}
+  else if (i == IPField::Dev_corKir_Inf_XZ){return _ipViscoElastoPlastic->_devCorKirinf_TVE(0,2);}
+  else if (i == IPField::Dev_corKir_Inf_YY){return _ipViscoElastoPlastic->_devCorKirinf_TVE(1,1);}
+  else if (i == IPField::Dev_corKir_Inf_YZ){return _ipViscoElastoPlastic->_devCorKirinf_TVE(1,2);}
+  else if (i == IPField::Dev_corKir_Inf_ZZ){return _ipViscoElastoPlastic->_devCorKirinf_TVE(2,2);}
   else if (i == IPField::Eve1_XX){
     if (_ipViscoElastoPlastic->_A.size() > 0)
       return _ipViscoElastoPlastic->_A[0](0,0) + _ipViscoElastoPlastic->_B[0]/3.;
@@ -6011,7 +6119,18 @@ double NonLinearTVPDG3DIPVariable::get(const int i) const{
   {
     return _ipViscoElastoPlastic->getConstRefToKinematicHardening().getR();
   }
-
+  else if (i == IPField::DEFO_ENERGY)
+  {
+    return _ipViscoElastoPlastic->_elasticEnergy;
+  }
+  else if (i == IPField::MAX_DEFO_ENERGY)
+  {
+    return _ipViscoElastoPlastic->_psiMax;
+  }
+  else if (i == IPField::MULLINS_DAMAGE)
+  {
+    return _ipViscoElastoPlastic->_mullinsDamage;
+  }
   else
   {
     return dG3DIPVariable::get(i);
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index 4cd09386362101060a703d602e19d0764ecb777e..f2aa0c7900b3a1e0b08a5aba9d510f08f8e0b8bf 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -246,7 +246,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
 
   _stressLaw->stress(ipvcur,ipvprev,false,checkfrac,dTangent);
   
-#if 0
+#if 1
   _stressLaw->stress(ipvcur,ipvprev,true,checkfrac,dTangent);
   ipvcur->getConstRefToDeformationGradient().print("F Analytique"); // FLE
   ipvcur->getConstRefToFirstPiolaKirchhoffStress().print("P Analytique"); // FLE
@@ -288,6 +288,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         Msg::Info("dEMFieldSource dp Analytique: %e",ipvcur->getConstRefTodEMFieldSourcedNonLocalVariable()(j,i));
     }
   }
+  /*
   for (int i=0; i< numExtraDof; i++)
   {
     Msg::Info("Field Analytique: %e",ipvcur->getConstRefToField(i)); // FLE
@@ -298,8 +299,9 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
     ipvcur->getConstRefTodFieldSourcedF()[i].print("d Field source dF Analytique");
     ipvcur->getConstRefTodMechanicalSourcedF()[i].print("d Mechanical source dF Analytique");
     ipvcur->getConstRefTodPdField()[i].print("dP d Field Analytique");
-    ipvcur->getConstRefTodEMFieldSourcedF()[i].print("dEMFieldSource dF Analytique");
-
+    // ipvcur->getConstRefTodEMFieldSourcedF()[i].print("dEMFieldSource dF Analytique");
+    
+    
     for (int k=0; k< numExtraDof; k++)
     {
       ipvcur->getConstRefTodFluxdField()[k][i].print("dFludx dField Analytique");
@@ -308,11 +310,11 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
       ipvcur->getConstRefTodFluxdGradField()[k][i].print("d Flux d GradField Analytique");
       Msg::Info("d thermal source d Grad field Analytique: %e",ipvcur->getConstRefTodFieldSourcedGradField()[k][i]);
       Msg::Info("d thermal source d Grad field Analytique: %e",ipvcur->getRefTodMechanicalSourcedGradField()[k][i]);
-      Msg::Info("dEMFieldSource dField Analytique: %e",ipvcur->getConstRefTodEMFieldSourcedField()(k,i));
-      ipvcur->getConstRefTodEMFieldSourcedGradField()[k][i].print("dEMFieldSource dGradField Analytique");
+      // Msg::Info("dEMFieldSource dField Analytique: %e",ipvcur->getConstRefTodEMFieldSourcedField()(k,i));
+      // ipvcur->getConstRefTodEMFieldSourcedGradField()[k][i].print("dEMFieldSource dGradField Analytique");
     }
 
-    for (unsigned int k = 0; k < numCurlDof; ++k)
+    /*for (unsigned int k = 0; k < numCurlDof; ++k)
     {
         ipvcur->getConstRefTodFluxdVectorPotential()[i][k].print("dFlux dMagneticVectorPotential Analytique");
         ipvcur->getConstRefTodFluxdVectorCurl()[i][k].print("dFlux dMagneticVectorCurl Analytique");
@@ -328,7 +330,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");
@@ -614,7 +616,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         }
 
     }
-#if 0
+#if 1
     ipvcur->getConstRefToDeformationGradient().print("F Numerique"); // FLE
     ipvcur->getConstRefToFirstPiolaKirchhoffStress().print("P Numerique"); // FLE
     ipvcur->getConstRefToTangentModuli().print("dPdE Numerique");
@@ -653,7 +655,8 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
             Msg::Info("dEMFieldSource dp Numerique: %e",ipvcur->getConstRefTodEMFieldSourcedNonLocalVariable()(j,i));
         }
     }
-    for (int i=0; i< numExtraDof; i++)
+    
+    /*for (int i=0; i< numExtraDof; i++)
     {
       Msg::Info("Field Numerique: %e",ipvcur->getConstRefToField(i)); // FLE
       ipvcur->getConstRefToFlux()[i].print("Flux Numerique"); // FLE
@@ -663,7 +666,8 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
       ipvcur->getConstRefTodFieldSourcedF()[i].print("d Field source dF Numerique");
       ipvcur->getConstRefTodMechanicalSourcedF()[i].print("d Mechanical source dF Numerique");
       ipvcur->getConstRefTodPdField()[i].print("dP d Field Numerique");
-      ipvcur->getConstRefTodEMFieldSourcedF()[i].print("dEMFieldSource dF Numerique");
+      // ipvcur->getConstRefTodEMFieldSourcedF()[i].print("dEMFieldSource dF Numerique");
+      
       for (int k=0; k< numExtraDof; k++)
       {
         ipvcur->getConstRefTodFluxdField()[k][i].print("dFludx dField Numerique");
@@ -672,11 +676,10 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         ipvcur->getConstRefTodFluxdGradField()[k][i].print("d Flux d GradField Numerique");
         Msg::Info("d thermal source d Grad field Numerique: %e",ipvcur->getConstRefTodFieldSourcedGradField()[k][i]);
         Msg::Info("d thermal source d Grad field Numerique: %e",ipvcur->getRefTodMechanicalSourcedGradField()[k][i]);
-
-        Msg::Info("dEMFieldSource dField Numerique: %e",ipvcur->getConstRefTodEMFieldSourcedField()(k,i));
-        ipvcur->getConstRefTodEMFieldSourcedGradField()[k][i].print("dEMFieldSource dGradField Numerique");
+        // Msg::Info("dEMFieldSource dField Numerique: %e",ipvcur->getConstRefTodEMFieldSourcedField()(k,i));
+        // ipvcur->getConstRefTodEMFieldSourcedGradField()[k][i].print("dEMFieldSource dGradField Numerique");
       }
-
+      /*
       for (unsigned int k = 0; k < numCurlDof; ++k)
       {
           ipvcur->getConstRefTodFluxdVectorPotential()[i][k].print("dFlux dMagneticVectorPotential Numerique");
@@ -693,7 +696,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
@@ -9447,6 +9450,9 @@ void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(con
 void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
   _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
 };
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_ElasticCorrection(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ElasticCorrection(Tfunc);
+};
 void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
   _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
 };
@@ -9456,6 +9462,15 @@ void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchShearModuli(const
 void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc, int i){
   _viscoLaw.setTemperatureFunction_BranchThermalDilationCoefficient(Tfunc,i);
 };
+void NonLinearTVEDG3DMaterialLaw::setMullinsEffect(const mullinsEffect& mullins){
+  _viscoLaw.setMullinsEffect(mullins);
+};
+void NonLinearTVEDG3DMaterialLaw::useExtraBranchBool(const bool useExtraBranch){
+  _viscoLaw.useExtraBranchBool(useExtraBranch);
+};
+void NonLinearTVEDG3DMaterialLaw::setVolumeCorrection(double _vc, double _xivc, double _zetavc, double _dc, double _thetadc, double _pidc){
+  _viscoLaw.setVolumeCorrection(_vc,_xivc,_zetavc,_dc,_thetadc,_pidc);
+};
 
 // Added extra argument in the NonLinearTVEDG3DIPVariable contructor - Tinitial   (added from LinearThermoMech)
 void NonLinearTVEDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
@@ -9632,6 +9647,12 @@ void NonLinearTVPDG3DMaterialLaw::setViscoElasticData(const std::string filename
 void NonLinearTVPDG3DMaterialLaw::setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3){
   _viscoLaw.setIsotropicHardeningCoefficients(HR1,HR2,HR3);
 };
+void NonLinearTVPDG3DMaterialLaw::setPolynomialOrderChabocheCoeffs(const int order){
+  _viscoLaw.setPolynomialOrderChabocheCoeffs(order);
+};
+void NonLinearTVPDG3DMaterialLaw::setPolynomialCoeffsChabocheCoeffs(const int i, const double val){
+  _viscoLaw.setPolynomialCoeffsChabocheCoeffs(i,val);
+};
 
 void NonLinearTVPDG3DMaterialLaw::setReferenceTemperature(const double Tref){
   _viscoLaw.setReferenceTemperature(Tref);
@@ -9663,6 +9684,9 @@ void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(con
 void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
   _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
 };
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_ElasticCorrection(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ElasticCorrection(Tfunc);
+};
 void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
   _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
 };
@@ -9685,6 +9709,9 @@ void NonLinearTVPDG3DMaterialLaw::setKinematicHardening(const kinematicHardening
 void NonLinearTVPDG3DMaterialLaw::setViscosityEffect(const viscosityLaw& v, const double p){
   _viscoLaw.setViscosityEffect(v,p);
 };
+void NonLinearTVPDG3DMaterialLaw::setMullinsEffect(const mullinsEffect& mullins){
+  _viscoLaw.setMullinsEffect(mullins);
+};
 
 void NonLinearTVPDG3DMaterialLaw::setYieldPowerFactor(const double n){
   _viscoLaw.setPowerFactor(n);
@@ -9699,8 +9726,8 @@ void NonLinearTVPDG3DMaterialLaw::setNonAssociatedFlow(const bool flag){
   _viscoLaw.setNonAssociatedFlow(flag);
 };
 
-void NonLinearTVPDG3DMaterialLaw::setTaylorQuineyFactor(const double f){
-  _viscoLaw.setTaylorQuineyFactor(f);
+void NonLinearTVPDG3DMaterialLaw::setTaylorQuineyFactor(const double f, const bool flag){
+  _viscoLaw.setTaylorQuineyFactor(f, flag);
 };
 void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc){
   _viscoLaw.setTemperatureFunction_InitialYieldStress(Tfunc);
@@ -9714,6 +9741,13 @@ void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_KinematicHardening(cons
 void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_Viscosity(const scalarFunction& Tfunc){
   _viscoLaw.setTemperatureFunction_Viscosity(Tfunc);
 };
+void NonLinearTVPDG3DMaterialLaw::useExtraBranchBool(const bool useExtraBranch){
+  _viscoLaw.useExtraBranchBool(useExtraBranch);
+};
+void NonLinearTVPDG3DMaterialLaw::setVolumeCorrection(double _vc, double _xivc, double _zetavc, double _dc, double _thetadc, double _pidc){
+  _viscoLaw.setVolumeCorrection(_vc,_xivc,_zetavc,_dc,_thetadc,_pidc);
+};
+
 
 // Added extra argument in the NonLinearTVEDG3DIPVariable contructor - Tinitial   (added from LinearThermoMech)
 void NonLinearTVPDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index f4898ebee8f81f60a19531c141e5fab440a2edd8..8ba7f7a811c68766aab277f03e5bb7f2cfd7fcee 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -56,6 +56,7 @@
 #include "mlawNonLinearTVM.h"
 #include "mlawNonLinearTVE.h"
 #include "mlawNonLinearTVP.h"
+#include "mullinsEffect.h"
 #endif
 #if defined(HAVE_TORCH)
 #include <torch/torch.h>
@@ -3167,20 +3168,25 @@ class NonLinearTVEDG3DMaterialLaw : public dG3DMaterialLaw{   // public Material
     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 setVolumeCorrection(double _vc, double _xivc, double _zetavc, double _dc, double _thetadc, double _pidc);
 
     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 useExtraBranchBool(const bool useExtraBranch);
     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(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 setMullinsEffect(const mullinsEffect& mullins);
 
     // For now use these Scalars - Fix by directly adding to constructor
    /* void setThermalExpansionCoefficient(const double Alpha);   // Fix this - for both scalar and tensor
@@ -3255,6 +3261,8 @@ class NonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // public Material
     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);
@@ -3266,21 +3274,25 @@ class NonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // public Material
     void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
     void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc);
     void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ElasticCorrection(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 setVolumeCorrection(double _vc, double _xivc, double _zetavc, double _dc, double _thetadc, double _pidc);
 
     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);
+    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);