diff --git a/NonLinearSolver/internalPoints/CMakeLists.txt b/NonLinearSolver/internalPoints/CMakeLists.txt
index 174256314067b55dc46aedc208c330c14e29b92f..9eb0f884c769a84b1c75fdf1357540bb201ec4f6 100644
--- a/NonLinearSolver/internalPoints/CMakeLists.txt
+++ b/NonLinearSolver/internalPoints/CMakeLists.txt
@@ -60,6 +60,7 @@ set(SRC
   ipNonLinearTVM.cpp
   ipNonLinearTVE.cpp
   ipNonLinearTVP.cpp
+  ipTVEMullins.cpp
 )
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.h)
diff --git a/NonLinearSolver/internalPoints/ipTVEMullins.cpp b/NonLinearSolver/internalPoints/ipTVEMullins.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ade8c119bb09e2105e7826ca2639407a1b6da206
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipTVEMullins.cpp
@@ -0,0 +1,71 @@
+//
+// 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 "ipTVEMullins.h"
+
+IPTVEMullins::IPTVEMullins(const J2IsotropicHardening* comp,
+                    const J2IsotropicHardening* trac,
+                    const kinematicHardening* kin, const int N): IPHyperViscoElastoPlastic(comp,trac,kin,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.){
+};
+
+IPTVEMullins::IPTVEMullins(const IPTVEMullins& src): IPHyperViscoElastoPlastic(src),
+            _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),
+            _thermalEnergy(src._thermalEnergy),
+            _dtShift(src._dtShift),_DdtShiftDT(src._DdtShiftDT),_DDdtShiftDDT(src._DDdtShiftDDT){};
+
+IPTVEMullins& IPTVEMullins::operator=(const IPVariable& src)
+{
+  IPHyperViscoElastoPlastic::operator=(src);
+  const IPTVEMullins* psrc = dynamic_cast<const IPTVEMullins*>(&src);
+  if(psrc != NULL)
+  {
+    _T = psrc->_T;
+    _mechSrcTVE = psrc->_mechSrcTVE;
+    _DmechSrcTVEdT = psrc->_DmechSrcTVEdT;
+    _DmechSrcTVEdF = psrc->_DmechSrcTVEdF;
+    _devDE = psrc->_devDE;
+    _trDE = psrc->_trDE;
+    _DE = psrc->_DE;
+    _DcorKirDT = psrc->_DcorKirDT;
+    _DDcorKirDTT = psrc->_DDcorKirDTT;
+    _thermalEnergy = psrc->_thermalEnergy;
+    _dtShift = psrc->_dtShift;
+    _DdtShiftDT = psrc->_DdtShiftDT;
+    _DDdtShiftDDT = psrc->_DDdtShiftDDT;
+  }
+  return *this;
+}
+
+double IPTVEMullins::defoEnergy() const
+{
+  return IPHyperViscoElastic::defoEnergy();
+}
+
+void IPTVEMullins::restart(){
+  IPHyperViscoElastoPlastic::restart();
+  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(_thermalEnergy);
+  restartManager::restart(_dtShift);
+  restartManager::restart(_DdtShiftDT);
+  restartManager::restart(_DDdtShiftDDT);
+}
diff --git a/NonLinearSolver/internalPoints/ipTVEMullins.h b/NonLinearSolver/internalPoints/ipTVEMullins.h
new file mode 100644
index 0000000000000000000000000000000000000000..f8c8dc019b09ad19ed0f55bc9615482c46b0471d
--- /dev/null
+++ b/NonLinearSolver/internalPoints/ipTVEMullins.h
@@ -0,0 +1,88 @@
+//
+// 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 IPTVEMULLINS_H_
+#define IPTVEMULLINS_H_
+#include "ipHyperelastic.h"
+#include "j2IsotropicHardening.h"
+#include "kinematicHardening.h"
+#include "STensor3.h"
+#include "STensor43.h"
+
+
+class IPTVEMullins : public IPHyperViscoElastoPlastic{
+    public:
+        // Temperature history
+        double _thermalEnergy;                                                                                                             
+        double _T;
+        //  double _fracEnergy;
+        STensor3 _devDE;
+        double _trDE;
+        STensor3 _DE;
+        double _mechSrcTVE;
+        double _DmechSrcTVEdT;
+        STensor3 _DmechSrcTVEdF;
+
+        // DcorKirDT
+        STensor3 _DcorKirDT;
+        STensor3 _DDcorKirDTT;
+
+        // Additional Internal Variables
+
+        // Additional variables
+        double _dtShift;
+        double _DdtShiftDT;
+        double _DDdtShiftDDT;
+
+    public:
+        IPTVEMullins(const J2IsotropicHardening* comp,
+                    const J2IsotropicHardening* trac,
+                    const kinematicHardening* kin, const int N);
+        IPTVEMullins(const IPTVEMullins& src);
+        virtual IPTVEMullins& operator=(const IPVariable& src);
+        virtual ~IPTVEMullins(){};
+
+        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 IPTVEMullins(*this);};
+        virtual void restart();
+};
+#endif // IPTVEMullins.h
diff --git a/NonLinearSolver/materialLaw/CMakeLists.txt b/NonLinearSolver/materialLaw/CMakeLists.txt
index 9da69791fd17edb91f649091ca268300272dc4f0..fdaa8c6db8e82fe50053ebf374eb23b22f5a9add 100644
--- a/NonLinearSolver/materialLaw/CMakeLists.txt
+++ b/NonLinearSolver/materialLaw/CMakeLists.txt
@@ -99,6 +99,7 @@ set(SRC
   mlawNonLinearTVM.cpp
   mlawNonLinearTVE.cpp
   mlawNonLinearTVP.cpp
+  mlawTVEMullins.cpp
   #  src/op_eshelby.cpp
    # Headers without cpp change this ??
   ID.h
diff --git a/NonLinearSolver/materialLaw/mlawTVEMullins.cpp b/NonLinearSolver/materialLaw/mlawTVEMullins.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..80902fcaaed42063be57fa78d2ee7fb2066d66be
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawTVEMullins.cpp
@@ -0,0 +1,1088 @@
+//
+// 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 "mlawTVEMullins.h"
+
+// Constructor
+mlawTVEMullins::mlawTVEMullins(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){
+
+  _G = _mu;
+
+  _Tref = 298.;
+  _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
+mlawTVEMullins::mlawTVEMullins(const mlawTVEMullins& src): mlawPowerYieldHyper(src),
+      _Tinitial(src._Tinitial),_scalarAlpha(src._scalarAlpha),_scalarK(src._scalarK),_Cp(src._Cp),
+      _thermalEstimationPreviousConfig(src._thermalEstimationPreviousConfig){
+
+  _G = src._G;
+  _Tref = src._Tref;
+  _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();}
+};
+
+
+mlawTVEMullins& mlawTVEMullins::operator=(const materialLaw& source){
+
+  mlawPowerYieldHyper::operator=(source);
+  const mlawTVEMullins* src =dynamic_cast<const mlawTVEMullins*>(&source);
+  if(src != NULL){
+
+    _Tinitial = src->_Tinitial; _scalarAlpha = src->_scalarAlpha; _scalarK = src->_scalarK; _Cp = src->_Cp;
+    _thermalEstimationPreviousConfig = src->_thermalEstimationPreviousConfig;
+
+    _G = src->_G;
+    _Tref = src->_Tref;
+    _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();}
+  }
+  return *this;
+}
+
+mlawTVEMullins::~mlawTVEMullins(){ 
+    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;
+};
+
+void mlawTVEMullins::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();
+
+  _Ki.resize(_N,0.);
+  _ki.resize(_N,0.);
+  _Gi.resize(_N,0.);
+  _gi.resize(_N,0.);
+};
+
+void mlawTVEMullins::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));
+
+    Msg::Info("setting: element=%d Ki= %e ki= %e, Gi= %e, gi= %e",i-1,KK,taui,GG,taui);
+  }
+};
+
+void mlawTVEMullins::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;
+    // Msg::Info("setting: element=%d Ki = %e ki = %e, ",i-1,Ki,ki);
+  }
+};
+
+void mlawTVEMullins::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;
+    // Msg::Info("setting: element=%d Gi = %e gi = %e, ",i-1,Gi,gi);
+  }
+};
+
+void mlawTVEMullins::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 mlawTVEMullins::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;
+}
+
+double mlawTVEMullins::freeEnergyMechanical(const IPTVEMullins& 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; KiT.resize(_N,0.); GiT.resize(_N,0.);
+        KiT = _Ki;
+        GiT = _Gi;
+
+        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;
+
+            Psy_mech += KiT[i]*0.5*(trEe-trGamma)*(trEe-trGamma) + GiT[i]*STensorOperation::doubledot(devEebranch,devEebranch);
+        }
+    }
+
+    return Psy_mech;
+}
+
+void mlawTVEMullins::corKirInfinity(const STensor3& devEe,  const double& trEe, const double T0, const double T, STensor3& CorKirDevInf, double& CorKirTrInf) const{
+
+}
+
+void mlawTVEMullins::getTVEdCorKirDT(const IPTVEMullins *q0, IPTVEMullins *q1, const double& T0, const double& T) const{
+
+}
+
+void mlawTVEMullins::getMechSourceTVE(const IPTVEMullins *q0, IPTVEMullins *q1, const double& T0, const double& T,
+                                        const double& DKDTsum, const double& DGDTsum, const STensor43& DEeDFe,
+                                        double *Wm, STensor3 *dWmdF, double *dWmdT) const{
+
+};
+
+void mlawTVEMullins::ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPTVEMullins *q0, IPTVEMullins *q1,
+          double& Ke, double& Ge,
+          const double T0, const double T1, const bool calculateStress) const{
+
+
+    // 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);
+
+    // Get corKirInfinity
+    static double CorKirTrInf;
+    static STensor3 CorKirDevInf;
+    corKirInfinity(devEe,trEe,T0,T1,CorKirDevInf,CorKirTrInf);
+
+    // Initialise CorKirStress - Dev
+    static STensor3 devK;
+    devK = CorKirDevInf;
+
+    // Initialise CorKirStress - Tr
+    static double p;
+    p = CorKirTrInf;
+
+    // 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, 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.);
+
+
+        // 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);
+
+            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 (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);
+
+
+                    // 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));
+                }
+            }
+
+            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.);
+
+            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;
+
+
+            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]);
+            
+            p += trOi[i];
+        }
+    }
+
+    if (calculateStress){
+        q1->_kirchhoff = devK;
+        q1->_kirchhoff(0,0) += p;
+        q1->_kirchhoff(1,1) += p;
+        q1->_kirchhoff(2,2) += p;
+    }
+
+}
+
+void mlawTVEMullins::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 mlawTVEMullins::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 IPTVEMullins *q0=dynamic_cast<const IPTVEMullins *>(q0i);
+  IPTVEMullins *q1 = dynamic_cast<IPTVEMullins *>(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("mlawTVEMullins 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 mlawTVEMullins::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 IPTVEMullins *q0 = dynamic_cast<const IPTVEMullins *>(q0i);
+        IPTVEMullins *q1 = dynamic_cast<IPTVEMullins *>(q1i);
+  if(elasticTangent!=NULL) Msg::Error("mlawTVECaruthers 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 IPTVEMullins 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 mlawTVEMullins::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 IPTVEMullins *q0,                       // array of initial internal variables
+                                              IPTVEMullins *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 mlawTVEMullins::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 IPTVEMullins *q0,                       // array of initial internal variables
+                                              IPTVEMullins *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);
+
+    // Get time step
+    double dt = this->getTimeStep();
+
+    // Make Identity Tensors
+    static const STensor3 I3(1.);
+    static const STensor43 I4(1.,1.);
+
+    // 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, 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.);
+
+        getKi(KiT,T_set,&DKiDT,&DDKiDT); getGi(GiT,T_set,&DGiDT,&DDGiDT); 
+
+        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);
+
+            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 mlawTVEMullins::soundSpeed() const {   // Correct this for current temperature
+    return sqrt((_K+4.*_G/3.)/_rho);
+}
diff --git a/NonLinearSolver/materialLaw/mlawTVEMullins.h b/NonLinearSolver/materialLaw/mlawTVEMullins.h
new file mode 100644
index 0000000000000000000000000000000000000000..195b9c7dd20b96ce21d7161ef234e775bd1b3682
--- /dev/null
+++ b/NonLinearSolver/materialLaw/mlawTVEMullins.h
@@ -0,0 +1,291 @@
+//
+// 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) 2023;
+//
+// Copyright: See COPYING file that comes with this distribution
+//
+//
+#ifndef MLAWTVEMULLINS_H_
+#define MLAWTVEMULLINS_H_
+
+#include "mlaw.h"
+#include "STensor3.h"
+#include "STensor43.h"
+#include "STensor63.h"
+#include "ipTVEMullins.h"
+#include "viscosityLaw.h"
+#include "mlawHyperelasticFailureCriterion.h"
+#include "scalarFunction.h"
+#include "mlawHyperelastic.h"
+
+class mlawTVEMullins : public mlawPowerYieldHyper{
+  protected:
+
+    // Material Properties at Room Temp. - Mechanical
+    double _G;          // 2nd Lame parameter (=mu) Shear 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)
+    
+    // Misc.
+    bool _thermalEstimationPreviousConfig;  // flap for thermalEstimation using PreviousConfig
+    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.
+    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
+
+    // Scalars - Additional constants
+    std::vector<double> nKi;            // branch free energy scalars
+    std::vector<double> nGi;            // 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 double freeEnergyMechanical(const IPTVEMullins& q, const double Tc) const ;
+
+    void corKirInfinity(const STensor3& devEe, const double& trEe, const double T0, const double T, STensor3& CorKirDevInf, double& CorKirTrInf) const;
+
+    void ThermoViscoElasticPredictor(const STensor3& Ee, const STensor3& Ee0,
+          const IPTVEMullins *q0, IPTVEMullins *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 IPTVEMullins *q0, IPTVEMullins *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 IPTVEMullins *q0, IPTVEMullins *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 IPTVEMullins *q0,                       // array of initial internal variables
+                                              IPTVEMullins *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 IPTVEMullins *q0,                       // array of initial internal variables
+                                              IPTVEMullins *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:
+    mlawTVEMullins(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
+    mlawTVEMullins(const mlawTVEMullins& src);
+
+    // Operator Assignment
+    mlawTVEMullins& operator=(const materialLaw& source);
+
+    // Virtual Destructor
+    virtual ~mlawTVEMullins();
+
+    // 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_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);
+
+    // 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;};
+    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();
+    }
+
+#ifndef SWIG
+
+    // Const Functions to get temp-updated values of material properties - Args by reference, or return the variable.
+
+    virtual std::vector<double> get_nKi(const double _K, const std::vector<double> _Ki) const{
+        std::vector<double> nKi;
+        nKi.resize(_N,0.);
+        for (int i=0; i<_Ki.size();i++){
+            nKi[i] = _Ki[i]/_K;
+        }
+        return nKi;
+    }
+        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);
+        }
+    }
+
+    // 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("mlawTVEMullins::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 mlawTVEMullins(*this);};
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+    #endif // SWIG
+};
+#endif //mlawTVECaruthers
diff --git a/dG3D/src/dG3DIPVariable.cpp b/dG3D/src/dG3DIPVariable.cpp
index 0eb550cf7ffa2c71c697315d8dd003095ce25680..8be63c8954866dd0799ea42d9642fbf4398b759d 100644
--- a/dG3D/src/dG3DIPVariable.cpp
+++ b/dG3D/src/dG3DIPVariable.cpp
@@ -5435,3 +5435,152 @@ void NonLinearTVPDG3DIPVariable::restart(){
 }
 
 // NonLinearTVP Law Interface =================================================================== END
+
+// TVEMullins Law Interface =================================================================== BEGIN
+
+// 1) Constructor Changed
+TVEMullinsDG3DIPVariable::TVEMullinsDG3DIPVariable(const mlawTVEMullins& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter) :
+              ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter){
+  _ipViscoElastic = new IPTVEMullins(viscoLaw.getConstRefToCompressionHardening(),
+                                       viscoLaw.getConstRefToTractionHardening(),
+                                       viscoLaw.getConstRefToKinematicHardening(),
+                                       viscoLaw.getViscoElasticNumberOfElement());
+  this->getRefToTemperature()=Tinitial;
+};
+
+// 2) Copy Constructor Changed
+TVEMullinsDG3DIPVariable::TVEMullinsDG3DIPVariable(const TVEMullinsDG3DIPVariable& src) :
+              ThermoMechanicsDG3DIPVariableBase(src), _ipViscoElastic(src._ipViscoElastic){
+  _ipViscoElastic = NULL;
+  if (src._ipViscoElastic != NULL){
+    _ipViscoElastic = dynamic_cast<IPTVECaruthers*>(src._ipViscoElastic->clone());
+  }
+};
+
+// 3) Operator Assignment Changed
+TVEMullinsDG3DIPVariable& TVEMullinsDG3DIPVariable::operator = (const IPVariable& src){
+  ThermoMechanicsDG3DIPVariableBase::operator =(src);
+  const TVEMullinsDG3DIPVariable* psrc = dynamic_cast<const TVEMullinsDG3DIPVariable*>(&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
+TVEMullinsDG3DIPVariable::~TVEMullinsDG3DIPVariable(){
+  if (_ipViscoElastic){delete _ipViscoElastic; _ipViscoElastic=NULL;};
+};
+
+// 5) Member Function - get(i) - Changed - Refer to HyperVisco...DG3DIP for the Original
+double TVEMullinsDG3DIPVariable::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  TVEMullinsDG3DIPVariable::defoEnergy() const{
+  return _ipViscoElastic->defoEnergy();
+}
+
+double TVEMullinsDG3DIPVariable::plasticEnergy() const{
+  return getIPTVECaruthers()->plasticEnergy();
+}
+
+// 7) Other Member Functions - damageEnergy(), etc, may have to be added later.
+
+// 8) Member Function - restart() - Changed only 2nd line
+void TVEMullinsDG3DIPVariable::restart(){
+// dG3DIPVariable::restart();
+  ThermoMechanicsDG3DIPVariableBase::restart();
+  restartManager::restart(_ipViscoElastic);
+  return;
+}
+
+// TVEMullins Law Interface =================================================================== END
diff --git a/dG3D/src/dG3DIPVariable.h b/dG3D/src/dG3DIPVariable.h
index 016efa98814b6fc3917c75e598fb7a560cd2ddc0..b16f5aadea83b08f8184d2145112071018b301e9 100644
--- a/dG3D/src/dG3DIPVariable.h
+++ b/dG3D/src/dG3DIPVariable.h
@@ -67,6 +67,8 @@
 #include "mlawNonLinearTVE.h"
 #include "ipNonLinearTVP.h"
 #include "mlawNonLinearTVP.h"
+#include "ipTVEMullins.h"
+#include "mlawTVEMullins.h"
 
 #if defined(HAVE_TORCH)
 #include <torch/torch.h>
@@ -5180,4 +5182,56 @@ class NonLinearTVPDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   /
 
 // NonLinearTVP Law Interface =================================================================== END
 
-#endif
+// TVECaruthers Law Interface =================================================================== BEGIN
+
+class TVEMullinsDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   // Changed
+
+  protected:
+    IPTVEMullins * _ipViscoElastic;
+    TVEMullinsDG3DIPVariable(const bool createBodyForceHO, const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter) {
+        Msg::Error("TVEMullinssDG3DIPVariable: Cannot use the default constructor of ThermoMechanicsDG3DIPVariableBase");}
+
+  public:
+    TVEMullinsDG3DIPVariable(const mlawTVEMullins& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter);  // Changed
+    TVEMullinsDG3DIPVariable(const TVEMullinsDG3DIPVariable& src);
+    virtual TVEMullinsDG3DIPVariable& operator = (const IPVariable& src);
+    virtual ~TVEMullinsDG3DIPVariable();
+
+    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
+    IPTVEMullins* getIPTVEMullins() {return _ipViscoElastic;};
+    const IPTVEMullins* getIPTVEMullins() 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 TVEMullinsDG3DIPVariable(*this);};
+    virtual void restart();
+};
+
+// TVEMullins Law Interface =================================================================== END
+
+#endif //DG3DIPVARIABLE
+
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index f6e6feb02ad0ac2500bc13b7e3dedd4bb4bab07c..8a080ad7c0571a74c0b7db8d285d2c5864f4b0cb 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -8720,3 +8720,175 @@ void NonLinearTVPDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp
 }
 
 // NonLinearTVP Law Interface =================================================================== END
+
+
+// TVEMullins Law Interface =================================================================== BEGIN
+
+TVEMullinsDG3DMaterialLaw::TVEMullinsDG3DMaterialLaw(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);  
+};
+
+TVEMullinsDG3DMaterialLaw::TVEMullinsDG3DMaterialLaw(const TVEMullinsDG3DMaterialLaw& src):  dG3DMaterialLaw(src), _viscoLaw(src._viscoLaw){};
+
+void TVEMullinsDG3DMaterialLaw::setStrainOrder(const int order){
+  _viscoLaw.setStrainOrder(order);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoelasticMethod(const int method){
+  _viscoLaw.setViscoelasticMethod(method);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoElasticNumberOfElement(const int N){
+  _viscoLaw.setViscoElasticNumberOfElement(N);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoElasticData(const int i, const double Ei, const double taui){
+  _viscoLaw.setViscoElasticData(i,Ei,taui);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoElasticData_Bulk(const int i, const double Ki, const double ki){
+  _viscoLaw.setViscoElasticData_Bulk(i,Ki,ki);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoElasticData_Shear(const int i, const double Gi, const double gi){
+  _viscoLaw.setViscoElasticData_Shear(i,Gi,gi);
+};
+void TVEMullinsDG3DMaterialLaw::setViscoElasticData(const std::string filename){
+  _viscoLaw.setViscoElasticData(filename);
+};
+
+void TVEMullinsDG3DMaterialLaw::setReferenceTemperature(const double Tref){
+  _viscoLaw.setReferenceTemperature(Tref);
+};
+void TVEMullinsDG3DMaterialLaw::setShiftFactorConstantsWLF(const double C1, const double C2){
+  _viscoLaw.setShiftFactorConstantsWLF(C1,C2);
+};
+
+// Added extra argument in the NonLinearTVEDG3DIPVariable contructor - Tinitial   (added from LinearThermoMech)
+void TVEMullinsDG3DMaterialLaw::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  TVEMullinsDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv1 = new  TVEMullinsDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  IPVariable* ipv2 = new  TVEMullinsDG3DIPVariable(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void TVEMullinsDG3DMaterialLaw::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  TVEMullinsDG3DMaterialLaw(_viscoLaw,_viscoLaw.getInitialTemperature(),hasBodyForce,inter);
+}
+
+double TVEMullinsDG3DMaterialLaw::getExtraDofStoredEnergyPerUnitField(double T) const{
+  return _viscoLaw.getExtraDofStoredEnergyPerUnitField(T);
+}
+
+double TVEMullinsDG3DMaterialLaw::getInitialExtraDofStoredEnergyPerUnitField() const{
+	return _viscoLaw.getInitialExtraDofStoredEnergyPerUnitField();
+};
+
+void TVEMullinsDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvp) const{
+ // get ipvariable
+  TVEMullinsDG3DIPVariable* ipvcur;
+  const TVEMullinsDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<TVEMullinsDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const TVEMullinsDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<TVEMullinsDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const TVEMullinsDG3DIPVariable*>(ipvp);
+  }
+  _viscoLaw.checkInternalState(ipvcur->getInternalData(), ipvprev->getInternalData());
+};
+
+void TVEMullinsDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent){
+
+  // get ipvariable
+  TVEMullinsDG3DIPVariable* ipvcur;
+  const TVEMullinsDG3DIPVariable* ipvprev;
+  FractureCohesive3DIPVariable* ipvtmp = dynamic_cast<FractureCohesive3DIPVariable*>(ipv);
+  if(ipvtmp !=NULL)
+  {
+    ipvcur = static_cast<TVEMullinsDG3DIPVariable*>(ipvtmp->getIPvBulk());
+    const FractureCohesive3DIPVariable *ipvtmp2 = static_cast<const FractureCohesive3DIPVariable*>(ipvp);
+    ipvprev = static_cast<const TVEMullinsDG3DIPVariable*>(ipvtmp2->getIPvBulk());
+  }
+  else
+  {
+    ipvcur = static_cast<TVEMullinsDG3DIPVariable*>(ipv);
+    ipvprev = static_cast<const TVEMullinsDG3DIPVariable*>(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?
+  IPTVEMullins* q1 = ipvcur->getTVEMullins();
+  const IPTVEMullins* q0 = ipvprev->getTVEMullins();
+  // 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); 
+
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+  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);
+
+}
+
+// defoEnergy functions from LinearThermoMechanicsDG3DMaterialLaw - add them?
+
+// TVEMullins Law Interface =================================================================== END
+
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index 4e0e4a9ec9d229b933c3dc6f1c81607356c9ee75..6b2fd2919534ab24b01f4a25e5c457e53528895f 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -52,6 +52,7 @@
 #include "mlawNonLinearTVM.h"
 #include "mlawNonLinearTVE.h"
 #include "mlawNonLinearTVP.h"
+#include "mlawTVEMullins.h"
 #endif
 #if defined(HAVE_TORCH)
 #include <torch/torch.h>
@@ -3048,4 +3049,79 @@ class NonLinearTVPDG3DMaterialLaw : public dG3DMaterialLaw{   // public Material
 
 // NonLinearTVP Law Interface =================================================================== END
 
+// TVEMullins Law Interface =================================================================== BEGIN
+
+class TVEMullinsDG3DMaterialLaw : public dG3DMaterialLaw{   // public MaterialLaw
+  #ifndef SWIG
+  protected:
+    mlawTVEMullins _viscoLaw;
+
+  #endif //SWIG
+  public:
+    TVEMullinsDG3DMaterialLaw(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_Bulk(const int i, const double Ki, const double ki);
+    void setViscoElasticData_Shear(const int i, const double Gi, const double gi);
+    void setViscoElasticData(const std::string filename);
+
+    void setReferenceTemperature(const double Tref);
+    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);
+
+    #ifndef SWIG
+     TVEMullinsDG3DMaterialLaw(const TVEMullinsDG3DMaterialLaw &source);
+    virtual ~TVEMullinsDG3DMaterialLaw(){}
+    // 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 TVEMullinsDG3DMaterialLaw(*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
+};
+
+// TVEMullins Law Interface =================================================================== END
+
 #endif