diff --git a/NonLinearSolver/internalPoints/ipField.cpp b/NonLinearSolver/internalPoints/ipField.cpp
index 299bcd77e153502a1352b8948963c05ae7e5eaec..922e0fdd50d563c98d63c07ee68fd0e32a3ea7f4 100644
--- a/NonLinearSolver/internalPoints/ipField.cpp
+++ b/NonLinearSolver/internalPoints/ipField.cpp
@@ -691,7 +691,10 @@ std::string IPField::ToString(const int i){
   else if (i == TEMPERATURE) return "TEMPERATURE";
   else if (i == THERMALFLUX_X) return "THERMALFLUX_X";
   else if (i == THERMALFLUX_Y) return "THERMALFLUX_Y";
-  else if (i == THERMALFLUX_Z) return "THERMALFLUX_Z";
+  else if (i == THERMALFLUX_Z) return "THERMALFLUX_Z"; 
+  else if (i == TEMP_GRAD_X) return "TEMP_GRAD_X";
+  else if (i == TEMP_GRAD_Y) return "TEMP_GRAD_Y";
+  else if (i == TEMP_GRAD_Z) return "TEMP_GRAD_Z";
   else if (i == THERMALSOURCE) return "THERMALSOURCE";
   else if (i == VOLTAGE) return "VOLTAGE";
   else if (i == ELECTRICALFLUX_X) return "ELECTRICALFLUX_X";
diff --git a/NonLinearSolver/internalPoints/ipField.h b/NonLinearSolver/internalPoints/ipField.h
index 2065f0f4a20c132d9d133decffd1f297fea0bbb4..c19e5143813beb01aab955ba95b145b295ea7bb4 100644
--- a/NonLinearSolver/internalPoints/ipField.h
+++ b/NonLinearSolver/internalPoints/ipField.h
@@ -260,7 +260,7 @@ class IPField : public elementsField {
                     ISO_YIELD,ISO_YIELD_TENSILE, ISO_YIELD_COMPRESSION, ISO_YIELD_SHEAR,KIN_YIELD,
                     MTX_SVM,MTX_SIG_XX,MTX_SIG_YY,MTX_SIG_ZZ,MTX_SIG_XY,MTX_SIG_YZ,MTX_SIG_XZ,
                     INC_SVM,INC_SIG_XX,INC_SIG_YY,INC_SIG_ZZ,INC_SIG_XY,INC_SIG_YZ,INC_SIG_XZ,
-                    TEMPERATURE,THERMALFLUX_X,THERMALFLUX_Y,THERMALFLUX_Z,THERMALSOURCE,
+                    TEMPERATURE,THERMALFLUX_X,THERMALFLUX_Y,THERMALFLUX_Z,THERMALSOURCE,TEMP_GRAD_X,TEMP_GRAD_Y,TEMP_GRAD_Z,
                     VOLTAGE,ELECTRICALFLUX_X,ELECTRICALFLUX_Y,ELECTRICALFLUX_Z,ELECTRICALSOURCE,
                     LOCAL_POROSITY, NONLOCAL_POROSITY, CORRECTED_POROSITY, YIELD_POROSITY,
                     NUCLEATED_POROSITY_TOT, NUCLEATED_POROSITY_0, NUCLEATED_POROSITY_1, NUCLEATED_POROSITY_2,
diff --git a/NonLinearSolver/internalPoints/ipFiniteStrain.h b/NonLinearSolver/internalPoints/ipFiniteStrain.h
index b5dc338a7f95c3b9a5f6a507ab411a514f91db6e..a09d0cc1781e4ca43f3bd5cfc75819a37536b110 100644
--- a/NonLinearSolver/internalPoints/ipFiniteStrain.h
+++ b/NonLinearSolver/internalPoints/ipFiniteStrain.h
@@ -76,6 +76,59 @@ class ipFiniteStrain : public IPVariableMechanics{
     virtual const SVector3 &getConstRefToJump() const=0;
     virtual SVector3 &getRefToJump()=0;
 
+    // FLE
+    //extraDof
+    virtual int getNumConstitutiveExtraDofDiffusionVariable() const=0;
+    virtual double getConstRefToField(const int idex) const=0;
+    virtual double  &getRefToField(const int idex)=0;
+    virtual const std::vector<SVector3>  &getConstRefToGradField() const=0;
+    virtual std::vector<SVector3>  &getRefToGradField()=0;
+    virtual const std::vector<SVector3>  &getConstRefToFlux() const=0;
+    virtual std::vector<SVector3>  &getRefToFlux()=0;
+
+    virtual const std::vector<STensor3>  &getConstRefTodPdField() const=0;
+    virtual std::vector<STensor3>  &getRefTodPdField()=0;
+    virtual const std::vector<STensor33>  &getConstRefTodPdGradField() const=0;
+    virtual std::vector<STensor33>  &getRefTodPdGradField()=0;
+    virtual const std::vector<std::vector<STensor3> >  &getConstRefTodFluxdGradField() const=0;
+    virtual std::vector<std::vector<STensor3> >  &getRefTodFluxdGradField()=0;
+    virtual const std::vector<std::vector<SVector3> >  &getConstRefTodFluxdField() const=0;
+    virtual std::vector<std::vector<SVector3> >  &getRefTodFluxdField()=0;
+    virtual const std::vector<STensor33>  &getConstRefTodFluxdF() const=0;
+    virtual std::vector<STensor33>   &getRefTodFluxdF()=0;
+
+    virtual const std::vector<std::vector<const STensor3*> > &getConstRefToLinearK() const =0;
+    virtual void setConstRefToLinearK(const STensor3 &eT, int i, int j) =0;
+    virtual const std::vector<std::vector<std::vector<STensor3> > >  &getConstRefTodLinearKdField() const=0;
+    virtual std::vector<std::vector<std::vector<STensor3> > >  &getRefTodLinearKdField()=0;
+    virtual const std::vector< std::vector<STensor43> >  &getConstRefTodLinearKdF() const=0;
+    virtual std::vector< std::vector<STensor43> >  &getRefTodLinearKdF()=0;
+
+    virtual const std::vector< std::vector<STensor43> >  &getConstRefTodFluxdGradFielddF() const=0;
+    virtual std::vector<std::vector<STensor43> >  &getRefTodFluxdGradFielddF()=0;
+    virtual const std::vector<std::vector<std::vector<STensor3> > >  &getConstRefTodFluxdGradFielddField() const=0;
+    virtual std::vector<std::vector<std::vector<STensor3> > >  &getRefTodFluxdGradFielddField()=0;
+    virtual const fullVector<double>  &getConstRefToFieldSource() const=0;
+    virtual fullVector<double>  &getRefToFieldSource()=0;
+    virtual const fullMatrix<double>  &getConstRefTodFieldSourcedField() const=0;
+    virtual fullMatrix<double>  &getRefTodFieldSourcedField()=0;
+    virtual const std::vector<std::vector<SVector3> >  &getConstRefTodFieldSourcedGradField() const=0;
+    virtual std::vector<std::vector<SVector3> >  &getRefTodFieldSourcedGradField()=0;
+    virtual const std::vector<STensor3>  &getConstRefTodFieldSourcedF() const=0;
+    virtual std::vector<STensor3>  &getRefTodFieldSourcedF()=0;
+    virtual const fullVector<double>  &getConstRefToMechanicalSource() const=0;
+    virtual fullVector<double>  &getRefToMechanicalSource()=0;
+    virtual const fullMatrix<double>  &getConstRefTodMechanicalSourcedField() const=0;
+    virtual fullMatrix<double>  &getRefTodMechanicalSourcedField()=0;
+    virtual const std::vector<std::vector<SVector3> >  &getConstRefTodMechanicalSourcedGradField() const=0;
+    virtual std::vector<std::vector<SVector3> >  &getRefTodMechanicalSourcedGradField()=0;
+    virtual const std::vector<STensor3>  &getConstRefTodMechanicalSourcedF() const=0;
+    virtual std::vector<STensor3>  &getRefTodMechanicalSourcedF()=0;
+
+    virtual const fullVector<double>  &getConstRefToExtraDofFieldCapacityPerUnitField() const=0;
+    virtual fullVector<double>  &getRefToExtraDofFieldCapacityPerUnitField()=0;
+    // FLE
+    
     virtual bool hasBodyForceForHO() const =0;
     virtual const STensor33 &getConstRefToGM()const=0;
     virtual STensor33 &getRefToGM()=0;
diff --git a/NonLinearSolver/materialLaw/mlaw.h b/NonLinearSolver/materialLaw/mlaw.h
index 4329b2659e603d7caf858e2f615033f59751a692..c9fa30748ee0daca3cd9b3e2ef7aab0afa9e36f3 100644
--- a/NonLinearSolver/materialLaw/mlaw.h
+++ b/NonLinearSolver/materialLaw/mlaw.h
@@ -33,7 +33,7 @@ class materialLaw{
                  hyperelastic, powerYieldLaw, powerYieldLawWithFailure,nonLocalDamagePowerYieldHyper,
                  localDamagePowerYieldHyperWithFailure,nonLocalDamagePowerYieldHyperWithFailure,ElecSMP,
                  ThermalConducter,AnIsotropicTherMech, localDamageJ2Hyper,linearElastic,nonLocalDamageGursonThermoMechanics,
-                 localDamageJ2SmallStrain,nonLocalDamageJ2SmallStrain,cluster,tfa,ANN, DMN, torchANN, NonlocalDamageTorchANN, StochDMN, LinearElecMagTherMech, LinearElecMagInductor, hyperviscoelastic, GenericResidualStrain,
+                 localDamageJ2SmallStrain,nonLocalDamageJ2SmallStrain,cluster,tfa,ANN, DMN, torchANN, NonlocalDamageTorchANN, StochDMN, StochTMDMN, LinearElecMagTherMech, LinearElecMagInductor, hyperviscoelastic, GenericResidualStrain,
                  GenericThermoMechanics, ElecMagGenericThermoMechanics, ElecMagInductor,
                  nonlineartvm,nonlinearTVE,nonlinearTVP,vevpmfh, VEVPUMAT, IMDEACPUMAT, Hill48,nonlinearTVEnonlinearTVP,nonlinearTVEnonlinearTVP2,
 				 TVEVPwithFailure,nonLocalDamageTVEVP,localDamageTVEVPWithFailure,nonLocalDamageTVEVPWithFailure,
diff --git a/NonLinearSolver/modelReduction/NetworkInteraction.cpp b/NonLinearSolver/modelReduction/NetworkInteraction.cpp
index dcfc63fc2f0076f0ea42cc60d3a954f4263ee1a5..755d286b09f1fd4a5f6044e566782791d596aad9 100644
--- a/NonLinearSolver/modelReduction/NetworkInteraction.cpp
+++ b/NonLinearSolver/modelReduction/NetworkInteraction.cpp
@@ -408,6 +408,148 @@ void InteractionMechanism::getDInducedStrainDCoefficient(int nodeId, STensor3& D
 };
 
 
+// FLE
+const double& InteractionMechanismExtraDOF::getConstRefToIncompatibleExtraDOF(const IPStateBase::whichState ws) const
+{
+  if (ws == IPStateBase::current)
+  {
+    return tcur;
+  }
+  else if (ws == IPStateBase::previous)
+  {
+    return tprev;
+  }
+  else if (ws == IPStateBase::initial)
+  {
+    return tinit;
+  }
+  else
+  {
+    Msg::Error("state %s has not been defined in InteractionMechanism::getConstRefToIncompatibleExtraDOF",ws);
+    Msg::Exit(0);
+  }
+};
+
+double& InteractionMechanismExtraDOF::getRefToIncompatibleExtraDOF(const IPStateBase::whichState ws)
+{
+  if (ws == IPStateBase::current)
+  {
+    return tcur;
+  }
+  else if (ws == IPStateBase::previous)
+  {
+    return tprev;
+  }
+  else if (ws == IPStateBase::initial)
+  {
+    return tinit;
+  }
+  else
+  {
+    Msg::Error("state %s has not been defined in InteractionMechanism::getRefToIncompatibleExtraDOF",ws);
+    Msg::Exit(0);
+  }
+};
+
+void InteractionMechanismExtraDOF::resetIncompatibleExtraDOF()
+{
+  tcur = 0.; tprev = 0.; tinit = 0.;
+};
+
+void InteractionMechanismExtraDOF::nextStepExtraDOF()
+{
+  tprev = tcur;
+};
+void InteractionMechanismExtraDOF::resetToPreviousStepExtraDOF()
+{
+  tcur = tprev;
+};
+
+void InteractionMechanismExtraDOF::copyExtraDOF(const IPStateBase::whichState ws1, const IPStateBase::whichState ws2)
+{
+  getRefToIncompatibleExtraDOF(ws2) = getRefToIncompatibleExtraDOF(ws1);
+};
+
+void InteractionMechanismExtraDOF::getInducedExtraDOFGrad(int nodeId, SVector3& Hi) const
+{
+  std::map<int,double>::const_iterator itF = coefficients.find(nodeId);
+  if (itF != coefficients.end())
+  {
+    static SVector3 direction;
+    getDirection(direction);
+    double alpha = itF->second;
+    for (int i=0; i<3; i++)
+    {
+        Hi(i) = alpha*tcur*direction(i);
+    }
+  }
+  else
+  {
+    Hi = 0.;
+  }
+};
+
+void InteractionMechanismExtraDOF::getDInducedExtraDOFGradDa(int nodeId, SVector3& DHiDt) const
+{
+  std::map<int,double>::const_iterator itF = coefficients.find(nodeId);
+  if (itF != coefficients.end())
+  {
+    static SVector3 direction;
+    getDirection(direction);
+    double alpha = itF->second;
+    for (int r=0; r<3; r++)
+    {
+      DHiDt(r) = direction(r)*alpha;
+    }
+  }
+  else
+  {
+    DHiDt = 0.;
+  }
+};
+
+void InteractionMechanismExtraDOF::getDInducedExtraDOFGradDDirection(int nodeId, STensor3& DHiDdir) const
+{
+  std::map<int,double>::const_iterator itF = coefficients.find(nodeId);
+  if (itF != coefficients.end())
+  {
+    static STensor3 I(1.);
+    double alpha = itF->second;
+    for (int r=0; r<3; r++)
+    {
+      for (int c=0; c<3; c++)
+      {
+          DHiDdir(r,c) = alpha*tcur*I(r,c);
+      }
+    };
+  }
+  else
+  {
+    STensorOperation::zero(DHiDdir);
+  }
+};
+
+void InteractionMechanismExtraDOF::getDInducedExtraDOFGradDCoefficient(int nodeId, SVector3& DHiDalpha) const
+{
+  std::map<int,double>::const_iterator itF = coefficients.find(nodeId);
+  if (itF != coefficients.end())
+  {
+    static SVector3 direction;
+    getDirection(direction);
+    double alpha = itF->second;
+    for (int r=0; r<3; r++)
+    {
+        DHiDalpha(r) = tcur*direction(r);
+    };
+  }
+  else
+  {
+    DHiDalpha = 0.;
+  }
+};
+
+// FLE
+
 
 NetworkInteraction::NetworkInteraction(int tag): _tag(tag)
 {
diff --git a/NonLinearSolver/modelReduction/NetworkInteraction.h b/NonLinearSolver/modelReduction/NetworkInteraction.h
index a737379823fb847bcbd6243c98577667afe05fe9..309890b95c4231b1bdcb4ec847e4b1d18468f25e 100644
--- a/NonLinearSolver/modelReduction/NetworkInteraction.h
+++ b/NonLinearSolver/modelReduction/NetworkInteraction.h
@@ -78,6 +78,37 @@ class InteractionMechanism
     #endif //SWIG
 };
 
+// FLE
+class InteractionMechanismExtraDOF: public InteractionMechanism  // for tempGrad
+{
+  protected:
+    #ifndef SWIG 
+    double tcur, tprev, tinit; // incompatible temperature scalar
+    #endif //SWIG
+  public:
+    InteractionMechanismExtraDOF():InteractionMechanism(),tcur(),tprev(),tinit(){}
+    
+    #ifndef SWIG
+    InteractionMechanismExtraDOF(const InteractionMechanismExtraDOF& src): InteractionMechanism(src),tcur(src.tcur),tprev(src.tprev),tinit(src.tinit){}
+    InteractionMechanismExtraDOF* clone() const {return new InteractionMechanismExtraDOF(*this);}
+    ~InteractionMechanismExtraDOF(){}
+
+    const double& getConstRefToIncompatibleExtraDOF(const IPStateBase::whichState ws) const;
+    double& getRefToIncompatibleExtraDOF(const IPStateBase::whichState ws);
+  
+    void nextStepExtraDOF();
+    void resetIncompatibleExtraDOF();
+    void resetToPreviousStepExtraDOF();
+    void copyExtraDOF(const IPStateBase::whichState ws1, const IPStateBase::whichState ws2);
+    // induce tempGrad from interaction
+    void getInducedExtraDOFGrad(int nodeIndex, SVector3& Hi) const;
+    void getDInducedExtraDOFGradDa(int nodeIndex, SVector3& DHiDt) const;
+    void getDInducedExtraDOFGradDDirection(int nodeIndex, STensor3& DHiDdir) const;
+    void getDInducedExtraDOFGradDCoefficient(int nodeIndex, SVector3& DHiDalpha) const;
+    #endif //SWIG
+};
+// FLE
+
 class NetworkInteraction
 {
   #ifndef SWIG
@@ -175,7 +206,7 @@ class NetworkInteraction
     //
     const STensor3& getStress(const MaterialNode* node) const;
     const STensor3& getDeformationGradient(const MaterialNode* node) const;
-    const STensor43& getTangent(const MaterialNode* node ) const;
+    const STensor43& getTangent(const MaterialNode* node ) const; // dPdF
     void getStress(STensor3& P) const;
     void getDeformationGradientPhase(int phaseIndex, STensor3& F) const;
     //
@@ -209,6 +240,132 @@ class NetworkInteraction
     #endif //SWIG
 };
 
+/*
+// FLE
+class NetworkInteractionExtraDOF : public NetworkInteraction
+{
+  public:
+    NetworkInteractionExtraDOF();
+    NetworkInteractionExtraDOF(const NetworkInteraction& src);
+    NetworkInteractionExtraDOF* clone() const {return new NetworkInteractionExtraDOF(*this);};
+    ~NetworkInteractionExtraDOF();
+
+    int getTag() const;
+    void clearData();
+    void getInteractionFromTree(const Tree& T,  bool standardize=true);
+
+    void resetIncompatibleExtraDOF();
+
+    void copyFrom(const NetworkInteraction& src);
+    void mergeNodesInteraction(InteractionMechanism& ie, const std::vector<int>& allNodes) const;
+    void mergeNodesAllInteractions(const std::vector<int>& allNodes);
+    void mergeNodes(int phaseIndex,  // phase index 
+                    int numberNodes,  // only interactions with numberNodes nodes
+                    NetworkInteraction& newInteraction);
+
+    int getNumberOfMaterialNodes() const;
+    int getDimension() const;
+    double getTotalWeight() const;
+    double getTotalWeightPhase(int iphase) const;
+    void getTotalWeightAllPhases(std::map<int, double>& allPhase) const;
+    void getPhaseFractions(std::map<int, double>& allPhase) const;
+    double getPhaseFraction(int phase) const;
+    int getPhaseIndex(int nodeId) const;
+    double getWeight(const MaterialNode* node) const;
+    double getWeight(int nodeId) const;
+    void getWeights(const InteractionMechanism* im, std::vector<double>& allWeights) const;
+    double get(int comp, int eleVal) const;
+    double getPerPhase(int phaseIndex, int comp, int eleVal) const;
+    
+    void saveDataToFile(std::string filename) const;
+    void loadDataFromFile(std::string filename);
+    void loadCohesiveDataFromFile(std::string filename);
+    void convertToLinearActivation(std::string outputFileName);
+    void createInteractionFromPairsData(std::string filename, int dim, std::string affunc="relu");
+    void createInteractionFullByDivison(int numPhases, int nodePerPhase, int numInteraction, int dim, std::string affunc="relu");
+    void initializeRandomFullInteraction(int numberMaterialNodes, int numberInteractions, int dim,
+                                         const fullVector<double>& phaseFraction, const std::string affunc="relu",
+                                        bool rand=true);
+                                        
+    void createTreeBasedFullInteraction(int Nlayers, int nodePerPhaseFullInteraction, 
+                                        int numFullInteraction, int dim,
+                                         const fullVector<double>& phaseFraction, 
+                                         const std::string affunc="relu",
+                                        bool rand=true, bool triple=false);
+    void initializeRandomPointwiseInteraction(int numberMaterialNodes, int numPhases, int dim, bool rand=true, std::string affunc="relu");
+    void normalizeWeights(std::string newaffunc="linear");
+    void standardizeInteractionDirections();
+    void normalizeAllInteractionCoefficients();
+    bool reInitialize();
+    bool checkValidity(bool message=true) const;
+    
+    #ifndef SWIG
+    void getMaterialNodesByMaterialIndex(int matIndex, std::vector<const MaterialNode*>& allNode) const;
+    void getMaterialNodesByMaterialIndex(int matIndex, std::vector<MaterialNode*>& allNode);
+    MaterialNodeContainer& getMaterialNodeContainer(){return _allMaterialNodes;}
+    const MaterialNodeContainer& getMaterialNodeContainer() const {return _allMaterialNodes;}
+    InteractionContainer& getInteractionContainer() {return _allInteractions;};
+    const InteractionContainer& getInteractionContainer() const {return _allInteractions;};
+    NodeMapContainer& getNodeMapContainer() {return _nodeInteractionMap;}
+    const NodeMapContainer& getNodeMapContainer() const {return _nodeInteractionMap;}
+    
+    void getAllMaterialNodes(std::vector<const MaterialNode*>& allNode) const;
+    void getAllMaterialNodesForMat(int matNum, std::vector<const MaterialNode*>& allNode) const;
+    void getAllMaterialNodes(std::vector<MaterialNode*>& allNode);
+    
+    MaterialNode* getMaterialNode(const int number);
+    const MaterialNode* getMaterialNode(const int number) const;
+    void getAllMaterialNodeIds(std::vector<int>& allIds) const;
+    void getAllMaterialNodeIdsForMat(int matNum, std::vector<int>& allIds) const;
+    void getNumberMaterialNodesPerMat(std::map<int, int>& nodePerMat) const;
+    
+    const std::vector<const InteractionMechanism*>* getInteractionsForNode(const MaterialNode* node) const;
+
+    void getDHDExtraDOF(const MaterialNode* node, std::vector<SVector3>& DHiDt) const;
+    void getDHDNormal(const MaterialNode* node, std::vector<STensor3>& DHiDn) const;
+    void getDHDCoefficient(const MaterialNode* node, std::vector<SVector3>& DHiDalpha) const;
+    
+    void getDfluxDIncompatibleExtraDOF(const MaterialNode* node, std::vector<SVector3>& DqiDt) const;
+    void getDfluxDNormal(const MaterialNode* node, std::vector<STensor3>& DqiDn) const;
+    void getDfluxDCoefficient(const MaterialNode* node, std::vector<SVector3>& DqiDalpha) const;
+    //
+    const STensor3& getFlux(const MaterialNode* node) const;
+    const STensor3& getExtraDOFGrad(const MaterialNode* node) const;
+    const STensor43& getTangent(const MaterialNode* node ) const; // dqDGradT // CHECK
+    void getFlux(SVector3& q) const;
+    void getExtraDOFGradientPhase(int phaseIndex, SVector3& H) const;
+    //
+    void nextStep();
+    void resetToPreviousStep();
+    void copy(const IPStateBase::whichState ws1, const IPStateBase::whichState ws2);
+    //
+    // linear term for im with respect to jm
+    void getDLinearTermDCoefficient(const InteractionMechanism* im, const InteractionMechanism* jm, fullMatrix<double>& mat) const;
+    // linear term for im with respect to jm
+    void getDLinearTermDNormalVars(const InteractionMechanism* im, const InteractionMechanism* jm, fullMatrix<double>& mat) const;
+    // with repsecto to material weights
+    void getDLinearTermDWeights(const InteractionMechanism* im, std::vector<int>& materialIds, fullMatrix<double>& DvecDWeights) const;
+    //
+    void computeLocalDeformationGradient(const STensor3& Fmacro);
+    // get force
+    void getLinearTerm(const InteractionMechanism* im, fullVector<double>& vec) const;
+    // get DforceDa
+    void getBilinearTerm(const InteractionMechanism* im, std::vector<const InteractionMechanism*>& others, fullMatrix<double>& mat) const;    
+    // get DforceDFbar
+    void getTangentTerm(const InteractionMechanism* im, fullMatrix<double>& mat) const;
+    //
+    void getLinearInterfaceTerm(const MaterialNode* node, fullVector<double>& vec) const;
+    //
+    void getBiLinearInterfaceTerm(const MaterialNode* node, fullMatrix<double>& mat) const;
+    //
+    void getBilinearCrossTermBulkInterface(const InteractionMechanism* im, std::vector<const MaterialNode*>& materialNodes, fullMatrix<double>& mat) const;
+    //
+    void getBilinearCrossTermInterfaceBulk(const MaterialNode* node, std::vector<const InteractionMechanism*>& others, 
+                                     fullMatrix<double>& mat) const;
+    #endif //SWIG
+};
+*/
+// FLE
 
 class CoefficientReduction
 {
diff --git a/dG3D/src/computeWithMaterialLaw.cpp b/dG3D/src/computeWithMaterialLaw.cpp
index e5cb775c14d567fda9a4af1cdeea5f1c0f4eb48f..df5aeaa61872f21954664183b73e6816d3ce6a92 100644
--- a/dG3D/src/computeWithMaterialLaw.cpp
+++ b/dG3D/src/computeWithMaterialLaw.cpp
@@ -13,8 +13,8 @@
 #include "nonLinearMechSolver.h"
 #include "STensorOperations.h"
 
-computeMaterialLaw::computeMaterialLaw(dG3DMaterialLaw& mlaw): _materialLaw(&mlaw), _ips(NULL), _step(0)
-{
+computeMaterialLaw::computeMaterialLaw(dG3DMaterialLaw& mlaw, bool flag_isothermal, bool flag_microTempFixed): _materialLaw(&mlaw), 
+_ips(NULL), _step(0), _flag_isothermal(flag_isothermal), _flag_microTempFixed(flag_microTempFixed){
   static nonLinearMechSolver solver(1000);
   _materialLaw->setMacroSolver(&solver);
   static bool state = true;
@@ -78,6 +78,42 @@ void computeMaterialLaw::setDeformationGradient(int i, int j, double val)
   F(i,j) = val;
 }
 
+void computeMaterialLaw::setTemperatureGradient(int i, double val)
+{
+  if (!_flag_isothermal){
+    // store current for next step
+  ThermoMechanicsDG3DIPVariableBase* dgip = dynamic_cast<ThermoMechanicsDG3DIPVariableBase*>(_ips->getState(IPStateBase::current));
+  if (!dgip)
+  {
+    Msg::Error("ThermoMechanicsDG3DIPVariableBase must be created from material law computeMaterialLaw::setTemperatureGradient");
+    Msg::Exit(0);
+  }
+  SVector3& H = dgip->getRefToGradT();
+  H(i) = val;
+  }
+  else{
+    Msg::Error("computeMaterialLaw::setTemperatureGradient can be activated only if flag_isothermal is set to false in the constructor.");
+  }
+}
+
+void computeMaterialLaw::setTemperature(double val)
+{
+  if (!_flag_isothermal){
+    // store current for next step
+  ThermoMechanicsDG3DIPVariableBase* dgip = dynamic_cast<ThermoMechanicsDG3DIPVariableBase*>(_ips->getState(IPStateBase::current));
+  if (!dgip)
+  {
+    Msg::Error("ThermoMechanicsDG3DIPVariableBase must be created from material law computeMaterialLaw::setTemperature");
+    Msg::Exit(0);
+  }
+  double& T = dgip->getRefToTemperature();
+  T = val;
+  }
+  else{
+    Msg::Error("computeMaterialLaw::setTemperature can be activated only if flag_isothermal is set to false in the constructor.");
+  }
+}
+
 void computeMaterialLaw::setTime(double t, double dt)
 {
   _materialLaw->setTime(t,dt);
@@ -108,7 +144,6 @@ void computeMaterialLaw::computeStressState_uniaxialStress(bool stiff)
   }
 };
 
-
 void computeMaterialLaw::computeStressState_PlaneStrainUniaxialStress( char* NoZeroPlane, bool stiff )
 {
   IPVariable* ipvcur = _ips->getState(IPStateBase::current);
@@ -139,10 +174,6 @@ void computeMaterialLaw::computeStressState_PlaneStrainUniaxialStress( char* NoZ
 };
 
 
-
-
-
-
 double computeMaterialLaw::getTime() const
 {
   return _materialLaw->getTime();
@@ -397,6 +428,32 @@ void computeMaterialLaw::getStress(std::vector<double>& Pstress){
     }
 } 
 
+void computeMaterialLaw::getHeatFlux(std::vector<double>& Qstress){
+  if(!_flag_isothermal){
+    IPVariable* ipvcur = _ips->getState(IPStateBase::current);
+    static SVector3 Q;
+    Q(0) = ipvcur->get(IPField::THERMALFLUX_X);
+    Q(1) = ipvcur->get(IPField::THERMALFLUX_Y);
+    Q(2) = ipvcur->get(IPField::THERMALFLUX_Z);
+    for(int i=0; i<3; i++){
+      Qstress.push_back(Q(i));
+    }
+  }
+  else{
+    Msg::Error("computeMaterialLaw::getHeatFlux can be used only if flag_isothermal is set to false in the constructor.");
+  }
+} 
+
+void computeMaterialLaw::get3rdDependentVariable(double& Cstress){
+  if(!_flag_microTempFixed){
+    IPVariable* ipvcur = _ips->getState(IPStateBase::current);
+    Cstress = ipvcur->get(IPField::FIELD_CAPACITY); // specific heat
+  }
+  else{
+    Msg::Error("computeMaterialLaw::get3rdDependentVariable can be used only if _flag_microTempFixed is set to false in the constructor.");
+  }
+};
+
 void computeMaterialLaw::getDeformationGradient(std::vector<double>& Fstrain){
     IPVariable* ipvcur = _ips->getState(IPStateBase::current);
     static STensor3 F;
@@ -416,6 +473,32 @@ void computeMaterialLaw::getDeformationGradient(std::vector<double>& Fstrain){
     }
 }   
 
+void computeMaterialLaw::getTemperatureGradient(std::vector<double>& Hstrain){
+  if(!_flag_isothermal){
+    IPVariable* ipvcur = _ips->getState(IPStateBase::current);
+    static SVector3 H;
+    H(0) = ipvcur->get(IPField::TEMP_GRAD_X);
+    H(1) = ipvcur->get(IPField::TEMP_GRAD_Y);
+    H(2) = ipvcur->get(IPField::TEMP_GRAD_Z);
+    for(int i=0; i<3; i++){
+      Hstrain.push_back(H(i));
+    }
+  }
+  else{
+    Msg::Error("computeMaterialLaw::getTemperatureGradient can be used only if flag_isothermal is set to false in the constructor.");
+  }
+}  
+
+void computeMaterialLaw::getTemperature(double& T){
+  if(!_flag_isothermal){
+    IPVariable* ipvcur = _ips->getState(IPStateBase::current);
+    T = ipvcur->get(IPField::TEMPERATURE);
+  }
+  else{
+    Msg::Error("computeMaterialLaw::getTemperatureGradient can be used only if flag_isothermal is set to false in the constructor.");
+  }
+}  
+
 void computeMaterialLaw::getParameterDerivative(std::vector< fullMatrix<double> >& dPdPn, std::vector< fullMatrix<double> >&dPdPv) const{
   const IPVariable* ipvcur = _ips->getState(IPStateBase::current);
   _materialLaw->getParameterDerivative(ipvcur, dPdPn, dPdPv);  
diff --git a/dG3D/src/computeWithMaterialLaw.h b/dG3D/src/computeWithMaterialLaw.h
index 1d1ece95bd25d54a8311397cb50623cd5e9bcfa8..de66420e1893fefc1091da55184145a6031d2837 100644
--- a/dG3D/src/computeWithMaterialLaw.h
+++ b/dG3D/src/computeWithMaterialLaw.h
@@ -24,12 +24,16 @@ class computeMaterialLaw
     dG3DMaterialLaw* _materialLaw;
     IPStateBase* _ips;
     int _step;
+    bool _flag_isothermal;
+    bool _flag_microTempFixed;
     #endif //SWIG
   public:
-    computeMaterialLaw(dG3DMaterialLaw& mlaw);
+    computeMaterialLaw(dG3DMaterialLaw& mlaw, bool flag_isothermal = true, bool flag_microTempFixed = true);
     virtual ~computeMaterialLaw();
     void resetState(dG3DMaterialLaw& mlaw);
     void setDeformationGradient(int i, int, double val);
+    void setTemperatureGradient(int i, double val);
+    void setTemperature(double val);
     void setTime(double t, double dt);
     void nextStep();
     void computeStressState(bool stiff=false);
@@ -40,7 +44,11 @@ class computeMaterialLaw
     double getTime() const;
     double getTimeStep() const;
     void getStress(std::vector<double>& Pstress);
+    void getHeatFlux(std::vector<double>& Qstress);
+    void get3rdDependentVariable(double& Cstress);
     void getDeformationGradient(std::vector<double>& Fstrain);
+    void getTemperatureGradient(std::vector<double>& Hstrain);
+    void getTemperature(double& T);
     void getParameterDerivative(std::vector< fullMatrix<double> >& dPdPn, std::vector< fullMatrix<double> >&dPdPv) const;
     void reset_Parameter(dG3DMaterialLaw& mlaw, std::vector<std::vector<double>>& Para_Norm, std::vector<std::vector<double>>& Para_Wt, const double Vf=0.0);
     void reset_Parameter(dG3DMaterialLaw& mlaw, const char* Para);
diff --git a/dG3D/src/dG3DIPVariable.cpp b/dG3D/src/dG3DIPVariable.cpp
index d29ab2917974a60884fe98ee77b294444df88f43..06d0c8844edbdbaff9e46650d729358e4b16a032 100644
--- a/dG3D/src/dG3DIPVariable.cpp
+++ b/dG3D/src/dG3DIPVariable.cpp
@@ -2165,134 +2165,6 @@ double ANNBasedDG3DIPVariable::get(const int comp) const
   }
 }
 
-
-StochDMNDG3DIPVariable::StochDMNDG3DIPVariable(const int NRoot,const int NInterface, const bool createBodyForceHO, const bool oninter):
-    dG3DIPVariable(createBodyForceHO, oninter), _NRoot(NRoot), _NInterface(NInterface), _IPVector(NRoot,NULL){
-    bool resizeFlag;
-    int entryFP = 9*_NRoot;
-    int entry_a = 3*_NInterface;
-    resizeFlag = Fvec.resize(entryFP, true);
-    resizeFlag = Pvec.resize(entryFP, true);
-    resizeFlag = a.resize(entry_a, true);
- }
-
-StochDMNDG3DIPVariable::StochDMNDG3DIPVariable(const StochDMNDG3DIPVariable& src):
-  dG3DIPVariable(src), _NRoot(src._NRoot), Fvec(src.Fvec), Pvec(src.Pvec), a(src.a),_IPVector(src._NRoot,NULL){
-    for (int j=0; j< src._NRoot; j++){
-      if (src._IPVector[j] != NULL){
-        _IPVector[j] = src._IPVector[j]->clone();
-      }
-    }
-  }
-
-
-StochDMNDG3DIPVariable& StochDMNDG3DIPVariable::operator =(const IPVariable& src)
-{
-  dG3DIPVariable::operator=(src);
-  const StochDMNDG3DIPVariable* psrc = dynamic_cast<const StochDMNDG3DIPVariable*>(&src);
-  if (psrc!=NULL)
-  {
-    _NRoot = psrc->_NRoot;
-    Fvec = psrc->Fvec;
-    Pvec = psrc->Pvec;
-    a = psrc->a;
-    for (int j=0; j< _NRoot; j++)
-    {
-      if ((_IPVector[j]!=NULL) and (psrc->_IPVector[j] != NULL))
-      {
-        _IPVector[j]->operator =(*(psrc->_IPVector[j]));
-      }
-      else
-      {
-        Msg::Error("cannot perform equal operator in StochDMNDG3DIPVariable::operator =");
-      }
-    }
-  }
-  return *this;
-}
-
-StochDMNDG3DIPVariable::~StochDMNDG3DIPVariable()
-{
-  for (int j=0; j< _NRoot; j++)
-  {
-    if (_IPVector[j] != NULL)
-    {
-      delete _IPVector[j];
-    }
-  }
-}
-
-void StochDMNDG3DIPVariable::addIPv(int loc, IPVariable* ipv)
-{
-  _IPVector[loc] = ipv;
-}
-
-double StochDMNDG3DIPVariable::get(const int comp) const
-{
-  if (comp == IPField::DEFO_ENERGY ||
-      comp == IPField::PLASTIC_ENERGY ||
-      comp == IPField::DAMAGE_ENERGY ||
-      comp == IPField::DAMAGE )
-  {
-    double v = 0;
-    for (int j=0; j< _NRoot; j++)
-    {
-      v += _IPVector[j]->get(comp);
-    }
-    return v;
-  }
-  else
-  {
-    return dG3DIPVariable::get(comp);
-  }
-};
-
-
-void StochDMNDG3DIPVariable::restart()
-{
-  dG3DIPVariable::restart();
-  restartManager::restart(_NRoot);
-  restartManager::restart(Fvec.getDataPtr(),9*_NRoot);
-  restartManager::restart(Pvec.getDataPtr(),9*_NRoot);
-  restartManager::restart(a.getDataPtr(),3*_NInterface);
-  restartManager::restart(_IPVector);
-  for (int j=0; j< _NRoot; j++){
-    _IPVector[j]->restart();
-  }
-};
-
-
-
-double StochDMNDG3DIPVariable::defoEnergy() const
-{
-  double v = 0;
-  for (int j=0; j< _NRoot; j++)
-  {
-    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->defoEnergy();
-  }
-  return v;
-}
-double StochDMNDG3DIPVariable::plasticEnergy() const
-{
-  double v = 0;
-  for (int j=0; j< _NRoot; j++)
-  {
-    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->plasticEnergy();
-  }
-  return v;
-}
-double StochDMNDG3DIPVariable::damageEnergy() const
-{
-  double v = 0;
-  for (int j=0; j< _NRoot; j++)
-  {
-    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->damageEnergy();
-  }
-  return v;
-}
-
-
-
 //torchANNBasedDG3DIPVariable::torchANNBasedDG3DIPVariable(const int n, const double initial_h, const bool createBodyForceHO, const bool oninter):
 //                 dG3DIPVariable(createBodyForceHO, oninter), _n(n), _initial_h(initial_h), restart_internalVars(1,n), _kinematicVariables(1,6)
 //{
@@ -4156,6 +4028,18 @@ double ThermoMechanicsDG3DIPVariableBase::get(const int i) const
   else if (i == IPField::MECHANICAL_SOURCE){
     return getConstRefToMechanicalSource()(0);
   }
+  else if (i == IPField::TEMP_GRAD_X){
+    return getConstRefToGradField()[0](0);
+  }
+  else if (i == IPField::TEMP_GRAD_Y){
+    return getConstRefToGradField()[0](1);
+  }
+  else if (i == IPField::TEMP_GRAD_Z){
+    return getConstRefToGradField()[0](2);
+  }
+  else if (i == IPField::FIELD_CAPACITY){
+    return getConstitutiveExtraDofFieldCapacityPerUnitField(0);
+  }
   else
   {
     return dG3DIPVariable::get(i);
@@ -4168,6 +4052,250 @@ void ThermoMechanicsDG3DIPVariableBase::restart()
   return;
 }
 
+StochDMNDG3DIPVariable::StochDMNDG3DIPVariable(const int NRoot,const int NInterface, const bool createBodyForceHO, const bool oninter):
+ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter), _NRoot(NRoot), _NInterface(NInterface), _IPVector(NRoot,NULL){
+    static STensor3 _I(1.); _R = _I; 
+    bool resizeFlag;
+    int entryFP = 9*_NRoot;
+    int entry_a = 3*_NInterface;
+    resizeFlag = Fvec.resize(entryFP, true);
+    resizeFlag = Pvec.resize(entryFP, true);
+    resizeFlag = a.resize(entry_a, true);
+ }
+
+StochDMNDG3DIPVariable::StochDMNDG3DIPVariable(const StochDMNDG3DIPVariable& src):
+ThermoMechanicsDG3DIPVariableBase(src), _NRoot(src._NRoot), _NInterface(src._NInterface), Fvec(src.Fvec), Pvec(src.Pvec), a(src.a),_IPVector(src._NRoot,NULL), _R(src._R){
+    for (int j=0; j< src._NRoot; j++){
+      if (src._IPVector[j] != NULL){
+        _IPVector[j] = src._IPVector[j]->clone();
+      }
+    }
+  }
+
+
+StochDMNDG3DIPVariable& StochDMNDG3DIPVariable::operator =(const IPVariable& src)
+{
+  ThermoMechanicsDG3DIPVariableBase::operator=(src);
+  const StochDMNDG3DIPVariable* psrc = dynamic_cast<const StochDMNDG3DIPVariable*>(&src);
+  if (psrc!=NULL)
+  {
+    _NRoot = psrc->_NRoot;
+    _NInterface = psrc->_NInterface;
+    Fvec = psrc->Fvec;
+    Pvec = psrc->Pvec;
+    a = psrc->a;
+    _R = psrc->_R;
+    for (int j=0; j< _NRoot; j++)
+    {
+      if ((_IPVector[j]!=NULL) and (psrc->_IPVector[j] != NULL))
+      {
+        _IPVector[j]->operator =(*(psrc->_IPVector[j]));
+      }
+      else
+      {
+        Msg::Error("cannot perform equal operator in StochDMNDG3DIPVariable::operator =");
+      }
+    }
+  }
+  return *this;
+}
+
+StochDMNDG3DIPVariable::~StochDMNDG3DIPVariable()
+{
+  for (int j=0; j< _NRoot; j++)
+  {
+    if (_IPVector[j] != NULL)
+    {
+      delete _IPVector[j];
+    }
+  }
+}
+
+void StochDMNDG3DIPVariable::addIPv(int loc, IPVariable* ipv)
+{
+  _IPVector[loc] = ipv;
+}
+
+double StochDMNDG3DIPVariable::get(const int comp) const
+{
+  if (comp == IPField::DEFO_ENERGY ||
+      comp == IPField::PLASTIC_ENERGY ||
+      comp == IPField::DAMAGE_ENERGY ||
+      comp == IPField::DAMAGE )
+  {
+    double v = 0;
+    for (int j=0; j< _NRoot; j++)
+    {
+      v += _IPVector[j]->get(comp);
+    }
+    return v;
+  }
+  else
+  {
+    return ThermoMechanicsDG3DIPVariableBase::get(comp);
+  }
+};
+
+
+void StochDMNDG3DIPVariable::restart()
+{
+  ThermoMechanicsDG3DIPVariableBase::restart();
+  restartManager::restart(_NRoot);
+  restartManager::restart(_NInterface);
+  restartManager::restart(Fvec.getDataPtr(),9*_NRoot);
+  restartManager::restart(Pvec.getDataPtr(),9*_NRoot);
+  restartManager::restart(a.getDataPtr(),3*_NInterface);
+  restartManager::restart(_R);
+  restartManager::restart(_IPVector);
+  for (int j=0; j< _NRoot; j++){
+    _IPVector[j]->restart();
+  }
+};
+
+
+
+double StochDMNDG3DIPVariable::defoEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->defoEnergy();
+  }
+  return v;
+}
+double StochDMNDG3DIPVariable::plasticEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->plasticEnergy();
+  }
+  return v;
+}
+double StochDMNDG3DIPVariable::damageEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const dG3DIPVariableBase*>(_IPVector[j])->damageEnergy();
+  }
+  return v;
+}
+
+// FLE
+StochTMDMNDG3DIPVariable::StochTMDMNDG3DIPVariable(const int NRoot,const int NInterface, const int col_Di, const int row_Di,
+                     const bool createBodyForceHO, const bool oninter):
+    StochDMNDG3DIPVariable(NRoot,NInterface,createBodyForceHO,oninter),_col_Di(col_Di), _row_Di(row_Di){
+    bool resizeFlag;
+    int entryFHPQ = _col_Di*_NRoot;
+    int entry_ab = _row_Di*_NInterface;
+    resizeFlag = FHvec.resize(entryFHPQ, true);
+    resizeFlag = PQvec.resize(entryFHPQ, true);
+    resizeFlag = ab.resize(entry_ab, true);
+    resizeFlag = Cpvec.resize(_NRoot, true);
+    resizeFlag = thermSrcvec.resize(_NRoot, true);
+    resizeFlag = mechSrcvec.resize(_NRoot, true);
+ }
+
+StochTMDMNDG3DIPVariable::StochTMDMNDG3DIPVariable(const StochTMDMNDG3DIPVariable& src): StochDMNDG3DIPVariable(src),
+    _col_Di(src._col_Di), _row_Di(src._row_Di),
+    FHvec(src.FHvec), PQvec(src.PQvec), ab(src.ab), Cpvec(src.Cpvec), 
+    thermSrcvec(src.thermSrcvec), mechSrcvec(src.mechSrcvec){
+  }
+
+StochTMDMNDG3DIPVariable& StochTMDMNDG3DIPVariable::operator =(const IPVariable& src)
+{
+  StochDMNDG3DIPVariable::operator=(src);
+  const StochTMDMNDG3DIPVariable* psrc = dynamic_cast<const StochTMDMNDG3DIPVariable*>(&src);
+  if (psrc!=NULL)
+  {
+    _col_Di = psrc->_col_Di;
+    _row_Di = psrc->_row_Di;
+    FHvec = psrc->FHvec;
+    PQvec = psrc->PQvec;
+    ab = psrc->ab;
+    Cpvec = psrc->Cpvec;
+    thermSrcvec = psrc->thermSrcvec;
+    mechSrcvec = psrc->mechSrcvec;
+  }
+  return *this;
+}
+
+StochTMDMNDG3DIPVariable::~StochTMDMNDG3DIPVariable()
+{
+}
+
+void StochTMDMNDG3DIPVariable::addIPv(int loc, IPVariable* ipv)
+{
+  _IPVector[loc] = ipv;
+}
+
+double StochTMDMNDG3DIPVariable::get(const int comp) const
+{
+  if (comp == IPField::_thermalEnergy)
+  {
+    double v = 0;
+    for (int j=0; j< _NRoot; j++)
+    {
+      v += _IPVector[j]->get(comp);
+    }
+    return v;
+  }
+  else{
+    return StochDMNDG3DIPVariable::get(comp);
+  }
+};
+
+void StochTMDMNDG3DIPVariable::restart()
+{
+  StochDMNDG3DIPVariable::restart();
+  restartManager::restart(_col_Di);
+  restartManager::restart(_row_Di);
+  restartManager::restart(FHvec.getDataPtr(),_col_Di*_NRoot);
+  restartManager::restart(PQvec.getDataPtr(),_col_Di*_NRoot);
+  restartManager::restart(ab.getDataPtr(),_row_Di*_NInterface);
+};
+
+double StochTMDMNDG3DIPVariable::defoEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const ThermoMechanicsDG3DIPVariableBase*>(_IPVector[j])->defoEnergy();
+  }
+  return v;
+}
+double StochTMDMNDG3DIPVariable::plasticEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const ThermoMechanicsDG3DIPVariableBase*>(_IPVector[j])->plasticEnergy();
+  }
+  return v;
+}
+double StochTMDMNDG3DIPVariable::damageEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const ThermoMechanicsDG3DIPVariableBase*>(_IPVector[j])->damageEnergy();
+  }
+  return v;
+}
+
+double StochTMDMNDG3DIPVariable::thermalEnergy() const
+{
+  double v = 0;
+  for (int j=0; j< _NRoot; j++)
+  {
+    v += dynamic_cast<const ThermoMechanicsDG3DIPVariableBase*>(_IPVector[j])->getInternalEnergyExtraDofDiffusion();
+  }
+  return v;
+}
+
+// FLE
+
 LinearThermoMechanicsDG3DIPVariable::LinearThermoMechanicsDG3DIPVariable(double tinitial, const bool createBodyForceHO, const bool oninter) :
                                    ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter)
 {
@@ -6094,6 +6222,7 @@ double NonLinearTVMDG3DIPVariable::get(const int i) const{
   else if (i == IPField::PRESSURE){return _ipViscoElastic->_pressure;}
   else if (i == IPField::viscousDissipatedEnergy){return _ipViscoElastic->_viscousDissipatedEnergy;}
   else if (i == IPField::mullinsDissipatedEnergy){return _ipViscoElastic->_mullinsDissipatedEnergy;}
+  else if (i == IPField::_thermalEnergy){return _ipViscoElastic->_thermalEnergy;}
   else if (i == IPField::Eve1_XX){
     if (_ipViscoElastic->_A.size() > 0)
       return _ipViscoElastic->_A[0](0,0) + _ipViscoElastic->_B[0]/3.;
@@ -6286,6 +6415,7 @@ double NonLinearTVPDG3DIPVariable::get(const int i) const{
   else if (i == IPField::Dev_corKir_Inf_ZZ){return _ipViscoElastoPlastic->_devCorKirinf_TVE(2,2);}
   else if (i == IPField::viscousDissipatedEnergy){return _ipViscoElastoPlastic->_viscousDissipatedEnergy;}
   else if (i == IPField::mullinsDissipatedEnergy){return _ipViscoElastoPlastic->_mullinsDissipatedEnergy;}
+  else if (i == IPField::_thermalEnergy){return _ipViscoElastoPlastic->_thermalEnergy;}
   else if (i == IPField::Eve1_XX){
     if (_ipViscoElastoPlastic->_A.size() > 0)
       return _ipViscoElastoPlastic->_A[0](0,0) + _ipViscoElastoPlastic->_B[0]/3.;
diff --git a/dG3D/src/dG3DIPVariable.h b/dG3D/src/dG3DIPVariable.h
index 492538adbaccafc523676ca0d47f9612fb1115ba..6bfee1b0890d80b3f275ae3dfba8a543631724a7 100644
--- a/dG3D/src/dG3DIPVariable.h
+++ b/dG3D/src/dG3DIPVariable.h
@@ -2395,48 +2395,6 @@ class ANNBasedDG3DIPVariable :public dG3DIPVariable
     virtual void restart();
 };
 
-
-class StochDMNDG3DIPVariable : public dG3DIPVariable
-{
-  protected:
-    int _NRoot, _NInterface;
-    std::vector<IPVariable*> _IPVector;
-    fullVector<double> Fvec;
-    fullVector<double> Pvec;
-    fullVector<double> a;
-
- public:
-    StochDMNDG3DIPVariable(const int NRoot,const int NInterface, const bool createBodyForceHO, const bool oninter);
-    StochDMNDG3DIPVariable(const StochDMNDG3DIPVariable& src);
-    virtual StochDMNDG3DIPVariable& operator =(const IPVariable& src);
-    virtual ~StochDMNDG3DIPVariable();
-
-    void InitializeFluctuationVector() {a.setAll(0.0);};
-    virtual double defoEnergy() const;
-    virtual double plasticEnergy() const;
-    virtual double damageEnergy() const;
-
-    void addIPv(int i, IPVariable* ipv);
-    IPVariable* getIPv(int i) {return _IPVector[i];};
-    const IPVariable* getIPv(int i) const {return _IPVector[i];};
-
-    virtual double get(const int comp) const;
-    virtual fullVector<double>& getRefToDeformationGradientVect() {return Fvec;};
-    virtual const fullVector<double>&  getConstRefToDeformationGradientVect() const {return Fvec;};
-    virtual fullVector<double>& getRefToFirstPiolaKirchhoffStressVect() {return Pvec;};
-    virtual const fullVector<double>& getConstRefToFirstPiolaKirchhoffStressVect() const {return Pvec;};
-    virtual fullVector<double>& getRefToInterfaceFluctuationVect() {return a;};
-    virtual const fullVector<double>& getConstRefToInterfaceFluctuationVect() const {return a;};
-
-
-
-    virtual IPVariable* getInternalData() {return NULL;};
-    virtual const IPVariable* getInternalData()  const {return NULL;};
-    virtual IPVariable* clone() const {return new StochDMNDG3DIPVariable(*this);};
-    virtual void restart();
-};
-
-
 class torchANNBasedDG3DIPVariable :public dG3DIPVariable
 {
   protected:
@@ -3476,6 +3434,99 @@ class ThermoMechanicsDG3DIPVariableBase : public dG3DIPVariable, public extraDof
   virtual void restart();
 };
 
+class StochDMNDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase
+{
+  protected:
+    int _NRoot, _NInterface;
+    std::vector<IPVariable*> _IPVector;
+    fullVector<double> Fvec;
+    fullVector<double> Pvec;
+    fullVector<double> a;
+    STensor3 _R;
+
+ public:
+    StochDMNDG3DIPVariable(const int NRoot,const int NInterface, const bool createBodyForceHO, const bool oninter);
+    StochDMNDG3DIPVariable(const StochDMNDG3DIPVariable& src);
+    virtual StochDMNDG3DIPVariable& operator =(const IPVariable& src);
+    virtual ~StochDMNDG3DIPVariable();
+
+    void InitializeFluctuationVector() {a.setAll(0.0);};
+    virtual double defoEnergy() const;
+    virtual double plasticEnergy() const;
+    virtual double damageEnergy() const;
+    virtual double getInternalEnergyExtraDofDiffusion() const {return 0.;};
+
+    void addIPv(int i, IPVariable* ipv);
+    IPVariable* getIPv(int i) {return _IPVector[i];};
+    const IPVariable* getIPv(int i) const {return _IPVector[i];};
+
+    virtual double get(const int comp) const;
+    virtual fullVector<double>& getRefToDeformationGradientVect() {return Fvec;};
+    virtual const fullVector<double>&  getConstRefToDeformationGradientVect() const {return Fvec;};
+    virtual fullVector<double>& getRefToFirstPiolaKirchhoffStressVect() {return Pvec;};
+    virtual const fullVector<double>& getConstRefToFirstPiolaKirchhoffStressVect() const {return Pvec;};
+    virtual fullVector<double>& getRefToInterfaceFluctuationVect() {return a;};
+    virtual const fullVector<double>& getConstRefToInterfaceFluctuationVect() const {return a;};
+
+    virtual STensor3& getReftoRotationMatrix() {return _R;};
+    virtual const STensor3& getConstReftoRotationMatrix() const {return _R;};
+
+    virtual IPVariable* getInternalData() {return NULL;};
+    virtual const IPVariable* getInternalData()  const {return NULL;};
+    virtual IPVariable* clone() const {return new StochDMNDG3DIPVariable(*this);};
+    virtual void restart();
+};
+
+// FLE
+class StochTMDMNDG3DIPVariable : public StochDMNDG3DIPVariable 
+{
+  protected:
+    int _col_Di, _row_Di;
+
+    // combined vectors
+    fullVector<double> FHvec; // F- defo, H -tempGrad
+    fullVector<double> PQvec; // P- 1st PK, Q-heatFlux
+    fullVector<double> ab;  // a- disp, b-temp
+    fullVector<double> Cpvec, thermSrcvec, mechSrcvec; 
+
+  public:
+    StochTMDMNDG3DIPVariable(const int NRoot, const int NInterface, const int col_Di, const int row_Di, const bool createBodyForceHO, const bool oninter);
+    StochTMDMNDG3DIPVariable(const StochTMDMNDG3DIPVariable& src);
+    virtual StochTMDMNDG3DIPVariable& operator =(const IPVariable& src);
+    virtual ~StochTMDMNDG3DIPVariable();
+
+    void InitializeFluctuationVector() {ab.setAll(0.0);};
+    virtual double defoEnergy() const;
+    virtual double plasticEnergy() const;
+    virtual double damageEnergy() const;
+    virtual double thermalEnergy() const;
+    virtual double getInternalEnergyExtraDofDiffusion() const {return this->thermalEnergy();};
+
+    void addIPv(int i, IPVariable* ipv);
+    IPVariable* getIPv(int i) {return _IPVector[i];};
+    const IPVariable* getIPv(int i) const {return _IPVector[i];};
+
+    virtual double get(const int comp) const;
+    virtual fullVector<double>& getRefToCombinedGradientVect() {return FHvec;};
+    virtual const fullVector<double>&  getConstRefToCombinedGradientVect() const {return FHvec;};
+    virtual fullVector<double>& getRefToCombinedStressVect() {return PQvec;};
+    virtual const fullVector<double>& getConstRefToCombinedStressVect() const {return PQvec;};
+    virtual fullVector<double>& getRefToCombinedInterfaceFluctuationVect() {return ab;};
+    virtual const fullVector<double>& getConstRefToCombinedInterfaceFluctuationVect() const {return ab;};
+    virtual fullVector<double>& getRefToCpVect() {return Cpvec;};
+    virtual const fullVector<double>&  getConstRefToCpVect() const {return Cpvec;};
+    virtual fullVector<double>& getRefToThermalSourceVect() {return thermSrcvec;};
+    virtual const fullVector<double>&  getConstRefToThermalSourceVect() const {return thermSrcvec;};
+    virtual fullVector<double>& getRefToMechSourceVect() {return mechSrcvec;};
+    virtual const fullVector<double>&  getConstRefToMechSourceVect() const {return mechSrcvec;};
+
+    virtual IPVariable* getInternalData() {return NULL;};
+    virtual const IPVariable* getInternalData()  const {return NULL;};
+    virtual IPVariable* clone() const {return new StochTMDMNDG3DIPVariable(*this);};
+    virtual void restart();
+};
+// FLE
+
 
 class LinearThermoMechanicsDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase
 {
@@ -5688,7 +5739,6 @@ public:
 
 // Take Care here, nonlocal variables cannot be directly defined with the ThermoMechanicsDG3DIPVariable Base Class (This is a pure virtual base class).
 
-// class NonLinearTVMDG3DIPVariable : public dG3DIPVariable{
 class NonLinearTVMDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   // Changed
 
   protected:
@@ -5696,8 +5746,6 @@ class NonLinearTVMDG3DIPVariable : public ThermoMechanicsDG3DIPVariableBase{   /
     NonLinearTVMDG3DIPVariable(const bool createBodyForceHO, const bool oninter):ThermoMechanicsDG3DIPVariableBase(createBodyForceHO, oninter) {Msg::Error("NonLinearTVMDG3DIPVariable: Cannot use the default constructor of ThermoMechanicsDG3DIPVariableBase");}
 
   public:
-// Constructor Changed
-  //  NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, const bool oninter=false, int nbExtraDof=0);  // ?? - WHAT to add/change?
     NonLinearTVMDG3DIPVariable(const mlawNonLinearTVM& viscoLaw, double Tinitial, const bool createBodyForceHO, const bool oninter);  // Changed
     NonLinearTVMDG3DIPVariable(const NonLinearTVMDG3DIPVariable& src);
     virtual NonLinearTVMDG3DIPVariable& operator = (const IPVariable& src);
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index 61e231436d125eab80eb4a5fe0a318438e75fd54..a8a50547267dee52bfbebec6e067c7a75a5ceb6e 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -3633,21 +3633,27 @@ double torchANNBasedDG3DMaterialLaw::soundSpeed() const
 
 
 
-StochDMNDG3DMaterialLaw::StochDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree, const bool porous,const double tol):
-  dG3DMaterialLaw(num,rho,false), _ReadTree(ReadTree), _porous(porous),_tol(tol){
-  if(_ReadTree){
-    read_TreeData(ParaFile);
-  }
-  else{
-    read_parameter(ParaFile);
-  }  
-  fill_Matrices();         
+StochDMNDG3DMaterialLaw::StochDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree, const bool porous,const double tol, const bool flag_isothermal):
+  dG3DMaterialLaw(num,rho,false), _ReadTree(ReadTree), _porous(porous),_tol(tol), _flag_isothermal(flag_isothermal){
+  
+    _alpha = 0.; _beta = 0.; _gamma = 0.; 
+  
+  if(_flag_isothermal){
+    if(_ReadTree){
+      read_TreeData(ParaFile);
+    }
+    else{
+      read_parameter(ParaFile);
+    }  
+    fill_Matrices();        
+  } 
 }
 
 StochDMNDG3DMaterialLaw::StochDMNDG3DMaterialLaw(const StochDMNDG3DMaterialLaw &src): dG3DMaterialLaw(src), _ReadTree(src._ReadTree), _porous(src._porous), 
     _LevelNode(src._LevelNode), _NodeLevel(src._NodeLevel), _Mat_Id(src._Mat_Id), _Parent(src._Parent), _Child(src._Child), _TotalLevel(src._TotalLevel), _NLeaf(src._NLeaf),
        _NInterface(src._NInterface), _N_Node(src._N_Node), _NPara_Wt(src._NPara_Wt), _NPara_Norm(src._NPara_Norm), _Dim(src._Dim), _Vf(src._Vf), _tol(src._tol),
-       _Nv(src._Nv), _NTV(src._NTV), _V(src._V), _Para_Wt(src._Para_Wt), _Para_Norm(src._Para_Norm), _VA(src._VA), _VI(src._VI), _mapLaw(src._mapLaw){ }
+       _Nv(src._Nv), _NTV(src._NTV), _V(src._V), _Para_Wt(src._Para_Wt), _Para_Norm(src._Para_Norm), _VA(src._VA), _VI(src._VI), _mapLaw(src._mapLaw),
+       _flag_isothermal(src._flag_isothermal), _alpha(src._alpha), _beta(src._beta), _gamma(src._gamma){ }
 
 StochDMNDG3DMaterialLaw::~StochDMNDG3DMaterialLaw(){};
 
@@ -3872,6 +3878,9 @@ void StochDMNDG3DMaterialLaw::getLeafOfInterface(const int pos, int &node_start,
 }  
          
 void StochDMNDG3DMaterialLaw::fill_NLocal(const int pos, double N[][3])const{
+
+  // code to fill a matrix related to local normals
+
   double n0 = _Para_Norm[pos][0];
   double n1 = _Para_Norm[pos][1];
   double n2 = _Para_Norm[pos][2];
@@ -3897,7 +3906,7 @@ void StochDMNDG3DMaterialLaw::fill_W_WI(const int pos, double W[][2]){
   double VI = _VI[pos];
   double Wtmp0 = _Para_Wt[pos][0];
   double Wtmp1 = _Para_Wt[pos][1];
-  double WA = Wtmp0*(1.0-VI)+ Wtmp1*VI;
+  double WA = Wtmp0*(1.0-VI)+ Wtmp1*VI; // Eq. 39 in Ling's draft
 
   for(int i=0; i<2; i++){
     for(int j=0; j<2; j++){
@@ -3906,13 +3915,14 @@ void StochDMNDG3DMaterialLaw::fill_W_WI(const int pos, double W[][2]){
   }
   W[0][0]= WA;
   W[0][1]= 1.0-WA;
-  W[1][0]= (Wtmp1*VI)/WA;
-  W[1][1]= ((1.0-Wtmp1)*VI)/(1.0-WA);
+  W[1][0]= (Wtmp1*VI)/WA; // Eq. 40 in Ling's draft, v_1A
+  W[1][1]= ((1.0-Wtmp1)*VI)/(1.0-WA); // Eq. 40 in Ling's draft, v_1B
 }
 
 
 // fill the matrices which keep the topological information
-void  StochDMNDG3DMaterialLaw::fill_Matrices(){    
+void  StochDMNDG3DMaterialLaw::fill_Matrices(){  
+
   double Norm[9][3];
   double W_WI[2][2];
   int pos0, pos1;
@@ -4116,7 +4126,7 @@ void StochDMNDG3DMaterialLaw::read_parameter(const char *ParaFile){
     }  
   }
    
-  Msg::Info("Finish reading parameter filefor Complete Binary Tree,  level = %d, Dim = %d, NLeaf = %d", _TotalLevel, _Dim, _NLeaf);
+  Msg::Info("Finish reading parameter file for Complete Binary Tree,  level = %d, Dim = %d, NLeaf = %d", _TotalLevel, _Dim, _NLeaf);
 }
    // end of read_parameter 
  
@@ -4385,7 +4395,7 @@ void StochDMNDG3DMaterialLaw::stress(IPVariable*ipv, const IPVariable*ipvprev, c
       }
     }
 
-    _NTV.mult(Pvec, Res_node);
+    _NTV.mult(Pvec, Res_node); // Eq 60 in Ling's draft, Res_node = residual at the node
     r = Res_node.norm()/_NInterface;
     
     _NTV.mult(_C, NTVC);
@@ -4418,7 +4428,7 @@ void StochDMNDG3DMaterialLaw::stress(IPVariable*ipv, const IPVariable*ipvprev, c
 
     if(stiff){
       NTVC.mult(_I, dRdF);
-      Jacobian.mult(dRdF, dadF);
+      Jacobian.mult(dRdF, dadF); // Eq. 68 in Ling's draft
       _Nv.mult(dadF, tmp);
       tmp.add(_I);
 
@@ -4994,7 +5004,956 @@ void StochDMNDG3DMaterialLaw::setTime(const double t,const double dtime){
   }
 }
 
-//
+void StochDMNDG3DMaterialLaw::eulerZXZToRotationMatrix(const double phi, const double theta, const double psi, STensor3& rotationMatrix) {
+  double cosPhi = cos(phi);
+  double sinPhi = sin(phi);
+  double cosTheta = cos(theta);
+  double sinTheta = sin(theta);
+  double cosPsi = cos(psi);
+  double sinPsi = sin(psi);
+
+  rotationMatrix(0,0) = cosPsi * cosPhi - cosTheta * sinPhi * sinPsi;
+  rotationMatrix(0,1) = cosPsi * sinPhi + cosTheta * cosPhi * sinPsi;
+  rotationMatrix(0,2) = sinPsi * sinTheta;
+
+  rotationMatrix(1,0) = -sinPsi * cosPhi - cosTheta * sinPhi * cosPsi;
+  rotationMatrix(1,1) = -sinPsi * sinPhi + cosTheta * cosPhi * cosPsi;
+  rotationMatrix(1,2) = cosPsi * sinTheta;
+
+  rotationMatrix(2,0) = sinTheta * sinPhi;
+  rotationMatrix(2,1) = -sinTheta * cosPhi;
+  rotationMatrix(2,2) = cosTheta;
+}
+
+void StochDMNDG3DMaterialLaw::setZXZRotationMatrix_in_IP(StochDMNDG3DIPVariable* ipv){
+  STensor3& R = ipv->getReftoRotationMatrix();
+  eulerZXZToRotationMatrix(_alpha,_beta,_gamma,R);
+}; 
+
+// FLE
+StochTMDMNDG3DMaterialLaw::StochTMDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree,
+      const bool porous, const bool flag_isothermal, const bool flag_microTempFixed, const double tol):
+      StochDMNDG3DMaterialLaw(num,rho,E,nu,ParaFile,ReadTree,porous,tol,flag_isothermal),_flag_microTempFixed(flag_microTempFixed){
+  
+  // Meanings of _col_Di and _row_Di are interchanged in this class.
+  if (_flag_isothermal && _flag_microTempFixed){
+    _col_Di = 9; _row_Di = 3;
+  }
+  else if(!_flag_isothermal && _flag_microTempFixed){
+    _col_Di = 12; _row_Di = 4;
+  }
+  else if(!_flag_isothermal && !_flag_microTempFixed){ // Deprecated option - Impossible to implement without length scale.
+    _col_Di = 13; _row_Di = 5;
+  }
+  else{
+    Msg::Error("This combination of flags doesn't exist. Redefine in the constructor.");
+  }
+  if(_ReadTree){
+    StochTMDMNDG3DMaterialLaw::read_TreeData(ParaFile);
+  }
+  else{
+    StochTMDMNDG3DMaterialLaw::read_parameter(ParaFile);
+  }
+
+  StochTMDMNDG3DMaterialLaw::fill_Matrices();         
+}
+
+StochTMDMNDG3DMaterialLaw::StochTMDMNDG3DMaterialLaw(const StochTMDMNDG3DMaterialLaw &source): StochDMNDG3DMaterialLaw(source), 
+    _col_Di(source._col_Di), _row_Di(source._row_Di), _flag_microTempFixed(source._flag_microTempFixed), _Para_Alpha(source._Para_Alpha){};
+
+StochTMDMNDG3DMaterialLaw::~StochTMDMNDG3DMaterialLaw(){};
+
+void StochTMDMNDG3DMaterialLaw::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 StochTMDMNDG3DIPVariable(_NLeaf, _NInterface, _col_Di, _row_Di, hasBodyForce,inter);
+    IPVariable* ipv1 = new StochTMDMNDG3DIPVariable(_NLeaf, _NInterface, _col_Di, _row_Di, hasBodyForce,inter);
+    IPVariable* ipv2 = new StochTMDMNDG3DIPVariable(_NLeaf, _NInterface, _col_Di, _row_Di, hasBodyForce,inter);
+
+    StochTMDMNDG3DIPVariable* ipvi_Leaf = static_cast<StochTMDMNDG3DIPVariable*>(ipvi);
+    StochTMDMNDG3DIPVariable* ipv1_Leaf = static_cast<StochTMDMNDG3DIPVariable*>(ipv1);
+    StochTMDMNDG3DIPVariable* ipv2_Leaf = static_cast<StochTMDMNDG3DIPVariable*>(ipv2);
+    int mat_IP;
+    for (int i=0; i< _NLeaf; i++){
+      mat_IP = _Mat_Id[_NInterface + i];
+      IPStateBase* ips_i = NULL;
+      _mapLaw[mat_IP]->createIPState(ips_i, hasBodyForce, state_, ele, nbFF_, GP, gpt);
+      std::vector<IPVariable*> ip_all;
+      ips_i->getAllIPVariable(ip_all);
+      ipvi_Leaf->addIPv(i, ip_all[0]);
+      ipv1_Leaf->addIPv(i, ip_all[1]);
+      ipv2_Leaf->addIPv(i, ip_all[2]);
+    }
+    if(ips != NULL) delete ips;
+      ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void StochTMDMNDG3DMaterialLaw::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  StochTMDMNDG3DIPVariable(_NLeaf, _NInterface, _col_Di, _row_Di, hasBodyForce,inter);
+  StochTMDMNDG3DIPVariable* ipv_Leaf = static_cast<StochTMDMNDG3DIPVariable*>(ipv);
+  int mat_IP;
+  for (int i=0; i< _NLeaf; i++){
+    IPVariable* ipv_i = NULL;
+    mat_IP = _Mat_Id[_NInterface + i];
+    _mapLaw[mat_IP]->createIPVariable(ipv_i, hasBodyForce, ele, nbFF_, GP, gpt);
+    ipv_Leaf->addIPv(i, ipv_i);
+  }
+};
+
+void StochTMDMNDG3DMaterialLaw::initialIPVariable(IPVariable* ipv, bool stiff){
+  StochTMDMNDG3DIPVariable* ipv_all = dynamic_cast<StochTMDMNDG3DIPVariable*>(ipv);
+  ipv_all->InitializeFluctuationVector();
+  if (ipv_all == NULL){
+    Msg::Error("StochTMDMNDG3DIPVariable must be used in StochTMDMNDG3DMaterialLaw::initialIPVariable");
+  }
+  int mat_IP;
+  for (int i=0; i< _NLeaf; i++){
+    IPVariable* ipv_i = ipv_all->getIPv(i);
+    mat_IP = _Mat_Id[_NInterface + i];
+    _mapLaw[mat_IP]->initialIPVariable(ipv_i, stiff);
+  }
+}
+
+void StochTMDMNDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{
+  StochTMDMNDG3DIPVariable* ipv_all = dynamic_cast<StochTMDMNDG3DIPVariable*>(ipv);
+  const StochTMDMNDG3DIPVariable* ipvprev_all = dynamic_cast<const StochTMDMNDG3DIPVariable*>(ipvprev);
+  if (ipv_all == NULL){
+    Msg::Error("StochTMDMNDG3DIPVariable must be used in StochTMDMNDG3DMaterialLaw::checkInternalState");
+  }
+  int mat_IP;
+  for (int i=0; i< _NLeaf; i++){
+    IPVariable* ipv_i = ipv_all->getIPv(i);
+    const IPVariable* ipvprev_i = ipvprev_all->getIPv(i);
+    mat_IP = _Mat_Id[_NInterface + i];
+    _mapLaw[mat_IP]->checkInternalState(ipv_i, ipvprev_i);
+  }
+}
+
+void StochTMDMNDG3DMaterialLaw::setMacroSolver(const nonLinearMechSolver* sv){
+   dG3DMaterialLaw::setMacroSolver(sv);
+    for (std::vector<dG3DMaterialLaw*>::iterator ite = _mapLaw.begin(); ite!= _mapLaw.end(); ite++){
+      (*ite)->setMacroSolver(sv);
+    }
+}
+
+void StochTMDMNDG3DMaterialLaw::fill_NLocal(const int pos, fullMatrix<double> N)const{
+
+  // code to fill a matrix related to local normals
+
+  double n0 = _Para_Norm[pos][0];
+  double n1 = _Para_Norm[pos][1];
+  double n2 = _Para_Norm[pos][2];
+
+  if (_flag_isothermal && _flag_microTempFixed){
+    N.set(0,0,n0); N.set(1,1,n0); N.set(2,2,n0);
+    N.set(3,0,n1); N.set(4,1,n1); N.set(5,2,n1);
+    N.set(6,0,n2); N.set(7,1,n2); N.set(8,2,n2);
+  }
+  else if(!_flag_isothermal && _flag_microTempFixed){
+    N.set(0,0,n0); N.set(1,1,n0); N.set(2,2,n0);
+    N.set(3,0,n1); N.set(4,1,n1); N.set(5,2,n1);
+    N.set(6,0,n2); N.set(7,1,n2); N.set(8,2,n2);
+    N.set(9,3,n0); N.set(10,3,n1); N.set(11,3,n2);
+  }
+  else if(!_flag_isothermal && !_flag_microTempFixed){
+    N.set(0,0,n0); N.set(1,1,n0); N.set(2,2,n0);
+    N.set(3,0,n1); N.set(4,1,n1); N.set(5,2,n1);
+    N.set(6,0,n2); N.set(7,1,n2); N.set(8,2,n2);
+    N.set(9,3,n0); N.set(10,3,n1); N.set(11,3,n2);
+    N.set(12,4,1.);
+  }
+  else{
+    Msg::Error("This combination of flags doesn't exist. Redefine in the constructor.");
+  }
+}
+
+void StochTMDMNDG3DMaterialLaw::initLaws(const std::map<int,materialLaw*> &maplaw){
+  // To define this function, StochDMNDG3DMaterialLaw::TwoPhasesInteract has to be redefined in this class.
+}
+
+// fill the matrices which keep the topological information
+void StochTMDMNDG3DMaterialLaw::fill_Matrices(){  
+
+  fullMatrix<double> Norm; bool resizeFlag = Norm.resize(_col_Di, _row_Di, true);
+  double W_WI[2][2];
+  int pos0, pos1;
+  int L_ch0, L_ch1;
+  int node_start0, node_end0, node_start1, node_end1;
+  int Col_start, Col_start0, Col_start1, Row_start, Row_start0, Row_start1;
+  double tmp;
+  int col = _col_Di; // = 9, 12;   // set the size of rows and cols in Di matrix
+  
+  _VA.resize(_N_Node,0.0); // Vector for position of nodes for Stress
+  _VA[0] = 1.0;
+  _VI.resize(_NInterface, 0.0); // fill matrix for equilibrium of interface
+  _VI[0] = _Vf;
+  int l;
+
+  for(int pos=0; pos <_NInterface; pos++){
+    l = _NodeLevel[pos];
+    StochTMDMNDG3DMaterialLaw::fill_NLocal(pos,Norm);  // size of Norm depends on the flags set inside this function
+    pos0 = _Child[pos][0];
+    pos1 = _Child[pos][1];
+    L_ch0 = _NodeLevel[pos0];
+    L_ch1 = _NodeLevel[pos1];
+    Row_start = pos*_row_Di; // 3, 4;
+    Col_start0 = (pos0-1)*col;
+    Col_start1 = (pos1-1)*col;
+
+    double S_ba = 1.0;
+    if(l ==_TotalLevel-1 and _porous) S_ba = _Para_Wt[pos][1];
+
+    // information of interface norm
+    for(int nc=0; nc<col;nc++){
+      for(int nr=0; nr<_row_Di; nr++){
+        _NT.set(Row_start+nr, Col_start0+nc, Norm(nc,nr));
+        _NT.set(Row_start+nr, Col_start1+nc,-S_ba*Norm(nc,nr));
+      }
+    }
+
+    if(l ==_TotalLevel-1){ // Last level
+      if(_porous){
+        _VA[pos0] = (1.0-_VI[pos])*_Para_Wt[pos][0];
+        _VA[pos1] = (1.0-_VI[pos])*(1.0-_Para_Wt[pos][0]);
+      }
+      else{
+        _VA[pos0] = 1.0-_VI[pos];
+        _VA[pos1] = _VI[pos];
+      }
+    }
+    else{ // Composite nodes - all other levels
+      StochDMNDG3DMaterialLaw::fill_W_WI(pos,W_WI);
+      _VA[pos0] = W_WI[0][0];
+      _VA[pos1] = W_WI[0][1];
+      if(L_ch0 < _TotalLevel) _VI[pos0]=W_WI[1][0];
+      if(L_ch1 < _TotalLevel) _VI[pos1]=W_WI[1][1];
+      // Msg::Info("Node= %d,%d,%d, VI = %f,%f,%f",pos,pos0,pos1,_VI[pos],W_WI[1][0],W_WI[1][1]);
+    }
+    //information of homogenous strain to local strain
+    Col_start = pos*_row_Di; // *3, 4 // Note that the meanings of _row_Di and _col_Di have been swapped
+    StochDMNDG3DMaterialLaw::getLeafOfInterface(pos0, node_start0, node_end0);
+    StochDMNDG3DMaterialLaw::getLeafOfInterface(pos1, node_start1, node_end1);
+    for(int r=node_start0; r<=node_end0; r++){
+      Row_start0 = (r-_NInterface)*col;
+      for(int nr=0; nr<col;nr++){
+        for(int nc=0; nc<_row_Di;nc++){
+          _Nv.set(Row_start0+nr, Col_start+nc, Norm(nr,nc)/_VA[pos0]);
+        }
+      }
+    }
+    for(int r=node_start1; r<=node_end1; r++){
+      Row_start1 = (r-_NInterface)*col;
+      for(int nr=0; nr<col;nr++){
+        for(int nc=0; nc<_row_Di;nc++){
+          _Nv.set(Row_start1+nr, Col_start+nc,-S_ba*Norm(nr,nc)/_VA[pos1]);
+        }
+      }
+    }         
+  }
+
+ // information of volume fraction to stress on node
+  Row_start = col*(_N_Node-1-_NLeaf);
+  for(int nc=0; nc<col*_NLeaf; nc++){
+    _V.set(Row_start+nc,nc,1.0);
+  }
+
+  for(int pos = _NInterface-1; pos > 0; pos--){
+    pos0 = _Child[pos][0];
+    pos1 = _Child[pos][1];
+    Row_start = (pos-1)*col;
+    Row_start0 = (pos0-1)*col;
+    Row_start1 = (pos1-1)*col;
+    for(int nr=0; nr<col;nr++){
+      for(int nc=0; nc<col*_NLeaf ; nc++){
+        tmp = _VA[pos0]*_V(Row_start0+nr,nc) + _VA[pos1]*_V(Row_start1+nr,nc);
+        _V.set(Row_start+nr,nc, tmp);
+      }
+    }
+  }
+  _NT.mult(_V, _NTV);
+
+  for(int i=0; i<col*_NLeaf;i++){
+    _I(i, i%col) = 1.0;
+  }
+}
+ // end fill_matrices
+
+// read parameter from input file
+void StochTMDMNDG3DMaterialLaw::read_parameter(const char *ParaFile){
+
+  double sin0, cos0, sin1, cos1;
+
+  FILE *Para = fopen(ParaFile, "r");
+  if ( Para != NULL ){
+    int okf = fscanf(Para, "%d %d\n", &_Dim, &_TotalLevel);
+
+    bool resizeFlag;
+    _NLeaf = int(pow(2,_TotalLevel));
+    _NInterface = _NLeaf-1;
+    _N_Node = _NLeaf + _NInterface;
+
+    int row = _col_Di*_NLeaf;
+    int col = _row_Di*_NInterface;
+    resizeFlag = _Nv.resize(row, col, true);
+
+    resizeFlag = _I.resize(row, _col_Di, true);
+
+    row = _col_Di*(_N_Node-1);
+    col = _col_Di*_NLeaf;
+    resizeFlag = _V.resize(row, col, true);
+        
+    row = _row_Di*_NInterface;        
+    resizeFlag = _NTV.resize(row, col, true);  
+    
+    resizeFlag = _NT.resize(row, _col_Di*(_N_Node-1), true);            
+        
+    okf = fscanf(Para, "%lf\n", &_Vf);
+
+    _NPara_Norm = _NInterface;
+    
+    resizeFlag = _C.resize(col,col,true);
+    resizeFlag = Jacobian.resize(row,row,true); 
+    
+    resizeFlag = _ParaAngle.resize(_NInterface,2,true);
+        
+    double ParaN[2]; // W_alpha and w_beta -> Eq. 37 in Ling's draft
+    double Pi(3.14159265359);        
+    SPoint3 Para_Norm;
+    SPoint2 Para_Wt;
+
+    for(int i=0;i<_NInterface;i++){        
+      if(_Dim==2){  
+        okf = fscanf(Para, "%lf\n", &ParaN[0]);
+        ParaN[1] = 0.0; 
+      }
+      else if(_Dim==3){
+        okf = fscanf(Para, "%lf %lf\n", &ParaN[0],  &ParaN[1]);
+      }
+      sin0 = sin(2.0*Pi*ParaN[0]);
+      cos0 = cos(2.0*Pi*ParaN[0]);
+      sin1 = sin(Pi*ParaN[1]);
+      cos1 = cos(Pi*ParaN[1]);
+      Para_Norm[0] = cos1*sin0;
+      Para_Norm[1] = cos1*cos0;
+      Para_Norm[2] = sin1;
+      _Para_Norm.push_back(Para_Norm); 
+      _ParaAngle(i,0) =  ParaN[0];
+      _ParaAngle(i,1) =  ParaN[1]; 
+    }       
+        
+    if(_porous){
+      _NPara_Wt = _NInterface;
+    }
+    else{
+      _NPara_Wt = int(pow(2,(_TotalLevel-1)))-1;
+    }
+    for(int i=0;i<_NPara_Wt;i++){
+      okf = fscanf(Para, "%lf %lf\n", &Para_Wt[0],  &Para_Wt[1]);
+      _Para_Wt.push_back(Para_Wt);
+    }
+  }
+   // creat data as for tree data
+  int n = 0;
+  int m = -10;
+  for(int l=0; l<=_TotalLevel; l++){
+    std::vector<int> ln;
+    _LevelNode.push_back(ln);
+    while(n < pow(2,l+1)-1){
+      _LevelNode[l].push_back(n);
+      _NodeLevel.push_back(l);
+      if(n==0){
+        _Parent.push_back(0);
+      }
+      else{
+        _Parent.push_back(int((n-1)/2));
+      }
+      if(l==_TotalLevel){
+        _Mat_Id.push_back((n+1)%2);
+      }
+      else{
+        std::vector<int> ch;
+        ch.push_back(2*n+1);
+        ch.push_back(2*n+2);
+        _Child.push_back(ch);
+        _Mat_Id.push_back(m);
+      }      
+      n +=1;
+    }  
+  }
+
+  Msg::Info("Finished reading parameter file for Complete Binary Tree,  level = %d, Dim = %d, NLeaf = %d", _TotalLevel, _Dim, _NLeaf);
+}
+   // end of read_parameter
+
+void StochTMDMNDG3DMaterialLaw::read_TreeData(const char *TreeFile){
+  std::ifstream file(TreeFile);
+  if(!file.is_open()) {
+        Msg::Error( "Error: Could not open the tree file." );
+        return ;
+  }
+  int level_value, node_value, parent_value;
+  double sin0, cos0, sin1,cos1;
+  double ParaN[2];
+  int pn = 0;
+  double Pi(3.14159265359);        
+  SPoint3 Para_Norm;
+  SPoint2 Para_Wt;
+  bool resizeFlag;
+  
+  std::string line;
+  int DataId = 0;
+  while(std::getline(file, line)) {
+    if(line.empty()) continue;
+    std::istringstream stream(line);
+    std::string value;
+    std::vector<std::string> row;
+    while (std::getline(stream, value, ',')) {
+      row.push_back(value);  
+    }
+    if (std::isalpha(row[0][0])){
+      DataId +=1;
+      if(DataId == 4){      
+        _NLeaf = static_cast<int>(_LevelNode[_TotalLevel].size());
+        _N_Node = static_cast<int>(_Parent.size());
+        _NInterface = _N_Node - _NLeaf;
+        resizeFlag = _ParaAngle.resize(_NInterface,2,true); 
+      } 
+    }
+    else{      
+      if(DataId == 1){                            // read the tree structure------------------
+        _TotalLevel = std::stoi(row[0]); 
+        for(int i=0; i<=_TotalLevel; i++){
+          std::vector<int> LN;
+          _LevelNode.push_back(LN);
+        }
+      }  
+      else if(DataId == 2){ 
+        level_value = std::stoi(row[0]);
+        node_value = std::stoi(row[1]);
+        parent_value = std::stoi(row[2]);
+        _Mat_Id.push_back(std::stoi(row[3]));
+                
+        _LevelNode[level_value].push_back(node_value);
+        _NodeLevel.push_back(level_value);
+        _Parent.push_back(parent_value);
+                
+        if(level_value < _TotalLevel){
+          std::vector<int> ch;
+          _Child.push_back(ch);
+        }  
+        if(parent_value != node_value) _Child[parent_value].push_back(node_value);
+      }  
+      else if(DataId == 3){               // read the DMN Parameter  -----------------------
+        _Dim = std::stoi(row[0]);
+        _Vf = std::stod(row[1]);        
+      }    
+      else if(DataId == 4){
+        if(_Dim==2){
+          ParaN[0] = std::stod(row[0]);           
+          ParaN[1] = 0.0;
+        }
+        else if(_Dim==3){
+          ParaN[0] = std::stod(row[0]);           
+          ParaN[1] = std::stod(row[1]);         
+        }          
+        sin0 = sin(2.0*Pi*ParaN[0]);
+        cos0 = cos(2.0*Pi*ParaN[0]);
+        sin1 = sin(Pi*ParaN[1]);
+        cos1 = cos(Pi*ParaN[1]);
+        Para_Norm[0] = cos1*sin0;
+        Para_Norm[1] = cos1*cos0;
+        Para_Norm[2] = sin1;
+        _Para_Norm.push_back(Para_Norm); 
+        _ParaAngle(pn,0) =  ParaN[0];
+        _ParaAngle(pn,1) =  ParaN[1]; 
+        pn +=1;
+      }  
+      else if(DataId == 5){
+        Para_Wt[0] = std::stod(row[0]);
+        Para_Wt[1] = std::stod(row[1]);
+        _Para_Wt.push_back(Para_Wt);
+      }
+    }
+  }      
+    
+  int row = _col_Di*_NLeaf;
+  int col = _row_Di*_NInterface;
+  resizeFlag = _Nv.resize(row, col, true);
+  resizeFlag = _I.resize(row, _col_Di, true);
+
+  row = _col_Di*(_N_Node-1);
+  col = _col_Di*_NLeaf;
+  resizeFlag = _V.resize(row, col, true);
+        
+  row = _row_Di*_NInterface;  
+  resizeFlag = _NT.resize(row, _col_Di*(_N_Node-1), true);         
+  resizeFlag = _NTV.resize(row, col, true);     
+           
+  resizeFlag = _C.resize(col, col,true);
+  resizeFlag = Jacobian.resize(row, row,true); 
+  _NPara_Norm = _NInterface; 
+  _NPara_Wt = static_cast<int>(_Para_Wt.size()); 
+  
+  Msg::Info("Finish reading Tree Data and parameter file, level = %d, Dim = %d, NLeaf = %d", _TotalLevel, _Dim, _NLeaf);
+}  
+
+void StochTMDMNDG3DMaterialLaw::reset_Parameter(std::vector<std::vector<double>>& Para_Norm, std::vector<std::vector<double>>& Para_Wt, std::vector<double>& Para_Alpha, const double Vf){
+    
+  double sin0, cos0, sin1,cos1; 
+  double Pi(3.14159265359);
+  for(int i=0;i<_NInterface;i++){ 
+    if(_Dim==2){
+      sin1 = 0.0;
+      cos1 = 1.0;
+      _ParaAngle(i,0) =  Para_Norm[i][0];
+    }
+    else if(_Dim==3){
+      sin1 = sin(Pi*Para_Norm[i][1]);
+      cos1 = cos(Pi*Para_Norm[i][1]); 
+      _ParaAngle(i,0) =  Para_Norm[i][0];
+      _ParaAngle(i,1) =  Para_Norm[i][1]; 
+    }  
+    sin0 = sin(2.0*Pi*Para_Norm[i][0]);
+    cos0 = cos(2.0*Pi*Para_Norm[i][0]);
+    _Para_Norm[i][0] = cos1*sin0;
+    _Para_Norm[i][1] = cos1*cos0;
+    _Para_Norm[i][2] = sin1; 
+  }      
+       
+  for(int i=0;i<_NPara_Wt;i++){          
+    _Para_Wt[i][0] = Para_Wt[i][0]; 
+    _Para_Wt[i][1] = Para_Wt[i][1]; 
+    if(_NodeLevel[_Child[i][1]]==_TotalLevel) _Para_Wt[i][1] = 1.0; 
+  }      
+  for(int i=0;i<Para_Alpha.size();i++){          
+    _Para_Alpha[i] = _Para_Alpha[i]; 
+    _Para_Alpha[i] = _Para_Alpha[i]; 
+  } 
+  _VA.clear();
+  _VI.clear();
+  _Nv.setAll(0.0);
+  _NTV.setAll(0.0);
+  _NT.setAll(0.0);
+  _V.setAll(0.0);
+  _I.setAll(0.0);
+  _C.setAll(0.0);
+  Jacobian.setAll(0.0);
+  if(Vf!= 0.0){
+    _Vf = Vf;
+  }
+  StochTMDMNDG3DMaterialLaw::fill_Matrices();     
+  //Msg::Info("Finish update parameters of DMN ");       
+}    
+
+void StochTMDMNDG3DMaterialLaw::reset_Parameter(const char* Para){
+  _VA.clear();
+  _VI.clear();
+  _Para_Norm.clear();
+  _Para_Wt.clear();
+  _Para_Alpha.clear();
+  _LevelNode.clear(); 
+  _NodeLevel.clear();    
+  _Mat_Id.clear();
+  _Parent.clear();      
+  _Child.clear();
+  if(_ReadTree){
+    StochTMDMNDG3DMaterialLaw::read_TreeData(Para);
+  }
+  else{
+    StochTMDMNDG3DMaterialLaw::read_parameter(Para);
+  } 
+  StochTMDMNDG3DMaterialLaw::fill_Matrices();
+}
+
+void StochTMDMNDG3DMaterialLaw::stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff, const bool checkfrac, const bool dTangent){
+   
+   // get ipvariable 
+  StochTMDMNDG3DIPVariable* ipvcur = static_cast<StochTMDMNDG3DIPVariable*>(ipv);
+  const StochTMDMNDG3DIPVariable* ipv_prev = static_cast<const StochTMDMNDG3DIPVariable*>(ipvprev);
+  const STensor3& F = ipvcur->getConstRefToDeformationGradient();
+  const SVector3& H = ipvcur->getConstRefToGradT();
+  const double T    = ipvcur->getConstRefToTemperature();
+
+  STensor3& P = ipvcur->getRefToFirstPiolaKirchhoffStress(); STensorOperation::zero(P);
+  SVector3& Q = ipvcur->getRefToThermalFlux(); STensorOperation::zero(Q);
+  double& w   = ipvcur->getRefToThermalSource(); w = 0.;
+  double& Cp         = ipvcur->getRefToExtraDofFieldCapacityPerUnitField()(0);
+  double& mechSource = ipvcur->getRefToMechanicalSource()(0); mechSource = 0.; 
+
+  STensor43& L       = ipvcur->getRefToTangentModuli(); STensorOperation::zero(L);
+  STensor3& dPdT     = ipvcur->getRefTodPdT(); STensorOperation::zero(dPdT);
+  STensor3& dqdgradT = ipvcur->getRefTodThermalFluxdGradT(); STensorOperation::zero(dqdgradT);
+  SVector3& dqdT     = ipvcur->getRefTodThermalFluxdT(); STensorOperation::zero(dqdT);
+  STensor33& dqdF    = ipvcur->getRefTodThermalFluxdF(); STensorOperation::zero(dqdF);
+  double& dwdt       = ipvcur->getRefTodThermalSourcedField();
+  STensor3& dwdf     = ipvcur->getRefTodThermalSourcedF(); STensorOperation::zero(dwdf);
+  double& dmechSourcedt = ipvcur->getRefTodMechanicalSourcedField()(0,0); dmechSourcedt = 0.;
+  STensor3& dmechSourcedf = ipvcur->getRefTodMechanicalSourcedF()[0]; STensorOperation::zero(dmechSourcedf);
+  double dCpdT(0.);
+  STensor3 dCpdF; STensorOperation::zero(dCpdF);
+  STensor33 dPdgradT; STensorOperation::zero(dPdgradT);
+
+  // The tangent C_hom is combined with thermal tangents.
+  fullMatrix<double> C_hom(_col_Di,_col_Di); 
+  // if(C_hom.size1()!=_col_Di || C_hom.size2()!=_col_Di){C_hom.resize(_col_Di,_col_Di);}; 
+  C_hom.setAll(0.); 
+  fullVector<double> PQ_hom(_col_Di); 
+  // if(PQ_hom.size()!=_col_Di){PQ_hom.resize(_col_Di);}; 
+  PQ_hom.setAll(0.);
+  fullVector<double> dPQdT_hom(_col_Di); 
+  // if(dPQdT_hom.size()!=_col_Di){dPQdT_hom.resize(_col_Di);}; 
+  dPQdT_hom.setAll(0.);
+  double Cp_hom(0.), thermSrc_hom(0.), mechSource_hom(0.), dwdt_hom(0.), dmechSourcedt_hom(0.);
+  fullVector<double> dwdf_hom(9), dmechSourcedf_hom(9); dwdf_hom.setAll(0.); dmechSourcedf_hom.setAll(0.);
+
+  fullVector<double>& FHvec = ipvcur->getRefToCombinedGradientVect();
+  fullVector<double>& PQvec = ipvcur->getRefToCombinedStressVect(); PQvec.setAll(0.0);
+  fullVector<double>& ab_cur = ipvcur->getRefToCombinedInterfaceFluctuationVect();
+  fullVector<double>& Cpvec = ipvcur->getRefToCpVect(); Cpvec.setAll(0.0);
+  fullVector<double>& thermSrcvec = ipvcur->getRefToThermalSourceVect(); thermSrcvec.setAll(0.0);
+  fullVector<double>& mechSrcvec = ipvcur->getRefToMechSourceVect(); mechSrcvec.setAll(0.0); 
+  fullVector<double> dwdtvec, dmechSrcdTvec, dwdFvec, dmechSrcdFvec;
+  dwdtvec.resize(_NLeaf); dwdtvec.setAll(0.); dmechSrcdTvec.resize(_NLeaf); dmechSrcdTvec.setAll(0.);
+  dwdFvec.resize(9*_NLeaf); dwdFvec.setAll(0.); dmechSrcdFvec.resize(9*_NLeaf); dmechSrcdFvec.setAll(0.);
+
+  fullVector<double> Res_node(_row_Di*_NInterface); 
+  // if(Res_node.size()!=_row_Di*_NInterface){Res_node.resize(_row_Di*_NInterface);}; 
+  Res_node.setAll(0.);  
+  fullVector<double> ab_step(_row_Di*_NInterface); 
+  // if(ab_step.size()!=_row_Di*_NInterface){ab_step.resize(_row_Di*_NInterface);}; 
+  ab_step.setAll(0.0);
+  fullMatrix<double> NTVC(_row_Di*_NInterface, _col_Di*_NLeaf); 
+  // if(NTVC.size1()!=_row_Di*_NInterface || NTVC.size2()!=_col_Di*_NLeaf){NTVC.resize(_row_Di*_NInterface, _col_Di*_NLeaf);}; 
+  NTVC.setAll(0.0); 
+  fullMatrix<double> Jacobian_inv(_row_Di*_NInterface, _row_Di*_NInterface); 
+  // if(Jacobian_inv.size1()!=_row_Di*_NInterface || Jacobian_inv.size2()!=_row_Di*_NInterface){Jacobian_inv.resize(_row_Di*_NInterface, _row_Di*_NInterface);}; 
+  Jacobian_inv.setAll(0.0); 
+  fullMatrix<double> tmp(_col_Di*_NLeaf, _col_Di); 
+  // if(tmp.size1()!=_col_Di*_NLeaf || tmp.size2()!=_col_Di){tmp.resize(_col_Di*_NLeaf, _col_Di);}; 
+  tmp.setAll(0.0); 
+  fullMatrix<double> dRdF(_row_Di*_NInterface, _col_Di); 
+  // if(dRdF.size1()!=_row_Di*_NInterface || dRdF.size2()!=_col_Di){dRdF.resize(_row_Di*_NInterface, _col_Di);}; 
+  dRdF.setAll(0.0);
+  fullMatrix<double> dadF(_row_Di*_NInterface, _col_Di); 
+  // if(dadF.size1()!=_row_Di*_NInterface || dadF.size2()!=_col_Di){dadF.resize(_row_Di*_NInterface, _col_Di);}; 
+  dadF.setAll(0.0);
+    
+  _C.setAll(0.0);
+  int ite = 0;
+  double r = 1.0;
+  int pos_start = _NInterface;
+  int max_iter= 15;
+  bool stiff_loc = true;
+
+
+  while(r>_tol and ite < max_iter){
+    ite +=1;
+    _Nv.mult(ab_cur, FHvec);
+    for(int i=0; i<_NLeaf; i++){
+
+      // Msg::Error("i is %d", i);
+      
+      if (_VA[pos_start+i] > 1.e-6){
+        ThermoMechanicsDG3DIPVariableBase* ipv_i = dynamic_cast<ThermoMechanicsDG3DIPVariableBase*>(ipvcur->getIPv(i));
+        const ThermoMechanicsDG3DIPVariableBase* ipvprev_i = dynamic_cast<const ThermoMechanicsDG3DIPVariableBase*>(ipv_prev->getIPv(i));
+        // std::cout << "Object type: " << typeid(*ipv_i).name() << std::endl;
+
+        STensor3& Floc = ipv_i->getRefToDeformationGradient();
+        SVector3& Hloc = ipv_i->getRefToGradT();
+        double& Tloc   = ipv_i->getRefToTemperature();
+
+        if (_flag_isothermal && _flag_microTempFixed){
+          Tloc = T;
+          Hloc = H;
+          for(int m=0; m<3; m++){
+            for(int n=0; n<3; n++){
+              Floc(m,n) = F(m,n) + FHvec(i*_col_Di + m + n*_row_Di);
+            }
+          }
+        }
+        else if(!_flag_isothermal && _flag_microTempFixed){
+          Tloc = T;
+          for(int m=0; m<3; m++){
+            Hloc(m) = H(m) + FHvec(i*_col_Di+ 9+m);
+            for(int n=0; n<3; n++){
+              Floc(m,n) = F(m,n) + FHvec(i*_col_Di + m + n*3);
+            }
+          }
+        }
+        else if(!_flag_isothermal && !_flag_microTempFixed){
+          Tloc = T + FHvec((i+1)*_col_Di-1);
+          for(int m=0; m<3; m++){  
+            Hloc(m) = H(m) + FHvec(i*_col_Di+ 9+m);
+            for(int n=0; n<3; n++){
+              Floc(m,n) = F(m,n) + FHvec(i*_col_Di + m + n*3);
+            }
+          }
+        }
+        else{
+          Msg::Error("This combination of flags doesn't exist. Redefine in the constructor.");
+        }
+        
+        int mat_IP = _Mat_Id[_NInterface + i];
+        _mapLaw[mat_IP]->stress(ipv_i, ipvprev_i, stiff_loc, checkfrac, dTangent);
+
+        const STensor3& P_i        = ipv_i->getConstRefToFirstPiolaKirchhoffStress();
+        const SVector3& Q_i        = ipv_i->getConstRefToThermalFlux();
+        const double& w_i          = ipv_i->getConstRefToThermalSource();
+        const double& Cp_i         = ipv_i->getConstRefToExtraDofFieldCapacityPerUnitField()(0);
+        const double& mechSource_i = ipv_i->getConstRefToMechanicalSource()(0);
+
+        if (_flag_isothermal && _flag_microTempFixed){
+          Cpvec(i) = Cp_i; thermSrcvec(i) = w_i; mechSrcvec(i) = mechSource_i;
+          for(int m=0; m<3; m++){
+            for(int n=0; n<3; n++){
+              PQvec(i*_col_Di + m + n*_row_Di) = P_i(m,n);
+            }
+          }
+        }
+        else if(!_flag_isothermal && _flag_microTempFixed){
+          Cpvec(i) = Cp_i; thermSrcvec(i) = w_i; mechSrcvec(i) = mechSource_i;
+          for(int m=0; m<3; m++){
+            PQvec(i*_col_Di+ 9+m) = Q_i(m);
+            for(int n=0; n<3; n++){
+              PQvec(i*_col_Di + m + n*3) = P_i(m,n);
+            }
+          }
+        }
+        else if(!_flag_isothermal && !_flag_microTempFixed){
+          thermSrcvec(i) = w_i; mechSrcvec(i) = mechSource_i;
+          PQvec((i+1)*_col_Di-1) = Cp_i;
+          for(int m=0; m<3; m++){
+            PQvec(i*_col_Di+ 9+m) = Q_i(m);
+            for(int n=0; n<3; n++){ 
+              PQvec(i*_col_Di + m + n*3) = P_i(m,n);
+            }
+          }
+        }
+        else{
+          Msg::Error("This combination of flags doesn't exist. Redefine in the constructor.");
+        }
+
+
+        if(stiff_loc){
+          const STensor43& L_i       = ipv_i->getConstRefToTangentModuli();
+          const STensor3& dPdT_i     = ipv_i->getRefTodPdT();
+          const STensor3& dqdgradT_i = ipv_i->getRefTodThermalFluxdGradT(); 
+          const SVector3& dqdT_i     = ipv_i->getRefTodThermalFluxdT();
+          const STensor33& dqdF_i    = ipv_i->getRefTodThermalFluxdF(); 
+          const double& dwdt_i       = ipv_i->getRefTodThermalSourcedField();
+          const STensor3& dwdf_i     = ipv_i->getRefTodThermalSourcedF(); STensorOperation::zero(dwdf);
+          const double& dmechSourcedt_i = ipv_i->getRefTodMechanicalSourcedField()(0,0);
+          const STensor3& dmechSourcedf_i = ipv_i->getRefTodMechanicalSourcedF()[0]; 
+
+          if (_flag_isothermal && _flag_microTempFixed){
+            dwdtvec(i) = 0.; dmechSrcdTvec(i) = 0.;
+            for(int m=0; m<3; m++)
+              for(int n=0; n<3; n++){
+                dwdFvec(i*_col_Di+m+_row_Di*n) = 0.;
+                dmechSrcdFvec(i*_col_Di+m+_row_Di*n) = 0.;
+                for(int k=0; k<3; k++)
+                  for(int l=0; l<3; l++)  
+                    _C(i*_col_Di+m+_row_Di*n, i*_col_Di+k+_row_Di*l) = L_i(m,n,k,l);
+              }
+          }
+          else if(!_flag_isothermal && _flag_microTempFixed){
+            dwdtvec(i) = dwdt_i; dmechSrcdTvec(i) = dmechSourcedt_i;
+            for(int m=0; m<3; m++)
+              for(int n=0; n<3; n++){
+                _C(i*_col_Di + 9+m, i*_col_Di + 9+n) = dqdgradT_i(m,n);
+                dwdFvec(i*9+m+_row_Di*n) = dwdf_i(m,n);
+                dmechSrcdFvec(i*9+m+_row_Di*n) = dmechSourcedf_i(m,n);
+                for(int k=0; k<3; k++){
+                  // _C(i*_col_Di+m+_row_Di*n, i*_col_Di + (k+1)*_row_Di-1) = 0.; // This is for dPdgradT_i
+                  _C(i*_col_Di + 9+m, i*_col_Di+n+3*k) = dqdF_i(m,n,k);
+                  for(int l=0; l<3; l++)  
+                    _C(i*_col_Di+m+3*n, i*_col_Di+k+3*l) = L_i(m,n,k,l);
+                }    
+              }
+          }
+          else if(!_flag_isothermal && !_flag_microTempFixed){
+            dwdtvec(i) = dwdt_i; dmechSrcdTvec(i) = dmechSourcedt_i;
+            for(int m=0; m<3; m++){
+              _C(i*_col_Di + (m+1)*(_row_Di-1)-1, (i+1)*_col_Di-1) = dqdT_i(m);
+              for(int n=0; n<3; n++){
+                _C(i*_col_Di + 9+m, i*_col_Di + 9+m) = dqdgradT_i(m,n);
+                _C(i*_col_Di + m + 3*n, (i+1)*_col_Di-1) = dPdT_i(m,n);
+                dwdFvec(i*9+m+_row_Di*n) = dwdf_i(m,n);
+                dmechSrcdFvec(i*9+m+_row_Di*n) = dmechSourcedf_i(m,n);
+                for(int k=0; k<3; k++){
+                  // _C(i*_col_Di+m+(_row_Di-1)*n, i*_col_Di + (k+1)*(_row_Di-1)-1) = 0.; // This is for dPdgradT_i
+                  _C(i*_col_Di + 9+m, i*_col_Di+n+3*k) = dqdF_i(m,n,k);
+                  for(int l=0; l<3; l++)  
+                    _C(i*_col_Di+m+3*n, i*_col_Di+k+3*l) = L_i(m,n,k,l);
+                }    
+              }
+            }
+          }
+
+        }
+      }
+      // Msg::Error("Sizes of PQVec are %d", PQvec.size());
+    }
+    // Msg::Error("Sizes of PQVec are %d", PQvec.size());
+    Msg::Error("Sizes of _NTV are %d and %d", _NTV.size1(),_NTV.size2());
+    _NTV.mult(PQvec, Res_node);
+    r = Res_node.norm()/_NInterface;
+        
+    _NTV.mult(_C, NTVC);
+    NTVC.mult(_Nv, Jacobian);
+    Jacobian.invertInPlace();
+
+    Jacobian.mult(Res_node, ab_step);
+    ab_step.scale(-1.0);
+    ab_cur.axpy(ab_step, 1.0);
+  }
+
+  Jacobian.scale(-1.0);
+  int pos0 = _Child[0][0];
+  int pos1 = _Child[0][1];  
+  if(r>_tol){
+    Msg::Error("TMDMN residual (= %lf) didn't converge to tolenerce after %d iteration",r,ite);
+    return;
+  }
+  else{
+    for(int m=0;m<_col_Di;m++){
+      PQ_hom(m) = 0.0;
+      for(int i=0;i<_NLeaf;i++){
+        PQ_hom(m) += (_VA[pos0]*_V((pos0-1)*_col_Di+m, _col_Di*i+m) + _VA[pos1]*_V((pos1-1)*_col_Di+m, _col_Di*i+m))*PQvec(_col_Di*i+m); // Stress average
+      }
+    }
+    
+    double temp = 0.;
+    for(int i=0;i<_NLeaf;i++){
+      temp = (_VA[pos0]*_V(0, _col_Di*i) + _VA[pos1]*_V(_col_Di, _col_Di*i));
+      Cp_hom +=  temp*Cpvec(i); // Cp average
+      thermSrc_hom += temp*thermSrcvec(i); // w average
+      mechSource_hom += temp*mechSrcvec(i); // mechSrc average
+    }
+
+    if (_flag_isothermal && _flag_microTempFixed){
+      Cp = Cp_hom; w = 0.; mechSource = 0.;
+      for(int i=0;i<3;i++){
+        Q(i) = 0.;
+        for(int j=0;j<3;j++){
+          P(i,j) = PQ_hom(i+_row_Di*j);
+        }
+      }
+    }
+    else if(!_flag_isothermal && _flag_microTempFixed){
+      Cp = Cp_hom; w = thermSrc_hom; mechSource = mechSource_hom; 
+      for(int i=0;i<3;i++){
+        Q(i) = PQ_hom(9+i);
+        for(int j=0;j<3;j++){
+          P(i,j) = PQ_hom(i+3*j); 
+        }
+      }
+    }
+    else if(!_flag_isothermal && !_flag_microTempFixed){
+      Cp = PQ_hom(_col_Di-1); w = thermSrc_hom; mechSource = mechSource_hom;
+      for(int i=0;i<3;i++){
+        Q(i) = PQ_hom(9+i);
+        for(int j=0;j<3;j++){
+          P(i,j) = PQ_hom(i+3*j);
+        }
+      }  
+    }
+
+    if(stiff){
+
+      NTVC.mult(_I, dRdF);
+      Jacobian.mult(dRdF, dadF);
+      _Nv.mult(dadF, tmp);
+      tmp.add(_I);
+
+      for(int m=0;m<_col_Di;m++){
+        for(int n=0;n<_col_Di;n++){
+          C_hom(m,n) = 0.0;
+          for(int i=0;i<_NLeaf;i++){
+            for(int j=0;j< _col_Di*_NLeaf;j++){
+              C_hom(m,n) += (_VA[pos0]*_V((pos0-1)*_col_Di+m,m+_col_Di*i) + _VA[pos1]*_V((pos1-1)*_col_Di+m,m+_col_Di*i))*_C(m+_col_Di*i,j)*tmp(j,n); 
+            }
+          }
+        }
+      }
+
+      double temp(0.), dTidT(1.); // = Cp_hom/(temp*Cpvec(i))
+      for(int i=0;i<_NLeaf;i++){
+        temp = (_VA[pos0]*_V(0, _col_Di*i) + _VA[pos1]*_V(_col_Di, _col_Di*i));
+        dwdt_hom += temp*dwdtvec(i)*dTidT; // dwdT average
+        dmechSourcedt_hom += temp*dmechSrcdTvec(i)*dTidT; // dmechSourcedt average
+        for(int m=0;m<9;m++)
+          for(int n=0;n<9;n++){
+            dwdf_hom(n) += temp*dwdFvec(m+9*i)*tmp(9*i,n);
+            dmechSourcedf_hom(n) += temp*dmechSrcdFvec(m+9*i)*tmp(9*i,n);
+          }
+      }
+
+      if (_flag_isothermal && _flag_microTempFixed){ 
+        for(int m=0; m<3; m++)
+          for(int n=0; n<3; n++)
+            for(int k=0; k<3; k++)
+              for(int l=0; l<3; l++)  
+                L(m,n,k,l) = C_hom(m+_row_Di*n,k+_row_Di*l);
+      }
+      else if(!_flag_isothermal && _flag_microTempFixed){
+        dwdt = dwdt_hom; dmechSourcedt = dmechSourcedt_hom;
+        for(int m=0; m<3; m++)
+          for(int n=0; n<3; n++){
+            dqdgradT(m,n) = C_hom(9+m,9+n);
+            dwdf(m,n) = dwdf_hom(m+3*n);
+            dmechSourcedf(m,n) = dmechSourcedf_hom(m+3*n);
+              for(int k=0; k<3; k++){
+                dqdF(m,n,k) = C_hom(9+m,n+3*k);
+                // dPdgradT(m,n,l) = C_hom[m+_row_Di*n][(k+1)*_row_Di-1]; // 0. This is for dPdgradT
+                for(int l=0; l<3; l++)  
+                  L(m,n,k,l) = C_hom(m+3*n,k+3*l);
+              }    
+            }
+      }
+      else if(!_flag_isothermal && !_flag_microTempFixed){
+        for(int m=0; m<3; m++){
+          dqdT(m) = C_hom( (m+1)*(_row_Di-1)-1, _col_Di-1 );
+          for(int n=0; n<3; n++){
+            dPdT(m,n) = C_hom( m + n*(_row_Di-1), _col_Di-1 );
+            dqdgradT(m,n) = C_hom( 9+m, 9+n);
+            dwdf(m,n) = dwdf_hom(m+3*n);
+            dmechSourcedf(m,n) = dmechSourcedf_hom(m+3*n);
+            for(int k=0; k<3; k++){
+              dqdF(m,n,k) = C_hom(9+m, n+3*k);
+              // C_hom[m+(_row_Di-1)*n][(k+1)*(_row_Di-1)-1] = 0.; This is for dPdgradT
+              for(int l=0; l<3; l++)  
+                L(m,n,k,l) = C_hom(m+3*n, k+3*l);
+              }    
+            }
+        }
+      }
+    }
+  }
+  Msg::Error("Sizes of PQVec are %d", PQvec.size());
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+  Msg::Error("Sizes");
+  Msg::Error("Sizes of PQVec are %d", PQvec.size());
+} 
+
+void StochTMDMNDG3DMaterialLaw::setTime(const double t,const double dtime){
+  dG3DMaterialLaw::setTime(t,dtime);
+  for (std::vector<dG3DMaterialLaw*>::iterator it = _mapLaw.begin(); it != _mapLaw.end(); it++) {
+    (*it)->setTime(t,dtime);
+  }
+}
+
+// end of stress
+
+// 
 J2SmallStrainDG3DMaterialLaw::J2SmallStrainDG3DMaterialLaw(const int num,const double rho,
                                    double E,const double nu,const double sy0,const double h,
                                    const double tol,const bool tangentByPert, const double pert) : dG3DMaterialLaw(num,rho,true),
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index a1ef00808fe2fdcd0021e214799e34bce3621928..a059ea83f427fefe42e9533bfb256401ea48810e 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -697,20 +697,21 @@ class StochDMNDG3DMaterialLaw : public dG3DMaterialLaw{
     int _NLeaf;
     int _NInterface;
     int _N_Node;
-    int _NPara_Wt;
-    int _NPara_Norm;
+    int _NPara_Wt; 
+    int _NPara_Norm; 
     int _Dim;
     double _Vf;
     double _tol;   
+    double _alpha, _beta, _gamma; // Euler Angles
     std::vector<std::vector<int>> _LevelNode;  // keep the Nodes at each level
     std::vector<int> _NodeLevel;    // _NodeLevel[Node] = Level of Node
     std::vector<int> _Mat_Id;
     std::vector<int> _Parent;       //Parent[Node] = Parent of Node
     std::vector<std::vector<int>> _Child;      // Child[Node][0] = left child ; Child[Node][1] = right child of Node
- 
+  
     
-    std::vector<SPoint2> _Para_Wt;
-    std::vector<SPoint3> _Para_Norm; 
+    std::vector<SPoint2> _Para_Wt; // vector of weights
+    std::vector<SPoint3> _Para_Norm; // vector of normals
     fullMatrix<double> _ParaAngle;   
     std::vector<dG3DMaterialLaw*> _mapLaw;
     fullMatrix<double> _Nv;
@@ -722,12 +723,14 @@ class StochDMNDG3DMaterialLaw : public dG3DMaterialLaw{
     
     fullMatrix<double> _C;
     fullMatrix<double> Jacobian;
-        
-    void fill_NLocal(const int pos, double N[][3])const;
+    
+    bool _flag_isothermal;
+
+    virtual void fill_NLocal(const int pos, double N[][3])const;
     void fill_W_WI(const int pos,  double W[][2]);
-    void fill_Matrices();
-    void read_parameter(const char *ParaFile);
-    void read_TreeData(const char *TreeFile); 
+    virtual void fill_Matrices();
+    virtual void read_parameter(const char *ParaFile);
+    virtual void read_TreeData(const char *TreeFile); 
     virtual void getLeafOfInterface(const int pos, int &node_start, int &node_end) const;
     virtual void TwoPhasesInteract(const std::vector<STensor43>& C, fullMatrix<double> &mat, const int pos);
     virtual void getdVAdP(std::vector< std::vector <SPoint2> >& dVAdPv) const;
@@ -735,9 +738,10 @@ class StochDMNDG3DMaterialLaw : public dG3DMaterialLaw{
     virtual void get_matrixdVdPv(std::vector< std::vector <SPoint2> >& dVAdPv, std::vector<std::vector<std::vector<std::vector<double>>>>& d_VdPv) const; 
     virtual void get_matrixdNdP(std::vector< std::vector <SPoint2> >& dVAdPv, std::vector<std::vector<std::vector<std::vector<double>>>>& d_NvdPv, std::vector<std::vector<std::vector<std::vector<double>>>>& d_NvdPn, std::vector<std::vector<std::vector<std::vector<double>>>>& d_NTdPn) const; 
     virtual void get_matrixdNTdPv(std::vector<std::vector<std::vector<std::vector<double>>>>& d_NTdPv) const;
+    virtual void eulerZXZToRotationMatrix(const double alpha, const double beta, const double gamma, STensor3& rotationMatrix);
     #endif //SWIG
   public:
-    StochDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree=false, const bool porous=false,const double tol=1e-6);
+    StochDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree=false, const bool porous=false,const double tol=1e-6,const bool flag_isothermal=true);
     void addLaw(dG3DMaterialLaw* law);
     #ifndef SWIG
     StochDMNDG3DMaterialLaw(const StochDMNDG3DMaterialLaw &source);
@@ -770,10 +774,63 @@ class StochDMNDG3DMaterialLaw : public dG3DMaterialLaw{
     virtual void setMacroSolver(const nonLinearMechSolver* sv);
     virtual void getParameterDerivative(const IPVariable*ipv, std::vector< fullMatrix<double> >& dPdPn, std::vector< fullMatrix<double> >&dPdPv) const;
     virtual void reset_Parameter(std::vector<std::vector<double>>& Para_Norm, std::vector<std::vector<double>>& Para_Wt, const double Vf = 0.0);
-    virtual void reset_Parameter(const char* Para);
+    virtual void reset_Parameter(const char* Para); 
+    virtual void setZXZRotationMatrix_in_IP(StochDMNDG3DIPVariable* ipv); 
     #endif //SWIG
+    virtual void setEulerAngles_rotation_DMN_response(const double alpha, const double beta, const double gamma){_alpha = alpha; _beta = beta; _gamma = gamma;};
  };   
 
+// FLE
+class StochTMDMNDG3DMaterialLaw : public StochDMNDG3DMaterialLaw{
+  protected:
+    #ifndef SWIG
+    int _col_Di, _row_Di;
+    bool _flag_microTempFixed;
+    std::vector<double> _Para_Alpha; // vector of coefficients 
+    void fill_Matrices();
+    void read_parameter(const char *ParaFile);
+    void read_TreeData(const char *TreeFile);
+    void fill_NLocal(const int pos, fullMatrix<double> N) const;
+    #endif //SWIG
+  public:
+    StochTMDMNDG3DMaterialLaw(const int num, const double rho, const double E,const double nu, const char *ParaFile, const bool ReadTree=false,
+                      const bool porous = false, const bool flag_isothermal = false, const bool flag_microTempFixed = true, const double tol=1e-6);
+    #ifndef SWIG
+    StochTMDMNDG3DMaterialLaw(const StochTMDMNDG3DMaterialLaw &source);
+    virtual ~StochTMDMNDG3DMaterialLaw();
+
+    virtual void setTime(const double t,const double dtime);
+    virtual materialLaw::matname getType() const {return materialLaw::StochTMDMN;}
+
+    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 initialIPVariable(IPVariable* ipv, bool stiff);   
+    virtual void initLaws(const std::map<int,materialLaw*> &maplaw);
+    virtual double scaleFactor() const {return 1.;};
+    virtual double soundSpeed() const {return 0.;};
+    virtual materialLaw* clone() const {return new StochTMDMNDG3DMaterialLaw(*this);};
+    virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+
+    virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const;
+    virtual bool withEnergyDissipation() const {return false;};
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      Msg::Error("getConstNonLinearSolverMaterialLaw in  StochTMDMNDG3DMaterialLaw does not exist");
+      return NULL;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      Msg::Error("getNonLinearSolverMaterialLaw in  StochTMDMNDG3DMaterialLaw does not exist");
+      return NULL;
+    }
+    virtual void setMacroSolver(const nonLinearMechSolver* sv);
+    virtual void reset_Parameter(const char* Para);
+    virtual void reset_Parameter(std::vector<std::vector<double>>& Para_Norm, std::vector<std::vector<double>>& Para_Wt, std::vector<double>& Para_Alpha, const double Vf);
+    #endif //SWIG
+    virtual void setEulerAngles_rotation_DMN_response(const double alpha, const double beta, const double gamma){_alpha = alpha; _beta = beta; _gamma = gamma;};
+ }; 
+// FLE
+
 class J2SmallStrainDG3DMaterialLaw : public dG3DMaterialLaw
 {
  protected: