diff --git a/NonLinearSolver/internalPoints/CMakeLists.txt b/NonLinearSolver/internalPoints/CMakeLists.txt
index 1705f449fc7b66848b4b9281d25766c7c186ad66..174256314067b55dc46aedc208c330c14e29b92f 100644
--- a/NonLinearSolver/internalPoints/CMakeLists.txt
+++ b/NonLinearSolver/internalPoints/CMakeLists.txt
@@ -57,6 +57,9 @@ set(SRC
   ipTFA.cpp
   ipVoidState.cpp
   ipLinearElecMagInductor.cpp
+  ipNonLinearTVM.cpp
+  ipNonLinearTVE.cpp
+  ipNonLinearTVP.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
diff --git a/NonLinearSolver/internalPoints/ipHardening.cpp b/NonLinearSolver/internalPoints/ipHardening.cpp
index fa3d3e275f3783487334e8bccb1dc9b1e310b524..f71905e98f715f3a3c9779ed6777b9849601b507 100644
--- a/NonLinearSolver/internalPoints/ipHardening.cpp
+++ b/NonLinearSolver/internalPoints/ipHardening.cpp
@@ -11,13 +11,13 @@
 #include "restartManager.h"
 
 IPJ2IsotropicHardening::IPJ2IsotropicHardening(const double R0_):
-      R0(R0_), R(R0_), dR(0.), ddR(0.), integR(0.),_isSaturated(false),dRdT(0.), wp(0.), dwp(0.)
+      R0(R0_), R(R0_), dR(0.), ddR(0.), integR(0.),_isSaturated(false),dRdT(0.), ddRdTT(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),
+      R0(source.R0), R(source.R), dR (source.dR), ddR (source.ddR),integR(source.integR),_isSaturated(source._isSaturated), dRdT(source.dRdT), ddRdTT(source.ddRdTT),
       wp(source.wp), dwp(source.dwp)
 {
 
@@ -32,6 +32,7 @@ IPJ2IsotropicHardening &IPJ2IsotropicHardening::operator=(const IPJ2IsotropicHar
   integR = src.integR;
   _isSaturated = src._isSaturated;
   dRdT = src.dRdT;
+  ddRdTT = src.ddRdTT;
   wp   = src.wp;
   dwp   = src.dwp;
   return *this;
@@ -46,6 +47,7 @@ void IPJ2IsotropicHardening::restart()
   restartManager::restart(integR);
   restartManager::restart(_isSaturated);
   restartManager::restart(dRdT);
+  restartManager::restart(ddRdTT);
   restartManager::restart(wp);
   restartManager::restart(dwp);
   return;
diff --git a/NonLinearSolver/internalPoints/ipHardening.h b/NonLinearSolver/internalPoints/ipHardening.h
index 9e24dc5f4a1d5e9642775c4d4bb4329f59ff09c0..c62fbf01b7df159e43d4b3176c4c94682ef4415d 100644
--- a/NonLinearSolver/internalPoints/ipHardening.h
+++ b/NonLinearSolver/internalPoints/ipHardening.h
@@ -27,6 +27,7 @@ protected:
     double integR;
     bool _isSaturated; // harderning modulus become 0 under some conditions
     double dRdT; // temeprature dependence
+    double ddRdTT; // 
 
     double wp;  //yield shrink because of plastic instability
     double dwp;
@@ -48,9 +49,10 @@ protected:
   virtual double getDDR() const {return (1-wp)*ddR;}
   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 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) 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) final
   {
     R0 = _r0;
     R=_r;
@@ -58,6 +60,7 @@ protected:
     ddR=_ddr;
     integR=_integR;
     dRdT = _dRdT;
+    ddRdTT = _ddRdTT;
   }
   virtual void setScaleFactor(double _wp, double _dwp) final
   {
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.cpp b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
index 84de44e88aa3f80962dfa5e847e55050dedffa25..93a02553cb5cdaca09f9b49a77bd786cfe44ec5f 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.cpp
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.cpp
@@ -27,7 +27,7 @@ IPHyperViscoElastic::IPHyperViscoElastic(const int N):IPVariableMechanics(),_N(N
 IPHyperViscoElastic::IPHyperViscoElastic(const IPHyperViscoElastic& src): IPVariableMechanics(src), _Ee(src._Ee),
     _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), 
+    _viscousEnergyPart(src._viscousEnergyPart), _dElasticEnergyPartdF(src._dElasticEnergyPartdF),
     _dViscousEnergyPartdF(src._dViscousEnergyPartdF)
 {
 
@@ -46,7 +46,7 @@ IPHyperViscoElastic& IPHyperViscoElastic::operator =(const IPVariable& src){
     _irreversibleEnergy = psrc->_irreversibleEnergy;
     _DirreversibleEnergyDF = psrc->_DirreversibleEnergyDF;
     _viscousEnergyPart = psrc->_viscousEnergyPart;
-    _dElasticEnergyPartdF = psrc->_dElasticEnergyPartdF; 
+    _dElasticEnergyPartdF = psrc->_dElasticEnergyPartdF;
     _dViscousEnergyPartdF = psrc->_dViscousEnergyPartdF;
   }
   return *this;
@@ -63,14 +63,14 @@ void IPHyperViscoElastic::restart() {
   restartManager::restart(_irreversibleEnergy);
   restartManager::restart(_DirreversibleEnergyDF);
   restartManager::restart(_viscousEnergyPart);
-  restartManager::restart(_dElasticEnergyPartdF); 
+  restartManager::restart(_dElasticEnergyPartdF);
   restartManager::restart(_dViscousEnergyPartdF);
 };
 
 void IPHyperViscoElastic::getViscoElasticStrain(int i, STensor3& Ev) const
 {
   if (i > _A.size() or i < 1)
-  { 
+  {
     Msg::Error("viscoelastic branch %d does not exist",i);
   }
   else
@@ -83,30 +83,30 @@ void IPHyperViscoElastic::getViscoElasticStrain(int i, STensor3& Ev) const
 };
 
 void IPHyperViscoElastic::resetA()
-{ 
+{
   for(int i=0; i<_A.size(); i++)
     STensorOperation::zero(_A[i]);
   getRefToElasticEnergyPart()=0.;
   getRefToViscousEnergyPart()=0.;
 }
 void IPHyperViscoElastic::resetB()
-{ 
+{
   for(int i=0;i<_B.size(); i++)
     _B[i]=0.;
   getRefToElasticEnergyPart()=0.;
   getRefToViscousEnergyPart()=0.;
 }
-    
+
 IPHyperViscoElastoPlastic::IPHyperViscoElastoPlastic(const J2IsotropicHardening* comp,
                     const J2IsotropicHardening* trac,
                     const kinematicHardening* kin, const int N):IPHyperViscoElastic(N),
-                    _backsig(0),_Fp(1.),_epspbarre(0.),_nup(0.),
+                    _backsig(0),_Fp(1.),_epspbarre(0.),_nup(0.), _Gamma(0.),
                     _epspCompression(0.),_epspTraction(0.),_epspShear(0.),
                     _DgammaDt(0.),_Fe(1.),_r(-1e100), _inPostFailureStage(false),
                     _DgammaDF(0.),_gF(0.),_dgFdF(0.), _plasticEnergy(0.),
                     _dissipationActive(false),_dissipationBlocked(false),
                     _dPlasticEnergyPartdF(0)
-                    
+
 {
 
   _ipCompression = NULL;
@@ -124,7 +124,7 @@ IPHyperViscoElastoPlastic::IPHyperViscoElastoPlastic(const IPHyperViscoElastoPla
       _backsig(src._backsig),_DgammaDt(src._DgammaDt),_Fe(src._Fe),
        _inPostFailureStage(src._inPostFailureStage),_r(src._r),_DgammaDF(src._DgammaDF),_gF(src._gF),_dgFdF(src._dgFdF),
        _plasticEnergy(src._plasticEnergy),_dissipationActive(src._dissipationActive),_dissipationBlocked(src._dissipationBlocked),
-       _dPlasticEnergyPartdF(src._dPlasticEnergyPartdF)       
+       _dPlasticEnergyPartdF(src._dPlasticEnergyPartdF)
 {
   if (src._ipCompression != NULL)
     _ipCompression = dynamic_cast<IPJ2IsotropicHardening*>(src._ipCompression->clone());
@@ -150,6 +150,7 @@ IPHyperViscoElastoPlastic& IPHyperViscoElastoPlastic::operator =(const IPVariabl
     _Fp = ps->_Fp;
     _epspbarre = ps->_epspbarre;
     _nup = ps->_nup;
+    _Gamma = ps->_Gamma;
     _epspCompression = ps->_epspCompression;
     _epspTraction = ps->_epspTraction;
     _epspShear = ps->_epspShear;
@@ -222,6 +223,7 @@ void IPHyperViscoElastoPlastic::restart() {
   restartManager::restart(_epspbarre);
   restartManager::restart(_Fp);
   restartManager::restart(_nup);
+  restartManager::restart(_Gamma);
   restartManager::restart(_epspCompression);
   restartManager::restart(_epspTraction);
   restartManager::restart(_epspShear);
@@ -349,4 +351,3 @@ void IPHyperViscoElastoPlastic::resetPlasticity()
 
   getRefToPlasticEnergyPart()=0.;
 }
-
diff --git a/NonLinearSolver/internalPoints/ipHyperelastic.h b/NonLinearSolver/internalPoints/ipHyperelastic.h
index 69b90f984c3c957db7528bff8deb22eaee9be03c..f6c3dc4e19cc3a48c2304e4eaa00634341644d40 100644
--- a/NonLinearSolver/internalPoints/ipHyperelastic.h
+++ b/NonLinearSolver/internalPoints/ipHyperelastic.h
@@ -28,7 +28,7 @@ class IPHyperViscoElastic : public IPVariableMechanics{
 
     double _irreversibleEnergy;
     STensor3 _DirreversibleEnergyDF;
-    
+
   protected:
     //For energy sources
     double _viscousEnergyPart;
@@ -41,9 +41,9 @@ class IPHyperViscoElastic : public IPVariableMechanics{
     virtual ~IPHyperViscoElastic(){};
 
     virtual IPVariable* clone() const{return new IPHyperViscoElastic(*this);};
-    
+
     virtual void getViscoElasticStrain(int i, STensor3& Ev) const;
-    
+
     virtual STensor3& getRefToElasticStrain() {return _Ee;};
     virtual const STensor3& getConstRefToElasticStrain() const {return _Ee;};
 
@@ -61,7 +61,7 @@ class IPHyperViscoElastic : public IPVariableMechanics{
     virtual const STensor3& getConstRefToDIrreversibleEnergyDF() const{return _DirreversibleEnergyDF;};
 
     virtual void restart();
-    
+
     virtual void resetA();
     virtual void resetB();
 
@@ -77,7 +77,7 @@ class IPHyperViscoElastic : public IPVariableMechanics{
     virtual const STensor3 &getConstRefToDElasticEnergyPartdF() const {return _dElasticEnergyPartdF;}
     virtual STensor3 &getRefToDViscousEnergyPartdF() {return _dViscousEnergyPartdF;}
     virtual const STensor3 &getConstRefToDViscousEnergyPartdF() const {return _dViscousEnergyPartdF;}
-    
+
 
 
 };
@@ -93,6 +93,7 @@ class IPHyperViscoElastoPlastic : public IPHyperViscoElastic{
     STensor3 _backsig; // backstress
     STensor3 _Fe; // elastic strain
 
+    double _Gamma; // flow rule parameter
     double _epspbarre; // equivalent plastic strain
     STensor3 _Fp;    // plastic part of the deformation gradient
     double _nup; // plastic poisson ration
@@ -223,10 +224,10 @@ class IPHyperViscoElastoPlastic : public IPHyperViscoElastic{
 
     virtual STensor3 &getRefToDPlasticEnergyPartdF() {return _dPlasticEnergyPartdF;}
     virtual const STensor3 &getConstRefToDPlasticEnergyPartdF() const {return _dPlasticEnergyPartdF;}
- 
- 
- 
- 
+
+
+
+
 };
 
 #endif // IPHYPERELASTIC_H_
diff --git a/NonLinearSolver/internalPoints/ipKinematicHardening.cpp b/NonLinearSolver/internalPoints/ipKinematicHardening.cpp
index 220d12f83e24003090d3391b24732bf9ee6aa16a..923b60aed8d69b75728abdc9d0f3199a14db3bb2 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),_isSaturated(false)
+IPKinematicHardening::IPKinematicHardening(): R(0), dR(0), ddR(0), dRdT(0.), ddRddT(0.), _isSaturated(false)
 {
 
 }
@@ -20,6 +20,8 @@ IPKinematicHardening::IPKinematicHardening(const IPKinematicHardening &source)
   R      = source.R;
   dR     = source.dR;
   ddR    = source.ddR;
+  dRdT   = source.dRdT;
+  ddRddT   = source.ddRddT;
   _isSaturated= source._isSaturated;
 }
 
@@ -28,6 +30,8 @@ IPKinematicHardening &IPKinematicHardening::operator=(const IPKinematicHardening
   R      = source.R;
   dR     = source.dR;
   ddR    = source.ddR;
+  dRdT   = source.dRdT;
+  ddRddT   = source.ddRddT;
   _isSaturated = source._isSaturated;
   return *this;
 }
@@ -37,6 +41,8 @@ void IPKinematicHardening::restart()
   restartManager::restart(R);
   restartManager::restart(dR);
   restartManager::restart(ddR);
+  restartManager::restart(dRdT);
+  restartManager::restart(ddRddT);
   restartManager::restart(_isSaturated);
   return;
 }
diff --git a/NonLinearSolver/internalPoints/ipKinematicHardening.h b/NonLinearSolver/internalPoints/ipKinematicHardening.h
index 7a9728962101d34d412e12d82a07414fa68f4f7c..f47257462cc9845ef513d2c273156b131e8ed6c3 100644
--- a/NonLinearSolver/internalPoints/ipKinematicHardening.h
+++ b/NonLinearSolver/internalPoints/ipKinematicHardening.h
@@ -18,7 +18,10 @@ class IPKinematicHardening{
     double R;
     double dR;
     double ddR;
+    double dRdT; // temeprature dependence
+    double ddRddT;
     bool _isSaturated;
+    
 
   public:
     IPKinematicHardening();
@@ -35,11 +38,15 @@ class IPKinematicHardening{
     virtual double getR() const {return R;}
     virtual double getDR() const {return dR;}
     virtual double getDDR() const {return ddR;};
-    virtual void set(const double &_r, const double &_dr, const double& _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)
     {
       R=_r;
       dR=_dr;
       ddR = _ddr;
+      dRdT = _dRdT;
+      ddRddT = _ddRddT;
     }
 };
 
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b9e0ae670bb61dc0824d24e4a26401cff828c15
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVE.cpp
@@ -0,0 +1,151 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVM (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// #include "ipHyperelastic.h"
+#include "ipNonLinearTVE.h"
+// #include "restartManager.h"
+
+IPNonLinearTVE::IPNonLinearTVE(const J2IsotropicHardening* comp,
+                    const J2IsotropicHardening* trac,
+                    const kinematicHardening* kin, const int N): 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.){
+    _devOGammai.clear();
+    _trOGammai.clear();
+    _devDOGammaiDT.clear();
+    _trDOGammaiDT.clear();
+    _devOi.clear();
+    _trOi.clear();
+    _devDOiDT.clear();
+    _trDOiDT.clear();
+    _devDDOiDTT.clear();
+    _trDDOiDTT.clear();
+    _C.clear();
+    _D.clear();
+    _E.clear();
+    _F.clear();
+    _G.clear();
+    for (int i=0; i < N; i++){
+        STensor3 el(0.);
+        _devOGammai.push_back(el);
+        _trOGammai.push_back(0.);
+        _devDOGammaiDT.push_back(el);
+        _trDOGammaiDT.push_back(0.);
+        _devOi.push_back(el);
+        _trOi.push_back(0.);
+        _devDOiDT.push_back(el);
+        _trDOiDT.push_back(0.);
+        _devDDOiDTT.push_back(el);
+        _trDDOiDTT.push_back(0.);
+        _C.push_back(el);
+        _D.push_back(0.);
+        _E.push_back(0.);
+        _F.push_back(0.);
+        _G.push_back(0.);
+    }
+    
+};
+
+IPNonLinearTVE::IPNonLinearTVE(const IPNonLinearTVE& src): IPHyperViscoElastoPlastic(src), //IPHyperViscoElastic(src), 
+            _devOGammai(src._devOGammai), _trOGammai(src._trOGammai), 
+            _devDOGammaiDT(src._devDOGammaiDT), _trDOGammaiDT(src._trDOGammaiDT),
+            _devOi(src._devOi), _trOi(src._trOi), _devDOiDT(src._devDOiDT), _trDOiDT(src._trDOiDT), _devDDOiDTT(src._devDDOiDTT), _trDDOiDTT(src._trDDOiDTT),
+            _T(src._T),_devDE(src._devDE), _trDE(src._trDE), _DE(src._DE), _DcorKirDT(src._DcorKirDT), _DDcorKirDTT(src._DDcorKirDTT),
+            _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){};
+            
+IPNonLinearTVE& IPNonLinearTVE::operator=(const IPVariable& src)
+{
+  // IPHyperViscoElastic::operator=(src);
+  IPHyperViscoElastoPlastic::operator=(src);
+  const IPNonLinearTVE* psrc = dynamic_cast<const IPNonLinearTVE*>(&src);
+  if(psrc != NULL)
+  {
+    _devOGammai = psrc->_devOGammai; 
+    _trOGammai = psrc->_trOGammai; 
+    _devDOGammaiDT = psrc->_devDOGammaiDT; 
+    _trDOGammaiDT = psrc->_trDOGammaiDT; 
+    _T = psrc->_T;
+    _mechSrcTVE = psrc->_mechSrcTVE;
+    _DmechSrcTVEdT = psrc->_DmechSrcTVEdT;
+    _DmechSrcTVEdF = psrc->_DmechSrcTVEdF;
+    _devOi = psrc->_devOi; 
+    _trOi = psrc->_trOi;
+    _devDOiDT = psrc->_devDOiDT; 
+    _trDOiDT = psrc->_trDOiDT;
+    _devDDOiDTT = psrc->_devDDOiDTT; 
+    _trDDOiDTT = psrc->_trDDOiDTT; 
+    _devDE = psrc->_devDE; 
+    _trDE = psrc->_trDE;
+    _DE = psrc->_DE;
+    _DcorKirDT = psrc->_DcorKirDT;
+    _DDcorKirDTT = psrc->_DDcorKirDTT;
+    _C = psrc->_C;
+    _D = psrc->_D;
+    _E = psrc->_E;
+    _F = psrc->_F;
+    _G = psrc->_G;
+    _thermalEnergy = psrc->_thermalEnergy;
+    _dtShift = psrc->_dtShift;
+    _DdtShiftDT = psrc->_DdtShiftDT;
+    _DDdtShiftDDT = psrc->_DDdtShiftDDT;
+  }
+  return *this;
+}
+
+double IPNonLinearTVE::defoEnergy() const
+{
+  return IPHyperViscoElastic::defoEnergy();
+}
+
+// Add plasticEnergy later -----------                                      CHANGE!!!
+/*
+double IPNonLinearTVE::plasticEnergy() const
+{
+  return IPHyperViscoElastic::plasticEnergy();
+}
+*/
+
+void IPNonLinearTVE::restart(){
+  // IPHyperViscoElastic::restart();
+  IPHyperViscoElastoPlastic::restart();
+  restartManager::restart(_devOGammai);
+  restartManager::restart(_trOGammai);
+  restartManager::restart(_devDOGammaiDT);
+  restartManager::restart(_trDOGammaiDT);
+  restartManager::restart(_devOi);
+  restartManager::restart(_trOi);
+  restartManager::restart(_devDOiDT);
+  restartManager::restart(_trDOiDT);
+  restartManager::restart(_devDDOiDTT);
+  restartManager::restart(_trDDOiDTT);
+  restartManager::restart(_devDE);
+  restartManager::restart(_trDE);
+  restartManager::restart(_DE);
+  restartManager::restart(_DcorKirDT);
+  restartManager::restart(_DDcorKirDTT);
+  restartManager::restart(_mechSrcTVE);
+  restartManager::restart(_DmechSrcTVEdT);
+  restartManager::restart(_DmechSrcTVEdF);
+  restartManager::restart(_T);
+  restartManager::restart(_C);
+  restartManager::restart(_D);
+  restartManager::restart(_E);
+  restartManager::restart(_F);
+  restartManager::restart(_G);
+  restartManager::restart(_thermalEnergy);
+  restartManager::restart(_dtShift);
+  restartManager::restart(_DdtShiftDT);
+  restartManager::restart(_DDdtShiftDDT);
+}
\ No newline at end of file
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVE.h b/NonLinearSolver/internalPoints/ipNonLinearTVE.h
new file mode 100644
index 0000000000000000000000000000000000000000..c6e6d68223f0ba862d0b726fac748d0acc7af394
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVE.h
@@ -0,0 +1,136 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVE (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef IPNONLINEARTVE_H_
+#define IPNONLINEARTVE_H_
+#include "ipHyperelastic.h"
+#include "j2IsotropicHardening.h"       
+#include "kinematicHardening.h"
+#include "STensor3.h"
+#include "STensor43.h"
+
+
+// class IPNonLinearTVE : public IPHyperViscoElastic{
+class IPNonLinearTVE : public IPHyperViscoElastoPlastic{
+    public:
+        // Temperature history (I think) - from IPLinearThermoMechanics.h (fracEnergy is unused w/o fracture - add and initialise it later)
+        double _thermalEnergy;                                                                                                               // Added _thermalEnergy
+        double _T; 
+        //  double _fracEnergy;
+        STensor3 _devDE;
+        double _trDE;
+        STensor3 _DE;
+        double _mechSrcTVE;
+        double _DmechSrcTVEdT;
+        STensor3 _DmechSrcTVEdF;
+        
+        // Viscoelastic Strain
+        std::vector<STensor3> _devOGammai;   // dev viscoelastic strain for each branch
+        std::vector<double> _trOGammai;      // tr viscoelastic strain for each branch
+        std::vector<STensor3> _devDOGammaiDT;  
+        std::vector<double> _trDOGammaiDT;     
+        
+        // Viscoelastic Stress
+        std::vector<STensor3> _devOi;   // dev viscoelastic stress for each branch
+        std::vector<double> _trOi;      // tr viscoelastic stress for each branch
+        std::vector<STensor3> _devDOiDT;  
+        std::vector<double> _trDOiDT; 
+        std::vector<STensor3> _devDDOiDTT;  
+        std::vector<double> _trDDOiDTT; 
+        
+        // DcorKirDT
+        STensor3 _DcorKirDT;
+        STensor3 _DDcorKirDTT;
+        
+        // Additional Internal Variables 
+        std::vector<STensor3> _C;           // dGi/dT summation
+        std::vector<double> _D;             // dKi/dT summation
+        std::vector<double> _E, _F, _G;
+        
+        // Additional variables
+        double _dtShift;
+        double _DdtShiftDT;
+        double _DDdtShiftDDT;
+        
+    public:
+        IPNonLinearTVE(const J2IsotropicHardening* comp,
+                    const J2IsotropicHardening* trac,
+                    const kinematicHardening* kin, const int N);
+        IPNonLinearTVE(const IPNonLinearTVE& src);
+        virtual IPNonLinearTVE& operator=(const IPVariable& src);
+        virtual ~IPNonLinearTVE(){};
+        
+        virtual std::vector<STensor3>& getRefToDevViscoElasticOverStrain() {return _devOGammai;};
+        virtual const std::vector<STensor3>& getConstRefToDevViscoElasticOverStrain() const {return _devOGammai;};
+        
+        virtual std::vector<double>& getRefToTrViscoElasticOverStrain() {return _trOGammai;};
+        virtual const std::vector<double>& getConstRefToTrViscoElasticOverStrain() const {return _trOGammai;};
+        
+        virtual std::vector<STensor3>& getRefToDevDOGammaiDT() {return _devDOGammaiDT;};
+        virtual const std::vector<STensor3>& getConstRefToDevDOGammaiDT() const {return _devDOGammaiDT;};
+        
+        virtual std::vector<double>& getRefToTrDOGammaiDT() {return _trDOGammaiDT;};
+        virtual const std::vector<double>& getConstRefToTrDOGammaiDT() const {return _trDOGammaiDT;};
+        
+        virtual std::vector<STensor3>& getRefToDevViscoElasticOverStress() {return _devOi;};
+        virtual const std::vector<STensor3>& getConstRefToDevViscoElasticOverStress() const {return _devOi;};
+        
+        virtual std::vector<double>& getRefToTrViscoElasticOverStress() {return _trOi;};
+        virtual const std::vector<double>& getConstRefToTrViscoElasticOverStress() const {return _trOi;};
+        
+        virtual std::vector<STensor3>& getRefToDevDOiDT() {return _devDOiDT;};
+        virtual const std::vector<STensor3>& getConstRefToDevDOiDT() const {return _devDOiDT;};
+        
+        virtual std::vector<double>& getRefToTrDOiDT() {return _trDOiDT;};
+        virtual const std::vector<double>& getConstRefToTrDOiDT() const {return _trDOiDT;};
+        
+        virtual std::vector<STensor3>& getRefToDevDDOiDTT() {return _devDDOiDTT;};
+        virtual const std::vector<STensor3>& getConstRefToDevDDOiDTT() const {return _devDDOiDTT;};
+        
+        virtual std::vector<double>& getRefToTrDDOiDTT() {return _trDDOiDTT;};
+        virtual const std::vector<double>& getConstRefToTrDDOiDTT() const {return _trDDOiDTT;};
+        
+        virtual STensor3& getRefToDcorKirDT() {return _DcorKirDT;};
+        virtual const STensor3& getConstRefToDcorKirDT() const {return _DcorKirDT;};
+        
+        virtual STensor3& getRefToDDcorKirDTT() {return _DDcorKirDTT;};
+        virtual const STensor3& getConstRefToDDcorKirDTT() const {return _DDcorKirDTT;};
+        
+        virtual double& getRefToTrDE() {return _trDE;};
+        virtual const double& getConstRefToTrDE() const {return _trDE;};
+        virtual STensor3& getRefToDevDE() {return _devDE;};
+        virtual const STensor3& getConstRefToDevDE() const {return _devDE;};
+        
+        virtual STensor3& getRefToDE() {return _DE;};
+        virtual const STensor3& getConstRefToDE() const {return _DE;};
+        
+        virtual double &getRefToMechSrcTVE() {return _mechSrcTVE;}
+        virtual const double &getConstRefToMechSrcTVE() const {return _mechSrcTVE;}
+        virtual double &getRefTodMechSrcTVEdT() {return _DmechSrcTVEdT;}
+        virtual const double &getConstRefTodMechSrcTVEdT() const {return _DmechSrcTVEdT;}
+        virtual STensor3 &getRefTodMechSrcTVEdF() {return _DmechSrcTVEdF;}
+        virtual const STensor3 &getConstRefTodMechSrcTVEdF() const {return _DmechSrcTVEdF;}
+        
+        virtual double& getShiftedTimeStep() {return _dtShift;};
+        virtual const double& getConstShiftedTimeStep() const {return _dtShift;};
+        virtual double& getShiftedTimeStepTempDerivative() {return _DdtShiftDT;};
+        virtual const double& getConstShiftedTimeStepTempDerivative() const {return _DdtShiftDT;};
+        virtual double& getShiftedTimeStepTempDoubleDerivative() {return _DDdtShiftDDT;};
+        virtual const double& getConstShiftedTimeStepTempDoubleDerivative() const {return _DDdtShiftDDT;};
+        
+        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)
+
+        virtual IPVariable* clone() const{return new IPNonLinearTVE(*this);};
+        virtual void restart();
+};
+#endif // IPNonLinearTVE.h
\ No newline at end of file
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..16353a1a8621aa2ce5a58555920961e526baaa82
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVM.cpp
@@ -0,0 +1,178 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVM (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+// #include "ipHyperelastic.h"
+#include "ipNonLinearTVM.h"
+// #include "restartManager.h"
+
+IPNonLinearTVM::IPNonLinearTVM(const int N): IPHyperViscoElastic(N), _thermalEnergy(0.){
+    _devGammai.clear();
+    _trGammai.clear();
+    _devDGammaiDT.clear();
+    _trDGammaiDT.clear();
+    _devQi.clear();
+    _trQi.clear();
+    _C.clear();
+    _D.clear();
+    _E.clear();
+    _F.clear();
+    _G.clear();
+    for (int i=0; i < N; i++){
+        STensor3 el(0.);
+        _devGammai.push_back(el);
+        _trGammai.push_back(0.);
+        _devDGammaiDT.push_back(el);
+        _trDGammaiDT.push_back(0.);
+        _devQi.push_back(el);
+        _trQi.push_back(0.);
+        _C.push_back(el);
+        _D.push_back(0.);
+        _E.push_back(0.);
+        _F.push_back(0.);
+        _G.push_back(0.);
+    }
+    
+};
+
+IPNonLinearTVM::IPNonLinearTVM(const IPNonLinearTVM& src): IPHyperViscoElastic(src), 
+            _devGammai(src._devGammai), _trGammai(src._trGammai), 
+            _devDGammaiDT(src._devDGammaiDT), _trDGammaiDT(src._trDGammaiDT),
+            _devQi(src._devQi), _trQi(src._trQi),
+            _devDE(src._devDE), _trDE(src._trDE), _DE(src._DE),
+            _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){};
+            
+IPNonLinearTVM& IPNonLinearTVM::operator=(const IPVariable& src)
+{
+  IPHyperViscoElastic::operator=(src);
+  const IPNonLinearTVM* psrc = dynamic_cast<const IPNonLinearTVM*>(&src);
+  if(psrc != NULL)
+  {
+    _devGammai = psrc->_devGammai; 
+    _trGammai = psrc->_trGammai; 
+    _devDGammaiDT = psrc->_devDGammaiDT; 
+    _trDGammaiDT = psrc->_trDGammaiDT; 
+    _devQi = psrc->_devQi; 
+    _trQi = psrc->_trQi; 
+    _devDE = psrc->_devDE; 
+    _trDE = psrc->_trDE; 
+    _DE = psrc->_DE;
+    _C = psrc->_C;
+    _D = psrc->_D;
+    _E = psrc->_E;
+    _F = psrc->_F;
+    _G = psrc->_G;
+    _thermalEnergy = psrc->_thermalEnergy;
+    _dtShift = psrc->_dtShift;
+    _DdtShiftDT = psrc->_DdtShiftDT;
+    _DDdtShiftDDT = psrc->_DDdtShiftDDT;
+  }
+  return *this;
+}
+
+double IPNonLinearTVM::defoEnergy() const
+{
+  return IPHyperViscoElastic::defoEnergy();
+}
+
+// Add plasticEnergy later -----------                                      CHANGE!!!
+/*
+double IPNonLinearTVM::plasticEnergy() const
+{
+  return IPHyperViscoElastic::plasticEnergy();
+}
+*/
+
+void IPNonLinearTVM::restart(){
+  IPHyperViscoElastic::restart();
+  restartManager::restart(_devGammai);
+  restartManager::restart(_trGammai);
+  restartManager::restart(_devDGammaiDT);
+  restartManager::restart(_trDGammaiDT);
+  restartManager::restart(_devQi);
+  restartManager::restart(_trQi);
+  restartManager::restart(_devDE);
+  restartManager::restart(_trDE);
+  restartManager::restart(_DE);
+  restartManager::restart(_C);
+  restartManager::restart(_D);
+  restartManager::restart(_E);
+  restartManager::restart(_F);
+  restartManager::restart(_G);
+  restartManager::restart(_thermalEnergy);
+  restartManager::restart(_dtShift);
+  restartManager::restart(_DdtShiftDT);
+  restartManager::restart(_DDdtShiftDDT);
+}
+
+
+/*
+IPNonLinearTVM::IPNonLinearTVM(const int N):IPVariableMechanics(),_N(N),_elasticEnergy(0.),_Ee(0.),_kirchhoff(0.),_thermalEnergy(0.),    // Added _thermalEnergy
+      _irreversibleEnergy(0.),_DirreversibleEnergyDF(0.){
+  _A.clear();
+  _B.clear();
+  for (int i=0; i< N; i++){
+    STensor3 el(0.);
+    _A.push_back(el);
+    _B.push_back(0.);
+  }
+};
+
+IPNonLinearTVM::IPNonLinearTVM(const IPNonLinearTVM& src): IPVariableMechanics(src), _Ee(src._Ee),
+    _N(src._N),_A(src._A),_B(src._B),_elasticEnergy(src._elasticEnergy), _kirchhoff(src._kirchhoff),_thermalEnergy(src._thermalEnergy),  // Added _thermalEnergy
+    _irreversibleEnergy(src._irreversibleEnergy),_DirreversibleEnergyDF(src._DirreversibleEnergyDF){};
+
+IPNonLinearTVM& IPNonLinearTVM::operator =(const IPVariable& src){
+  IPVariableMechanics::operator =(src);
+  const IPNonLinearTVM* psrc = dynamic_cast<const IPNonLinearTVM*>(&src);
+  if (psrc != NULL){
+    _Ee = psrc->_Ee;
+    _kirchhoff = psrc->_kirchhoff;
+    _N = psrc->_N;
+    _A = psrc->_A;
+    _B = psrc->_B;
+    _elasticEnergy = psrc->_elasticEnergy;
+    _thermalEnergy = psrc->_thermalEnergy;                                                                              // Added _thermalEnergy
+    _irreversibleEnergy = psrc->_irreversibleEnergy;
+    _DirreversibleEnergyDF = psrc->_DirreversibleEnergyDF;
+  }
+  return *this;
+};
+
+void IPNonLinearTVM::restart() {
+  IPVariableMechanics::restart();
+  restartManager::restart(_elasticEnergy);
+  restartManager::restart(_N);
+  restartManager::restart(_A);
+  restartManager::restart(_B);
+  restartManager::restart(_Ee);
+  restartManager::restart(_kirchhoff);
+  restartManager::restart(_thermalEnergy);                                                                              // Added _thermalEnergy
+  restartManager::restart(_irreversibleEnergy);
+  restartManager::restart(_DirreversibleEnergyDF);
+};
+
+void IPNonLinearTVM::getViscoElasticStrain(int i, STensor3& Ev) const
+{
+  if (i > _A.size() or i < 1)
+  { 
+    Msg::Error("viscoelastic branch %d does not exist",i);
+  }
+  else
+  {
+    Ev = _A[i-1];
+    Ev(0,0) += _B[i-1]/3.;
+    Ev(1,1) += _B[i-1]/3.;
+    Ev(2,2) += _B[i-1]/3.;
+  }
+};
+*/
\ No newline at end of file
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVM.h b/NonLinearSolver/internalPoints/ipNonLinearTVM.h
new file mode 100644
index 0000000000000000000000000000000000000000..eaf813bf858edcdf691263e624f64477cb8b2589
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVM.h
@@ -0,0 +1,147 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVM (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef IPNONLINEARTVM_H_
+#define IPNONLINEARTVM_H_
+#include "ipHyperelastic.h"
+#include "j2IsotropicHardening.h"       
+#include "kinematicHardening.h"
+#include "STensor3.h"
+#include "STensor43.h"
+
+
+class IPNonLinearTVM : public IPHyperViscoElastic{
+    public:
+        // Temperature history (I think) - from IPLinearThermoMechanics.h (fracEnergy is unused w/o fracture - add and initialise it later)
+        double _thermalEnergy;                                                                                                               // Added _thermalEnergy
+        //  double _fracEnergy;
+        STensor3 _devDE;
+        double _trDE;
+        STensor3 _DE;
+        
+        // Viscoelastic Strain
+        std::vector<STensor3> _devGammai;   // dev viscoelastic strain for each branch
+        std::vector<double> _trGammai;      // tr viscoelastic strain for each branch
+        std::vector<STensor3> _devDGammaiDT;  
+        std::vector<double> _trDGammaiDT;     
+        
+        // Viscoelastic Stress
+        std::vector<STensor3> _devQi;   // dev viscoelastic stress for each branch
+        std::vector<double> _trQi;      // tr viscoelastic stress for each branch
+        
+        // Additional Internal Variables 
+        std::vector<STensor3> _C;           // dGi/dT summation
+        std::vector<double> _D;             // dKi/dT summation
+        std::vector<double> _E, _F, _G;
+        
+        // Additional variables
+        double _dtShift;
+        double _DdtShiftDT;
+        double _DDdtShiftDDT;
+        
+    public:
+        IPNonLinearTVM(const int N);
+        IPNonLinearTVM(const IPNonLinearTVM& src);
+        virtual IPNonLinearTVM& operator=(const IPVariable& src);
+        virtual ~IPNonLinearTVM(){};
+            
+        virtual std::vector<STensor3>& getRefToDevViscoElasticStrain() {return _devGammai;};
+        virtual const std::vector<STensor3>& getConstRefToDevViscoElasticStrain() const {return _devGammai;};
+        
+        virtual std::vector<double>& getRefToTrViscoElasticStrain() {return _trGammai;};
+        virtual const std::vector<double>& getConstRefToTrViscoElasticStrain() const {return _trGammai;};
+        
+        virtual std::vector<STensor3>& getRefToDevDGammaiDT() {return _devDGammaiDT;};
+        virtual const std::vector<STensor3>& getConstRefToDevDGammaiDT() const {return _devDGammaiDT;};
+        
+        virtual std::vector<double>& getRefToTrDGammaiDT() {return _trDGammaiDT;};
+        virtual const std::vector<double>& getConstRefToTrDGammaiDT() const {return _trDGammaiDT;};
+        
+        virtual std::vector<STensor3>& getRefToDevViscoElasticStress() {return _devQi;};
+        virtual const std::vector<STensor3>& getConstRefToDevViscoElasticStress() const {return _devQi;};
+        
+        virtual std::vector<double>& getRefToTrViscoElasticStress() {return _trQi;};
+        virtual const std::vector<double>& getConstRefToTrViscoElasticStress() const {return _trQi;};
+        
+        virtual double& getRefToTrDE() {return _trDE;};
+        virtual const double& getConstRefToTrDE() const {return _trDE;};
+        virtual STensor3& getRefToDevDE() {return _devDE;};
+        virtual const STensor3& getConstRefToDevDE() const {return _devDE;};
+        
+        virtual STensor3& getRefToDE() {return _DE;};
+        virtual const STensor3& getConstRefToDE() const {return _DE;};
+        
+        virtual double& getShiftedTimeStep() {return _dtShift;};
+        virtual const double& getConstShiftedTimeStep() const {return _dtShift;};
+        virtual double& getShiftedTimeStepTempDerivative() {return _DdtShiftDT;};
+        virtual const double& getConstShiftedTimeStepTempDerivative() const {return _DdtShiftDT;};
+        virtual double& getShiftedTimeStepTempDoubleDerivative() {return _DDdtShiftDDT;};
+        virtual const double& getConstShiftedTimeStepTempDoubleDerivative() const {return _DDdtShiftDDT;};
+        
+        virtual double defoEnergy() const;
+        // virtual double plasticEnergy() const;                                                // CHANGE this later
+        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)
+
+        virtual IPVariable* clone() const{return new IPNonLinearTVM(*this);};
+        virtual void restart();
+};
+#endif // IPNonLinearTVM.h
+
+/*
+class IPNonLinearTVM : public IPVariableMechanics{
+  public:
+    // ViscoElastic history
+    int _N;                             // number spring-Dashpot of element
+    std::vector<STensor3> _A;           // N elements
+    std::vector<double> _B;             // N elements
+    double _elasticEnergy;              // elastic energy stored
+    STensor3 _Ee;                       // elastic strain
+    STensor3 _kirchhoff;                // corotational Kirchhoff stress
+    
+    // Temperature history (I think) - from IPLinearThermoMechanics.h (fracEnergy is unused w/o fracture - add and initialise it later)
+    double _thermalEnergy;                                                                                                               // Added _thermalEnergy
+    //  double _fracEnergy;
+
+    double _irreversibleEnergy;
+    STensor3 _DirreversibleEnergyDF;
+
+  public:
+    IPNonLinearTVM(const int N);
+    IPNonLinearTVM(const IPNonLinearTVM& src);
+    virtual IPNonLinearTVM& operator=(const IPVariable& src);
+    virtual ~IPNonLinearTVM(){};
+    
+    virtual void getViscoElasticStrain(int i, STensor3& Ev) const;
+    
+    virtual STensor3& getRefToElasticStrain() {return _Ee;};
+    virtual const STensor3& getConstRefToElasticStrain() const {return _Ee;};
+
+    virtual STensor3& getRefToCorotationalKirchhoffStress() {return _kirchhoff;};
+    virtual const STensor3& getConstRefToCorotationalKirchhoffStress() const {return _kirchhoff;};
+
+    virtual double defoEnergy() const{return _elasticEnergy;}        
+    virtual double& getRefToElasticEnergy() {return _elasticEnergy;};
+    virtual double plasticEnergy() const{return 0.;}
+    
+    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)
+
+    virtual double irreversibleEnergy() const {return _irreversibleEnergy;};
+    virtual double & getRefToIrreversibleEnergy() {return _irreversibleEnergy;};
+
+    virtual STensor3& getRefToDIrreversibleEnergyDF() {return _DirreversibleEnergyDF;};
+    virtual const STensor3& getConstRefToDIrreversibleEnergyDF() const{return _DirreversibleEnergyDF;};
+
+    virtual IPVariable* clone() const{return new IPNonLinearTVM(*this);};
+    virtual void restart();
+};
+*/
\ No newline at end of file
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..97c878a547f7e4c43ab6d81cfe8eef0109c71076
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.cpp
@@ -0,0 +1,113 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVM (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "ipNonLinearTVP.h"
+
+IPNonLinearTVP::IPNonLinearTVP(const J2IsotropicHardening* comp, const J2IsotropicHardening* trac,
+                                const kinematicHardening* kin, const int N):IPNonLinearTVE(comp,trac,kin,N),
+                                _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.),
+                                _mechSrcTVP(0.),_DmechSrcTVPdT(0.),_DmechSrcTVPdF(0.),
+                                _dPlasticEnergyPartdT(0.),_dElasticEnergyPartdT(0.),_dViscousEnergyPartdT(0.)
+{
+    
+    _IsoHardForce.clear(); _dIsoHardForcedT.clear(); _dIsoHardForcedF.clear();
+    for (int i=0; i < 3; i++){
+      _IsoHardForce.push_back(0.);
+      _dIsoHardForcedT.push_back(0.);
+      _ddIsoHardForcedTT.push_back(0.);
+      STensor3 el(0.);
+      _dIsoHardForcedF.push_back(el);
+    }
+    
+};
+
+IPNonLinearTVP::IPNonLinearTVP(const IPNonLinearTVP& src):IPNonLinearTVE(src),
+                                _DgammaDT(src._DgammaDT),_DGammaDT(src._DGammaDT),_DGammaDF(src._DGammaDF),_DirreversibleEnergyDT(src._DirreversibleEnergyDT), 
+                                _IsoHardForce(src._IsoHardForce), _dIsoHardForcedT(src._dIsoHardForcedT), _dIsoHardForcedF(src._dIsoHardForcedF), 
+                                _ddIsoHardForcedTT(src._ddIsoHardForcedTT),
+                                _psiTVM(src._psiTVM), _DpsiTVMdT(src._DpsiTVMdT), _DDpsiTVMdTT(src._DDpsiTVMdTT),
+                                _mechSrcTVP(src._mechSrcTVP),_DmechSrcTVPdT(src._DmechSrcTVPdT),_DmechSrcTVPdF(src._DmechSrcTVPdF),
+                                _ModMandel(src._ModMandel), _DModMandelDT(src._DModMandelDT), _DbackSigDT(src._DbackSigDT), _DphiPDF(src._DphiPDF),
+                                _DModMandelDF(src._DModMandelDF), _DbackSigDF(src._DbackSigDF),
+                                _dPlasticEnergyPartdT(src._dPlasticEnergyPartdT),_dElasticEnergyPartdT(src._dElasticEnergyPartdT),
+                                _dViscousEnergyPartdT(src._dViscousEnergyPartdT)      
+{
+    
+};
+
+IPNonLinearTVP& IPNonLinearTVP::operator =(const IPVariable &source){
+  IPNonLinearTVE::operator=(source);
+  
+  const IPNonLinearTVP* ps = dynamic_cast<const IPNonLinearTVP*>(&source);
+  if (ps != NULL){
+      
+    _DgammaDT = ps->_DgammaDT;
+    _DGammaDT = ps->_DGammaDT;
+    _DGammaDF = ps->_DGammaDF;
+    _DirreversibleEnergyDT = ps->_DirreversibleEnergyDT;
+    _IsoHardForce = ps->_IsoHardForce;
+    _dIsoHardForcedT = ps->_dIsoHardForcedT;
+    _dIsoHardForcedF = ps->_dIsoHardForcedF;
+    _ddIsoHardForcedTT = ps->_ddIsoHardForcedTT;
+    _psiTVM = ps->_psiTVM;
+    _DpsiTVMdT = ps->_DpsiTVMdT;
+    _DDpsiTVMdTT = ps->_DDpsiTVMdTT;
+    _mechSrcTVP = ps->_mechSrcTVP;
+    _DmechSrcTVPdT = ps->_DmechSrcTVPdT;
+    _DmechSrcTVPdF = ps->_DmechSrcTVPdF;
+    _ModMandel = ps->_ModMandel;
+    _DModMandelDT = ps->_DModMandelDT;
+    _DModMandelDF = ps->_DModMandelDF;
+    _DbackSigDT = ps->_DbackSigDT;
+    _DbackSigDF = ps->_DbackSigDF;
+    _DphiPDF = ps->_DphiPDF;
+    _dPlasticEnergyPartdT = ps->_dPlasticEnergyPartdT;
+    _dElasticEnergyPartdT = ps->_dElasticEnergyPartdT;
+    _dViscousEnergyPartdT = ps->_dViscousEnergyPartdT;
+
+  }
+  return *this;
+};
+
+IPNonLinearTVP::~IPNonLinearTVP(){
+
+};
+
+
+void IPNonLinearTVP::restart() {
+  IPNonLinearTVE::restart();
+  restartManager::restart(_DgammaDT);
+  restartManager::restart(_DGammaDT);
+  restartManager::restart(_DGammaDF);
+  restartManager::restart(_DirreversibleEnergyDT);
+  restartManager::restart(_IsoHardForce);
+  restartManager::restart(_dIsoHardForcedT);
+  restartManager::restart(_dIsoHardForcedF);
+  restartManager::restart(_ddIsoHardForcedTT);
+  restartManager::restart(_psiTVM);
+  restartManager::restart(_DpsiTVMdT);
+  restartManager::restart(_DDpsiTVMdTT);
+  restartManager::restart(_mechSrcTVP);
+  restartManager::restart(_DmechSrcTVPdT);
+  restartManager::restart(_DmechSrcTVPdF);
+  restartManager::restart(_ModMandel);
+  restartManager::restart(_DModMandelDT);
+  restartManager::restart(_DModMandelDF);
+  restartManager::restart(_DbackSigDT);
+  restartManager::restart(_DbackSigDF);
+  restartManager::restart(_DphiPDF);
+  restartManager::restart(_dPlasticEnergyPartdT);
+  restartManager::restart(_dElasticEnergyPartdT);
+  restartManager::restart(_dViscousEnergyPartdT);
+  return;
+}
diff --git a/NonLinearSolver/internalPoints/ipNonLinearTVP.h b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
new file mode 100644
index 0000000000000000000000000000000000000000..7deb4ee21be3d96f7fc3c5c7dac93f5350588142
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipNonLinearTVP.h
@@ -0,0 +1,108 @@
+//
+// C++ Interface: Material Law
+//
+// Description: IPNonLinearTVE (IP Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#ifndef IPNONLINEARTVP_H_
+#define IPNONLINEARTVP_H_
+#include "ipNonLinearTVE.h"
+#include "j2IsotropicHardening.h"       
+#include "kinematicHardening.h"
+#include "STensor3.h"
+#include "STensor43.h"
+
+
+class IPNonLinearTVP : public IPNonLinearTVE{
+    
+    public:
+        double _DgammaDT; // DequivalentPlasticStrainDT
+        double _DGammaDT; 
+        double _DirreversibleEnergyDT; 
+        double _mechSrcTVP;
+        double _DmechSrcTVPdT;
+        std::vector<double> _IsoHardForce;
+        std::vector<double> _dIsoHardForcedT;
+        std::vector<double> _ddIsoHardForcedTT;
+        
+        double _psiTVM; // free energy - full TVM
+        double _DpsiTVMdT;
+        double _DDpsiTVMdTT; 
+        
+        STensor3 _DGammaDF;
+        STensor3 _ModMandel;
+        STensor3 _DModMandelDT;
+        STensor3 _DbackSigDT;
+        STensor3 _DmechSrcTVPdF;
+        std::vector<STensor3> _dIsoHardForcedF;
+        
+        STensor43 _DbackSigDF;
+        STensor43 _DModMandelDF;
+        STensor3 _DphiPDF; // need this for mechSrc
+
+        
+    protected:
+        double _dPlasticEnergyPartdT;
+        double _dElasticEnergyPartdT, _dViscousEnergyPartdT;
+    
+    public:
+        IPNonLinearTVP(const J2IsotropicHardening* comp,
+                    const J2IsotropicHardening* trac,
+                    const kinematicHardening* kin, const int N);
+        IPNonLinearTVP(const IPNonLinearTVP& src);
+        virtual IPNonLinearTVP& operator =(const IPVariable &source);
+        virtual ~IPNonLinearTVP();
+        
+        virtual STensor3& getRefToModifiedMandel() {return _ModMandel;};
+        virtual const STensor3& getConstRefToModifiedMandel() const {return _ModMandel;};
+        virtual STensor3& getRefToDModMandelDT() {return _DModMandelDT;};
+        virtual const STensor3& getConstRefToDModMandelDT() const {return _DModMandelDT;};
+        virtual STensor43& getRefToDModMandelDF() {return _DModMandelDF;};
+        virtual const STensor43& getConstRefToDModMandelDF() const {return _DModMandelDF;};
+        
+        /*virtual double &getRefToIsotropicHardeningForce() {return _IsoHardForce;}
+        virtual const double &getConstRefToIsotropicHardeningForce() const {return _IsoHardForce;}*/
+        
+        virtual double &getRefToFreeEnergyTVM() {return _psiTVM;}
+        virtual const double &getConstRefToFreeEnergyTVM() const {return _psiTVM;}
+        
+        virtual double &getRefToDDFreeEnergyTVMdTT() {return _DDpsiTVMdTT;}
+        virtual const double &getConstRefToDDFreeEnergyTVMdTT() const {return _DDpsiTVMdTT;}
+        
+        virtual double &getRefToMechSrcTVP() {return _mechSrcTVP;}
+        virtual const double &getConstRefToMechSrcTVP() const {return _mechSrcTVP;}
+        virtual double &getRefTodMechSrcTVPdT() {return _DmechSrcTVPdT;}
+        virtual const double &getConstRefTodMechSrcTVPdT() const {return _DmechSrcTVPdT;}
+        virtual STensor3 &getRefTodMechSrcTVPdF() {return _DmechSrcTVPdF;}
+        virtual const STensor3 &getConstRefTodMechSrcTVPdF() const {return _DmechSrcTVPdF;}
+        
+        virtual STensor3& getRefToDbackStressdT() {return _DbackSigDT;}
+        virtual const STensor3& getConstRefToDbackStressdT() const {return _DbackSigDT;}
+        virtual STensor43& getRefToDbackStressdF() {return _DbackSigDF;};
+        virtual const STensor43& getConstRefToDbackStressdF() const {return _DbackSigDF;};
+        
+        virtual STensor3& getRefToDphiPDF() {return _DphiPDF;}
+        virtual const STensor3& getConstRefToDphiPDF() const {return _DphiPDF;}
+        
+        virtual double &getRefToDElasticEnergyPartdT() {return _dElasticEnergyPartdT;}
+        virtual const double &getConstRefToDElasticEnergyPartdT() const {return _dElasticEnergyPartdT;}
+        virtual double &getRefToDViscousEnergyPartdT() {return _dViscousEnergyPartdT;}
+        virtual const double &getConstRefToDViscousEnergyPartdT() const {return _dViscousEnergyPartdT;}
+        
+        virtual double &getRefToDPlasticEnergyPartdT() {return _dPlasticEnergyPartdT;}
+        virtual const double &getConstRefToDPlasticEnergyPartdT() const {return _dPlasticEnergyPartdT;}
+        
+        virtual double& getRefToDIrreversibleEnergyDT() {return _DirreversibleEnergyDT;};
+        virtual const double& getConstRefToDIrreversibleEnergyDT() const{return _DirreversibleEnergyDT;};
+    
+        virtual IPVariable* clone() const{return new IPNonLinearTVP(*this);};
+        virtual void restart();
+    
+};
+
+#endif // IPNonLinearTVP.h
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/CMakeLists.txt b/NonLinearSolver/materialLaw/CMakeLists.txt
index 405bdc6b1d9c3ac2edbae20b82604bf6522fcea8..9da69791fd17edb91f649091ca268300272dc4f0 100644
--- a/NonLinearSolver/materialLaw/CMakeLists.txt
+++ b/NonLinearSolver/materialLaw/CMakeLists.txt
@@ -96,6 +96,9 @@ set(SRC
   mlawTFAMaterialLaws.cpp
   mlawNonLocalPorousWithFailure.cpp
   mlawLinearElecMagInductor.cpp
+  mlawNonLinearTVM.cpp
+  mlawNonLinearTVE.cpp
+  mlawNonLinearTVP.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 0ea6210aae3ca622c3473c7b116fc2a2dd2ba67c..877081750e1f8bee4339d3918a72a83d1e05e020 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;
+  double dR=0, ddR=0, intR=0, dRdT =0, ddRdTT=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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-------------------------------------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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -128,9 +128,10 @@ void PerfectlyPlasticJ2IsotropicHardening::hardening(double p0, const IPJ2Isotro
       ddR=0;
       intR=0.5*tol*p*p+getYield0(T)*p;
       dRdT=getDYield0DT(T);
+      ddRdTT=getDDYield0DTT(T);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------end
 J2IsotropicHardening * PerfectlyPlasticJ2IsotropicHardening::clone() const
@@ -216,7 +217,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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -244,12 +245,12 @@ void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHarde
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //--------------------------------------------------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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -302,7 +303,7 @@ void PowerLawJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHarde
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //--------------------------------------------------------------------------end
 J2IsotropicHardening * PowerLawJ2IsotropicHardening::clone() const
@@ -387,7 +388,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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -415,12 +416,12 @@ void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHa
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------------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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -451,17 +452,21 @@ void ExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHa
     }
 
     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)
     {
       dRdT=getDYield0DT(T);
+      ddRdTT=getDDYield0DTT(T);
     }
     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));
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 
@@ -553,7 +558,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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -577,7 +582,7 @@ void EnhancedExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Iso
 
     intR= ipvprev.getIntegR()+ R*(p-p0);
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------------added
 void EnhancedExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p,double T, IPJ2IsotropicHardening &ipv) const
@@ -676,7 +681,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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -696,12 +701,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------------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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -728,7 +733,7 @@ void ExponentialSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
       dRdT += dhdT*(1-tmp)+hT*(dhexpdT*p*tmp);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 
@@ -816,7 +821,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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -842,12 +847,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //----------------------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;
+  double dR=0, ddR=0, intR=0, dRdT=0, ddRdTT=0;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -885,7 +890,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //------------------------------end
@@ -938,7 +943,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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -963,13 +968,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //----------------------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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1006,7 +1011,7 @@ void MultipleSwiftJ2IsotropicHardening::hardening(double p0, const IPJ2Isotropic
       dRdT = DsigY1DT*pow(pp,_n1);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //------------------------------end
@@ -1115,7 +1120,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.;
+  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1143,13 +1148,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------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.;
+  double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1183,16 +1188,22 @@ void LinearExponentialJ2IsotropicHardening::hardening(double p0, const IPJ2Isotr
 
     if (p< tol){
       dRdT = getDYield0DT(T);
+      ddRdTT = getDDYield0DTT(T);
     }
     else{
       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));
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //----------------------------end
@@ -1245,7 +1256,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
     LinearExponentialJ2IsotropicHardening::hardening(p0,ipvprev,p,ipv);
   }
   else{
-    double dR=0, ddR=0, intR=0, dRdT = 0.;
+    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
     double R0 = getYield0();
     double R = R0;
     if (ipvprev.isSaturated()){
@@ -1263,7 +1274,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);
+    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
   }
 }
 //-----------------------------added
@@ -1273,7 +1284,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
     LinearExponentialJ2IsotropicHardening::hardening(p0,ipvprev,p,T,ipv);
   }
   else{
-    double dR=0, ddR=0, intR=0, dRdT = 0.;
+    double dR=0, ddR=0, intR=0, dRdT=0., ddRdTT=0.;
     double R0 = getYield0(T);
     double R = R0;
     if (ipvprev.isSaturated()){
@@ -1298,7 +1309,7 @@ void LinearExponentialFollowedBySwiftLawJ2IsotropicHardening::hardening(double p
       dRdT = getYield0(T)*pow(1+_h3*(p-_p3),_n3);
 
     }
-    ipv.set(R0,R,dR,ddR,intR,dRdT);
+    ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
   }
 }
 
@@ -1448,7 +1459,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.);
+  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.);
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1491,12 +1502,12 @@ void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const
       intR = ipvprev.getIntegR()+ R*(p-p0);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------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.);
+  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.);
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1544,26 +1555,35 @@ void LinearFollowedByExponentialJ2IsotropicHardening::hardening(double p0, const
     }
 
     double dh1dT=_h1*_temFunc_h1->getDiff(T);
+    double ddh1dTT=_h1*_temFunc_h1->getDoubleDiff(T);
     double dhexp2dT=_hexp2*_temFunc_hexp2->getDiff(T);
+    double ddhexp2dTT=_hexp2*_temFunc_hexp2->getDoubleDiff(T);
     double dh2dT=_h2*_temFunc_h2->getDiff(T);
+    double ddh2dTT=_h2*_temFunc_h2->getDoubleDiff(T);
     double dpexpdT=_pexp*_temFunc_pexp->getDiff(T);
+    double ddpexpdTT=_pexp*_temFunc_pexp->getDoubleDiff(T);
     if (p < 1.e-16){
       dRdT = getDYield0DT(T);
+      ddRdTT = getDDYield0DTT(T);
     }
     else if (p<=pexpT)
     {
        dRdT=getDYield0DT(T)+dh1dT*p;
+       ddRdTT=getDDYield0DTT(T)+ddh1dTT*p;
     }
     else if (p > _pexp and p<=_p3)
     {
        dRdT=getDYield0DT(T)+dh1dT*p+dh2dT*(1-exp(-hexp2T*(p-pexpT)))+h2T*(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*exp(-hexp2T*p);
+       dRdT=getDDYield0DTT(T)+ddh1dTT*p+ddh2dTT*(1-exp(-hexp2T*(p-pexpT)))+dh2dT*(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*exp(-hexp2T*p)
+            +dh2dT*(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*exp(-hexp2T*p)
+            +h2T*((ddhexp2dTT*(p-pexpT)-dhexp2dT*dpexpdT-dhexp2dT*dpexpdT-hexp2T*ddpexpdTT)*exp(-hexp2T*p)-(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*dhexp2dT*p*exp(-hexp2T*p));
     }
     else{
       Msg::Error("DRDT for p > %e has not been implemented",_p3);
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //----------------------------end
@@ -1675,7 +1695,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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1705,12 +1725,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------------------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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1744,19 +1764,27 @@ void LinearFollowedByPowerLawJ2IsotropicHardening::hardening(double p0, const IP
     }
 
     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 dpexpdT=_pexp*_temFunc_pexp->getDiff(T);
+    double ddpexpdTT=_pexp*_temFunc_pexp->getDoubleDiff(T);
     if(p<pexpT)
     {
       dRdT=getDYield0DT(T)+dh1dT*p;
+      ddRdTT=getDDYield0DTT(T)+ddh1dTT*p;
     }
     else
     {
-      dRdT=getDYield0DT(T)*(1+h1T*pexpT)*pow(p/pexpT,hexpT)+getYield0(T)*(1+dh1dT*pexpT+h1T*dpexpdT)*pow(p/pexpT,hexpT)+getYield0(T)*(1+h1T*pexpT)*((-dpexpdT/pexpT)*hexpT+log(p/pexpT)*dhexpdT)*pow(p/    pexpT,hexpT);
+      dRdT=getDYield0DT(T)*(1+h1T*pexpT)*pow(p/pexpT,hexpT)+getYield0(T)*(1+dh1dT*pexpT+h1T*dpexpdT)*pow(p/pexpT,hexpT)
+            +getYield0(T)*(1+h1T*pexpT)*((-dpexpdT/pexpT)*hexpT+log(p/pexpT)*dhexpdT)*pow(p/pexpT,hexpT);
+      // ddRdTT=getDDYield0DTT(T)*(1+h1T*pexpT)*pow(p/pexpT,hexpT)+getDYield0DT(T)*((dh1dT*pexpT+h1T*dpexpdT)*pow(p/pexpT,hexpT)
+       //             +(1+h1T*pexpT)*pow(p/pexpT,hexpT)*(dhexpdT*ln(p/pexpT)-hexpT/(p/pexpT)*(p/(pexpT*pexpT)*dpexpdT))); // 1st term lmao
+       // TBD
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //--------------------------------end
@@ -1795,7 +1823,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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   double R0 = getYield0();
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1828,12 +1856,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------------------------------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.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1852,6 +1880,7 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0,
       ddR = 0.;
       intR = getYield0(T)*p + 0.5*_H*p*p;
       dRdT = getDYield0DT(T);
+      ddRdTT = getDDYield0DTT(T);
     }
     else if ( p > _p1 and p <= _p2){
       R = sy1*pow(p/_p1,_n1);
@@ -1859,6 +1888,7 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0,
       ddR = dR*_n1/p - R*_n1/(p*p);
       intR = getYield0(T)*_p1 + 0.5*_H*_p1*_p1 + R*p/(_n1+1) - sy1*_p1/(_n1+1);
       dRdT = getDYield0DT(T)*pow(p/_p1,_n1);
+      ddRdTT = getDDYield0DTT(T)*pow(p/_p1,_n1);
     }
     else{
       R = sy2*pow(p/_p2,_n2);
@@ -1866,10 +1896,11 @@ void LinearFollowedByMultiplePowerLawJ2IsotropicHardening::hardening(double p0,
       ddR = dR*_n2/p - R*_n2/(p*p);
       intR = getYield0(T)*_p1 + 0.5*_H*_p1*_p1 + sy2*_p2/(_n1+1) - sy1*_p1/(_n1+1) + R*p/(_n2+1) - sy2*_p2/(_n2+1);
       dRdT = getDYield0DT(T)*pow(p/_p2,_n2);
+      ddRdTT = getDDYield0DTT(T)*pow(p/_p2,_n2);
     }
   }
 
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 
 }
 
@@ -1918,7 +1949,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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -1947,12 +1978,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening &ipvprev, double p, double T, IPJ2IsotropicHardening &ipv) const
 {
-  double dR=0., ddR=0., intR=0.,dRdT=0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
   double R0 = getYield0(T);
   double R = R0;
   if (ipvprev.isSaturated()){
@@ -1985,8 +2016,9 @@ void PolynomialJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
       Msg::Error("order %d is not implemented PolynomialJ2IsotropicHaderning::hardening",_order);
 
     dRdT = getDYield0DT(T);
+    dRdT = getDDYield0DTT(T);
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 };
 
 
@@ -2046,7 +2078,7 @@ void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardeni
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT = 0.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2059,14 +2091,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-------------------------------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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2083,9 +2115,11 @@ void TwoExpJ2IsotropicHaderning::hardening(double p0, const IPJ2IsotropicHardeni
     intR = yield0T*p +KT*(exp(p)+0.5*exp(-2.*p));
 
     double dKdT=_K*_temFunc_K->getDiff(T);
+    double ddKdTT=_K*_temFunc_K->getDoubleDiff(T);
     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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //-------------------------------------end
@@ -2165,7 +2199,7 @@ void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT = 0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2179,14 +2213,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //------------------------------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.;
+  double dR=0., ddR=0., intR=0., dRdT=0., ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2205,10 +2239,14 @@ void TanhJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHardening
     intR = yield0T*p +KT*p0T*log(cosh(p/p0T));
 
     double dKdT=_K*_temFunc_K->getDiff(T);
+    double ddKdTT=_K*_temFunc_K->getDoubleDiff(T);
     double dp0dT=_p0*_temFunc_p0->getDiff(T);
+    double ddp0dTT=_p0*_temFunc_p0->getDoubleDiff(T);
     dRdT=getDYield0DT(T)+dKdT*tanh(p/p0T)+KT*(1-th*th)*(-p*dp0dT/p0T/p0T);
+    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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //------------------------------------------end
@@ -2260,7 +2298,7 @@ void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
 {
   double R0 = getYield0();
   double R = R0;
-  double dR=0., ddR=0., intR=0.,dRdT = 0.;
+  double dR=0., ddR=0., intR=0.,dRdT=0., ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2276,14 +2314,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);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //------------------------------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.;
+  double dR=0., ddR=0., intR=0.,dRdT=0.,ddRdTT=0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2298,9 +2336,10 @@ void TanhSeriesJ2IsotropicHardening::hardening(double p0, const IPJ2IsotropicHar
       ddR += _K[i]*2.*th*(th*th-1.)/(_p0[i]*_p0[i]);
       intR += getYield0(T)*p +_K[i]*_p0[i]*log(cosh(p/_p0[i]));
       dRdT = getDYield0DT(T);
+      dRdT = getDDYield0DTT(T);
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //------------------------------------------end
@@ -2472,7 +2511,7 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
 {
   double R0 = getYield0();
   double R = R0;
-  double dR(0.), ddR(0.), intR(0.), dRdT(0.);
+  double dR(0.), ddR(0.), intR(0.), dRdT(0.), ddRdTT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2515,14 +2554,14 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
 
     }
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 //-----------------------------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.);
+  double dR(0.), ddR(0.), intR(0.),dRdT(0.),ddRdTT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -2574,23 +2613,32 @@ void LinearFollowedByExponentialFollowedByMultiplePowerLawJ2IsotropicHardening::
       intR += h2T*(p-pexpT) + h2T*(tmp-exp(0.)) *hexp2T;
     }
     double dh1dT=_h1*_temFunc_h1->getDiff(T);
+    double ddh1dTT=_h1*_temFunc_h1->getDoubleDiff(T);
     double dhexp2dT=_hexp2*_temFunc_hexp2->getDiff(T);
+    double ddhexp2dTT=_hexp2*_temFunc_hexp2->getDoubleDiff(T);
     double dh2dT=_h2*_temFunc_h2->getDiff(T);
+    double ddh2dTT=_h2*_temFunc_h2->getDoubleDiff(T);
     double dpexpdT=_pexp*_temFunc_pexp->getDiff(T);
+    double ddpexpdTT=_pexp*_temFunc_pexp->getDoubleDiff(T);
     if (p < 1.e-16){
       dRdT = getDYield0DT(T);
+      ddRdTT = getDDYield0DTT(T);
     }
     else if (p<=pexpT)
     {
        dRdT=getDYield0DT(T)+dh1dT*p;
+       ddRdTT=getDDYield0DTT(T)+ddh1dTT*p;
     }
     else
     {
        dRdT=getDYield0DT(T)+dh1dT*p+dh2dT*(1-exp(-hexp2T*(p-pexpT)))+h2T*(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*exp(-hexp2T*p);
+       ddRdTT=getDDYield0DTT(T)+ddh1dTT*p+ddh2dTT*(1-exp(-hexp2T*(p-pexpT)))+dh2dT*(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*exp(-hexp2T*p)
+              +dh2dT*((dhexp2dT*(p-pexpT)+hexp2T*(-dpexpdT))*exp(-hexp2T*(p-pexpT)))
+              +h2T*((ddhexp2dTT*(p-pexpT)-dhexp2dT*dpexpdT-dhexp2dT*dpexpdT-hexp2T*ddpexpdTT)*exp(-hexp2T*p)-(dhexp2dT*(p-pexpT)-hexp2T*dpexpdT)*dhexp2dT*p*exp(-hexp2T*p));
     }
 
   }
-  ipv.set(R0,R,dR,ddR,intR,dRdT);
+  ipv.set(R0,R,dR,ddR,intR,dRdT,ddRdTT);
 }
 
 //----------------------------end
diff --git a/NonLinearSolver/materialLaw/j2IsotropicHardening.h b/NonLinearSolver/materialLaw/j2IsotropicHardening.h
index 520bdb37c8bb6a1a6ecf0ef837f921b22ab4dc24..003d7507f1234c5e1bac28d2964e946f712f6f17 100644
--- a/NonLinearSolver/materialLaw/j2IsotropicHardening.h
+++ b/NonLinearSolver/materialLaw/j2IsotropicHardening.h
@@ -47,6 +47,7 @@ class J2IsotropicHardening{
   virtual double getYield0() const {return _yield0;}
   virtual double getYield0(double T) const {return _yield0*_temFunc_Sy0->getVal(T);}
   virtual double getDYield0DT(double T) const {return _yield0*_temFunc_Sy0->getDiff(T);}
+  virtual double getDDYield0DTT(double T) const {return _yield0*_temFunc_Sy0->getDoubleDiff(T);}
 
   virtual hardeningname getType() const=0;
   virtual void createIPVariable(IPJ2IsotropicHardening* &ipv) const=0;
diff --git a/NonLinearSolver/materialLaw/kinematicHardening.cpp b/NonLinearSolver/materialLaw/kinematicHardening.cpp
index d720401a558cd06189fc1f31f2b2609f32b0a1c4..92ca0d92d520c202330a01a6901cf07060ca2603 100644
--- a/NonLinearSolver/materialLaw/kinematicHardening.cpp
+++ b/NonLinearSolver/materialLaw/kinematicHardening.cpp
@@ -26,14 +26,23 @@ kinematicHardening& kinematicHardening::operator=(const kinematicHardening &sour
 
 
 PolynomialKinematicHardening::PolynomialKinematicHardening(const int num, int order,  bool init):
-kinematicHardening(num,init),_order(order){
-  _coefficients.resize(_order+1);
-  _coefficients.setAll(0.);
-  _coefficients(0) = 0.;
+  kinematicHardening(num,init),_order(order){
+      
+    _coefficients.resize(_order+1);
+    _coefficients.setAll(0.);
+    _coefficients(0) = 0.;
+    
+    _temFunc_K= new constantScalarFunction(1.);
 };
 
 PolynomialKinematicHardening::PolynomialKinematicHardening(const PolynomialKinematicHardening& src):
-  kinematicHardening(src), _order(src._order),_coefficients(src._coefficients){};
+  kinematicHardening(src), _order(src._order),_coefficients(src._coefficients){
+      
+    _temFunc_K = NULL;
+    if (src._temFunc_K != NULL){
+        _temFunc_K = src._temFunc_K->clone();
+    }
+};
 
 PolynomialKinematicHardening& PolynomialKinematicHardening::operator =(const kinematicHardening& src){
   kinematicHardening::operator=(src);
@@ -43,24 +52,47 @@ PolynomialKinematicHardening& PolynomialKinematicHardening::operator =(const kin
     _order = psrc->_order;
     _coefficients.resize(psrc->_coefficients.size());
     _coefficients.setAll(psrc->_coefficients);
+    
+    if (psrc->_temFunc_K != NULL){
+      if (_temFunc_K != NULL){
+        _temFunc_K->operator=(*psrc->_temFunc_K);
+      }
+      else{
+        _temFunc_K = psrc->_temFunc_K->clone();
+      }
+    }
   }
   return *this;
 };
 
+PolynomialKinematicHardening::~PolynomialKinematicHardening(){
+  if (_temFunc_K != NULL) {delete _temFunc_K; _temFunc_K = NULL;};
+};
+
 void PolynomialKinematicHardening::setCoefficients(const int i, const double val){
   _coefficients(i) = val;
 };
 
+void PolynomialKinematicHardening::setTemperatureFunction_K(const scalarFunction& Tfunc){
+  if (_temFunc_K != NULL) delete _temFunc_K;
+  _temFunc_K = Tfunc.clone();
+}
+
 void PolynomialKinematicHardening::createIPVariable(IPKinematicHardening* &ipv) const
 {
   if(ipv != NULL) delete ipv;
   ipv = new IPKinematicHardening();
 }
 
-void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const
+void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const
 {
+  double tol = 1.e-20;
+  double p = _p;
+  if (_p<tol){
+    p = tol; 
+  }  
   //_coefficients.print("_coefficients");
-  double R =0., dR=0., ddR=0.;
+  double R=0., dR=0., ddR=0., dRdT = 0., ddRddT = 0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -100,9 +132,70 @@ void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardeni
     else
       Msg::Error("order %d is not implemented PolynomialJ2IsotropicHaderning::hardening",_order);
   }
-  ipv.set(R,dR,ddR);
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
 }
 
+void PolynomialKinematicHardening::hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const
+{
+  double tol = 1.e-20;
+  double p = _p;
+  if (_p<tol){
+    p = tol; 
+  }
+  
+  //_coefficients.print("_coefficients");
+  double R=0., dR=0., ddR=0., dRdT=0., ddRddT=0.;
+  
+  if (ipvprev.isSaturated()){
+    R = ipvprev.getR();
+    dR = 0.;
+    ddR = 0.;
+    dRdT = 0.;
+    ddRddT = 0.;
+  }
+  else{
+    if (_order == 1){
+      R = _coefficients(0)+ _coefficients(1)*p;
+      dR = _coefficients(1);
+      ddR = 0.;
+    }
+    else if (_order == 2){
+      R = _coefficients(0)+ _coefficients(1)*p + _coefficients(2)*p*p;
+      dR = _coefficients(1)+2.*_coefficients(2)*p;
+      ddR = 2.*_coefficients(2);
+    }
+    else if (_order == 3){
+      R = _coefficients(0)+ _coefficients(1)*p + _coefficients(2)*p*p+_coefficients(3)*p*p*p;
+      dR = _coefficients(1)+2.*_coefficients(2)*p+ 3*_coefficients(3)*p*p;
+      ddR = 2.*_coefficients(2)+6.*_coefficients(3)*p;
+    }
+    else if (_order == 4){
+      R = _coefficients(0)+ _coefficients(1)*p + _coefficients(2)*p*p+_coefficients(3)*p*p*p+_coefficients(4)*p*p*p*p;
+      dR = _coefficients(1)+2.*_coefficients(2)*p+ 3*_coefficients(3)*p*p+4*_coefficients(4)*p*p*p;
+      ddR = 2.*_coefficients(2)+6.*_coefficients(3)*p+12.*_coefficients(4)*p*p;
+    }
+    else if (_order == 5){
+      double p2 = p*p;
+      double p3 = p2*p;
+      double p4 = p3*p;
+      double p5 = p4*p;
+      
+      R = _coefficients(0)+ _coefficients(1)*p + _coefficients(2)*p2+_coefficients(3)*p2+_coefficients(4)*p4+_coefficients(5)*p5;
+      dR = _coefficients(1)+2.*_coefficients(2)*p+ 3*_coefficients(3)*p2+4*_coefficients(4)*p3+5*_coefficients(5)*p4;
+      ddR = 2.*_coefficients(2)+6.*_coefficients(3)*p+12.*_coefficients(4)*p2+20*_coefficients(5)*p3;
+    }
+    else
+      Msg::Error("order %d is not implemented PolynomialJ2IsotropicHaderning::hardening",_order);
+  }
+  
+  R *= _temFunc_K->getVal(T);
+  dR *= _temFunc_K->getVal(T);
+  ddR *= _temFunc_K->getVal(T);
+  dRdT = R*_temFunc_K->getDiff(T);
+  ddRddT = R*_temFunc_K->getDoubleDiff(T);
+  
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
+}
 
 kinematicHardening * PolynomialKinematicHardening::clone() const
 {
@@ -138,7 +231,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.;
+  double dR=0., ddR=0., dRdT=0., ddRddT=0.;
   double R = 0.;
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
@@ -168,9 +261,16 @@ void PowerKinematicHardening::hardening(double p0, const IPKinematicHardening &i
       ddR = (_exp-1.)*dR/p;
     }
   }
-  ipv.set(R,dR,ddR);
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
 }
 
+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.;
+  
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
+}
 
 kinematicHardening * PowerKinematicHardening::clone() const
 {
@@ -204,7 +304,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.);
+  double R(0.), dR(0.), ddR(0.), dRdT(0.), ddRddT(0.);
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -216,9 +316,16 @@ void CoshKinematicHardening::hardening(double p0, const IPKinematicHardening &ip
     ddR = _K*cosh(p/_p0)/(_p0*_p0);
   }
 
-  ipv.set(R,dR,ddR);
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
 }
 
+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.;
+  
+  ipv.set(R,dR,ddR,dRdT,ddRddT);
+}
 
 kinematicHardening * CoshKinematicHardening::clone() const
 {
@@ -227,10 +334,20 @@ kinematicHardening * CoshKinematicHardening::clone() const
 
 
 exponentialKinematicHardeningLaw::exponentialKinematicHardeningLaw(const int num, const double KK, const double h, const double alp): kinematicHardening(num,true),
-  _K(KK),_h(h),_alpha(alp){};
+  _K(KK),_h(h),_alpha(alp){
+      
+    if(_K<0) Msg::Error("exponentialKinematicHardening: negative _K parameter");
+    _temFunc_K= new constantScalarFunction(1.);
+};
   
 exponentialKinematicHardeningLaw::exponentialKinematicHardeningLaw(const exponentialKinematicHardeningLaw& src): 
-      kinematicHardening(src), _K(src._K), _h(src._h),_alpha(src._alpha){};
+      kinematicHardening(src), _K(src._K), _h(src._h),_alpha(src._alpha){
+          
+    _temFunc_K = NULL;
+    if (src._temFunc_K != NULL){
+        _temFunc_K = src._temFunc_K->clone();
+    }
+};
 
 exponentialKinematicHardeningLaw& exponentialKinematicHardeningLaw::operator =(const kinematicHardening& src){
   kinematicHardening::operator =(src);
@@ -239,10 +356,28 @@ exponentialKinematicHardeningLaw& exponentialKinematicHardeningLaw::operator =(c
     _K = psrc->_K;
     _h = psrc->_h;
     _alpha = psrc->_alpha;
+    
+    if (psrc->_temFunc_K != NULL){
+      if (_temFunc_K != NULL){
+        _temFunc_K->operator=(*psrc->_temFunc_K);
+      }
+      else{
+        _temFunc_K = psrc->_temFunc_K->clone();
+      }
+    }
   }
   return *this;
 };
 
+exponentialKinematicHardeningLaw::~exponentialKinematicHardeningLaw(){
+  if (_temFunc_K != NULL) {delete _temFunc_K; _temFunc_K = NULL;};
+};
+
+void exponentialKinematicHardeningLaw::setTemperatureFunction_K(const scalarFunction& Tfunc){
+  if (_temFunc_K != NULL) delete _temFunc_K;
+  _temFunc_K = Tfunc.clone();
+}
+
 void exponentialKinematicHardeningLaw::createIPVariable(IPKinematicHardening* &ipv) const
 {
   if(ipv != NULL) delete ipv;
@@ -251,7 +386,8 @@ 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 R(0.), dR(0.), ddR(0.); 
+  double dRdT=0., ddRddT=0.; // added
   if (ipvprev.isSaturated()){
     R = ipvprev.getR();
     dR = 0.;
@@ -266,9 +402,34 @@ 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);
+  ipv.set(R,dR,ddR,dRdT,ddRddT); //added dRdT
 }
 
+// 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.); 
+  if (ipvprev.isSaturated()){
+    R = ipvprev.getR();
+    dR = 0.;
+    ddR = 0.;
+  }
+  else{
+    double term = -_h*pow(p,_alpha);
+    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);
+    
+    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);
+  }
+
+  ipv.set(R,dR,ddR,dRdT,ddRddT); //added dRdT
+} // 
 
 kinematicHardening * exponentialKinematicHardeningLaw::clone() const
 {
diff --git a/NonLinearSolver/materialLaw/kinematicHardening.h b/NonLinearSolver/materialLaw/kinematicHardening.h
index 297a1f8c6d52d236a06c1ef352dab5fafe52ac09..a6c7401261fe25dd99847a5dea9953e97449d1e8 100644
--- a/NonLinearSolver/materialLaw/kinematicHardening.h
+++ b/NonLinearSolver/materialLaw/kinematicHardening.h
@@ -12,6 +12,7 @@
 
 #include "ipKinematicHardening.h"
 #include "fullMatrix.h"
+#include "scalarFunction.h"
 
 class kinematicHardening {
   public:
@@ -32,7 +33,8 @@ class kinematicHardening {
     virtual void createIPVariable(IPKinematicHardening* &ipv) const=0;
     virtual void initLaws(const std::map<int,kinematicHardening*> &maplaw)=0;
     virtual const bool isInitialized() {return _initialized;}
-    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const=0;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const=0;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const=0;
     virtual kinematicHardening * clone() const=0;
   #endif
 
@@ -43,19 +45,22 @@ class PolynomialKinematicHardening : public kinematicHardening{
   protected:
     int _order; // order of polymonial
     fullVector<double> _coefficients; // coeff of polymonial _coefficients(0)+_coefficients(1)*eps+...
+    scalarFunction* _temFunc_K;
   #endif // SWIG
 
   public:
     PolynomialKinematicHardening(const int num, int order, bool init = true);
     void setCoefficients(const int i, const double val);
+    void setTemperatureFunction_K(const scalarFunction& Tfunc);
     #ifndef SWIG
-    virtual ~PolynomialKinematicHardening(){}
+    virtual ~PolynomialKinematicHardening();
     PolynomialKinematicHardening(const PolynomialKinematicHardening& src);
     virtual PolynomialKinematicHardening& operator =(const kinematicHardening& src);
     virtual hardeningname getType() const{return kinematicHardening::polynomialKinematicHardening; };
     virtual void createIPVariable(IPKinematicHardening* &ipv) const;
     virtual void initLaws(const std::map<int,kinematicHardening*> &maplaw) {}; //nothing now, we will see if we use the mapping
-    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const;
     virtual kinematicHardening * clone() const;
     #endif // SWIG
 };
@@ -74,7 +79,8 @@ class PowerKinematicHardening : public kinematicHardening{
     virtual hardeningname getType() const{return kinematicHardening::powerKinematicHardening; };
     virtual void createIPVariable(IPKinematicHardening* &ipv) const;
     virtual void initLaws(const std::map<int,kinematicHardening*> &maplaw) {}; //nothing now, we will see if we use the mapping
-    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const;
     virtual kinematicHardening * clone() const;
     #endif // SWIG
 };
@@ -93,7 +99,8 @@ class CoshKinematicHardening : public kinematicHardening{
     virtual hardeningname getType() const{return kinematicHardening::coshKinematicHardening; };
     virtual void createIPVariable(IPKinematicHardening* &ipv) const;
     virtual void initLaws(const std::map<int,kinematicHardening*> &maplaw) {}; //nothing now, we will see if we use the mapping
-    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const;
     virtual kinematicHardening * clone() const;
     #endif // SWIG
 };
@@ -102,18 +109,22 @@ class exponentialKinematicHardeningLaw : public kinematicHardening{
   // R = K*(1-exp(-h p^alp))
   protected:
     double _K, _h, _alpha;
+    scalarFunction* _temFunc_K;
     
   public:
     exponentialKinematicHardeningLaw(const int num, const double KK, const double h, const double alp);
+    void setTemperatureFunction_K(const scalarFunction& Tfunc);
+    
     #ifndef SWIG
-    virtual ~exponentialKinematicHardeningLaw(){}
+    virtual ~exponentialKinematicHardeningLaw();
     exponentialKinematicHardeningLaw(const exponentialKinematicHardeningLaw& src);
     virtual exponentialKinematicHardeningLaw& operator =(const kinematicHardening& src);
     virtual hardeningname getType() const{return kinematicHardening::exponentialKinematicHardening; };
     virtual void createIPVariable(IPKinematicHardening* &ipv) const;
     virtual void initLaws(const std::map<int,kinematicHardening*> &maplaw) {}; //nothing now, we will see if we use the mapping
-    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double p, IPKinematicHardening &ipv) const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, IPKinematicHardening &ipv) const;
     virtual kinematicHardening * clone() const;
+    virtual void hardening(double p0, const IPKinematicHardening &ipvprev, double _p, double T, IPKinematicHardening &ipv) const;
     #endif 
 };
 
diff --git a/NonLinearSolver/materialLaw/mlaw.h b/NonLinearSolver/materialLaw/mlaw.h
index 9b7f8094836ef693f7f47baaa4daa05433888850..dbd7b1bab43895ddfdd4c1a365bb41e51ca3e4d7 100644
--- a/NonLinearSolver/materialLaw/mlaw.h
+++ b/NonLinearSolver/materialLaw/mlaw.h
@@ -34,7 +34,7 @@ class materialLaw{
                  localDamagePowerYieldHyperWithFailure,nonLocalDamagePowerYieldHyperWithFailure,ElecSMP,
                  ThermalConducter,AnIsotropicTherMech, localDamageJ2Hyper,linearElastic,nonLocalDamageGursonThermoMechanics,
                  localDamageJ2SmallStrain,nonLocalDamageJ2SmallStrain,cluster,tfa,ANN, DMN, torchANN, LinearElecMagTherMech, LinearElecMagInductor, hyperviscoelastic,
-                 vevpmfh};
+                 nonlineartvm,nonlinearTVE,nonlinearTVP,vevpmfh};
 
 
  protected :
@@ -116,7 +116,7 @@ class materialLaw{
                                Msg::Error("constitutiveTFA not implemented for this material law");
                                Msg::Exit(0);
                             };
-                            
+
   virtual void constitutiveTFA_corr(
                             const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
@@ -133,7 +133,7 @@ class materialLaw{
                                Msg::Error("constitutiveTFA not implemented for this material law");
                                Msg::Exit(0);
                             };
-                            
+
   virtual void constitutiveTFA_incOri(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
                             const fullVector<double>& euler,
@@ -187,7 +187,7 @@ class materialLaw{
                             IPVariable *q1,             // current array of internal variable (in ipvcur on output),
                             STensor43 &Secant,         // tangents (output)
                             const bool stiff,            // if true compute the tangents
-                            STensor43* elasticTangent = NULL, 
+                            STensor43* elasticTangent = NULL,
                             const bool dSecant =false,
                             STensor63* dCsecdeps = NULL,
                             const bool Calg_compute =false,
@@ -205,7 +205,7 @@ class materialLaw{
                             IPVariable *q1,             // current array of internal variable (in ipvcur on output),
                             STensor43 &Secant,         // tangents (output)
                             const bool stiff,            // if true compute the tangents
-                            STensor43* elasticTangent = NULL, 
+                            STensor43* elasticTangent = NULL,
                             const bool dSecant =false,
                             STensor63* dCsecdeps = NULL,
                             const bool Calg_compute =false,
@@ -270,7 +270,7 @@ class materialLaw{
   virtual double getH(const IPVariable *q0, const IPVariable *q1) const {return 0.;};
   virtual double getPlasticEqStrainIncrement(const IPVariable *q0i, const IPVariable *q1i) const {return 0.;};
   virtual double getPlasticEqStrain(const IPVariable *qi) const {return 0.;};
-  virtual bool materialLawHasLocalOrientation() const {return false;} 
+  virtual bool materialLawHasLocalOrientation() const {return false;}
   virtual void getLocalOrientation(fullVector<double> &GaussP, fullVector<double> &vecEulerAngles) const
                             {
                                Msg::Error("getLocalOrientation not implemented for this material law");
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
index 60d192e0a37cbde0b9464e1a5ab9ae1b2ae07238..4096527b46682f9bd4c21986b1e5a1a1fb5536ef 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
@@ -109,7 +109,7 @@ double mlawHyperViscoElastic::deformationEnergy(const IPHyperViscoElastic& q) co
     for (int i=0; i<_N; i++){
       static STensor3 devEebranch;
       Psy += _Ki[i]*0.5*(q._B[i])*(q._B[i])+_Gi[i]*STensorOperation::doubledot(q._A[i],q._A[i]);
-    }    
+    }
   }
   else if (_viscoMethod == KelvinVoight)
   {
@@ -153,7 +153,7 @@ double mlawHyperViscoElastic::viscousEnergy(const IPHyperViscoElastic& q0,const
       dtrq*=_Ki[i]*3.;
       DViscous+=  STensorOperation::doubledot(q._A[i],dqdev);
       DViscous+= q._B[i]*dtrq/3.;
-    }    
+    }
   }
   //else
   //{
@@ -166,7 +166,7 @@ double mlawHyperViscoElastic::viscousEnergy(const IPHyperViscoElastic& q0,const
 
 
 void mlawHyperViscoElastic::dViscousEnergydF(const IPHyperViscoElastic& q0, const IPHyperViscoElastic& q,  const STensor43 &dlnCdC, const STensor3 &Fe, STensor3 &dViscousEnergydF) const
-{   
+{
   static STensor3 dDeltaViscousdEve;
   STensorOperation::zero(dDeltaViscousdEve);
   STensorOperation::zero(dViscousEnergydF);
@@ -180,10 +180,10 @@ void mlawHyperViscoElastic::dViscousEnergydF(const IPHyperViscoElastic& q0, cons
     for (int i=0; i<_N; i++)
     {
       double dtg = dt/(_gi[i]);
-      double ratiog=exp(-dtg/2.);      
+      double ratiog=exp(-dtg/2.);
       double dtk = dt/(_ki[i]);
-      double ratiok=exp(-dtk/2.);      
-      
+      double ratiok=exp(-dtk/2.);
+
       static STensor3 dqdev, GA2;
       dqdev = devEe;
       dqdev -= q._A[i];
@@ -231,14 +231,14 @@ void mlawHyperViscoElastic::dViscousEnergydF(const IPHyperViscoElastic& q0, cons
 mlawHyperViscoElastic::mlawHyperViscoElastic(const int num,const double E,const double nu, const double rho,
                           const bool matrixbyPerturbation, const double pert):
     materialLaw(num,true), _E(E),_nu(nu),_rho(rho),_tangentByPerturbation(matrixbyPerturbation),_perturbationfactor(pert),
-    _viscoMethod(Maxwell),_N(0.),_order(1),_Ki(0),_ki(0),_Gi(0),_gi(0), _I4(1.,1.), _I(1.)  
+    _viscoMethod(Maxwell),_N(0.),_order(1),_Ki(0),_ki(0),_Gi(0),_gi(0), _I4(1.,1.), _I(1.)
 {
    _Idev = _I4;
    STensor3 mIon3(-1./3);
    STensor43 mIIon3;
    tensprod(_I,mIon3, mIIon3);
    _Idev += mIIon3;
-   
+
   _lambda = (E*nu)/(1.+nu)/(1.-2.*nu);
   _mu = 0.5*E/(1.+nu);
   _K = E/3./(1.-2.*nu);
@@ -279,6 +279,21 @@ mlawHyperViscoElastic::mlawHyperViscoElastic(const mlawHyperViscoElastic& src):
 
 };
 
+mlawHyperViscoElastic& mlawHyperViscoElastic::operator=(const materialLaw &source)
+{
+  materialLaw::operator=(source);
+  const mlawHyperViscoElastic* src =dynamic_cast<const mlawHyperViscoElastic*>(&source);
+  if(src != NULL)
+  {
+      _E = src->_E; _nu = src->_nu; _rho = src->_rho,
+      _lambda = src->_lambda; _mu = src->_mu; _K = src->_K; Cel = src->Cel;
+      _order = src->_order;
+      _tangentByPerturbation = src->_tangentByPerturbation; _perturbationfactor = src->_perturbationfactor;
+      _N = src->_N; _viscoMethod = src->_viscoMethod; _Ki = src->_Ki; _ki = src->_ki; _Gi = src->_Gi; _gi = src->_gi;
+  }
+  return *this;
+}
+
 double mlawHyperViscoElastic::soundSpeed() const
 {
   double factornu = (1.-_nu)/((1.+_nu)*(1.-2.*_nu));
@@ -571,13 +586,13 @@ void mlawHyperViscoElastic::predictorCorrector_ViscoElastic(const STensor3& F0,
 
 };
 
-void mlawHyperViscoElastic::constitutive(const STensor3& F0, 
+void mlawHyperViscoElastic::constitutive(const STensor3& F0,
                                          const STensor3& F, STensor3&P,
-                                         const IPVariable *q0i, 
+                                         const IPVariable *q0i,
                                          IPVariable *q1i,
-                                         STensor43& Tangent, 
+                                         STensor43& Tangent,
                                          const bool stiff,
-                                         STensor43* elasticTangent, 
+                                         STensor43* elasticTangent,
                                          const bool dTangent,
                                          STensor63* dCalgdeps) const{
 
@@ -606,7 +621,7 @@ void mlawHyperViscoElastic::constitutive(const STensor3& F0,
           }
           q1->getRefToDElasticEnergyPartdF()(i,j)=(qtemp.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/_perturbationfactor;
           q1->getRefToDViscousEnergyPartdF()(i,j)=(qtemp.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/_perturbationfactor;
- 
+
         }
       }
     }
@@ -677,7 +692,7 @@ void mlawPowerYieldHyper::tangent_full_perturbation(
       q1->getRefToDElasticEnergyPartdF()(i,j)=(q11.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/_perturbationfactor;
       q1->getRefToDViscousEnergyPartdF()(i,j)=(q11.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/_perturbationfactor;
       q1->getRefToDPlasticEnergyPartdF()(i,j)=(q11.getConstRefToPlasticEnergyPart()-q1->getConstRefToPlasticEnergyPart())/_perturbationfactor;
- 
+
     }
   }
 };
@@ -1234,10 +1249,10 @@ void mlawPowerYieldHyper::predictorCorrector_nonAssociatedFlow(const STensor3& F
     dDeformationEnergydF(*q1,  P, q1->getRefToDElasticEnergyPartdF(), Fp1, dFedF);
     dViscousEnergydF(*q0,  *q1,  DlnDCe, Fe, q1->getRefToDViscousEnergyPartdF(), dFedF);
     dPlasticEnergydF(N, Gamma, Dgamma, dKcorDcepr, DGDCepr, DdevNDCepr, DtrNDCepr, KS, CeprToF,q1->getRefToDPlasticEnergyPartdF());
-    
-    
+
+
     STensor3& DirrEnergDF = q1->_DirreversibleEnergyDF;
-    
+
     if (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DEFO_ENERGY){
       DirrEnergDF=q1->getConstRefToDElasticEnergyPartdF();
     }
@@ -1284,7 +1299,7 @@ void mlawPowerYieldHyper::dViscousEnergydF(const IPHyperViscoElastoPlastic& q0,
       {
         for(int L=0; L<3; L++)
         {
-          dViscousEnergydF(i,J)+=dViscousEnergyPartdFe(k,L)*dFedF(k,L,i,J);  
+          dViscousEnergydF(i,J)+=dViscousEnergyPartdFe(k,L)*dFedF(k,L,i,J);
         }
       }
     }
@@ -1910,6 +1925,34 @@ mlawPowerYieldHyper::mlawPowerYieldHyper(const mlawPowerYieldHyper& src):mlawHyp
   if (src._kinematic) _kinematic = src._kinematic->clone();
 };
 
+mlawPowerYieldHyper& mlawPowerYieldHyper::operator=(const materialLaw& source){
+
+  mlawHyperViscoElastic::operator=(source);
+  const mlawPowerYieldHyper* src =dynamic_cast<const mlawPowerYieldHyper*>(&source);
+  if(src != NULL){
+
+    _tol = src->_tol;
+    _n = src->_n;
+    _nonAssociatedFlow = src->_nonAssociatedFlow;
+    _b = src->_b;
+    _p = src->_p;
+
+    if(_viscosity != NULL) delete _viscosity;
+    if (src->_viscosity != NULL){ _viscosity = src->_viscosity->clone();}
+
+    if(_compression != NULL) delete _compression;
+    if (src->_compression!=NULL){ _compression = src->_compression->clone();}
+
+    if(_traction != NULL) delete _traction;
+    if (src->_traction!=NULL){ _traction = src->_traction->clone();}
+
+    if(_kinematic != NULL) delete _kinematic;
+    if (src->_kinematic!=NULL){ _kinematic = src->_kinematic->clone();}
+
+  }
+  return *this;
+}
+
 mlawPowerYieldHyper::~mlawPowerYieldHyper(){
   if (_compression) delete _compression; _compression = NULL;
   if (_traction) delete _traction; _traction = NULL;
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.h b/NonLinearSolver/materialLaw/mlawHyperelastic.h
index 44a3f1e32afac20a752a22a2b1b58aec61b7e02e..89c1dd540423296e39289f82c2ed5e38e6fdef70 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.h
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.h
@@ -78,6 +78,7 @@ class mlawHyperViscoElastic : public materialLaw{
 
     #ifndef SWIG
     mlawHyperViscoElastic(const mlawHyperViscoElastic& src);
+    mlawHyperViscoElastic& operator=(const materialLaw& source);
     virtual ~mlawHyperViscoElastic(){};
 
     virtual matname getType() const{return materialLaw::hyperviscoelastic;}
@@ -105,7 +106,7 @@ class mlawHyperViscoElastic : public materialLaw{
             IPVariable *q1,             // updated array of internal variable (in ipvcur on output),
             STensor43 &Tangent,         // constitutive tangents (output)
             const bool stiff,          // if true compute the tangents
-            STensor43* elasticTangent = NULL, 
+            STensor43* elasticTangent = NULL,
             const bool dTangent =false,
             STensor63* dCalgdeps = NULL) const;
 
@@ -153,7 +154,7 @@ class mlawPowerYieldHyper : public mlawHyperViscoElastic{
     virtual void dViscousEnergydF(const IPHyperViscoElastoPlastic& q0,  const IPHyperViscoElastoPlastic& q,  const STensor43 &dlnCdC, const STensor3 &Fe, STensor3 &dViscousEnergydF, const STensor43 &dFedF) const;
     virtual void dPlasticEnergydF(const STensor3 &N, double Gamma, double Dgamma, const STensor43 &dKcorDcepr, const STensor3 &DGDCepr,
        const STensor43 &DdevNDCepr, const STensor3 &DtrNDCepr, const STensor3 &KS, const STensor43 &CeprToF, STensor3 &dPlasticEnergydF) const;
-    
+
     virtual void predictorCorrector_nonAssociatedFlow(const STensor3& F, const IPHyperViscoElastoPlastic *q0_, IPHyperViscoElastoPlastic *q1,
                             STensor3&P, const bool stiff, STensor43& Tangent,  STensor43& dFedF, STensor43& dFpdF) const;
 
@@ -194,6 +195,7 @@ class mlawPowerYieldHyper : public mlawHyperViscoElastic{
 
     #ifndef SWIG
     mlawPowerYieldHyper(const mlawPowerYieldHyper& src);
+    mlawPowerYieldHyper& operator=(const materialLaw& source);
     virtual ~mlawPowerYieldHyper();
 
     virtual materialLaw* clone() const{return new mlawPowerYieldHyper(*this);};
@@ -215,7 +217,7 @@ class mlawPowerYieldHyper : public mlawHyperViscoElastic{
             IPVariable *q1,             // updated array of internal variable (in ipvcur on output),
             STensor43 &Tangent,         // constitutive tangents (output)
             const bool stiff,          // if true compute the tangents
-            STensor43* elasticTangent = NULL, 
+            STensor43* elasticTangent = NULL,
             const bool dTangent =false,
             STensor63* dCalgdeps = NULL) const;
 
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..480e9295e495a01d55ea9e034bf5cfe9abf41003
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVE.cpp
@@ -0,0 +1,1876 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022;  <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "mlawHyperelastic.h"
+#include "STensorOperations.h"
+#include "nonLinearMechSolver.h"
+#include "mlawNonLinearTVE.h"
+
+// Constructor
+mlawNonLinearTVE::mlawNonLinearTVE(const int num,const double E,const double nu, const double rho, const double tol,
+                                    const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                                    const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
+     mlawPowerYieldHyper(num, E, nu, rho, tol, matrixbyPerturbation, pert),
+     _Tinitial(Tinitial),_scalarAlpha(Alpha),_scalarK(KThCon),_Cp(Cp),
+     _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig), _Alphai(0){
+
+  _G = _mu;
+
+  _Tref = 298.;
+  _TemFuncOpt = 0;                                                                     // To be discarded soon
+  _modelFlag = 1;         // For additional volumetric terms.
+  _testFlag = 1;          // To test double convolution.
+  _C1 = 0.;
+  _C2 = 0.;
+
+  // _scalarAlpha = 0.; _scalarK = 0.; _Cp = 0.;
+  _tensorAlpha = 0.;
+  _tensorAlpha(0,0)= _scalarAlpha; _tensorAlpha(1,1)= _scalarAlpha; _tensorAlpha(2,2)= _scalarAlpha;
+
+  // to be unifom in DG3D q = k' gradT with k'=-k instead of q=-kgradT
+  _tensorK = 0.;
+  _tensorK(0,0)= - _scalarK; _tensorK(1,1)= - _scalarK; _tensorK(2,2)= - _scalarK;
+
+  _temFunc_K = new constantScalarFunction(1.);
+  _temFunc_G = new constantScalarFunction(1.);
+  _temFunc_Alpha = new constantScalarFunction(1.);
+  _temFunc_KThCon = new constantScalarFunction(1.);
+  _temFunc_Cp = new constantScalarFunction(1.);
+
+};
+
+// Copy Constructor
+mlawNonLinearTVE::mlawNonLinearTVE(const mlawNonLinearTVE& src): mlawPowerYieldHyper(src),
+      _Tinitial(src._Tinitial),_scalarAlpha(src._scalarAlpha),_scalarK(src._scalarK),_Cp(src._Cp),
+      _thermalEstimationPreviousConfig(src._thermalEstimationPreviousConfig),_Alphai(src._Alphai){
+
+  _G = src._G;
+  _Tref = src._Tref;
+  _TemFuncOpt = src._TemFuncOpt;
+  _modelFlag = src._modelFlag;
+  _testFlag = src._testFlag;
+  _C1 = src._C1;
+  _C2 = src._C2;
+  _tensorAlpha = src._tensorAlpha;
+  _tensorK = src._tensorK;
+
+  _temFunc_K = NULL;                                                                    // bulk modulus
+  if (src._temFunc_K != NULL){ _temFunc_K = src._temFunc_K->clone();}
+
+  _temFunc_G = NULL;                                                                    // shear modulus
+  if (src._temFunc_G!=NULL){ _temFunc_G = src._temFunc_G->clone();}
+
+  _temFunc_Alpha = NULL;                                                                // thermal dilatation coeffecient
+  if (src._temFunc_Alpha!=NULL){ _temFunc_Alpha = src._temFunc_Alpha->clone();}
+
+  _temFunc_KThCon = NULL;                                                               // thermal conductivity
+  if (src._temFunc_KThCon!=NULL){ _temFunc_KThCon = src._temFunc_KThCon->clone();}
+
+  _temFunc_Cp = NULL;                                                                   // specific heat
+  if (src._temFunc_Cp!=NULL){ _temFunc_Cp = src._temFunc_Cp->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();}
+  }
+
+  _temFunc_Gi.resize(_N,NULL);                                                          // branch shear moduli
+  for(int i=0;i<_N;i++){
+    if (src._temFunc_Gi[i]!=NULL) {_temFunc_Gi[i] = src._temFunc_Gi[i]->clone();}
+  }
+
+  _temFunc_Alphai.resize(_N,NULL);                                                      // branch alpha
+  for(int i=0;i<_N;i++){
+    if (src._temFunc_Alphai[i]!=NULL) {_temFunc_Alphai[i] = src._temFunc_Alphai[i]->clone();}
+  }
+};
+
+
+mlawNonLinearTVE& mlawNonLinearTVE::operator=(const materialLaw& source){
+
+  mlawPowerYieldHyper::operator=(source);
+  const mlawNonLinearTVE* src =dynamic_cast<const mlawNonLinearTVE*>(&source);
+  if(src != NULL){
+
+      _Tinitial = src->_Tinitial; _scalarAlpha = src->_scalarAlpha; _scalarK = src->_scalarK; _Cp = src->_Cp;
+      _thermalEstimationPreviousConfig = src->_thermalEstimationPreviousConfig; _Alphai = src->_Alphai;
+
+    _G = src->_G;
+    _Tref = src->_Tref;
+    _TemFuncOpt = src->_TemFuncOpt;
+    _modelFlag = src->_modelFlag;
+    _testFlag = src->_testFlag;
+    _C1 = src->_C1;
+    _C2 = src->_C2;
+    _tensorAlpha = src->_tensorAlpha;
+    _tensorK = src->_tensorK;
+
+    if(_temFunc_K != NULL) delete _temFunc_K;                                                   // bulk modulus
+    if (src->_temFunc_K != NULL){ _temFunc_K = src->_temFunc_K->clone();}
+
+    if(_temFunc_G != NULL) delete _temFunc_G;                                                   // shear modulus
+    if (src->_temFunc_G!=NULL){ _temFunc_G = src->_temFunc_G->clone();}
+
+    if(_temFunc_Alpha != NULL) delete _temFunc_Alpha;                                           // thermal dilatation coeffecient
+    if (src->_temFunc_Alpha!=NULL){ _temFunc_Alpha = src->_temFunc_Alpha->clone();}
+
+    if(_temFunc_KThCon != NULL) delete _temFunc_KThCon;                                         // thermal conductivity
+    if (src->_temFunc_KThCon!=NULL){ _temFunc_KThCon = src->_temFunc_KThCon->clone();}
+
+    if(_temFunc_Cp != NULL) delete _temFunc_Cp;                                                 // specific heat
+    if (src->_temFunc_Cp!=NULL){ _temFunc_Cp = src->_temFunc_Cp->clone();}
+
+    for(int i=0;i<_temFunc_Ki.size();i++){                                                          // branch bulk moduli
+        if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+        _temFunc_Ki[i]=NULL;
+    }
+    _temFunc_Ki.resize(_N,NULL);
+    for(int i=0;i<_N;i++){
+        if (src->_temFunc_Ki[i]!=NULL)
+        _temFunc_Ki[i] = src->_temFunc_Ki[i]->clone();
+    }
+
+    for(int i=0;i<_temFunc_Gi.size();i++){                                                          // branch shear moduli
+        if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+        _temFunc_Gi[i]=NULL;
+    }
+    _temFunc_Gi.resize(_N,NULL);
+    for(int i=0;i<_N;i++){
+        if (src->_temFunc_Gi[i]!=NULL)
+        _temFunc_Gi[i] = src->_temFunc_Gi[i]->clone();
+    }
+
+    for(int i=0;i<_temFunc_Alphai.size();i++){                                                      // branch alpha
+        if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+        _temFunc_Alphai[i]=NULL;
+    }
+    _temFunc_Alphai.resize(_N,NULL);
+    for(int i=0;i<_N;i++){
+        if (src->_temFunc_Alphai[i]!=NULL)
+        _temFunc_Alphai[i] = src->_temFunc_Alphai[i]->clone();
+    }
+  }
+  return *this;
+}
+
+mlawNonLinearTVE::~mlawNonLinearTVE(){
+    if(_temFunc_K != NULL) delete _temFunc_K; _temFunc_K = NULL;                    // bulk modulus;
+    if(_temFunc_G != NULL) delete _temFunc_G; _temFunc_G = NULL;                    // shear modulus;
+    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;
+    for(int i=0;i<_temFunc_Ki.size();i++){
+        if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+        _temFunc_Ki[i]=NULL;
+    }
+    for(int i=0;i<_temFunc_Gi.size();i++){
+        if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+        _temFunc_Gi[i]=NULL;
+    }
+    for(int i=0;i<_temFunc_Alphai.size();i++){
+        if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+        _temFunc_Alphai[i]=NULL;
+    }
+};
+
+void mlawNonLinearTVE::setViscoElasticNumberOfElement(const int N){
+  _N = N;
+  Msg::Info("Numer of Spring/Dashpot for viscoelastic model: %d",_N);
+  _Ki.clear(); _ki.clear();
+  _Gi.clear(); _gi.clear();
+  _Alphai.clear();
+  _Ki.resize(_N,0.);
+  _ki.resize(_N,0.);
+  _Gi.resize(_N,0.);
+  _gi.resize(_N,0.);
+  _Alphai.resize(_N,0.);
+
+  // _temFunc_Ki and Gi need to be here to get initiated only if setViscoElasticNumberOfElement is called.
+  for(int i=0;i<_temFunc_Ki.size();i++){
+    if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+    _temFunc_Ki[i]=NULL;
+  }
+  _temFunc_Ki.resize(_N,NULL);
+  /*for(int i=0;i<_N;i++){
+    _temFunc_Ki[i] = new constantScalarFunction(1.);
+  }*/
+
+  for(int i=0;i<_temFunc_Gi.size();i++){
+    if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+    _temFunc_Gi[i]=NULL;
+  }
+  _temFunc_Gi.resize(_N,NULL);
+ /* for(int i=0;i<_N;i++){
+    _temFunc_Gi[i] = new constantScalarFunction(1.);
+  }*/
+
+  for(int i=0;i<_temFunc_Alphai.size();i++){
+    if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+    _temFunc_Alphai[i]=NULL;
+  }
+  _temFunc_Alphai.resize(_N,NULL);
+ /* for(int i=0;i<_N;i++){
+    _temFunc_Alphai[i] = new constantScalarFunction(1.);
+  }*/
+};
+
+void mlawNonLinearTVE::setViscoElasticData(const int i, const double Ei, const double taui){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    double KK = Ei/(3.*(1.-2.*_nu));
+    double GG = Ei/(2.*(1.+_nu));
+
+    _Ki[i-1] = KK;
+    _ki[i-1] = taui; // /(3.*(1.-2.*_nu));
+    _Gi[i-1] = GG;
+    _gi[i-1] = taui; // /(2.*(1.+_nu));
+    _Alphai[i-1] = 0.;
+
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.); // (1.*KK)
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.); // (1.*GG)
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.);
+
+    Msg::Info("setting: element=%d Ki= %e ki= %e, Gi= %e, gi= %e",i-1,KK,taui,GG,taui);
+  }
+};
+
+void mlawNonLinearTVE::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    double KK = Ei/(3.*(1.-2.*_nu));
+    double GG = Ei/(2.*(1.+_nu));
+    double AA = Alphai;
+
+    _Ki[i-1] = KK;
+    _ki[i-1] = taui;
+    _Gi[i-1] = GG;
+    _gi[i-1] = taui;
+    _Alphai[i-1] = AA;
+
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.); // (1.*KK)
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.); // (1.*GG)
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.*AA);
+
+    Msg::Info("setting: element=%d Ki= %e ki= %e, Gi= %e, gi= %e, Alphai= %e",i-1,KK,taui,GG,taui,Alphai);
+  }
+};
+
+void mlawNonLinearTVE::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Ki[i-1] = Ki;
+    _ki[i-1] = ki;
+    
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.);
+
+    // Msg::Info("setting: element=%d Ki = %e ki = %e, ",i-1,Ki,ki);
+  }
+};
+
+void mlawNonLinearTVE::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Gi[i-1] = Gi;
+    _gi[i-1] = gi;
+    _Alphai[i-1] = 0.;
+
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.);
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.);
+
+    // Msg::Info("setting: element=%d Gi = %e gi = %e, ",i-1,Gi,gi);
+  }
+};
+
+// This function is a mandatory definition in .py file currently ---> Make it so that you dont always have to define the vector ----- CHANGE!!
+void mlawNonLinearTVE::setViscoElasticData_Alpha(const int i, const double Alpha_i){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Alphai[i-1] = Alpha_i;
+
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.*Alpha_i);
+
+    Msg::Info("setting: element=%d Alphai = %e ",i-1,Alpha_i);
+  }
+};
+
+void mlawNonLinearTVE::setViscoElasticData(const std::string filename){
+  FILE* file = fopen(filename.c_str(),"r");
+  if (file == NULL) Msg::Error("file: %s does not exist",filename.c_str());
+  _Ki.clear(); _ki.clear();
+  _Gi.clear(); _gi.clear();
+  _N = 0;
+  Msg::Info("reading viscoelastic input data");
+
+  while (!feof(file)){
+    int ok = fscanf(file,"%d",&_N);
+    Msg::Info("Numer of Maxwell elements: %d",_N);
+    double KK, k, GG, g;
+
+    for (int i=0; i<_N; i++){
+      ok = fscanf(file,"%lf %lf %lf %lf",&KK,&k,&GG,&g);
+      _Ki.push_back(KK);
+      _ki.push_back(k);
+      _Gi.push_back(GG);
+      _gi.push_back(g);
+      Msg::Info("Maxwell element %d: K[%d] = %e, k[%d] = %e, G[%d] = %e, g[%d] = %e",
+                i,i,KK,i,k,i,GG,i,g);
+    }
+  }
+  fclose(file);
+};
+
+double mlawNonLinearTVE::ShiftFactorWLF(const double T, double *DaDT, double *DDaDDT) const{
+
+    double a_WLF = exp(- (_C1*(T - _Tref)) / (_C2 + T - _Tref) );
+
+    if(DaDT!=NULL){
+        *DaDT = 1/a_WLF * (_C1*_C2) / pow( (_C2 + T-_Tref) ,2);
+    }
+    if(DDaDDT!=NULL){
+        *DDaDDT = 1/a_WLF * (_C1*_C2) * (_C1*_C2 - 2*(_C2+ T-_Tref)) / pow( (_C2 + T-_Tref) ,4);
+    }
+    return a_WLF;
+}
+
+void mlawNonLinearTVE::shiftedTime(const double t, const double T0, const double T1, double *t_shift, double *Ddt_shiftDT, double *DDdt_shiftDT,
+                                    const int opt_time, const int opt_order) const{
+
+// Shift t -> t is either delta_t or t (final time).  This function returns either t^* or delta_t^*.
+
+// opt_time -> 0 or 1 (default), depending on full-step or mid-step integration approximation for shifted time step
+// opt_order -> 1 or 2 (default) or 4, order of Guassian quadrature  (1 doesnt work, 4 probably works)
+
+    double dt = this->getTimeStep();
+    double t1 = this->getTime();
+    double t0 = t1 - dt;
+
+    // Linearly Interpolate Temperture -> This means dT/dt is constant between tn and tn+1
+    double ts, t_x0, t_x1, t_x2 = 0.;
+    double t_x6, t_x7, t_x8, t_x9 = 0.;
+    if (opt_time == 0){
+        ts = 2;
+
+        t_x0 = (t1+t0)/2;
+
+        t_x1 = (t1+t0)/2 - dt/2 * (1/sqrt(3));
+        t_x2 = (t1+t0)/2 + dt/2 * (1/sqrt(3));
+
+        t_x6 = (t1+t0)/2 - dt/2 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x7 = (t1+t0)/2 + dt/2 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x8 = (t1+t0)/2 - dt/2 * sqrt(3/7 + 2/7*sqrt(6/5));
+        t_x9 = (t1+t0)/2 + dt/2 * sqrt(3/7 + 2/7*sqrt(6/5));
+    } else {
+        ts = 4;
+
+        t_x0 = (3*t1+t0)/4;
+
+        t_x1 = (3*t1+t0)/4 - dt/4 * (1/sqrt(3));
+        t_x2 = (3*t1+t0)/4 + dt/4 * (1/sqrt(3));
+
+        t_x6 = (3*t1+t0)/4 - dt/4 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x7 = (3*t1+t0)/4 + dt/4 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x8 = (3*t1+t0)/4 - dt/4 * sqrt(3/7 + 2/7*sqrt(6/5));
+        t_x9 = (3*t1+t0)/4 + dt/4 * sqrt(3/7 + 2/7*sqrt(6/5));
+    }
+
+    double T_x0 = linearInterpTemp(t_x0, t0, t1, T0, T1);
+    double T_x1 = linearInterpTemp(t_x1, t0, t1, T0, T1);
+    double T_x2 = linearInterpTemp(t_x2, t0, t1, T0, T1);
+    double T_x6 = linearInterpTemp(t_x6, t0, t1, T0, T1);
+    double T_x7 = linearInterpTemp(t_x7, t0, t1, T0, T1);
+    double T_x8 = linearInterpTemp(t_x8, t0, t1, T0, T1);
+    double T_x9 = linearInterpTemp(t_x9, t0, t1, T0, T1);
+    // double T_x1 = 1/dt*( (t_1 - t_x1) )*T_0 + 1/dt*( (t_x1 - t_0) )*T_1 ;
+    // double T_x2 = 1/dt*( (t_1 - t_x2) )*T_0 + 1/dt*( (t_x2 - t_0) )*T_1 ;
+
+    if (t_shift!=NULL){
+
+        // double a_T1 = ShiftFactorWLF(T1);
+
+        if (opt_order == 1){
+            // 1 point Gauss rule
+            double a_x0 = ShiftFactorWLF(T_x0);
+            *t_shift = t/ts * (1/a_x0);
+        } else if (opt_order == 2){
+            // 2 point Gauss rule
+            double a_x1 = ShiftFactorWLF(T_x1);
+            double a_x2 = ShiftFactorWLF(T_x2);
+            *t_shift = t/ts * (1/a_x1 + 1/a_x2);
+        } else {
+            // 4 point Gauss rule
+            double a_x6 = ShiftFactorWLF(T_x6);
+            double a_x7 = ShiftFactorWLF(T_x7);
+            double a_x8 = ShiftFactorWLF(T_x8);
+            double a_x9 = ShiftFactorWLF(T_x9);
+            *t_shift = t/ts * (((18+sqrt(30))/36)*(1/a_x6 + 1/a_x7) + ((18-sqrt(30))/36)*(1/a_x8 + 1/a_x9));
+        }
+    }
+
+    if (Ddt_shiftDT!=NULL){
+
+        // double DaDT_T1 = 0.; double a_T1 = ShiftFactorWLF(T1,&DaDT_T1);
+
+        if (dt > 0.){
+            if (opt_order == 1){
+                // 1 point Gauss rule
+                double DaDT_x0 = 0.;
+                double a_x0 = ShiftFactorWLF(T_x0,&DaDT_x0);
+                *Ddt_shiftDT = t/ts * (DaDT_x0 * (t_x0-t0)/dt );
+            } else if (opt_order == 2){
+                // 2 point Gauss rule
+                double DaDT_x1, DaDT_x2 = 0.;
+                double a_x1 = ShiftFactorWLF(T_x1,&DaDT_x1);
+                double a_x2 = ShiftFactorWLF(T_x2,&DaDT_x2);
+                *Ddt_shiftDT = t/ts * (DaDT_x1 * (t_x1-t0)/dt + DaDT_x2 * (t_x2-t0)/dt);
+             } else {
+                // 4 point Gauss rule
+                double DaDT_x6, DaDT_x7, DaDT_x8, DaDT_x9 = 0.;
+                double a_x6 = ShiftFactorWLF(T_x6,&DaDT_x6);
+                double a_x7 = ShiftFactorWLF(T_x7,&DaDT_x7);
+                double a_x8 = ShiftFactorWLF(T_x8,&DaDT_x8);
+                double a_x9 = ShiftFactorWLF(T_x9,&DaDT_x9);
+                *Ddt_shiftDT = t/ts * ( ((18+sqrt(30))/36)*(DaDT_x6 * (t_x6-t0)/dt  + DaDT_x7 * (t_x7-t0)/dt ) +
+                                        ((18-sqrt(30))/36)*(DaDT_x8 * (t_x8-t0)/dt  + DaDT_x9 * (t_x9-t0)/dt ) );
+             }
+        } else { *Ddt_shiftDT = 0.;}
+    }
+
+    if (DDdt_shiftDT!=NULL){
+
+        // double DDaDT_T1 = 0.; double a_T1 = ShiftFactorWLF(T1,NULL,&DDaDT_T1);
+
+        if (dt > 0.){
+            if (opt_order == 1){
+                // 1 point Gauss rule
+                double DDaDT_x0 = 0.;
+                double a_x0 = ShiftFactorWLF(T_x0,NULL,&DDaDT_x0);
+                *DDdt_shiftDT = t/ts * ( DDaDT_x0 * pow( ((t_x0-t0)/dt) ,2 ) );
+            } else if (opt_order == 2){
+                // 2 point Gauss rule
+                double DDaDT_x1, DDaDT_x2 = 0.;
+                double a_x1 = ShiftFactorWLF(T_x1,NULL,&DDaDT_x1);
+                double a_x2 = ShiftFactorWLF(T_x2,NULL,&DDaDT_x2);
+                *DDdt_shiftDT = t/ts * ( DDaDT_x1 * pow( ((t_x1-t0)/dt) ,2 ) + DDaDT_x2 * pow( ((t_x2-t0)/dt) ,2 ) );
+            } else {
+                // 4 point Gauss rule
+                double DDaDT_x6, DDaDT_x7, DDaDT_x8, DDaDT_x9 = 0.;
+                double a_x6 = ShiftFactorWLF(T_x6,NULL,&DDaDT_x6);
+                double a_x7 = ShiftFactorWLF(T_x7,NULL,&DDaDT_x7);
+                double a_x8 = ShiftFactorWLF(T_x8,NULL,&DDaDT_x8);
+                double a_x9 = ShiftFactorWLF(T_x9,NULL,&DDaDT_x9);
+                *Ddt_shiftDT = t/ts * ( ((18+sqrt(30))/36)*( DDaDT_x6 * pow( (t_x6-t0)/dt, 2 ) + DDaDT_x7 * pow( (t_x7-t0)/dt, 2 )) +
+                                        ((18-sqrt(30))/36)*( DDaDT_x8 * pow( (t_x8-t0)/dt, 2 ) + DDaDT_x9 * pow( (t_x9-t0)/dt, 2 )) );
+            }
+        } else { *DDdt_shiftDT = 0.;}
+    }
+}
+
+
+double mlawNonLinearTVE::linearInterpTemp(const double t_interp, const double t0, const double t1, const double T0, const double T1) const{
+
+    // This function linearly interpolates temperature for the given intermediate time -> t_interp is tn + fraction of step (i.e., midstep = tn + 0.5*dt)
+        // Also, linear interp -> constant gradients
+    double dt = t1 - t0;
+    double T_interp;
+    if (dt > 0.){
+        T_interp = 1/dt*( (t1 - t_interp) )*T0 + 1/dt*( (t_interp - t0) )*T1;
+    }
+    else { T_interp = T0;}
+    return T_interp;
+}
+
+double mlawNonLinearTVE::setTemp(const double T0, const double T1, const int para) const{
+
+    double T_set = 0.;
+
+    if (para == 1){ // @T1
+        T_set = T1;
+
+    } else if (para == 2){ // @Tmid
+        double dt = this->getTimeStep();
+        double t1 = this->getTime();
+        double t0 = t1 - dt;
+        double t_mid = t1 - dt/2;
+        double T_mid = linearInterpTemp(t_mid, t0, t1, T0, T1);
+        T_set = T_mid;
+
+    } else if (para == 3){ // @Tmidshift
+        double dt = this->getTimeStep();
+        double t1 = this->getTime();
+        double dt_shift, t1_shift;
+        shiftedTime(dt,T0,T1,&dt_shift); shiftedTime(t1,T0,T1,&t1_shift);
+        double t0_shift = t1_shift - dt_shift;
+        double t_mid_shift = t1_shift - dt_shift/2;
+        double aT_0 = ShiftFactorWLF(T0);
+        double aT_1 = ShiftFactorWLF(T1);
+        double T_mid_shift = linearInterpTemp(t_mid_shift, t0_shift, t1_shift, T0, T1);
+        T_set = T_mid_shift;
+    }
+
+    return T_set;
+}
+
+double mlawNonLinearTVE::freeEnergyMechanical(const IPNonLinearTVE& q, const double Tc) 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 Psy_mech = 0.;
+
+    // Get trEe and devEe
+    double trEe;
+    static STensor3 devEe;
+    STensorOperation::decomposeDevTr(q._Ee,devEe,trEe);
+
+    // Get thermal strain
+    double Eth = 3.*AlphaT*(Tc-_Tinitial);
+
+    // Get Equilibrium freeEnergy_mech
+    Psy_mech = KT*0.5*(trEe-Eth)*(trEe-Eth) + GT*STensorOperation::doubledot(devEe,devEe);
+
+    // 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);
+
+        for (int i=0; i<_N; i++){
+            static STensor3 devEebranch;
+            devEebranch = devEe;
+
+            // 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);
+            }
+
+            Psy_mech += KiT[i]*0.5*(trEe-trGamma)*(trEe-trGamma) + GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
+        }
+    }
+
+    return Psy_mech;
+}
+
+void mlawNonLinearTVE::corKirInfinity( 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);
+    CorKirDevInf = 2*GT*devEe;
+    CorKirTrInf = KT*(trEe - 3*AlphaT*(T1-_Tinitial));
+}
+
+void mlawNonLinearTVE::getTVEdCorKirDT(const IPNonLinearTVE *q0, IPNonLinearTVE *q1, const double& T0, const double& T) const{
+                                          
+    // put DcorKirDT in the IP
+    STensor3& DcorKirDT = q1->getRefToDcorKirDT();
+    STensor3& DDcorKirDT = q1->getRefToDDcorKirDTT();
+    STensorOperation::zero(DcorKirDT); 
+    STensorOperation::zero(DDcorKirDT); 
+
+    // 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);
+    
+    // Add corKirinf terms to DcorKirDT
+    STensor3 corKirDevInf, devEe;
+    double corKirTrInf, trEe;
+    STensorOperation::decomposeDevTr(q1->_Ee,devEe,trEe);
+
+    // DEe
+    STensor3 DEe;
+    DEe = q1->_Ee;
+    DEe -= q0->_Ee;
+    q1->_DE = DEe;
+    STensor3& devDE = q1->getRefToDevDE();
+    double& trDE = q1->getRefToTrDE();
+    STensorOperation::decomposeDevTr(DEe,devDE,trDE);
+    
+    // Add Infinity terms
+    corKirInfinity( 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);
+        for (int j=0; j<3; j++){
+            DcorKirDT(i,j) += corKirDevInf(i,j)*DGDT/GT;
+            DDcorKirDT(i,j) += corKirDevInf(i,j)*DDGDT/GT;
+        }
+    }
+    
+        // Add visco terms
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+
+        // Update the Branch Moduli to the current temperature
+        std::vector<double> KiT, GiT, DKiDT, DGiDT, DDKiDT, DDGiDT;
+        KiT.resize(_N,0.);GiT.resize(_N,0.);DKiDT.resize(_N,0.);DGiDT.resize(_N,0.);DDKiDT.resize(_N,0.);DDGiDT.resize(_N,0.);
+
+        static STensor3 DOiDT;
+        static STensor3 DDOiDT;
+        static STensor3 DOGammaiDT;
+
+        static STensor3 DQiDT;
+        static STensor3 DDQiDT;
+        static STensor3 DDGammaiDT;
+
+        STensor3 DDOGammaiDT;
+        STensor3 DOGammai, Oi;
+        STensor3 DGammai, Qi;
+
+        const std::vector<STensor3>& devOi = q1->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi = q1->getConstRefToTrViscoElasticOverStress();
+        const std::vector<STensor3>& devOi_0 = q0->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi_0 = q0->getConstRefToTrViscoElasticOverStress();
+
+        const std::vector<STensor3>& devOGammai = q1->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai = q1->getConstRefToTrViscoElasticOverStrain();
+        const std::vector<STensor3>& devOGammai_0 = q0->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai_0 = q0->getConstRefToTrViscoElasticOverStrain();
+
+        std::vector<STensor3>& devDOGammaiDT = q1->getRefToDevDOGammaiDT();
+        std::vector<double>& trDOGammaiDT = q1->getRefToTrDOGammaiDT();
+        std::vector<STensor3>& devDOiDT = q1->getRefToDevDOiDT();
+        std::vector<double>& trDOiDT = q1->getRefToTrDOiDT();
+        std::vector<STensor3>& devDDOiDTT = q1->getRefToDevDDOiDTT();
+        std::vector<double>& trDDOiDTT = q1->getRefToTrDDOiDTT();
+
+        double dt_shift, Ddt_shiftDT, DDdt_shiftDT = 0.;
+        shiftedTime(this->getTimeStep(),T0,T,&dt_shift,&Ddt_shiftDT,&DDdt_shiftDT); // the convolution term with mid step approximation exponential
+        q1->_dtShift = dt_shift; q1->_DdtShiftDT = Ddt_shiftDT; q1->_DDdtShiftDDT = DDdt_shiftDT;
+
+        double dt_shift_rec, Ddt_shiftDT_rec, DDdt_shiftDT_rec = 0.;
+        shiftedTime(this->getTimeStep(),T0,T,&dt_shift_rec,&Ddt_shiftDT_rec,&DDdt_shiftDT_rec,0); // the recursive term exponential
+
+        double dtg,dtk,dtg2,dtk2,expdtk,expdtg,expdtkby2,expdtgby2 = 0.;
+
+        // Construct Oi, DOiDT and DDOiDT tensors
+        for (int i=0; i<_Gi.size(); i++){
+
+            dtk = dt_shift_rec/(_ki[i]); dtg = dt_shift_rec/(_gi[i]); expdtk = exp(-dtk); expdtg = exp(-dtg);
+
+            dtk2 = dt_shift/(_ki[i]); dtg2 = dt_shift/(_gi[i]);
+            expdtkby2 = exp(-dtk2); // exp(-dtk/2.);
+            expdtgby2 = exp(-dtg2); // exp(-dtk/2.);
+
+            STensorOperation::zero(Oi); STensorOperation::zero(DOiDT); STensorOperation::zero(DDOiDT);
+            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;
+            }
+
+            for (int j=0; j<3; j++){
+                
+                DOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*(-1/(_ki[i])) * Ddt_shiftDT ;
+                DOiDT(j,j) += trOi_0[i]*expdtk*(-1/(_ki[i])) * Ddt_shiftDT_rec ;
+
+                Oi(j,j) += trOi[i];
+                // Oi(j,j) -= T*DOiDT(j,j);
+                
+                DDOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*( (-1/(_ki[i])) * DDdt_shiftDT + (-1/(_ki[i]))*Ddt_shiftDT*(-1/(_ki[i]))*Ddt_shiftDT);
+                DDOiDT(j,j) += trOi_0[i]*expdtk*( (-1/(_ki[i])) * DDdt_shiftDT_rec + (-1/(_ki[i]))*Ddt_shiftDT_rec*(-1/(_ki[i]))*Ddt_shiftDT_rec);
+
+                DOGammai(j,j) += 1/3*trOGammai[i];
+                DOGammai(j,j) -= 1/3*trOGammai_0[i];
+
+                DOGammaiDT(j,j) += 1/3*(trOGammai[i]-trOGammai_0[i]*expdtk)*(-1/(_ki[i])* Ddt_shiftDT);
+                DOGammaiDT(j,j) += 1/3*trOGammai_0[i]*expdtk*(-1/(_ki[i])* Ddt_shiftDT_rec);
+
+                trDOGammaiDT[i] = DOGammaiDT(j,j);
+                DDOGammaiDT(j,j) = DOGammaiDT(j,j) - q0->_trDOGammaiDT[i];
+                
+                trDOiDT[i] = DOiDT(j,j);
+                trDDOiDTT[i] = DDOiDT(j,j);
+
+                for (int k=0; k<3; k++){
+                    
+                    DOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*(-1/(_gi[i])) * Ddt_shiftDT ;
+                    DOiDT(j,k) += devOi_0[i](j,k)*expdtg*(-1/(_gi[i])) * Ddt_shiftDT_rec ;
+
+                    Oi(j,k) += devOi[i](j,k);
+                    // Oi(j,k) -= T*DOiDT(j,k);
+
+                    DDOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*( (-1/(_gi[i])) * DDdt_shiftDT + (-1/(_gi[i]))*Ddt_shiftDT*(-1/(_gi[i]))*Ddt_shiftDT );
+                    DDOiDT(j,k) += devOi_0[i](j,k)*expdtg*( (-1/(_gi[i])) * DDdt_shiftDT_rec + (-1/(_gi[i]))*Ddt_shiftDT_rec*(-1/(_gi[i]))*Ddt_shiftDT_rec );
+
+                    DOGammai(j,k) += devOGammai[i](j,k);
+                    DOGammai(j,k) -= devOGammai_0[i](j,k);
+
+                    DOGammaiDT(j,k) += (devOGammai[i](j,k)-devOGammai_0[i](j,k)*expdtg)*(-1/(_gi[i])* Ddt_shiftDT);
+                    DOGammaiDT(j,k) += devOGammai_0[i](j,k)*expdtg*(-1/(_gi[i])* Ddt_shiftDT_rec);
+
+                    devDOGammaiDT[i](j,k) = DOGammaiDT(j,k);
+                    DDOGammaiDT(j,k) = DOGammaiDT(j,k) - q0->_devDOGammaiDT[i](j,k);
+                    
+                    devDOiDT[i](j,k) = DOiDT(j,k);
+                    devDDOiDTT[i](j,k) = DDOiDT(j,k);
+                }
+            }
+
+            // corKir Derivatives
+            DcorKirDT += DOiDT;
+            DDcorKirDT += DDOiDT;
+        }
+    }
+    
+    
+}
+
+void mlawNonLinearTVE::getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE *q1, const double& T0, const double& T, 
+                                        const double& DKDTsum, const double& DGDTsum, const STensor43& DEeDFe,
+                                        double *Wm, STensor3 *dWmdF, double *dWmdT) const{
+                                          
+    // I am stupid
+    double mechSrcTVE, dmechSrcTVEdT = 0.;
+    STensor3 dmechSrcTVEdE(0.);
+    STensor3 dmechSrcTVEdF(0.);
+    
+                                          
+    // Make Identity Tensors
+    static const STensor43 I4(1.,1.);
+                                          
+    // DcorKirDT from IP
+    const STensor3& DcorKirDT = q1->getRefToDcorKirDT();
+    const STensor3& DDcorKirDT = q1->getRefToDDcorKirDTT();
+
+    // Ee
+    static STensor3 devEe;
+    static double trEe;
+    STensorOperation::decomposeDevTr(q1->_Ee,devEe,trEe);
+
+    // DEe
+    static STensor3 DEe;
+    DEe = q1->_Ee;
+    DEe -= q0->_Ee;
+    q1->_DE = DEe;
+    const STensor3& devDE = q1->getConstRefToDevDE();
+    const double& trDE = q1->getConstRefToTrDE();
+    // STensorOperation::decomposeDevTr(DEe,devDE,trDE);
+
+    // Add visco terms
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+
+        // Update the Branch Moduli to the current temperature
+        std::vector<double> KiT, GiT, DKiDT, DGiDT, DDKiDT, DDGiDT;
+        KiT.resize(_N,0.);GiT.resize(_N,0.);DKiDT.resize(_N,0.);DGiDT.resize(_N,0.);DDKiDT.resize(_N,0.);DDGiDT.resize(_N,0.);
+
+        static STensor3 DOiDT;
+        static STensor3 DDOiDT;
+        static STensor3 DOGammaiDT;
+
+        static STensor3 DQiDT;
+        static STensor3 DDQiDT;
+        static STensor3 DDGammaiDT;
+
+        STensor3 DDOGammaiDT;
+        STensor3 DOGammai, Oi, temp_WmDQDE, temp_WmDGammaDE;
+        STensor3 DGammai, Qi, temp_WmDqDE, temp_WmDgammaDE;
+
+        const std::vector<STensor3>& devOi = q1->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi = q1->getConstRefToTrViscoElasticOverStress();
+        const std::vector<STensor3>& devOi_0 = q0->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi_0 = q0->getConstRefToTrViscoElasticOverStress();
+
+        const std::vector<STensor3>& devOGammai = q1->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai = q1->getConstRefToTrViscoElasticOverStrain();
+        const std::vector<STensor3>& devOGammai_0 = q0->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai_0 = q0->getConstRefToTrViscoElasticOverStrain();
+
+        const std::vector<STensor3>& devDOGammaiDT = q1->getConstRefToDevDOGammaiDT();
+        const std::vector<double>& trDOGammaiDT = q1->getConstRefToTrDOGammaiDT();
+        const std::vector<STensor3>& devDOiDT = q1->getConstRefToDevDOiDT();
+        const std::vector<double>& trDOiDT = q1->getConstRefToTrDOiDT();
+        const std::vector<STensor3>& devDDOiDTT = q1->getConstRefToDevDDOiDTT();
+        const std::vector<double>& trDDOiDTT = q1->getConstRefToTrDDOiDTT();
+
+        double dt_shift, Ddt_shiftDT, DDdt_shiftDT = 0.;
+        shiftedTime(this->getTimeStep(),T0,T,&dt_shift,&Ddt_shiftDT,&DDdt_shiftDT); // the convolution term with mid step approximation exponential
+        q1->_dtShift = dt_shift; q1->_DdtShiftDT = Ddt_shiftDT; q1->_DDdtShiftDDT = DDdt_shiftDT;
+
+        double dt_shift_rec, Ddt_shiftDT_rec, DDdt_shiftDT_rec = 0.;
+        shiftedTime(this->getTimeStep(),T0,T,&dt_shift_rec,&Ddt_shiftDT_rec,&DDdt_shiftDT_rec,0); // the recursive term exponential
+
+        double dtg,dtk,dtg2,dtk2,expdtk,expdtg,expdtkby2,expdtgby2 = 0.;
+
+        // Construct Oi, DOiDT and DDOiDT tensors
+        for (int i=0; i<_Gi.size(); i++){
+
+            dtk = dt_shift_rec/(_ki[i]); dtg = dt_shift_rec/(_gi[i]); expdtk = exp(-dtk); expdtg = exp(-dtg);
+
+            dtk2 = dt_shift/(_ki[i]); dtg2 = dt_shift/(_gi[i]);
+            expdtkby2 = exp(-dtk2); // exp(-dtk/2.);
+            expdtgby2 = exp(-dtg2); // exp(-dtk/2.);
+
+            STensorOperation::zero(Oi); STensorOperation::zero(DOiDT); STensorOperation::zero(DDOiDT);
+            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;
+            }
+
+            for (int j=0; j<3; j++){
+                
+                DOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*(-1/(_ki[i])) * Ddt_shiftDT ;
+                DOiDT(j,j) += trOi_0[i]*expdtk*(-1/(_ki[i])) * Ddt_shiftDT_rec ;
+
+                Oi(j,j) += trOi[i];
+                // Oi(j,j) -= T*DOiDT(j,j);
+                
+                DDOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*( (-1/(_ki[i])) * DDdt_shiftDT + (-1/(_ki[i]))*Ddt_shiftDT*(-1/(_ki[i]))*Ddt_shiftDT);
+                DDOiDT(j,j) += trOi_0[i]*expdtk*( (-1/(_ki[i])) * DDdt_shiftDT_rec + (-1/(_ki[i]))*Ddt_shiftDT_rec*(-1/(_ki[i]))*Ddt_shiftDT_rec);
+
+                DOGammai(j,j) += 1/3*trOGammai[i];
+                DOGammai(j,j) -= 1/3*trOGammai_0[i];
+
+                DOGammaiDT(j,j) += 1/3*(trOGammai[i]-trOGammai_0[i]*expdtk)*(-1/(_ki[i])* Ddt_shiftDT);
+                DOGammaiDT(j,j) += 1/3*trOGammai_0[i]*expdtk*(-1/(_ki[i])* Ddt_shiftDT_rec);
+
+                DDOGammaiDT(j,j) = DOGammaiDT(j,j) - q0->_trDOGammaiDT[i];
+        
+
+                for (int k=0; k<3; k++){
+                    
+                    DOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*(-1/(_gi[i])) * Ddt_shiftDT ;
+                    DOiDT(j,k) += devOi_0[i](j,k)*expdtg*(-1/(_gi[i])) * Ddt_shiftDT_rec ;
+
+                    Oi(j,k) += devOi[i](j,k);
+                    // Oi(j,k) -= T*DOiDT(j,k);
+
+                    DDOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*( (-1/(_gi[i])) * DDdt_shiftDT + (-1/(_gi[i]))*Ddt_shiftDT*(-1/(_gi[i]))*Ddt_shiftDT );
+                    DDOiDT(j,k) += devOi_0[i](j,k)*expdtg*( (-1/(_gi[i])) * DDdt_shiftDT_rec + (-1/(_gi[i]))*Ddt_shiftDT_rec*(-1/(_gi[i]))*Ddt_shiftDT_rec );
+
+                    DOGammai(j,k) += devOGammai[i](j,k);
+                    DOGammai(j,k) -= devOGammai_0[i](j,k);
+
+                    DOGammaiDT(j,k) += (devOGammai[i](j,k)-devOGammai_0[i](j,k)*expdtg)*(-1/(_gi[i])* Ddt_shiftDT);
+                    DOGammaiDT(j,k) += devOGammai_0[i](j,k)*expdtg*(-1/(_gi[i])* Ddt_shiftDT_rec);
+
+                    DDOGammaiDT(j,k) = DOGammaiDT(j,k) - q0->_devDOGammaiDT[i](j,k);
+                    
+                }
+            }
+
+            // Corrected Viscous Tensors
+            STensorOperation::zero(Qi); STensorOperation::zero(DQiDT); STensorOperation::zero(DDQiDT);
+            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]);
+                for (int k=0; k<3; k++){
+                    Qi(j,k) += (2*_Gi[i]*devEe(j,k) - devOi[i](j,k));
+                }
+            }
+            DGammai += DEe;
+            DGammai -= DOGammai;
+            Qi -= (T*DQiDT);
+            
+
+            // mechanicalSource - TVE contributions
+
+            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]);
+            isotropicHookTensor( Ki_term, Gi_term , temp_DDQiDTDE );
+
+            double Ki_term_2 = 1/3*expdtkby2;
+            double Gi_term_2 = 0.5*expdtgby2;
+            isotropicHookTensor( Ki_term_2, Gi_term_2, temp_DDgammiDtDE );
+            
+            STensorOperation::zero(temp_WmDqDE); STensorOperation::zero(temp_WmDgammaDE); 
+            
+            if (this->getTimeStep() > 0){
+                mechSrcTVE += (STensorOperation::doubledot(Qi,DGammai)/this->getTimeStep());         // viscoelastic heat  (added to mechSource)
+            
+                // dmechanicalSourceT
+                dmechSrcTVEdT -= (STensorOperation::doubledot(DDQiDT,DGammai))*T/this->getTimeStep();  // 1st Term
+                dmechSrcTVEdT -= (STensorOperation::doubledot(Qi,DOGammaiDT))/this->getTimeStep();      // 2nd Term
+
+                // dmechanicalSourceE
+                for (int l=0; l<3; l++){
+                  for (int m=0; m<3; m++){
+                    temp_WmDqDE(l,m) = 0.;
+                    for (int n=0; n<3; n++){
+                      for (int p=0; p<3; p++){
+                        temp_WmDqDE(l,m) += temp_DDQiDTDE(l,m,n,p)*DGammai(n,p)/this->getTimeStep();
+                      }
+                    }
+                  }
+                }
+
+                for (int l=0; l<3; l++){
+                  for (int m=0; m<3; m++){
+                    temp_WmDgammaDE(l,m) = 0.;
+                    for (int n=0; n<3; n++){
+                      for (int p=0; p<3; p++){
+                        temp_WmDgammaDE(l,m) += Qi(n,p)*I4(n,p,l,m)/this->getTimeStep();
+                        temp_WmDgammaDE(l,m) -= Qi(n,p)*temp_DDgammiDtDE(n,p,l,m)/this->getTimeStep();
+                      }
+                    }
+                  }
+                }
+
+                dmechSrcTVEdE += temp_WmDqDE;                  // 1st Term
+                dmechSrcTVEdE += temp_WmDgammaDE;              // 2nd Term
+
+            }
+        }
+    }
+               
+    if (this->getTimeStep() > 0){
+            mechSrcTVE += (STensorOperation::doubledot(DcorKirDT,DEe)*T/this->getTimeStep());    // thermoelastic heat   (added to mechSource)
+  
+            dmechSrcTVEdT += (STensorOperation::doubledot(DcorKirDT,DEe)/this->getTimeStep()); // 1st term
+            dmechSrcTVEdT += T*(STensorOperation::doubledot(DDcorKirDT,DEe)/this->getTimeStep()); // 2nd term
+            
+          // 1st term
+          static STensor3 CorKir_WmDE; STensorOperation::zero(CorKir_WmDE);
+          static STensor43 DDcorKirDTDE;
+          isotropicHookTensor(DKDTsum,DGDTsum,DDcorKirDTDE);
+            
+          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++){
+                  CorKir_WmDE(i,j) += DDcorKirDTDE(i,j,k,l)*DEe(k,l);
+                }
+              }
+            }
+          }
+
+          // 2nd term
+          static STensor3 DcorKirDT_I;
+          STensorOperation::multSTensor3STensor43(DcorKirDT,I4,DcorKirDT_I);
+            
+          for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+              dmechSrcTVEdE(i,j) += T*( CorKir_WmDE(i,j) + DcorKirDT_I(i,j) )/this->getTimeStep();
+            }
+          }
+    }
+    STensorOperation::multSTensor3STensor43(dmechSrcTVEdE,DEeDFe,dmechSrcTVEdF);
+        
+    if(Wm!=NULL){
+        *Wm = mechSrcTVE;
+    }
+    
+    if(dWmdT!=NULL){  
+        *dWmdT = dmechSrcTVEdT;
+    }
+    
+    if(dWmdF!=NULL){
+        *dWmdF = dmechSrcTVEdF;
+    }
+                                          
+};
+
+void mlawNonLinearTVE::ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPNonLinearTVE *q0, IPNonLinearTVE *q1,
+          double& Ke, double& Ge, double& Kde, double& Gde,
+          double& DKe, double& DGe, double& DKde, double& DGde,
+          double& KTsum, double& GTsum, double& DKDTsum, double& DGDTsum,
+          const double T0, const double T1, const bool calculateStress) const{
+
+    // Set Temperature to calculate temperature updated properties
+    double T_set = setTemp(T0,T1,1);  // 1->T1, 2->T_mid, 3->T_midshift
+
+    // 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);
+
+    // Get LogStrain
+    static STensor3 DE, devDE, devEe;
+    static double trDE, trEe;
+    DE =  Ee;
+    DE -= Ee0;
+    STensorOperation::decomposeDevTr(DE,devDE,trDE);
+    STensorOperation::decomposeDevTr(Ee,devEe,trEe);
+
+    // Initialise CorKirStress - Dev
+    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;
+
+
+    // Main Loop for Maxwell Branches
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+
+        // Get ShiftFactor and shifted time increment
+        double dt = this->getTimeStep();
+        double dt_shift_1, dt_shift_2 = 0.;
+        double Ddt_shiftDT, DDdt_shiftDT = 0.;
+        // dt_shift = dt;
+        shiftedTime(dt, T0, T1, &dt_shift_1,NULL,NULL,0);
+        shiftedTime(dt, T0, T1, &dt_shift_2,&Ddt_shiftDT,&DDdt_shiftDT);
+            // double aT_1 = ShiftFactorWLF(T1);
+
+        std::vector<double> KiT, GiT, AlphaiT_0, AlphaiT, DKiDT, DGiDT, DAlphaiDT, DDKiDT, DDGiDT;
+        KiT.resize(_N,0.); GiT.resize(_N,0.); AlphaiT_0.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.);
+
+        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);
+        }
+
+
+        // Dev Q_i
+        std::vector<STensor3>& devOi = q1->getRefToDevViscoElasticOverStress(); // devOi.resize(_N,0.);
+        std::vector<STensor3>& devOGammai = q1->getRefToDevViscoElasticOverStrain();
+
+        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(-dtg/2.);
+            double expdtgby2 = exp(-dtg2);
+
+            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;
+            }
+
+            // For Single Convolution
+            // Ge for DcorKirDE, DGe for DDcorKirDEDT (sort of)
+            Ge += GiT[i]*expdtgby2; // 2* (..) - Dont multiply by 2 if using lambda and mu in Hooks tensor function
+            DGe += DGiDT[i]*expdtgby2;
+
+            GTsum += GiT[i];
+            DGDTsum += DGiDT[i];
+
+            // For Double Convolutions
+            double temp_Gdi = 0.; // 0.25*DGiDT[i]*( expdtgby2 + 2*expdtg+ exp(-3*dtg/2.) );    // Gde for DcorKirDT
+            double temp_DGdi = 0.; // 0.25*DDGiDT[i]*( expdtgby2 + 2*expdtg + exp(-3*dtg/2.) ); // DGde
+
+            for (int k=0; k<3; k++){
+                for (int l=0; l<3; l++){
+
+                    // Single Convolution
+                    // q1->_A[i](k,l) = expdtg*q0->_A[i](k,l) + 2*GiT[i]*expdtgby2*devDE(k,l);
+                    q1->_A[i](k,l) = expdtg*q0->_A[i](k,l) + expdtgby2*devDE(k,l);
+
+                    // Double Convolution
+                    q1->_C[i](k,l) = expdtg*q0->_C[i](k,l) + 2*temp_Gdi*devDE(k,l)*(T1 - T0);
+
+                    // devOGammai[i](k,l) = devEe(k,l) - (q1->_A[i](k,l))/GiT[i];
+                    // devOGammai[i](k,l) = (q1->_A[i](k,l))/GiT[i];
+                    devOGammai[i](k,l) = (q1->_A[i](k,l));
+                }
+            }
+
+            Gde += temp_Gdi;
+            DGde += temp_DGdi;
+
+            devOi[i] = 2*GiT[i]*q1->_A[i]; // + q1->_C[i];
+            devK += devOi[i];
+         }
+
+
+        // Tr Q_i
+        std::vector<double>& trOi = q1 -> getRefToTrViscoElasticOverStress(); // trOi[i].resize(_N,0.);
+        std::vector<double>& trOGammai = q1 -> getRefToTrViscoElasticOverStrain();
+
+        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);
+            // double expdtkby2 = exp(-dtk/2.);
+
+            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;
+            }
+
+            // Single Convolution
+            Ke += KiT[i]*expdtkby2;
+            DKe += DKiDT[i]*expdtkby2;
+
+            KTsum += KiT[i]; DKDTsum += DKiDT[i];
+
+            // q1->_B[i] = expdtk*q0->_B[i] + KiT[i]*expdtkby2*trDE;
+            q1->_B[i] = expdtk*q0->_B[i] + expdtkby2*trDE;
+
+            // Double Convolution
+            double temp_Kdi = 0.; // 0.25*DKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) );   // For Kde
+            double temp_DKdi = 0.; // 0.25*DDKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) ); // For DKde
+
+            Kde += temp_Kdi; DKde += temp_DKdi;
+            q1->_D[i] = expdtk*q0->_D[i] + temp_Kdi*trDE*( T1 - T0 );
+
+
+            if (_modelFlag == 1){ // because for _modelFlag == 2, the equation for Oi changes.
+
+                trOi[i] = KiT[i]*q1->_B[i]; //+ q1->_D[i];
+
+                // trOGammai
+                // trOGammai[i] = trEe - (q1->_B[i])/KiT[i];
+                // trOGammai[i] = (q1->_B[i])/KiT[i];
+                trOGammai[i] = (q1->_B[i]);
+            }
+
+            if (_modelFlag == 2){ // additional volumetric terms
+
+                // Double Convolution
+                q1->_E[i] = expdtk*q0->_E[i] + 3*0.25*DKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) )*( (AlphaT-AlphaiT[i])*(T1-_Tinitial) - (AlphaT_0-AlphaiT_0[i])*(T0-_Tinitial) )*(T1 - T0);
+
+                // Single Convolution
+                q1->_F[i] = expdtk*q0->_F[i] + 3*KiT[i]*(T1-_Tinitial)*( DAlphaDT - DAlphaiDT[i] )*expdtkby2*(T1 - T0);
+                q1->_G[i] = expdtk*q0->_G[i] + 3*KiT[i]*( AlphaT - AlphaiT[i] )*expdtkby2*(T1 - T0);
+
+                trOi[i] = q1->_B[i] + q1->_D[i] - q1->_E[i] - q1->_F[i] - q1->_G[i];
+
+                // trOGammai
+                trOGammai[i] = trEe - ( 3*(AlphaT - AlphaiT[i])*(T1-_Tinitial) ) - (q1->_B[i]-q1->_F[i]-q1->_G[i])/KiT[i];
+            }
+
+            p += trOi[i];
+        }
+    }
+
+    if (calculateStress){
+        q1->_kirchhoff = devK;
+        q1->_kirchhoff(0,0) += p;
+        q1->_kirchhoff(1,1) += p;
+        q1->_kirchhoff(2,2) += p;
+    }
+
+}
+
+void mlawNonLinearTVE::isotropicHookTensor(const double K, const double G, STensor43& L) const{
+  double lambda = K - 2.*G/3.;
+  static STensor3 I(1.);
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      for (int k=0; k<3; k++){
+        for (int l=0; l<3; l++){
+          L(i,j,k,l) = lambda*I(i,j)*I(k,l)+ G*(I(i,k)*I(j,l)+I(i,l)*I(j,k));
+        }
+      }
+    }
+  }
+};
+
+
+void mlawNonLinearTVE::constitutive(const STensor3& F0,
+                                    const STensor3& F,
+                                    STensor3& P,
+                                    const IPVariable *q0i,
+                                    IPVariable *q1i,
+                                    STensor43& Tangent,
+                                    const bool stiff,
+                                    STensor43* elasticTangent,
+                                    const bool dTangent,
+                                    STensor63* dCalgdeps) const{
+
+  const IPNonLinearTVE *q0=dynamic_cast<const IPNonLinearTVE *>(q0i);
+  IPNonLinearTVE *q1 = dynamic_cast<IPNonLinearTVE *>(q1i);
+
+  double Tc = _Tref;
+  static SVector3 gradT, temp2;
+  static STensor3 temp3;
+  static STensor33 temp33;
+  static double tempVal;
+  static STensor43 dFpdF, dFedF;
+  static STensor3 dFpdT, dFedT, dGammadF;
+  double dGammadT;
+
+  if(elasticTangent!=NULL) Msg::Error("mlawNonLinearTVE elasticTangent not defined");
+  predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,_Tref,_Tref,gradT,gradT,temp2,temp3,temp3,temp2,temp33,tempVal,
+                      tempVal,temp3,tempVal,tempVal,temp3,stiff);
+};
+
+void mlawNonLinearTVE::constitutive(
+                            const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                            const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,                          // array of initial internal variable
+                                  IPVariable *q1i,                          // updated array of internal variable (in ipvcur on output),
+                                  STensor43& Tangent,                       // mechanical tangents (output)
+                            const double& T0,                               // previous temperature
+                            const double& T,                                // temperature
+                            const SVector3& gradT0,                         // previous temperature gradient
+                            const SVector3& gradT,                          // temperature gradient
+                                  SVector3& fluxT,                          // temperature flux
+                                  STensor3& dPdT,                           // mechanical-thermal coupling
+                                  STensor3& dfluxTdgradT,                   // thermal tengent
+                                  SVector3& dfluxTdT,
+                                  STensor33& dfluxTdF,                      // thermal-mechanical coupling
+                                  double& thermalSource,                    // - Cp*DTdt
+                                  double& dthermalSourcedT,                 // thermal source
+                                  STensor3& dthermalSourcedF,
+                                  double& mechanicalSource,                 // mechanical source --> convert to heat
+                                  double& dmechanicalSourcedT,
+                                  STensor3& dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const{
+
+  const IPNonLinearTVE *q0 = dynamic_cast<const IPNonLinearTVE *>(q0i);
+        IPNonLinearTVE *q1 = dynamic_cast<IPNonLinearTVE *>(q1i);
+  if(elasticTangent!=NULL) Msg::Error("mlawNonLinearTVE elasticTangent not defined");
+
+  if (!_tangentByPerturbation){
+    static STensor43 dFedF;
+    static STensor3 dFedT;
+    STensorOperation::unity(dFedF);
+    STensorOperation::zero(dFedT);
+    predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                      thermalSource,dthermalSourcedT,dthermalSourcedF,
+                      mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,stiff);
+  }
+   else{
+    predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,T0,T,gradT0,gradT,fluxT,thermalSource,mechanicalSource);
+
+    static STensor3 Fplus, Pplus;
+    static SVector3 fluxTPlus, gradTplus;
+    static double thermalSourcePlus;
+    static double mechanicalSourcePlus;
+    static IPNonLinearTVE qPlus(*q0);
+
+    // perturb F
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        Fplus = (F);
+        Fplus(i,j) += _perturbationfactor;
+        predictorCorrector_ThermoViscoElastic(F0,Fplus,Pplus,q0,&qPlus,T0,T,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus);
+        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);
+          }
+          dfluxTdF(k,i,j) = (fluxTPlus(k) - fluxT(k))/_perturbationfactor;
+        }
+        dthermalSourcedF(i,j) = (thermalSourcePlus - thermalSource)/_perturbationfactor;
+        dmechanicalSourceF(i,j) = (mechanicalSourcePlus - mechanicalSource)/_perturbationfactor;
+      }
+    }
+
+    // perturb gradT
+    double gradTpert = _perturbationfactor*T0/1e-3;
+    for (int i=0; i<3; i++){
+      gradTplus = (gradT);
+      gradTplus(i) += (gradTpert);
+      predictorCorrector_ThermoViscoElastic(F0,F,Pplus,q0,&qPlus,T0,T,gradT0,gradTplus,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus);
+      for (int k=0; k<3; k++){
+        dfluxTdgradT(k,i) = (fluxTPlus(k) - fluxT(k))/gradTpert;
+      }
+    }
+
+    // perturb on T
+    double Tplus = T+ _perturbationfactor*T0;
+    predictorCorrector_ThermoViscoElastic(F0,F,Pplus,q0,&qPlus,T0,Tplus,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus);
+    for (int k=0; k<3; k++){
+      for (int l=0; l<3; l++){
+        dPdT(k,l) = (Pplus(k,l) - P(k,l))/(_perturbationfactor*T0);
+      }
+      dfluxTdT(k) = (fluxTPlus(k) - fluxT(k))/(_perturbationfactor*T0);
+    }
+
+    dthermalSourcedT = (thermalSourcePlus - thermalSource)/(_perturbationfactor*T0);
+    dmechanicalSourcedT = (mechanicalSourcePlus - mechanicalSource)/(_perturbationfactor*T0);
+
+   }
+};
+
+void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVE *q0,                       // array of initial internal variables
+                                              IPNonLinearTVE *q1,                       // updated array of internal variables (in ipvcur on output),
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                              double& thermalSource,
+                                              double& mechanicalSource) const{
+  // temp variables
+  static STensor43 Tangent, dFedF;
+  static STensor3 dPdT, dfluxTdgradT, dthermalSourcedF, dmechanicalSourceF, dFedT;
+  static STensor33 dfluxTdF;
+  static SVector3 dfluxTdT;
+  static double dthermalSourcedT, dmechanicalSourcedT;
+  predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                      thermalSource,dthermalSourcedT,dthermalSourcedF,
+                      mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,false);
+}
+
+void mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVE *q0,                       // array of initial internal variables
+                                              IPNonLinearTVE *q1,                       // updated array of internal variableS (in ipvcur on output),
+                                              STensor43& Tangent,                       // mechanical tangents (output)
+                                              STensor43& dFedF,                         // elastic tangent
+                                              STensor3& dFedT,                          // elastic tangent
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                              STensor3& dPdT,                           // mechanical-thermal coupling
+                                              STensor3& dfluxTdgradT,                   // thermal tengent
+                                              SVector3& dfluxTdT,
+                                              STensor33& dfluxTdF,                      // thermal-mechanical coupling
+                                              double& thermalSource,                    // - Cp*dTdt
+                                              double& dthermalSourcedT,                 // thermal source
+                                              STensor3& dthermalSourcedF,
+                                              double& mechanicalSource,                 // mechanical source --> convert to heat
+                                              double& dmechanicalSourcedT,
+                                              STensor3& dmechanicalSourceF,
+                                        const bool stiff) const{
+
+   // const bool _thermalEstimationPreviousConfig(false);
+
+    // q1->_T = T; // CHANGE !!!
+    
+    // Get time step
+    double dt = this->getTimeStep();
+    double T_set = setTemp(T0,T,1);  // 1->T1, 2->T_mid, 3->T_midshift
+
+    // Make Identity Tensors
+    static const STensor3 I3(1.);
+    static const STensor43 I4(1.,1.);
+
+    // 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);
+
+    // Calculate/update Log Strain
+    static STensor3 C;
+    static STensor43 dlnCdC;
+    static STensor63 ddlnCddC;
+
+    STensor3& E = q1->getRefToElasticStrain();
+
+    STensorOperation::multSTensor3FirstTranspose(F,F,C);
+    if (_order == 1){
+        STensorOperation::logSTensor3(C,_order,E,&dlnCdC);  // as ddlogCddC = 0
+    }
+    else{
+        STensorOperation::logSTensor3(C,_order,E,&dlnCdC,&ddlnCddC);
+    }
+    E *= 0.5; // strain
+
+    // Stresses and Effective Moduli
+    double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
+    double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;  // double Wm = 0.;
+
+    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.;
+
+    const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
+    static STensor3 secondPK;
+    STensorOperation::multSTensor3STensor43(corKir,dlnCdC,secondPK);
+    STensorOperation::multSTensor3(F,secondPK,P);                  // 1st PK
+
+    // elastic energy
+    q1->_elasticEnergy = freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+
+    // thermal energy
+    q1->_thermalEnergy = CpT*T;
+
+
+    // fluxT
+    double J  = 1.;
+    STensor3 Finv(0.);
+    if (_thermalEstimationPreviousConfig){                                            // ADD  _thermalEstimationPreviousConfig
+        STensorOperation::inverseSTensor3(F0,Finv);
+        J = STensorOperation::determinantSTensor3(F0);
+    }
+    else{
+        STensorOperation::inverseSTensor3(F,Finv);
+        J = STensorOperation::determinantSTensor3(F);
+    }
+    static STensor3 Cinv;
+    STensorOperation::multSTensor3SecondTranspose(Finv,Finv,Cinv);
+    STensorOperation::multSTensor3SVector3(Cinv,gradT,fluxT);
+    fluxT *= (-KThConT*J);
+
+
+    // thermalSource
+    if (this->getTimeStep() > 0.){
+        thermalSource = -CpT*(T-T0)/this->getTimeStep();
+    }
+    else
+        thermalSource = 0.;
+
+
+    // mechanicalSource
+    mechanicalSource = 0.;
+    static STensor3 dmechanicalSourceE;
+
+    double T_temp = 0.;
+    if (_testFlag == 1 || _testFlag == 3) {T_temp = T0;} else if(_testFlag == 2) {T_temp = setTemp(T0,T,2);} // CHANGE the latter - case 2 of double convolution
+
+    // CorKir derivatives wrt T
+    static STensor3 DcorKirDT;
+    static STensor3 DDcorKirDT;    // for mech source derivatives
+    STensorOperation::zero(DcorKirDT);
+    STensorOperation::zero(DDcorKirDT);
+
+
+    // Add corKirinf terms to DcorKirDT
+    static STensor3 corKirDevInf, devEe;
+    static double corKirTrInf, trEe;
+    STensorOperation::decomposeDevTr(E,devEe,trEe);
+
+    static STensor3 DEe;
+    DEe = E;
+    DEe -= q0->_Ee;
+    q1->_DE = DEe;
+    STensor3& devDE = q1->getRefToDevDE();
+    double& trDE = q1->getRefToTrDE();
+    STensorOperation::decomposeDevTr(DEe,devDE,trDE);
+
+    corKirInfinity( devEe, trEe, T, corKirDevInf, corKirTrInf );
+
+    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
+        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);
+        for (int j=0; j<3; j++){
+            // DcorKirDT(i,j) += corKirDev(i,j)/(Ge+Gde*(T-T_temp))*(DGe + DGde*(T-T_temp)) ;                                         // 1st formulation
+            DcorKirDT(i,j) += corKirDevInf(i,j)*DGDT/GT;
+            DDcorKirDT(i,j) += corKirDevInf(i,j)*DDGDT/GT;
+        }
+    }
+
+    // Add visco terms
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+
+        // Update the Branch Moduli to the current temperature
+        std::vector<double> KiT, GiT, AlphaiT, DKiDT, DGiDT, DAlphaiDT, DDKiDT, DDGiDT, DDAlphaiDT;
+        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);
+        }
+
+        static STensor3 DOiDT;
+        static STensor3 DDOiDT;
+        static STensor3 DOGammaiDT;
+
+        static STensor3 DQiDT;
+        static STensor3 DDQiDT;
+        static STensor3 DDGammaiDT;
+
+        STensor3 DDOGammaiDT;
+        STensor3 DOGammai, Oi, temp_WmDQDE, temp_WmDGammaDE;
+        STensor3 DGammai, Qi, temp_WmDqDE, temp_WmDgammaDE;
+
+        const std::vector<STensor3>& devOi = q1->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi = q1->getConstRefToTrViscoElasticOverStress();
+        const std::vector<STensor3>& devOi_0 = q0->getConstRefToDevViscoElasticOverStress();
+        const std::vector<double>& trOi_0 = q0->getConstRefToTrViscoElasticOverStress();
+
+        const std::vector<STensor3>& devOGammai = q1->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai = q1->getConstRefToTrViscoElasticOverStrain();
+        const std::vector<STensor3>& devOGammai_0 = q0->getConstRefToDevViscoElasticOverStrain();
+        const std::vector<double>& trOGammai_0 = q0->getConstRefToTrViscoElasticOverStrain();
+
+        std::vector<STensor3>& devDOGammaiDT = q1->getRefToDevDOGammaiDT();
+        std::vector<double>& trDOGammaiDT = q1->getRefToTrDOGammaiDT();
+        std::vector<STensor3>& devDOiDT = q1->getRefToDevDOiDT();
+        std::vector<double>& trDOiDT = q1->getRefToTrDOiDT();
+        std::vector<STensor3>& devDDOiDTT = q1->getRefToDevDDOiDTT();
+        std::vector<double>& trDDOiDTT = q1->getRefToTrDDOiDTT();
+
+        double dt_shift, Ddt_shiftDT, DDdt_shiftDT = 0.;
+        shiftedTime(dt,T0,T,&dt_shift,&Ddt_shiftDT,&DDdt_shiftDT); // the convolution term with mid step approximation exponential
+        q1->_dtShift = dt_shift; q1->_DdtShiftDT = Ddt_shiftDT; q1->_DDdtShiftDDT = DDdt_shiftDT;
+
+        double dt_shift_rec, Ddt_shiftDT_rec, DDdt_shiftDT_rec = 0.;
+        shiftedTime(dt,T0,T,&dt_shift_rec,&Ddt_shiftDT_rec,&DDdt_shiftDT_rec,0); // the recursive term exponential
+
+        double dtg,dtk,dtg2,dtk2,expdtk,expdtg,expdtkby2,expdtgby2 = 0.;
+        
+        if(stiff){
+            dmechanicalSourcedT = 0;
+            STensorOperation::zero(dmechanicalSourceE); 
+        }
+
+        // Construct Oi, DOiDT and DDOiDT tensors
+        for (int i=0; i<_Gi.size(); i++){
+
+            dtk = dt_shift_rec/(_ki[i]); dtg = dt_shift_rec/(_gi[i]); expdtk = exp(-dtk); expdtg = exp(-dtg);
+
+            dtk2 = dt_shift/(_ki[i]); dtg2 = dt_shift/(_gi[i]);
+            expdtkby2 = exp(-dtk2); // exp(-dtk/2.);
+            expdtgby2 = exp(-dtg2); // exp(-dtk/2.);
+
+            STensorOperation::zero(Oi); STensorOperation::zero(DOiDT); STensorOperation::zero(DDOiDT);
+            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;
+            }
+
+            for (int j=0; j<3; j++){
+                
+                DOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*(-1/(_ki[i])) * Ddt_shiftDT ;
+                DOiDT(j,j) += trOi_0[i]*expdtk*(-1/(_ki[i])) * Ddt_shiftDT_rec ;
+
+                Oi(j,j) += trOi[i];
+                // Oi(j,j) -= T*DOiDT(j,j);
+                
+                DDOiDT(j,j) += (trOi[i]-trOi_0[i]*expdtk)*( (-1/(_ki[i])) * DDdt_shiftDT + (-1/(_ki[i]))*Ddt_shiftDT*(-1/(_ki[i]))*Ddt_shiftDT);
+                DDOiDT(j,j) += trOi_0[i]*expdtk*( (-1/(_ki[i])) * DDdt_shiftDT_rec + (-1/(_ki[i]))*Ddt_shiftDT_rec*(-1/(_ki[i]))*Ddt_shiftDT_rec);
+
+                DOGammai(j,j) += 1/3*trOGammai[i];
+                DOGammai(j,j) -= 1/3*trOGammai_0[i];
+
+                DOGammaiDT(j,j) += 1/3*(trOGammai[i]-trOGammai_0[i]*expdtk)*(-1/(_ki[i])* Ddt_shiftDT);
+                DOGammaiDT(j,j) += 1/3*trOGammai_0[i]*expdtk*(-1/(_ki[i])* Ddt_shiftDT_rec);
+
+                trDOGammaiDT[i] = DOGammaiDT(j,j);
+                DDOGammaiDT(j,j) = DOGammaiDT(j,j) - q0->_trDOGammaiDT[i];
+                
+                trDOiDT[i] = DOiDT(j,j);
+                trDDOiDTT[i] = DDOiDT(j,j);
+
+                for (int k=0; k<3; k++){
+                    
+                    DOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*(-1/(_gi[i])) * Ddt_shiftDT ;
+                    DOiDT(j,k) += devOi_0[i](j,k)*expdtg*(-1/(_gi[i])) * Ddt_shiftDT_rec ;
+
+                    Oi(j,k) += devOi[i](j,k);
+                    // Oi(j,k) -= T*DOiDT(j,k);
+
+                    DDOiDT(j,k) += (devOi[i](j,k)-devOi_0[i](j,k)*expdtg)*( (-1/(_gi[i])) * DDdt_shiftDT + (-1/(_gi[i]))*Ddt_shiftDT*(-1/(_gi[i]))*Ddt_shiftDT );
+                    DDOiDT(j,k) += devOi_0[i](j,k)*expdtg*( (-1/(_gi[i])) * DDdt_shiftDT_rec + (-1/(_gi[i]))*Ddt_shiftDT_rec*(-1/(_gi[i]))*Ddt_shiftDT_rec );
+
+                    DOGammai(j,k) += devOGammai[i](j,k);
+                    DOGammai(j,k) -= devOGammai_0[i](j,k);
+
+                    DOGammaiDT(j,k) += (devOGammai[i](j,k)-devOGammai_0[i](j,k)*expdtg)*(-1/(_gi[i])* Ddt_shiftDT);
+                    DOGammaiDT(j,k) += devOGammai_0[i](j,k)*expdtg*(-1/(_gi[i])* Ddt_shiftDT_rec);
+
+                    devDOGammaiDT[i](j,k) = DOGammaiDT(j,k);
+                    DDOGammaiDT(j,k) = DOGammaiDT(j,k) - q0->_devDOGammaiDT[i](j,k);
+                    
+                    devDOiDT[i](j,k) = DOiDT(j,k);
+                    devDDOiDTT[i](j,k) = DDOiDT(j,k);
+                }
+            }
+
+            // Corrected Viscous Tensors
+            STensorOperation::zero(Qi); STensorOperation::zero(DQiDT); STensorOperation::zero(DDQiDT);
+            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]);
+                for (int k=0; k<3; k++){
+                    Qi(j,k) += (2*_Gi[i]*devEe(j,k) - devOi[i](j,k));
+                }
+            }
+            DGammai += DEe;
+            DGammai -= DOGammai;
+            Qi -= (T*DQiDT);
+
+            // corKir Derivatives
+            DcorKirDT += DOiDT;
+            DDcorKirDT += DDOiDT;
+
+            // mechanicalSource - TVE contributions
+
+            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]);
+            isotropicHookTensor( Ki_term, Gi_term , temp_DDQiDTDE );
+
+            double Ki_term_2 = 1/3*expdtkby2;
+            double Gi_term_2 = 0.5*expdtgby2;
+            isotropicHookTensor( Ki_term_2, Gi_term_2, temp_DDgammiDtDE );
+
+            // For convenience -> Add the TVE Term here
+            STensorOperation::zero(temp_WmDqDE); STensorOperation::zero(temp_WmDgammaDE);
+
+            if (this->getTimeStep() > 0){
+
+                mechanicalSource += (STensorOperation::doubledot(Qi,DGammai)/this->getTimeStep()); // viscoelastic heat  (added to mechSource)
+
+                    if (stiff){
+
+                        // dmechanicalSourceT
+                        dmechanicalSourcedT -= (STensorOperation::doubledot(DDQiDT,DGammai))*T/this->getTimeStep();  // 1st Term
+                        dmechanicalSourcedT -= (STensorOperation::doubledot(Qi,DOGammaiDT))/this->getTimeStep();      // 2nd Term
+
+                        // dmechanicalSourceE
+                        for (int l=0; l<3; l++){
+                          for (int m=0; m<3; m++){
+                            temp_WmDqDE(l,m) = 0.;
+                            for (int n=0; n<3; n++){
+                              for (int p=0; p<3; p++){
+                                temp_WmDqDE(l,m) += temp_DDQiDTDE(l,m,n,p)*DGammai(n,p)/this->getTimeStep();
+                              }
+                            }
+                          }
+                        }
+
+                        for (int l=0; l<3; l++){
+                          for (int m=0; m<3; m++){
+                            temp_WmDgammaDE(l,m) = 0.;
+                            for (int n=0; n<3; n++){
+                              for (int p=0; p<3; p++){
+                                temp_WmDgammaDE(l,m) += Qi(n,p)*I4(n,p,l,m)/this->getTimeStep();
+                                temp_WmDgammaDE(l,m) -= Qi(n,p)*temp_DDgammiDtDE(n,p,l,m)/this->getTimeStep();
+                              }
+                            }
+                          }
+                        }
+
+                        dmechanicalSourceE += temp_WmDqDE;                  // 1st Term
+                        dmechanicalSourceE += temp_WmDgammaDE;              // 2nd Term
+
+                    }
+            }
+        }
+    }
+
+    // put DcorKirDT in the IP
+    STensor3& _DcorKirDT = q1->getRefToDcorKirDT();
+    _DcorKirDT = DcorKirDT;
+            
+    // ThermoElastic Heat
+    if (this->getTimeStep() > 0){
+        mechanicalSource += (STensorOperation::doubledot(DcorKirDT,DEe)*T/this->getTimeStep());    // thermoelastic heat   (added to mechSource)
+    }
+
+
+    if (stiff){
+
+        // 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
+
+        static STensor43 DCeDFe; //(0.);
+        static STensor43 DEeDFe(0.);
+        STensorOperation::unity(dFedF);
+        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(dlnCdC,DCeDFe,DEeDFe);
+        DEeDFe *= 0.5;
+
+        static STensor43 DsecondPKdC;
+        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++){
+                        DsecondPKdC(i,j,k,l) = 0.;
+                            for (int p=0; p<3; p++){
+                                for (int q=0; q<3; q++){
+                                    if (_order != 1){
+                                        DsecondPKdC(i,j,k,l) += corKir(p,q)*ddlnCddC(p,q,i,j,k,l);
+                                    }
+                                    for (int r=0; r<3; r++){
+                                        for (int s=0; s<3; s++){
+                                            DsecondPKdC(i,j,k,l) += 0.5*DcorKDE(p,q,r,s)*dlnCdC(p,q,i,j)*dlnCdC(r,s,k,l);
+                                        }
+                                    }
+                                }
+                            }
+                    }
+                }
+            }
+        }
+
+        STensorOperation::zero(Tangent);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int p=0; p<3; p++){
+                    Tangent(i,j,i,p) += secondPK(p,j);
+                    for (int q=0; q<3; q++){
+                        for (int s=0; s<3; s++){
+                            for (int k=0; k<3; k++){
+                                Tangent(i,j,p,q) += 2.*F(i,k)*DsecondPKdC(k,j,q,s)*F(p,s);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Compute Mechano-thermal Tangents - dSdT and dPdT
+        static STensor3 DSDT;
+        STensorOperation::zero(DSDT);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int r=0; r<3; r++){
+                    for (int s=0; s<3; s++){
+                        DSDT(i,j) += DcorKirDT(r,s)*dlnCdC(r,s,i,j);
+                    }
+                }
+            }
+        }
+
+        STensorOperation::zero(dPdT);
+        STensorOperation::multSTensor3(F,DSDT,dPdT);
+
+        // fluxT  derivatives
+        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);
+                        }
+                    }
+                }
+            }
+        }
+
+
+        // thermal source derivatives
+        static STensor3 DCpDF;
+        STensorOperation::zero(DCpDF);                                                       // CHANGE for DCpDF
+        if (this->getTimeStep() > 0){
+            dthermalSourcedT = -CpT/this->getTimeStep() - DCpDT*(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);
+        }
+
+
+
+        // mechanical source derivatives                                                 --- CHANGED for TVE terms
+        if (_N<1){
+           STensorOperation::zero(dmechanicalSourceE);
+           dmechanicalSourcedT = 0;
+        }
+        STensorOperation::zero(dmechanicalSourceF);
+
+
+        if (this->getTimeStep() > 0){
+
+            // dmechanicalSourceE
+
+            // 1st term
+            static STensor3 CorKir_WmDE; STensorOperation::zero(CorKir_WmDE);
+            static STensor43 DDcorKirDTDE;
+            // isotropicHookTensor(DKe,DGe,DDcorKirDTDE);
+            isotropicHookTensor(DKDTsum,DGDTsum,DDcorKirDTDE);
+            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++){
+                            CorKir_WmDE(i,j) += DDcorKirDTDE(i,j,k,l)*DEe(k,l);
+                        }
+                    }
+                }
+            }
+
+            // 2nd term
+            static STensor3 DcorKirDT_I;
+            STensorOperation::multSTensor3STensor43(DcorKirDT,I4,DcorKirDT_I);
+            for (int i=0; i<3; i++){
+                for (int j=0; j<3; j++){
+                    dmechanicalSourceE(i,j) += T*( CorKir_WmDE(i,j) + DcorKirDT_I(i,j) )/this->getTimeStep();
+                }
+            }
+
+            STensorOperation::multSTensor3STensor43(dmechanicalSourceE,DEeDFe,dmechanicalSourceF);
+
+
+            // dmechanicalSourcedT
+            dmechanicalSourcedT += (STensorOperation::doubledot(DcorKirDT,DEe)/this->getTimeStep()); // 1st term
+            dmechanicalSourcedT += T*(STensorOperation::doubledot(DDcorKirDT,DEe)/this->getTimeStep()); // 2nd term
+
+        }
+    }
+};
+
+
+// ========================================================================================================================================
+// Unused Member Functions
+
+double mlawNonLinearTVE::soundSpeed() const {   // Correct this for current temperature
+    return sqrt((_K+4.*_G/3.)/_rho);
+}
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVE.h b/NonLinearSolver/materialLaw/mlawNonLinearTVE.h
new file mode 100644
index 0000000000000000000000000000000000000000..9afdddbf5a9a02afeeeb2245871a79f064fa7457
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVE.h
@@ -0,0 +1,457 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; ; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MLAWNONLINEARTVE_H_
+#define MLAWNONLINEARTVE_H_
+
+#include "mlaw.h"
+#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"
+
+/* 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
+    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
+    double _scalarK;        // (scalar) Thermal Conductivity (K)                                                  - Tensor exists for Anisotropic Conductivity - Generic Fourier's Law
+    double _Cp;       // (scalar) Specific Heat at const pressure or volume or deformation????   - WHAT?
+
+    STensor3 _tensorAlpha;  // (tensor3) Thermal Dilatation Coefficient (=alpha)
+    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
+    double _Tinitial;                               // Initial Temperature
+    double _Tref;                                   // Reference Tempereture           - Set this regardless of thermo problem, can check the code at this constant temperature.
+    int _TemFuncOpt;                                // Option for TemperatureFunction  - 0-> Shift Factor based derivatives of Ki; 1-> Gibson/Huang based derivatives
+    int _modelFlag;                                 // Flag for Model:  1 -> Simo (alpha_i = alpha_inf); 2 -> Extended volumetric terms
+    scalarFunction* _temFunc_K;                     // bulk modulus temperature function
+    scalarFunction* _temFunc_G;                     // shear modulus temperature function
+    scalarFunction* _temFunc_Alpha;                 // alpha temperature function
+    scalarFunction* _temFunc_KThCon;                // thermal conductivity temperature function
+    scalarFunction* _temFunc_Cp;                    // specific heat temperature function
+    std::vector<scalarFunction*> _temFunc_Ki;       // branch bulk moduli temperature functions
+    std::vector<scalarFunction*> _temFunc_Gi;       // branch shear moduli temperature function
+    std::vector<scalarFunction*> _temFunc_Alphai;   // branch alpha temperature function
+
+  // Scalars - Additional constants
+    std::vector<scalarFunction*> _Betai;            // branch free energy scalars
+
+  // 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
+
+  #ifndef SWIG
+  protected:
+  // Const Functions for constitutive function - To update any variable, pass it as an argument by reference.
+    virtual double ShiftFactorWLF(const double T, double *DaDT = NULL, double *DDaDDT = NULL) const ;
+    virtual void shiftedTime(const double t, const double T0, const double T1,
+                             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 setTemp(const double T0, const double T1, const int para) const ;
+
+    void corKirInfinity( 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,
+          double& DKe, double& DGe, double& DKde, double& DGde,
+          double& KTsum, double& GTsum, double& DKDTsum, double& DGDTsum,
+          const double T0, const double T1, const bool calculateStress = true) const;
+
+    void isotropicHookTensor(const double K, const double G, STensor43& L) const;
+
+    void getMechSourceTVE(const IPNonLinearTVE *q0, IPNonLinearTVE *q1, const double& T0, const double& T, 
+                                  const double& DKDTsum, const double& DGDTsum, const STensor43& DEeDFe,
+                                  double *Wm = NULL, STensor3 *dWmdF = NULL, double *dWmdT = NULL) const;
+                                  
+    void getTVEdCorKirDT(const IPNonLinearTVE *q0, IPNonLinearTVE *q1, const double& T0, const double& T) const;
+    
+    void predictorCorrector_ThermoViscoElastic(        // For thermomech - with _tengentPerturbation
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3 &P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVE *q0,                       // array of initial internal variables
+                                              IPNonLinearTVE *q1,                       // updated array of internal variables (in ipvcur on output),
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                              double& thermalSource,
+                                              double& mechanicalSource) const;
+
+    void predictorCorrector_ThermoViscoElastic(       // For thermomech
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVE *q0,                       // array of initial internal variables
+                                              IPNonLinearTVE *q1,                       // updated array of internal variableS (in ipvcur on output),
+                                              STensor43& Tangent,                       // mechanical tangents (output)
+                                              STensor43& dFedF,                         // elastic tangent
+                                              STensor3& dFedT,                          // elastic tangent
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3 &gradT0,                         // previous temperature gradient
+                                        const SVector3 &gradT,                          // temperature gradient
+                                              SVector3 &fluxT,                          // temperature flux
+                                              STensor3 &dPdT,                           // mechanical-thermal coupling
+                                              STensor3 &dfluxTdgradT,                   // thermal tengent
+                                              SVector3 &dfluxTdT,
+                                              STensor33 &dfluxTdF,                      // thermal-mechanical coupling
+                                              double& thermalSource,                    // - Cp*dTdt
+                                              double& dthermalSourcedT,                 // thermal source
+                                              STensor3 &dthermalSourcedF,
+                                              double& mechanicalSource,                 // mechanical source --> convert to heat
+                                              double& dmechanicalSourcedT,
+                                              STensor3& dmechanicalSourceF,
+                                        const bool stiff) const;
+  #endif // SWIG
+
+  public:
+    // Constructor Declaration
+    mlawNonLinearTVE(const int num,const double E,const double nu, const double rho, const double tol, const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = true);
+
+    // Copy Contructor
+    mlawNonLinearTVE(const mlawNonLinearTVE& src);
+
+    // Operator Assignment
+    mlawNonLinearTVE& operator=(const materialLaw& source);
+
+    // Virtual Destructor
+    virtual ~mlawNonLinearTVE();
+
+  // 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);
+    virtual void setViscoElasticData(const int i, const double Ei, const double taui);
+    virtual void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    virtual void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    virtual void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    virtual void setViscoElasticData(const std::string filename);
+    virtual void setViscoElasticData_Alpha(const int i, const double Alpha_i);
+
+  // Non-Const Functions for temp and temp_functions that are called from .py file.  ---- These WILL change the values of the variables defined in the class object.
+    virtual void setReferenceTemperature(const double Tr){_Tref = Tr;};
+    virtual void setTempFuncOption(const double TemFuncOpt){_TemFuncOpt = TemFuncOpt;};
+    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;};
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+     if (_temFunc_K != NULL) delete _temFunc_K;
+      _temFunc_K = Tfunc.clone();
+    }
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+      if (_temFunc_G != NULL) delete _temFunc_G;
+      _temFunc_G = Tfunc.clone();
+    }
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+      if (_temFunc_Alpha != NULL) delete _temFunc_Alpha;
+      _temFunc_Alpha = Tfunc.clone();
+    }
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+      if (_temFunc_KThCon != NULL) delete _temFunc_KThCon;
+      _temFunc_KThCon = Tfunc.clone();
+    }
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+      if (_temFunc_Cp != NULL) delete _temFunc_Cp;
+      _temFunc_Cp = 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);
+       if (_temFunc_Ki[i-1] != NULL) delete _temFunc_Ki[i-1];
+         _temFunc_Ki[i-1] = Tfunc.clone();
+    }
+    void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i){
+       if (i> _N or i<1)
+         Msg::Error("This setting is invalid %d > %d",i,_N);
+       if (_temFunc_Gi[i-1] != NULL) delete _temFunc_Gi[i-1];
+         _temFunc_Gi[i-1] = Tfunc.clone();
+    }
+    void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i){
+       if (i> _N or i<1)
+         Msg::Error("This setting is invalid %d > %d",i,_N);
+       if (_temFunc_Alphai[i-1] != NULL) delete _temFunc_Alphai[i-1];
+         _temFunc_Alphai[i-1] = Tfunc.clone();
+    }
+
+#ifndef SWIG
+
+// Const Functions to get temp-updated values of material properties - Args by reference, or return the variable.
+
+    virtual std::vector<double> getBetai(const double _K, const std::vector<double> _Ki) const{
+        std::vector<double> Beta_i;
+        Beta_i.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+            Beta_i[i] = _Ki[i]/_K;
+        }
+        return Beta_i;
+    }
+
+    virtual void getK(double& KT, const double Tc, double *dK = NULL, double *ddK = NULL) const{
+        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.
+        }
+        if(ddK!=NULL){
+            *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);
+        if(dG!=NULL){
+            *dG = _G*_temFunc_G->getDiff(Tc);
+        }
+        if(ddG!=NULL){
+            *ddG = _G*_temFunc_G->getDoubleDiff(Tc);
+        }
+    }
+     virtual void getAlpha(double& alphaT, const double Tc, double *dAlpha = NULL, double *ddAlpha = NULL) const{
+        alphaT = _scalarAlpha*_temFunc_Alpha->getVal(Tc);
+        if(dAlpha!=NULL){
+            *dAlpha = _scalarAlpha*_temFunc_Alpha->getDiff(Tc);
+        }
+        if(ddAlpha!=NULL){
+            *ddAlpha = _scalarAlpha*_temFunc_Alpha->getDoubleDiff(Tc);
+        }
+    }
+    virtual void getKTHCon(double& KThConT,const double Tc, double *dKThCon = NULL) const{
+        KThConT = _scalarK*_temFunc_KThCon->getVal(Tc);
+        if(dKThCon!=NULL){
+            *dKThCon = _scalarK*_temFunc_KThCon->getDiff(Tc);
+        }
+    }
+    virtual void getCp(double& CpT, const double Tc, double *dCp = NULL, double *ddCp = NULL) const{
+        CpT = _Cp*_temFunc_Cp->getVal(Tc);
+        if(dCp!=NULL){
+            *dCp = _Cp*_temFunc_Cp->getDiff(Tc);
+        }
+        if(ddCp!=NULL){
+            *ddCp = _Cp*_temFunc_Cp->getDoubleDiff(Tc);
+        }
+    }
+
+    // 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{
+        Ki_T.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+            Ki_T[i] = _Ki[i]*_temFunc_Ki[i]->getVal(Tc);
+            if(dKi!=NULL){
+                dKi->at(i) = _Ki[i]*_temFunc_Ki[i]->getDiff(Tc);
+            }
+            if(ddKi!=NULL){
+                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{
+        Gi_T.resize(_N,0.);
+        for (int i=0; i<_Gi.size();i++){
+            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]
+            }
+            if(ddGi!=NULL){
+                ddGi->at(i) = _Gi[i]*_temFunc_Gi[i]->getDoubleDiff(Tc);
+            }
+        }
+    }
+
+    // The 3rd argument is a pointer to a vector.
+    virtual void getAlphai(std::vector<double>& Alphai_T, const double Tc, std::vector<double>* dAlphai=NULL, std::vector<double>* ddAlphai=NULL) const{
+        Alphai_T.resize(_N,0.);
+        for (int i=0; i<_Alphai.size();i++){
+            Alphai_T[i] = _Alphai[i]*_temFunc_Alphai[i]->getVal(Tc);
+            if(dAlphai!=NULL){
+                dAlphai->at(i) = _Alphai[i]*_temFunc_Alphai[i]->getDiff(Tc); // *(dAlphai+i) is equivalent to dAlphai[i]
+            }
+            if(ddAlphai!=NULL){
+                ddAlphai->at(i) = _Alphai[i]*_temFunc_Alphai[i]->getDoubleDiff(Tc);
+            }
+        }
+    }
+
+
+    // Deprecated member function - Currently implementing scalar functions directly in the .py file.
+    virtual void temFuncGlassTransition(const double Tc, const double opt, const double Prop0, const double Prop1, double& Prop, double *dProp = NULL) const {
+        // Prop0 = At room temp or glassy state
+        // Prop1 = In rubbery state - or the lowest possible value after glass transition
+        if (opt == 0) { // LinearFunction  - This is only for test, Prop1 = 0;
+            Prop = Prop0*(1 - 0.1/Prop0*(Tc - 298));
+            if (dProp!= NULL) {
+                *dProp = -0.1;
+                }
+        } else if (opt == 1) { // Gibson et al
+            double Tg = 373; double k = 0.0975; double m = 0;
+            Prop = 0.5*(Prop0+Prop1) -0.5*(Prop0-Prop1) * tanh(k*(Tc-Tg)) - m*(Tc-Tg);
+            if (dProp!= NULL) {
+                *dProp = -0.5*k*(Prop0-Prop1) * (1-pow(tanh(k*(Tc-Tg)),2)) - m;
+                }
+        } else if (opt == 2) { // Huang et al
+            double Tg = 373; double k = 0.0994; double m = 2.968;
+            Prop = Prop0 - (Prop0-Prop1) / (pow((m*exp(-m*k*(Tc-Tg))+1),(1/m)));
+            if (dProp!= NULL) {
+                *dProp = -(Prop0-Prop1)*(pow(m,2.0)*k*exp(-m*k*(Tc-Tg)))/( m* ( pow( (m*exp(-m*k*(Tc-Tg))+1),(1+1/m) )));   // Correct this derivative - CHANGE!!
+                }
+        }
+    }
+
+//    #ifndef SWIG
+
+// 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{
+        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
+
+    // virtual bool withEnergyDissipation() const {if (_N == 0) return false; else return true;};
+    // virtual int getViscoElasticNumberOfElement() const{return _N;};
+
+    virtual double soundSpeed() const; // default but you can redefine it for your case
+
+// Added from LinearThermomech
+    virtual double getInitialTemperature() const {return _Tinitial;};
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const {return getExtraDofStoredEnergyPerUnitField(_Tinitial);}
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const {
+        double Cp; getCp(Cp,T);
+        return Cp;
+    };
+
+// Const functions to directly export the thermal_cond and alpha when called for ipvcur in dG3DMaterialLaw.cpp
+    virtual const STensor3& getConductivityTensor() const {return _tensorK;}; // isotropic only for now
+    virtual const STensor3& getStiff_alphaDilatation() const {return _tensorAlpha;}; // isotropic only for now
+
+    // Default Constitutive function - placeholder
+    virtual void constitutive(
+            const STensor3& F0,         // initial deformation gradient (input @ time n)
+            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+            STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+            const IPVariable *q0,       // array of initial internal variables
+            IPVariable *q1,             // updated array of internal variables (in ipvcur on output),
+            STensor43& Tangent,         // constitutive tangents (output)
+            const bool stiff,           // if true compute the tangents
+            STensor43* elasticTangent = NULL,
+            const bool dTangent =false,
+            STensor63* dCalgdeps = NULL) const;
+
+    // ThermoMech Constitutive function - J2Full
+    virtual void constitutive(
+            const STensor3& F0,                     // initial deformation gradient (input @ time n)
+            const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
+                  STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+            const IPVariable *q0,                   // array of initial internal variable
+                  IPVariable *q1,                   // updated array of internal variable (in ipvcur on output),
+                  STensor43 &Tangent,               // constitutive mechanical tangents (output)
+            const double& T0,                       // previous temperature
+            const double& T,                        // temperature
+            const SVector3 &gradT0,                 // previous temperature gradient
+            const SVector3 &gradT,                  // temperature gradient
+                  SVector3 &fluxT,                  // temperature flux
+                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                  STensor3 &dfluxTdgradT,           // thermal tengent
+                  SVector3 &dfluxTdT,
+                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                  double &thermalSource,            // - Cp*dTdt
+                  double &dthermalSourcedT,         // thermal source
+                  STensor3 &dthermalSourcedF,
+                  double &mechanicalSource,         // mechanical source--> convert to heat
+                  double &dmechanicalSourcedT,
+                  STensor3 & dmechanicalSourceF,
+            const bool stiff,
+                  STensor43* elasticTangent = NULL) const;
+
+    virtual materialLaw* clone() const {return new mlawNonLinearTVE(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+    #endif // SWIG
+};
+#endif //mlawNonLinearTVE
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8a8198b4f641f8765cb3671542dde63d7ba29635
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVM.cpp
@@ -0,0 +1,2205 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022;  <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "mlawHyperelastic.h"
+#include "STensorOperations.h"
+#include "nonLinearMechSolver.h"
+#include "mlawNonLinearTVM.h"
+
+// Constructor
+/* mlawNonLinearTVM::mlawNonLinearTVM(const int num,const double E,const double nu, const double rho, const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                          const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
+    materialLaw(num,true), _E(E),_nu(nu),_rho(rho),_Tinitial(Tinitial),_scalarAlpha(Alpha),_scalarK(KThCon),_Cp(Cp),
+    _tangentByPerturbation(matrixbyPerturbation),_perturbationfactor(pert), _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig),
+    _viscoMethod(Maxwell),_N(0.),_order(1),_Ki(0),_ki(0),_Gi(0),_gi(0),_Alphai(0){
+        
+*/
+
+mlawNonLinearTVM::mlawNonLinearTVM(const int num,const double E,const double nu, const double rho, const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                          const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
+     mlawHyperViscoElastic(num,E,nu,rho,matrixbyPerturbation,pert), _Tinitial(Tinitial),_scalarAlpha(Alpha),_scalarK(KThCon),_Cp(Cp),
+     _thermalEstimationPreviousConfig(thermalEstimationPreviousConfig), _Alphai(0){
+
+  _G = _mu;      
+/*
+  _lambda = (E*nu)/(1.+nu)/(1.-2.*nu);
+  _G = 0.5*E/(1.+nu);
+  _K = E/3./(1.-2.*nu);
+
+  Cel = 0.;
+  Cel(0,0,0,0) = _lambda + 2.*_G;
+  Cel(1,1,0,0) = _lambda;
+  Cel(2,2,0,0) = _lambda;
+  Cel(0,0,1,1) = _lambda;
+  Cel(1,1,1,1) = _lambda + 2.*_G;
+  Cel(2,2,1,1) = _lambda;
+  Cel(0,0,2,2) = _lambda;
+  Cel(1,1,2,2) = _lambda;
+  Cel(2,2,2,2) = _lambda + 2.*_G;
+
+  Cel(1,0,1,0) = _G;
+  Cel(2,0,2,0) = _G;
+  Cel(0,1,0,1) = _G;
+  Cel(2,1,2,1) = _G;
+  Cel(0,2,0,2) = _G;
+  Cel(1,2,1,2) = _G;
+
+  Cel(0,1,1,0) = _G;
+  Cel(0,2,2,0) = _G;
+  Cel(1,0,0,1) = _G;
+  Cel(1,2,2,1) = _G;
+  Cel(2,0,0,2) = _G;
+  Cel(2,1,1,2) = _G;
+ */
+ 
+  _Tref = 298.;
+  _TemFuncOpt = 0;                                                                     // To be discarded soon
+  _modelFlag = 1;         // For additional volumetric terms.
+  _testFlag = 1;          // To test double convolution.
+  _C1 = 0.;
+  _C2 = 0.;
+  
+  // _scalarAlpha = 0.; _scalarK = 0.; _Cp = 0.;
+  _tensorAlpha = 0.;
+  _tensorAlpha(0,0)= _scalarAlpha; _tensorAlpha(1,1)= _scalarAlpha; _tensorAlpha(2,2)= _scalarAlpha;
+  
+  // to be unifom in DG3D q = k' gradT with k'=-k instead of q=-kgradT
+  _tensorK = 0.;
+  _tensorK(0,0)= - _scalarK; _tensorK(1,1)= - _scalarK; _tensorK(2,2)= - _scalarK;
+  
+  _temFunc_K = new constantScalarFunction(1.);
+  _temFunc_G = new constantScalarFunction(1.);
+  _temFunc_Alpha = new constantScalarFunction(1.);
+  _temFunc_KThCon = new constantScalarFunction(1.);
+  _temFunc_Cp = new constantScalarFunction(1.);
+};
+
+// Copy Constructor
+/*mlawNonLinearTVM::mlawNonLinearTVM(const mlawNonLinearTVM& src): materialLaw(src),
+      _E(src._E),_nu(src._nu),_rho(src._rho),_Tinitial(src._Tinitial),_scalarAlpha(src._scalarAlpha),_scalarK(src._scalarK),_Cp(src._Cp),
+      _lambda(src._lambda),_G(src._G),_K(src._K),Cel(src.Cel),
+      _order(src._order),
+      _tangentByPerturbation(src._tangentByPerturbation),_perturbationfactor(src._perturbationfactor), _thermalEstimationPreviousConfig(src._thermalEstimationPreviousConfig),
+      _N(src._N),_viscoMethod(src._viscoMethod),_Ki(src._Ki),_ki(src._ki),_Gi(src._Gi),_gi(src._gi),_Alphai(src._Alphai){
+*/
+          
+mlawNonLinearTVM::mlawNonLinearTVM(const mlawNonLinearTVM& src): mlawHyperViscoElastic(src),
+      _Tinitial(src._Tinitial),_scalarAlpha(src._scalarAlpha),_scalarK(src._scalarK),_Cp(src._Cp),
+      _thermalEstimationPreviousConfig(src._thermalEstimationPreviousConfig),_Alphai(src._Alphai){
+  
+  _G = src._G;        
+  _Tref = src._Tref;
+  _TemFuncOpt = src._TemFuncOpt;
+  _modelFlag = src._modelFlag;
+  _testFlag = src._testFlag;
+  _C1 = src._C1;
+  _C2 = src._C2;
+//  _scalarAlpha = src._scalarAlpha; _scalarK = src._scalarK; _Cp = src._Cp;
+  _tensorAlpha = src._tensorAlpha;
+  _tensorK = src._tensorK;
+  
+  _temFunc_K = NULL;                                                                    // bulk modulus
+  if (src._temFunc_K != NULL){ _temFunc_K = src._temFunc_K->clone();}
+  
+  _temFunc_G = NULL;                                                                    // shear modulus
+  if (src._temFunc_G!=NULL){ _temFunc_G = src._temFunc_G->clone();}
+
+  _temFunc_Alpha = NULL;                                                                // thermal dilatation coeffecient
+  if (src._temFunc_Alpha!=NULL){ _temFunc_Alpha = src._temFunc_Alpha->clone();}
+
+  _temFunc_KThCon = NULL;                                                               // thermal conductivity
+  if (src._temFunc_KThCon!=NULL){ _temFunc_KThCon = src._temFunc_KThCon->clone();}
+  
+  _temFunc_Cp = NULL;                                                                   // specific heat
+  if (src._temFunc_Cp!=NULL){ _temFunc_Cp = src._temFunc_Cp->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();}
+  }
+  
+  _temFunc_Gi.resize(_N,NULL);                                                          // branch shear moduli
+  for(int i=0;i<_N;i++){
+    if (src._temFunc_Gi[i]!=NULL) {_temFunc_Gi[i] = src._temFunc_Gi[i]->clone();}
+  }
+  
+  _temFunc_Alphai.resize(_N,NULL);                                                      // branch alpha
+  for(int i=0;i<_N;i++){
+    if (src._temFunc_Alphai[i]!=NULL) {_temFunc_Alphai[i] = src._temFunc_Alphai[i]->clone();}
+  }
+};  
+
+
+mlawNonLinearTVM& mlawNonLinearTVM::operator=(const materialLaw &source){
+    
+  // materialLaw::operator=(source);  
+  mlawHyperViscoElastic::operator=(source);
+  const mlawNonLinearTVM* src =dynamic_cast<const mlawNonLinearTVM*>(&source);
+  if(src != NULL){
+      
+      // _E = src->_E; _nu = src->_nu; _rho = src->_rho; 
+      _Tinitial = src->_Tinitial; _scalarAlpha = src->_scalarAlpha; _scalarK = src->_scalarK; _Cp = src->_Cp;
+      // _lambda = src->_lambda; _G = src->_G; _K = src->_K; Cel = src->Cel; _order = src->_order;
+      // _tangentByPerturbation = src->_tangentByPerturbation; _perturbationfactor = src->_perturbationfactor; 
+      //_N = src->_N; _viscoMethod = src->_viscoMethod; _Ki = src->_Ki; _ki = src->_ki; _Gi = src->_Gi; _gi = src->_gi;
+      _thermalEstimationPreviousConfig = src->_thermalEstimationPreviousConfig; _Alphai = src->_Alphai;
+     
+    _G = src->_G;
+    _Tref = src->_Tref;
+    _TemFuncOpt = src->_TemFuncOpt;
+    _modelFlag = src->_modelFlag;   
+    _testFlag = src->_testFlag; 
+    _C1 = src->_C1;
+    _C2 = src->_C2;
+    // _scalarAlpha = src->_scalarAlpha; _scalarK = src->_scalarK; _Cp = src->_Cp;
+    _tensorAlpha = src->_tensorAlpha;
+    _tensorK = src->_tensorK;
+    
+    if(_temFunc_K != NULL) delete _temFunc_K;                                                   // bulk modulus
+    if (src->_temFunc_K != NULL){ _temFunc_K = src->_temFunc_K->clone();}
+
+    if(_temFunc_G != NULL) delete _temFunc_G;                                                   // shear modulus
+    if (src->_temFunc_G!=NULL){ _temFunc_G = src->_temFunc_G->clone();} 
+    
+    if(_temFunc_Alpha != NULL) delete _temFunc_Alpha;                                           // thermal dilatation coeffecient
+    if (src->_temFunc_Alpha!=NULL){ _temFunc_Alpha = src->_temFunc_Alpha->clone();} 
+    
+    if(_temFunc_KThCon != NULL) delete _temFunc_KThCon;                                         // thermal conductivity
+    if (src->_temFunc_KThCon!=NULL){ _temFunc_KThCon = src->_temFunc_KThCon->clone();} 
+
+    if(_temFunc_Cp != NULL) delete _temFunc_Cp;                                                 // specific heat
+    if (src->_temFunc_Cp!=NULL){ _temFunc_Cp = src->_temFunc_Cp->clone();} 
+    
+    for(int i=0;i<_temFunc_Ki.size();i++){                                                          // branch bulk moduli   
+        if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+        _temFunc_Ki[i]=NULL;
+    }
+    _temFunc_Ki.resize(_N,NULL);
+    for(int i=0;i<_N;i++){                                                                           
+        if (src->_temFunc_Ki[i]!=NULL)
+        _temFunc_Ki[i] = src->_temFunc_Ki[i]->clone();
+    }
+    
+    for(int i=0;i<_temFunc_Gi.size();i++){                                                          // branch shear moduli 
+        if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+        _temFunc_Gi[i]=NULL;
+    }
+    _temFunc_Gi.resize(_N,NULL);
+    for(int i=0;i<_N;i++){                                                                           
+        if (src->_temFunc_Gi[i]!=NULL)
+        _temFunc_Gi[i] = src->_temFunc_Gi[i]->clone();
+    }
+    
+    for(int i=0;i<_temFunc_Alphai.size();i++){                                                      // branch alpha   
+        if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+        _temFunc_Alphai[i]=NULL;
+    }
+    _temFunc_Alphai.resize(_N,NULL);
+    for(int i=0;i<_N;i++){                                                                           
+        if (src->_temFunc_Alphai[i]!=NULL)
+        _temFunc_Alphai[i] = src->_temFunc_Alphai[i]->clone();
+    }
+  }
+  return *this;
+}
+
+mlawNonLinearTVM::~mlawNonLinearTVM(){
+    if(_temFunc_K != NULL) delete _temFunc_K; _temFunc_K = NULL;                    // bulk modulus;
+    if(_temFunc_G != NULL) delete _temFunc_G; _temFunc_G = NULL;                    // shear modulus;     
+    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;
+    for(int i=0;i<_temFunc_Ki.size();i++){   
+        if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+        _temFunc_Ki[i]=NULL;
+    }
+    for(int i=0;i<_temFunc_Gi.size();i++){   
+        if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+        _temFunc_Gi[i]=NULL;
+    }
+    for(int i=0;i<_temFunc_Alphai.size();i++){   
+        if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+        _temFunc_Alphai[i]=NULL;
+    }
+};
+
+/*
+void mlawNonLinearTVM::setStrainOrder(const int order){
+  _order = order;
+  Msg::Info("order = %d is used to approximate log and exp");
+};
+
+void mlawNonLinearTVM::setViscoelasticMethod(const int method){
+  _viscoMethod = (viscoelasticType)method;
+  if (_viscoMethod == Maxwell)
+    Msg::Info("generalized maxwell model is used for viscoelasticity");
+  else if (_viscoMethod == KelvinVoight)
+    Msg::Info("generalized Voigt-Kelvin model is used for viscoelasticity");
+  else
+    Msg::Error("this method has not been implemented");
+};
+*/
+
+void mlawNonLinearTVM::setViscoElasticNumberOfElement(const int N){
+  _N = N;
+  Msg::Info("Numer of Spring/Dashpot for viscoelastic model: %d",_N);
+  _Ki.clear(); _ki.clear();
+  _Gi.clear(); _gi.clear();
+  _Alphai.clear(); 
+  _Ki.resize(_N,0.);
+  _ki.resize(_N,0.);
+  _Gi.resize(_N,0.);
+  _gi.resize(_N,0.);
+  _Alphai.resize(_N,0.); 
+  
+  // _temFunc_Ki and Gi need to be here to get initiated only if setViscoElasticNumberOfElement is called.
+  for(int i=0;i<_temFunc_Ki.size();i++){   
+    if(_temFunc_Ki[i]!=NULL) delete _temFunc_Ki[i];
+    _temFunc_Ki[i]=NULL;
+  }
+  _temFunc_Ki.resize(_N,NULL);
+  /*for(int i=0;i<_N;i++){
+    _temFunc_Ki[i] = new constantScalarFunction(1.);
+  }*/
+
+  for(int i=0;i<_temFunc_Gi.size();i++){   
+    if(_temFunc_Gi[i]!=NULL) delete _temFunc_Gi[i];
+    _temFunc_Gi[i]=NULL;
+  }
+  _temFunc_Gi.resize(_N,NULL);
+ /* for(int i=0;i<_N;i++){
+    _temFunc_Gi[i] = new constantScalarFunction(1.);
+  }*/
+  
+  for(int i=0;i<_temFunc_Alphai.size();i++){   
+    if(_temFunc_Alphai[i]!=NULL) delete _temFunc_Alphai[i];
+    _temFunc_Alphai[i]=NULL;
+  }
+  _temFunc_Alphai.resize(_N,NULL);
+ /* for(int i=0;i<_N;i++){
+    _temFunc_Alphai[i] = new constantScalarFunction(1.);
+  }*/
+};
+
+void mlawNonLinearTVM::setViscoElasticData(const int i, const double Ei, const double taui){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    double KK = Ei/(3.*(1.-2.*_nu));
+    double GG = Ei/(2.*(1.+_nu));
+
+    _Ki[i-1] = KK;
+    _ki[i-1] = taui;
+    _Gi[i-1] = GG;
+    _gi[i-1] = taui;
+    _Alphai[i-1] = 0.;
+    
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.); // (1.*KK)  
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.); // (1.*GG)
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.); 
+    
+    Msg::Info("setting: element=%d Ki= %e ki= %e, Gi= %e, gi= %e",i-1,KK,taui,GG,taui);
+  }
+};
+
+void mlawNonLinearTVM::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    double KK = Ei/(3.*(1.-2.*_nu));
+    double GG = Ei/(2.*(1.+_nu));
+    double AA = Alphai;
+
+    _Ki[i-1] = KK;
+    _ki[i-1] = taui;
+    _Gi[i-1] = GG;
+    _gi[i-1] = taui;
+    _Alphai[i-1] = AA;
+    
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.); // (1.*KK)  
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.); // (1.*GG)
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.*AA); 
+    
+    Msg::Info("setting: element=%d Ki= %e ki= %e, Gi= %e, gi= %e, Alphai= %e",i-1,KK,taui,GG,taui,Alphai);
+  }
+};
+
+void mlawNonLinearTVM::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Ki[i-1] = Ki;
+    _ki[i-1] = ki;
+    
+    _temFunc_Ki[i-1] = new constantScalarFunction(1.*Ki); 
+    
+    Msg::Info("setting: element=%d Ki = %e ki = %e, ",i-1,Ki,ki);
+  }
+};
+
+void mlawNonLinearTVM::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Gi[i-1] = Gi;
+    _gi[i-1] = gi;
+
+    _temFunc_Gi[i-1] = new constantScalarFunction(1.*Gi);
+
+    Msg::Info("setting: element=%d Gi = %e gi = %e, ",i-1,Gi,gi);
+  }
+};
+
+// This function is a mandatory definition in .py file currently ---> Make it so that you dont always have to define the vector ----- CHANGE!!
+void mlawNonLinearTVM::setViscoElasticData_Alpha(const int i, const double Alpha_i){
+  if (i> _N or i<1)
+    Msg::Error("This setting is invalid %d > %d",i,_N);
+  else{
+    _Alphai[i-1] = Alpha_i;
+    
+    _temFunc_Alphai[i-1] = new constantScalarFunction(1.*Alpha_i); 
+    
+    Msg::Info("setting: element=%d Alphai = %e ",i-1,Alpha_i);
+  }
+};
+
+void mlawNonLinearTVM::setViscoElasticData(const std::string filename){
+  FILE* file = fopen(filename.c_str(),"r");
+  if (file == NULL) Msg::Error("file: %s does not exist",filename.c_str());
+  _Ki.clear(); _ki.clear();
+  _Gi.clear(); _gi.clear();
+  _N = 0;
+  Msg::Info("reading viscoelastic input data");
+
+  while (!feof(file)){
+    int ok = fscanf(file,"%d",&_N);
+    Msg::Info("Numer of Maxwell elements: %d",_N);
+    double KK, k, GG, g;
+
+    for (int i=0; i<_N; i++){
+      ok = fscanf(file,"%lf %lf %lf %lf",&KK,&k,&GG,&g);
+      _Ki.push_back(KK);
+      _ki.push_back(k);
+      _Gi.push_back(GG);
+      _gi.push_back(g);
+      Msg::Info("Maxwell element %d: K[%d] = %e, k[%d] = %e, G[%d] = %e, g[%d] = %e",
+                i,i,KK,i,k,i,GG,i,g);
+    }
+  }
+  fclose(file);
+};
+
+double mlawNonLinearTVM::ShiftFactorWLF(const double T, double *DaDT, double *DDaDDT) const{
+    
+    double a_WLF = exp(- (_C1*(T - _Tref)) / (_C2 + T - _Tref) );
+    
+    if(DaDT!=NULL){
+        *DaDT = 1/a_WLF * (_C1*_C2) / pow( (_C2 + T-_Tref) ,2);
+    }
+    if(DDaDDT!=NULL){
+        *DDaDDT = 1/a_WLF * (_C1*_C2) * (_C1*_C2 - 2*(_C2+ T-_Tref)) / pow( (_C2 + T-_Tref) ,4);
+    }
+    return a_WLF;
+}
+
+void mlawNonLinearTVM::shiftedTime(const double t, const double T0, const double T1, double *t_shift, double *Ddt_shiftDT, double *DDdt_shiftDT, const int option) const{
+    
+// Shift t -> t is either delta_t or t (final time).  This function returns either t^* or delta_t^*. 
+
+    double dt = this->getTimeStep();
+    double t1 = this->getTime();
+    double t0 = t1 - dt;
+    
+    // Linearly Interpolate Temperture -> This means dT/dt is constant between tn and tn+1
+    double ts, t_x0, t_x1, t_x2 = 0.;
+    double t_x6, t_x7, t_x8, t_x9 = 0.;
+    if (option == 0){
+        ts = 2; 
+        
+        t_x0 = (t1+t0)/2;
+        
+        t_x1 = (t1+t0)/2 - dt/2 * (1/sqrt(3));
+        t_x2 = (t1+t0)/2 + dt/2 * (1/sqrt(3));
+        
+        t_x6 = (t1+t0)/2 - dt/2 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x7 = (t1+t0)/2 + dt/2 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x8 = (t1+t0)/2 - dt/2 * sqrt(3/7 + 2/7*sqrt(6/5));
+        t_x9 = (t1+t0)/2 + dt/2 * sqrt(3/7 + 2/7*sqrt(6/5));
+    } else {
+        ts = 4;
+        
+        t_x0 = (3*t1+t0)/4;
+        
+        t_x1 = (3*t1+t0)/4 - dt/4 * (1/sqrt(3));
+        t_x2 = (3*t1+t0)/4 + dt/4 * (1/sqrt(3));
+        
+        t_x6 = (3*t1+t0)/4 - dt/4 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x7 = (3*t1+t0)/4 + dt/4 * sqrt(3/7 - 2/7*sqrt(6/5));
+        t_x8 = (3*t1+t0)/4 - dt/4 * sqrt(3/7 + 2/7*sqrt(6/5));
+        t_x9 = (3*t1+t0)/4 + dt/4 * sqrt(3/7 + 2/7*sqrt(6/5));
+    }
+    
+    double T_x0 = linearInterpTemp(t_x0, t0, t1, T0, T1);
+    double T_x1 = linearInterpTemp(t_x1, t0, t1, T0, T1);
+    double T_x2 = linearInterpTemp(t_x2, t0, t1, T0, T1);
+    double T_x6 = linearInterpTemp(t_x6, t0, t1, T0, T1);
+    double T_x7 = linearInterpTemp(t_x7, t0, t1, T0, T1);
+    double T_x8 = linearInterpTemp(t_x8, t0, t1, T0, T1);
+    double T_x9 = linearInterpTemp(t_x9, t0, t1, T0, T1);
+    // double T_x1 = 1/dt*( (t_1 - t_x1) )*T_0 + 1/dt*( (t_x1 - t_0) )*T_1 ;
+    // double T_x2 = 1/dt*( (t_1 - t_x2) )*T_0 + 1/dt*( (t_x2 - t_0) )*T_1 ; 
+    
+    if (t_shift!=NULL){
+        double a_x0 = ShiftFactorWLF(T_x0);
+        double a_x1 = ShiftFactorWLF(T_x1);
+        double a_x2 = ShiftFactorWLF(T_x2); 
+        double a_x6 = ShiftFactorWLF(T_x6); 
+        double a_x7 = ShiftFactorWLF(T_x7); 
+        double a_x8 = ShiftFactorWLF(T_x8); 
+        double a_x9 = ShiftFactorWLF(T_x9); 
+        double a_T1 = ShiftFactorWLF(T1);
+        // 1 point Gauss rule
+        // *t_shift = t/ts * (1/a_x0);
+        
+        // 2 point Gauss rule
+        *t_shift = t/ts * (1/a_x1 + 1/a_x2);
+        
+        // 4 point Gauss rule
+        // *t_shift = t/ts * (((18+sqrt(30))/36)*(1/a_x6 + 1/a_x7) + ((18-sqrt(30))/36)*(1/a_x8 + 1/a_x9));
+        
+    }
+    if (Ddt_shiftDT!=NULL){
+        double DaDT_x0, DaDT_x1, DaDT_x2, DaDT_T1 = 0.;
+        double DaDT_x6, DaDT_x7, DaDT_x8, DaDT_x9 = 0.;
+        double a_x0 = ShiftFactorWLF(T_x0,&DaDT_x0);
+        double a_x1 = ShiftFactorWLF(T_x1,&DaDT_x1);
+        double a_x2 = ShiftFactorWLF(T_x2,&DaDT_x2);
+        double a_x6 = ShiftFactorWLF(T_x6,&DaDT_x6);
+        double a_x7 = ShiftFactorWLF(T_x7,&DaDT_x7);
+        double a_x8 = ShiftFactorWLF(T_x8,&DaDT_x8);
+        double a_x9 = ShiftFactorWLF(T_x9,&DaDT_x9);
+        double a_T1 = ShiftFactorWLF(T1,&DaDT_T1);
+        
+        if (dt > 0.){
+            
+            // 1 point Gauss rule
+            // *Ddt_shiftDT = t/ts * (DaDT_x0 * (t_x0-t0)/dt );
+            
+            // 2 point Gauss rule
+            *Ddt_shiftDT = t/ts * (DaDT_x1 * (t_x1-t0)/dt + DaDT_x2 * (t_x2-t0)/dt);
+                    
+            // 4 point Gauss rule
+            // *Ddt_shiftDT = t/ts * ( ((18+sqrt(30))/36)*(DaDT_x6 * (t_x6-t0)/dt  + DaDT_x7 * (t_x7-t0)/dt ) + 
+            //                         ((18-sqrt(30))/36)*(DaDT_x8 * (t_x8-t0)/dt  + DaDT_x9 * (t_x9-t0)/dt ) );
+        } else { *Ddt_shiftDT = 0.;}
+    }
+    if (DDdt_shiftDT!=NULL){
+        double DDaDT_x0, DDaDT_x1, DDaDT_x2, DDaDT_T1 = 0.;
+        double DDaDT_x6, DDaDT_x7, DDaDT_x8, DDaDT_x9 = 0.;
+        double a_x0 = ShiftFactorWLF(T_x0,NULL,&DDaDT_x0);
+        double a_x1 = ShiftFactorWLF(T_x1,NULL,&DDaDT_x1);
+        double a_x2 = ShiftFactorWLF(T_x2,NULL,&DDaDT_x2);
+        double a_x6 = ShiftFactorWLF(T_x6,NULL,&DDaDT_x6);
+        double a_x7 = ShiftFactorWLF(T_x7,NULL,&DDaDT_x7);
+        double a_x8 = ShiftFactorWLF(T_x8,NULL,&DDaDT_x8);
+        double a_x9 = ShiftFactorWLF(T_x9,NULL,&DDaDT_x9);
+        double a_T1 = ShiftFactorWLF(T1,NULL,&DDaDT_T1);
+    
+        if (dt > 0.){
+            
+            // 1 point Gauss rule
+            // *DDdt_shiftDT = t/ts * ( DDaDT_x0 * pow( ((t_x0-t0)/dt) ,2 ) );
+            
+            // 2 point Gauss rule
+            *DDdt_shiftDT = t/ts * ( DDaDT_x1 * pow( ((t_x1-t0)/dt) ,2 ) + DDaDT_x2 * pow( ((t_x2-t0)/dt) ,2 ) );
+                  
+            // 4 point Gauss rule  
+            // *Ddt_shiftDT = t/ts * ( ((18+sqrt(30))/36)*( DDaDT_x6 * pow( (t_x6-t0)/dt, 2 ) + DDaDT_x7 * pow( (t_x7-t0)/dt, 2 )) + 
+            //                        ((18-sqrt(30))/36)*( DDaDT_x8 * pow( (t_x8-t0)/dt, 2 ) + DDaDT_x9 * pow( (t_x9-t0)/dt, 2 )) );
+        } else { *DDdt_shiftDT = 0.;}
+    } 
+}        
+
+
+double mlawNonLinearTVM::linearInterpTemp(const double t_interp, const double t0, const double t1, const double T0, const double T1) const{
+    
+    // This function linearly/quadratically interpolates temperature for the given intermediate time -> t_interp is tn + fraction of step (i.e., midstep = tn + 0.5*dt)
+        // Also, linear interp -> constant gradients
+    double dt = t1 - t0;
+    double T_interp;
+    if (dt > 0.){
+        T_interp = 1/dt*( (t1 - t_interp) )*T0 + 1/dt*( (t_interp - t0) )*T1;
+    }
+    else { T_interp = T0;}
+    return T_interp; 
+}
+
+double mlawNonLinearTVM::setTemp(const double T0, const double T1, const int para) const{
+    
+    double T_set = 0.;
+    
+    if (para == 1){ // @T1
+        T_set = T1;
+        
+    } else if (para == 2){ // @Tmid
+        double dt = this->getTimeStep();
+        double t1 = this->getTime();
+        double t0 = t1 - dt;
+        double t_mid = t1 - dt/2;
+        double T_mid = linearInterpTemp(t_mid, t0, t1, T0, T1);
+        T_set = T_mid; 
+        
+    } else if (para == 3){ // @Tmidshift
+        double dt = this->getTimeStep();
+        double t1 = this->getTime();            
+        double dt_shift, t1_shift; 
+        shiftedTime(dt,T0,T1,&dt_shift); shiftedTime(t1,T0,T1,&t1_shift);
+        double t0_shift = t1_shift - dt_shift;
+        double t_mid_shift = t1_shift - dt_shift/2;
+        double aT_0 = ShiftFactorWLF(T0);
+        double aT_1 = ShiftFactorWLF(T1);
+        double T_mid_shift = linearInterpTemp(t_mid_shift, t0_shift, t1_shift, T0, T1);
+        T_set = T_mid_shift;
+    }
+    
+    return T_set;
+}
+
+double mlawNonLinearTVM::freeEnergyMechanical(const IPNonLinearTVM& q, const double Tc) 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 Psy_mech = 0.;
+    
+    // Get trEe and devEe
+    double trEe;
+    static STensor3 devEe;
+    STensorOperation::decomposeDevTr(q._Ee,devEe,trEe);
+    
+    // Get thermal strain
+    double Eth = 3.*AlphaT*(Tc-_Tinitial); 
+    
+    // Get Equilibrium freeEnergy_mech
+    Psy_mech = KT*0.5*(trEe-Eth)*(trEe-Eth) + GT*STensorOperation::doubledot(devEe,devEe);
+    
+    // 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);
+        
+        for (int i=0; i<_N; i++){
+            static STensor3 devEebranch;
+            devEebranch = devEe;
+      
+            // 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._trGammai[i];
+            static STensor3 devGamma = q._devGammai[i];
+            devEebranch -= devGamma;
+                
+            if (_modelFlag == 2){  // Additional volumetric terms
+                trGamma += 3*(AlphaT-AlphaiT[i])*(Tc-_Tinitial);
+            }
+        
+            Psy_mech += KiT[i]*0.5*(trEe-trGamma)*(trEe-trGamma) + GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
+        }
+    } 
+    
+    return Psy_mech;
+}   
+
+void mlawNonLinearTVM::corKirInfinity( 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); 
+    CorKirDevInf = 2*GT*devEe;
+    CorKirTrInf = KT*(trEe - 3*AlphaT*(T1-_Tinitial));  
+}  
+
+void mlawNonLinearTVM::ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
+          double& Ke, double& Ge, double& Kde, double& Gde, 
+          double& DKe, double& DGe, double& DKde, double& DGde,
+          double& KTsum, double& GTsum, double& DKDTsum, double& DGDTsum,
+          const double T0, const double T1) const{
+    
+    // Set Temperature to calculate temperature updated properties
+    double T_set = setTemp(T0,T1,1);  // 1->T1, 2->T_mid, 3->T_midshift 
+    
+    // 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);
+    
+    // Get LogStrain 
+    
+    // static STensor3 devEe_0, devEe_1;
+    // static double trEe_0, trEe_1;
+    // STensorOperation::decomposeDevTr(Ee0,devEe_0,trEe_0);
+    static STensor3 DE, devDE, devEe;
+    static double trDE, trEe;
+    DE =  Ee;
+    DE -= Ee0;
+    STensorOperation::decomposeDevTr(DE,devDE,trDE);
+    STensorOperation::decomposeDevTr(Ee,devEe,trEe);
+    
+    // Initialise CorKirStress - Dev
+    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;
+
+    
+    // Main Loop for Maxwell Branches
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+        
+        // Get ShiftFactor and shifted time increment
+        double dt = this->getTimeStep();
+        double dt_shift_1, dt_shift_2 = 0.; 
+        double Ddt_shiftDT, DDdt_shiftDT = 0.;
+        // dt_shift = dt;
+        shiftedTime(dt, T0, T1, &dt_shift_1,NULL,NULL,0);
+        shiftedTime(dt, T0, T1, &dt_shift_2,&Ddt_shiftDT,&DDdt_shiftDT);
+            // double aT_1 = ShiftFactorWLF(T1);
+            
+        std::vector<double> KiT, GiT, AlphaiT_0, AlphaiT, DKiDT, DGiDT, DAlphaiDT, DDKiDT, DDGiDT;
+        KiT.resize(_N,0.); GiT.resize(_N,0.); AlphaiT_0.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.);
+        
+        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); 
+        }
+
+
+        // Dev Q_i 
+        std::vector<STensor3>& devQi = q1->getRefToDevViscoElasticStress(); // devQi.resize(_N,0.);
+        std::vector<STensor3>& devGammai = q1->getRefToDevViscoElasticStrain();
+        
+        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(-dtg/2.);
+            double expdtgby2 = exp(-dtg2);
+            
+            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;
+            }   
+            
+            // For Single Convolution
+            // Ge for DcorKirDE, DGe for DDcorKirDEDT (sort of)        
+            Ge += GiT[i]*expdtgby2; // 2* (..) - Dont multiply by 2 if using lambda and mu in Hooks tensor function
+            DGe += DGiDT[i]*expdtgby2;
+                
+            GTsum += GiT[i];
+            DGDTsum += DGiDT[i];
+            
+            // For Double Convolutions
+            double temp_Gdi = 0.; // 0.25*DGiDT[i]*( expdtgby2 + 2*expdtg+ exp(-3*dtg/2.) );    // Gde for DcorKirDT
+            double temp_DGdi = 0.; // 0.25*DDGiDT[i]*( expdtgby2 + 2*expdtg + exp(-3*dtg/2.) ); // DGde 
+
+            for (int k=0; k<3; k++){
+                for (int l=0; l<3; l++){
+                    
+                    // Single Convolution
+                    // q1->_A[i](k,l) = expdtg*q0->_A[i](k,l) + 2*GiT[i]*expdtgby2*devDE(k,l);
+                    q1->_A[i](k,l) = expdtg*q0->_A[i](k,l) + expdtgby2*devDE(k,l);
+                    
+                    // Double Convolution
+                    q1->_C[i](k,l) = expdtg*q0->_C[i](k,l) + 2*temp_Gdi*devDE(k,l)*(T1 - T0);
+         
+                    // devGammai[i](k,l) = devEe(k,l) - (q1->_A[i](k,l))/GiT[i]; 
+                    // devGammai[i](k,l) = (q1->_A[i](k,l))/GiT[i]; 
+                    devGammai[i](k,l) = (q1->_A[i](k,l)); 
+                } 
+            }
+                        
+            Gde += temp_Gdi; 
+            DGde += temp_DGdi;
+            
+            devQi[i] = 2*GiT[i]*q1->_A[i]; // + q1->_C[i];
+            devK += devQi[i];
+         }
+        
+        
+        // Tr Q_i
+        std::vector<double>& trQi = q1 -> getRefToTrViscoElasticStress(); // trQi[i].resize(_N,0.);
+        std::vector<double>& trGammai = q1 -> getRefToTrViscoElasticStrain(); 
+        
+        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);
+            // double expdtkby2 = exp(-dtk/2.);
+            
+            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;
+            } 
+            
+            // Single Convolution
+            Ke += KiT[i]*expdtkby2;        
+            DKe += DKiDT[i]*expdtkby2;
+            
+            KTsum += KiT[i]; DKDTsum += DKiDT[i];
+            
+            // q1->_B[i] = expdtk*q0->_B[i] + KiT[i]*expdtkby2*trDE;
+            q1->_B[i] = expdtk*q0->_B[i] + expdtkby2*trDE;
+            
+            // Double Convolution 
+            double temp_Kdi = 0.; // 0.25*DKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) );   // For Kde
+            double temp_DKdi = 0.; // 0.25*DDKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) ); // For DKde
+                
+            Kde += temp_Kdi; DKde += temp_DKdi;
+            q1->_D[i] = expdtk*q0->_D[i] + temp_Kdi*trDE*( T1 - T0 );
+           
+            
+            if (_modelFlag == 1){ // because for _modelFlag == 2, the equation for Qi changes.
+            
+                trQi[i] = KiT[i]*q1->_B[i]; //+ q1->_D[i];
+                
+                // trGammai
+                // trGammai[i] = trEe - (q1->_B[i])/KiT[i]; 
+                // trGammai[i] = (q1->_B[i])/KiT[i]; 
+                trGammai[i] = (q1->_B[i]); 
+            }
+            
+            if (_modelFlag == 2){ // additional volumetric terms
+ 
+                // Double Convolution
+                q1->_E[i] = expdtk*q0->_E[i] + 3*0.25*DKiDT[i]*( expdtkby2 + 2*expdtk + exp(-3*dtk/2.) )*( (AlphaT-AlphaiT[i])*(T1-_Tinitial) - (AlphaT_0-AlphaiT_0[i])*(T0-_Tinitial) )*(T1 - T0);
+                
+                // Single Convolution
+                q1->_F[i] = expdtk*q0->_F[i] + 3*KiT[i]*(T1-_Tinitial)*( DAlphaDT - DAlphaiDT[i] )*expdtkby2*(T1 - T0);
+                q1->_G[i] = expdtk*q0->_G[i] + 3*KiT[i]*( AlphaT - AlphaiT[i] )*expdtkby2*(T1 - T0);
+
+                trQi[i] = q1->_B[i] + q1->_D[i] - q1->_E[i] - q1->_F[i] - q1->_G[i];
+                
+                // trGammai
+                trGammai[i] = trEe - ( 3*(AlphaT - AlphaiT[i])*(T1-_Tinitial) ) - (q1->_B[i]-q1->_F[i]-q1->_G[i])/KiT[i];
+            }     
+        
+            p += trQi[i]; 
+        }
+    }
+    
+    q1->_kirchhoff = devK;
+    q1->_kirchhoff(0,0) += p;
+    q1->_kirchhoff(1,1) += p;
+    q1->_kirchhoff(2,2) += p;
+}
+
+void mlawNonLinearTVM::isotropicHookTensor(const double K, const double G, STensor43& L) const{
+  double lambda = K - 2.*G/3.;
+  static STensor3 I(1.);
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      for (int k=0; k<3; k++){
+        for (int l=0; l<3; l++){
+          L(i,j,k,l) = lambda*I(i,j)*I(k,l)+ G*(I(i,k)*I(j,l)+I(i,l)*I(j,k));
+        }
+      }
+    }
+  }
+};
+
+
+void mlawNonLinearTVM::constitutive(const STensor3& F0, 
+                                    const STensor3& F, 
+                                    STensor3& P,
+                                    const IPVariable *q0i, 
+                                    IPVariable *q1i,
+                                    STensor43& Tangent, 
+                                    const bool stiff,
+                                    STensor43* elasticTangent, 
+                                    const bool dTangent,
+                                    STensor63* dCalgdeps) const{
+  
+  const IPNonLinearTVM *q0=dynamic_cast<const IPNonLinearTVM *>(q0i);
+  IPNonLinearTVM *q1 = dynamic_cast<IPNonLinearTVM *>(q1i);
+                                           
+  double Tc = _Tref;  
+  static SVector3 gradT, temp2;
+  static STensor3 temp3;
+  static STensor33 temp33;
+  static double tempVal;
+  static STensor43 dFpdF, dFedF;
+  static STensor3 dFpdT, dFedT, dGammadF;
+  double dGammadT;
+
+  if(elasticTangent!=NULL) Msg::Error("mlawNonLinearTVM elasticTangent not defined");
+  predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,_Tref,_Tref,gradT,gradT,temp2,temp3,temp3,temp2,temp33,tempVal,tempVal,
+                      tempVal,temp3,tempVal,tempVal,tempVal,temp3,stiff);
+                      
+/*
+  if (!_tangentByPerturbation){
+    this->predictorCorrector_ViscoElastic(F0,F,P,q0,q1,stiff,Tangent,Tc);
+  }
+  else{
+    this->predictorCorrector_ViscoElastic(F0,F,P,q0,q1,false,Tangent,Tc);
+    if (stiff){
+      static STensor3 Fplus, Pplus;
+      static STensor43 Ttemp;
+      static IPNonLinearTVM qtemp(*q1);
+      for (int i= 0; i<3; i++){
+        for (int j=0; j<3; j++){
+          Fplus = F;
+          Fplus(i,j) += _perturbationfactor;
+          this->predictorCorrector_ViscoElastic(F0,Fplus,Pplus,q0,&qtemp,false,Ttemp,Tc);
+          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;
+            }
+          }
+        }
+      }
+    }
+  } */
+};
+
+void mlawNonLinearTVM::constitutive(
+                            const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                            const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,                          // array of initial internal variable
+                                  IPVariable *q1i,                          // updated array of internal variable (in ipvcur on output),
+                                  STensor43& Tangent,                       // mechanical tangents (output)
+                            const double& T0,                               // previous temperature
+                            const double& T,                                // temperature
+                            const SVector3& gradT0,                         // previous temperature gradient
+                            const SVector3& gradT,                          // temperature gradient
+                                  SVector3& fluxT,                          // temperature flux
+                                  STensor3& dPdT,                           // mechanical-thermal coupling
+                                  STensor3& dfluxTdgradT,                   // thermal tengent
+                                  SVector3& dfluxTdT,
+                                  STensor33& dfluxTdF,                      // thermal-mechanical coupling
+                            const double& thermalSource0,
+                                  double& thermalSource,                    // - Cp*DTdt
+                                  double& dthermalSourcedT,                 // thermal source
+                                  STensor3& dthermalSourcedF,
+                            const double& mechanicalSource0,
+                                  double& mechanicalSource,                 // mechanical source --> convert to heat
+                                  double& dmechanicalSourcedT,
+                                  STensor3& dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const{
+
+  // double T = _Tref;
+
+  // this->constitutive(F0,F, P,q0i, q1i,Tangent,stiff,elasticTangent);  // Should update the mechanical stresses? ---- WHAT?
+                                        // The above line is commented and the predictorCorrector is added below to allow the usage of current temperature.
+
+  const IPNonLinearTVM *q0 = dynamic_cast<const IPNonLinearTVM *>(q0i);
+        IPNonLinearTVM *q1 = dynamic_cast<IPNonLinearTVM *>(q1i);
+  if(elasticTangent!=NULL) Msg::Error("mlawNonLinearTVM elasticTangent not defined");
+
+// Notice the current temp: Tc = T
+  if (!_tangentByPerturbation){
+    static STensor43 dFedF;
+    static STensor3 dFedT;
+    STensorOperation::unity(dFedF);
+    STensorOperation::zero(dFedT); 
+    predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                      thermalSource0,thermalSource,dthermalSourcedT,dthermalSourcedF,
+                      mechanicalSource0,mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,stiff);
+  }
+   else{
+    predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,T0,T,gradT0,gradT,fluxT,thermalSource0,thermalSource,mechanicalSource0,mechanicalSource);
+
+    static STensor3 Fplus, Pplus;
+    static SVector3 fluxTPlus, gradTplus;
+    static double thermalSourcePlus;
+    static double mechanicalSourcePlus;
+    static IPNonLinearTVM qPlus(*q0);
+
+    // perturb F
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        Fplus = (F);
+        Fplus(i,j) += _perturbationfactor;
+        predictorCorrector_ThermoViscoElastic(F0,Fplus,Pplus,q0,&qPlus,T0,T,gradT0,gradT,fluxTPlus,thermalSource0,thermalSourcePlus,mechanicalSource0,mechanicalSourcePlus);
+        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);
+          }
+          dfluxTdF(k,i,j) = (fluxTPlus(k) - fluxT(k))/_perturbationfactor;
+        }
+        dthermalSourcedF(i,j) = (thermalSourcePlus - thermalSource)/_perturbationfactor;
+        dmechanicalSourceF(i,j) = (mechanicalSourcePlus - mechanicalSource)/_perturbationfactor;
+      }
+    }
+     
+    // perturb gradT
+    double gradTpert = _perturbationfactor*T0/1e-3;
+    for (int i=0; i<3; i++){
+      gradTplus = (gradT);
+      gradTplus(i) += (gradTpert);
+      predictorCorrector_ThermoViscoElastic(F0,F,Pplus,q0,&qPlus,T0,T,gradT0,gradTplus,fluxTPlus,thermalSource0,thermalSourcePlus,mechanicalSource0,mechanicalSourcePlus);
+      for (int k=0; k<3; k++){
+        dfluxTdgradT(k,i) = (fluxTPlus(k) - fluxT(k))/gradTpert;
+      }
+    }
+    
+    // perturb on T
+    double Tplus = T+ _perturbationfactor*T0;
+    predictorCorrector_ThermoViscoElastic(F0,F,Pplus,q0,&qPlus,T0,Tplus,gradT0,gradT,fluxTPlus,thermalSource0,thermalSourcePlus,mechanicalSource0,mechanicalSourcePlus);
+    for (int k=0; k<3; k++){
+      for (int l=0; l<3; l++){
+        dPdT(k,l) = (Pplus(k,l) - P(k,l))/(_perturbationfactor*T0);
+      }
+      dfluxTdT(k) = (fluxTPlus(k) - fluxT(k))/(_perturbationfactor*T0);
+    }
+    
+    dthermalSourcedT = (thermalSourcePlus - thermalSource)/(_perturbationfactor*T0);
+    dmechanicalSourcedT = (mechanicalSourcePlus - mechanicalSource)/(_perturbationfactor*T0);
+        
+   }             
+};
+
+void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVM *q0,                       // array of initial internal variables
+                                              IPNonLinearTVM *q1,                       // updated array of internal variables (in ipvcur on output),
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                        const double& thermalSource0,
+                                              double& thermalSource,
+                                        const double& mechanicalSource0,
+                                              double& mechanicalSource) const{
+  // temp variables
+  static STensor43 Tangent, dFedF;
+  static STensor3 dPdT, dfluxTdgradT, dthermalSourcedF, dmechanicalSourceF, dFedT;
+  static STensor33 dfluxTdF;
+  static SVector3 dfluxTdT;
+  static double dthermalSourcedT, dmechanicalSourcedT;
+  predictorCorrector_ThermoViscoElastic(F0,F,P,q0,q1,Tangent,dFedF,dFedT,T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                      thermalSource0,thermalSource,dthermalSourcedT,dthermalSourcedF,
+                      mechanicalSource0,mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,false);
+}
+
+void mlawNonLinearTVM::predictorCorrector_ThermoViscoElastic(
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVM *q0,                       // array of initial internal variables
+                                              IPNonLinearTVM *q1,                       // updated array of internal variableS (in ipvcur on output),
+                                              STensor43& Tangent,                       // mechanical tangents (output)
+                                              STensor43& dFedF,                         // elastic tangent
+                                              STensor3& dFedT,                          // elastic tangent
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                              STensor3& dPdT,                           // mechanical-thermal coupling
+                                              STensor3& dfluxTdgradT,                   // thermal tengent
+                                              SVector3& dfluxTdT,
+                                              STensor33& dfluxTdF,                      // thermal-mechanical coupling
+                                        const double& thermalSource0,
+                                              double& thermalSource,                    // - Cp*dTdt
+                                              double& dthermalSourcedT,                 // thermal source
+                                              STensor3& dthermalSourcedF,
+                                        const double& mechanicalSource0,
+                                              double& mechanicalSource,                 // mechanical source --> convert to heat
+                                              double& dmechanicalSourcedT,
+                                              STensor3& dmechanicalSourceF,
+                                        const bool stiff) const{
+
+   // const bool _thermalEstimationPreviousConfig(false);  // --------  WHAT does this do?
+
+   
+    // Get shifted time if required
+    double dt = this->getTimeStep();
+    // double dt_shift(0.); shiftedTime(dt,T0,T,&dt_shift);
+    double aT_1 = ShiftFactorWLF(T);
+    
+    double T_set = setTemp(T0,T,1);  // 1->T1, 2->T_mid, 3->T_midshift 
+
+    // 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); 
+    
+    // Calculate/update Log Strain
+    static STensor3 C;
+    static STensor43 dlnCdC;
+    static STensor63 ddlnCddC;
+
+    STensor3& E = q1->getRefToElasticStrain();
+
+    STensorOperation::multSTensor3FirstTranspose(F,F,C);
+    if (_order == 1){
+        STensorOperation::logSTensor3(C,_order,E,&dlnCdC);  // as ddlogCddC = 0
+    }
+    else{
+        STensorOperation::logSTensor3(C,_order,E,&dlnCdC,&ddlnCddC);
+    }
+    E *= 0.5; // strain
+
+    // Stresses and Effective Moduli
+    double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
+    double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;  // double Wm = 0.;
+
+    ThermoViscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,Kde,Gde,DKe,DGe,DKde,DGde,KTsum,GTsum,DKDTsum,DGDTsum,T0,T); // This will update the values of moduli to the current temperatures and calculate stresses.
+    Kde = 0.; Gde = 0.;
+    
+    const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
+    static STensor3 secondPK;
+    STensorOperation::multSTensor3STensor43(corKir,dlnCdC,secondPK);
+    STensorOperation::multSTensor3(F,secondPK,P);                  // 1st PK
+    
+    // elastic energy
+    q1->_elasticEnergy = freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+
+    // thermal energy
+    q1->_thermalEnergy = CpT*T;
+
+
+    // fluxT
+    double J  = 1.;
+    STensor3 Finv(0.);
+    if (_thermalEstimationPreviousConfig){                                            // ADD  _thermalEstimationPreviousConfig -- WHAT?
+        STensorOperation::inverseSTensor3(F0,Finv);
+        J = STensorOperation::determinantSTensor3(F0);
+    }
+    else{
+        STensorOperation::inverseSTensor3(F,Finv);
+        J = STensorOperation::determinantSTensor3(F);
+    }
+    static STensor3 Cinv;
+    STensorOperation::multSTensor3SecondTranspose(Finv,Finv,Cinv);
+    STensorOperation::multSTensor3SVector3(Cinv,gradT,fluxT);
+    fluxT *= (-KThConT*J);
+
+
+    // thermalSource
+    if (this->getTimeStep() > 0.){
+        thermalSource = -CpT*(T-T0)/this->getTimeStep();
+    }
+    else
+        thermalSource = 0.;
+
+
+    // mechanicalSource   
+    mechanicalSource = 0.;     
+    static STensor3 dmechanicalSourceE;   
+  
+    double T_temp = 0.;
+    if (_testFlag == 1 || _testFlag == 3) {T_temp = T0;} else if(_testFlag == 2) {T_temp = setTemp(T0,T,2);} // CHANGE the latter - case 2 of double convolution
+  
+    // CorKir derivatives wrt T 
+    static STensor3 DcorKirDT;
+    static STensor3 DDcorKirDT;    // for mech source derivatives
+    STensorOperation::zero(DcorKirDT); 
+    STensorOperation::zero(DDcorKirDT); 
+
+
+    // Add corKirinf terms to DcorKirDT  
+    static STensor3 corKirDevInf, devEe; 
+    static double corKirTrInf, trEe; 
+    STensorOperation::decomposeDevTr(E,devEe,trEe);
+    
+    static STensor3 DEe;
+    DEe = E;
+    DEe -= q0->_Ee;
+    q1->_DE = DEe;
+    STensor3& devDE = q1->getRefToDevDE();
+    double& trDE = q1->getRefToTrDE();
+    STensorOperation::decomposeDevTr(DEe,devDE,trDE);
+    
+    corKirInfinity( devEe, trEe, T, corKirDevInf, corKirTrInf );
+
+    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
+        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);
+        for (int j=0; j<3; j++){
+            // DcorKirDT(i,j) += corKirDev(i,j)/(Ge+Gde*(T-T_temp))*(DGe + DGde*(T-T_temp)) ;                                         // 1st formulation
+            DcorKirDT(i,j) += corKirDevInf(i,j)*DGDT/GT;
+            DDcorKirDT(i,j) += corKirDevInf(i,j)*DDGDT/GT;
+        }
+    }
+  
+    // Add visco terms 
+    if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+      
+        // Update the Branch Moduli to the current temperature
+        std::vector<double> KiT, GiT, AlphaiT, DKiDT, DGiDT, DAlphaiDT, DDKiDT, DDGiDT, DDAlphaiDT; 
+        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); 
+        } 
+      
+        static STensor3 DQiDT; 
+        static STensor3 DDQiDT; 
+        static STensor3 DGammaiDT;
+        
+        static STensor3 DqiDT; 
+        static STensor3 DDqiDT; 
+        static STensor3 DDgammaiDT;
+  
+        STensor3 DDGammaiDT;
+        STensor3 DGammai, Qi, temp_WmDQDE, temp_WmDGammaDE; 
+        STensor3 Dgammai, qi, temp_WmDqDE, temp_WmDgammaDE;
+    
+        const std::vector<STensor3>& devQi = q1->getConstRefToDevViscoElasticStress();
+        const std::vector<double>& trQi = q1->getConstRefToTrViscoElasticStress();
+        const std::vector<STensor3>& devQi_0 = q0->getConstRefToDevViscoElasticStress();
+        const std::vector<double>& trQi_0 = q0->getConstRefToTrViscoElasticStress();
+        
+        const std::vector<STensor3>& devGammai = q1->getConstRefToDevViscoElasticStrain();
+        const std::vector<double>& trGammai = q1->getConstRefToTrViscoElasticStrain();
+        const std::vector<STensor3>& devGammai_0 = q0->getConstRefToDevViscoElasticStrain();
+        const std::vector<double>& trGammai_0 = q0->getConstRefToTrViscoElasticStrain();
+        
+        std::vector<STensor3>& devDGammaiDT = q1->getRefToDevDGammaiDT();
+        std::vector<double>& trDGammaiDT = q1->getRefToTrDGammaiDT();
+        const std::vector<STensor3>& devDGammaiDT_0 = q0->getConstRefToDevDGammaiDT();
+        const std::vector<double>& trDGammaiDT_0 = q0->getConstRefToTrDGammaiDT();
+        
+        double dt_shift, Ddt_shiftDT, DDdt_shiftDT = 0.; 
+        shiftedTime(dt,T0,T,&dt_shift,&Ddt_shiftDT,&DDdt_shiftDT); // the convolution term with mid step approximation exponential
+        q1->_dtShift = dt_shift; q1->_DdtShiftDT = Ddt_shiftDT; q1->_DDdtShiftDDT = DDdt_shiftDT;
+        
+        double dt_shift_rec, Ddt_shiftDT_rec, DDdt_shiftDT_rec = 0.;
+        shiftedTime(dt,T0,T,&dt_shift_rec,&Ddt_shiftDT_rec,&DDdt_shiftDT_rec,0); // the recursive term exponential
+        
+        double dtg,dtk,dtg2,dtk2,expdtk,expdtg,expdtkby2,expdtgby2 = 0.;
+        
+        if(stiff){
+            dmechanicalSourcedT = 0;
+            STensorOperation::zero(dmechanicalSourceE); 
+        }
+            
+        // Construct Qi, DQiDT and DDQiDT tensors
+        for (int i=0; i<_Gi.size(); i++){
+            
+            dtk = dt_shift_rec/(_ki[i]); dtg = dt_shift_rec/(_gi[i]); expdtk = exp(-dtk); expdtg = exp(-dtg); 
+            
+            dtk2 = dt_shift/(_ki[i]); dtg2 = dt_shift/(_gi[i]); 
+            expdtkby2 = exp(-dtk2); // exp(-dtk/2.);
+            expdtgby2 = exp(-dtg2); // exp(-dtk/2.);
+            
+            
+            STensorOperation::zero(Qi); STensorOperation::zero(DQiDT); STensorOperation::zero(DDQiDT); 
+            STensorOperation::zero(DGammai); STensorOperation::zero(DGammaiDT); STensorOperation::zero(DDGammaiDT); 
+        
+            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;
+            }
+            
+            double DT(0.);
+            if ( (T-T0)<1e-8){ DT = T0*(1e-1);}
+            else { DT = T-T0;}
+            
+            for (int j=0; j<3; j++){
+                
+                // + _Ki[i]*expdtkby2* (trDE-q0->_trDE)/DT; 1/3*
+                DQiDT(j,j) += (trQi[i]-trQi_0[i]*expdtk)*(-1/(_ki[i])) * Ddt_shiftDT ; 
+                DQiDT(j,j) += trQi_0[i]*expdtk*(-1/(_ki[i])) * Ddt_shiftDT_rec ; 
+                
+                Qi(j,j) += trQi[i];
+                // Qi(j,j) -= T*DQiDT(j,j);
+                 
+                DDQiDT(j,j) += (trQi[i]-trQi_0[i]*expdtk)*( (-1/(_ki[i])) * DDdt_shiftDT + (-1/(_ki[i]))*Ddt_shiftDT*(-1/(_ki[i]))*Ddt_shiftDT);
+                DDQiDT(j,j) += trQi_0[i]*expdtk*( (-1/(_ki[i])) * DDdt_shiftDT_rec + (-1/(_ki[i]))*Ddt_shiftDT_rec*(-1/(_ki[i]))*Ddt_shiftDT_rec);
+                
+                DGammai(j,j) += 1/3*trGammai[i];
+                DGammai(j,j) -= 1/3*trGammai_0[i];
+                
+                DGammaiDT(j,j) += 1/3*(trGammai[i]-trGammai_0[i]*expdtk)*(-1/(_ki[i])* Ddt_shiftDT);
+                DGammaiDT(j,j) += 1/3*trGammai_0[i]*expdtk*(-1/(_ki[i])* Ddt_shiftDT_rec);
+                // DGammaiDT(j,j) -= trGammai_0[i]*(-1/(_ki[i]))* (q0->_DdtShiftDT);
+                
+                trDGammaiDT[i] = DGammaiDT(j,j);
+                DDGammaiDT(j,j) = DGammaiDT(j,j) - q0->_trDGammaiDT[i];
+                
+                for (int k=0; k<3; k++){
+                    
+                    // + 2*_Gi[i]*expdtgby2*(devDE(j,k)-q0->_devDE(j,k))/DT; *2
+                    DQiDT(j,k) += (devQi[i](j,k)-devQi_0[i](j,k)*expdtg)*(-1/(_gi[i])) * Ddt_shiftDT ; 
+                    DQiDT(j,k) += devQi_0[i](j,k)*expdtg*(-1/(_gi[i])) * Ddt_shiftDT_rec ; 
+                    
+                    Qi(j,k) += devQi[i](j,k);
+                    // Qi(j,k) -= T*DQiDT(j,k);
+                    
+                    DDQiDT(j,k) += (devQi[i](j,k)-devQi_0[i](j,k)*expdtg)*( (-1/(_gi[i])) * DDdt_shiftDT + (-1/(_gi[i]))*Ddt_shiftDT*(-1/(_gi[i]))*Ddt_shiftDT );
+                    DDQiDT(j,k) += devQi_0[i](j,k)*expdtg*( (-1/(_gi[i])) * DDdt_shiftDT_rec + (-1/(_gi[i]))*Ddt_shiftDT_rec*(-1/(_gi[i]))*Ddt_shiftDT_rec );
+                    
+                    DGammai(j,k) += devGammai[i](j,k); 
+                    DGammai(j,k) -= devGammai_0[i](j,k);
+                    
+                    DGammaiDT(j,k) += (devGammai[i](j,k)-devGammai_0[i](j,k)*expdtg)*(-1/(_gi[i])* Ddt_shiftDT);
+                    DGammaiDT(j,k) += devGammai_0[i](j,k)*expdtg*(-1/(_gi[i])* Ddt_shiftDT_rec);
+                    // DGammaiDT(j,k) -= devGammai_0[i](j,k)*(-1/(_gi[i])* (q0->_DdtShiftDT));
+                    
+                    devDGammaiDT[i](j,k) = DGammaiDT(j,k);
+                    DDGammaiDT(j,k) = DGammaiDT(j,k) - q0->_devDGammaiDT[i](j,k);
+                }
+            }
+            
+            // Corrected Viscous Tensors
+            STensorOperation::zero(qi); STensorOperation::zero(DqiDT); STensorOperation::zero(DDqiDT); 
+            STensorOperation::zero(Dgammai); STensorOperation::zero(DDgammaiDT);
+            DqiDT -= DQiDT; DDqiDT -= DDQiDT; DDgammaiDT -= DDGammaiDT;
+            for (int j=0; j<3; j++){
+                qi(j,j) += (_Ki[i]*trEe - trQi[i]);
+                // DDgammaiDT(j,j) -= DDGammaiDT(j,j);
+                for (int k=0; k<3; k++){
+                    qi(j,k) += (2*_Gi[i]*devEe(j,k) - devQi[i](j,k)); 
+                    // DDgammaiDT(j,k) -= DDGammaiDT(j,k);
+                }
+            }
+            Dgammai += DEe;
+            Dgammai -= DGammai;
+            qi -= (T*DqiDT);
+            
+            // corKir Derivatives
+            DcorKirDT += DQiDT;
+            DDcorKirDT += DDQiDT;
+             
+                    
+            // static STensor43 temp_DDQiDTDE;
+            // static STensor43 temp_DDGammiDtDE;
+            static STensor43 temp_DDqiDTDE;
+            static STensor43 temp_DDgammiDtDE;
+            
+            // dmechanicalSourceE and dmechanicalSourceT  
+            // isotropicHookTensor( (KiT[i]*expdtkby2-T*DKiDT[i]), (GiT[i]*expdtgby2-T*DGiDT[i]), temp_DDQiDTDE ); 
+            // isotropicHookTensor( (expdtkby2), (expdtgby2), temp_DDGammiDtDE ); 
+            
+            double Ki_term = (_Ki[i]*(1-expdtkby2)+T*DKiDT[i]);
+            double Gi_term = (_Gi[i]*(1-expdtgby2)+T*DGiDT[i]);
+            // isotropicHookTensor( (_Ki[i]*(1-expdtkby2)+T*DKiDT[i]), (_Gi[i]*(1-expdtgby2)+T*DGiDT[i]), temp_DDqiDTDE ); 
+            isotropicHookTensor( Ki_term, Gi_term , temp_DDqiDTDE ); 
+            //isotropicHookTensor( (1-expdtkby2), (1-expdtgby2), temp_DDgammiDtDE ); 
+            
+            double Ki_term_2 = 1/3*expdtkby2;
+            double Gi_term_2 = 0.5*expdtgby2;
+            isotropicHookTensor( Ki_term_2, Gi_term_2, temp_DDgammiDtDE ); 
+        
+            // For convenience -> Add the TVE Term here
+            STensorOperation::zero(temp_WmDqDE); STensorOperation::zero(temp_WmDgammaDE); 
+            
+            if (this->getTimeStep() > 0){
+                
+                // mechanicalSource += (STensorOperation::doubledot(Qi,DGammai)/this->getTimeStep()); // viscoelastic heat  (added to mechSource)
+                mechanicalSource += (STensorOperation::doubledot(qi,Dgammai)/this->getTimeStep()); // viscoelastic heat  (added to mechSource)
+                static const STensor3 I(1.);
+                static STensor43 I4_3(1.,1.);
+                // mechanicalSource += (STensorOperation::doubledot(qi,I)/this->getTimeStep()); // viscoelastic heat  (added to mechSource) //TEST
+                    if (stiff){
+                    
+                        // dmechanicalSourcedT -= (STensorOperation::doubledot(DDQiDT,DGammai))*T/this->getTimeStep();
+                        // dmechanicalSourcedT += (STensorOperation::doubledot(Qi,DDGammaiDT))/this->getTimeStep();
+                       
+                        dmechanicalSourcedT -= (STensorOperation::doubledot(DDqiDT,Dgammai))*T/this->getTimeStep();  // 1st Term
+                        // dmechanicalSourcedT += (STensorOperation::doubledot(qi,DDgammaiDT))/this->getTimeStep(); // This term is wrong
+                        dmechanicalSourcedT -= (STensorOperation::doubledot(qi,DGammaiDT))/this->getTimeStep();  // 2nd Term
+                       
+            
+                        // STensorOperation::multSTensor43STensor3SecondTranspose(temp_DDQiDTDE,DGammai,temp_WmDQDE);
+                        for (int l=0; l<3; l++){
+                          for (int m=0; m<3; m++){
+                            // temp_WmDQDE(l,m) = 0.;  
+                            temp_WmDqDE(l,m) = 0.;  
+                            for (int n=0; n<3; n++){
+                              for (int p=0; p<3; p++){
+                                // temp_WmDQDE(l,m) += temp_DDQiDTDE(l,m,n,p)*DGammai(n,p)/this->getTimeStep();
+                                temp_WmDqDE(l,m) += temp_DDqiDTDE(l,m,n,p)*Dgammai(n,p)/this->getTimeStep();
+                                // temp_WmDqDE(l,m) += temp_DDqiDTDE(l,m,n,p)*I(n,p)/this->getTimeStep();
+                              }
+                            }
+                          }         
+                        }
+                        
+                        for (int l=0; l<3; l++){
+                          for (int m=0; m<3; m++){
+                            // temp_WmDGammaDE(l,m) = 0.;  
+                            temp_WmDgammaDE(l,m) = 0.;  
+                            for (int n=0; n<3; n++){
+                              for (int p=0; p<3; p++){
+                                // temp_WmDGammaDE(l,m) += Qi(n,p)*temp_DDGammiDtDE(n,p,l,m)/this->getTimeStep();
+                                temp_WmDgammaDE(l,m) += qi(n,p)*I4_3(n,p,l,m)/this->getTimeStep();
+                                temp_WmDgammaDE(l,m) -= qi(n,p)*temp_DDgammiDtDE(n,p,l,m)/this->getTimeStep();
+                              }
+                            }
+                          }         
+                        }
+                        
+        
+                        // dmechanicalSourceE += temp_WmDQDE;  
+                        // dmechanicalSourceE += temp_WmDGammaDE;  
+                        dmechanicalSourceE += temp_WmDqDE;  
+                        dmechanicalSourceE += temp_WmDgammaDE;  
+        
+                    }
+            }
+        }
+    }
+  
+    // ThermoElastic Heat
+    // static STensor3 DEe;
+    // DEe = E;
+    // DEe -= q0->_Ee;
+    if (this->getTimeStep() > 0){
+        mechanicalSource += (STensorOperation::doubledot(DcorKirDT,DEe)*T/this->getTimeStep());    // thermoelastic heat   (added to mechSource)
+    }
+    
+
+    if (stiff){
+     
+        // 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
+        
+        static STensor43 DCeDFe; //(0.);
+        static STensor43 DEeDFe(0.);
+        STensorOperation::unity(dFedF);
+        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);
+              }
+            }
+          }
+         }
+        }
+        /*
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int q=0; q<3; q++){ 
+                    DCeDFe(i,j,j,q) += F(i,q);
+                }
+            }
+        }
+        for (int q=0; q<3; q++){
+            for (int j=0; j<3; j++){
+                for (int p=0; p<3; p++){ 
+                    DCeDFe(q,j,p,j) += F(q,p);
+                }
+            }
+        }*/
+        STensorOperation::multSTensor43(dlnCdC,DCeDFe,DEeDFe);
+        DEeDFe *= 0.5;
+        
+        static STensor43 DsecondPKdC;
+        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++){
+                        DsecondPKdC(i,j,k,l) = 0.;
+                            for (int p=0; p<3; p++){
+                                for (int q=0; q<3; q++){
+                                    if (_order != 1){
+                                        DsecondPKdC(i,j,k,l) += corKir(p,q)*ddlnCddC(p,q,i,j,k,l);
+                                    }
+                                    for (int r=0; r<3; r++){
+                                        for (int s=0; s<3; s++){
+                                            DsecondPKdC(i,j,k,l) += 0.5*DcorKDE(p,q,r,s)*dlnCdC(p,q,i,j)*dlnCdC(r,s,k,l);
+                                        }
+                                    }
+                                }
+                            }
+                    }
+                }
+            }
+        }
+
+        STensorOperation::zero(Tangent);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int p=0; p<3; p++){
+                    Tangent(i,j,i,p) += secondPK(p,j);
+                    for (int q=0; q<3; q++){
+                        for (int s=0; s<3; s++){
+                            for (int k=0; k<3; k++){
+                                Tangent(i,j,p,q) += 2.*F(i,k)*DsecondPKdC(k,j,q,s)*F(p,s);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        // Compute Mechano-thermal Tangents - dSdT and dPdT
+        static STensor3 DSDT;
+        STensorOperation::zero(DSDT);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int r=0; r<3; r++){
+                    for (int s=0; s<3; s++){
+                        DSDT(i,j) += DcorKirDT(r,s)*dlnCdC(r,s,i,j);
+                    }
+                }
+            }
+        }
+
+        STensorOperation::zero(dPdT);
+        STensorOperation::multSTensor3(F,DSDT,dPdT); 
+
+/*
+
+        STensor3 invFp0(1.);                                        // For plasticity you will have to CHANGE this!!
+        static STensor3 Fepr;
+        STensorOperation::multSTensor3(F,invFp0,Fepr);
+        static STensor43 EprToF;
+        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++){
+                        EprToF(i,j,k,l) = 0.;
+                        for (int p=0; p<3; p++){
+                            for (int q=0; q<3; q++){
+                                EprToF(i,j,k,l) += dlnCdC(i,j,p,q)*Fepr(k,p)*invFp0(l,q);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        static STensor43 DcorKirDF;
+        STensorOperation::multSTensor43(DcorKDE,dlnCdC,DcorKirDF);
+        // done DcorKirDF, DcorKirDT
+
+        // STensorOperation::zero(dFedF);                                        // CHANGE for plasticity
+        // STensorOperation::unity(dFedF);
+        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++)
+               if((i == k) && (j == l))
+                 dFedF(i,j,k,l) = 1.0;
+               else
+                 dFedF(i,j,k,l) = 0.0;
+        // STensorOperation::zero(dFedT);                                           // CHANGE for plasticity
+
+
+        // L = dlnCdC;
+        // dLDCe = ddlnCddC;
+        static STensor63 DLDF;
+        // static STensor43 DLDT;
+        STensorOperation::zero(DLDF);
+        // STensorOperation::zero(DLDT);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int k=0; k<3; k++){
+                    for (int l=0; l<3; l++){
+                        for (int r=0; r<3; r++){
+                            for (int s=0; s<3; s++){
+                                for (int a=0; a<3; a++){
+                                    // DLDT(i,j,k,l) += ddlnCddC(i,j,k,l,r,s)*2.*F(a,r)*dFedT(a,s);            // dLDCe is the 2nd derivative
+                                    for (int p=0; p<3; p++){
+                                        for (int q=0; q<3; q++){
+                                            DLDF(i,j,k,l,p,q) += ddlnCddC(i,j,k,l,r,s)*2.*F(a,r)*dFedF(a,s,p,q);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }   
+            }
+        }
+
+
+        static STensor43 DSDF; // S = corKir:L     (L = dlnCdC)
+        // static STensor3 DSDT;
+        STensorOperation::zero(DSDF);
+        // STensorOperation::zero(DSDT);
+        for (int i=0; i<3; i++){
+            for (int j=0; j<3; j++){
+                for (int r=0; r<3; r++){
+                    for (int s=0; s<3; s++){
+                        // DSDT(i,j) += DcorKirDT(r,s)*dlnCdC(r,s,i,j) + corKir(r,s)*DLDT(r,s,i,j);
+                        for (int k=0; k<3; k++){
+                            for (int l=0; l<3; l++){
+                                DSDF(i,j,k,l) += DcorKirDF(r,s,k,l)*dlnCdC(r,s,i,j) + corKir(r,s)*DLDF(r,s,i,j,k,l);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    
+        // compute mechanical tengent                                                         // CHANGE for plasticity
+        STensorOperation::zero(Tangent);
+        // STensorOperation::zero(dPdT);
+        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++){
+                        // dPdT(i,j) += (dFedT(i,k)*secondPK(k,l) + F(i,k)*DSDT(k,l));
+                        for (int p=0; p<3; p++){
+                            for (int q=0; q<3; q++){
+                                Tangent(i,j,p,q) += (dFedF(i,k,p,q)*secondPK(k,l) + F(i,k)*DSDF(k,l,p,q));
+                            }
+                        }
+                    }
+                }
+            }
+        }
+*/
+
+        // fluxT  derivatives
+        dfluxTdT = fluxT;
+        dfluxTdT *= (DKThConDT/KThConT);
+        dfluxTdgradT = Cinv;
+        dfluxTdgradT *= (-KThConT*J);
+        STensorOperation::zero(dfluxTdF);
+
+        if (!_thermalEstimationPreviousConfig){
+            static const STensor43 I4(1.,1.);
+            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);
+                        }
+                    }
+                }
+            }
+        }
+
+
+        // thermal source derivatives
+        static STensor3 DCpDF;
+        STensorOperation::zero(DCpDF);                                                       // CHANGE for DCpDF 
+        if (this->getTimeStep() > 0){
+            dthermalSourcedT = -CpT/this->getTimeStep() - DCpDT*(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();          // --- See below for perturbation implementation
+                }
+            }
+        }
+        else{
+            dthermalSourcedT = 0.;
+            STensorOperation::zero(dthermalSourcedF); 
+        }
+                                    
+
+
+        // mechanical source derivatives                                                 --- CHANGE for TVE terms
+        if (_N<1){
+           STensorOperation::zero(dmechanicalSourceE);
+           dmechanicalSourcedT = 0;
+        }
+        STensorOperation::zero(dmechanicalSourceF);
+        
+        static STensor3 CorKir_WmDE; STensorOperation::zero(CorKir_WmDE);
+        static STensor43 DDcorKirDTDE;
+        // isotropicHookTensor(DKe,DGe,DDcorKirDTDE); 
+        isotropicHookTensor(DKDTsum,DGDTsum,DDcorKirDTDE); 
+        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++){
+                        CorKir_WmDE(i,j) += DDcorKirDTDE(i,j,k,l)*DEe(k,l);
+                    }
+                }
+            }
+        }
+        
+        static const STensor43 I4_2(1.,1.);
+        static STensor3 DcorKirDT_I;
+        STensorOperation::multSTensor3STensor43(DcorKirDT,I4_2,DcorKirDT_I);
+        
+
+        
+        if (this->getTimeStep() > 0){
+            for (int i=0; i<3; i++){
+                for (int j=0; j<3; j++){
+                    // perturb F
+                    // double pertF = 0.; pertF = F(i,j)-F0(i,j); if (pertF>0){ // dthermalSourcedF(i,j) += (thermalSource - thermalSource0)/pertF; dmechanicalSourceF(i,j) += (mechanicalSource - mechanicalSource0)/pertF;}
+                    dmechanicalSourceE(i,j) += T*( CorKir_WmDE(i,j) + DcorKirDT_I(i,j) )/this->getTimeStep();
+                }
+            }
+            // STensorOperation::multSTensor3STensor43(dmechanicalSourceE,dlnCdC,dmechanicalSourceF);
+            // STensorOperation::multSTensor3(F,dmechanicalSourceF,dmechanicalSourceF);
+            STensorOperation::multSTensor3STensor43(dmechanicalSourceE,DEeDFe,dmechanicalSourceF);
+        
+            dmechanicalSourcedT += (STensorOperation::doubledot(DcorKirDT,DEe)/this->getTimeStep());
+            dmechanicalSourcedT += T*(STensorOperation::doubledot(DDcorKirDT,DEe)/this->getTimeStep());
+            
+            /*
+            double dT(0.);
+            if ( (T-T0)<1e-8){ dT = T0*(1e-1);}
+            else { dT = T-T0;}
+            static STensor3 DDE;
+            DDE = q1->_DE; DDE -= q0->_DE;
+            dmechanicalSourcedT -= T*(STensorOperation::doubledot(DcorKirDT,DDE)/this->getTimeStep())/dT;*/
+                        
+        }
+    
+        // perturb T
+        // double pertT = T-T0; if (pertT>0){dmechanicalSourcedT += (mechanicalSource - mechanicalSource0)/pertT;}
+    }
+};
+
+
+// ========================================================================================================================================
+// Unused Member Functions
+
+double mlawNonLinearTVM::soundSpeed() const {   // Correct this for current temperature
+    return sqrt((_K+4.*_G/3.)/_rho);
+}
+
+/*
+// Use this for Plasticity Later
+void mlawNonLinearTVM::updateViscoElasticFlow(const IPNonLinearTVM *q0, IPNonLinearTVM *q1, double& Ke, double& Ge, const double Tc) 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);
+    // temFuncGlassTransition(Tc,_opt,_K,9.0,KT); temFuncGlassTransition(Tc,_opt,_G,9.0,GT);
+    
+
+  if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+      
+    // Update the Branch Moduli to the current temperature
+    std::vector<double> KiT,GiT; KiT.resize(_N,0.); GiT.resize(_N,0.);
+    getKi(KiT,Tc); getGi(GiT,Tc);
+    /*for (int i=0; i<_Ki.size(); i++){
+        double KiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Ki[i],9.0,KiT_inter);
+        KiT[i] = KiT_inter;
+    }
+    for (int i=0; i<_Gi.size(); i++){
+        double GiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Gi[i],9.0,GiT_inter);
+        GiT[i] = GiT_inter;
+    }*/
+/*
+    double dt = this->getTimeStep();
+    if (_viscoMethod == Maxwell){
+      static STensor3 DE, devDE;
+      static double trDE;
+
+      DE = q1->_Ee;
+      DE -= q0->_Ee;
+      STensorOperation::decomposeDevTr(DE,devDE,trDE);
+
+      // maxwell
+     // Ge = _G; Ke = _K;
+      Ge = GT; Ke = KT;
+      
+      
+      for (int i=0; i<_Gi.size(); i++){
+        double dtg = dt/_gi[i];
+        double expmdtg = exp(-dtg);
+        double ztag = exp(-dtg/2.);
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            q1->_A[i](k,l) = expmdtg*q0->_A[i](k,l) + ztag*devDE(k,l);
+          }
+        }
+       // Ge += _Gi[i]*ztag;
+        Ge += GiT[i]*ztag;
+      }
+      for (int i=0; i<_Ki.size(); i++){
+        double dtk = dt/_ki[i];
+        double expmdtk = exp(-dtk);
+        double ztak = exp(-dtk/2.);
+        q1->_B[i] = q0->_B[i]*expmdtk +ztak*trDE;
+        // Ke += _Ki[i]*ztak;
+        Ke += KiT[i]*ztak;
+      }
+    }
+    else if (_viscoMethod == KelvinVoight){
+      static STensor3 DK, devDK;
+      static double trDK;
+
+      DK = q1->_kirchhoff;
+      DK -= q0->_kirchhoff;
+
+      STensorOperation::decomposeDevTr(DK,devDK,trDK);
+
+      // update internal variable from stress increment
+      for (int i=0; i< _Gi.size(); i++)
+      {
+        STensorOperation::zero(q1->_A[i]);
+        double dtg = dt/(_gi[i]);
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+           // q1->_A[i](k,l) += exp(-dtg)*q0->_A[i](k,l) + exp(-dtg/2.)*devDK(k,l)/(2.*_Gi[i]);
+            q1->_A[i](k,l) += exp(-dtg)*q0->_A[i](k,l) + exp(-dtg/2.)*devDK(k,l)/(2.*GiT[i]);
+          }
+        }
+      }
+
+      for (int i=0; i< _Ki.size(); i++){
+        q1->_B[i] = 0.;
+        double dtk = dt/(_ki[i]);
+        // q1->_B[i] += exp(-dtk)*q0->_B[i] + exp(-dtk/2.)*trDK/(3.*_Ki[i]);
+        q1->_B[i] += exp(-dtk)*q0->_B[i] + exp(-dtk/2.)*trDK/(3.*KiT[i]);
+      }
+    }
+    else{
+      Msg::Error("visco elastic method %d has not been defined");
+    }
+  }
+}; */
+
+/* 
+double mlawNonLinearTVM::deformationEnergy(const IPNonLinearTVM& q, const double Tc) 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);
+    // temFuncGlassTransition(Tc,_opt,_K,9.0,KT); temFuncGlassTransition(Tc,_opt,_G,9.0,GT);
+
+    std::vector<double> KiT,GiT; KiT.resize(_N,0.); GiT.resize(_N,0.);
+    getKi(KiT,Tc); getGi(GiT,Tc);
+    /*for (int i=0; i<_Ki.size(); i++){
+        double KiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Ki[i],9.0,KiT_inter);
+        KiT[i] = KiT_inter;
+    }
+    for (int i=0; i<_Gi.size(); i++){
+        double GiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Gi[i],9.0,GiT_inter);
+        GiT[i] = GiT_inter;
+    }*/
+/*    
+  double Psy = 0.;
+  if (_viscoMethod == Maxwell)
+  {
+    double trEe;
+    static STensor3 devEe;
+    STensorOperation::decomposeDevTr(q._Ee,devEe,trEe);
+    
+    // Psy = _K*0.5*trEe*trEe+_G*STensorOperation::doubledot(devEe,devEe);
+    
+    double Eth = 3.*alphaT*(Tc-_Tinitial);                                                         // ADDED thermal strain   ---- CHANGE!!!
+    
+    Psy = KT*0.5*(trEe-Eth)*(trEe-Eth) + GT*STensorOperation::doubledot(devEe,devEe);
+
+    for (int i=0; i<_N; i++){
+      static STensor3 devEebranch;
+      devEebranch = devEe;
+      devEebranch -= q._A[i];
+      // Psy += _Ki[i]*0.5*(trEe-q._B[i])*(trEe-q._B[i])+_Gi[i]*STensorOperation::doubledot(devEebranch,devEebranch);
+      Psy += KiT[i]*0.5*(trEe-q._B[i])*(trEe-q._B[i])+GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
+    }    
+  }
+  else if (_viscoMethod == KelvinVoight)
+  {
+    // needs to be complete
+    
+    // ADDED thermal strain
+    double thermalStrain = - alphaT*(Tc-_Tinitial);  // divided by 3, since we are directly adding to the tensor below.
+    STensor3 Ee_KV;                             // temporary Ee_KelvinVoight tensor
+    STensorOperation::zero(Ee_KV);
+    STensorOperation::diag(Ee_KV,thermalStrain);
+    Ee_KV += q._Ee;
+    Psy = 0.5*STensorOperation::doubledot(Ee_KV,q._kirchhoff);
+
+    // Psy = 0.5*STensorOperation::doubledot(q._Ee,q._kirchhoff);
+    
+    for (int i=0; i<_N; i++){
+      static STensor3 Ev;
+      q.getViscoElasticStrain(i+1,Ev);
+      // ADDED thermal strain
+      STensor3 Ev_KV;                             // temporary Ev_KelvinVoight tensor
+      STensorOperation::zero(Ev_KV);
+      STensorOperation::diag(Ev_KV,thermalStrain);
+      Ev_KV += Ev;
+      Psy += 0.5*STensorOperation::doubledot(Ev_KV,q._kirchhoff);
+
+      // Psy += 0.5*STensorOperation::doubledot(Ev,q._kirchhoff);
+    }
+  }
+  else{
+    Msg::Error("visco elastic method %d has not been defined");
+  }
+
+  return Psy;;
+}
+*/
+
+/*
+void mlawNonLinearTVM::viscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
+          double& Ke, double& Ge, const double Tc) 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);
+    // temFuncGlassTransition(Tc,_opt,_K,9.0,KT); temFuncGlassTransition(Tc,_opt,_G,9.0,GT);
+
+  if ((_Ki.size() > 0) or (_Gi.size() > 0)){
+      
+    // Update the Branch Moduli to the current temperature
+    std::vector<double> KiT,GiT; KiT.resize(_N,0.); GiT.resize(_N,0.);
+    getKi(KiT,Tc); getGi(GiT,Tc);
+    /*for (int i=0; i<_Ki.size(); i++){
+        double KiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Ki[i],9.0,KiT_inter);
+        KiT[i] = KiT_inter;
+    }
+    for (int i=0; i<_Gi.size(); i++){
+        double GiT_inter = 0; temFuncGlassTransition(Tc,_opt,_Gi[i],9.0,GiT_inter);
+        GiT[i] = GiT_inter;
+    }*/
+    
+ /*   
+    static STensor3 DE, devDE;
+    static double trDE;
+    DE =  Ee;
+    DE -= Ee0;
+    STensorOperation::decomposeDevTr(DE,devDE,trDE);
+
+    double dt = this->getTimeStep();
+    if (_viscoMethod == Maxwell){
+      // Ge = _G; Ke = _K;
+      Ge = GT; Ke = KT;
+      for (int i=0; i<_Gi.size(); i++){
+        double dtg = dt/_gi[i];
+        double expmdtg = exp(-dtg);
+        double ztag = exp(-dtg/2.);
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            q1->_A[i](k,l) = expmdtg*q0->_A[i](k,l) + ztag*devDE(k,l);
+          }
+        }
+       // Ge += _Gi[i]*ztag;
+        Ge += GiT[i]*ztag;
+      }
+      for (int i=0; i<_Ki.size(); i++){
+        double dtk = dt/_ki[i];
+        double expmdtk = exp(-dtk);
+        double ztak = exp(-dtk/2.);
+        q1->_B[i] = q0->_B[i]*expmdtk +ztak*trDE;              // Check this with the formula once --- CHANGE!!!
+       // Ke += _Ki[i]*ztak;
+       Ke += KiT[i]*ztak;
+      }
+
+      static STensor3 devK;
+      static double p;
+      STensorOperation::decomposeDevTr(Ee,devK,p);
+      // devK *= (2.*_G);  // deviatoric part
+      devK *= (2.*GT);  // deviatoric part
+      // p *= _K; // pressure
+      p *= KT; // pressure
+
+      for (int i=0; i<_Gi.size(); i++){
+       // devK.daxpy(q1->_A[i],2.*_Gi[i]);
+       devK.daxpy(q1->_A[i],2.*GiT[i]);
+      }
+      for (int i=0; i<_Ki.size(); i++){
+       // p += q1->_B[i]*_Ki[i];
+       p += q1->_B[i]*KiT[i];
+      }
+
+
+      p -= 3.*Ke*alphaT*(Tc-_Tinitial);                  // ADDED - thermal strain               -  CHANGE with scalarTgFunc,
+                                                                        // CHANGE for Maxwell (this is wrong, branch stifness contribution to thermal strains is absent)                                                                        
+      q1->_kirchhoff = devK;
+      q1->_kirchhoff(0,0) += p;
+      q1->_kirchhoff(1,1) += p;
+      q1->_kirchhoff(2,2) += p;
+    }
+    else if (_viscoMethod == KelvinVoight){
+      // double invGe = 1./_G;
+      double invGe = 1./GT;
+      STensor3 D(0.);
+      for (int i=0; i<_Gi.size(); i++){
+        double dtg = dt/(_gi[i]);
+       // invGe += (1.-exp(-dtg/2.))/_Gi[i];
+        invGe += (1.-exp(-dtg/2.))/GiT[i];
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            D(k,l) += q0->_A[i](k,l)*(exp(-dtg)-1.);
+          }
+        }
+      }
+      Ge = 1./invGe;
+
+     // double invKe = 1./_K;
+      double invKe = 1./KT;
+      double V= 0.;
+      for (int i=0; i<_Ki.size(); i++){
+        double dtk = dt/(_ki[i]);
+        // invKe += (1.-exp(-dtk/2))/_Ki[i];
+        invKe += (1.-exp(-dtk/2))/KiT[i];
+        V += q0->_B[i]*(exp(-dtk)-1.);
+      }
+      Ke = 1./invKe;
+
+      // stress increment
+      static STensor3 DdevK;
+      DdevK = devDE; // dev corotational kirchoff stress predictor
+      DdevK += D;
+      DdevK *= (2.*Ge);
+      double Dp = Ke*(trDE+ V); // pressure predictor
+      
+      Dp -= 3.*Ke*alphaT*(Tc-_Tinitial);                  // ADDED - thermal strain               -  CHANGE with scalarTgFunc
+      
+      //update internal variable from stress increment
+      for (int i=0; i< _Gi.size(); i++){
+        STensorOperation::zero(q1->_A[i]);
+        double dtg = dt/(_gi[i]);
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+        //    q1->_A[i](k,l) += exp(-dtg)*q0->_A[i](k,l) + exp(-dtg/2.)*DdevK(k,l)/(2.*_Gi[i]);
+            q1->_A[i](k,l) += exp(-dtg)*q0->_A[i](k,l) + exp(-dtg/2.)*DdevK(k,l)/(2.*GiT[i]);
+          }
+        }
+      }
+
+      for (int i=0; i< _Ki.size(); i++){
+        q1->_B[i] = 0.;
+        double dtk = dt/(_ki[i]);
+       // q1->_B[i] += exp(-dtk)*q0->_B[i] + exp(-dtk/2.)*Dp/(_Ki[i]);
+        q1->_B[i] += exp(-dtk)*q0->_B[i] + exp(-dtk/2.)*Dp/(KiT[i]);
+      }
+
+      // corotational Kirchhoff stress tenor from previous and increment
+      STensor3& corK = q1->_kirchhoff;                                             // Update _kirchoff in q1 by reference (declare, then add q0 _kirchoff and other stuff)
+      corK = q0->_kirchhoff;
+
+      corK += DdevK;
+      corK(0,0) += Dp;
+      corK(1,1) += Dp;
+      corK(2,2) += Dp;
+    }
+    else{
+      Msg::Error("visco elastic method %d has not been defined");
+    }
+  }
+  else{
+    static STensor3 devK;
+    static double p;
+    STensorOperation::decomposeDevTr(Ee,devK,p);
+    // devK *= (2.*_G);  // deviatoric part
+    devK *= (2.*GT);  // deviatoric part
+        
+    // p *= _K; // pressure
+    p *= KT; // pressure
+
+    // Ke = _K; Ge = _G;
+    Ke = KT; Ge = GT;
+
+    p -= 3.*Ke*alphaT*(Tc-_Tinitial);                  // ADDED - thermal strain               -  CHANGE with scalarTgFunc
+    
+    q1->_kirchhoff = devK;
+    q1->_kirchhoff(0,0) += p;
+    q1->_kirchhoff(1,1) += p;
+    q1->_kirchhoff(2,2) += p;
+  }
+};
+*/
+
+/*
+void mlawNonLinearTVM::predictorCorrector_ViscoElastic(const STensor3& F0, const STensor3& F, STensor3&P, const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
+                                  const bool stiff, STensor43& Tangent, const double Tc) const{
+  static STensor3 C;
+  static STensor43 dlnCdC;
+  static STensor63 ddlnCddC;
+
+  STensor3& E = q1->getRefToElasticStrain();
+
+  STensorOperation::multSTensor3FirstTranspose(F,F,C);
+  if (_order == 1){
+    STensorOperation::logSTensor3(C,_order,E,&dlnCdC);  // as ddlogCddC = 0
+  }
+  else{
+    STensorOperation::logSTensor3(C,_order,E,&dlnCdC,&ddlnCddC);
+  }
+  E *= 0.5; // strain
+
+  double Ke, Ge;
+  
+  viscoElasticPredictor(E,q0->_Ee,q0,q1,Ke,Ge,Tc); // This will update the values of moduli to the current temperatures right?
+
+  const STensor3& corKir = q1->getConstRefToCorotationalKirchhoffStress();
+  static STensor3 secondPK;
+  STensorOperation::multSTensor3STensor43(corKir,dlnCdC,secondPK);
+  STensorOperation::multSTensor3(F,secondPK,P);
+  // first PK
+
+  q1->_elasticEnergy=deformationEnergy(*q1,Tc);
+
+  if (stiff){
+    static STensor43 DsecondPKdC;
+    static STensor43 DcorKDE;
+    isotropicHookTensor(Ke,Ge,DcorKDE);
+
+    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++){
+            DsecondPKdC(i,j,k,l) = 0.;
+            for (int p=0; p<3; p++){
+              for (int q=0; q<3; q++){
+                if (_order != 1){
+                  DsecondPKdC(i,j,k,l) += corKir(p,q)*ddlnCddC(p,q,i,j,k,l);
+                }
+                for (int r=0; r<3; r++){
+                  for (int s=0; s<3; s++){
+                    DsecondPKdC(i,j,k,l) += 0.5*DcorKDE(p,q,r,s)*dlnCdC(p,q,i,j)*dlnCdC(r,s,k,l);
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+
+    STensorOperation::zero(Tangent);
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        for (int p=0; p<3; p++){
+          Tangent(i,j,i,p) += secondPK(p,j);
+          for (int q=0; q<3; q++){
+            for (int s=0; s<3; s++){
+              for (int k=0; k<3; k++){
+                Tangent(i,j,p,q) += 2.*F(i,k)*DsecondPKdC(k,j,q,s)*F(p,s);
+              }
+            }
+          }
+        }
+      }
+    }
+  };
+
+};
+*/
+
+/*
+// This function doesn't update the thermal props to the current temperature.
+void mlawNonLinearTVM::constitutive(const STensor3& F0, 
+                                    const STensor3& F, 
+                                    STensor3& P,
+                                    const IPVariable *q0i, 
+                                    IPVariable *q1i,
+                                    STensor43& Tangent, 
+                                    double T0,
+                                    double T,
+                                    const SVector3 &gradT,
+                                    SVector3 &fluxT,
+                                    STensor3 &dPdT,
+                                    STensor3 &dqdgradT,
+                                    SVector3 &dqdT,
+                                    STensor33 &dqdF,
+                                    // double h,   //time
+                                    double &w,   //cp*dTdh
+                                    double &dwdt,
+                                    STensor3 &dwdf,
+                                    //STensor3 &Stiff_alphaDilatation,
+            
+                                    const bool stiff,            // if true compute the tangents
+                                    STensor43* elasticTangent) const{
+                                             
+  // double Tc = _Tref;
+  
+  this->constitutive(F0,F,P,q0i, q1i,Tangent,stiff,elasticTangent);  // Should update the mechanical stresses? ---- WHAT?
+                                    
+  const IPNonLinearTVM *q0=dynamic_cast<const IPNonLinearTVM *>(q0i);
+  IPNonLinearTVM *q1 = dynamic_cast<IPNonLinearTVM *>(q1i);
+  if(elasticTangent!=NULL) Msg::Error("mlawNonLinearTVM elasticTangent not defined");
+
+  if (!_tangentByPerturbation){
+      
+      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++){
+                      P(i,j) -= Cel(i,j,k,l)*_tensorAlpha(k,l)*(T-_Tinitial);
+                  }
+              }
+          }
+      }
+ }
+  
+  STensorOperation::zero(fluxT);
+  for(int i=0;i<3;i++){
+      for(int j=0;j<3;j++){
+          fluxT(i)+=_tensorK(i,j)*gradT(j);
+      }
+  }
+  
+  if(stiff){
+        STensorOperation::zero(dPdT);
+        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++){
+                        dPdT(i,j) -= Cel(i,j,k,l)*_tensorAlpha(k,l);
+                    }
+                }
+            }
+        }
+        dqdgradT = _tensorK;
+        STensorOperation::zero(dqdT); //if _k depends on T this should be here
+        STensorOperation::zero(dqdF); // dependency of flux with deformation gradient
+
+        double dh;
+        double dcpdt = 0.;
+        dh = getTimeStep();
+        w = 0.; dwdt =0.; STensorOperation::zero(dwdf);
+        w = -_Cp*(T-T0)/dh;                             // w = -_cp->getVal(T0)*(T-T0)/dh;
+        dwdt = -dcpdt*(T-T0)/dh-_Cp/dh;                 // dwdt = -dcpdt*(T-T0)/dh-_cp->getVal(T0)/dh;
+        STensorOperation::zero(dwdf);
+        q1->_thermalEnergy = _Cp*T; //(T-_t0);    //q1->_thermalEnergy = _cp->getVal(T0)*T; //(T-_t0);
+    }
+
+// Calculate elasticEnergy again??
+// q1->_elasticEnergy=deformationEnergy(Fn,gradT); //comment it to get H1 norm in the interface  e.g. LinearThermoMech
+
+};
+*/
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVM.h b/NonLinearSolver/materialLaw/mlawNonLinearTVM.h
new file mode 100644
index 0000000000000000000000000000000000000000..f9766c0522a05730859cdc7e8b179a91463dce54
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVM.h
@@ -0,0 +1,505 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022; ; <Van Dung Nguyen>, (C) 2014
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MLAWNONLINEARTVM_H_
+#define MLAWNONLINEARTVM_H_
+
+#include "mlaw.h"
+#include "STensor3.h"
+#include "STensor43.h"
+#include "STensor63.h"
+// #include "ipHyperelastic.h"
+#include "ipNonLinearTVM.h"
+#include "viscosityLaw.h"
+#include "mlawHyperelasticFailureCriterion.h"
+#include "scalarFunction.h"
+#include "mlawHyperelastic.h"
+
+/* Patch Notes
+
+1)            23/12/21  - NonLinearTVM 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 ipNonLinearTVM with adaptations from LinearThermoMechanicsDG3DMaterial.
+.......1.1.4) 29/12/21  - Updated mlawNonLinearTVM 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....TVM.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.?) ??/??/22  - Addition of new class for Psi_ve
+*/
+
+
+// class mlawNonLinearTVM : public materialLaw{
+  // public:
+    // enum viscoelasticType{Maxwell=0,KelvinVoight=1};
+class mlawNonLinearTVM : public mlawHyperViscoElastic{
+  protected:
+  
+  // Material Properties at Room Temp. - Mechanical
+    // double _rho;        // Density
+    // double _E;          // Youngs Modulus
+    // double _nu;         // Poissons Ratio
+    // double _lambda;     // 1st Lame parameter
+    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
+    double _scalarK;        // (scalar) Thermal Conductivity (K)                                                  - Tensor exists for Anisotropic Conductivity - General Fourier 
+    double _Cp;       // (scalar) Specific Heat at const pressure or volume or deformation????   - WHAT? 
+    
+    STensor3 _tensorAlpha;  // (tensor3) Thermal Dilatation Coefficient (=alpha)  
+    STensor3 _tensorK;      // (tensor3) Thermal Conductivity (K)  
+    
+  // ViscoElastic Data
+    // viscoelasticType _viscoMethod; // viscoelastic method 0- generalized Maxwell model, 1- generalized Kelvin-Voight model   (ENUM type variable)
+    // 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  - WHAT? - How to use?
+    
+  // Testing
+    // double _perturbationfactor;             // perturbation factor                          - WHAT?
+    // bool _tangentByPerturbation;            // flag for tangent by perturbation             - WHAT? - How to use?
+    int _testFlag;                          // for various solutions to convolution
+    
+  // Temperature Settings and Functions
+    double _Tinitial;                               // Initial Temperature             
+    double _Tref;                                   // Reference Tempereture           - Set this regardless of thermo problem, can check the code at this constant temperature.
+    double _TemFuncOpt;                             // Option for TemperatureFunction  - 0-> Shift Factor based derivatives of Ki; 1-> Gibson/Huang based derivatives
+    int _modelFlag;                                 // Flag for Model:  1 -> Simo (alpha_i = alpha_inf); 2 -> Extended volumetric terms   
+    scalarFunction* _temFunc_K;                     // bulk modulus temperature function
+    scalarFunction* _temFunc_G;                     // shear modulus temperature function
+    scalarFunction* _temFunc_Alpha;                 // alpha temperature function
+    scalarFunction* _temFunc_KThCon;                // thermal conductivity temperature function
+    scalarFunction* _temFunc_Cp;                    // specific heat temperature function
+    std::vector<scalarFunction*> _temFunc_Ki;       // branch bulk moduli temperature functions
+    std::vector<scalarFunction*> _temFunc_Gi;       // branch shear moduli temperature function
+    std::vector<scalarFunction*> _temFunc_Alphai;   // branch alpha temperature function
+
+  // Scalars - Additional constants
+    std::vector<scalarFunction*> _Betai;            // branch free energy scalars
+    
+  // 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
+
+  #ifndef SWIG  
+  protected:
+  // Const Functions for constitutive function - To update any variable, pass it as an argument by reference. 
+    virtual double ShiftFactorWLF(const double T, double *DaDT = NULL, double *DDaDDT = NULL) const ;
+    virtual void shiftedTime(const double t, const double T0, const double T1, 
+                             double *t_shift = NULL, double *Ddt_shiftDT = NULL, double *DDdt_shiftDT = NULL, 
+                             const int option = 1) 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 IPNonLinearTVM& q, const double Tc) const ;
+    virtual double setTemp(const double T0, const double T1, const int para) const ;
+  //  virtual double deformationEnergy(const IPNonLinearTVM& q, const double Tc) const ;
+  //  void updateViscoElasticFlow(const IPNonLinearTVM *q0, IPNonLinearTVM *q1, double& Ke, double& Ge, const double Tc) const;
+  //  void viscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+  //            const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
+  //            double& Ke, double& Ge, const double Tc) const;
+    
+    void corKirInfinity( const STensor3& devEe, const double& trEe, const double T1, STensor3& CorKirDevInf, double& CorKirTrInf) const;
+    void ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPNonLinearTVM *q0, IPNonLinearTVM *q1,
+          double& Ke, double& Ge, double& Kde, double& Gde,
+          double& DKe, double& DGe, double& DKde, double& DGde, 
+          double& KTsum, double& GTsum, double& DKDTsum, double& DGDTsum,
+          const double T0, const double T1) const; 
+              
+    void isotropicHookTensor(const double K, const double G, STensor43& L) const;
+  //  void predictorCorrector_ViscoElastic(const STensor3& F0, const STensor3& F, STensor3& P, const IPNonLinearTVM *q0_, IPNonLinearTVM *q1,
+  //                                const bool stiff, STensor43& Tangent, const double Tc) const;
+
+    void predictorCorrector_ThermoViscoElastic(        // For thermomech - with _tengentPerturbation
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3 &P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVM *q0,                       // array of initial internal variables
+                                              IPNonLinearTVM *q1,                       // updated array of internal variables (in ipvcur on output),
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3& gradT0,                         // previous temperature gradient
+                                        const SVector3& gradT,                          // temperature gradient
+                                              SVector3& fluxT,                          // temperature flux
+                                        const double& thermalSource0,
+                                              double& thermalSource,
+                                        const double& mechanicalSource0,
+                                              double& mechanicalSource) const;
+                            
+    void predictorCorrector_ThermoViscoElastic(       // For thermomech
+                                        const STensor3& F0,                             // initial deformation gradient (input @ time n)
+                                        const STensor3& F,                              // updated deformation gradient (input @ time n+1)
+                                              STensor3& P,                              // updated 1st Piola-Kirchhoff stress tensor (output)
+                                        const IPNonLinearTVM *q0,                       // array of initial internal variables
+                                              IPNonLinearTVM *q1,                       // updated array of internal variableS (in ipvcur on output),
+                                              STensor43& Tangent,                       // mechanical tangents (output)
+                                              STensor43& dFedF,                         // elastic tangent
+                                              STensor3& dFedT,                          // elastic tangent
+                                        const double& T0,                               // previous temperature
+                                        const double& T,                                // temperature
+                                        const SVector3 &gradT0,                         // previous temperature gradient
+                                        const SVector3 &gradT,                          // temperature gradient
+                                              SVector3 &fluxT,                          // temperature flux
+                                              STensor3 &dPdT,                           // mechanical-thermal coupling
+                                              STensor3 &dfluxTdgradT,                   // thermal tengent
+                                              SVector3 &dfluxTdT,
+                                              STensor33 &dfluxTdF,                      // thermal-mechanical coupling
+                                        const double& thermalSource0,
+                                              double& thermalSource,                    // - Cp*dTdt
+                                              double& dthermalSourcedT,                 // thermal source
+                                              STensor3 &dthermalSourcedF,
+                                        const double& mechanicalSource0,
+                                              double& mechanicalSource,                 // mechanical source --> convert to heat
+                                              double& dmechanicalSourcedT,
+                                              STensor3& dmechanicalSourceF,
+                                        const bool stiff) const; 
+  #endif // SWIG
+
+  public:
+    // Constructor Declaration
+    mlawNonLinearTVM(const int num,const double E,const double nu, const double rho, const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = true);
+    // mlawNonLinearTVM(const double Tinitial, const double Alpha, const double KThCon, const double Cp, const bool thermalEstimationPreviousConfig = false);
+                
+    // Copy Contructor
+    mlawNonLinearTVM(const mlawNonLinearTVM& src);
+    
+    // Operator Assignment
+    mlawNonLinearTVM& operator=(const materialLaw& source);
+    
+    // Virtual Destructor
+    virtual ~mlawNonLinearTVM();
+    
+  // Mandatory const member functions
+  
+  
+  // 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 setStrainOrder(const int order);
+    // virtual void setViscoelasticMethod(const int method);
+    virtual void setViscoElasticNumberOfElement(const int N);
+    virtual void setViscoElasticData(const int i, const double Ei, const double taui);
+    virtual void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    virtual void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    virtual void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    virtual void setViscoElasticData(const std::string filename);
+    virtual void setViscoElasticData_Alpha(const int i, const double Alpha_i);
+
+  // Non-Const Functions for temp and temp_functions that are called from .py file.  ---- These WILL change the values of the variables defined in the class object.  
+    void setReferenceTemperature(const double Tr){_Tref = Tr;};
+    void setTempFuncOption(const double TemFuncOpt){_TemFuncOpt = TemFuncOpt;};              
+    void setModelOption(const int modelFlag){_modelFlag = modelFlag;};
+    void setTestOption(const int testFlag){_testFlag = testFlag;};                   
+    void setShiftFactorConstantsWLF(const double C1, const double C2){_C1 = C1; _C2 = C2;};
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+     if (_temFunc_K != NULL) delete _temFunc_K;
+      _temFunc_K = Tfunc.clone();
+    }
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+      if (_temFunc_G != NULL) delete _temFunc_G;
+      _temFunc_G = Tfunc.clone();
+    }
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+      if (_temFunc_Alpha != NULL) delete _temFunc_Alpha;
+      _temFunc_Alpha = Tfunc.clone();
+    }
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+      if (_temFunc_KThCon != NULL) delete _temFunc_KThCon;
+      _temFunc_KThCon = Tfunc.clone();
+    }
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+      if (_temFunc_Cp != NULL) delete _temFunc_Cp;
+      _temFunc_Cp = 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);
+       if (_temFunc_Ki[i-1] != NULL) delete _temFunc_Ki[i-1];
+         _temFunc_Ki[i-1] = Tfunc.clone();
+    }
+    void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i){
+       if (i> _N or i<1)
+         Msg::Error("This setting is invalid %d > %d",i,_N);
+       if (_temFunc_Gi[i-1] != NULL) delete _temFunc_Gi[i-1];
+         _temFunc_Gi[i-1] = Tfunc.clone();
+    }      
+    void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i){
+       if (i> _N or i<1)
+         Msg::Error("This setting is invalid %d > %d",i,_N);
+       if (_temFunc_Alphai[i-1] != NULL) delete _temFunc_Alphai[i-1];
+         _temFunc_Alphai[i-1] = Tfunc.clone();
+    }     
+  
+#ifndef SWIG
+
+// Const Functions to get temp-updated values of material properties - Args by reference, or return the variable.
+
+    virtual std::vector<double> getBetai(const double _K, const std::vector<double> _Ki) const{ 
+        std::vector<double> Beta_i;
+        Beta_i.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+            Beta_i[i] = _Ki[i]/_K;
+        }
+        return Beta_i;
+    }
+    
+    virtual void getK(double& KT, const double Tc, double *dK = NULL, double *ddK = NULL) const{
+        KT = _K*_temFunc_K->getVal(Tc);
+        // KT = _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 = _temFunc_K->getDiff(Tc);
+        }
+        if(ddK!=NULL){
+            *ddK = _K*_temFunc_K->getDoubleDiff(Tc);
+            // *ddK = _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);
+        // GT = _temFunc_G->getVal(Tc);
+        if(dG!=NULL){
+            *dG = _G*_temFunc_G->getDiff(Tc);
+            // *dG = _temFunc_G->getDiff(Tc);
+        }
+        if(ddG!=NULL){
+            *ddG = _G*_temFunc_G->getDoubleDiff(Tc);
+            // *ddG = _temFunc_G->getDoubleDiff(Tc);    
+        }
+    }
+     virtual void getAlpha(double& alphaT, const double Tc, double *dAlpha = NULL, double *ddAlpha = NULL) const{
+        alphaT = _scalarAlpha*_temFunc_Alpha->getVal(Tc);
+        if(dAlpha!=NULL){
+            *dAlpha = _scalarAlpha*_temFunc_Alpha->getDiff(Tc);
+        }
+        if(ddAlpha!=NULL){
+            *ddAlpha = _scalarAlpha*_temFunc_Alpha->getDoubleDiff(Tc);
+        }
+    }
+    virtual void getKTHCon(double& KThConT,const double Tc, double *dKThCon = NULL) const{
+        KThConT = _scalarK*_temFunc_KThCon->getVal(Tc);
+        if(dKThCon!=NULL){
+            *dKThCon = _scalarK*_temFunc_KThCon->getDiff(Tc);
+        }
+    }
+    virtual void getCp(double& CpT, const double Tc, double *dCp = NULL) const{
+        CpT = _Cp*_temFunc_Cp->getVal(Tc);
+        if(dCp!=NULL){
+            *dCp = _Cp*_temFunc_Cp->getDiff(Tc);
+        }
+    } 
+    
+    // The 3rd argument must be a vector pointer as well. -------------------------------------------------------------- DONE  
+    virtual void getKi(std::vector<double>& Ki_T, const double Tc, std::vector<double>* dKi=NULL, std::vector<double>* ddKi=NULL) const{
+        Ki_T.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+            Ki_T[i] = _Ki[i]*_temFunc_Ki[i]->getVal(Tc);
+            if(dKi!=NULL){
+                dKi->at(i) = _Ki[i]*_temFunc_Ki[i]->getDiff(Tc);
+            }
+            if(ddKi!=NULL){
+                ddKi->at(i) = _Ki[i]*_temFunc_Ki[i]->getDoubleDiff(Tc); 
+            }
+        }
+    }
+    
+    // The 3rd argument must be a vector pointer as well. -------------------------------------------------------------- DONE
+    virtual void getGi(std::vector<double>& Gi_T, const double Tc, std::vector<double>* dGi=NULL, std::vector<double>* ddGi=NULL) const{
+        Gi_T.resize(_N,0.);
+        for (int i=0; i<_Gi.size();i++){
+            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]
+            }
+            if(ddGi!=NULL){
+                ddGi->at(i) = _Gi[i]*_temFunc_Gi[i]->getDoubleDiff(Tc);  
+            }
+        }
+    }
+    
+    // The 3rd argument must be a vector pointer as well. -------------------------------------------------------------- DONE
+    virtual void getAlphai(std::vector<double>& Alphai_T, const double Tc, std::vector<double>* dAlphai=NULL, std::vector<double>* ddAlphai=NULL) const{
+        Alphai_T.resize(_N,0.);
+        for (int i=0; i<_Alphai.size();i++){
+            Alphai_T[i] = _Alphai[i]*_temFunc_Alphai[i]->getVal(Tc);
+            if(dAlphai!=NULL){
+                dAlphai->at(i) = _Alphai[i]*_temFunc_Alphai[i]->getDiff(Tc); // *(dAlphai+i) is equivalent to dAlphai[i]
+            }
+            if(ddAlphai!=NULL){
+                ddAlphai->at(i) = _Alphai[i]*_temFunc_Alphai[i]->getDoubleDiff(Tc);
+            }
+        }
+    }
+    
+    
+    // This "scalar" member function is backup; Member function will be deprecated soon - awaiting scalarFunction implementation in .py file
+    virtual void temFuncGlassTransition(const double Tc, const double opt, const double Prop0, const double Prop1, double& Prop, double *dProp = NULL) const {
+        // Prop0 = At room temp or glassy state
+        // Prop1 = In rubbery state - or the lowest possible value after glass transition
+        if (opt == 0) { // LinearFunction  - This is only for test, Prop1 = 0;
+            Prop = Prop0*(1 - 0.1/Prop0*(Tc - 298));
+            if (dProp!= NULL) {
+                *dProp = -0.1;
+                }
+        } else if (opt == 1) { // Gibson et al
+            double Tg = 373; double k = 0.0975; double m = 0;
+            Prop = 0.5*(Prop0+Prop1) -0.5*(Prop0-Prop1) * tanh(k*(Tc-Tg)) - m*(Tc-Tg);
+            if (dProp!= NULL) {
+                *dProp = -0.5*k*(Prop0-Prop1) * (1-pow(tanh(k*(Tc-Tg)),2)) - m;
+                }
+        } else if (opt == 2) { // Huang et al
+            double Tg = 373; double k = 0.0994; double m = 2.968;
+            Prop = Prop0 - (Prop0-Prop1) / (pow((m*exp(-m*k*(Tc-Tg))+1),(1/m)));
+            if (dProp!= NULL) {
+                *dProp = -(Prop0-Prop1)*(pow(m,2.0)*k*exp(-m*k*(Tc-Tg)))/( m* ( pow( (m*exp(-m*k*(Tc-Tg))+1),(1+1/m) )));   // Correct this derivative - CHANGE!!
+                }
+        }
+    }
+
+//    #ifndef SWIG
+
+// Some more Member Functions
+
+    virtual matname getType() const{return materialLaw::nonlineartvm;}    // 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{
+        Msg::Error("mlawNonLinearTVM::createIPState has not been defined");
+    };
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}; // this law is initialized so nothing to do
+
+    // virtual bool withEnergyDissipation() const {if (_N == 0) return false; else return true;};
+    // virtual int getViscoElasticNumberOfElement() const{return _N;};
+
+    virtual double soundSpeed() const; // default but you can redefine it for your case
+    // virtual double density()const{return _rho;}
+    // virtual const double bulkModulus() const{return _K;}       
+    // virtual const double shearModulus() const{return _G;}
+    // virtual const double poissonRatio() const{return _nu;}
+    // virtual double scaleFactor() const { return _G;};
+  
+// Added from LinearThermomech  
+    // const STensor43& getElasticityTensor() const { return _ElasticityTensor;};  // Dont need this
+    virtual double getInitialTemperature() const {return _Tinitial;};
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const {return getExtraDofStoredEnergyPerUnitField(_Tinitial);}
+    // virtual double getExtraDofStoredEnergyPerUnitField(double T) const {return _Cp->getVal(T);};   // Fix this
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const {
+        double Cp_current; getCp(Cp_current,T);
+        return Cp_current;
+        // return _Cp;
+    };   // Fix this
+    
+// Const functions to directly export the thermal_cond and alpha when called for ipvcur in dG3DMaterialLaw.cpp   - Make these Virtual??? ---- WHAT????
+                                                                                // ALSO, add temfuncTg definition here!!!!!                  - CHANGE!!!!
+    const STensor3& getConductivityTensor() const {return _tensorK;}; // linearK = _tensorK
+    const STensor3& getStiff_alphaDilatation() const {return _tensorAlpha;}; // Stiff_alphaDilatation = _tensorAlpha
+
+    // Default Constitutive function
+    virtual void constitutive(
+            const STensor3& F0,         // initial deformation gradient (input @ time n)
+            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+            STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+            const IPVariable *q0,       // array of initial internal variables
+            IPVariable *q1,             // updated array of internal variables (in ipvcur on output),
+            STensor43& Tangent,         // constitutive tangents (output)
+            const bool stiff,           // if true compute the tangents
+            STensor43* elasticTangent = NULL, 
+            const bool dTangent =false,
+            STensor63* dCalgdeps = NULL) const;
+
+/*
+    // ThermoMech Constitutive function - LinearThermoMech
+    virtual void constitutive(
+            const STensor3& F0,         // initial deformation gradient (input @ time n)
+            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+            STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                        // contains the initial values on input
+            const IPVariable *q0,       // array of initial internal variable
+            IPVariable *q1,             // updated array of internal variable (in ipvcur on output),
+            STensor43 &Tangent,         // constitutive tangents (output)
+            
+            double T0,
+            double T,
+            const SVector3 &gradT,
+            SVector3 &fluxT,
+            STensor3 &dPdT,
+            STensor3 &dqdgradT,
+            SVector3 &dqdT,
+            STensor33 &dqdF,
+            // double h,   //time
+            double &w,   //cp*dTdh
+            double &dwdt,
+            STensor3 &dwdf,
+            //STensor3 &Stiff_alphaDilatation,
+            
+            const bool stiff,            // if true compute the tangents
+            STensor43* elasticTangent = NULL) const; */
+    
+    // ThermoMech Constitutive function - J2Full
+    virtual void constitutive(
+            const STensor3& F0,                     // initial deformation gradient (input @ time n)
+            const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
+                  STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+            const IPVariable *q0,                   // array of initial internal variable
+                  IPVariable *q1,                   // updated array of internal variable (in ipvcur on output),
+                  STensor43 &Tangent,               // constitutive mechanical tangents (output)
+            const double& T0,                       // previous temperature
+            const double& T,                        // temperature
+            const SVector3 &gradT0,                 // previous temperature gradient
+            const SVector3 &gradT,                  // temperature gradient
+                  SVector3 &fluxT,                  // temperature flux
+                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                  STensor3 &dfluxTdgradT,           // thermal tengent
+                  SVector3 &dfluxTdT,
+                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+            const double& thermalSource0,
+                  double &thermalSource,            // - Cp*dTdt
+                  double &dthermalSourcedT,         // thermal source
+                  STensor3 &dthermalSourcedF,
+            const double& mechanicalSource0,
+                  double &mechanicalSource,         // mechanical source--> convert to heat
+                  double &dmechanicalSourcedT,
+                  STensor3 & dmechanicalSourceF,
+            const bool stiff,
+                  STensor43* elasticTangent = NULL) const; 
+                  
+    virtual materialLaw* clone() const {return new mlawNonLinearTVM(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+    #endif // SWIG
+};
+#endif //mlawNonLinearTVM
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3206b2ac6331291a40ab66f8d8ca75bcd8328af7
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVP.cpp
@@ -0,0 +1,3454 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+
+#include "STensorOperations.h"
+#include "nonLinearMechSolver.h"
+#include "mlawNonLinearTVP.h"
+
+
+mlawNonLinearTVP::mlawNonLinearTVP(const int num,const double E,const double nu, const double rho, const double tol,
+                                   const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                                   const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
+                                   mlawNonLinearTVE(num, E, nu, rho, tol, Tinitial, Alpha, KThCon, Cp, matrixbyPerturbation, pert, thermalEstimationPreviousConfig),
+                                   _TaylorQuineyFactor(0.9), _HR(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;
+    _HR = src._HR;
+
+  _temFunc_Sy0 = NULL; // temperature dependence of initial yield stress
+  if (src._temFunc_Sy0!= NULL)
+    _temFunc_Sy0 = src._temFunc_Sy0->clone();
+
+  _temFunc_H = NULL; // temperature dependence of hardening stress
+  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;
+        _HR = src->_HR;
+        if(_temFunc_Sy0 != NULL) delete _temFunc_Sy0; // temperature dependence of initial yield stress
+        if (src->_temFunc_Sy0!= NULL)
+            _temFunc_Sy0 = src->_temFunc_Sy0->clone();
+        if(_temFunc_H != NULL) delete _temFunc_H; // temperature dependence of hardening stress
+        if (src->_temFunc_H != NULL)
+            _temFunc_H = src->_temFunc_H->clone();
+        if(_temFunc_Hb != NULL) delete _temFunc_Hb; // temperature dependence of kinematic hardening
+        if (src->_temFunc_Hb != NULL)
+            _temFunc_Hb = src->_temFunc_Hb->clone();
+        if(_temFunc_visc != NULL) delete _temFunc_visc; // temperature dependence of viscosity
+        if (src->_temFunc_visc != NULL)
+            _temFunc_visc = src->_temFunc_visc->clone();
+    }
+    return *this;
+};
+
+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_visc != NULL) delete _temFunc_visc; _temFunc_visc= NULL; 
+};
+
+// CHECK IF IPSTATE NEEDS the same definition as in mlawPowerYieldHyper --- WHAT??
+
+// NEW
+
+void mlawNonLinearTVP::setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3){
+
+    _HR.clear();
+    _HR.resize(3,0.);
+    _HR[0] = HR1;
+    _HR[1] = HR2;
+    _HR[2] = HR3;
+};
+
+void mlawNonLinearTVP::hardening(const IPNonLinearTVP* q0, IPNonLinearTVP* q1, const double& T) const{
+  //Msg::Error("epspCompression = %e, epspTRaction = %e, epspShear = %e",q->_epspCompression,q->_epspTraction,q->_epspShear);
+  if (_compression != NULL && q1->_ipCompression != NULL){
+    _compression->hardening(q0->_epspCompression, *q0->_ipCompression, q1->_epspCompression,T,*q1->_ipCompression);
+  }
+
+  if (_traction!= NULL && q1->_ipTraction != NULL){
+    _traction->hardening(q0->_epspTraction,*q0->_ipTraction, q1->_epspTraction,T,*q1->_ipTraction);
+  }
+
+  if (_kinematic!= NULL && q1->_ipKinematic != NULL)
+    _kinematic->hardening(q0->_epspbarre,*q0->_ipKinematic,q1->_epspbarre,T,*q1->_ipKinematic);
+};
+
+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 
+    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{
+
+    double p = q1->_epspbarre; // eq.plastic strain
+    
+    coeffs.resize(2);
+    
+    coeffs(0) = 0; // 1; //DEBUGGING
+    coeffs(1) = 0;
+    
+    // add dependency on p later
+};
+
+void mlawNonLinearTVP::getPlasticPotential(const double& phiP, const double& phiE, double& Px) const{
+    
+    Px = pow(phiE,2) + _b*pow(phiP,2);
+};
+
+void mlawNonLinearTVP::getYieldCoefficientTempDers(const IPNonLinearTVP *q1, const double& T, fullVector<double>& DcoeffsDT, fullVector<double>& DDcoeffsDTT) const{
+  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();
+  
+
+  double sigt(0.), Ht(0.), dsigtdT(0.), ddsigtdTT(0.);
+  sigt = q1->_ipTraction->getR();
+  Ht = q1->_ipTraction->getDR();
+  dsigtdT = q1->_ipTraction->getDRDT();
+  ddsigtdTT = q1->_ipTraction->getDDRDTT();
+
+
+  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 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 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);
+
+  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;
+    
+};
+
+void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T,
+                                      double *psiTVM, double *DpsiTVMdT, double *DDpsiTVMdTT) const{
+
+    // get some Things
+    const double& Gamma = q1->_Gamma;
+    const double& DgammaDT = q1->_DgammaDT;
+    const double& dGammaDT = q1->_DGammaDT;
+    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->_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 = 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);
+    getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+    getYieldCoefficientTempDers(q1,T,DaDT,DDaDTT);
+    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();
+    
+    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();
+    }
+
+    double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+    static STensor3 alpha;
+    alpha = X;
+    alpha *= 1/(pow(kk,2)*Hb);
+    
+    // ddXdTT 
+    static STensor3 ddXdTT; // ddGammaDTT and ddQDTT are very difficult to estimate
+    STensorOperation::zero(ddXdTT);
+    double delT = T-T0;
+    if (delT>1e-10){
+     for (int i=0; i<3; i++)
+       for (int j=0; j<3; j++){
+         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 
+                        - X(i,j)*( -2/(pow(kk*Hb,3))*dHbdT*dHbdT +  1/(pow(kk*Hb,2))*ddHbddT);
+      }
+
+    // finally
+    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);
+    
+    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);
+    
+    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;
+    DdevKeinfDT *= dGdT/GT;
+    DDdevKeinfDTT = devKeinf;
+    DDdevKeinfDTT *= ddGdTT/GT;
+
+    const std::vector<STensor3>& devOi = q1->getConstRefToDevViscoElasticOverStress();
+    const std::vector<double>& trOi = q1->getConstRefToTrViscoElasticOverStress();
+    const std::vector<STensor3>& devDOiDT = q1->getConstRefToDevDOiDT();
+    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);
+    
+    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)); 
+    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)) 
+                      - 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)){
+      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));
+        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));
+          }    
+        }
+    }
+    
+    // FINALLY
+    if(psiTVM!=NULL){
+        *psiTVM = psiT + psiVE + psiVP;
+    }
+    if(DpsiTVMdT!=NULL){
+        *DpsiTVMdT = DpsiTdT + DpsiVEdT + DpsiVPdT;
+    }
+    if(DDpsiTVMdTT!=NULL){
+        *DDpsiTVMdTT = DpsiTdTT + DDpsiVEdTT + DDpsiVPdTT;
+    }
+
+};
+
+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;
+    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 *= 1/3; trX1 *= 1/3; dTrMeDT *= 1/3; dTrXdT *= 1/3;  
+    trMe_0 *= 1/3; trX1_0 *= 1/3; dTrMeDT_0 *= 1/3; dTrXdT_0 *= 1/3;  
+    
+    // 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.);
+    sigc = q1->_ipCompression->getR();
+    Hc = q1->_ipCompression->getDR();
+    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; 
+    }
+     
+    // dRdF
+    // static STensor3 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) = -Da(1)*(trMe-trX1)*DgammaDF(i,j)*sigc - a(1)*(dPhiPdF(i,j)*sigc + (trMe-trX1)*Hc);  
+        dRdF[1](i,j) = -Da(0)*DgammaDF(i,j)*sigc - a(0)*Hc; 
+        }
+          
+    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; 
+        }
+    }
+    
+    // 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 = 2*DphiPDT/delT - 2*(trMe-trMe_0+trX1_0-trX1)/pow(delT,2);
+        ddRdTT->at(0) -= a(1) * DDphiPDTT * sigc;
+        
+        if (Gamma>0 and etaOverDt>0){
+         double DDGammaDTT = 2*dGammaDT/delT - 2*(Gamma-Gamma_0)/pow(delT,2);
+         ddRdTT->at(2) -= _p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(eta*DDGammaDTT)/this->getTimeStep() * sigc;
+        } 
+       }
+       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 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;
+        }
+      }  
+    }
+};
+                                      
+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;                                        
+    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  = q1->_DbackSigDT;
+    const STensor3& dXdT_0  = q0->_DbackSigDT;
+    const STensor43& dXdF_0  = q0->_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);
+    
+    // get Dgamma
+    double Dgamma = gamma1 - gamma0;
+    
+    // get Hb
+    double Hb(0.), dHb(0), dHbdT(0.), ddHbddT(0.);
+    if (q1->_ipKinematic != NULL){
+        Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
+        dHb = q1->_ipKinematic->getDDR();
+        dHbdT = q1->_ipKinematic->getDRDT();
+        ddHbddT = q1->_ipKinematic->getDDRDDT();
+    }
+
+    // get Dp
+    static STensor3 Fpinv, Fp_dot, Dp;
+    STensorOperation::inverseSTensor3(Fp1,Fpinv);
+    Fp_dot = Fp1;
+    Fp_dot -= Fp0;
+    STensorOperation::multSTensor3(Dp,Fp_dot,Fpinv);
+   
+    // 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?  
+    alpha1 -= alpha0;
+    alpha1 *= 1/this->getTimeStep();
+    
+    // get TempX - convenient backStress tensor
+    STensor3 tempX;
+    tempX = X1;
+    tempX -= T*dXdT; 
+    
+    // get R, dRdT, dRdF
+    std::vector<double> ddIsoHardForcedTT; ddIsoHardForcedTT.resize(3,0.);
+    std::vector<STensor3> ddIsoHardForcedFdT; ddIsoHardForcedFdT.resize(3,0.);
+    
+    getIsotropicHardeningForce(q0,q1,T0,T,dPhiPdF,&ddIsoHardForcedTT,&ddIsoHardForcedFdT);
+    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];
+      dRdT += dIsoHardForcedT[i];
+      ddRdTT += ddIsoHardForcedTT[i];
+      dRdF += dIsoHardForcedF[i];
+      ddRdFdT += ddIsoHardForcedFdT[i];
+    }
+    
+    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();
+        }
+        *Wm = mechSourceTVP;
+        // Second Term TBD - need dXdT, dRdT -> added above
+    }
+    
+    // Some Generic Conversion Tensors
+    static STensor43 dDpdFp, dFpinvdFp;
+    
+    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,j,k,s)*Fpinv(s,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++){
+            dDpdFp(i,j,k,l) = 0.;
+            for (int m=0; m<3; m++)
+              dDpdFp(i,j,k,l) += 1/this->getTimeStep()*_I4(i,j,k,m)*Fpinv(m,l) + Fp_dot(i,m)*dFpinvdFp(m,j,k,l);
+          }
+    
+    // dDpdF and dDpdT
+    static STensor43 dDpdF;   
+    // STensorOperation::zero(dDpdF);
+    STensorOperation::multSTensor43(dDpdFp, dFpdF, dDpdF);
+          
+    static STensor3 dDpdT;
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        dDpdT(i,j) = 0.;
+        for (int k=0; k<3; k++)
+          for (int l=0; l<3; l++)
+            dDpdT(i,j) += dDpdFp(i,j,k,l)*dFpdT(k,l);
+      }
+      
+   // dXdF is available 
+   // const STensor43 dXdF = q1->_DbackSigDF;
+   
+   // ddXdTF -> make it -- CHANGE!!
+   static STensor43 ddXdTF; // ddGammaDTF and ddQDTF are very difficult to estimate
+   static STensor3 ddXdTT; // ddGammaDTT and ddQDTT are very difficult to estimate
+   STensorOperation::zero(ddXdTF);
+   STensorOperation::zero(ddXdTT);
+   double delT = T-T0;
+   if (delT>1e-10){
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        ddXdTT(i,j) += 2*dXdT(i,j)/(T-T0) - 2*(X1(i,j)-X0(i,j))/pow((T-T0),2);
+        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);
+          }
+        }
+      }
+   
+   // 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(k,l) + Me(i,j)*dDpdF(i,j,k,l) 
+                                        - (dXdF(i,j,k,l) - T*ddXdTF(i,j,k,l))*alpha1(k,l) - tempX(i,j)*dAlphadF(i,j,k,l)/this->getTimeStep();
+                }
+            }
+        }  
+        *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() ;
+            }
+        }
+        *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)
+                            const STensor3& F1,         // current deformation gradient (input @ time n+1)
+                                  STensor3 &P1,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,       // array of previous internal variables
+                                  IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,         // tangents (output)
+                            const bool stiff,            // if true compute the tangents
+                                  STensor43* elasticTangent, 
+                            const bool dTangent,
+                                  STensor63* dCalgdeps) const{
+    static SVector3 gradT, temp2;
+    static STensor3 temp3;
+    static STensor33 temp33;    
+    static double tempVal;
+    static STensor43 dFpdF, dFedF;
+    static STensor3 dFpdT, dFedT;
+
+    const IPNonLinearTVP *q0 = dynamic_cast<const IPNonLinearTVP *> (q0i);
+          IPNonLinearTVP *q1 = dynamic_cast<IPNonLinearTVP *>(q1i);
+          
+    if(elasticTangent != NULL) Msg::Error("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)
+                                  STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,                   // array of initial internal variable
+                                  IPVariable *q1i,                   // updated array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,               // constitutive mechanical tangents (output)
+                            const double& T0,                       // previous temperature
+                            const double& T,                        // temperature
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const{
+
+    const IPNonLinearTVP *q0 = dynamic_cast<const IPNonLinearTVP *>(q0i);
+          IPNonLinearTVP *q1 = dynamic_cast<IPNonLinearTVP *>(q1i);
+
+    // Declaring here, coz I dont know better.
+    static STensor43 dFedF, dFpdF;
+    static STensor3 dFpdT, dFedT;
+        
+    if (!_tangentByPerturbation){
+
+        this->predictorCorrector_ThermoViscoPlastic(F0, F1, P, q0, q1, Tangent, dFpdF, dFpdT, dFedF, dFedT,
+                                                    T0, T, gradT0, gradT, fluxT, dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF,
+                                                    thermalSource, dthermalSourcedT, dthermalSourcedF,
+                                                    mechanicalSource, dmechanicalSourcedT, dmechanicalSourceF,
+                                                    stiff, elasticTangent);
+    }
+        
+    else{
+
+        this->predictorCorrector_ThermoViscoPlastic(F0, F1, P, q0, q1, T0, T, gradT0, gradT, fluxT, thermalSource, mechanicalSource, elasticTangent);
+        if (stiff)
+            this->tangent_full_perturbation(F0,F1,P,q0,q1,T0, T, gradT0, gradT, fluxT, thermalSource, mechanicalSource,
+                                            Tangent, dFpdF, dFpdT, dFedF, dFedT,
+                                            dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF,
+                                            dthermalSourcedT, dthermalSourcedF,
+                                            dmechanicalSourcedT, dmechanicalSourceF);            
+    }
+};
+
+
+void mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
+                                                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                                                    const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                                          STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                    const IPNonLinearTVP *q0,       // array of initial internal variable
+                                                          IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                                    const double& T0, // previous temperature
+                                                    const double& T, // temperature
+                                                    const SVector3 &gradT0, // previous temeprature gradient
+                                                    const SVector3 &gradT, // temeprature gradient
+                                                          SVector3 &fluxT, // temperature flux)
+                                                          double &thermalSource,
+                                                          double& mechanicalSource,
+                                                          STensor43* elasticTangent) const{
+  // temp variables
+  static STensor43 Tangent, dFpdF, dFedF;
+  static STensor3 dPdT, dfluxTdgradT, dthermalSourcedF, dmechanicalSourceF, dFpdT, dFedT;
+  static STensor33 dfluxTdF;
+  static SVector3 dfluxTdT;
+  static double dthermalSourcedT, dmechanicalSourcedT;
+  predictorCorrector_ThermoViscoPlastic(F0,F1,P,q0,q1,Tangent,dFpdF,dFpdT,dFedF,dFedT,
+                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,
+                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF,false,elasticTangent);
+};
+
+
+void mlawNonLinearTVP::tangent_full_perturbation(
+                            const STensor3& F0,
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const{
+
+    static STensor3 Fplus, Pplus;
+    static SVector3 fluxTPlus, gradTplus;
+    static double thermalSourcePlus;
+    static double mechanicalSourcePlus;
+    static IPNonLinearTVP qPlus(*q0);
+
+    // perturb F
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        Fplus = F1;
+        Fplus(i,j) += _perturbationfactor;
+        
+        predictorCorrector_ThermoViscoPlastic(F0,Fplus,Pplus,q0,&qPlus,T0,T,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+        
+        q1->_DgammaDF(i,j) = (qPlus._epspbarre - q1->_epspbarre)/_perturbationfactor;
+        q1->_DirreversibleEnergyDF(i,j) = (qPlus._irreversibleEnergy - q1->_irreversibleEnergy)/_perturbationfactor;
+        
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            Tangent(k,l,i,j) = (Pplus(k,l) - P(k,l))/(_perturbationfactor);
+            dFpdF(k,l,i,j) = (qPlus._Fp(k,l)-q1->_Fp(k,l))/_perturbationfactor;
+            dFedF(k,l,i,j) = (qPlus._Fe(k,l)-q1->_Fe(k,l))/_perturbationfactor;
+          }
+          dfluxTdF(k,i,j) = (fluxTPlus(k) - fluxT(k))/_perturbationfactor;
+        }
+        
+        q1->getRefToDElasticEnergyPartdF()(i,j)=(qPlus.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/_perturbationfactor;
+        q1->getRefToDViscousEnergyPartdF()(i,j)=(qPlus.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/_perturbationfactor;
+        q1->getRefToDPlasticEnergyPartdF()(i,j)=(qPlus.getConstRefToPlasticEnergyPart()-q1->getConstRefToPlasticEnergyPart())/_perturbationfactor;
+      
+        dthermalSourcedF(i,j) = (thermalSourcePlus - thermalSource)/_perturbationfactor;
+        dmechanicalSourceF(i,j) = (mechanicalSourcePlus - mechanicalSource)/_perturbationfactor;
+      }
+    }
+    
+    // perturb gradT
+    double gradTpert = _perturbationfactor*T0/1e-3;
+    for (int i=0; i<3; i++){
+      gradTplus = gradT;
+      gradTplus(i) += gradTpert;
+      predictorCorrector_ThermoViscoPlastic(F0,F1,Pplus,q0,&qPlus,T0,T,gradT0,gradTplus,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+      for (int k=0; k<3; k++){
+        dfluxTdgradT(k,i) = (fluxTPlus(k) - fluxT(k))/gradTpert;
+      }
+    }
+
+    // perturb T
+    double Tplus = T+ _perturbationfactor*T0;
+    predictorCorrector_ThermoViscoPlastic(F0,F1,Pplus,q0,&qPlus,T0,Tplus,gradT0,gradT,fluxTPlus,thermalSourcePlus,mechanicalSourcePlus, NULL);
+    
+    q1->_DgammaDT = (qPlus._epspbarre - q1->_epspbarre)/(_perturbationfactor*T0);
+    q1->_DirreversibleEnergyDT = (qPlus._irreversibleEnergy - q1->_irreversibleEnergy)/(_perturbationfactor*T0);
+        
+    for (int k=0; k<3; k++){
+      for (int l=0; l<3; l++){
+        dFpdT(k,l) = (qPlus._Fp(k,l) - q1->_Fp(k,l))/(_perturbationfactor*T0);
+        dFedT(k,l) = (qPlus._Fe(k,l) - q1->_Fe(k,l))/(_perturbationfactor*T0);
+        dPdT(k,l) = (Pplus(k,l) - P(k,l))/(_perturbationfactor*T0);
+      }
+      dfluxTdT(k) = (fluxTPlus(k) - fluxT(k))/(_perturbationfactor*T0);
+    }
+    
+    q1->getRefToDElasticEnergyPartdT() = (qPlus.getConstRefToElasticEnergyPart()-q1->getConstRefToElasticEnergyPart())/(_perturbationfactor*T0);
+    q1->getRefToDViscousEnergyPartdT() = (qPlus.getConstRefToViscousEnergyPart()-q1->getConstRefToViscousEnergyPart())/(_perturbationfactor*T0);
+    q1->getRefToDPlasticEnergyPartdT() = (qPlus.getConstRefToPlasticEnergyPart()-q1->getConstRefToPlasticEnergyPart())/(_perturbationfactor*T0);
+      
+    dthermalSourcedT = (thermalSourcePlus - thermalSource)/(_perturbationfactor*T0);
+    dmechanicalSourcedT = (mechanicalSourcePlus - mechanicalSource)/(_perturbationfactor*T0);
+                                      
+};
+
+void mlawNonLinearTVP::predictorCorrector_ThermoViscoPlastic(
+                                                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                                                    const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                                          STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                    const IPNonLinearTVP *q0,       // array of initial internal variable
+                                                          IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                                          STensor43 &Tangent,         // mechanical tangents (output)
+                                                          STensor43 &dFpdF, // plastic tangent
+                                                          STensor3 &dFpdT, // plastic tangent
+                                                          STensor43 &dFedF, // elastic tangent
+                                                          STensor3 &dFedT, // elastic tangent
+                                                    const double& T0, // previous temperature
+                                                    const double& T, // temperature
+                                                    const SVector3 &gradT0, // previoustemeprature gradient
+                                                    const SVector3 &gradT, // temeprature gradient
+                                                          SVector3 &fluxT, // temperature flux
+                                                          STensor3 &dPdT, // mechanical-thermal coupling
+                                                          STensor3 &dfluxTdgradT, // thermal tengent
+                                                          SVector3 &dfluxTdT,
+                                                          STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                                          double &thermalSource,   // - cp*dTdt
+                                                          double &dthermalSourcedT, // thermal source
+                                                          STensor3 &dthermalSourcedF,
+                                                          double &mechanicalSource, // mechanical source--> convert to heat
+                                                          double &dmechanicalSourcedT,
+                                                          STensor3 &dmechanicalSourceF,
+                                                    const bool stiff,
+                                                          STensor43* elasticTangent) const{
+
+  if (_tangentByPerturbation){
+    if (_nonAssociatedFlow){
+      this->predictorCorrector_TVP_nonAssociatedFlow(F0,F1,q0,q1,P,false,Tangent,dFedF,dFpdF,dFedT,dFpdT, 
+                                                        T0,T,gradT0,gradT,fluxT,dPdT,dfluxTdgradT,dfluxTdT,dfluxTdF,      
+                                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF);
+    }
+    else{
+      this->predictorCorrector_TVP_AssociatedFlow(F1,q0,q1,P,false,Tangent,dFedF,dFpdF,T0,T);
+    }
+
+//    if (stiff){                                                                      // WHAT?????  WHY TWICE? (The same line happens above as STIFF is always TRUE)
+//      tangent_full_perturbation(Tangent,dFedF,dFpdF,P,F,q0,q1);
+//    }
+
+  }
+  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,      
+                                                        thermalSource,dthermalSourcedT,dthermalSourcedF,
+                                                        mechanicalSource,dmechanicalSourcedT,dmechanicalSourceF);
+    }
+    else{
+      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,                     
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const{
+                                      
+  // Compute elastic predictor first
+  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 stuff 
+  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);
+
+  double Hb(0.), dHb(0.), dHbdT(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();
+  }
+
+  //a.print("a init");
+  
+  
+  // 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;
+  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;
+  static STensor43 dexpAdA; // estimation of dexpA/dA
+
+  STensor3& Ee = q1->_Ee;
+  STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  Ee *= 0.5;
+  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);
+  
+  // Get Mepr
+  static STensor3 Me, Mepr, Kepr;  // Ke is corKir
+  getModifiedMandel(Ce,q0,q1);
+  Me = q1->_ModMandel;
+  Mepr = Me;
+  Kepr = q1-> _kirchhoff;
+
+  // Get Xn
+  static STensor3 devXn;
+  static double trXn;
+  STensorOperation::decomposeDevTr(q0->_backsig,devXn,trXn); // needed for chaboche model
+  
+  // Initialise Phipr
+  static STensor3 PhiPr;
+  PhiPr = q1->_ModMandel;
+  PhiPr -= q1->_backsig;
+  
+  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 
+  double dDgammaDGamma = 0.;
+  double Dgamma = 0.; // eqplastic strain
+  static fullVector<double> m(2);
+  double Px(0.);
+  getChabocheCoeffs(m,0,q1);
+  getPlasticPotential(ptildepr, PhiEqpr, Px);  // CHANGE -> this is wrong, change to backstress instead of phi 
+
+  double DfDGamma = 0.;
+  double dfdDgamma = 0.;  
+  double u = 1.;
+  double v = 1.;
+  
+  // Initialise Cx, Gt, Kt
+  double Cx = m(0)*Dgamma + m(1)*Px - 1/Hb * dHbdT * (T-T0) + 1;   // CHECK 
+  double Gt = Ge;
+  double Kt = Ke;
+  
+  // Initialise ptilde and devPhi (phi)
+  ptilde = ptildepr + 1/3*trXn; // current effective pressure  -> first invariant
+  ptilde *= 1/v;
+  devPhi = devPhipr + devXn;
+  devPhi *= 1/u;
+  
+  if (abs(Cx) > 0.0){
+    Gt += pow(kk,1) * Hb/(2*Cx); // pow(kk,2) CHANGE
+    Kt += pow(kk,1) * Hb/(3*Cx); // pow(kk,2) CHANGE
+    
+    ptilde -= 1/3*trXn*1/Cx;
+    devPhi -= devXn;
+    devPhi *= 1/Cx;
+  }
+  
+  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);
+
+
+  // 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);
+        double etaOverDt = eta/this->getTimeStep();
+        
+        double 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
+        
+        // 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
+        
+        static STensor3 DdevPhidDgamma, term2; 
+        STensorOperation::zero(DdevPhidDgamma);
+        if (abs(Cx) > 0.0){
+            // 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;
+            
+            // 2nd term of He
+            term2 = 3*Gamma*pow(kk,1)*Cx*devPhi; // pow(kk,2) CHANGE
+            term2 *= 1/(Cx*Cx*u) * dHb;
+            
+            DdevPhidDgamma -= term2;
+        }
+        double Stemp = STensorOperation::doubledot(devPhi,DdevPhidDgamma);
+        double He = 1.5*Stemp/PhiEq;
+        
+        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 += 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??
+
+        DfDGamma = dfdDgamma*dDgammaDGamma - (_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.);
+
+        double dGamma = -f/DfDGamma;    // NR 
+
+        if (Gamma + dGamma <=0.){
+            Gamma /= 2.;                // NR
+        }
+        else
+          Gamma += dGamma;
+
+        //Msg::Error("Gamma = %e",Gamma);
+        
+        // Correct Phi, A, delgamma
+        Cx = m(0)*Dgamma + m(1)*Px - 1/Hb * dHbdT * (T-T0) + 1;
+        u = 1.+6.*Gt*Gamma;
+        v = 1.+2.*_b*Kt*Gamma; 
+        
+        ptilde = ptildepr + 1/3*trXn; // current effective pressure  -> first invariant
+        ptilde *= 1/v;
+        devPhi = devPhipr + devXn;
+        devPhi *= 1/u;
+        
+        devPhi = (devPhipr + devXn * (1-1/Cx));
+        devPhi *= 1./u;  
+        PhiEq = sqrt(1.5*devPhi.dotprod());
+        ptilde = (ptildepr + 1/3*trXn*(1-1/Cx))/v;  
+        
+        if (abs(Cx) > 0.0){
+            Gt += pow(kk,1) * Hb/(2*Cx); // pow(kk,2) CHANGE
+            Kt += pow(kk,1) * Hb/(3*Cx); // pow(kk,2) CHANGE
+    
+            ptilde -= 1/3*trXn*1/Cx;
+            devPhi -= devXn;
+            devPhi *= 1/Cx;
+        }
+        
+        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);
+
+        updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+        hardening(q0,q1,T);
+        getYieldCoefficients(q1,a);
+        //a.print("a update");
+
+        f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+        double viscoTerm = etaOverDt*Gamma;   // I THINK temperature dependency of viscosity should be present in eta, but this relation remains the same
+        if (Gamma>0 and etaOverDt>0) f-= pow(viscoTerm,_p);
+
+        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;
+        }
+      };
+
+      q1->_DgammaDt = Dgamma/this->getTimeStep();
+
+      // update effective stress tensor
+      // NEW
+      devPhi = (devPhipr + devXn * (1-1/Cx));
+      devPhi *= 1./u;   //NEW
+      ptilde = (ptildepr + 1/3*trXn*(1-1/Cx))/v; //NEW
+      // NEW
+
+      // update 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);
+
+      // update plastic deformation tensor
+      STensorOperation::multSTensor3(expGN,Fp0,Fp1);
+      // update IP
+      updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma); // Why again???? WHAT??
+
+      // update 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; // Here We have assumed that, Ce commutes with Q (i.e. with M) 
+      
+      // update 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 
+
+      // backstress
+      static STensor3 DB; // increment
+      DB = (N); // increment
+      DB *= (kk*Hb*Gamma); // pow(kk,2) CHANGE
+    // NEW
+      DB += q0->_backsig;
+      DB *= 1/Cx;
+      DB -= q0->_backsig;
+    // NEW
+      q1->_backsig += DB; // update
+
+    /*
+      // corotationaal Kirchhoff stress
+      q1->_kirchhoff = devPhi;
+      q1->_kirchhoff += q1->_backsig;
+
+      q1->_kirchhoff(0,0) += (ptilde);
+      q1->_kirchhoff(1,1) += (ptilde);
+      q1->_kirchhoff(2,2) += (ptilde);
+      
+    */ 
+      // NEW
+      q1->_ModMandel = devPhi;
+      q1->_ModMandel += q1->_backsig;
+
+      q1->_ModMandel(0,0) += (ptilde);
+      q1->_ModMandel(1,1) += (ptilde);
+      q1->_ModMandel(2,2) += (ptilde);
+      
+      // NEW
+      
+    }
+    else{
+      q1->getRefToDissipationActive() = false;
+    }
+  }
+
+
+  const STensor3& KS = q1->_kirchhoff;
+  // second Piola Kirchhoff stress
+  // static STensor3 S;
+  // STensorOperation::multSTensor3STensor43(KS,DlnDCe,S);
+  
+  // NEW 
+  getModifiedMandel(Ce, q0, q1); // update Mandel
+  
+  const STensor3& MS = q1->_ModMandel;
+  // second Piola Kirchhoff stress
+  static STensor3 S, Ceinv;
+  STensorOperation::inverseSTensor3(Ce,Ceinv);
+  STensorOperation::multSTensor3(Ceinv,q1->_ModMandel,S);
+  // NEW
+   
+  // 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);
+    }
+
+
+  // defo energy
+  // q1->getRefToElasticEnergy()=deformationEnergy(*q1);
+  q1->getRefToViscousEnergyPart()=viscousEnergy(*q0,*q1)+q0->getConstRefToViscousEnergyPart();
+  q1->getRefToPlasticEnergy() = q0->plasticEnergy();
+  if (Gamma > 0){
+    // NEW  
+    // double dotKSN = dot(KS,N);
+    //q1->getRefToPlasticEnergy() += Gamma*dotKSN;
+    double dotMSN = dot(MS,N);
+    q1->getRefToPlasticEnergy() += Gamma*dotMSN; // = Dp:Me
+    // NEW
+  }
+
+  
+   // 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{
+    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);
+                                      
+  // I didnt make this
+  if (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DEFO_ENERGY){
+    q1->getRefToIrreversibleEnergy() = q1->defoEnergy();
+  }
+  else if ((this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::PLASTIC_ENERGY) or
+           (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DISSIPATION_ENERGY)){
+    q1->getRefToIrreversibleEnergy() = q1->plasticEnergy();
+  }
+  else{
+    q1->getRefToIrreversibleEnergy() = 0.;
+  }
+
+  if (stiff){  
+      
+      // 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 and DCeinvprDCepr
+      static STensor43 DCeprDCepr, DCeinvprDCepr;
+      DCeprDCepr = _I4;
+
+      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;
+          }
+        }
+
+        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);
+          }
+        }
+      
+     //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 = dCxdCepr;
+       temp9 *= (2/3*_b*Gamma*pow(kk,1)*Hb/pow(Cx,2)); // 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;  // CHECK sign
+       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);
+       
+       temp13 = devXn;       // This must be temp12?
+       temp13 *= 1/pow(Cx,2);  // This must be temp12?
+       
+       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)); // pow(kk,2) CHANGE
+         }
+       } 
+       
+       STensorOperation::prod(temp13, temp14, 1., temp11);
+       temp11 *= 1/pow(u,2);
+       
+       DdevphiDCepr -= temp10;  // CHECK sign
+       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)/Cx -  q1->_backsig(i,j)*dCxdCepr(k,l)/Cx; // CHECK, MIGHT HAVE TO DIFFERENTIATE Hb wrt gamma
+               // 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
+    }
+    
+    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.;
+            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);
+          }
+        }
+      }
+    }
+    
+    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, DphiPDF;
+    STensorOperation::multSTensor43(dXdCepr,CeprToF,dXdF); 
+
+    // DphiPDCepr - use this for the pressure term in R
+    // 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;
+    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.;
+            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();
+    
+    /* 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
+          }
+    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
+          }
+    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);
+              }
+            }
+          }
+          
+          
+    // dP/dT
+    
+    // 1. get dMeprDT from dKeprDT  -> DcorKirprDT from TVE
+    static STensor3 dMeprDT, dDevMeprDT, DcorKirDT;
+    double dpMeprDT(0.);
+    const STensor3& dKeprDT = q1->getConstRefToDcorKirDT();
+    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;
+    
+    DcorKirDT = dKeprDT; // update later
+    
+    // 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 = 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
+    
+    // need this for DmechsourceDT -> initialise here (X is backStress)
+    STensor3& dXdT = q1->getRefToDbackStressdT();  
+    STensorOperation::zero(dXdT);
+    dXdT -= (q1->_backsig)*(dCxdT);
+    dXdT *= 1/Cx;
+    
+    // 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  // CHECK the sign of the 2nd term
+    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);  // CHECK the sign of the 2nd term
+      }
+    }
+   
+    // 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 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, dAdT and dfdT
+        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);
+        if (this->getTimeStep()>0){
+            dfdT -= (DetaDT*Gamma/this->getTimeStep())*_p*pow((eta*Gamma/this->getTimeStep()),(_p-1));
+        }
+        
+        // 7. get dGammaDT, DgammaDT
+        dGammaDT = (-dfdT-dfdDgamma*kk*Gamma*dAdT)/DfDGamma;
+        DgammaDT = kk*Gamma*dAdT + kk*dDgammaDGamma*dGammaDT;
+        
+        // 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;
+        
+        // 9. get DtrNdT DdevNdT
+        DtrNdT = dPhiPdT;
+        DtrNdT *= (2*_b);
+
+        DdevNdT = dDevPhiDT;
+        DdevNdT *= 3;
+        
+        // 10. get dFpdT
+        static STensor3 temp20;
+        STensorOperation::zero(temp20);
+        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) + 1/3*Gamma*_I(i,j)*DtrNdT;
+            
+        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);
+                }
+              }
+        
+        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) += EprFp0(i,j,k,l)*temp20(k,l);
+              }
+            }
+          }
+        }
+        
+        // 10.1 dXdT - backstress temperature derivative -> correction
+        
+        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
+          }
+        }
+        
+        // 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)));
+          }
+        }
+        
+    }
+    else{
+        // elastic
+        STensorOperation::zero(DgammaDT);
+        // STensorOperation::zero(dFpdT);
+        STensorOperation::zero(DtrNdT);
+        STensorOperation::zero(DdevNdT);
+        STensorOperation::zero(dGammaDT);
+        }
+        
+    // 11.1
+    q1->_DGammaDT = dGammaDT;
+    q1->_DgammaDT = 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) += 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);
+        }
+      }
+    // 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));
+          }
+      }
+  
+  
+  }
+  
+  if(stiff){
+  
+  // TVP - flux, thermalEnergy, thermalSource
+    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.;
+
+  // mechSourceTVP
+  double& Wm = q1->getRefToMechSrcTVP();
+  double& Wm_TVE = q1->getRefToMechSrcTVE();
+  
+  mechanicalSource = 0.;
+  mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,_I4,&Wm_TVE); // mechSourceTVE
+  // mechanicalSource += Wm_TVE; // DEBUGGING
+
+  getMechSourceTVP(q0,q1,T0,T,dFpdT,dFpdF,DphiPDF,&Wm);
+  // mechanicalSource += Wm;    // DEBUGGING 
+    
+  // freeEnergy and elastic energy
+  double& psiTVM = q1->getRefToFreeEnergyTVM();
+  getFreeEnergyTVM(q0,q1,T0,T,&psiTVM,NULL);
+  
+  q1->_elasticEnergy = mlawNonLinearTVE::freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+  
+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(); // 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);
+    }
+    
+ 
+    // mechSourceTVP derivatives
+    
+    // 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);
+    
+    dmechanicalSourcedT = 0.;
+    STensorOperation::zero(dmechanicalSourceF);
+    // dmechanicalSourceF += dWmdF_TVE; // DEBUGGING 
+    // dmechanicalSourcedT += dWmdT_TVE; // DEBUGGING
+    
+    double& dWmdT = q1->getRefTodMechSrcTVPdT();
+    STensor3& dWmdF = q1->getRefTodMechSrcTVPdF();
+
+    getMechSourceTVP(q0,q1,T0,T,dFpdT,dFpdF,DphiPDF,NULL,&dWmdF,&dWmdT); 
+    
+    // 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 
+  STensor3& Fp1 = q1->_Fp;
+  const STensor3& Fp0 = q0->_Fp;
+
+  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->_DgammaDt = 0.; // plastic rate --> failure
+
+  static STensor3 Fpinv, Ce, Fepr;
+  STensorOperation::inverseSTensor3(Fp1,Fpinv);
+  STensorOperation::multSTensor3(F,Fpinv,Fepr);
+  STensorOperation::multSTensor3FirstTranspose(Fepr,Fepr,Ce);
+
+  static STensor3 invFp0; // plastic predictor
+  invFp0= Fpinv;
+  STensor3& Fe = q1->_Fe;
+  Fe = Fepr;
+
+  static STensor43 DlnDCepr, DlnDCe;
+  static STensor63 DDlnDDCe;
+  static STensor43 dexpAdA; // estimation of dexpA/dA
+
+  STensor3& Ee = q1->_Ee;
+  STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  Ee *= 0.5;
+  DlnDCe = DlnDCepr;
+
+  // update A, B
+  // double Ge, Ke;
+  double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
+  double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;
+  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
+
+  STensorOperation::decomposeDevTr(q1->_kirchhoff,devKpr,ppr);
+  ppr /= 3.;
+  double keqpr = sqrt(1.5*devKpr.dotprod());
+
+  static STensor3 devK;
+  devK= devKpr;  // dev corotational kirchoff stress
+  double p = ppr; // pressure
+
+   // hardening
+  this->hardening(q0,q1,T);
+  fullVector<double> a(3), Da(3); // yield coefficients and derivatives in respect to plastic deformation
+  this->getYieldCoefficients(q1,a);
+
+  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);
+
+  double sigVM = keqpr;
+  double Dgamma = 0.;
+  double Gamma = 0.;
+
+  double g0 = 0.;
+  double z = a(1)/a(2)*pow(sigVM,1.-_n);
+  double A = sqrt(1.5+1.*z*z/(3.*_n*_n));
+
+  static fullMatrix<double> invJ(2,2); // inversed jacobian
+  invJ.setAll(0.);
+
+  double dAdz =0.;
+  double dzdDgamma = 0.;
+  double dzdsigVM = 0.;
+  double dg0dsigVM = -1./(3.*Ge);
+
+  if (q1->dissipationIsBlocked()){
+    q1->getRefToDissipationActive() = false;
+  }
+  else{
+    double f = a(2)*pow(sigVM,_n) - (a(1)*ppr+a(0));
+    if (f>_tol){
+      q1->getRefToDissipationActive() = true;
+      // plasticity
+      int ite = 0;
+      int maxite = 1000; // maximal number of iters
+      double val  = 1.5*a(2)*_n*pow(3.*fabs(p),_n-2.);
+      q1->_nup = (val*p+ a(1)/3.)/(val*2.*p - a(1)/3.);
+      double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+      A*=kk;
+
+      fullVector<double> R(2); // residual of eqs to estimate Dgamma, Dpression and Gamma
+
+      R(0) = Dgamma - g0*A;
+      R(1) = a(2)*pow(sigVM,_n) - a(1)*(ppr+Ke*z*g0/_n) - a(0);
+
+      double res = R.norm();
+
+      while(res>_tol or ite<1){
+
+        this->getYieldCoefficientDerivatives(q1,q1->_nup,Da);
+
+        static fullMatrix<double> J(2,2);
+        J.setAll(0.);
+
+        dAdz = kk*z/(3.*_n*_n*A);
+        dzdDgamma = (Da(1)*a(2) - a(1)*Da(2))/(a(2)*a(2))*pow(sigVM,1.-_n);
+        dzdsigVM = a(1)/a(2)*(1.-_n)*pow(sigVM,-_n);
+
+
+
+        J(0,0) = 1. - g0*dAdz*dzdDgamma;
+        J(0,1) = -dg0dsigVM*A-g0*dAdz*dzdsigVM;
+
+        J(1,0) =  Da(2)*pow(sigVM,_n) - Da(1)*(ppr+Ke*z*g0/_n) - Da(0) - a(1)*Ke*dzdDgamma*g0/_n;
+        J(1,1) = a(2)*_n*pow(sigVM,_n-1) - a(1)*Ke/_n*(dzdsigVM*g0+z*dg0dsigVM);
+
+
+
+        double detJ = J(0,0)*J(1,1) - J(1,0)*J(0,1);
+        if (detJ == 0.) Msg::Error("the corrected system can not be solved: mlawNonLinearTVP::predictorCorrector_associatedFlow");
+
+        invJ(0,0) = J(1,1)/detJ;
+        invJ(0,1) = -J(0,1)/detJ;
+        invJ(1,0) = -J(1,0)/detJ;
+        invJ(1,1) = J(0,0)/detJ;
+
+        double solDgamma = -invJ(0,0)*R(0)-invJ(0,1)*R(1);
+        double solsigVM = -invJ(1,0)*R(0)-invJ(1,1)*R(1);
+
+       // bool isSolved = J.luSolve(residual,sol);
+       // if (!isSolved) Msg::Error("the corrected system can not be solved: mlawPowerYieldHyper::predictorCorrector");
+        //sol.print("sol");
+
+        if (solDgamma >0.1)
+          Dgamma+= 0.1;
+        else if (Dgamma+ solDgamma< 0.)
+          Dgamma /= 2.;
+        else
+          Dgamma += solDgamma;
+
+        if (sigVM + solsigVM< 0.)
+          sigVM /= 2.;
+        else
+          sigVM += solsigVM;
+
+
+        updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+        this->hardening(q0,q1,T);
+        this->getYieldCoefficients(q1,a);
+
+        g0 = (keqpr- sigVM)/(3.*Ge);
+        z = a(1)/a(2)*pow(sigVM,1.-_n);
+        A = kk*sqrt(1.5+1.*z*z/(3.*_n*_n));
+
+        R(0) = Dgamma - g0*A;
+        R(1) = a(2)*pow(sigVM,_n) - a(1)*(ppr+Ke*z*g0/_n) - a(0);
+
+        res = R.norm();
+
+        ite++;
+
+        //Msg::Info("iter = %d, res = %e,  Dgamma = %e, sigVM/keqpr = %e",ite,res, Dgamma, sigVM/keqpr);
+
+        if(ite > maxite){
+          Msg::Error("No convergence for plastic correction in mlawPowerYieldHyper iter = %d, res = %e!!",ite,res);
+          P(0,0) = P(1,1) = P(2,2) = sqrt(-1.);
+          break;
+        }
+      }
+
+      Gamma = z*g0/(_n*a(1));
+
+      // update
+      p += Ke*Gamma*a(1);
+
+      double ff =a(2)*_n*pow(sigVM,_n-2.);
+      devK*= 1./(1.+3.*Ge*Gamma*ff);
+
+      // estimate yield normal
+      devN = devK;
+      devN *=  1.5*ff;
+      trN = -a(1);
+
+      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);
+
+      // update plastic deformation tensor
+      STensorOperation::multSTensor3(expGN,Fp0,Fp1);
+      // update IP
+      updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+
+      // update 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;
+
+      // 
+      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;
+    }
+  }
+
+  // corotational Kirchhoff stress tenor
+
+  STensor3& KS = q1->_kirchhoff;
+  KS = devK;
+  KS(0,0) += p;
+  KS(1,1) += p;
+  KS(2,2) += p;
+
+  // first Piola Kirchhoff stress
+  static STensor3 S;
+  S*=(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++)
+          S(i,j)+= KS(k,l)*DlnDCe(k,l,i,j);
+
+  STensorOperation::zero(P);
+  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++)
+          P(i,j) += Fe(i,k)*S(k,l)*Fpinv(j,l);
+
+  // defo energy
+  q1->_elasticEnergy=deformationEnergy(*q1);
+  q1->getRefToPlasticEnergy() = q0->plasticEnergy();
+  if (Gamma > 0){
+    double dotKSN = dot(KS,N);
+    q1->getRefToPlasticEnergy() += Gamma*dotKSN;
+  }
+
+  if (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DEFO_ENERGY){
+    q1->getRefToIrreversibleEnergy() = q1->defoEnergy();
+  }
+  else if ((this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::PLASTIC_ENERGY) or
+           (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DISSIPATION_ENERGY)){
+    q1->getRefToIrreversibleEnergy() = q1->plasticEnergy();
+  }
+  else{
+    q1->getRefToIrreversibleEnergy() = 0.;
+  }
+
+  if (stiff){
+     // FILL THIS
+      }
+};   
+
+/*
+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& 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  = q1->_DbackSigDT;
+    const STensor3& dXdT_0  = q0->_DbackSigDT;
+    const STensor43& dXdF_0  = q0->_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);
+    
+    // get Dgamma
+    double Dgamma = gamma1 - gamma0;
+    
+    // get Hb
+    double Hb(0.), dHb(0), dHbdT(0.), ddHbddT(0.);
+    if (q1->_ipKinematic != NULL){
+        Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
+        dHb = q1->_ipKinematic->getDDR();
+        dHbdT = q1->_ipKinematic->getDRDT();
+        ddHbddT = q1->_ipKinematic->getDDRDDT();
+    }
+
+    // get Dp
+    static STensor3 Fpinv, Fp_dot, Dp;
+    STensorOperation::inverseSTensor3(Fp1,Fpinv);
+    Fp_dot = Fp1;
+    Fp_dot -= Fp0;
+    STensorOperation::multSTensor3(Dp,Fp_dot,Fpinv);
+   
+    // 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?  
+    alpha1 -= alpha0;
+    alpha1 *= 1/this->getTimeStep();
+    
+    // get TempX - convenient backStress tensor
+    STensor3 tempX;
+    tempX = X1;
+    tempX -= T*dXdT; 
+    
+    // get R
+    getIsotropicHardeningForce(q0,q1,T0,T,Gamma,dFpdT,dFpdF,dPhiPdF,ddRdTT,ddRdFdT);
+    
+    double eta(0.),Deta(0.),DetaDT(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);
+    double etaOverDt = eta/this->getTimeStep();
+    double viscoTerm = etaOverDt*Gamma;
+    
+    const double& R0 = 0;
+    
+    // double& R = q1->getRefToIsotropicHardeningForce(); //change
+    const double& dRdT_0 = 0; 
+    // double& dRdT = q1->_dIsoHardForcedT; 
+    double R(0.); 
+    double dRdT(0.);
+    R = -a(1)/a(2) * (trMe-trX1); 
+    dRdT = (-DaDT(1)/a(2) + a(1)/pow(a(2),2) *DaDT(2))*(trMe-trX1) + (-a(1)/a(2))*(dTrMeDT-dTrXdT);
+    R -= a(0)/a(2); 
+    dRdT += (-DaDT(0)/a(2) + a(0)/pow(a(2),2)*DaDT(2));
+    if (Gamma>0 and etaOverDt>0){
+        R -= 1/a(2)*pow(eta*Gamma/this->getTimeStep(),_p);
+        dRdT += (1/pow(a(2),2)*DaDT(2)*pow(eta*Gamma/this->getTimeStep(),_p) 
+                - 1/a(2)*_p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(DetaDT*Gamma/this->getTimeStep() 
+                + eta*dGammaDT/this->getTimeStep()) ); 
+    }
+        
+    R -= T*dRdT;
+    
+    // mechSourceTVP
+    if(Wm!=NULL){
+        double mechSourceTVP = STensorOperation::doubledot(Me,Dp);
+        mechSourceTVP -= STensorOperation::doubledot(tempX,alpha1);
+        mechSourceTVP -= (R*Dgamma)/this->getTimeStep();
+        *Wm = mechSourceTVP;
+        // Second Term TBD - need dXdT, dRdT -> added above
+    }
+    
+    // Some Generic Conversion Tensors
+    static STensor43 dDpdFp, dFpinvdFp;
+    
+    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,j,k,s)*Fpinv(s,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++){
+            dDpdFp(i,j,k,l) = 0.;
+            for (int m=0; m<3; m++)
+              dDpdFp(i,j,k,l) += 1/this->getTimeStep()*_I4(i,j,k,m)*Fpinv(m,l) + Fp_dot(i,m)*dFpinvdFp(m,j,k,l);
+          }
+    
+    // dDpdF and dDpdT
+    static STensor43 dDpdF;   
+    // STensorOperation::zero(dDpdF);
+    STensorOperation::multSTensor43(dDpdFp, dFpdF, dDpdF);
+          
+    static STensor3 dDpdT;
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        dDpdT(i,j) = 0.;
+        for (int k=0; k<3; k++)
+          for (int l=0; l<3; l++)
+            dDpdT(i,j) += dDpdFp(i,j,k,l)*dFpdT(k,l);
+      }
+      
+   // dXdF is available 
+   // const STensor43 dXdF = q1->_DbackSigDF;
+   
+   // ddXdTF -> make it -- CHANGE!!
+   static STensor43 ddXdTF; // ddGammaDTF and ddQDTF are very difficult to estimate
+   static STensor3 ddXdTT; // ddGammaDTT and ddQDTT are very difficult to estimate
+   STensorOperation::zero(ddXdTF);
+   STensorOperation::zero(ddXdTT);
+   double delT = T-T0;
+   if (delT>1e-10){
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        ddXdTT(i,j) += 2*dXdT(i,j)/(T-T0) - 2*(X1(i,j)-X0(i,j))/pow((T-T0),2);
+        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);
+          }
+        }
+      }
+   
+   // 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;
+        }
+   
+   
+    // dRdF
+    // static STensor3 dRdF;
+    const STensor3& dRdF_0 = 0.; //q0->_dIsoHardForcedF;
+    // STensor3& dRdF = q1->_dIsoHardForcedF;
+    static STensor3 dRdF;
+    for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        dRdF(i,j) = (-Da(1)/a(2) + a(1)/pow(a(2),2) *Da(2))*(trMe-trX1)*DgammaDF(i,j) + (-a(1)/a(2))*dPhiPdF(i,j) + (-Da(0)/a(2) + a(0)/pow(a(2),2)*Da(2))*DgammaDF(i,j);
+        }
+          
+    if (Gamma>0 and etaOverDt>0){
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dRdF += (1/pow(a(2),2)*Da(2)*pow(eta*Gamma/this->getTimeStep(),_p)*DgammaDF(i,j) 
+                    - 1/a(2)*_p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(eta*DGammaDF(i,j)/this->getTimeStep())); 
+          }
+    }
+    
+   // ddRdTT, ddRdTF -> make all these -- CHANGE!!    
+   static STensor3 ddRdTF;
+   for (int i=0; i<3; i++)
+      for (int j=0; j<3; j++){
+        ddRdTF(i,j) = (dRdF(i,j)-dRdF_0(i,j))/(T-T0);
+      }
+   // STensorOperation::zero(ddRdTF); // ddGammaDTF is very difficult to estimate
+   
+   static double ddRdTT;
+   ddRdTT = 2*dRdT/(T-T0) -2*(R-R0)/pow((T-T0),2); // 0.; // ddGammaDTT is very difficult to estimate
+   
+   
+   // dMedF is available
+   // const STensor43 dMedF = q1->_DModMandelDF;
+
+    if(dWmdF!=NULL){
+        STensor3 dmechSourceTVPdF;
+        
+        for (int i=0; i<3; i++)
+          for (int j=0; j<3; j++){
+            dmechSourceTVPdF(i,j) = - (dRdF(i,j) - T*ddRdTF(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(k,l) + Me(i,j)*dDpdF(i,j,k,l) 
+                                        - (dXdF(i,j,k,l) - T*ddXdTF(i,j,k,l))*alpha1(k,l) - tempX(i,j)*dAlphadF(i,j,k,l)/this->getTimeStep();
+              }
+          }
+          
+        *dWmdF = dmechSourceTVPdF;
+    }
+    
+    if(dWmdT!=NULL){
+        double dmechSourceTVPdT(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() ;
+              }
+        *dWmdT = dmechSourceTVPdT;
+    }
+}; */
+
+/*void mlawNonLinearTVP::getFreeEnergyTVM(const IPNonLinearTVP *q0, const IPNonLinearTVP *q1, const double& T0, const double& T,
+                                      double *psiTVM, double *DpsiTVMdT, double *DDpsiTVMdTT) const{
+
+    // get some Things
+    const double& Gamma = q1->_Gamma;
+    const double& DgammaDT = q1->_DgammaDT;
+    const double& dGammaDT = q1->_DGammaDT;
+    const STensor3& Me = q1->_ModMandel;
+    const STensor3& X = q1->_backsig;
+    const STensor3& dXdT  = q1->_DbackSigDT;
+    const STensor3& ddMedTT(0.);                   // CHANGE!!
+    const STensor3& ddXdTT(0.);                    // CHANGE!!
+    
+    STensor3 devMe, devX, dDevXdT, dDevMeDT, ddDevXdTT, ddDevMeDTT;
+    double trMe, trX, dTrXdT, dTrMeDT, ddTrXdTT, ddTrMedTT;
+    STensorOperation::decomposeDevTr(q1->_ModMandel,devMe,trMe); 
+    STensorOperation::decomposeDevTr(q1->_backsig,devX,trX); 
+    STensorOperation::decomposeDevTr(q1->_DbackSigDT,dDevXdT,dTrXdT); 
+    STensorOperation::decomposeDevTr(q1->_DModMandelDT,dDevMeDT,dTrMeDT);
+    STensorOperation::decomposeDevTr(ddXdTT,ddDevXdTT,ddTrXdTT);
+    STensorOperation::decomposeDevTr(ddMedTT,ddDevMeDTT,ddTrMedTT);
+    
+    // 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 = CpT*((T-_Tinitial)-T*log(T/_Tinitial));
+    DpsiTdT = -CpT*log(T/_Tinitial) - psiT/CpT*DCpDT;
+    DpsiTdTT = -CpT/T - psiT/CpT*DDCpDTT;
+    
+    //
+    // psiVP -> make IP for this  CHANGE!!!
+    
+      // get Isotropic Hardening stuff
+    double eta(0.),Deta(0.),DetaDT(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);
+    double etaOverDt = eta/this->getTimeStep();
+    double viscoTerm = etaOverDt*Gamma;
+    
+    double R1(0.), R2(0.), R3(0.), dR1dT(0.), dR2dT(0.), dR3dT(0.), ddR1dTT(0.), ddR2dTT(0.), ddR3dTT(0.);
+    R1 = -a(1)/a(2) * (trMe-trX); 
+    dR1dT = (-DaDT(1)/a(2) + a(1)/pow(a(2),2) *DaDT(2))*(trMe-trX) + (-a(1)/a(2))*(dTrMeDT-dTrXdT);
+    R2 = -a(0)/a(2); 
+    dR2dT = (-DaDT(0)/a(2) + a(0)/pow(a(2),2)*DaDT(2));
+    if (Gamma>0 and etaOverDt>0){
+        R3 -= 1/a(2)*pow(eta*Gamma/this->getTimeStep(),_p); 
+        dR3dT += (1/pow(a(2),2)*DaDT(2)*pow(eta*Gamma/this->getTimeStep(),_p) 
+                - 1/a(2)*_p*pow(eta*Gamma/this->getTimeStep(),_p-1)*(DetaDT*Gamma/this->getTimeStep() 
+                + eta*dGammaDT/this->getTimeStep()) ); 
+    }
+    
+     // 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();
+    }
+
+    double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+    static STensor3 alpha;
+    alpha = X;
+    alpha *= 1/(pow(kk,2)*Hb);
+    
+    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) + X(i,j)*DgammaDT*1/(pow(kk*Hb,2))*dHbdT;
+      }
+    
+    
+     // finally
+    STensorOperation::doubleContractionSTensor3(X,alpha,psiVP);
+    psiVP *= 0.5;
+    psiVP += 0.5*( 1/_HR[0]*R1*a(1)/a(2) + 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*(0.);
+      }
+    DpsiVPdT += 0.5*( 1/_HR[0]*(dR1dT*a(1)/a(2) + R1*(DaDT(1)/a(2) - a(1)/pow(a(2),2) *DaDT(2))) + 2/_HR[1]*R2*dR2dT + 2/_HR[2]*R3*dR3dT );
+    
+    DDpsiVPdTT += 0.; // 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);
+    
+    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);
+    
+    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;
+    DdevKeinfDT *= dGdT/GT;
+    DDdevKeinfDTT = devKeinf;
+    DDdevKeinfDTT *= ddGdTT/GT;
+
+    const std::vector<STensor3>& devOi = q1->getConstRefToDevViscoElasticOverStress();
+    const std::vector<double>& trOi = q1->getConstRefToTrViscoElasticOverStress();
+    const std::vector<STensor3>& devDOiDT = q1->getConstRefToDevDOiDT();
+    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);
+    
+    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)); 
+    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)) 
+                      - 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)){
+      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));
+        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));
+          }    
+        }
+    }
+    
+    // FINALLY
+    if(psiTVM!=NULL){
+        *psiTVM = psiT + psiVE + psiVP;
+    }
+    if(DpsiTVMdT!=NULL){
+        *DpsiTVMdT = DpsiTdT + DpsiVEdT + DpsiVPdT;
+    }
+    if(DDpsiTVMdTT!=NULL){
+        *DDpsiTVMdTT = DpsiTdTT + DDpsiVEdTT + DDpsiVPdTT;
+    }
+
+};*/
+
+/* OLD PLasticity Correction step
+
+ * // compute elastic predictor 
+  STensor3& Fp1 = q1->_Fp;
+  const STensor3& Fp0 = q0->_Fp;
+
+  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.;
+
+
+  static STensor3 Fpinv, Ce, Fepr;
+  STensorOperation::inverseSTensor3(Fp1,Fpinv);
+  STensorOperation::multSTensor3(F,Fpinv,Fepr);
+  STensorOperation::multSTensor3FirstTranspose(Fepr,Fepr,Ce);
+  
+  // NEW
+  static STensor3 Cepr, Ceinvpr;
+  Cepr = Ce;
+  STensorOperation::inverseSTensor3(Cepr,Ceinvpr);
+  // NEW
+
+  static STensor3 invFp0; // plastic predictor
+  invFp0= Fpinv;
+  STensor3& Fe = q1->_Fe;
+  Fe = Fepr;
+
+  static STensor43 DlnDCepr, DlnDCe;
+  static STensor63 DDlnDDCe;
+  static STensor3 expGN;
+  static STensor43 dexpAdA; // estimation of dexpA/dA
+
+  STensor3& Ee = q1->_Ee;
+  STensorOperation::logSTensor3(Ce,_order,Ee,&DlnDCepr,&DDlnDDCe);
+  Ee *= 0.5;
+  DlnDCe = DlnDCepr;
+
+  // update A, B
+  // double Ge, Ke;
+  double Ke, Ge = 0.; double Kde, Gde = 0.; double KTsum, GTsum = 0.;
+  double DKe, DGe = 0.; double DKde, DGde = 0.; double DKDTsum, DGDTsum = 0.;
+  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);
+  
+  // NEW
+  static STensor3 Me, Mepr, Kepr;  // Ke is corKir
+  
+  getModifiedMandel(Ce,q0,q1);
+  Me = q1->_ModMandel;
+  Mepr = Me;
+  Kepr = q1-> _kirchhoff;
+  // const STensor3& dKeprDT = q1->getConstRefToDcorKirDT();
+  // NEW
+
+  // NEW
+  static STensor3 devXn;
+  static double trXn;
+  STensorOperation::decomposeDevTr(q0->_backsig,devXn,trXn); // needed for chaboche model
+  // NEW
+  
+  static STensor3 PhiPr;
+  PhiPr = q1->_ModMandel; // _kirchhoff; //NEW
+  PhiPr -= q1->_backsig;
+  
+  static STensor3 devPhipr,devPhi; // effective dev stress predictor
+  static double ptildepr,ptilde;
+  STensorOperation::decomposeDevTr(PhiPr,devPhipr,ptildepr);
+  ptildepr/= 3.;
+
+  ptilde = ptildepr; // current effective pressure  -> first invariant
+  devPhi = devPhipr;
+
+  double PhiEqpr2 = 1.5*devPhipr.dotprod();
+  double PhiEqpr = sqrt(PhiEqpr2);      // -> second invariant
+
+  // plastic poisson ratio
+  q1->_nup = (9.-2.*_b)/(18.+2.*_b);
+  double kk = 1./sqrt(1.+2.*q1->_nup*q1->_nup);
+
+  // double Gamma = 0.;   // flow rule parameter
+  double& Gamma = q1->_Gamma;   // flow rule parameter
+  double PhiEq = PhiEqpr;   // current effective deviator  
+
+
+   // hardening
+  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);
+
+  double Hb(0.), dHbdT(0.), ddHbddT(0.);
+  if (q1->_ipKinematic != NULL){
+    Hb = q1->_ipKinematic->getDR(); // kinematic hardening parameter
+    dHbdT = Hb * q1->_ipKinematic->getDRDT();  // make sure to normalise DRDT while defining in python file //NEW
+    ddHbddT = Hb * q1->_ipKinematic->getDDRDDT();
+  }
+
+  //a.print("a init");
+
+  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);
+
+  double f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+
+  double DfDGamma = 0.;
+  double dfdDgamma = 0.;
+  
+  // NEW  
+   // Change u and v inside iterations
+  double u = 1.;
+  double v = 1.;
+  // NEW
+ 
+  double A = sqrt(6.*PhiEq*PhiEq+4.*_b*_b/3.*ptilde*ptilde);
+
+
+  double dDgammaDGamma = 0.;
+  double Dgamma = 0.; // eqplastic strain
+  
+// NEW
+  double Gt = 0.; // Ge + kk*Hb/2.;
+  double Kt = 0.; // Ke + kk*Hb/3.;
+  static fullVector<double> m(2);
+  getChabocheCoeffs(m,0,q1);
+  double Cx(0.), Px(0.);
+  getPlasticPotential(ptilde, PhiEq, Px); 
+  Cx = m(0)*(q0->_epspbarre + Dgamma) + m(1)*Px - 1/Hb * dHbdT + 1;  
+  Gt = Ge + pow(kk,2) * Hb/(2*Cx);
+  Kt = Ke + pow(kk,2) * Hb/(3*Cx);
+// NEW  
+
+  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){
+        double eta(0.),Deta(0.),DetaDT(0.);
+        if (_viscosity != NULL)
+          _viscosity->get(q1->_epspbarre,T,eta,Deta,DetaDT);
+        double etaOverDt = eta/this->getTimeStep();
+        
+     // NEW
+        // DEFINE THESE INSIDE PLASTIC ITERATIONS -> Because dgamma is available here
+        // need to calculate m(0) and m(1), preferably like yield coeffs (a(i)), they are functions of gamma 
+        // make sure that Px is already multiplied to m(1) or something
+        // put these inside the iterations? Because dgamma isnt available here -> may have to put it in IP?
+        // add temp funcs for dHbdT
+     
+        // Cx = m(0)*(q0->_epspbarre + Dgamma) + m(1)*Px - 1/Hb * dHbdT + 1;  
+        // Gt = Ge + pow(kk,2) * Hb/(2*Cx);
+        // Kt = Ke + pow(kk,2) * Hb/(3*Cx);
+    // NEW  
+        
+    // NEW
+        double dAdGamma = -(72.*Gt*PhiEq*PhiEq/u+ 16.*Kt*_b*_b*_b*ptilde*ptilde/(3.*v))/(2.*A);
+        // double dAdGamma = -(72.*Gt*PhiEq*PhiEq/u+ 16.*Kt*_b*_b*_b*ptilde*ptilde/(3.*v))/(2.*A); // -> the same
+    // NEW
+        
+        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); 
+    // NEW
+        double dCxdDgamma = m(0);
+        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
+        double Hp = ptilde*(2*_b*Gamma*kk*kk*Hb - trXn)/(3*Cx*Cx*v) * dCxdDgamma;
+        dfdDgamma += a(2)*_n*pow(PhiEq,(_n-1))*He - a(1)*Hp;
+    // NEW
+        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??
+
+        DfDGamma = dfdDgamma*dDgammaDGamma - (_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.);
+
+        double dGamma = -f/DfDGamma; // WHAT 
+
+        if (Gamma + dGamma <=0.){
+            Gamma /= 2.;                // WHAT
+        }
+        else
+          Gamma += dGamma;
+
+        //Msg::Error("Gamma = %e",Gamma);
+
+        u = 1.+6.*Gt*Gamma;
+        v = 1.+2.*_b*Kt*Gamma; 
+    // NEW       
+        // PhiEq = PhiEqpr/u; // -> original
+        // ptilde = ptildepr/v; // -> original
+        devPhi = (devPhipr + devXn * (1-1/Cx));
+        devPhi *= 1./u;  
+        PhiEq = sqrt(1.5*devPhi.dotprod());
+        ptilde = (ptildepr + 1/3*trXn*(1-1/Cx))/v;
+     // NEW   
+        
+        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);
+
+        updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma);
+        hardening(q0,q1,T);
+        getYieldCoefficients(q1,a);
+        //a.print("a update");
+
+        f = a(2)*pow(PhiEq,_n) - (a(1)*ptilde+a(0));
+        double viscoTerm = etaOverDt*Gamma;   // I THINK temperature dependency of viscosity should be present in eta, but this relation remains the same
+        if (Gamma>0 and etaOverDt>0) f-= pow(viscoTerm,_p);
+
+        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;
+        }
+      };
+
+      q1->_DgammaDt = Dgamma/this->getTimeStep();
+
+      // update effective stress tensor
+      // NEW
+      devPhi = (devPhipr + devXn * (1-1/Cx));
+      devPhi *= 1./u;   //NEW
+      ptilde = (ptildepr + 1/3*trXn*(1-1/Cx))/v; //NEW
+      // NEW
+
+      // update 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);
+
+      // update plastic deformation tensor
+      STensorOperation::multSTensor3(expGN,Fp0,Fp1);
+      // update IP
+      updateEqPlasticDeformation(q1,q0,q1->_nup,Dgamma); // Why again???? WHAT??
+
+      // update 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; // Here We have assumed that, Ce commutes with Q (i.e. with M) 
+      
+      // update 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 
+
+      // backstress
+      static STensor3 DB; // increment
+      DB = (N); // increment
+      DB *= (kk*Hb*Gamma);
+    // NEW
+      DB += q0->_backsig;
+      DB *= 1/Cx;
+      DB -= q0->_backsig;
+    // NEW
+      q1->_backsig += DB; // update
+
+    /*
+      // corotationaal Kirchhoff stress
+      q1->_kirchhoff = devPhi;
+      q1->_kirchhoff += q1->_backsig;
+
+      q1->_kirchhoff(0,0) += (ptilde);
+      q1->_kirchhoff(1,1) += (ptilde);
+      q1->_kirchhoff(2,2) += (ptilde);
+      
+    */ 
+    /*
+      // NEW
+      q1->_ModMandel = devPhi;
+      q1->_ModMandel += q1->_backsig;
+
+      q1->_ModMandel(0,0) += (ptilde);
+      q1->_ModMandel(1,1) += (ptilde);
+      q1->_ModMandel(2,2) += (ptilde);
+      
+      // NEW
+      
+    }
+    else{
+      q1->getRefToDissipationActive() = false;
+    }
+  }
+
+
+  const STensor3& KS = q1->_kirchhoff;
+  // second Piola Kirchhoff stress
+  // static STensor3 S;
+  // STensorOperation::multSTensor3STensor43(KS,DlnDCe,S);
+  
+  // NEW 
+  getModifiedMandel(Ce, q0, q1); // update Mandel // this step is probably wrong -> Mandel is already being updated above in the NR loop. Should corKir come from Mandel then?
+                                    // WHAT ???
+  const STensor3& MS = q1->_ModMandel;
+  // second Piola Kirchhoff stress
+  static STensor3 S, Ceinv;
+  STensorOperation::inverseSTensor3(Ce,Ceinv);
+  STensorOperation::multSTensor3(Ceinv,MS,S);
+  // NEW
+
+  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);
+    }
+
+
+  // defo energy
+  // q1->getRefToElasticEnergy()=deformationEnergy(*q1);
+  q1->getRefToViscousEnergyPart()=viscousEnergy(*q0,*q1)+q0->getConstRefToViscousEnergyPart();
+  q1->getRefToPlasticEnergy() = q0->plasticEnergy();
+  if (Gamma > 0){
+    // NEW  
+    // double dotKSN = dot(KS,N);
+    //q1->getRefToPlasticEnergy() += Gamma*dotKSN;
+    double dotMSN = dot(MS,N);
+    q1->getRefToPlasticEnergy() += Gamma*dotMSN; // = Dp:Me
+    // NEW
+  }
+
+  
+   // 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{
+    STensorOperation::inverseSTensor3(F,Finv);
+    J = STensorOperation::determinantSTensor3(F);
+   }
+   
+   static STensor3 Cinv;
+   STensorOperation::multSTensor3SecondTranspose(Finv,Finv,Cinv);
+   STensorOperation::multSTensor3SVector3(Cinv,gradT,fluxT);
+   fluxT *= (-KThConT*J);
+
+   // thermalEnergy -> assuming stiff = false  
+   double CpT; 
+   if (stiff){
+       double& DDpsiTVMdTT = q1->getRefToDDFreeEnergyTVMdTT();
+       getFreeEnergyTVM(q0,q1,T0,T,NULL,NULL,&DDpsiTVMdTT);
+       CpT = -T*DDpsiTVMdTT;
+    }
+   else{
+       getCp(CpT,T);
+    }
+ 
+   q1->_thermalEnergy = CpT*T;  
+    
+   // thermalSource
+   if (this->getTimeStep() > 0.){
+    thermalSource = -CpT*(T-T0)/this->getTimeStep();
+    }
+   else
+    thermalSource = 0.;
+
+  // NEW - mechSourceTVP
+  double& Wm = q1->getRefToMechSrcTVP();
+  double& Wm_TVE = q1->getRefToMechSrcTVE();
+  
+  // Have to do this to update DcorKirDT in IP, and mechSourceTVE and derivatives
+  mechanicalSource = 0.;
+  mlawNonLinearTVE::getMechSourceTVE(q0,q1,T0,T,DKDTsum,DGDTsum,_I4,&Wm_TVE);
+  // STensor3 temp101 = q1->_DcorKirDT;
+  mechanicalSource += Wm_TVE;
+ 
+  STensor3 P_TVE(0.);
+  SVector3 fluxT_TVE(0.);
+  double thermalSource_TVE(0.);
+  double mechanicalSource_TVE(0.);
+ /* mlawNonLinearTVE::predictorCorrector_ThermoViscoElastic(q0->getConstRefToFe(), q1->getConstRefToFe(), P_TVE, q0, q1, Tangent, dFedF, dFedT,
+                                                      T0, T, gradT0, gradT, fluxT_TVE, dPdT, dfluxTdgradT, dfluxTdT, dfluxTdF, 
+                                                      thermalSource_TVE, dthermalSourcedT, dthermalSourcedF, 
+                                                      mechanicalSource, dmechanicalSourcedT, dmechanicalSourceF, 
+                                                      stiff);
+
+
+  getMechSourceTVP(q0,q1,T0,T,_I,_I4,_I,&Wm);
+  mechanicalSource += Wm;
+    
+  // freeEnergy and elastic energy
+  double& psiTVM = q1->getRefToFreeEnergyTVM();
+  getFreeEnergyTVM(q0,q1,T0,T,&psiTVM,NULL);
+  
+  q1->_elasticEnergy = mlawNonLinearTVE::freeEnergyMechanical(*q1,T);     // deformationEnergy(*q1,T);
+                                      
+  // I didnt make this
+  if (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DEFO_ENERGY){
+    q1->getRefToIrreversibleEnergy() = q1->defoEnergy();
+  }
+  else if ((this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::PLASTIC_ENERGY) or
+           (this->getMacroSolver()->getPathFollowingLocalIncrementType() == pathFollowingManager::DISSIPATION_ENERGY)){
+    q1->getRefToIrreversibleEnergy() = q1->plasticEnergy();
+  }
+  else{
+    q1->getRefToIrreversibleEnergy() = 0.;
+  } 
+  
+  */
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/mlawNonLinearTVP.h b/NonLinearSolver/materialLaw/mlawNonLinearTVP.h
new file mode 100644
index 0000000000000000000000000000000000000000..922286a716d4ae3e6cbc8f83a340f0379460d07f
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawNonLinearTVP.h
@@ -0,0 +1,228 @@
+//
+// C++ Interface: Material Law
+//
+// Description: Non-Linear Thermo-Visco-Mechanics (Thermo-ViscoElasto-ViscoPlasto Law) with Non-Local Damage Interface (soon.....)
+//
+// Author: <Ujwal Kishore J - FLE_Knight>, (C) 2022
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MLAWNONLINEARTVP_H_
+#define MLAWNONLINEARTVP_H_
+
+#include "ipNonLinearTVP.h"
+#include "mlawNonLinearTVE.h"
+
+class mlawNonLinearTVP : public mlawNonLinearTVE{
+
+    protected:
+        // double _tol; // for plasticity convergence
+        double _TaylorQuineyFactor; // for heat conversion
+        
+        scalarFunction* _temFunc_Sy0; // temperature dependence of initial yield stress
+        scalarFunction* _temFunc_H; // temperature dependence of hardening stress    
+        scalarFunction* _temFunc_visc; // temperature dependence of viscosity law
+        scalarFunction* _temFunc_Hb; // temperature dependence of kinematic hardening modulus  
+        
+        std::vector<double> _HR; // isotropic hardening moduli for R
+        
+    protected:
+    
+        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 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,
+                                      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 getFreeEnergyTVM(const IPNonLinearTVP *q0, IPNonLinearTVP *q1, const double& T0, const double& T,
+                                      double *psiTVM = NULL, double *DpsiTVMdT = NULL, double *DDpsiTVMdTT = 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,
+                            const SVector3 &gradT0,                 // previous temperature gradient
+                            const SVector3 &gradT,                  // temperature gradient
+                                  SVector3 &fluxT,                  // temperature flux
+                                  STensor3 &dPdT,                   // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT,           // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                                  double &thermalSource,            // - Cp*dTdt
+                                  double &dthermalSourcedT,         // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource,         // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const;
+
+        virtual void predictorCorrector_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;
+                            
+        virtual void predictorCorrector_ThermoViscoPlastic(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43* elasticTangent) const;
+
+        virtual void predictorCorrector_ThermoViscoPlastic(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previoustemeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &thermalSource,   // - cp*dTdt
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &mechanicalSource, // mechanical source--> convert to heat
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF,
+                            const bool stiff,
+                                  STensor43* elasticTangent) const; // tangent is used by pointer, if NULL->no compute
+                            
+        virtual void tangent_full_perturbation( // compute tangent by perturbation
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F1,         // updated deformation gradient (input @ time n+1)
+                                  STensor3& P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPNonLinearTVP *q0,       // array of initial internal variable
+                                  IPNonLinearTVP *q1,             // updated array of internal variable (in ipvcur on output),
+                            const double& T0, // previous temperature
+                            const double& T, // temperature
+                            const SVector3 &gradT0, // previous temeprature gradient
+                            const SVector3 &gradT, // temeprature gradient
+                                  SVector3 &fluxT, // temperature flux)
+                                  double &thermalSource,
+                                  double &mechanicalSource,
+                                  STensor43 &Tangent,         // mechanical tangents (output)
+                                  STensor43 &dFpdF, // plastic tangent
+                                  STensor3 &dFpdT, // plastic tangent
+                                  STensor43 &dFedF, // elastic tangent
+                                  STensor3 &dFedT, // elastic tangent
+                                  STensor3 &dPdT, // mechanical-thermal coupling
+                                  STensor3 &dfluxTdgradT, // thermal tengent
+                                  SVector3 &dfluxTdT,
+                                  STensor33 &dfluxTdF, // thermal-mechanical coupling
+                                  double &dthermalSourcedT, // thermal source
+                                  STensor3 &dthermalSourcedF,
+                                  double &dmechanicalSourcedT,
+                                  STensor3 &dmechanicalSourceF) const;
+                            
+                            
+    public: 
+        mlawNonLinearTVP(const int num, const double E, const double nu, const double rho, const double tol, 
+                         const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                         const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = true);
+        
+        #ifndef SWIG
+        mlawNonLinearTVP(const mlawNonLinearTVP& src);
+        mlawNonLinearTVP& operator=(const materialLaw& source);
+        virtual ~mlawNonLinearTVP();
+        
+        virtual bool withEnergyDissipation() const {return true;};
+        
+        virtual void setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3);
+        
+        void setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc){
+            if (_temFunc_Sy0 != NULL) delete _temFunc_Sy0;
+            _temFunc_Sy0 = Tfunc.clone();
+        }
+        void setTemperatureFunction_Hardening(const scalarFunction& Tfunc){
+            if (_temFunc_H != NULL) delete _temFunc_H;
+            _temFunc_H = Tfunc.clone();
+            // _compression->setTemperatureFunction(Tfunc);
+            // _traction->setTemperatureFunction(Tfunc); // - this is difficult, because of multiple parameters
+        }
+        void setTemperatureFunction_KinematicHardening(const scalarFunction& Tfunc){
+            if (_temFunc_Hb != NULL) delete _temFunc_Hb;
+            _temFunc_Hb = Tfunc.clone();
+            // _kinematic->setTemperatureFunction_K(Tfunc); 
+                    // - this is not a pure virtual parent class, on the other hand the viscosity/kine harde type isnt set here but in the .py file.
+        }
+        void setTemperatureFunction_Viscosity(const scalarFunction& Tfunc){
+            if (_temFunc_visc != NULL) delete _temFunc_visc;
+            _temFunc_visc = Tfunc.clone();
+            // _viscosity->setTemperatureFunction(Tfunc);
+        }
+        
+        void setTaylorQuineyFactor(const double f){_TaylorQuineyFactor = f;};
+        
+        virtual matname getType() const{return materialLaw::nonlinearTVP;}
+        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("mlawNonLinearTVP::createIPState has not been defined");
+        }
+        virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}; // this law is initialized so nothing to do
+
+        virtual void constitutive(
+                    const STensor3& F0,         // initial deformation gradient (input @ time n)
+                    const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                          STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                    const IPVariable *q0,       // array of initial internal variable
+                          IPVariable *q1,             // updated array of internal variable (in ipvcur on output),
+                          STensor43 &Tangent,         // constitutive tangents (output)
+                    const bool stiff,           // if true compute the tangents
+                          STensor43* elasticTangent = NULL, 
+                    const bool dTangent =false,
+                          STensor63* dCalgdeps = NULL) const;
+            
+        virtual void constitutive(
+                    const STensor3& F0,                     // initial deformation gradient (input @ time n)
+                    const STensor3& F1,                     // updated deformation gradient (input @ time n+1)
+                          STensor3& P,                      // updated 1st Piola-Kirchhoff stress tensor (output)
+                    const IPVariable *q0,                   // array of initial internal variable
+                          IPVariable *q1,                   // updated array of internal variable (in ipvcur on output),
+                          STensor43 &Tangent,               // constitutive mechanical tangents (output)
+                    const double& T0,                       // previous temperature
+                    const double& T,                        // temperature
+                    const SVector3 &gradT0,                 // previous temperature gradient
+                    const SVector3 &gradT,                  // temperature gradient
+                          SVector3 &fluxT,                  // temperature flux
+                          STensor3 &dPdT,                   // mechanical-thermal coupling
+                          STensor3 &dfluxTdgradT,           // thermal tengent
+                          SVector3 &dfluxTdT,
+                          STensor33 &dfluxTdF,              // thermal-mechanical coupling
+                          double &thermalSource,            // - Cp*dTdt
+                          double &dthermalSourcedT,         // thermal source
+                          STensor3 &dthermalSourcedF,
+                          double &mechanicalSource,         // mechanical source--> convert to heat
+                          double &dmechanicalSourcedT,
+                          STensor3 &dmechanicalSourceF,
+                    const bool stiff,
+                          STensor43* elasticTangent = NULL) const; 
+    
+        virtual materialLaw* clone() const{return new mlawNonLinearTVP(*this);};
+        virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+        #endif // SWIG
+};
+
+#endif //mlawNonLinearTVP
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/viscosityLaw.cpp b/NonLinearSolver/materialLaw/viscosityLaw.cpp
index f34afd719d5d5e8de5ec883217344e01a65bc28d..bc7aa3c5aafd3d89a3c65a48a8e177ed3a468348 100644
--- a/NonLinearSolver/materialLaw/viscosityLaw.cpp
+++ b/NonLinearSolver/materialLaw/viscosityLaw.cpp
@@ -22,33 +22,116 @@ viscosityLaw& viscosityLaw::operator = (const viscosityLaw& src){
 
 
 
+constantViscosityLaw::constantViscosityLaw(const int num, const double val, const bool init):viscosityLaw(num,init),_eta0(val){
+    _temFunc = new constantScalarFunction(1.);
+};
+
+constantViscosityLaw::constantViscosityLaw(const constantViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0){
+    _temFunc = NULL;
+    if (src._temFunc != NULL){
+        _temFunc = src._temFunc->clone();
+    }
+};
 
-constantViscosityLaw::constantViscosityLaw(const int num, const double val, const bool init):viscosityLaw(num,init),_eta0(val){};
-constantViscosityLaw::constantViscosityLaw(const constantViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0){};
 constantViscosityLaw& constantViscosityLaw::operator = (const viscosityLaw& src){
   viscosityLaw::operator=(src);
   const constantViscosityLaw* ps = dynamic_cast<const constantViscosityLaw*>(&src);
   if (ps != NULL){
     _eta0 = ps->_eta0;
+    
+  if (ps->_temFunc != NULL){
+      if (_temFunc != NULL){
+        _temFunc->operator=(*ps->_temFunc);
+      }
+      else{
+        _temFunc = ps->_temFunc->clone();
+      }
   }
+ }
   return *this;
 };
 
+constantViscosityLaw::~constantViscosityLaw(){
+  if (_temFunc != NULL) {delete _temFunc; _temFunc = NULL;};
+};
 
+void constantViscosityLaw::setTemperatureFunction(const scalarFunction& Tfunc){
+  if (_temFunc != NULL) delete _temFunc;
+  _temFunc = Tfunc.clone();
+}
 
+void constantViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT) const {
+    R = _eta0*_temFunc->getVal(T);
+    dR = 0.;
+    dRdT = _eta0*_temFunc->getDiff(T);    
+};
+
+void constantViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) const {
+    R = _eta0*_temFunc->getVal(T);
+    dR = 0.;
+    dRdT = _eta0*_temFunc->getDiff(T);    
+    ddRdTT = _eta0*_temFunc->getDoubleDiff(T);    
+};
 
 saturatePowerViscosityLaw::saturatePowerViscosityLaw(const int num, const double eta0, const double q, const bool init):
-                viscosityLaw(num,init), _eta0(eta0), _q(q){};
-saturatePowerViscosityLaw::saturatePowerViscosityLaw(const saturatePowerViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0),_q(src._q){};
+                viscosityLaw(num,init), _eta0(eta0), _q(q){
+                _temFunc_eta0 = new constantScalarFunction(1.);
+                _temFunc_q = new constantScalarFunction(1.);
+};
+
+saturatePowerViscosityLaw::saturatePowerViscosityLaw(const saturatePowerViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0),_q(src._q){
+    _temFunc_eta0 = NULL;
+    if (src._temFunc_eta0 != NULL){
+        _temFunc_eta0 = src._temFunc_eta0->clone();
+    }
+    _temFunc_q = NULL;
+    if (src._temFunc_q != NULL){
+        _temFunc_q = src._temFunc_q->clone();
+    }
+};
+
 saturatePowerViscosityLaw& saturatePowerViscosityLaw::operator = (const viscosityLaw& src){
   viscosityLaw::operator=(src);
   const saturatePowerViscosityLaw* ps = dynamic_cast<const saturatePowerViscosityLaw*>(&src);
   if (ps != NULL){
     _eta0 = ps->_eta0;
     _q = ps->_q;
+    
+  if (ps->_temFunc_eta0 != NULL){
+      if (_temFunc_eta0 != NULL){
+        _temFunc_eta0->operator=(*ps->_temFunc_eta0);
+      }
+      else{
+        _temFunc_eta0 = ps->_temFunc_eta0->clone();
+      }
+  }
+  if (ps->_temFunc_q != NULL){
+      if (_temFunc_q != NULL){
+        _temFunc_q->operator=(*ps->_temFunc_q);
+      }
+      else{
+        _temFunc_q = ps->_temFunc_q->clone();
+      }
+  }
   }
   return *this;
 };
+
+saturatePowerViscosityLaw::~saturatePowerViscosityLaw(){
+  if (_temFunc_eta0 != NULL) {delete _temFunc_eta0; _temFunc_eta0 = NULL;};
+  if (_temFunc_q != NULL) {delete _temFunc_q; _temFunc_q = NULL;};
+};
+
+void saturatePowerViscosityLaw::setTemperatureFunction_eta0(const scalarFunction& Tfunc){
+  if (_temFunc_eta0 != NULL) delete _temFunc_eta0;
+  _temFunc_eta0 = Tfunc.clone();
+}
+
+void saturatePowerViscosityLaw::setTemperatureFunction_q(const scalarFunction& Tfunc){
+  if (_temFunc_q != NULL) delete _temFunc_q;
+  _temFunc_q = Tfunc.clone();
+}
+
 void saturatePowerViscosityLaw::get(const double p, double& R, double& dR) const{
   R = _eta0 * pow(p,_q);
   if(p <1.e-6 and _q < 1.)
@@ -61,15 +144,81 @@ void saturatePowerViscosityLaw::get(const double p, double& R, double& dR) const
     R = _eta0 * pow(p,_q);
     dR = _eta0 * pow(p,_q-1.) * _q;
   }
+};
+
+void saturatePowerViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT) const{
+  
+  double eta = _eta0*_temFunc_eta0->getVal(T);
+  double DetaDT = _eta0*_temFunc_eta0->getDiff(T);
+  double q = _q*_temFunc_q->getVal(T);
+  double DqDT = _q*_temFunc_q->getDiff(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 *log(1.e-6) *pow(1.e-6,_q)*(p/1.e-6)*DqDT;
+  }
+  else
+  {
+    R = eta * pow(p,q);
+    dR = eta * pow(p,q-1.) * q;
+    dRdT = DetaDT * pow(p,q) + eta*log(p)*pow(p,_q)*DqDT;
+  }
   
 };
 
+void saturatePowerViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) 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);
+  }
+  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);
+  }
+  
+};
 
+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.);
+            _temFunc_eta1 = new constantScalarFunction(1.);
+            _temFunc_g0 = new constantScalarFunction(1.);
+};
 
+saturateSinhViscosityLaw::saturateSinhViscosityLaw(const saturateSinhViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0),_eta1(src._eta1),_g0(src._g0){
+    _temFunc_eta0 = NULL;
+    if (src._temFunc_eta0 != NULL){
+        _temFunc_eta0 = src._temFunc_eta0->clone();
+    }
+    _temFunc_eta1 = NULL;
+    if (src._temFunc_eta1 != NULL){
+        _temFunc_eta1 = src._temFunc_eta1->clone();
+    }
+    _temFunc_g0 = NULL;
+    if (src._temFunc_g0 != NULL){
+        _temFunc_g0 = src._temFunc_g0->clone();
+    }
+};
 
-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){};
-saturateSinhViscosityLaw::saturateSinhViscosityLaw(const saturateSinhViscosityLaw& src):viscosityLaw(src),_eta0(src._eta0),_eta1(src._eta1),_g0(src._g0){};
 saturateSinhViscosityLaw& saturateSinhViscosityLaw::operator = (const viscosityLaw& src){
   viscosityLaw::operator=(src);
   const saturateSinhViscosityLaw* ps = dynamic_cast<const saturateSinhViscosityLaw*>(&src);
@@ -77,9 +226,57 @@ saturateSinhViscosityLaw& saturateSinhViscosityLaw::operator = (const viscosityL
     _eta0 = ps->_eta0;
     _eta1 = ps->_eta1;
     _g0 = ps->_g0;
+    
+  if (ps->_temFunc_eta0 != NULL){
+      if (_temFunc_eta0 != NULL){
+        _temFunc_eta0->operator=(*ps->_temFunc_eta0);
+      }
+      else{
+        _temFunc_eta0 = ps->_temFunc_eta0->clone();
+      }
+  }
+  if (ps->_temFunc_eta1 != NULL){
+      if (_temFunc_eta1 != NULL){
+        _temFunc_eta1->operator=(*ps->_temFunc_eta1);
+      }
+      else{
+        _temFunc_eta1 = ps->_temFunc_eta1->clone();
+      }
+  }
+  if (ps->_temFunc_g0 != NULL){
+      if (_temFunc_g0 != NULL){
+        _temFunc_g0->operator=(*ps->_temFunc_g0);
+      }
+      else{
+        _temFunc_g0 = ps->_temFunc_g0->clone();
+      }
+  }
+    
   }
   return *this;
 };
+
+saturateSinhViscosityLaw::~saturateSinhViscosityLaw(){
+  if (_temFunc_eta0 != NULL) {delete _temFunc_eta0; _temFunc_eta0 = NULL;};
+  if (_temFunc_g0 != NULL) {delete _temFunc_g0; _temFunc_g0 = NULL;};
+  if (_temFunc_eta1 != NULL) {delete _temFunc_eta1; _temFunc_eta1 = NULL;};
+};
+
+void saturateSinhViscosityLaw::setTemperatureFunction_eta0(const scalarFunction& Tfunc){
+  if (_temFunc_eta0 != NULL) delete _temFunc_eta0;
+  _temFunc_eta0 = Tfunc.clone();
+}
+
+void saturateSinhViscosityLaw::setTemperatureFunction_g0(const scalarFunction& Tfunc){
+  if (_temFunc_g0 != NULL) delete _temFunc_g0;
+  _temFunc_g0 = Tfunc.clone();
+}
+
+void saturateSinhViscosityLaw::setTemperatureFunction_eta1(const scalarFunction& Tfunc){
+  if (_temFunc_eta1 != NULL) delete _temFunc_eta1;
+  _temFunc_eta1 = Tfunc.clone();
+}
+
 void saturateSinhViscosityLaw::get(const double p, double& R, double& dR) const{
   double pa = p/_g0;
   if (pa< 1e-6){
@@ -92,3 +289,33 @@ void saturateSinhViscosityLaw::get(const double p, double& R, double& dR) const{
     dR = (_eta0-_eta1)*(1./sinh(pa) - (pa*cosh(pa))/(sinh(pa)*sinh(pa)))/_g0 ;
   }
 };
+void saturateSinhViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT) const{
+  double pa = p/_g0;
+  if (pa< 1e-6){
+    R = _eta0;
+    dR = 0.;
+    dRdT = 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
+  }
+};
+void saturateSinhViscosityLaw::get(const double p, const double T, double& R, double& dR, double& dRdT, double& ddRdTT) 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
+  }
+  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
+  }
+};
\ No newline at end of file
diff --git a/NonLinearSolver/materialLaw/viscosityLaw.h b/NonLinearSolver/materialLaw/viscosityLaw.h
index c3cb0eba5c124e89174e45d188cc16fc29d61231..3ba88cc9eba7795565a0bb721ad9492c0d1bfc59 100644
--- a/NonLinearSolver/materialLaw/viscosityLaw.h
+++ b/NonLinearSolver/materialLaw/viscosityLaw.h
@@ -11,12 +11,13 @@
 #define VISCOSITYLAW_H_
 
 #include <cstddef>
-
+#include "scalarFunction.h"
 
 class viscosityLaw {
   protected:
     int _num;
     bool _initialized;
+    
 
   #ifndef SWIG
   public:
@@ -26,6 +27,8 @@ class viscosityLaw {
     virtual  ~viscosityLaw(){};
     virtual int getNum() const {return _num;};
     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 viscosityLaw* clone() const = 0;
   #endif // SWIG
 };
@@ -33,14 +36,18 @@ class viscosityLaw {
 class constantViscosityLaw : public viscosityLaw{
   protected:
     double _eta0;
+    scalarFunction* _temFunc;
 
   public:
     constantViscosityLaw(const int num, const double val, const bool init = true);
+    void setTemperatureFunction(const scalarFunction& Tfunc);
     #ifndef SWIG
     constantViscosityLaw(const constantViscosityLaw& src);
     virtual constantViscosityLaw& operator = (const viscosityLaw& src);
-    virtual ~constantViscosityLaw(){};
+    virtual ~constantViscosityLaw();
     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 viscosityLaw* clone() const {return new constantViscosityLaw(*this);};
     #endif // SWIG
 };
@@ -49,14 +56,20 @@ class saturatePowerViscosityLaw : public viscosityLaw{
   protected:
     double _eta0;
     double _q;
+    scalarFunction* _temFunc_eta0;
+    scalarFunction* _temFunc_q;
 
   public:
     saturatePowerViscosityLaw(const int num, const double eta0, const double q, const bool init = true);
+    void setTemperatureFunction_eta0(const scalarFunction& Tfunc);
+    void setTemperatureFunction_q(const scalarFunction& Tfunc);
     #ifndef SWIG
     saturatePowerViscosityLaw(const saturatePowerViscosityLaw& src);
     virtual saturatePowerViscosityLaw& operator = (const viscosityLaw& src);
-    virtual ~saturatePowerViscosityLaw(){};
+    virtual ~saturatePowerViscosityLaw();
     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 viscosityLaw* clone() const {return new saturatePowerViscosityLaw(*this);};
     #endif // SWIG
 };
@@ -68,14 +81,22 @@ class saturateSinhViscosityLaw : public viscosityLaw{
   protected:
     double _eta0, _eta1;
     double _g0;
+    scalarFunction* _temFunc_eta0;
+    scalarFunction* _temFunc_g0;
+    scalarFunction* _temFunc_eta1;
 
   public:
     saturateSinhViscosityLaw(const int num, const double eta0, const double eta1, const double g0, const bool init = true);
+    void setTemperatureFunction_eta0(const scalarFunction& Tfunc);
+    void setTemperatureFunction_eta1(const scalarFunction& Tfunc);
+    void setTemperatureFunction_g0(const scalarFunction& Tfunc);
     #ifndef SWIG
     saturateSinhViscosityLaw(const saturateSinhViscosityLaw& src);
     virtual saturateSinhViscosityLaw& operator = (const viscosityLaw& src);
-    virtual ~saturateSinhViscosityLaw(){};
+    virtual ~saturateSinhViscosityLaw();
     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 viscosityLaw* clone() const {return new saturateSinhViscosityLaw(*this);};
     #endif // SWIG
 };
diff --git a/NonLinearSolver/nlsolver/scalarFunction.h b/NonLinearSolver/nlsolver/scalarFunction.h
index 5b12f82aee8ec1d344a1acd660c7d7c9a772208a..94ee94541c0d4f5afee402805e59385f04056510 100644
--- a/NonLinearSolver/nlsolver/scalarFunction.h
+++ b/NonLinearSolver/nlsolver/scalarFunction.h
@@ -26,6 +26,12 @@ class scalarFunction{
   virtual void setElement(MElement* el) const{}
   virtual double getVal(const double x) const = 0; // function value at x
   virtual double getDiff(const double x) const = 0; // function derivative at x
+  virtual double getDoubleDiff(const double x) const = 0; // function double derivative at x
+  /*
+  {
+      Msg::Error("scalarFunction getDoubleDiff not implemented in generic form");
+  }
+  */
   virtual double getVal(const std::vector<double>& input) const {return getVal(input[0]);};
   virtual int getInputDimension() const {return 1;};
   virtual void getDiff(const std::vector<double>& input, std::vector<double>& grad) const{
@@ -57,6 +63,7 @@ class constantScalarFunction : public scalarFunction{
     virtual ~constantScalarFunction(){};
     virtual double getVal(const double x) const {return _f;};
     virtual double getDiff(const double x) const {return 0.;};
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new constantScalarFunction(*this);};
     #endif // SWIG
 };
@@ -93,6 +100,10 @@ class elementWiseScalarFunction : public constantScalarFunction{
       Msg::Error("elementWiseScalarFunction::getDiff should not be used");
       return 0.;
     };
+    virtual double getDoubleDiff(const double x) const {      
+      Msg::Error("elementWiseScalarFunction::getDoubleDiff should not be used");
+      return 0.;
+    };
     virtual scalarFunction* clone() const {return new elementWiseScalarFunction(*this);};
     #endif //SWIG
 };
@@ -123,6 +134,7 @@ class twoValuesFunction : public scalarFunction{
       else return _A1;
     };
     virtual double getDiff(const double x) const {return 0.;};
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new twoValuesFunction(*this);};
     #endif // SWIG
 };
@@ -149,10 +161,73 @@ class linearScalarFunction : public scalarFunction{
     virtual ~linearScalarFunction(){};
     virtual double getVal(const double x) const {return _a*(x-_x0)+_f0;};
     virtual double getDiff(const double x) const {return _a;};
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new linearScalarFunction(*this);};
     #endif // SWIG
 };
 
+
+// FLE 
+class GlassTransitionScalarFunction : public scalarFunction{
+    protected:
+        double _PU, _PR, _Tg, _k, _m;
+        int _c;  // c for choice ___=D____
+                // P_gibson(T) = 0.5*(P_U + P_R) - 0.5*(P_U - P_R).*tanh(k_prime*(T-Tg))-_m*(T-_Tg);
+                // P_huang(T) = P_U - (P_U - P_R)./( ( m.*exp(-m*k*(T-Tg)) + 1 ) ).^(1/m);
+    public:
+        GlassTransitionScalarFunction(const double PU, const double PR, const double Tg, const double k, const double m, const int c) : scalarFunction(),_PU(PU), _PR(PR), _Tg(Tg), _k(k), _m(m), _c(c){}
+        
+        #ifndef SWIG
+        GlassTransitionScalarFunction(const GlassTransitionScalarFunction& src): scalarFunction(src), _PU(src._PU), _PR(src._PR), _Tg(src._Tg), _k(src._k), _m(src._m), _c(src._c){}
+        virtual GlassTransitionScalarFunction& operator =(const scalarFunction& src){
+            scalarFunction::operator=(src);
+            const GlassTransitionScalarFunction* psrc = dynamic_cast<const GlassTransitionScalarFunction*>(&src);
+            if (psrc!= NULL){
+                _PU = psrc->_PU;
+                _PR = psrc->_PR;
+                _Tg = psrc->_Tg;
+                _k = psrc->_k;
+                _m = psrc->_m;
+                _c = psrc->_c;
+            }
+            return *this;
+        }
+        
+        virtual ~GlassTransitionScalarFunction(){};
+        
+        // This normalisation needs to be fixed.
+        virtual double getVal(const double T) const {
+            if (_c == 0) {         // Gibson et al
+                return (0.5*(_PU+_PR)-0.5*(_PU-_PR)*tanh(_k*(T-_Tg))-_m*(T-_Tg))/_PU;
+            }
+            else {       // _c == 1   Huang et al
+                return (_PU-(_PU-_PR)/(pow((_m*exp(-_m*_k*(T-_Tg))+1),(1/_m))))/_PU;
+            }
+        }; 
+        virtual double getDiff(const double T) const {
+            if (_c == 0) {         // Gibson et al
+                // return ( 0.5*_k*(_PR-_PU)*(1-pow(tanh(_k*(T-_Tg)),2))-_m)/_PU;
+                return 0.5*_k*(_PR-_PU)*pow( 1/cosh(_k*(T-_Tg)) ,2);
+            }
+            else {       // _c == 1   Huang et al
+                // return (-(_PU-_PR)*(pow(_m,2.0)*_k*exp(-_m*_k*(T-_Tg)))/( _m* ( pow( (_m*exp(-_m*_k*(T-_Tg))+1),(1+1/_m) ) ) ))/_PU;
+                return _m*_k*(_PR-_PU)*exp(-_m*_k*(T-_Tg) )* pow( (_m*exp(-_m*_k*(T-_Tg) ) +1 ), (-(1+_m)/_m) );
+            }
+        };
+        virtual double getDoubleDiff(const double T) const {
+            if (_c == 0) {         // Gibson et al
+                return  pow(_k,2)*(_PU-_PR)*tanh(_k*(T-_Tg))* pow(1/cosh(_k*(T-_Tg)),2);
+            }
+            else {       // _c == 1   Huang et al
+                return ( pow(_k*_m,2)*(_PU-_PR)* (exp(_k*_m*(T-_Tg))-1)*pow( _m*exp(_k*_m*(_Tg-T)) + 1, -1/_m) )/ (pow(  exp(_k*_m*(T-_Tg))+_m ,2)) ;
+            }
+        };
+            
+        virtual scalarFunction* clone() const {return new GlassTransitionScalarFunction(*this);};      
+        #endif // SWIG
+    };
+
+
 class piecewiseScalarFunction : public scalarFunction{
 protected:
     std::vector<double> _var;
@@ -206,6 +281,7 @@ protected:
       }
       return 0.;
     };
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new piecewiseScalarFunction(*this);};
     #endif // SWIG
 };
@@ -267,6 +343,7 @@ class twoVariableExponentialSaturationScalarFunction : public scalarFunction{
         }
       }
     };
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new twoVariableExponentialSaturationScalarFunction(*this);};
     #endif //SWIG
 };
@@ -344,7 +421,8 @@ protected:
         return 1.;
       }
     };
-
+    virtual double getDoubleDiff(const double x) const {return 0.;};
+    
     virtual scalarFunction* clone() const {return new fourVariableExponentialSaturationScalarFunction(*this);};
     #endif //SWIG
 };
@@ -392,6 +470,7 @@ class polynomialScalarFunction : public scalarFunction{
       else Msg::Error("polynomialScalarFunction with order %d has not been implemented",_order);
 			return 0.;
     };
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new polynomialScalarFunction(*this);};
     #endif //SWIG
 };
@@ -417,6 +496,7 @@ class asinwt : public scalarFunction{
     virtual ~asinwt(){};
     virtual double getVal(const double x) const {return _a*sin(_omega*x);};
     virtual double getDiff(const double x) const {return _a*_omega*cos(_omega*x);};
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new asinwt(*this);};
     #endif // SWIG
 };
@@ -454,9 +534,47 @@ class aexpMinusXpoweredByn : public scalarFunction
       double DprDx = _n*0.5*pow(r,_n-1.)*DrDx;
       return -DprDx*_a*exp(-pr);
     };
+    virtual double getDoubleDiff(const double x) const {return 0.;};
     virtual scalarFunction* clone() const {return new aexpMinusXpoweredByn(*this);};
     #endif // SWIG
 };
 
+// function y = exp(- (_C1*(T - _Tref)) / (_C2 + T - _Tref) ) 
+// NOTE: this is not normalized
+class negExpWLFshiftFactor : public scalarFunction
+{
+  protected:
+    double _C1, _C2, _Tref;
+    
+  public:
+    negExpWLFshiftFactor(double C1, double C2, double Tref) : scalarFunction(),_C1(C1),_C2(C2),_Tref(Tref){}
+    #ifndef SWIG
+    negExpWLFshiftFactor(const negExpWLFshiftFactor& src) : _C1(src._C1),_C2(src._C2),_Tref(src._Tref){}
+    virtual negExpWLFshiftFactor& operator = (const scalarFunction& src){
+      scalarFunction::operator=(src);
+      const negExpWLFshiftFactor* psrc = dynamic_cast<const negExpWLFshiftFactor*>(&src);
+      if (psrc!= NULL){
+        _C1 = psrc->_C1;
+        _C2 = psrc->_C2;
+        _Tref = psrc->_Tref;
+      }
+      return *this;
+    }
+    virtual ~negExpWLFshiftFactor(){};
+    virtual double getVal(const double x) const {
+      return exp(-(_C1*(x - _Tref)) / (_C2 + x - _Tref));
+    };
+    virtual double getDiff(const double x) const {
+      return (this->getVal(x))*(-_C1*_C2)/pow( (_C2 + x-_Tref) ,2);
+    };
+    virtual double getDoubleDiff(const double x) const {
+      return (this->getVal(x)) * (_C1*_C2) * (_C1*_C2 - 2*(_C2+ x-_Tref)) / pow( (_C2 + x-_Tref) ,4);
+    };
+    virtual scalarFunction* clone() const {return new negExpWLFshiftFactor(*this);};
+    #endif // SWIG
+};
+
+
+
 #endif // SCALARFUNCTION_H_
 
diff --git a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
index 2e237130ebf15ef23202e7ada635686870ae4303..9a8bc1dc45c872a38533384af4f7a30afcfa80a9 100644
--- a/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
+++ b/dG3D/benchmarks/powerYieldViscoElastoPlastic/cylinder.py
@@ -1,8 +1,7 @@
 #coding-Utf-8-*-
 
 from gmshpy import *
-from dG3Dpy import*
-
+# from dG3Dpy import*
 from math import*
 
 #script to launch PBC problem with a python script
@@ -22,7 +21,7 @@ hc = 300.
 sy0t = sy0c*0.78
 ht = 300.
 
-    
+
 # creation of law
 hardenc = LinearExponentialJ2IsotropicHardening(1, sy0c, hc, 0., 10.)
 hardent = LinearExponentialJ2IsotropicHardening(2, sy0t, ht, 0., 10.)
diff --git a/dG3D/benchmarks/test1DUniaxialStress/line.msh b/dG3D/benchmarks/test1DUniaxialStress/line.msh
deleted file mode 100644
index d7f8f3a190e2c8a6c874d2b5ed1101296e383e68..0000000000000000000000000000000000000000
--- a/dG3D/benchmarks/test1DUniaxialStress/line.msh
+++ /dev/null
@@ -1,212 +0,0 @@
-$MeshFormat
-2.2 0 8
-$EndMeshFormat
-$Nodes
-101
-1 0 0 0
-2 5 0 0
-3 0.008233330448046892 0 0
-4 0.01671366073030414 0 0
-5 0.02544840063616353 0 0
-6 0.0344451821142551 0 0
-7 0.04371186713335751 0 0
-8 0.05325655264591833 0 0
-9 0.06308757804567544 0 0
-10 0.07321353429759644 0 0
-11 0.08364327016126007 0 0
-12 0.09438589772837597 0 0
-13 0.1054508038341165 0 0
-14 0.116847657847122 0 0
-15 0.1285864174104397 0 0
-16 0.1406773392804196 0 0
-17 0.1531309884214111 0 0
-18 0.1659582477122095 0 0
-19 0.1791703248554747 0 0
-20 0.1927787641551272 0 0
-21 0.2067954569082466 0 0
-22 0.2212326499824571 0 0
-23 0.2361029584353169 0 0
-24 0.2514193765698796 0 0
-25 0.2671952874553593 0 0
-26 0.2834444752151047 0 0
-27 0.3001811381713936 0 0
-28 0.31741990151803 0 0
-29 0.3351758286477699 0 0
-30 0.3534644330434303 0 0
-31 0.372301695495865 0 0
-32 0.3917040756117358 0 0
-33 0.4116885272296583 0 0
-34 0.432272512798794 0 0
-35 0.4534740172083889 0 0
-36 0.4753115671982825 0 0
-37 0.4978042439575176 0 0
-38 0.520971700931929 0 0
-39 0.5448341817706615 0 0
-40 0.5694125369005317 0 0
-41 0.5947282424023436 0 0
-42 0.6208034187749437 0 0
-43 0.6476608509325344 0 0
-44 0.6753240059882035 0 0
-45 0.7038170554800255 0 0
-46 0.7331648967852645 0 0
-47 0.7633931734527039 0 0
-48 0.7945282980073765 0 0
-49 0.8265974760555226 0 0
-50 0.8596287296792313 0 0
-51 0.8936509210234185 0 0
-52 0.9286937785359755 0 0
-53 0.9647879213936159 0 0
-54 1.001964887620402 0 0
-55 1.040257162862379 0 0
-56 1.079698207465576 0 0
-57 1.120322483942211 0 0
-58 1.162165487739258 0 0
-59 1.205263781406641 0 0
-60 1.249655024654076 0 0
-61 1.295378004791349 0 0
-62 1.342472673657588 0 0
-63 1.39098018338702 0 0
-64 1.440942918706007 0 0
-65 1.492404535631868 0 0
-66 1.545410001557268 0 0
-67 1.600005632041137 0 0
-68 1.656239130588693 0 0
-69 1.714159633125633 0 0
-70 1.773817751330627 0 0
-71 1.835265613048903 0 0
-72 1.898556910216334 0 0
-73 1.96374694661764 0 0
-74 2.030892683771098 0 0
-75 2.100052793161879 0 0
-76 2.171287705953465 0 0
-77 2.244659665685397 0 0
-78 2.320232784225052 0 0
-79 2.398073096583552 0 0
-80 2.478248619015515 0 0
-81 2.560829407381226 0 0
-82 2.645887618903809 0 0
-83 2.733497576706765 0 0
-84 2.823735833604651 0 0
-85 2.916681238749485 0 0
-86 3.012415006011735 0 0
-87 3.111020785442104 0 0
-88 3.212584737870448 0 0
-89 3.31719560959661 0 0
-90 3.424944807044433 0 0
-91 3.535926480453506 0 0
-92 3.650237604904716 0 0
-93 3.76797806264756 0 0
-94 3.889250734011282 0 0
-95 4.014161585860751 0 0
-96 4.142819763141486 0 0
-97 4.27533768492177 0 0
-98 4.411831143951246 0 0
-99 4.552419407792404 0 0
-100 4.69722531932773 0 0
-101 4.846375407792818 0 0
-$EndNodes
-$Elements
-102
-1 15 2 1 1 1
-2 15 2 2 2 2
-3 1 2 11 1 1 3
-4 1 2 11 1 3 4
-5 1 2 11 1 4 5
-6 1 2 11 1 5 6
-7 1 2 11 1 6 7
-8 1 2 11 1 7 8
-9 1 2 11 1 8 9
-10 1 2 11 1 9 10
-11 1 2 11 1 10 11
-12 1 2 11 1 11 12
-13 1 2 11 1 12 13
-14 1 2 11 1 13 14
-15 1 2 11 1 14 15
-16 1 2 11 1 15 16
-17 1 2 11 1 16 17
-18 1 2 11 1 17 18
-19 1 2 11 1 18 19
-20 1 2 11 1 19 20
-21 1 2 11 1 20 21
-22 1 2 11 1 21 22
-23 1 2 11 1 22 23
-24 1 2 11 1 23 24
-25 1 2 11 1 24 25
-26 1 2 11 1 25 26
-27 1 2 11 1 26 27
-28 1 2 11 1 27 28
-29 1 2 11 1 28 29
-30 1 2 11 1 29 30
-31 1 2 11 1 30 31
-32 1 2 11 1 31 32
-33 1 2 11 1 32 33
-34 1 2 11 1 33 34
-35 1 2 11 1 34 35
-36 1 2 11 1 35 36
-37 1 2 11 1 36 37
-38 1 2 11 1 37 38
-39 1 2 11 1 38 39
-40 1 2 11 1 39 40
-41 1 2 11 1 40 41
-42 1 2 11 1 41 42
-43 1 2 11 1 42 43
-44 1 2 11 1 43 44
-45 1 2 11 1 44 45
-46 1 2 11 1 45 46
-47 1 2 11 1 46 47
-48 1 2 11 1 47 48
-49 1 2 11 1 48 49
-50 1 2 11 1 49 50
-51 1 2 11 1 50 51
-52 1 2 11 1 51 52
-53 1 2 11 1 52 53
-54 1 2 11 1 53 54
-55 1 2 11 1 54 55
-56 1 2 11 1 55 56
-57 1 2 11 1 56 57
-58 1 2 11 1 57 58
-59 1 2 11 1 58 59
-60 1 2 11 1 59 60
-61 1 2 11 1 60 61
-62 1 2 11 1 61 62
-63 1 2 11 1 62 63
-64 1 2 11 1 63 64
-65 1 2 11 1 64 65
-66 1 2 11 1 65 66
-67 1 2 11 1 66 67
-68 1 2 11 1 67 68
-69 1 2 11 1 68 69
-70 1 2 11 1 69 70
-71 1 2 11 1 70 71
-72 1 2 11 1 71 72
-73 1 2 11 1 72 73
-74 1 2 11 1 73 74
-75 1 2 11 1 74 75
-76 1 2 11 1 75 76
-77 1 2 11 1 76 77
-78 1 2 11 1 77 78
-79 1 2 11 1 78 79
-80 1 2 11 1 79 80
-81 1 2 11 1 80 81
-82 1 2 11 1 81 82
-83 1 2 11 1 82 83
-84 1 2 11 1 83 84
-85 1 2 11 1 84 85
-86 1 2 11 1 85 86
-87 1 2 11 1 86 87
-88 1 2 11 1 87 88
-89 1 2 11 1 88 89
-90 1 2 11 1 89 90
-91 1 2 11 1 90 91
-92 1 2 11 1 91 92
-93 1 2 11 1 92 93
-94 1 2 11 1 93 94
-95 1 2 11 1 94 95
-96 1 2 11 1 95 96
-97 1 2 11 1 96 97
-98 1 2 11 1 97 98
-99 1 2 11 1 98 99
-100 1 2 11 1 99 100
-101 1 2 11 1 100 101
-102 1 2 11 1 101 2
-$EndElements
diff --git a/dG3D/src/dG3D1DDomain.cpp b/dG3D/src/dG3D1DDomain.cpp
index f6c72ba8e3f05b17f4c381bfcc8927796d4280eb..84196578e32c41beabefbd83e95149696e2d5ac5 100644
--- a/dG3D/src/dG3D1DDomain.cpp
+++ b/dG3D/src/dG3D1DDomain.cpp
@@ -64,12 +64,16 @@ void dG3D1DDomain::setStressTriaxiality(const double T){
 };
 
 
-dG3D1DDomain::dG3D1DDomain(const int tag, const int phys, const int sp_, const int lnum, const int fdg, int numNL) : dG3DDomain(tag,phys,sp_,lnum,fdg,1,numNL),
+dG3D1DDomain::dG3D1DDomain(const int tag, const int phys, const int sp_, const int lnum, const int fdg, int numNL, int numExtraDOF) : dG3DDomain(tag,phys,sp_,lnum,fdg,1,numNL,numExtraDOF),
 _state(UniaxialStrain), _T(0.){
   _crossSectionDistribution = new constantScalarFunction(1.);
   #if _DEBUG
   Msg::Warning("1D must be defined in x-coordinate only");
   #endif //
+
+  if( getNumConstitutiveExtraDofDiffusionVariable() >0){
+        setConstitutiveExtraDofDiffusionEqRatio(_ThermoMechanicsEqRatio);
+    }
 };
 
 
@@ -124,7 +128,7 @@ void dG3D1DDomain::createTerms(unknownField *uf,IPField*ip)
   {
     withPF = this->getMacroSolver()->withPathFollowing();
   }
-  
+
   if (withPF){
     if (getMacroSolver()->getPathFollowingLocation() == pathFollowingManager::INTERFACE){
       scalarTermPF = new nonLinearScalarTermVoid();
@@ -167,7 +171,7 @@ void dG3D1DDomain::createTerms(unknownField *uf,IPField*ip)
   {
     withPF = getMacroSolver()->withPathFollowing();
   }
-  
+
   if (withPF){
     if (getMacroSolver()->getPathFollowingLocation() == pathFollowingManager::INTERFACE){
       scalarTermPF = new nonLinearScalarTermVoid();
diff --git a/dG3D/src/dG3D1DDomain.h b/dG3D/src/dG3D1DDomain.h
index 6be47fc70e36b7e65df26135ba52942db563f758..ab5836607e4ac456988e20922de7043bb2715518 100644
--- a/dG3D/src/dG3D1DDomain.h
+++ b/dG3D/src/dG3D1DDomain.h
@@ -22,13 +22,24 @@ class dG3D1DDomain : public dG3DDomain{
     scalarFunction* _crossSectionDistribution;
     State _state;
     double _T; // stress triaxiality
+    double _ThermoMechanicsEqRatio;
     #endif //SWIG
   public:
-    dG3D1DDomain(const int tag, const int phys, const int sp_, const int lnum, const int fdg, int numNL=0);
+    dG3D1DDomain(const int tag, const int phys, const int sp_, const int lnum, const int fdg, int numNL=0, int numExtraDOF=0);
     void setCrossSectionDistribution(const scalarFunction* fct);
     void setCrossSection(const double val);
     void setState(const int s);
     void setStressTriaxiality(const double T);
+
+    virtual void ThermoMechanicsStabilityParameters(const double b2=10., bool continuity=true)
+    {
+        setConstitutiveExtraDofDiffusionStabilityParameters(b2,continuity);
+    }
+    void setThermoMechanicsEqRatio(const double ThermoMechanicsEqRatio){_ThermoMechanicsEqRatio = ThermoMechanicsEqRatio;}
+    virtual double getThermoMechanicsStabilityParameter() const { return getConstitutiveExtraDofDiffusionStabilityParameter(); }
+    virtual bool   getThermoMechanicsContinuity() const { return getConstitutiveExtraDofDiffusionContinuity();}
+    virtual double getThermoMechanicsEqRatio() const { return getConstitutiveExtraDofDiffusionEqRatio();}
+
     #ifndef SWIG
     dG3D1DDomain(const dG3D1DDomain& src);
     virtual ~dG3D1DDomain();
diff --git a/dG3D/src/dG3DIPVariable.cpp b/dG3D/src/dG3DIPVariable.cpp
index 8506d1f64664d85138888fafc4714251f6bf931f..0eb550cf7ffa2c71c697315d8dd003095ce25680 100644
--- a/dG3D/src/dG3DIPVariable.cpp
+++ b/dG3D/src/dG3DIPVariable.cpp
@@ -109,11 +109,11 @@ void nonlocalData::restart(){
 
 };
 //
-bodyForceForHO::bodyForceForHO() 
+bodyForceForHO::bodyForceForHO()
 {
   STensorOperation::unity(dFmdFM);
 };
-bodyForceForHO::bodyForceForHO(const bodyForceForHO& src):  GM(src.GM), dFmdFM(src.dFmdFM),  dFmdGM(src.dFmdGM), Bm(src.Bm), dBmdFm(src.dBmdFm), dBmdGM(src.dBmdGM), dCmdFm(src.dCmdFm), dPmdFM(src.dPmdFM) 
+bodyForceForHO::bodyForceForHO(const bodyForceForHO& src):  GM(src.GM), dFmdFM(src.dFmdFM),  dFmdGM(src.dFmdGM), Bm(src.Bm), dBmdFm(src.dBmdFm), dBmdGM(src.dBmdGM), dCmdFm(src.dCmdFm), dPmdFM(src.dPmdFM)
 {
 
 };
@@ -711,7 +711,7 @@ double dG3DIPVariable::getJ(int dim) const
   else if(dim==2)
     return F(0,0)*F(1,1)-F(0,1)*F(1,0);
   else
-    return F(0,0);  
+    return F(0,0);
 }
 
 void dG3DIPVariable::getCauchyStress(STensor3 &cauchy) const
@@ -1100,422 +1100,422 @@ double dG3DIPVariable::get(const int comp) const
   else if (comp == IPField::BODYFORCE_X){
     if(hasBodyForceForHO())
       return _bodyForceForHO->Bm(0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::BODYFORCE_Y){
     if(hasBodyForceForHO())
       return _bodyForceForHO->Bm(1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::BODYFORCE_Z){
     if(hasBodyForceForHO())
       return _bodyForceForHO->Bm(2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_XXXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_XXZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XXZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,0,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_XYZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XYZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,1,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_XZZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_XZZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(0,2,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_YXZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YXZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,0,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_YYZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YYZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,1,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_YZZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_YZZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(1,2,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_ZXZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZXZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,0,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_ZYZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZYZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,1,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZXX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,0,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZXY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,0,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZXZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,0,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZYX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,1,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZYY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,1,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZYZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,1,2);
-    else  return 0.0;  
-  }  
+    else  return 0.0;
+  }
   else if (comp == IPField::dFmdFM_ZZZX){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,2,0);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZZY){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,2,1);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else if (comp == IPField::dFmdFM_ZZZZ){
     if(hasBodyForceForHO())
       return _bodyForceForHO->dFmdFM(2,2,2,2);
-    else  return 0.0;  
+    else  return 0.0;
   }
   else
      return 0.;
@@ -1576,8 +1576,8 @@ void dG3DIPVariable::computeBodyForce(const STensor33& G, SVector3& B) const{
           B(i) -= 0.5*(tmp1(i,j,k)+tmp2(i,j,k))*I(k,j);
         }
       }
-    } 
-} 
+    }
+}
 
 
 void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliType){
@@ -1590,7 +1590,7 @@ void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliT
    static const STensor3 I(1.);
    static STensor33 tmp1;
    static STensor33 tmp2;
-   
+
    if(ModuliType == partDomain::Homogeneous){
      STensorOperation::multSTensor43STensor33(K, _bodyForceForHO->GM, tmp1);
      STensorOperation::multSTensor43STensor33RightTranspose(K, _bodyForceForHO->GM, tmp2);
@@ -1608,10 +1608,10 @@ void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliT
              for (int p=0; p<3; p++){
               _bodyForceForHO->dBmdGM(i,j,k,l) -= 0.5*(K(i,p,j,k)*I(l,p) + K(i,p,j,l)*I(k,p));
             }
-          }  
+          }
         }
       }
-     }   
+     }
    }
    else{
      STensorOperation::multSTensor43(K, _bodyForceForHO->dFmdFM, _bodyForceForHO->dPmdFM);
@@ -1624,8 +1624,8 @@ void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliT
           _bodyForceForHO->Bm(i) -= 0.5*(tmp1(i,j,k)+tmp2(i,j,k))*I(k,j);
         }
       }
-     }    
-     
+     }
+
      for (int i=0; i<3; i++){
        for (int j=0; j<3; j++){
          for (int k=0; k<3; k++){
@@ -1633,7 +1633,7 @@ void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliT
              for (int p=0; p<3; p++){
               _bodyForceForHO->dBmdGM(i,j,k,l) -= 0.5*(_bodyForceForHO->dPmdFM(i,p,j,k)*I(l,p)+_bodyForceForHO->dPmdFM(i,p,j,l)*I(k,p));
             }
-          }  
+          }
         }
       }
      }
@@ -1645,21 +1645,21 @@ void dG3DIPVariable::setValueForBodyForce(const STensor43& K, const int _ModuliT
            for (int k=0; k<3; k++){
              for (int l=0; l<3; l++){
                 for (int p=0; p<3; p++){
-                  for (int q=0; q<3; q++){                    
-                      _bodyForceForHO->dBmdFm(i,p,q) -= _bodyForceForHO->dCmdFm(i,j,k,l,p,q)*(tmp1(k,l,j)+tmp2(k,l,j))/2.0;  
+                  for (int q=0; q<3; q++){
+                      _bodyForceForHO->dBmdFm(i,p,q) -= _bodyForceForHO->dCmdFm(i,j,k,l,p,q)*(tmp1(k,l,j)+tmp2(k,l,j))/2.0;
                   }
                 }
-             }    
+             }
            }
          }
-       } 
+       }
      }
-   }      
+   }
   }
   else{
   Msg::Error("Body Force is not defined");
   }
- } 
+ }
 
 void dG3DIPVariable::restart()
 {
@@ -1810,7 +1810,7 @@ double ANNBasedDG3DIPVariable::get(const int comp) const
 }
 
 
-torchANNBasedDG3DIPVariable::torchANNBasedDG3DIPVariable(const int n, const bool createBodyForceHO, const bool oninter): 
+torchANNBasedDG3DIPVariable::torchANNBasedDG3DIPVariable(const int n, const bool createBodyForceHO, const bool oninter):
                  dG3DIPVariable(createBodyForceHO, oninter), _n(n),restart_internalVars(1,n), _kinematicVariables(1,6)
 {
 #if defined(HAVE_TORCH)
@@ -2648,7 +2648,7 @@ VEVPMFHDG3DIPVariable& VEVPMFHDG3DIPVariable::operator=(const IPVariable &source
   /*if(src != NULL)
     _tiipv.operator=(*dynamic_cast<const IPVariable*>(&( src->_tiipv)));
   return *this;*/
-  
+
   if(src != NULL){
     if (src->_VEVPipv){
       if (_VEVPipv){
@@ -2983,8 +2983,8 @@ void TransverseIsoUserDirectionDG3DIPVariable::restart()
 
 
 TransverseIsoCurvatureDG3DIPVariable::TransverseIsoCurvatureDG3DIPVariable(const SVector3 &GaussP, const SVector3 &Centroid,
-                                          const SVector3 &PointStrart1, const SVector3 &PointStrart2, const double init_Angle, 
-                                          bool createBodyForceHO, const bool oninter) :dG3DIPVariable(createBodyForceHO, oninter), 
+                                          const SVector3 &PointStrart1, const SVector3 &PointStrart2, const double init_Angle,
+                                          bool createBodyForceHO, const bool oninter) :dG3DIPVariable(createBodyForceHO, oninter),
                                           _tiipv(GaussP, Centroid, PointStrart1, PointStrart2, init_Angle)
 {
 
@@ -3153,7 +3153,7 @@ AnisotropicStochDG3DIPVariable::AnisotropicStochDG3DIPVariable(const SVector3 &G
                                  const fullMatrix<double> &EyMat, const fullMatrix<double> &EzMat, const fullMatrix<double> &VxyMat,
                                  const fullMatrix<double> &VxzMat, const fullMatrix<double> &VyzMat, const fullMatrix<double> &MUxyMat,
                                  const fullMatrix<double> &MUxzMat, const fullMatrix<double> &MUyzMat, const double dx, const double dy,
-                                 const double OrigX, const double OrigY, const int intpl, const bool createBodyForceHO, const bool oninter) : 
+                                 const double OrigX, const double OrigY, const int intpl, const bool createBodyForceHO, const bool oninter) :
                                  dG3DIPVariable(createBodyForceHO, oninter), _tiipv(GaussP, ExMat,
                                  EyMat, EzMat, VxyMat, VxzMat, VyzMat, MUxyMat, MUxzMat, MUyzMat, dx, dy, OrigX, OrigY, intpl) {}
 
@@ -3221,7 +3221,7 @@ TFADG3DIPVariable& TFADG3DIPVariable::operator=(const IPVariable &source)
 }
 
 
-double TFADG3DIPVariable::get(const int i) const 
+double TFADG3DIPVariable::get(const int i) const
 {
   double val = _tfaipv->get(i);
   if (val == 0.)
@@ -3277,7 +3277,7 @@ GenericTFADG3DIPVariable::~GenericTFADG3DIPVariable()
 }
 
 
-double GenericTFADG3DIPVariable::get(const int i) const 
+double GenericTFADG3DIPVariable::get(const int i) const
 {
   double val = _generictfaipv->get(i);
   if (val == 0.)
@@ -3332,7 +3332,7 @@ TFADG3DIPVariable::~TFADG3DIPVariable()
   _tfaipv = NULL;
 }
 
-double TFADG3DIPVariable::get(const int i) const 
+double TFADG3DIPVariable::get(const int i) const
 {
   double val = _tfaipv->get(i);
   if (val == 0.)
@@ -3373,7 +3373,7 @@ TFA2LevelsDG3DIPVariable::~TFA2LevelsDG3DIPVariable()
   _tfa2levelsipv = NULL;
 }
 
-double TFA2LevelsDG3DIPVariable::get(const int i) const 
+double TFA2LevelsDG3DIPVariable::get(const int i) const
 {
   double val = _tfa2levelsipv->get(i);
   if (val == 0.)
@@ -3631,7 +3631,7 @@ void J2ThermoMechanicsDG3DIPVariable::restart()
   return;
 }
 
-J2FullThermoMechanicsDG3DIPVariable::J2FullThermoMechanicsDG3DIPVariable(const J2IsotropicHardening* j2harden, const bool createBodyForceHO, 
+J2FullThermoMechanicsDG3DIPVariable::J2FullThermoMechanicsDG3DIPVariable(const J2IsotropicHardening* j2harden, const bool createBodyForceHO,
                        const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter),_j2Thermo(j2harden){};
 J2FullThermoMechanicsDG3DIPVariable::J2FullThermoMechanicsDG3DIPVariable(const J2FullThermoMechanicsDG3DIPVariable& src):
 			ThermoMechanicsDG3DIPVariableBase(src),_j2Thermo(src._j2Thermo){};
@@ -3735,9 +3735,9 @@ void SMPDG3DIPVariable::restart()
 }
 
 //===========/start/Phenomenological===================================================================================
-PhenomenologicalSMPDG3DIPVariable::PhenomenologicalSMPDG3DIPVariable(double tinitial, const mlawPhenomenologicalSMP &_lawSMP, const bool createBodyForceHO,  
+PhenomenologicalSMPDG3DIPVariable::PhenomenologicalSMPDG3DIPVariable(double tinitial, const mlawPhenomenologicalSMP &_lawSMP, const bool createBodyForceHO,
                                   const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter)
-{   _TMIPSMP = new IPPhenomenologicalSMP(tinitial, _lawSMP.getCrystallizationTemperature(), _lawSMP.getMeltingTemperature(), 
+{   _TMIPSMP = new IPPhenomenologicalSMP(tinitial, _lawSMP.getCrystallizationTemperature(), _lawSMP.getMeltingTemperature(),
        _lawSMP.getCrystallizationParameter(), _lawSMP.getMeltingParameter(),
       _lawSMP.getJ2IsotropicHardeningCompressionG(), _lawSMP.getJ2IsotropicHardeningTractionG(), _lawSMP.getKinematicHardeningG(), _lawSMP.getViscoElasticNumberOfElementG(),
       _lawSMP.getJ2IsotropicHardeningCompressionR(), _lawSMP.getJ2IsotropicHardeningTractionR(), _lawSMP.getKinematicHardeningR(), _lawSMP.getViscoElasticNumberOfElementR(),
@@ -3938,7 +3938,7 @@ double PhenomenologicalSMPDG3DIPVariable::get(const int i) const
     else if(i==IPField::EnThG_XY)      {return _TMIPSMP->getConstRefToEnThG()(0,1);}
     else if(i==IPField::EnThG_YZ)      {return _TMIPSMP->getConstRefToEnThG()(1,2);}
     else if(i==IPField::EnThG_ZX)      {return _TMIPSMP->getConstRefToEnThG()(0,2);}
-    
+
     else if(i==IPField::EnThR_XX)      {return _TMIPSMP->getConstRefToEnThR()(0,0);}
     else if(i==IPField::EnThR_YY)      {return _TMIPSMP->getConstRefToEnThR()(1,1);}
     else if(i==IPField::EnThR_ZZ)      {return _TMIPSMP->getConstRefToEnThR()(2,2);}
@@ -3952,7 +3952,7 @@ double PhenomenologicalSMPDG3DIPVariable::get(const int i) const
     else if(i==IPField::EnThAM_XY)      {return _TMIPSMP->getConstRefToEnThAM()(0,1);}
     else if(i==IPField::EnThAM_YZ)      {return _TMIPSMP->getConstRefToEnThAM()(1,2);}
     else if(i==IPField::EnThAM_ZX)      {return _TMIPSMP->getConstRefToEnThAM()(0,2);}
-    
+
     else if(i==IPField::appliedEnergy)  {return _TMIPSMP->getConstRefToAppliedEnergy();}
     else if(i==IPField::_SMPEnergy)     {return _TMIPSMP->defoEnergy();}
     else if(i==IPField::_thermalEnergy) {return _TMIPSMP->getThermalEnergy();}
@@ -4116,7 +4116,7 @@ void gursonUMATDG3DIPVariable::restart()
 }
 
 //
-ElecTherMechDG3DIPVariableBase::ElecTherMechDG3DIPVariableBase(bool createBodyForceHO,  const bool oninter) : 
+ElecTherMechDG3DIPVariableBase::ElecTherMechDG3DIPVariableBase(bool createBodyForceHO,  const bool oninter) :
                                                     dG3DIPVariable(createBodyForceHO, oninter,0,2,0,true,true)
 
 {
@@ -4877,3 +4877,561 @@ void ElecSMPDG3DIPVariable::restart()
   restartManager::restart(_ESMPIP);
   return;
 }
+
+
+// NonLinearTVM Law Interface =================================================================== BEGIN
+
+// Take Care here, nonlocal variables cannot be directly defined with the ThermoMechanicsDG3DIPVariable Base Class (This is a pure virtual base class).
+
+// 1) Constructor Changed
+/*
+NonLinearTVMDG3DIPVariable::NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, const bool oninter, int nbExtraDof): dG3DIPVariable(oninter, 0, nbExtraDof){
+  _ipViscoElastic = new IPNonLinearTVM(viscoLaw.getViscoElasticNumberOfElement());
+};
+*/
+NonLinearTVMDG3DIPVariable::NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter) :
+              ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter){
+  _ipViscoElastic = new IPNonLinearTVM(viscoLaw.getViscoElasticNumberOfElement());
+  this->getRefToTemperature()=Tinitial;
+};
+
+// 2) Copy Constructor Changed
+/*
+NonLinearTVMDG3DIPVariable::NonLinearTVMDG3DIPVariable(const NonLinearTVMDG3DIPVariable& src): dG3DIPVariable(src){
+  _ipViscoElastic = NULL;
+  if (src._ipViscoElastic != NULL){
+    _ipViscoElastic = dynamic_cast<IPNonLinearTVM*>(src._ipViscoElastic->clone());
+  }
+};
+*/
+NonLinearTVMDG3DIPVariable::NonLinearTVMDG3DIPVariable(const NonLinearTVMDG3DIPVariable& src) :
+              ThermoMechanicsDG3DIPVariableBase(src), _ipViscoElastic(src._ipViscoElastic){
+  _ipViscoElastic = NULL;
+  if (src._ipViscoElastic != NULL){
+    _ipViscoElastic = dynamic_cast<IPNonLinearTVM*>(src._ipViscoElastic->clone());
+  }
+};
+
+// 3) Operator Assignment Changed
+/*
+NonLinearTVMDG3DIPVariable& NonLinearTVMDG3DIPVariable::operator = (const IPVariable& src){
+  dG3DIPVariable::operator =(src);
+  const NonLinearTVMDG3DIPVariable* psrc = dynamic_cast<const NonLinearTVMDG3DIPVariable*>(&src);
+  if (psrc != NULL){
+    if (psrc->_ipViscoElastic != NULL){
+      if (_ipViscoElastic!= NULL){
+        _ipViscoElastic->operator=(*dynamic_cast<const IPVariable*>(psrc->_ipViscoElastic));
+      }
+      else{
+        _ipViscoElastic = dynamic_cast<IPNonLinearTVM*>(psrc->_ipViscoElastic->clone());
+      }
+    }
+  }
+  return *this;
+};
+*/
+NonLinearTVMDG3DIPVariable& NonLinearTVMDG3DIPVariable::operator = (const IPVariable& src){
+  ThermoMechanicsDG3DIPVariableBase::operator =(src);
+  const NonLinearTVMDG3DIPVariable* psrc = dynamic_cast<const NonLinearTVMDG3DIPVariable*>(&src);
+  if (psrc != NULL){
+    if (psrc->_ipViscoElastic != NULL){
+      if (_ipViscoElastic!= NULL){
+        _ipViscoElastic->operator=(*dynamic_cast<const IPVariable*>(psrc->_ipViscoElastic));
+      }
+      else{
+        _ipViscoElastic = dynamic_cast<IPNonLinearTVM*>(psrc->_ipViscoElastic->clone());
+      }
+    }
+  }
+  return *this;
+};
+
+// 4) Virtual Destructor - Unchanged
+NonLinearTVMDG3DIPVariable::~NonLinearTVMDG3DIPVariable(){
+  if (_ipViscoElastic){delete _ipViscoElastic; _ipViscoElastic=NULL;};
+};
+
+// 5) Member Function - get(i) - Changed - Refer to HyperVisco...DG3DIP for the Original
+double NonLinearTVMDG3DIPVariable::get(const int i) const{
+
+  if      (i == IPField::Ee_XX){return _ipViscoElastic->_Ee(0,0);}
+  else if (i == IPField::Ee_XY){return _ipViscoElastic->_Ee(0,1);}
+  else if (i == IPField::Ee_XZ){return _ipViscoElastic->_Ee(0,2);}
+  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::Eve1_XX){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,0) + _ipViscoElastic->_B[0]/3.;
+    else
+      return 0.;
+    }
+  else if (i == IPField::Eve1_XY){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_XZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,2);
+    return 0.;
+  }
+  else if (i == IPField::Eve1_YY){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](1,1) + _ipViscoElastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_YZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_ZZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](2,2) + _ipViscoElastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XX){                                              // Eve2 - WHAT is it?
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,0) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XY){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YY){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](1,1) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_ZZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](2,2) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+
+  // Additional IPFields from ThermoMechanicsDG3DIPVariableBase - Adopted here directly
+  else if (i == IPField::TEMPERATURE){return getConstRefToField(0);}
+  else if (i == IPField::THERMALFLUX_X){return getConstRefToFlux()[0](0);}
+  else if (i == IPField::THERMALFLUX_Y){return getConstRefToFlux()[0](1);}
+  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
+  {
+    return dG3DIPVariable::get(i);
+  }
+};
+
+// 5) Member Function - defoEnergy()  - Unchanged
+double  NonLinearTVMDG3DIPVariable::defoEnergy() const{
+  return _ipViscoElastic->defoEnergy();
+}
+
+// 6) Member Function - plasticEnergy() - Added from LinearTherMech -------------- WHY and used HOW??
+double NonLinearTVMDG3DIPVariable::plasticEnergy() const{
+  return getIPNonLinearTVM()->plasticEnergy();
+}
+
+// 7) Other Member Functions - damageEnergy(), etc, may have to be added later.
+
+// 8) Member Function - restart() - Changed only 2nd line
+void NonLinearTVMDG3DIPVariable::restart(){
+// dG3DIPVariable::restart();
+  ThermoMechanicsDG3DIPVariableBase::restart();
+  restartManager::restart(_ipViscoElastic);
+  return;
+}
+
+// NonLinearTVM Law Interface ========
+
+// NonLinearTVE Law Interface =================================================================== BEGIN
+
+// Take Care here, nonlocal variables cannot be directly defined with the ThermoMechanicsDG3DIPVariable Base Class (This is a pure virtual base class).
+
+// 1) Constructor Changed
+/*
+NonLinearTVEDG3DIPVariable::NonLinearTVEDG3DIPVariable(const mlawNonLinearTVE& viscoLaw, const bool oninter, int nbExtraDof): dG3DIPVariable(oninter, 0, nbExtraDof){
+  _ipViscoElastic = new IPNonLinearTVE(viscoLaw.getViscoElasticNumberOfElement());
+};
+*/
+NonLinearTVEDG3DIPVariable::NonLinearTVEDG3DIPVariable(const mlawNonLinearTVE& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter) :
+              ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter){
+  _ipViscoElastic = new IPNonLinearTVE(viscoLaw.getConstRefToCompressionHardening(),
+                                       viscoLaw.getConstRefToTractionHardening(),
+                                       viscoLaw.getConstRefToKinematicHardening(),
+                                       viscoLaw.getViscoElasticNumberOfElement());
+  this->getRefToTemperature()=Tinitial;
+};
+
+// 2) Copy Constructor Changed
+/*
+NonLinearTVEDG3DIPVariable::NonLinearTVEDG3DIPVariable(const NonLinearTVEDG3DIPVariable& src): dG3DIPVariable(src){
+  _ipViscoElastic = NULL;
+  if (src._ipViscoElastic != NULL){
+    _ipViscoElastic = dynamic_cast<IPNonLinearTVE*>(src._ipViscoElastic->clone());
+  }
+};
+*/
+NonLinearTVEDG3DIPVariable::NonLinearTVEDG3DIPVariable(const NonLinearTVEDG3DIPVariable& src) :
+              ThermoMechanicsDG3DIPVariableBase(src), _ipViscoElastic(src._ipViscoElastic){
+  _ipViscoElastic = NULL;
+  if (src._ipViscoElastic != NULL){
+    _ipViscoElastic = dynamic_cast<IPNonLinearTVE*>(src._ipViscoElastic->clone());
+  }
+};
+
+// 3) Operator Assignment Changed
+/*
+NonLinearTVEDG3DIPVariable& NonLinearTVEDG3DIPVariable::operator = (const IPVariable& src){
+  dG3DIPVariable::operator =(src);
+  const NonLinearTVEDG3DIPVariable* psrc = dynamic_cast<const NonLinearTVEDG3DIPVariable*>(&src);
+  if (psrc != NULL){
+    if (psrc->_ipViscoElastic != NULL){
+      if (_ipViscoElastic!= NULL){
+        _ipViscoElastic->operator=(*dynamic_cast<const IPVariable*>(psrc->_ipViscoElastic));
+      }
+      else{
+        _ipViscoElastic = dynamic_cast<IPNonLinearTVE*>(psrc->_ipViscoElastic->clone());
+      }
+    }
+  }
+  return *this;
+};
+*/
+NonLinearTVEDG3DIPVariable& NonLinearTVEDG3DIPVariable::operator = (const IPVariable& src){
+  ThermoMechanicsDG3DIPVariableBase::operator =(src);
+  const NonLinearTVEDG3DIPVariable* psrc = dynamic_cast<const NonLinearTVEDG3DIPVariable*>(&src);
+  if (psrc != NULL){
+    if (psrc->_ipViscoElastic != NULL){
+      if (_ipViscoElastic!= NULL){
+        _ipViscoElastic->operator=(*dynamic_cast<const IPVariable*>(psrc->_ipViscoElastic));
+      }
+      else{
+        _ipViscoElastic = dynamic_cast<IPNonLinearTVE*>(psrc->_ipViscoElastic->clone());
+      }
+    }
+  }
+  return *this;
+};
+
+// 4) Virtual Destructor - Unchanged
+NonLinearTVEDG3DIPVariable::~NonLinearTVEDG3DIPVariable(){
+  if (_ipViscoElastic){delete _ipViscoElastic; _ipViscoElastic=NULL;};
+};
+
+// 5) Member Function - get(i) - Changed - Refer to HyperVisco...DG3DIP for the Original
+double NonLinearTVEDG3DIPVariable::get(const int i) const{
+
+  if      (i == IPField::Ee_XX){return _ipViscoElastic->_Ee(0,0);}
+  else if (i == IPField::Ee_XY){return _ipViscoElastic->_Ee(0,1);}
+  else if (i == IPField::Ee_XZ){return _ipViscoElastic->_Ee(0,2);}
+  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::Eve1_XX){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,0) + _ipViscoElastic->_B[0]/3.;
+    else
+      return 0.;
+    }
+  else if (i == IPField::Eve1_XY){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_XZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](0,2);
+    return 0.;
+  }
+  else if (i == IPField::Eve1_YY){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](1,1) + _ipViscoElastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_YZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_ZZ){
+    if (_ipViscoElastic->_A.size() > 0)
+      return _ipViscoElastic->_A[0](2,2) + _ipViscoElastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XX){                                              // Eve2 - WHAT is it?
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,0) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XY){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](0,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YY){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](1,1) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_ZZ){
+    if (_ipViscoElastic->_A.size() > 1)
+      return _ipViscoElastic->_A[1](2,2) + _ipViscoElastic->_B[1]/3.;
+    else return 0.;
+  }
+
+  // Additional IPFields from ThermoMechanicsDG3DIPVariableBase - Adopted here directly
+  else if (i == IPField::TEMPERATURE){return getConstRefToField(0);}
+  else if (i == IPField::THERMALFLUX_X){return getConstRefToFlux()[0](0);}
+  else if (i == IPField::THERMALFLUX_Y){return getConstRefToFlux()[0](1);}
+  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
+  {
+    return dG3DIPVariable::get(i);
+  }
+};
+
+// 5) Member Function - defoEnergy()  - Unchanged
+double  NonLinearTVEDG3DIPVariable::defoEnergy() const{
+  return _ipViscoElastic->defoEnergy();
+}
+
+// 6) Member Function - plasticEnergy() - Added from LinearTherMech -------------- WHY and used HOW??
+double NonLinearTVEDG3DIPVariable::plasticEnergy() const{
+  return getIPNonLinearTVE()->plasticEnergy();
+}
+
+// 7) Other Member Functions - damageEnergy(), etc, may have to be added later.
+
+// 8) Member Function - restart() - Changed only 2nd line
+void NonLinearTVEDG3DIPVariable::restart(){
+// dG3DIPVariable::restart();
+  ThermoMechanicsDG3DIPVariableBase::restart();
+  restartManager::restart(_ipViscoElastic);
+  return;
+}
+
+// NonLinearTVE Law Interface =================================================================== END
+
+// NonLinearTVP Law Interface =================================================================== BEGIN
+
+NonLinearTVPDG3DIPVariable::NonLinearTVPDG3DIPVariable(const mlawNonLinearTVP& viscoEPLaw, double Tinitial, const bool createBodyForceHO, const bool oninter) :
+              ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter){
+  _ipViscoElastoPlastic = new IPNonLinearTVP(viscoEPLaw.getConstRefToCompressionHardening(),
+                                              viscoEPLaw.getConstRefToTractionHardening(),
+                                              viscoEPLaw.getConstRefToKinematicHardening(),
+                                              viscoEPLaw.getViscoElasticNumberOfElement());
+  this->getRefToTemperature()=Tinitial;
+};
+
+NonLinearTVPDG3DIPVariable::NonLinearTVPDG3DIPVariable(const NonLinearTVPDG3DIPVariable& src) :
+              ThermoMechanicsDG3DIPVariableBase(src), _ipViscoElastoPlastic(src._ipViscoElastoPlastic){
+  _ipViscoElastoPlastic = NULL;
+  if (src._ipViscoElastoPlastic != NULL){
+    _ipViscoElastoPlastic = dynamic_cast<IPNonLinearTVP*>(src._ipViscoElastoPlastic->clone());
+  }
+};
+
+NonLinearTVPDG3DIPVariable& NonLinearTVPDG3DIPVariable::operator = (const IPVariable& src){
+  ThermoMechanicsDG3DIPVariableBase::operator =(src);
+  const NonLinearTVPDG3DIPVariable* psrc = dynamic_cast<const NonLinearTVPDG3DIPVariable*>(&src);
+  if (psrc != NULL){
+    if (psrc->_ipViscoElastoPlastic != NULL){
+      if (_ipViscoElastoPlastic!= NULL){
+        _ipViscoElastoPlastic->operator=(*dynamic_cast<const IPVariable*>(psrc->_ipViscoElastoPlastic));
+      }
+      else{
+        _ipViscoElastoPlastic = dynamic_cast<IPNonLinearTVP*>(psrc->_ipViscoElastoPlastic->clone());
+      }
+    }
+  }
+  return *this;
+};
+
+NonLinearTVPDG3DIPVariable::~NonLinearTVPDG3DIPVariable(){
+  if (_ipViscoElastoPlastic){delete _ipViscoElastoPlastic; _ipViscoElastoPlastic = NULL;};
+};
+
+double NonLinearTVPDG3DIPVariable::get(const int i) const{
+
+  if      (i == IPField::Ee_XX){return _ipViscoElastoPlastic->_Ee(0,0);}
+  else if (i == IPField::Ee_XY){return _ipViscoElastoPlastic->_Ee(0,1);}
+  else if (i == IPField::Ee_XZ){return _ipViscoElastoPlastic->_Ee(0,2);}
+  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::Eve1_XX){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](0,0) + _ipViscoElastoPlastic->_B[0]/3.;
+    else
+      return 0.;
+    }
+  else if (i == IPField::Eve1_XY){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_XZ){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](0,2);
+    return 0.;
+  }
+  else if (i == IPField::Eve1_YY){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](1,1) + _ipViscoElastoPlastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_YZ){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve1_ZZ){
+    if (_ipViscoElastoPlastic->_A.size() > 0)
+      return _ipViscoElastoPlastic->_A[0](2,2) + _ipViscoElastoPlastic->_B[0]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XX){                                              // Eve2 - WHAT is it?
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](0,0) + _ipViscoElastoPlastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XY){
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](0,1);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_XZ){
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](0,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YY){
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](1,1) + _ipViscoElastoPlastic->_B[1]/3.;
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_YZ){
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](1,2);
+    else return 0.;
+  }
+  else if (i == IPField::Eve2_ZZ){
+    if (_ipViscoElastoPlastic->_A.size() > 1)
+      return _ipViscoElastoPlastic->_A[1](2,2) + _ipViscoElastoPlastic->_B[1]/3.;
+    else return 0.;
+  }
+
+  // Additional IPFields from ThermoMechanicsDG3DIPVariableBase - Adopted here directly
+  else if (i == IPField::TEMPERATURE){return getConstRefToField(0);}
+  else if (i == IPField::THERMALFLUX_X){return getConstRefToFlux()[0](0);}
+  else if (i == IPField::THERMALFLUX_Y){return getConstRefToFlux()[0](1);}
+  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::PLASTICSTRAIN)
+  {
+    return _ipViscoElastoPlastic->getConstRefToEqPlasticStrain();
+  }
+   else if(i == IPField::FP_XX)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(0,0);
+  }
+  else if(i == IPField::FP_XY)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(0,1);
+  }
+  else if(i == IPField::FP_XZ)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(0,2);
+  }
+  else if(i == IPField::FP_YX)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(1,0);
+  }
+  else if(i == IPField::FP_YY)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(1,1);
+  }
+  else if(i == IPField::FP_YZ)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(1,2);
+  }
+  else if(i == IPField::FP_ZX)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(2,0);
+  }
+  else if(i == IPField::FP_ZY)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(2,1);
+  }
+  else if(i == IPField::FP_ZZ)
+  {
+    return _ipViscoElastoPlastic->getConstRefToFp()(2,2);
+  }
+  else if (i == IPField::PLASTIC_POISSON_RATIO){
+    return _ipViscoElastoPlastic->getConstRefToPlasticPoissonRatio();
+  }
+  else if (i == IPField::ISO_YIELD_COMPRESSION)
+  {
+    return _ipViscoElastoPlastic->getConstRefToIPCompressionHardening().getR();
+  }
+  else if (i == IPField::ISO_YIELD_TENSILE)
+  {
+    return _ipViscoElastoPlastic->getConstRefToIPTractionHardening().getR();
+  }
+  else if (i == IPField::KIN_YIELD)
+  {
+    return _ipViscoElastoPlastic->getConstRefToKinematicHardening().getR();
+  }
+
+  else
+  {
+    return dG3DIPVariable::get(i);
+  }
+};
+
+double  NonLinearTVPDG3DIPVariable::defoEnergy() const{
+  return _ipViscoElastoPlastic->defoEnergy();
+}
+
+double NonLinearTVPDG3DIPVariable::plasticEnergy() const{
+  return getIPNonLinearTVP()->plasticEnergy();
+}
+
+void NonLinearTVPDG3DIPVariable::restart(){
+// dG3DIPVariable::restart();
+  ThermoMechanicsDG3DIPVariableBase::restart();
+  restartManager::restart(_ipViscoElastoPlastic);
+  return;
+}
+
+// NonLinearTVP Law Interface =================================================================== END
diff --git a/dG3D/src/dG3DIPVariable.h b/dG3D/src/dG3DIPVariable.h
index 9380968a8cf22bd592364d897e48d9b88fa1e43b..0042ecfe845da139f2bed7cba6936183d8c0a827 100644
--- a/dG3D/src/dG3DIPVariable.h
+++ b/dG3D/src/dG3DIPVariable.h
@@ -61,6 +61,12 @@
 #include "mlawLinearElecMagInductor.h"
 #include "mlawLocalDamageJ2SmallStrain.h"
 #include "mlawLocalDamageIsotropicElasticity.h"
+#include "ipNonLinearTVM.h"
+#include "mlawNonLinearTVM.h"
+#include "ipNonLinearTVE.h"
+#include "mlawNonLinearTVE.h"
+#include "ipNonLinearTVP.h"
+#include "mlawNonLinearTVP.h"
 
 #if defined(HAVE_TORCH)
 #include <torch/torch.h>
@@ -93,7 +99,7 @@ class dG3DIPVariableBase : public ipFiniteStrain
   virtual double getLocalJ() const=0;
   virtual double &getRefToLocalJ()=0;
   virtual void getBackLocalDeformationGradient(STensor3& localF) const=0;
- 
+
   virtual const STensor3 &getConstRefToDeformationGradient() const=0;
   virtual STensor3 &getRefToDeformationGradient()=0;
 
@@ -687,8 +693,8 @@ protected:
     if(_bodyForceForHO==NULL)
       return false;
     else
-      return true; 
-  }  
+      return true;
+  }
   virtual const STensor33 &getConstRefToGM() const
   {
     if(hasBodyForceForHO())
@@ -699,7 +705,7 @@ protected:
       static STensor33 VoidGM;
       return VoidGM;
     }
-  }  
+  }
   virtual STensor33 &getRefToGM()
   {
     if(hasBodyForceForHO())
@@ -710,8 +716,8 @@ protected:
       static STensor33 VoidGM;
       return VoidGM;
     }
-  }  
-  
+  }
+
   virtual const STensor43 &getConstRefToDFmdFM() const
   {
     if(hasBodyForceForHO())
@@ -721,7 +727,7 @@ protected:
     static STensor43 VoiddFmdFM;
     return VoiddFmdFM;
     }
-  }  
+  }
   virtual STensor43 &getRefToDFmdFM()
   {
     if(hasBodyForceForHO())
@@ -732,7 +738,7 @@ protected:
       static STensor43 VoiddFmdFM;
       return VoiddFmdFM;
     }
-  }  
+  }
 
   virtual const STensor53 &getConstRefToDFmdGM() const
   {
@@ -743,7 +749,7 @@ protected:
     static STensor53 VoiddFmdGM;
     return VoiddFmdGM;
     }
-  }  
+  }
   virtual STensor53 &getRefToDFmdGM()
   {
     if(hasBodyForceForHO())
@@ -754,7 +760,7 @@ protected:
       static STensor53 VoiddFmdGM;
       return VoiddFmdGM;
     }
-  }  
+  }
 
 virtual const SVector3 &getConstRefToBm() const
   {
@@ -766,7 +772,7 @@ virtual const SVector3 &getConstRefToBm() const
       static SVector3 VoidBm;
       return VoidBm;
     }
-  }  
+  }
 virtual SVector3 &getRefToBm()
   {
     if(hasBodyForceForHO())
@@ -777,7 +783,7 @@ virtual SVector3 &getRefToBm()
       static SVector3 VoidBm;
       return VoidBm;
     }
-  }  
+  }
 
 virtual const STensor43 &getConstRefTodBmdGM() const
   {
@@ -788,7 +794,7 @@ virtual const STensor43 &getConstRefTodBmdGM() const
     static STensor43 VoiddBmdGM;
     return VoiddBmdGM;
     }
-  }  
+  }
   virtual STensor43 &getRefTodBmdGM()
   {
     if(hasBodyForceForHO())
@@ -798,7 +804,7 @@ virtual const STensor43 &getConstRefTodBmdGM() const
       static STensor43 VoiddBmdGM;
       return VoiddBmdGM;
     }
-  }    
+  }
 
 
 virtual const STensor33 &getConstRefTodBmdFm() const
@@ -811,7 +817,7 @@ virtual const STensor33 &getConstRefTodBmdFm() const
       static STensor33 VoiddBmdFm;
       return VoiddBmdFm;
     }
-  }  
+  }
 virtual STensor33 &getRefTodBmdFm()
   {
     if(hasBodyForceForHO())
@@ -822,8 +828,8 @@ virtual STensor33 &getRefTodBmdFm()
       static STensor33 VoiddBmdFm;
       return VoiddBmdFm;
     }
-  }  
-  
+  }
+
 virtual const STensor43 &getConstRefTodPmdFM() const
   {
     if(hasBodyForceForHO())
@@ -834,8 +840,8 @@ virtual const STensor43 &getConstRefTodPmdFM() const
       static STensor43 VoiddPmdFM;
       return VoiddPmdFM;
     }
-  }  
-  
+  }
+
 virtual STensor43 &getRefTodPmdFM()
   {
     if(hasBodyForceForHO())
@@ -858,7 +864,7 @@ virtual const STensor63 &getConstRefTodCmdFm() const
       static STensor63 VoiddCmdFm;
       return VoiddCmdFm;
     }
-  }  
+  }
 virtual STensor63 &getRefTodCmdFm()
   {
     if(hasBodyForceForHO())
@@ -877,10 +883,10 @@ virtual STensor63 *getPtrTodCmdFm()
     else
       return NULL;
   }
-  
-virtual void computeBodyForce(const STensor33& G, SVector3& B) const;  
+
+virtual void computeBodyForce(const STensor33& G, SVector3& B) const;
 virtual void setValueForBodyForce(const STensor43& K, const int _ModuliType);
-  
+
   // non local
 
   virtual int getNumberNonLocalVariable() const
@@ -2776,7 +2782,7 @@ class TransverseIsoCurvatureDG3DIPVariable : public dG3DIPVariable // or store d
   IPTransverseIsoCurvature _tiipv;
  public:
   TransverseIsoCurvatureDG3DIPVariable(const SVector3 &GaussP, const SVector3 &Centroid,
-                                       const SVector3 &PointStrart1, const SVector3 &PointStrart2, const double init_Angle, 
+                                       const SVector3 &PointStrart1, const SVector3 &PointStrart2, const double init_Angle,
                                        const bool createBodyForceHO,const bool oninter);
   TransverseIsoCurvatureDG3DIPVariable(const TransverseIsoCurvatureDG3DIPVariable &source);
   virtual TransverseIsoCurvatureDG3DIPVariable& operator=(const IPVariable &source);
@@ -2945,7 +2951,7 @@ class GenericTFADG3DIPVariable : public dG3DIPVariable // or store data in a dif
     _generictfaipv->setLocation(loc);
   };
   virtual ~GenericTFADG3DIPVariable();
-  
+
   virtual IPVariable* getInternalData() {return _generictfaipv;};
   virtual const IPVariable* getInternalData()  const {return _generictfaipv;};
 
@@ -2972,7 +2978,7 @@ class TFADG3DIPVariable : public GenericTFADG3DIPVariable // or store data in a
     dG3DIPVariable::setLocation(loc);
     _tfaipv->setLocation(loc);
   };
-  
+
   virtual ~TFADG3DIPVariable();
 
   virtual IPVariable* getInternalData() {return _tfaipv;};
@@ -5003,4 +5009,175 @@ public:
   virtual void restart();
 };
 
+// NonLinearTVM Law Interface =================================================================== BEGIN
+
+// Take Care here, nonlocal variables cannot be directly defined with the ThermoMechanicsDG3DIPVariable Base Class (This is a pure virtual base class).
+
+// class NonLinearTVMDG3DIPVariable : public dG3DIPVariable{
+class NonLinearTVMDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   // Changed
+
+  protected:
+    IPNonLinearTVM * _ipViscoElastic;
+    NonLinearTVMDG3DIPVariable(const bool createBodyForceHO, const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter) {Msg::Error("NonLinearTVMDG3DIPVariable: Cannot use the default constructor of ThermoMechanicsDG3DIPVariableBase");}
+
+  public:
+// Constructor Changed
+  //  NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, const bool oninter=false, int nbExtraDof=0);  // ?? - WHAT to add/change?
+    NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter);  // Changed
+    NonLinearTVMDG3DIPVariable(const NonLinearTVMDG3DIPVariable& src);
+    virtual NonLinearTVMDG3DIPVariable& operator = (const IPVariable& src);
+    virtual ~NonLinearTVMDG3DIPVariable();
+
+    virtual void setLocation(const IPVariable::LOCATION loc) {
+      dG3DIPVariable::setLocation(loc);
+      if (_ipViscoElastic)
+        _ipViscoElastic->setLocation(loc);
+    };
+
+    virtual IPVariable* getInternalData() {return _ipViscoElastic;};
+    virtual const IPVariable* getInternalData()  const {return _ipViscoElastic;};
+
+ // Specific functions - getIP
+    IPNonLinearTVM* getIPNonLinearTVM() {return _ipViscoElastic;};
+    const IPNonLinearTVM* getIPNonLinearTVM() const {return _ipViscoElastic;};
+
+    virtual double get(const int i) const;
+    virtual double defoEnergy() const;
+
+// Added from LinearThermoMechanicsDG3DIPVariable
+    virtual double getInternalEnergyExtraDofDiffusion() const {return _ipViscoElastic->getThermalEnergy();};           // Added
+    virtual double plasticEnergy() const;                                                                             // Added
+    virtual double damageEnergy() const {return _ipViscoElastic->damageEnergy();};                                     // Added
+    // virtual int fractureEnergy(double* arrayEnergy) const{arrayEnergy[0]=_linearTMIP.getConstRefToFractureEnergy(); return 1;} // need it to get H1 norm in the interface  e.g. LinearThermoMech
+                                                                        // Fracture energy for WHAT?? Added but unused?
+
+// for Path-Following based on irreversible energy
+    virtual double irreversibleEnergy() const {return _ipViscoElastic->irreversibleEnergy();};
+    virtual double& getRefToIrreversibleEnergy() {return _ipViscoElastic->getRefToIrreversibleEnergy();};
+
+    virtual const STensor3& getConstRefToDIrreversibleEnergyDDeformationGradient() const {return _ipViscoElastic->getConstRefToDIrreversibleEnergyDF();};
+    virtual STensor3& getRefToDIrreversibleEnergyDDeformationGradient() {return _ipViscoElastic->getRefToDIrreversibleEnergyDF();};
+
+    virtual IPVariable* clone() const {return new NonLinearTVMDG3DIPVariable(*this);};
+    virtual void restart();
+};
+
+// NonLinearTVM Law Interface =================================================================== END
+
+
+// NonLinearTVE Law Interface =================================================================== BEGIN
+
+// Take Care here, nonlocal variables cannot be directly defined with the ThermoMechanicsDG3DIPVariable Base Class (This is a pure virtual base class).
+
+// class NonLinearTVMDG3DIPVariable : public dG3DIPVariable{
+class NonLinearTVEDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   // Changed
+
+  protected:
+    IPNonLinearTVE * _ipViscoElastic;
+    NonLinearTVEDG3DIPVariable(const bool createBodyForceHO, const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter) {Msg::Error("NonLinearTVEDG3DIPVariable: Cannot use the default constructor of ThermoMechanicsDG3DIPVariableBase");}
+
+  public:
+// Constructor Changed
+  //  NonLinearTVEDG3DIPVariable(const mlawNonLinearTVE& viscoLaw, const bool oninter=false, int nbExtraDof=0);  // ?? - WHAT to add/change?
+    NonLinearTVEDG3DIPVariable(const mlawNonLinearTVE& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter);  // Changed
+    NonLinearTVEDG3DIPVariable(const NonLinearTVEDG3DIPVariable& src);
+    virtual NonLinearTVEDG3DIPVariable& operator = (const IPVariable& src);
+    virtual ~NonLinearTVEDG3DIPVariable();
+
+    virtual void setLocation(const IPVariable::LOCATION loc) {
+      dG3DIPVariable::setLocation(loc);
+      if (_ipViscoElastic)
+        _ipViscoElastic->setLocation(loc);
+    };
+
+    virtual IPVariable* getInternalData() {return _ipViscoElastic;};
+    virtual const IPVariable* getInternalData()  const {return _ipViscoElastic;};
+
+ // Specific functions - getIP
+    IPNonLinearTVE* getIPNonLinearTVE() {return _ipViscoElastic;};
+    const IPNonLinearTVE* getIPNonLinearTVE() const {return _ipViscoElastic;};
+
+    virtual double get(const int i) const;
+    virtual double defoEnergy() const;
+
+// Added from LinearThermoMechanicsDG3DIPVariable
+    virtual double getInternalEnergyExtraDofDiffusion() const {return _ipViscoElastic->getThermalEnergy();};           // Added
+    virtual double plasticEnergy() const;                                                                             // Added
+    virtual double damageEnergy() const {return _ipViscoElastic->damageEnergy();};                                     // Added
+    // virtual int fractureEnergy(double* arrayEnergy) const{arrayEnergy[0]=_linearTMIP.getConstRefToFractureEnergy(); return 1;} // need it to get H1 norm in the interface  e.g. LinearThermoMech
+                                                                        // Fracture energy for WHAT?? Added but unused?
+
+// for Path-Following based on irreversible energy
+    virtual double irreversibleEnergy() const {return _ipViscoElastic->irreversibleEnergy();};
+    virtual double& getRefToIrreversibleEnergy() {return _ipViscoElastic->getRefToIrreversibleEnergy();};
+
+    virtual const STensor3& getConstRefToDIrreversibleEnergyDDeformationGradient() const {return _ipViscoElastic->getConstRefToDIrreversibleEnergyDF();};
+    virtual STensor3& getRefToDIrreversibleEnergyDDeformationGradient() {return _ipViscoElastic->getRefToDIrreversibleEnergyDF();};
+
+    virtual IPVariable* clone() const {return new NonLinearTVEDG3DIPVariable(*this);};
+    virtual void restart();
+};
+
+// NonLinearTVE Law Interface =================================================================== END
+
+// NonLinearTVP Law Interface =================================================================== BEGIN
+
+class NonLinearTVPDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   // Changed
+
+  protected:
+    IPNonLinearTVP * _ipViscoElastoPlastic;
+    NonLinearTVPDG3DIPVariable(const bool createBodyForceHO, const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter) {
+        Msg::Error("NonLinearTVPDG3DIPVariable: Cannot use the default constructor of ThermoMechanicsDG3DIPVariableBase");
+    }
+
+  public:
+    NonLinearTVPDG3DIPVariable(const mlawNonLinearTVP& viscoEPLaw, double Tinitial, const bool createBodyForceHO, const bool oninter);
+    NonLinearTVPDG3DIPVariable(const NonLinearTVPDG3DIPVariable& src);
+    virtual NonLinearTVPDG3DIPVariable& operator = (const IPVariable& src);
+    virtual ~NonLinearTVPDG3DIPVariable();
+
+    virtual void setLocation(const IPVariable::LOCATION loc) {
+      dG3DIPVariable::setLocation(loc);
+      if (_ipViscoElastoPlastic)
+        _ipViscoElastoPlastic->setLocation(loc);
+    };
+
+    virtual IPVariable* getInternalData() {return _ipViscoElastoPlastic;};
+    virtual const IPVariable* getInternalData()  const {return _ipViscoElastoPlastic;};
+
+    IPNonLinearTVP* getIPNonLinearTVP() {return _ipViscoElastoPlastic;};
+    const IPNonLinearTVP* getIPNonLinearTVP() const {return _ipViscoElastoPlastic;};
+
+    // CHECK
+    /*
+    virtual void setLocation(const IPVariable::LOCATION loc) {
+      dG3DIPVariable::setLocation(loc);
+      if (_ipViscoElastoPlastic)
+        _ipViscoElastoPlastic->setLocation(loc);
+    };*/
+
+    virtual double get(const int i) const;
+
+    virtual bool dissipationIsActive() const {return _ipViscoElastoPlastic->dissipationIsActive();};
+    virtual void blockDissipation(const bool fl){   _ipViscoElastoPlastic->blockDissipation(fl);}
+    virtual bool dissipationIsBlocked() const { return _ipViscoElastoPlastic->dissipationIsBlocked();}
+
+// for Path-Following based on irreversible energy
+    virtual double irreversibleEnergy() const {return _ipViscoElastoPlastic->irreversibleEnergy();};
+    virtual double& getRefToIrreversibleEnergy() {return _ipViscoElastoPlastic->getRefToIrreversibleEnergy();};
+
+    virtual const STensor3& getConstRefToDIrreversibleEnergyDDeformationGradient() const {return _ipViscoElastoPlastic->getConstRefToDIrreversibleEnergyDF();};
+    virtual STensor3& getRefToDIrreversibleEnergyDDeformationGradient() {return _ipViscoElastoPlastic->getRefToDIrreversibleEnergyDF();};
+
+    virtual double defoEnergy() const;
+    virtual double plasticEnergy() const;
+    virtual double damageEnergy() const {return _ipViscoElastoPlastic->damageEnergy();};
+    virtual double getInternalEnergyExtraDofDiffusion() const {return _ipViscoElastoPlastic->getThermalEnergy();};
+
+    virtual IPVariable* clone() const {return new NonLinearTVPDG3DIPVariable(*this);};
+    virtual void restart();
+};
+
+// NonLinearTVP Law Interface =================================================================== END
+
 #endif //DG3DIPVARIABLE
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index acf40d0067af7eca03ae7195ff5186e0aae23d52..074c235685f1464342f4e05f1a75d5052b929888 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -92,12 +92,12 @@ void dG3DMaterialLaw::fillElasticStiffness(double Ex,double Ey,double Ez,double
                                            double MUxy,double MUxz,double MUyz,double alpha,double beta,double gamma,
                                            STensor43 &K_) const
 {
-  const double Vyx= Vxy*Ey/Ex  ; 
-  const double Vzx= Vxz*Ez/Ex  ; 
+  const double Vyx= Vxy*Ey/Ex  ;
+  const double Vzx= Vxz*Ez/Ex  ;
   const double Vzy= Vyz*Ez/Ey  ;
   const double D=( 1-Vxy*Vyx-Vzy*Vyz-Vxz*Vzx-2*Vxy*Vyz*Vzx ) / ( Ex*Ey*Ez );
 
-  STensor43 ElasticityTensor(0.); 
+  STensor43 ElasticityTensor(0.);
   ElasticityTensor(0,0,0,0)=( 1-Vyz*Vzy ) / (Ey*Ez*D );
   ElasticityTensor(1,1,1,1)=( 1-Vxz*Vzx ) / (Ex*Ez*D );
   ElasticityTensor(2,2,2,2)=( 1-Vyx*Vxy ) / (Ey*Ex*D );
@@ -134,7 +134,7 @@ void dG3DMaterialLaw::fillElasticStiffness(double Ex,double Ey,double Ez,double
 
   s1c2 = s1*c2;
   c1c2 = c1*c2;
-  
+
   STensor3 R;		//3x3 rotation matrix
   R(0,0) = c3*c1 - s1c2*s3;
   R(0,1) = c3*s1 + c1c2*s3;
@@ -171,7 +171,7 @@ void dG3DMaterialLaw::fillElasticStiffness(double Ex,double Ey,double Ez,double
         }
       }
     }
-  } 
+  }
 }
 
 void dG3DMaterialLaw::initialIPVariable(IPVariable* ipv, bool stiff){
@@ -607,7 +607,7 @@ void dG3DMaterialLawWithTangentByPerturbation::stress(IPVariable* ipv, const IPV
         }
 
     }
-#if 0
+#if 1
     ipvcur->getConstRefToTangentModuli().print("dPdE Numerique");
     for (int k=0; k< numNonLocalVars; k++)
     {
@@ -866,7 +866,7 @@ double dG3DLinearElasticMaterialLaw::soundSpeed() const
 };
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-dG3DLinearElasticAnisotropicMaterialLaw::dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho, 
+dG3DLinearElasticAnisotropicMaterialLaw::dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho,
 		                                      const double Ex, const double Ey, const double Ez,
                                                       const double Vxy, const double Vxz, const double Vyz,
                                                       const double MUxy, const double MUxz, const double MUyz,
@@ -935,7 +935,7 @@ double dG3DLinearElasticAnisotropicMaterialLaw::soundSpeed() const
 };
 
 
-dG3DLinearElasticTriclinicMaterialLaw::dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho, 
+dG3DLinearElasticTriclinicMaterialLaw::dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho,
 		                                      const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
 		                                      const double C01, const double C02, const double C03, const double C04, const double C05,
 		                                      const double C12, const double C13, const double C14, const double C15,
@@ -2773,7 +2773,7 @@ void TrescaDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce
   int numExtraDof=0;
   if(_trescaLaw->isThermomechanicallyCoupled())
     numExtraDof=1;
-  
+
   if(ipv !=NULL) delete ipv;
   ipv = new  nonLocalPorosityDG3DIPVariable(*_trescaLaw,fvInit,hasBodyForce,inter,numNL,numExtraDof);
 }
@@ -2838,7 +2838,7 @@ void TrescaDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, cons
 	q1->setRefToCurrentOutwardNormal(ipvcur->getConstRefToCurrentOutwardNormal());
 	q1->setRefToReferenceOutwardNormal(ipvcur->getConstRefToReferenceOutwardNormal());
   q1->setRefToDeformationGradient(ipvcur->getConstRefToDeformationGradient());
-  
+
   /* compute stress */
   if(!_trescaLaw->isThermomechanicallyCoupled())
   {
@@ -3166,7 +3166,7 @@ void VEVPMFHDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForc
   if(iele == NULL){
     inter=false;
   }
-  
+
   ipv = new  VEVPMFHDG3DIPVariable(hasBodyForce,inter);
 
 }
@@ -3211,7 +3211,7 @@ void VEVPMFHDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, con
     const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
     ipvprev = static_cast<const VEVPMFHDG3DIPVariable*>(ipvtmp2->getIPvBulk());
    }
-   
+
   else
   {
     ipvcur = static_cast<VEVPMFHDG3DIPVariable*>(ipv);
@@ -3839,7 +3839,7 @@ void LocalDamageHyperelasticDG3DMaterialLaw::stress(IPVariable* ipv, const IPVar
 
 
     ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);   // Is it correct ????
-    
+
 }
 
 // *********************
@@ -4537,7 +4537,7 @@ TransverseIsoYarnBDG3DMaterialLaw::TransverseIsoYarnBDG3DMaterialLaw(int lawnum,
 }
 
 
-void TransverseIsoYarnBDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, 
+void TransverseIsoYarnBDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce,
                                                       const bool* state_,
 						      const MElement *ele,
 						      const int nbFF,
@@ -4583,7 +4583,7 @@ void TransverseIsoYarnBDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool ha
 }
 
 
-void TransverseIsoYarnBDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, 
+void TransverseIsoYarnBDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce,
                                                          const MElement *ele,
 							 const int nbFF,
 							 const IntPt *GP,
@@ -4708,7 +4708,7 @@ AnisotropicDG3DMaterialLaw::AnisotropicDG3DMaterialLaw(
   double mu = _tilaw.shearModulus();
   double E = 2.*mu*(1.+nu); //Where does this come from? To Have the E corresponding to the Vmax, MUmax
 		            //In the linear & homogeneous & isotropic case ?
-  fillElasticStiffness(Ex,Ey,Ez,Vxy,Vxz,Vyz,MUxy,MUxz,MUyz,alpha,beta,gamma,elasticStiffness); 
+  fillElasticStiffness(Ex,Ey,Ez,Vxy,Vxz,Vyz,MUxy,MUxz,MUyz,alpha,beta,gamma,elasticStiffness);
 }
 AnisotropicDG3DMaterialLaw::AnisotropicDG3DMaterialLaw(const AnisotropicDG3DMaterialLaw &source) :
 								     dG3DMaterialLaw(source),
@@ -5148,10 +5148,10 @@ void ClusterDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, con
   {
     Msg::Error("this not implemented");
   }
-  
+
   static STensor3 Fn;
   Fn = ipvcur->getConstRefToDeformationGradient();
-  STensorOperation::multSTensor3(Fn,Feig,ipvcur->getRefToDeformationGradient());  
+  STensorOperation::multSTensor3(Fn,Feig,ipvcur->getRefToDeformationGradient());
   itmlaw->second->stress(ipv,ipvp,stiff,checkfrac,dTangent);
   ipvcur->getRefToDeformationGradient() = Fn;
   ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
@@ -5292,7 +5292,7 @@ void TFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsFromFiles(const
   _TFAlaw.loadClusterSummaryAndInteractionTensorsFromFiles(clusterSummaryFileName,interactionTensorsFileName);
 }
 
-void TFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+void TFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName)
 {
   _TFAlaw.loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(clusterSummaryFileName,interactionTensorsFileName);
@@ -5367,7 +5367,7 @@ void TFADG3DMaterialLaw::setClusterIncOrientation()
 
 GenericTFADG3DMaterialLaw::GenericTFADG3DMaterialLaw(const int num, double rho):
                                   dG3DMaterialLaw(num,rho,true)
-{ 
+{
   _GenericTFAlaw = new mlawGenericTFAMaterialLaws(num,rho);
   double nu = _GenericTFAlaw->poissonRatio();
   double mu = _GenericTFAlaw->shearModulus();
@@ -5384,7 +5384,7 @@ void GenericTFADG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyFor
   bool inter=true;
   const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
   if(iele==NULL) inter=false;
-  
+
   IPTFA* ipvicluster=NULL;
   _GenericTFAlaw->createIPVariable(ipvicluster, hasBodyForce, ele,nbFF_, GP, gpt);
   IPTFA* ipv1cluster=NULL;
@@ -5477,7 +5477,7 @@ void GenericTFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsFromFiles
   _GenericTFAlaw->loadClusterSummaryAndInteractionTensorsFromFiles(clusterSummaryFileName,interactionTensorsFileName);
 }
 
-void GenericTFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+void GenericTFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName)
 {
   _GenericTFAlaw->loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(clusterSummaryFileName,interactionTensorsFileName);
@@ -5566,7 +5566,7 @@ void HierarchicalTFADG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBo
   bool inter=true;
   const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
   if(iele==NULL) inter=false;
-  
+
   IPTFA2Levels* ipvicluster=NULL;
   dynamic_cast<mlawTFAHierarchicalMaterialLaws*>(_GenericTFAlaw)->createIPVariable(ipvicluster, hasBodyForce, ele,nbFF_, GP, gpt);
   IPTFA2Levels* ipv1cluster=NULL;
@@ -6398,28 +6398,28 @@ void SMPDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const b
 
 
 //===========/start/PhenomenologicalSMPDG3DMaterialLaw===================================================================================
-PhenomenologicalSMPDG3DMaterialLaw::PhenomenologicalSMPDG3DMaterialLaw(const int num, const double rho, const double alpha, const double beta, const double gamma, const double t0, 
+PhenomenologicalSMPDG3DMaterialLaw::PhenomenologicalSMPDG3DMaterialLaw(const int num, const double rho, const double alpha, const double beta, const double gamma, const double t0,
                             const double Kxg, const double Kyg, const double Kzg, const double Kxr, const double Kyr, const double Kzr,
                             const double KxAM, const double KyAM, const double KzAM,
                             const double cfG, const double cfR, const double cfAM,
-                            const double cg, const double cr, const double cAM, 
-                            const double Tm0, const double Tc0, const double xi, const double wm0, const double wc0, 
+                            const double cg, const double cr, const double cAM,
+                            const double Tm0, const double Tc0, const double xi, const double wm0, const double wc0,
                             const double alphag0, const double alphar0, const double alphaAM0, const double alphaAD0,
-                            const double Eg, const double Er,const double EAM, 
+                            const double Eg, const double Er,const double EAM,
                             const double nug, const double nur, const double nuAM,
-                            const double TaylorQuineyG,const double TaylorQuineyR, const double TaylorQuineyAM, 
+                            const double TaylorQuineyG,const double TaylorQuineyR, const double TaylorQuineyAM,
                             const double zAM): dG3DMaterialLaw (num, rho, true)
 {
-    _lawTMSMP = new mlawPhenomenologicalSMP( num, rho,alpha, beta, gamma,  t0, 
+    _lawTMSMP = new mlawPhenomenologicalSMP( num, rho,alpha, beta, gamma,  t0,
                             Kxg, Kyg, Kzg, Kxr, Kyr, Kzr,
                             KxAM, KyAM, KzAM,
                             cfG, cfR, cfAM,
-                            cg, cr, cAM, 
-                            Tm0, Tc0, xi, wm0, wc0, 
+                            cg, cr, cAM,
+                            Tm0, Tc0, xi, wm0, wc0,
                             alphag0, alphar0, alphaAM0, alphaAD0,
-                            Eg, Er,EAM, 
+                            Eg, Er,EAM,
                             nug, nur, nuAM,
-                            TaylorQuineyG,TaylorQuineyR, TaylorQuineyAM, 
+                            TaylorQuineyG,TaylorQuineyR, TaylorQuineyAM,
                             zAM);
 
     linearK               =_lawTMSMP->getInitialConductivityTensor();
@@ -6474,7 +6474,7 @@ void PhenomenologicalSMPDG3DMaterialLaw::setTcTmWcWm(const double Atc, const dou
 
 void PhenomenologicalSMPDG3DMaterialLaw::setAlphaParam
                       (const double GP, const double RP, const double ADP, const double AMP, const double GN, const double RN, const double ADN, const double AMN,
-                const double alphaGP, const double alphaRP, const double alphaADP, const double alphaAMP, 
+                const double alphaGP, const double alphaRP, const double alphaADP, const double alphaAMP,
                 const double alphaGN, const double alphaRN, const double alphaADN, const double alphaAMN)
 {_lawTMSMP->setAlphaParam(GP, RP, ADP, AMP, GN, RN, ADN, AMN,alphaGP, alphaRP, alphaADP, alphaAMP, alphaGN, alphaRN, alphaADN, alphaAMN);};
 
@@ -6641,7 +6641,7 @@ void crystalPlasticityDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool has
 
   if(ips != NULL) delete ips;
   ips = new IP3State(state_,ipvi,ipv1,ipv2);
-  _cplaw->createIPState((static_cast <crystalPlasticityDG3DIPVariable*> (ipvi))->getIPCrystalPlasticity(), 
+  _cplaw->createIPState((static_cast <crystalPlasticityDG3DIPVariable*> (ipvi))->getIPCrystalPlasticity(),
                          (static_cast <crystalPlasticityDG3DIPVariable*> (ipv1))->getIPCrystalPlasticity(),
              			 (static_cast <crystalPlasticityDG3DIPVariable*> (ipv2))->getIPCrystalPlasticity());
 
@@ -6791,7 +6791,7 @@ void gursonUMATDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyFor
 
   if(ips != NULL) delete ips;
   ips = new IP3State(state_,ipvi,ipv1,ipv2);
-  _glaw->createIPState((static_cast <gursonUMATDG3DIPVariable*> (ipvi))->getIPGursonUMAT(), 
+  _glaw->createIPState((static_cast <gursonUMATDG3DIPVariable*> (ipvi))->getIPGursonUMAT(),
                          (static_cast <gursonUMATDG3DIPVariable*> (ipv1))->getIPGursonUMAT(),
              			 (static_cast <gursonUMATDG3DIPVariable*> (ipv2))->getIPGursonUMAT());
 
@@ -8030,3 +8030,674 @@ void mlawElecSMPDG3DMaterialLaw::setMechanism2(bool mechanism2)
 };
 
 
+// NonLinearTVM Law Interface =================================================================== BEGIN
+
+// Constructor - Added Tinitial and thermal properties
+NonLinearTVMDG3DMaterialLaw::NonLinearTVMDG3DMaterialLaw(const int num, const double rho, 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)
+                        : dG3DMaterialLaw(num,rho), _viscoLaw(num,E,nu,rho,Tinitial,Alpha, KThCon, Cp, matrixbyPerturbation,pert, thermalEstimationPreviousConfig)
+{
+  fillElasticStiffness(E, nu, elasticStiffness);   // Why are some of the variables defined in this constructor?  --- WHAT??
+};
+
+// Copy Constructor - No Changes Yet
+NonLinearTVMDG3DMaterialLaw::NonLinearTVMDG3DMaterialLaw(const NonLinearTVMDG3DMaterialLaw& src):  dG3DMaterialLaw(src), _viscoLaw(src._viscoLaw){};
+
+void NonLinearTVMDG3DMaterialLaw::setStrainOrder(const int order){
+  _viscoLaw.setStrainOrder(order);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoelasticMethod(const int method){
+  _viscoLaw.setViscoelasticMethod(method);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticNumberOfElement(const int N){
+  _viscoLaw.setViscoElasticNumberOfElement(N);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui){
+  _viscoLaw.setViscoElasticData(i,Ei,taui);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  _viscoLaw.setViscoElasticData(i,Ei,taui,Alphai);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  _viscoLaw.setViscoElasticData_Bulk(i,Ki,ki);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  _viscoLaw.setViscoElasticData_Shear(i,Gi,gi);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData_Alpha(const int i, const double Alphai){
+  _viscoLaw.setViscoElasticData_Alpha(i,Alphai);
+};
+void NonLinearTVMDG3DMaterialLaw::setViscoElasticData(const std::string filename){
+  _viscoLaw.setViscoElasticData(filename);
+};
+
+void NonLinearTVMDG3DMaterialLaw::setReferenceTemperature(const double Tref){
+  _viscoLaw.setReferenceTemperature(Tref);
+};
+void NonLinearTVMDG3DMaterialLaw::setTempFuncOption(const double TemFuncOpt){           // To be discarded
+  _viscoLaw.setTempFuncOption(TemFuncOpt);
+};
+void NonLinearTVMDG3DMaterialLaw::setModelOption(const int modelFlag){
+  _viscoLaw.setModelOption(modelFlag);
+};
+void NonLinearTVMDG3DMaterialLaw::setTestOption(const int testFlag){
+  _viscoLaw.setTestOption(testFlag);
+};
+void NonLinearTVMDG3DMaterialLaw::setShiftFactorConstantsWLF(const double C1, const double C2){
+  _viscoLaw.setShiftFactorConstantsWLF(C1,C2);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_BulkModulus(Tfunc);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ShearModulus(Tfunc);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalDilationCoefficient(Tfunc);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalConductivity(Tfunc);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchShearModuli(Tfunc,i);
+};
+void NonLinearTVMDG3DMaterialLaw::setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchThermalDilationCoefficient(Tfunc,i);
+};
+
+// Added extra argument in the NonLinearTVMDG3DIPVariable contructor - Tinitial   (added from LinearThermoMech)
+void NonLinearTVMDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  // check interface element
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele==NULL) inter=false;
+  IPVariable* ipvi = new  NonLinearTVMDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);   // Why 3 times? --- WHAT??    Add getInitialTemperature in Material Law
+  IPVariable* ipv1 = new  NonLinearTVMDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv2 = new  NonLinearTVMDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void NonLinearTVMDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  if(ipv !=NULL) delete ipv;
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele == NULL){
+    inter=false;
+  }
+  ipv = new  NonLinearTVMDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+}
+
+// 2 Member Functions added from LinearThermoMechanicsDG3DMaterialLaw  --  Add these functions in the material law
+double NonLinearTVMDG3DMaterialLaw::getExtraDofStoredEnergyPerUnitField(double T) const{
+  return _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+double NonLinearTVMDG3DMaterialLaw::getInitialExtraDofStoredEnergyPerUnitField() const{
+	return _viscoLaw.getInitialExtraDofStoredEnergyPerUnitField();
+};
+
+void NonLinearTVMDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvp) const{
+ // get ipvariable
+  NonLinearTVMDG3DIPVariable* ipvcur;
+  const NonLinearTVMDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVMDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVMDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVMDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVMDG3DIPVariable*>(ipvp);
+  }
+  _viscoLaw.checkInternalState(ipvcur->getInternalData(), ipvprev->getInternalData());
+};
+
+void NonLinearTVMDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent){
+
+  // get ipvariable
+  NonLinearTVMDG3DIPVariable* ipvcur;
+  const NonLinearTVMDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVMDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVMDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVMDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVMDG3DIPVariable*>(ipvp);
+  }
+
+// Added a bunch of ip variables and derivatives from LinearThermoMechanicsDG3DMaterialLaw in dG3DMaterialLaw.cpp
+  // Current and Previous Deformation Gradient (F) and Temperature (T), Current Temp Gradient (gradT) and other current derivatives.
+     // THe new variables need to be added in the constitutive function of material law.
+  const STensor3& F1       = ipvcur->getConstRefToDeformationGradient();
+  const STensor3& F0       = ipvprev->getConstRefToDeformationGradient();
+  const double T           = ipvcur->getConstRefToTemperature();
+  const double T0          = ipvprev->getConstRefToTemperature();
+  const SVector3& gradT0   = ipvprev->getConstRefToGradT();
+  const SVector3& gradT    = ipvcur->getConstRefToGradT();
+        STensor3& dPdT     = ipvcur->getRefTodPdT();
+        SVector3& fluxT    = ipvcur->getRefToThermalFlux();
+        STensor3& dqdgradT = ipvcur->getRefTodThermalFluxdGradT();
+        SVector3& dqdT     = ipvcur->getRefTodThermalFluxdT();
+        STensor33& dqdF    = ipvcur->getRefTodThermalFluxdF();
+//const STensor3 *linearK()=ipvcur-> getConstRefTolinearK();
+
+        STensor3& P        = ipvcur->getRefToFirstPiolaKirchhoffStress();
+        STensor43& Tangent = ipvcur->getRefToTangentModuli();
+  const double& w0         = ipvprev->getConstRefToThermalSource();
+        double& w          = ipvcur->getRefToThermalSource();
+        double& dwdt       = ipvcur->getRefTodThermalSourcedField();
+        STensor3& dwdf     = ipvcur->getRefTodThermalSourcedF();
+  const SVector3& N        = ipvcur->getRefToReferenceOutwardNormal();
+  const SVector3& ujump    = ipvcur->getRefToJump()(0);
+  const double& Tjump      = ipvcur->getRefToFieldJump()(0);
+        double& Cp         = ipvcur->getRefToExtraDofFieldCapacityPerUnitField()(0);
+  const double& mechSource0 = ipvprev->getConstRefToMechanicalSource()(0);
+        double& mechSource = ipvcur->getRefToMechanicalSource()(0);
+        double& dmechSourcedt = ipvcur->getRefTodMechanicalSourcedField()(0,0);
+        STensor3& dmechSourcedf = ipvcur->getRefTodMechanicalSourcedF()[0];
+
+  // data for J2 law                  ---------------------------------------------   WHAT is J2law here?
+  IPNonLinearTVM* q1 = ipvcur->getIPNonLinearTVM();
+  const IPNonLinearTVM* q0 = ipvprev->getIPNonLinearTVM();
+  // static STensor63 dCalgdeps;
+  // STensor43& elasticL = ipvcur->getRefToElasticTangentModuli();
+
+  // Compute Stress
+  // _viscoLaw.constitutive(F0,F1,ipvcur->getRefToFirstPiolaKirchhoffStress(),q0,q1,ipvcur->getRefToTangentModuli(),stiff,NULL,dTangent,NULL);   //-- Without Thermomech Coupling
+  // _viscoLaw.constitutive(F0,F1,P,q0, q1,Tangent,T0,T, gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w,dwdt,dwdf,stiff); //LinearThermoMech mlaw
+_viscoLaw.constitutive(F0,F1,P,q0,q1,Tangent,T0,T,gradT0,gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w0,w,dwdt,dwdf,mechSource0,mechSource,dmechSourcedt,dmechSourcedf,stiff);  // FUllJ2 mlaw
+
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);  // --------------------------- WHAT does this line do?
+  ipvcur->setRefToLinearConductivity(_viscoLaw.getConductivityTensor());
+  ipvcur->setRefToStiff_alphaDilatation(_viscoLaw.getStiff_alphaDilatation());
+
+// Add the following lines here from LinearThermoMechanicsDG3DMaterialLaw ??
+        // Fracture hasn't been defined as of yet.
+/*
+   if (checkfrac==true)    // to get the H1 norm in the interface
+   q1->_fracEnergy=defoEnergy(ujump,Tjump,N);
+ else
+    q1->_elasticEnergy=defoEnergy(F1, gradT); */
+  Cp = _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);            // ---------------------------- WHAT is this line?
+
+}
+
+// defoEnergy functions from LinearThermoMechanicsDG3DMaterialLaw - add them?
+
+// NonLinearTVM Law Interface =================================================================== END
+
+
+// NonLinearTVE Law Interface =================================================================== BEGIN
+
+// Constructor - Added Tinitial and thermal properties
+NonLinearTVEDG3DMaterialLaw::NonLinearTVEDG3DMaterialLaw(const int num, const double rho, 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)
+                        : dG3DMaterialLaw(num,rho), _viscoLaw(num,E,nu,rho,0.,Tinitial,Alpha, KThCon, Cp, matrixbyPerturbation,pert, thermalEstimationPreviousConfig)
+{
+  fillElasticStiffness(E, nu, elasticStiffness);   // Why are some of the variables defined in this constructor?  --- WHAT??
+};
+
+// Copy Constructor - No Changes Yet
+NonLinearTVEDG3DMaterialLaw::NonLinearTVEDG3DMaterialLaw(const NonLinearTVEDG3DMaterialLaw& src):  dG3DMaterialLaw(src), _viscoLaw(src._viscoLaw){};
+
+void NonLinearTVEDG3DMaterialLaw::setStrainOrder(const int order){
+  _viscoLaw.setStrainOrder(order);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoelasticMethod(const int method){
+  _viscoLaw.setViscoelasticMethod(method);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticNumberOfElement(const int N){
+  _viscoLaw.setViscoElasticNumberOfElement(N);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui){
+  _viscoLaw.setViscoElasticData(i,Ei,taui);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  _viscoLaw.setViscoElasticData(i,Ei,taui,Alphai);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  _viscoLaw.setViscoElasticData_Bulk(i,Ki,ki);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  _viscoLaw.setViscoElasticData_Shear(i,Gi,gi);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData_Alpha(const int i, const double Alphai){
+  _viscoLaw.setViscoElasticData_Alpha(i,Alphai);
+};
+void NonLinearTVEDG3DMaterialLaw::setViscoElasticData(const std::string filename){
+  _viscoLaw.setViscoElasticData(filename);
+};
+
+void NonLinearTVEDG3DMaterialLaw::setReferenceTemperature(const double Tref){
+  _viscoLaw.setReferenceTemperature(Tref);
+};
+void NonLinearTVEDG3DMaterialLaw::setTempFuncOption(const double TemFuncOpt){           // To be discarded
+  _viscoLaw.setTempFuncOption(TemFuncOpt);
+};
+void NonLinearTVEDG3DMaterialLaw::setModelOption(const int modelFlag){
+  _viscoLaw.setModelOption(modelFlag);
+};
+void NonLinearTVEDG3DMaterialLaw::setTestOption(const int testFlag){
+  _viscoLaw.setTestOption(testFlag);
+};
+void NonLinearTVEDG3DMaterialLaw::setShiftFactorConstantsWLF(const double C1, const double C2){
+  _viscoLaw.setShiftFactorConstantsWLF(C1,C2);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_BulkModulus(Tfunc);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ShearModulus(Tfunc);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalDilationCoefficient(Tfunc);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalConductivity(Tfunc);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchShearModuli(Tfunc,i);
+};
+void NonLinearTVEDG3DMaterialLaw::setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchThermalDilationCoefficient(Tfunc,i);
+};
+
+// 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
+{
+  // check interface element
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele==NULL) inter=false;
+  IPVariable* ipvi = new  NonLinearTVEDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);   // Why 3 times? --- WHAT??    Add getInitialTemperature in Material Law
+  IPVariable* ipv1 = new  NonLinearTVEDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv2 = new  NonLinearTVEDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void NonLinearTVEDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  if(ipv !=NULL) delete ipv;
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele == NULL){
+    inter=false;
+  }
+  ipv = new  NonLinearTVEDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+}
+
+// 2 Member Functions added from LinearThermoMechanicsDG3DMaterialLaw  --  Add these functions in the material law
+double NonLinearTVEDG3DMaterialLaw::getExtraDofStoredEnergyPerUnitField(double T) const{
+  return _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+double NonLinearTVEDG3DMaterialLaw::getInitialExtraDofStoredEnergyPerUnitField() const{
+	return _viscoLaw.getInitialExtraDofStoredEnergyPerUnitField();
+};
+
+void NonLinearTVEDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvp) const{
+ // get ipvariable
+  NonLinearTVEDG3DIPVariable* ipvcur;
+  const NonLinearTVEDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVEDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVEDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVEDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVEDG3DIPVariable*>(ipvp);
+  }
+  _viscoLaw.checkInternalState(ipvcur->getInternalData(), ipvprev->getInternalData());
+};
+
+void NonLinearTVEDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent){
+
+  // get ipvariable
+  NonLinearTVEDG3DIPVariable* ipvcur;
+  const NonLinearTVEDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVEDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVEDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVEDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVEDG3DIPVariable*>(ipvp);
+  }
+
+// Added a bunch of ip variables and derivatives from LinearThermoMechanicsDG3DMaterialLaw in dG3DMaterialLaw.cpp
+  // Current and Previous Deformation Gradient (F) and Temperature (T), Current Temp Gradient (gradT) and other current derivatives.
+     // THe new variables need to be added in the constitutive function of material law.
+  const STensor3& F1       = ipvcur->getConstRefToDeformationGradient();
+  const STensor3& F0       = ipvprev->getConstRefToDeformationGradient();
+  const double T           = ipvcur->getConstRefToTemperature();
+  const double T0          = ipvprev->getConstRefToTemperature();
+  const SVector3& gradT0   = ipvprev->getConstRefToGradT();
+  const SVector3& gradT    = ipvcur->getConstRefToGradT();
+        STensor3& dPdT     = ipvcur->getRefTodPdT();
+        SVector3& fluxT    = ipvcur->getRefToThermalFlux();
+        STensor3& dqdgradT = ipvcur->getRefTodThermalFluxdGradT();
+        SVector3& dqdT     = ipvcur->getRefTodThermalFluxdT();
+        STensor33& dqdF    = ipvcur->getRefTodThermalFluxdF();
+//const STensor3 *linearK()=ipvcur-> getConstRefTolinearK();
+
+        STensor3& P        = ipvcur->getRefToFirstPiolaKirchhoffStress();
+        STensor43& Tangent = ipvcur->getRefToTangentModuli();
+  const double& w0         = ipvprev->getConstRefToThermalSource();
+        double& w          = ipvcur->getRefToThermalSource();
+        double& dwdt       = ipvcur->getRefTodThermalSourcedField();
+        STensor3& dwdf     = ipvcur->getRefTodThermalSourcedF();
+  const SVector3& N        = ipvcur->getRefToReferenceOutwardNormal();
+  const SVector3& ujump    = ipvcur->getRefToJump()(0);
+  const double& Tjump      = ipvcur->getRefToFieldJump()(0);
+        double& Cp         = ipvcur->getRefToExtraDofFieldCapacityPerUnitField()(0);
+  const double& mechSource0 = ipvprev->getConstRefToMechanicalSource()(0);
+        double& mechSource = ipvcur->getRefToMechanicalSource()(0);
+        double& dmechSourcedt = ipvcur->getRefTodMechanicalSourcedField()(0,0);
+        STensor3& dmechSourcedf = ipvcur->getRefTodMechanicalSourcedF()[0];
+
+  // data for J2 law                  ---------------------------------------------   WHAT is J2law here?
+  IPNonLinearTVE* q1 = ipvcur->getIPNonLinearTVE();
+  const IPNonLinearTVE* q0 = ipvprev->getIPNonLinearTVE();
+  // static STensor63 dCalgdeps;
+  // STensor43& elasticL = ipvcur->getRefToElasticTangentModuli();
+
+  // Compute Stress
+  // _viscoLaw.constitutive(F0,F1,ipvcur->getRefToFirstPiolaKirchhoffStress(),q0,q1,ipvcur->getRefToTangentModuli(),stiff,NULL,dTangent,NULL);   //-- Without Thermomech Coupling
+  // _viscoLaw.constitutive(F0,F1,P,q0, q1,Tangent,T0,T, gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w,dwdt,dwdf,stiff); //LinearThermoMech mlaw
+_viscoLaw.constitutive(F0,F1,P,q0,q1,Tangent,T0,T,gradT0,gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w,dwdt,dwdf,mechSource,dmechSourcedt,dmechSourcedf,stiff);  // FUllJ2 mlaw
+
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);  // --------------------------- WHAT does this line do?
+  ipvcur->setRefToLinearConductivity(_viscoLaw.getConductivityTensor());
+  ipvcur->setRefToStiff_alphaDilatation(_viscoLaw.getStiff_alphaDilatation());
+
+// Add the following lines here from LinearThermoMechanicsDG3DMaterialLaw ??
+        // Fracture hasn't been defined as of yet.
+/*
+   if (checkfrac==true)    // to get the H1 norm in the interface
+   q1->_fracEnergy=defoEnergy(ujump,Tjump,N);
+ else
+    q1->_elasticEnergy=defoEnergy(F1, gradT); */
+  Cp = _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);            // ---------------------------- WHAT is this line?
+
+}
+
+// defoEnergy functions from LinearThermoMechanicsDG3DMaterialLaw - add them?
+
+// NonLinearTVE Law Interface =================================================================== END
+
+
+// NonLinearTVP Law Interface =================================================================== BEGIN
+
+NonLinearTVPDG3DMaterialLaw::NonLinearTVPDG3DMaterialLaw(const int num, const double rho, const double E, const double nu, const double tol,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation, const double pert, const bool thermalEstimationPreviousConfig):
+                        dG3DMaterialLaw(num,rho), _viscoLaw(num,E,nu,rho,tol,Tinitial,Alpha, KThCon, Cp, matrixbyPerturbation,pert, thermalEstimationPreviousConfig)
+{
+  fillElasticStiffness(E, nu, elasticStiffness);   // Why are some of the variables defined in this constructor?  --- WHAT??
+};
+
+NonLinearTVPDG3DMaterialLaw::NonLinearTVPDG3DMaterialLaw(const NonLinearTVPDG3DMaterialLaw& src):  dG3DMaterialLaw(src), _viscoLaw(src._viscoLaw){};
+
+void NonLinearTVPDG3DMaterialLaw::setStrainOrder(const int order){
+  _viscoLaw.setStrainOrder(order);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoelasticMethod(const int method){
+  _viscoLaw.setViscoelasticMethod(method);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticNumberOfElement(const int N){
+  _viscoLaw.setViscoElasticNumberOfElement(N);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui){
+  _viscoLaw.setViscoElasticData(i,Ei,taui);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai){
+  _viscoLaw.setViscoElasticData(i,Ei,taui,Alphai);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  _viscoLaw.setViscoElasticData_Bulk(i,Ki,ki);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  _viscoLaw.setViscoElasticData_Shear(i,Gi,gi);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData_Alpha(const int i, const double Alphai){
+  _viscoLaw.setViscoElasticData_Alpha(i,Alphai);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscoElasticData(const std::string filename){
+  _viscoLaw.setViscoElasticData(filename);
+};
+void NonLinearTVPDG3DMaterialLaw::setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3){
+  _viscoLaw.setIsotropicHardeningCoefficients(HR1,HR2,HR3);
+};
+
+void NonLinearTVPDG3DMaterialLaw::setReferenceTemperature(const double Tref){
+  _viscoLaw.setReferenceTemperature(Tref);
+};
+void NonLinearTVPDG3DMaterialLaw::setTempFuncOption(const double TemFuncOpt){           // To be discarded
+  _viscoLaw.setTempFuncOption(TemFuncOpt);
+};
+void NonLinearTVPDG3DMaterialLaw::setModelOption(const int modelFlag){
+  _viscoLaw.setModelOption(modelFlag);
+};
+void NonLinearTVPDG3DMaterialLaw::setTestOption(const int testFlag){
+  _viscoLaw.setTestOption(testFlag);
+};
+void NonLinearTVPDG3DMaterialLaw::setShiftFactorConstantsWLF(const double C1, const double C2){
+  _viscoLaw.setShiftFactorConstantsWLF(C1,C2);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_BulkModulus(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ShearModulus(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalDilationCoefficient(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_ThermalConductivity(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_SpecificHeat(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchBulkModuli(Tfunc,i);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchShearModuli(Tfunc,i);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc, int i){
+  _viscoLaw.setTemperatureFunction_BranchThermalDilationCoefficient(Tfunc,i);
+};
+
+void NonLinearTVPDG3DMaterialLaw::setCompressionHardening(const J2IsotropicHardening& comp){
+  _viscoLaw.setCompressionHardening(comp);
+};
+void NonLinearTVPDG3DMaterialLaw::setTractionHardening(const J2IsotropicHardening& trac){
+  _viscoLaw.setTractionHardening(trac);
+};
+void NonLinearTVPDG3DMaterialLaw::setKinematicHardening(const kinematicHardening& kin){
+  _viscoLaw.setKinematicHardening(kin);
+};
+void NonLinearTVPDG3DMaterialLaw::setViscosityEffect(const viscosityLaw& v, const double p){
+  _viscoLaw.setViscosityEffect(v,p);
+};
+
+void NonLinearTVPDG3DMaterialLaw::setYieldPowerFactor(const double n){
+  _viscoLaw.setPowerFactor(n);
+};
+void NonLinearTVPDG3DMaterialLaw::nonAssociatedFlowRuleFactor(const double b){
+  _viscoLaw.nonAssociatedFlowRuleFactor(b);
+};
+void NonLinearTVPDG3DMaterialLaw::setPlasticPoissonRatio(const double nup){
+  _viscoLaw.setPlasticPoissonRatio(nup);
+};
+void NonLinearTVPDG3DMaterialLaw::setNonAssociatedFlow(const bool flag){
+  _viscoLaw.setNonAssociatedFlow(flag);
+};
+
+void NonLinearTVPDG3DMaterialLaw::setTaylorQuineyFactor(const double f){
+  _viscoLaw.setTaylorQuineyFactor(f);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_InitialYieldStress(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_Hardening(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_Hardening(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_KinematicHardening(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_KinematicHardening(Tfunc);
+};
+void NonLinearTVPDG3DMaterialLaw::setTemperatureFunction_Viscosity(const scalarFunction& Tfunc){
+  _viscoLaw.setTemperatureFunction_Viscosity(Tfunc);
+};
+
+// 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
+{
+  // check interface element
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele==NULL) inter=false;
+  IPVariable* ipvi = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);   // Why 3 times? --- WHAT??    Add getInitialTemperature in Material Law
+  IPVariable* ipv1 = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv2 = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void NonLinearTVPDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  if(ipv !=NULL) delete ipv;
+  bool inter=true;
+  const MInterfaceElement *iele = dynamic_cast<const MInterfaceElement*>(ele);
+  if(iele == NULL){
+    inter=false;
+  }
+  ipv = new  NonLinearTVPDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+}
+
+// 2 Member Functions added from LinearThermoMechanicsDG3DMaterialLaw  --  Add these functions in the material law
+double NonLinearTVPDG3DMaterialLaw::getExtraDofStoredEnergyPerUnitField(double T) const{
+  return _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+double NonLinearTVPDG3DMaterialLaw::getInitialExtraDofStoredEnergyPerUnitField() const{
+	return _viscoLaw.getInitialExtraDofStoredEnergyPerUnitField();
+};
+
+void NonLinearTVPDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvp) const{
+ // get ipvariable
+  NonLinearTVPDG3DIPVariable* ipvcur;
+  const NonLinearTVPDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvp);
+  }
+  _viscoLaw.checkInternalState(ipvcur->getInternalData(), ipvprev->getInternalData());
+};
+
+void NonLinearTVPDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent){
+
+  // get ipvariable
+  NonLinearTVPDG3DIPVariable* ipvcur;
+  const NonLinearTVPDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<NonLinearTVPDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const NonLinearTVPDG3DIPVariable*>(ipvp);
+  }
+
+// All IP Variables passed to the Constitutive function defined in mlaw
+  const STensor3& F1       = ipvcur->getConstRefToDeformationGradient();
+  const STensor3& F0       = ipvprev->getConstRefToDeformationGradient();
+  const double T           = ipvcur->getConstRefToTemperature();
+  const double T0          = ipvprev->getConstRefToTemperature();
+  const SVector3& gradT0   = ipvprev->getConstRefToGradT();
+  const SVector3& gradT    = ipvcur->getConstRefToGradT();
+        STensor3& dPdT     = ipvcur->getRefTodPdT();
+        SVector3& fluxT    = ipvcur->getRefToThermalFlux();
+        STensor3& dqdgradT = ipvcur->getRefTodThermalFluxdGradT();
+        SVector3& dqdT     = ipvcur->getRefTodThermalFluxdT();
+        STensor33& dqdF    = ipvcur->getRefTodThermalFluxdF();
+
+        STensor3& P        = ipvcur->getRefToFirstPiolaKirchhoffStress();
+        STensor43& Tangent = ipvcur->getRefToTangentModuli();
+  const double& w0         = ipvprev->getConstRefToThermalSource();
+        double& w          = ipvcur->getRefToThermalSource();
+        double& dwdt       = ipvcur->getRefTodThermalSourcedField();
+        STensor3& dwdf     = ipvcur->getRefTodThermalSourcedF();
+  const SVector3& N        = ipvcur->getRefToReferenceOutwardNormal();
+  const SVector3& ujump    = ipvcur->getRefToJump()(0);
+  const double& Tjump      = ipvcur->getRefToFieldJump()(0);
+        double& Cp         = ipvcur->getRefToExtraDofFieldCapacityPerUnitField()(0);
+  const double& mechSource0 = ipvprev->getConstRefToMechanicalSource()(0);
+        double& mechSource = ipvcur->getRefToMechanicalSource()(0);
+        double& dmechSourcedt = ipvcur->getRefTodMechanicalSourcedField()(0,0);
+        STensor3& dmechSourcedf = ipvcur->getRefTodMechanicalSourcedF()[0];
+
+  // data for J2 law
+  IPNonLinearTVP* q1 = ipvcur->getIPNonLinearTVP();
+  const IPNonLinearTVP* q0 = ipvprev->getIPNonLinearTVP();
+  // static STensor63 dCalgdeps;
+  STensor43& elasticL = ipvcur->getRefToElasticTangentModuli();
+
+  // Compute Stress
+  _viscoLaw.constitutive(F0,F1,P,q0,q1,Tangent,T0,T,gradT0,gradT,fluxT,dPdT,dqdgradT,dqdT,dqdF,w,dwdt,dwdf,mechSource,dmechSourcedt,dmechSourcedf,stiff,&elasticL);
+
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+  ipvcur->setRefToLinearConductivity(_viscoLaw.getConductivityTensor());
+  ipvcur->setRefToStiff_alphaDilatation(_viscoLaw.getStiff_alphaDilatation());
+
+  Cp = _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+// NonLinearTVP Law Interface =================================================================== END
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index c7f48703df6fff91b257e7920725584c45d48177..234321640135c11b24053a1687bf9c35e0bb1a8a 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -49,6 +49,9 @@
 #include "mlawLinearElecMagTherMech.h"
 #include "mlawLinearElecMagInductor.h"
 #include "dG3DDeepMaterialNetworks.h"
+#include "mlawNonLinearTVM.h"
+#include "mlawNonLinearTVE.h"
+#include "mlawNonLinearTVP.h"
 #endif
 #if defined(HAVE_TORCH)
 #include <torch/torch.h>
@@ -237,7 +240,7 @@ class dG3DLinearElasticAnisotropicMaterialLaw : public dG3DMaterialLaw{
 	#endif
 
 	public:
-		dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho, 
+		dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho,
 		                                        const double Ex, const double Ey, const double Ez,
                                                         const double Vxy, const double Vxz, const double Vyz,
                                                         const double MUxy, const double MUxz, const double MUyz,
@@ -277,7 +280,7 @@ class dG3DLinearElasticTriclinicMaterialLaw : public dG3DMaterialLaw{
 	#endif
 
 	public:
-		dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho, 
+		dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho,
 		                                      const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
 		                                      const double C01, const double C02, const double C03, const double C04, const double C05,
 		                                      const double C12, const double C13, const double C14, const double C15,
@@ -1434,7 +1437,7 @@ class ClusterDG3DMaterialLaw : public dG3DMaterialLaw
   void setTFAMethod(int TFAMethodNum, int dim, int correction=0, int solverType=0, int tag=1000);
   void loadClusterSummaryAndInteractionTensorsFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName);
-  void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+  void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName);
   void loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName);
 
@@ -1448,14 +1451,14 @@ class ClusterDG3DMaterialLaw : public dG3DMaterialLaw
   void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName);
   void loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName);
   void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string InteractionTensorsHomogenizedFrameELFileName);
-  
+
   void loadReferenceStiffnessFromFile(const std::string referenceStiffnessFileName);
   void loadReferenceStiffnessIsoFromFile(const std::string referenceStiffnessIsoFileName);
   void loadInteractionTensorIsoFromFile(const std::string interactionTensorsIsoFileName);
-  
+
   void setClusterIncOrientation();
   void loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName);
-  
+
   void addClusterMaterialLaw(int clusterNb, dG3DMaterialLaw* clusterLaw)
   {
     _TFAlaw.addClusterMaterialLaw(clusterNb, clusterLaw->getNonLinearSolverMaterialLaw());
@@ -1510,7 +1513,7 @@ class GenericTFADG3DMaterialLaw : public dG3DMaterialLaw
   void setTFAMethod(int TFAMethodNum, int dim, int correction=0, int solverType=0, int tag=1000);
   void loadClusterSummaryAndInteractionTensorsFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName);
-  void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+  void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName);
   void loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName);
 
@@ -1523,14 +1526,14 @@ class GenericTFADG3DMaterialLaw : public dG3DMaterialLaw
   void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName);
   void loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName);
   void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string InteractionTensorsHomogenizedFrameELFileName);
-  
+
   void loadReferenceStiffnessFromFile(const std::string referenceStiffnessFileName);
   void loadReferenceStiffnessIsoFromFile(const std::string referenceStiffnessIsoFileName);
   void loadInteractionTensorIsoFromFile(const std::string interactionTensorsIsoFileName);
-  
+
   void setClusterIncOrientation();
   void loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName);
-  
+
   void addClusterMaterialLaw(int clusterNb, dG3DMaterialLaw* clusterLaw)
   {
     _GenericTFAlaw->addClusterMaterialLaw(clusterNb, clusterLaw->getNonLinearSolverMaterialLaw());
@@ -1593,16 +1596,16 @@ class HierarchicalTFADG3DMaterialLaw : public GenericTFADG3DMaterialLaw
 {
  public:
   HierarchicalTFADG3DMaterialLaw(const int num, double rho);
-  
+
   void setTFAMethod(int TFAMethodNum, int dim, int correction=0, int solverType=0, int tag=1000);
   void setTFALawID(int tfaLawID);
-  
+
   void loadClusterSummaryAndInteractionTensorsLevel1FromFiles(const std::string clusterSummaryFileName,
                                                               const std::string interactionTensorsFileName);
 
  #ifndef SWIG
   HierarchicalTFADG3DMaterialLaw(const HierarchicalTFADG3DMaterialLaw &source): GenericTFADG3DMaterialLaw(source) {};
-  virtual ~HierarchicalTFADG3DMaterialLaw(){};  
+  virtual ~HierarchicalTFADG3DMaterialLaw(){};
   virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
   virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
   virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
@@ -2104,28 +2107,28 @@ protected:
 
 
 public:
-    PhenomenologicalSMPDG3DMaterialLaw(const int num, const double rho, const double alpha, const double beta, const double gamma, const double t0, 
+    PhenomenologicalSMPDG3DMaterialLaw(const int num, const double rho, const double alpha, const double beta, const double gamma, const double t0,
                             const double Kxg, const double Kyg, const double Kzg, const double Kxr, const double Kyr, const double Kzr,
                             const double KxAM, const double KyAM, const double KzAM,
                             const double cfG, const double cfR, const double cfAM,
-                            const double cg, const double cr, const double cAM, 
-                            const double Tm0, const double Tc0, const double xi, const double wm0, const double wc0, 
+                            const double cg, const double cr, const double cAM,
+                            const double Tm0, const double Tc0, const double xi, const double wm0, const double wc0,
                             const double alphag0, const double alphar0, const double alphaAM0, const double alphaAD0,
-                            const double Eg, const double Er,const double EAM, 
+                            const double Eg, const double Er,const double EAM,
                             const double nug, const double nur, const double nuAM,
-                            const double TaylorQuineyG,const double TaylorQuineyR, const double TaylorQuineyAM, 
+                            const double TaylorQuineyG,const double TaylorQuineyR, const double TaylorQuineyAM,
                             const double zAM);
-  
-  
+
+
 
     virtual void setStrainOrder(const int order)
     {
       _lawTMSMP->setStrainOrder(order);
     }
-    
+
     virtual void setViscoelasticMethod(const int method)
     {
-      _lawTMSMP->setViscoelasticMethod(method);     
+      _lawTMSMP->setViscoelasticMethod(method);
     }
     virtual void setViscoElasticNumberOfElementG(const int N)
     {
@@ -2186,7 +2189,7 @@ public:
     virtual void setViscoElasticDataAM(const std::string filename)
     {
       _lawTMSMP->setViscoElasticDataAM( filename);
-    }       
+    }
 
     virtual void setJ2IsotropicHardeningCompressionG(const J2IsotropicHardening& isoHard) const {
       _lawTMSMP->setJ2IsotropicHardeningCompressionG(isoHard);
@@ -2197,7 +2200,7 @@ public:
     virtual void setKinematicHardeningG(const kinematicHardening& isoHard) const {
       _lawTMSMP->setKinematicHardeningG(isoHard);
     };
-    
+
     virtual void setJ2IsotropicHardeningCompressionR(const J2IsotropicHardening& isoHard) const {
       _lawTMSMP->setJ2IsotropicHardeningCompressionR(isoHard);
     };
@@ -2207,7 +2210,7 @@ public:
     virtual void setKinematicHardeningR(const kinematicHardening& isoHard) const {
       _lawTMSMP->setKinematicHardeningR(isoHard);
     };
-    
+
     virtual void setJ2IsotropicHardeningCompressionAM(const J2IsotropicHardening& isoHard) const {
       _lawTMSMP->setJ2IsotropicHardeningCompressionAM(isoHard);
     };
@@ -2217,7 +2220,7 @@ public:
     virtual void setKinematicHardeningAM(const kinematicHardening& isoHard) const {
       _lawTMSMP->setKinematicHardeningAM(isoHard);
     };
-            
+
     virtual void setViscosityEffectG(const viscosityLaw& isoHard, const double p) const {
       _lawTMSMP->setViscosityEffectG(isoHard,p);
     };
@@ -2293,7 +2296,7 @@ public:
     virtual void setTcTmWcWm(const double Atc, const double Btm, const double Cwc, const double Dwm,
                              const double alphaAtc, const double alphaBtm, const double alphaCwc, const double alphaDwm);
     virtual void setAlphaParam(const double GP, const double RP, const double ADP, const double AMP, const double GN, const double RN, const double ADN, const double AMN,
-                const double alphaGP, const double alphaRP, const double alphaADP, const double alphaAMP, 
+                const double alphaGP, const double alphaRP, const double alphaADP, const double alphaAMP,
                 const double alphaGN, const double alphaRN, const double alphaADN, const double alphaAMN);
 
 
@@ -2772,4 +2775,275 @@ class mlawElecSMPDG3DMaterialLaw :public dG3DMaterialLaw
 #endif
 };
 
+
+// NonLinearTVM Law Interface =================================================================== BEGIN
+
+class NonLinearTVMDG3DMaterialLaw : public dG3DMaterialLaw{   // public MaterialLaw
+  #ifndef SWIG
+  protected:
+    mlawNonLinearTVM _viscoLaw;
+
+  #endif //SWIG
+  public:
+    NonLinearTVMDG3DMaterialLaw(const int num, const double rho, const double E, const double nu,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = false);
+
+    void setStrainOrder(const int order);
+    void setViscoelasticMethod(const int method);
+    void setViscoElasticNumberOfElement(const int N);
+    void setViscoElasticData(const int i, const double Ei, const double taui);
+    void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    void setViscoElasticData_Alpha(const int i, const double Alphai);
+    void setViscoElasticData(const std::string filename);
+
+    void setReferenceTemperature(const double Tref);
+    void setTempFuncOption(const double TemFuncOpt);
+    void setModelOption(const int modelFlag);
+    void setTestOption(const int testFlag);
+    void setShiftFactorConstantsWLF(const double C1, const double C2);
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc);
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc);
+    void setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i);
+
+    // For now use these Scalars - Fix by directly adding to constructor
+   /* void setThermalExpansionCoefficient(const double Alpha);   // Fix this - for both scalar and tensor
+    void setThermalConductivity(const double KthCon);     // Fix this - for both scalar and tensor
+    void setSpecificHeat(const double Cp);*/
+
+    #ifndef SWIG
+     NonLinearTVMDG3DMaterialLaw(const NonLinearTVMDG3DMaterialLaw &source);
+    virtual ~NonLinearTVMDG3DMaterialLaw(){}
+    // set the time of _j2law
+    virtual void setTime(const double t,const double dtime){
+      dG3DMaterialLaw::setTime(t,dtime);
+      _viscoLaw.setTime(t,dtime);
+    }
+    virtual materialLaw::matname getType() const {return _viscoLaw.getType();}
+    virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
+    virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}
+    virtual double soundSpeed() const{return _viscoLaw.soundSpeed();} // or change value ??
+    virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+    virtual const double bulkModulus() const {return _viscoLaw.bulkModulus();}
+    virtual double scaleFactor() const{return _viscoLaw.scaleFactor();}
+
+// Added from LinearThermoMechanicsDG3DMaterialLaw
+    virtual int getNumberOfExtraDofsDiffusion() const {return 1;}
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const;
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const;
+   // virtual double defoEnergy(const STensor3& Fn,const SVector3& gradT) const;                            // NO definition in .cpp yet
+   // virtual double defoEnergy( const SVector3&ujump,const double &Tjump, const SVector3& N) const;        // NO definition in .cpp yet
+//
+    virtual materialLaw* clone() const{return new NonLinearTVMDG3DMaterialLaw(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
+    virtual bool withEnergyDissipation() const {return _viscoLaw.withEnergyDissipation();};
+    virtual void setMacroSolver(const nonLinearMechSolver* sv){
+      dG3DMaterialLaw::setMacroSolver(sv);
+      _viscoLaw.setMacroSolver(sv);
+    };
+
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      return &_viscoLaw;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      return &_viscoLaw;
+    }
+    #endif //SWIG
+};
+
+// NonLinearTVM Law Interface =================================================================== END
+
+// NonLinearTVE Law Interface =================================================================== BEGIN
+
+class NonLinearTVEDG3DMaterialLaw : public dG3DMaterialLaw{   // public MaterialLaw
+  #ifndef SWIG
+  protected:
+    mlawNonLinearTVE _viscoLaw;
+
+  #endif //SWIG
+  public:
+    NonLinearTVEDG3DMaterialLaw(const int num, const double rho, const double E, const double nu,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = false);
+
+    void setStrainOrder(const int order);
+    void setViscoelasticMethod(const int method);
+    void setViscoElasticNumberOfElement(const int N);
+    void setViscoElasticData(const int i, const double Ei, const double taui);
+    void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    void setViscoElasticData_Alpha(const int i, const double Alphai);
+    void setViscoElasticData(const std::string filename);
+
+    void setReferenceTemperature(const double Tref);
+    void setTempFuncOption(const double TemFuncOpt);
+    void setModelOption(const int modelFlag);
+    void setTestOption(const int testFlag);
+    void setShiftFactorConstantsWLF(const double C1, const double C2);
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc);
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc);
+    void setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i);
+
+    // For now use these Scalars - Fix by directly adding to constructor
+   /* void setThermalExpansionCoefficient(const double Alpha);   // Fix this - for both scalar and tensor
+    void setThermalConductivity(const double KthCon);     // Fix this - for both scalar and tensor
+    void setSpecificHeat(const double Cp);*/
+
+    #ifndef SWIG
+     NonLinearTVEDG3DMaterialLaw(const NonLinearTVEDG3DMaterialLaw &source);
+    virtual ~NonLinearTVEDG3DMaterialLaw(){}
+    // set the time of _j2law
+    virtual void setTime(const double t,const double dtime){
+      dG3DMaterialLaw::setTime(t,dtime);
+      _viscoLaw.setTime(t,dtime);
+    }
+    virtual materialLaw::matname getType() const {return _viscoLaw.getType();}
+    virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
+    virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}
+    virtual double soundSpeed() const{return _viscoLaw.soundSpeed();} // or change value ??
+    virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+    virtual const double bulkModulus() const {return _viscoLaw.bulkModulus();}
+    virtual double scaleFactor() const{return _viscoLaw.scaleFactor();}
+
+// Added from LinearThermoMechanicsDG3DMaterialLaw
+    virtual int getNumberOfExtraDofsDiffusion() const {return 1;}
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const;
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const;
+   // virtual double defoEnergy(const STensor3& Fn,const SVector3& gradT) const;                            // NO definition in .cpp yet
+   // virtual double defoEnergy( const SVector3&ujump,const double &Tjump, const SVector3& N) const;        // NO definition in .cpp yet
+//
+    virtual materialLaw* clone() const{return new NonLinearTVEDG3DMaterialLaw(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
+    virtual bool withEnergyDissipation() const {return _viscoLaw.withEnergyDissipation();};
+    virtual void setMacroSolver(const nonLinearMechSolver* sv){
+      dG3DMaterialLaw::setMacroSolver(sv);
+      _viscoLaw.setMacroSolver(sv);
+    };
+
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      return &_viscoLaw;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      return &_viscoLaw;
+    }
+    #endif //SWIG
+};
+
+// NonLinearTVE Law Interface =================================================================== END
+
+// NonLinearTVP Law Interface =================================================================== START
+
+class NonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // public MaterialLaw
+  #ifndef SWIG
+  protected:
+    mlawNonLinearTVP _viscoLaw;
+
+  #endif //SWIG
+  public:
+    NonLinearTVPDG3DMaterialLaw(const int num, const double rho, const double E, const double nu, const double tol,
+                        const double Tinitial, const double Alpha, const double KThCon, const double Cp,
+                        const bool matrixbyPerturbation = false, const double pert = 1e-8, const bool thermalEstimationPreviousConfig = false);
+
+    void setStrainOrder(const int order);
+    void setViscoelasticMethod(const int method);
+    void setViscoElasticNumberOfElement(const int N);
+    void setViscoElasticData(const int i, const double Ei, const double taui);
+    void setViscoElasticData(const int i, const double Ei, const double taui, const double Alphai);
+    void setViscoElasticData_Bulk(const int i, const double Ki, const double ki);
+    void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    void setViscoElasticData_Alpha(const int i, const double Alphai);
+    void setViscoElasticData(const std::string filename);
+    void setIsotropicHardeningCoefficients(const double HR1, const double HR2, const double HR3);
+
+    void setReferenceTemperature(const double Tref);
+    void setTempFuncOption(const double TemFuncOpt);
+    void setModelOption(const int modelFlag);
+    void setTestOption(const int testFlag);
+    void setShiftFactorConstantsWLF(const double C1, const double C2);
+    void setTemperatureFunction_BulkModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ShearModulus(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalDilationCoefficient(const scalarFunction& Tfunc);
+    void setTemperatureFunction_ThermalConductivity(const scalarFunction& Tfunc);
+    void setTemperatureFunction_SpecificHeat(const scalarFunction& Tfunc);
+    void setTemperatureFunction_BranchBulkModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchShearModuli(const scalarFunction& Tfunc,int i);
+    void setTemperatureFunction_BranchThermalDilationCoefficient(const scalarFunction& Tfunc,int i);
+
+    void setCompressionHardening(const J2IsotropicHardening& comp);
+    void setTractionHardening(const J2IsotropicHardening& trac);
+    void setKinematicHardening(const kinematicHardening& kin);
+    void setViscosityEffect(const viscosityLaw& v, const double p);
+
+    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 setTemperatureFunction_InitialYieldStress(const scalarFunction& Tfunc);
+    void setTemperatureFunction_Hardening(const scalarFunction& Tfunc);
+    void setTemperatureFunction_KinematicHardening(const scalarFunction& Tfunc);
+    void setTemperatureFunction_Viscosity(const scalarFunction& Tfunc);
+
+    #ifndef SWIG
+     NonLinearTVPDG3DMaterialLaw(const NonLinearTVPDG3DMaterialLaw &source);
+    virtual ~NonLinearTVPDG3DMaterialLaw(){}
+    // set the time of _j2law
+    virtual void setTime(const double t,const double dtime){
+      dG3DMaterialLaw::setTime(t,dtime);
+      _viscoLaw.setTime(t,dtime);
+    }
+    virtual materialLaw::matname getType() const {return _viscoLaw.getType();}
+    virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
+    virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}
+    virtual double soundSpeed() const{return _viscoLaw.soundSpeed();} // or change value ??
+    virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+    virtual const double bulkModulus() const {return _viscoLaw.bulkModulus();}
+    virtual double scaleFactor() const{return _viscoLaw.scaleFactor();}
+
+    virtual int getNumberOfExtraDofsDiffusion() const {return 1;}
+    virtual double getExtraDofStoredEnergyPerUnitField(double T) const;
+    virtual double getInitialExtraDofStoredEnergyPerUnitField() const;
+
+    virtual materialLaw* clone() const{return new NonLinearTVPDG3DMaterialLaw(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
+    virtual bool withEnergyDissipation() const {return _viscoLaw.withEnergyDissipation();};
+    virtual void setMacroSolver(const nonLinearMechSolver* sv){
+      dG3DMaterialLaw::setMacroSolver(sv);
+      _viscoLaw.setMacroSolver(sv);
+    };
+
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      return &_viscoLaw;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      return &_viscoLaw;
+    }
+    #endif //SWIG
+};
+
+// NonLinearTVP Law Interface =================================================================== END
+
 #endif