diff --git a/NonLinearSolver/internalPoints/ipAnisotropic.cpp b/NonLinearSolver/internalPoints/ipAnisotropic.cpp
index 73dd884616970305f94fc075129753561ceef644..f259c7ab2c485354c56821c158f7e486b5076406 100644
--- a/NonLinearSolver/internalPoints/ipAnisotropic.cpp
+++ b/NonLinearSolver/internalPoints/ipAnisotropic.cpp
@@ -9,14 +9,18 @@
 //
 #include "ipAnisotropic.h"
 #include "restartManager.h"
-IPAnisotropic::IPAnisotropic() : IPVariableMechanics(), _elasticEnergy(0.) {};
-IPAnisotropic::IPAnisotropic(const IPAnisotropic &source) : IPVariableMechanics(source), _elasticEnergy(source._elasticEnergy){}
+#include "ipField.h"
+IPAnisotropic::IPAnisotropic() : IPVariableMechanics(), _elasticEnergy(0.), _P(0.), _sig(0.), _strain(0.) {};
+IPAnisotropic::IPAnisotropic(const IPAnisotropic &source) : IPVariableMechanics(source), _elasticEnergy(source._elasticEnergy), _P(source._P), _sig(source._sig), _strain(source._strain) {}
 IPAnisotropic& IPAnisotropic::operator=(const IPVariable &source)
 {
   IPVariableMechanics::operator=(source);
   const IPAnisotropic* src = dynamic_cast<const IPAnisotropic*>(&source);
 	if (src!=NULL){
 		_elasticEnergy = src->_elasticEnergy;
+		_P = src->_P;
+		_sig = src->_sig;
+		_strain = src->_strain;
 	}
 	return *this;
 }
@@ -26,10 +30,131 @@ double IPAnisotropic::defoEnergy() const
   return _elasticEnergy;
 }
 
+
+double IPAnisotropic::get(int comp) const
+{
+  if(comp == IPField::SIG_XX)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(0,0);
+    return val;
+  }
+  else if(comp == IPField::SIG_YY)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(1,1);
+    return val;
+  }
+  else if(comp == IPField::SIG_ZZ)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(2,2);
+    return val;
+  }
+  else if(comp == IPField::SIG_XY)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(0,1);
+    return val;
+  }
+  else if(comp == IPField::SIG_XZ)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(0,2);
+    return val;
+  }
+  else if(comp == IPField::SIG_YZ)
+  {
+    const STensor3 tensor = _sig;
+    double val = tensor(1,2);
+    return val;
+  } 
+  else if(comp == IPField::P_XX)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(0,0);
+    return val;
+  }
+  else if(comp == IPField::P_YY)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(1,1);
+    return val;
+  }
+  else if(comp == IPField::P_ZZ)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(2,2);
+    return val;
+  }
+  else if(comp == IPField::P_XY)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(0,1);
+    return val;
+  }
+  else if(comp == IPField::P_XZ)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(0,2);
+    return val;
+  }
+  else if(comp == IPField::P_YZ)
+  {
+    const STensor3 tensor = _P;
+    double val = tensor(1,2);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_XX)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(0,0);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_YY)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(1,1);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_ZZ)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(2,2);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_XY)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(0,1);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_XZ)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(0,2);
+    return val;
+  }
+  else if(comp == IPField::STRAIN_YZ)
+  {
+    const STensor3 tensor = _strain;
+    double val = tensor(1,2);
+    return val;
+  }
+  else
+  {
+    return 0.;
+  }
+}
+
+
 void IPAnisotropic::restart()
 {
   IPVariableMechanics::restart();
   restartManager::restart(_elasticEnergy);
+  restartManager::restart(_P);
+  restartManager::restart(_sig);
+  restartManager::restart(_strain);
   return;
 }
 
diff --git a/NonLinearSolver/internalPoints/ipAnisotropic.h b/NonLinearSolver/internalPoints/ipAnisotropic.h
index b365e0f46a0b7dc52a59bda541c9fba642c152ea..90ddf57f4ea66a1501e2a7edcca557c982a553c7 100644
--- a/NonLinearSolver/internalPoints/ipAnisotropic.h
+++ b/NonLinearSolver/internalPoints/ipAnisotropic.h
@@ -12,16 +12,21 @@
 #define IPANISOTROPIC_H_
 #include "ipvariable.h"
 #include "STensor3.h"
+#include "ipField.h"
 class IPAnisotropic : public IPVariableMechanics
 {
  public:
   double _elasticEnergy;
+  STensor3 _P;
+  STensor3 _sig;
+  STensor3 _strain; 
  public:
   IPAnisotropic();
   IPAnisotropic(const IPAnisotropic &source);
   IPAnisotropic& operator=(const IPVariable &source);
   virtual double defoEnergy() const;
   virtual void restart();
+  virtual double get(const int comp) const;
   virtual IPVariable* clone() const {return new IPAnisotropic(*this);};
 };
 
diff --git a/NonLinearSolver/internalPoints/ipField.cpp b/NonLinearSolver/internalPoints/ipField.cpp
index 00ae8e1e70418256e5480ae550cd400b13ace492..cd5c1aa477dec89a9b8ff8e1637caa8012185e53 100644
--- a/NonLinearSolver/internalPoints/ipField.cpp
+++ b/NonLinearSolver/internalPoints/ipField.cpp
@@ -952,6 +952,19 @@ std::string IPField::ToString(const int i){
   else if (i == USER9) return "USER9";
   else if (i == BROKEN) return "BROKEN";
   else if (i == EQUIVALENT_EIGENSTRESS) return "EQUIVALENT_EIGENSTRESS";
+  else if (i == EQUIVALENT_EIGENSTRAIN) return "EQUIVALENT_EIGENSTRAIN";
+  else if (i == EIGENSTRESS_XX) return "EIGENSTRESS_XX";
+  else if (i == EIGENSTRESS_YY) return "EIGENSTRESS_YY";
+  else if (i == EIGENSTRESS_ZZ) return "EIGENSTRESS_ZZ";
+  else if (i == EIGENSTRESS_XY) return "EIGENSTRESS_XY";
+  else if (i == EIGENSTRESS_XZ) return "EIGENSTRESS_XZ";
+  else if (i == EIGENSTRESS_YZ) return "EIGENSTRESS_YZ";
+  else if (i == EIGENSTRAIN_XX) return "EIGENSTRAIN_XX";
+  else if (i == EIGENSTRAIN_YY) return "EIGENSTRAIN_YY";
+  else if (i == EIGENSTRAIN_ZZ) return "EIGENSTRAIN_ZZ";
+  else if (i == EIGENSTRAIN_XY) return "EIGENSTRAIN_XY";
+  else if (i == EIGENSTRAIN_XZ) return "EIGENSTRAIN_XZ";
+  else if (i == EIGENSTRAIN_YZ) return "EIGENSTRAIN_YZ";
   else{
     Msg::Warning("This IP field %d is not defined in IPField::ToString(%d)",i,i);
     return "UNDEFINED";
diff --git a/NonLinearSolver/internalPoints/ipField.h b/NonLinearSolver/internalPoints/ipField.h
index b127539ec1d04dd1dc6f53776b7d9ecfdcc34399..5e9327eddca8fad08df27a6e6af865a96e761fd7 100644
--- a/NonLinearSolver/internalPoints/ipField.h
+++ b/NonLinearSolver/internalPoints/ipField.h
@@ -317,8 +317,12 @@ class IPField : public elementsField {
                     MAGNETICFIELD_X, MAGNETICFIELD_Y, MAGNETICFIELD_Z,
                     EMSOURCEVECTORFIELD_X,EMSOURCEVECTORFIELD_Y,EMSOURCEVECTORFIELD_Z,
                     INDUCTORSOURCEVECTORFIELD_X,INDUCTORSOURCEVECTORFIELD_Y,INDUCTORSOURCEVECTORFIELD_Z, EMFIELDSOURCE,
-                    BROKEN, EQUIVALENT_EIGENSTRESS, UNDEFINED};
-    enum  Operator { MEAN_VALUE=1, MIN_VALUE, MAX_VALUE, CRUDE_VALUE};
+                    BROKEN, 
+                    EQUIVALENT_EIGENSTRESS,EQUIVALENT_EIGENSTRAIN, 
+                    EIGENSTRESS_XX, EIGENSTRESS_YY, EIGENSTRESS_ZZ, EIGENSTRESS_XY, EIGENSTRESS_XZ, EIGENSTRESS_YZ,
+                    EIGENSTRAIN_XX, EIGENSTRAIN_YY, EIGENSTRAIN_ZZ, EIGENSTRAIN_XY, EIGENSTRAIN_XZ, EIGENSTRAIN_YZ,
+                    UNDEFINED};
+    enum  Operator { MEAN_VALUE=1, MIN_VALUE, MAX_VALUE, CRUDE_VALUE};      
     static std::string ToString(const int i);
   #ifndef SWIG
     // Struct for archiving
diff --git a/NonLinearSolver/internalPoints/ipJ2linear.cpp b/NonLinearSolver/internalPoints/ipJ2linear.cpp
index a8dbb80b359ad08a90778a3a8f702a4e52e8bfdd..b5d1aa6bf8567ad80215e8b64e460f5e8057b2e3 100644
--- a/NonLinearSolver/internalPoints/ipJ2linear.cpp
+++ b/NonLinearSolver/internalPoints/ipJ2linear.cpp
@@ -13,7 +13,7 @@
 IPJ2linear::IPJ2linear() : IPVariableMechanics(), _j2lepspbarre(0.), _j2lepsp(1.), _j2ldsy(0.),  _elasticEnergy(0.),
 _plasticPower(0.),_DplasticPowerDF(0.),_Ee(0.),_irreversibleEnergy(0.),_DirreversibleEnergyDF(0.),
 _dissipationBlocked(false),_dissipationActive(false),_plasticEnergy(0.), 
-_sig(0.), _svm(0.), _sigEq_2ndOrder(0.), _strain(0.), _volstrain(0.), _strainNorm(0.), _eigenstress(0.), _eigenstress_eq(0.)
+_P(0.), _sig(0.), _svm(0.), _strain(0.), _eigenstress(0.), _eigenstress_eq(0.), _eigenstrain(0.)
 {
   ipvJ2IsotropicHardening=NULL;
   Msg::Error("IPJ2Linear::IPJ2Linear is not initialized with a hardening IP Variable");
@@ -22,7 +22,7 @@ _sig(0.), _svm(0.), _sigEq_2ndOrder(0.), _strain(0.), _volstrain(0.), _strainNor
 IPJ2linear::IPJ2linear(const J2IsotropicHardening *j2IH) : IPVariableMechanics(), _j2lepspbarre(0.), _j2lepsp(1.), _j2ldsy(0.),
 _elasticEnergy(0.),_plasticPower(0.),_DplasticPowerDF(0.),_Ee(0.),_irreversibleEnergy(0.),_DirreversibleEnergyDF(0.),
 _dissipationBlocked(false),_dissipationActive(false),_plasticEnergy(0.),
-_sig(0.),_svm(0.),_sigEq_2ndOrder(0.), _strain(0.), _volstrain(0.), _strainNorm(0.), _eigenstress(0.), _eigenstress_eq(0.)
+_P(0.), _sig(0.),_svm(0.), _strain(0.), _eigenstress(0.), _eigenstress_eq(0.), _eigenstrain(0.)
 {
   ipvJ2IsotropicHardening=NULL;
   if(j2IH ==NULL) Msg::Error("IPJ2Linear::IPJ2Linear has no j2IH");
@@ -33,7 +33,7 @@ IPJ2linear::IPJ2linear(const IPJ2linear &source) : IPVariableMechanics(source),
                                                    _j2lepsp(source._j2lepsp), _j2ldsy(source._j2ldsy),
                                                    _elasticEnergy(source._elasticEnergy),
                                                    _plasticPower(source._plasticPower),_DplasticPowerDF(source._DplasticPowerDF), _Ee(source._Ee),_irreversibleEnergy(source._irreversibleEnergy), _DirreversibleEnergyDF(source._DirreversibleEnergyDF),																									 _dissipationBlocked(source._dissipationBlocked),_dissipationActive(source._dissipationActive),_plasticEnergy(source._plasticEnergy),
-_sig(source._sig), _svm(source._svm), _sigEq_2ndOrder(source._sigEq_2ndOrder), _strain(source._strain), _volstrain(source._volstrain), _strainNorm(source._strainNorm), _eigenstress(source._eigenstress), _eigenstress_eq(source._eigenstress_eq)
+_P(source._P), _sig(source._sig), _svm(source._svm), _strain(source._strain), _eigenstress(source._eigenstress), _eigenstress_eq(source._eigenstress_eq), _eigenstrain(source._eigenstrain)
 {
   ipvJ2IsotropicHardening = NULL;
   if(source.ipvJ2IsotropicHardening != NULL)
@@ -59,14 +59,13 @@ IPJ2linear& IPJ2linear::operator=(const IPVariable &source)
 		_dissipationBlocked = src->_dissipationBlocked;
     _dissipationActive = src->_dissipationActive;
     _plasticEnergy = src->_plasticEnergy;
+    _P = src->_P;
     _sig = src->_sig;
     _svm = src->_svm;
-    _sigEq_2ndOrder = src->_sigEq_2ndOrder;
     _strain = src->_strain;
-    _volstrain = src->_volstrain;
-    _strainNorm = src->_strainNorm;
     _eigenstress = src->_eigenstress;
     _eigenstress_eq = src->_eigenstress_eq;
+    _eigenstrain = src->_eigenstrain;
     if(src->ipvJ2IsotropicHardening != NULL)
     {
       if (ipvJ2IsotropicHardening!=NULL){
@@ -109,93 +108,138 @@ double IPJ2linear::svm() const
 
 double IPJ2linear::get(int comp) const
 {
-  if(comp == IPField::SIG_XX)
+  if(comp == IPField::P_XX)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(0,0);
-    return val;
+    return _P(0,0);
+  }
+  else if(comp == IPField::P_YY)
+  {
+    return _P(1,1);
+  }
+  else if(comp == IPField::P_ZZ)
+  {
+    return _P(2,2);
+  }
+  else if(comp == IPField::P_XY)
+  {
+    return _P(0,1);
+  }
+  else if(comp == IPField::P_XZ)
+  {
+    return _P(0,2);
+  }
+  else if(comp == IPField::P_YZ)
+  {
+    return _P(1,2);
+  } 
+  else if(comp == IPField::SVM)
+  {
+    return _svm;
+  }
+  else if(comp == IPField::SIG_XX)
+  {
+    return _sig(0,0);
   }
   else if(comp == IPField::SIG_YY)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(1,1);
-    return val;
+    return _sig(1,1);
   }
   else if(comp == IPField::SIG_ZZ)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(2,2);
-    return val;
+    return _sig(2,2);
   }
   else if(comp == IPField::SIG_XY)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(0,1);
-    return val;
+    return _sig(0,1);
   }
   else if(comp == IPField::SIG_XZ)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(0,2);
-    return val;
+    return _sig(0,2);
   }
   else if(comp == IPField::SIG_YZ)
   {
-    const STensor3 tensor = _sig;
-    double val = tensor(1,2);
-    return val;
+    return _sig(1,2);
   } 
-  else if(comp == IPField::SVM)
-  {
-    const double val = _svm;
-    return val;
-  }
 
   else if(comp == IPField::STRAIN_XX)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(0,0);
-    return val;
+    return _strain(0,0);
   }
   else if(comp == IPField::STRAIN_YY)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(1,1);
-    return val;
+    return _strain(1,1);
   }
   else if(comp == IPField::STRAIN_ZZ)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(2,2);
-    return val;
+    return _strain(2,2);
   }
   else if(comp == IPField::STRAIN_XY)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(0,1);
-    return val;
+    return _strain(0,1);
   }
   else if(comp == IPField::STRAIN_XZ)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(0,2);
-    return val;
+    return _strain(0,2);
   }
   else if(comp == IPField::STRAIN_YZ)
   {
-    const STensor3 tensor = _strain;
-    double val = tensor(1,2);
-    return val;
+    return _strain(1,2);
   }
   else if(comp == IPField::PLASTICSTRAIN)
   {
-    const double val = _j2lepspbarre;
-    return val;
+    return _j2lepspbarre;
   }
   else if(comp == IPField::EQUIVALENT_EIGENSTRESS)
   {
-    const double val = _eigenstress_eq;
-    return val;
+    return _eigenstress_eq;
+  }
+  else if(comp==IPField::EIGENSTRESS_XX)
+  {
+    return _eigenstress(0,0);
+  }
+  else if(comp==IPField::EIGENSTRESS_YY)
+  {
+    return _eigenstress(1,1);
+  }
+  else if(comp==IPField::EIGENSTRESS_ZZ)
+  {
+    return _eigenstress(2,2);
+  }
+  else if(comp==IPField::EIGENSTRESS_XY)
+  {
+    return _eigenstress(0,1);
+  }
+  else if(comp==IPField::EIGENSTRESS_XZ)
+  {
+    return _eigenstress(0,2);
+  }
+  else if(comp==IPField::EIGENSTRESS_YZ)
+  {
+    return _eigenstress(1,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XX)
+  {
+    return _eigenstrain(0,0);
+  }
+  else if(comp==IPField::EIGENSTRAIN_YY)
+  {
+    return _eigenstrain(1,1);
+  }
+  else if(comp==IPField::EIGENSTRAIN_ZZ)
+  {
+    return _eigenstrain(2,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XY)
+  {
+    return _eigenstrain(0,1);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XZ)
+  {
+    return _eigenstrain(0,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_YZ)
+  {
+    return _eigenstrain(1,2);
   }
   else
   {
@@ -219,14 +263,14 @@ void IPJ2linear::restart()
 	restartManager::restart(_dissipationBlocked);
   restartManager::restart(_dissipationActive);
   restartManager::restart(_plasticEnergy);
+  restartManager::restart(_P);
   restartManager::restart(_sig);
   restartManager::restart(_svm);
-  restartManager::restart(_sigEq_2ndOrder);
   restartManager::restart(_strain);
-  restartManager::restart(_volstrain);
-  restartManager::restart(_strainNorm);
   restartManager::restart(_eigenstress);
   restartManager::restart(_eigenstress_eq);
+  restartManager::restart(_eigenstress);
+  restartManager::restart(_eigenstrain);
   return;
 }
 
diff --git a/NonLinearSolver/internalPoints/ipJ2linear.h b/NonLinearSolver/internalPoints/ipJ2linear.h
index 405fac3b4942c4b9d1a2ea4c884f3e33789918c3..8d1120de22f12e0df3ffd670e9fa1c64af4ccab7 100644
--- a/NonLinearSolver/internalPoints/ipJ2linear.h
+++ b/NonLinearSolver/internalPoints/ipJ2linear.h
@@ -26,14 +26,12 @@ class IPJ2linear : public IPVariableMechanics
   double _j2ldsy;       // yield stress increment
   double _elasticEnergy; // elastic energy stored
 
-  double _volstrain;
-  double _strainNorm;
-
+  STensor3 _P;
   STensor3 _sig;
   double _svm;
-  double _sigEq_2ndOrder;
   double _eigenstress_eq;
   STensor3 _eigenstress;
+  STensor3 _eigenstrain;
 
   STensor3 _strain;
   
@@ -121,18 +119,9 @@ class IPJ2linear : public IPVariableMechanics
   virtual STensor3& getRefToStress() {return _sig;};
   virtual const STensor3& getConstRefToStress() const {return _sig;};
 
-  virtual double& getRefToEqStress2ndOrder() {return _sigEq_2ndOrder;};
-  virtual const double& getConstRefToEqStress2ndOrder() const {return _sigEq_2ndOrder;};
-
   virtual STensor3& getRefToStrain() {return _strain;};
   virtual const STensor3& getConstRefToStrain() const {return _strain;};
 
-  virtual double& getRefToVolStrain() {return _volstrain;};
-  virtual const double& getConstRefToVolStrain() const {return _volstrain;};
-
-  virtual double& getRefToStrainNorm() {return _strainNorm;};
-  virtual const double& getConstRefToStrainNorm() const {return _strainNorm;};
-
   virtual double get(const int comp) const;
 
   virtual IPVariable* clone() const {return new IPJ2linear(*this);};
diff --git a/NonLinearSolver/internalPoints/ipNonLocalDamage.cpp b/NonLinearSolver/internalPoints/ipNonLocalDamage.cpp
index 89549d2477d8ae4f03048f3f0aedb80ff99156b8..dffbaca036351e3595bfe651a2f2ed21273ec1fc 100644
--- a/NonLinearSolver/internalPoints/ipNonLocalDamage.cpp
+++ b/NonLinearSolver/internalPoints/ipNonLocalDamage.cpp
@@ -1420,6 +1420,54 @@ double IPNonLocalDamage::get(int comp) const
     else
       return 0.;
   }
+  else if(comp==IPField::EIGENSTRESS_XX)
+  {
+    return _eigenstress(0,0);
+  }
+  else if(comp==IPField::EIGENSTRESS_YY)
+  {
+    return _eigenstress(1,1);
+  }
+  else if(comp==IPField::EIGENSTRESS_ZZ)
+  {
+    return _eigenstress(2,2);
+  }
+  else if(comp==IPField::EIGENSTRESS_XY)
+  {
+    return _eigenstress(0,1);
+  }
+  else if(comp==IPField::EIGENSTRESS_XZ)
+  {
+    return _eigenstress(0,2);
+  }
+  else if(comp==IPField::EIGENSTRESS_YZ)
+  {
+    return _eigenstress(1,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XX)
+  {
+    return _eigenstrain(0,0);
+  }
+  else if(comp==IPField::EIGENSTRAIN_YY)
+  {
+    return _eigenstrain(1,1);
+  }
+  else if(comp==IPField::EIGENSTRAIN_ZZ)
+  {
+    return _eigenstrain(2,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XY)
+  {
+    return _eigenstrain(0,1);
+  }
+  else if(comp==IPField::EIGENSTRAIN_XZ)
+  {
+    return _eigenstrain(0,2);
+  }
+  else if(comp==IPField::EIGENSTRAIN_YZ)
+  {
+    return _eigenstrain(1,2);
+  }
   else
      return 0.;
   return 0.;
@@ -1489,6 +1537,9 @@ void IPNonLocalDamage::restart()
   restartManager::restart(_DirreversibleEnergyDF);
   restartManager::restart(_DirreversibleEnergyDNonLocalVariableMatrix);
   restartManager::restart(_DirreversibleEnergyDNonLocalVariableFiber);
+  
+  restartManager::restart(_eigenstress);
+  restartManager::restart(_eigenstrain);
 
   // for VT case (VM or VLM)
   // for VLM case
diff --git a/NonLinearSolver/internalPoints/ipNonLocalDamage.h b/NonLinearSolver/internalPoints/ipNonLocalDamage.h
index d06fae3aa29132b4711f3916b7d805ceed3748b1..d9fdca4235ac40e31fee5d05d935e621e4d2743d 100644
--- a/NonLinearSolver/internalPoints/ipNonLocalDamage.h
+++ b/NonLinearSolver/internalPoints/ipNonLocalDamage.h
@@ -162,6 +162,10 @@ class IPNonLocalDamage : public IPVariableMechanics
   double _plasticEne;
   double _stressWork;
   bool _dissipationBlocked;
+  
+//for TFA
+  STensor3 _eigenstrain;
+  STensor3 _eigenstress;
 
  protected:
 // parthFollowing
@@ -186,7 +190,8 @@ class IPNonLocalDamage : public IPVariableMechanics
                             pos_Mhmod2(0), pos_Mhexp(0), pos_DamParm1(0), pos_DamParm2(0), pos_DamParm3(0), 
                             pos_INCDamParm1(0), pos_INCDamParm2(0), pos_INCDamParm3(0), Randnum(0),
                             _irreversibleEnergy(0),  _DirreversibleEnergyDF(0.),  _DirreversibleEnergyDNonLocalVariableMatrix(0.),
-                            _DirreversibleEnergyDNonLocalVariableFiber(0.)
+                            _DirreversibleEnergyDNonLocalVariableFiber(0.),
+                            _eigenstrain(0.), _eigenstress(0.)
 
     {
        	mallocvector(&_nldStatev,_nldNsdv);
@@ -274,6 +279,9 @@ class IPNonLocalDamage : public IPVariableMechanics
      pos_INCDamParm3 = source.pos_INCDamParm3;
 
      Randnum = source.Randnum;
+     
+     _eigenstrain = source._eigenstrain;
+     _eigenstress = source._eigenstress;
 
      // for VT case (VM or VLM)
      // for VLM case
@@ -415,6 +423,9 @@ class IPNonLocalDamage : public IPVariableMechanics
      pos_INCDamParm3 = source->pos_INCDamParm3;
 
      Randnum = source->Randnum;
+     
+     _eigenstrain = source->_eigenstrain;
+     _eigenstress = source->_eigenstress;
 
      // for VT case (VM or VLM)
      // for VLM case
diff --git a/NonLinearSolver/materialLaw/RandomField.cpp b/NonLinearSolver/materialLaw/RandomField.cpp
index 61667650d32095abd7b03570664f5b07f57ffee6..138971e45e922fb757dff38b178231a5acc4a478 100644
--- a/NonLinearSolver/materialLaw/RandomField.cpp
+++ b/NonLinearSolver/materialLaw/RandomField.cpp
@@ -274,11 +274,11 @@ Random_Feul::Random_Feul(const Random_Feul &source):Random_Fclass(source){
       _Eul_mean[1] = source._Eul_mean[1];
       _Eul_mean[2] = source._Eul_mean[2];
       strcpy(_Geo,source._Geo);
-
-      malloctens4(&_RF_eul,_nx,_ny,_nz,3);
-      for(int i=0;i<_nx;i++){
-          for(int j=0;j<_ny;j++){
-              for(int k=0;k<_nz;k++){
+      //printf("_nx %.16g, _ny %.16g, _nz %.16g", _nx,_ny,_nz);
+      malloctens4(&_RF_eul,int(_nx),int(_ny),int(_nz),3);
+      for(int i=0;i<int(_nx);i++){
+          for(int j=0;j<int(_ny);j++){
+              for(int k=0;k<int(_nz);k++){
                   for(int p=0;p<3;p++){
                       _RF_eul[i][j][k][p] = source._RF_eul[i][j][k][p];
                   }
diff --git a/NonLinearSolver/materialLaw/STensorOperations.h b/NonLinearSolver/materialLaw/STensorOperations.h
index 83525cc79be309089ac8d028f9672f77787db1b0..e778968bb55c630d19adeca30bcf821dba67577e 100644
--- a/NonLinearSolver/materialLaw/STensorOperations.h
+++ b/NonLinearSolver/materialLaw/STensorOperations.h
@@ -184,6 +184,11 @@ namespace STensorOperation{
   inline double trace(const STensor3& a){
     return a(0,0) + a(1,1)+ a(2,2);
   };
+  
+  inline double trace(const STensor43& a){
+    return a(0,0,0,0) + a(1,1,1,1) + a(2,2,2,2) + 2.*a(0,1,0,1) + 2.*a(0,2,0,2) + 2.*a(1,2,1,2);
+  };
+  
   inline void decomposeDevTr(const STensor3& E, STensor3& devE, double& trE){
     trE = E.trace();
     devE = E;
@@ -789,7 +794,30 @@ namespace STensorOperation{
     }
     a = a_new;
   };
+  
+  inline void multSTensor43InPlaceSecond(const STensor43& a, STensor43& b){
+    STensor43 b_new;
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            b_new(i,j,k,l) = 0.;
+            for (int p=0; p<3; p++){
+              for (int q=0; q<3; q++){
+                b_new(i,j,k,l) += a(i,j,p,q)*b(p,q,k,l);
+              }
+            }
+          }
+        }
+      }
+    }
+    b = b_new;
+  };
 
+  inline void mult3xSTensor43(const STensor43& a, const STensor43& b, const STensor43& c, STensor43& abc){
+    multSTensor43(a,b,abc);
+    multSTensor43InPlace(abc,c);
+  };
 
   inline void contract4STensor43(const STensor43& a, const STensor43& b, double& c){
     c=0.;
@@ -1137,7 +1165,6 @@ namespace STensorOperation{
     }
   };
 
-
   inline void multSTensor43STensor3SecondTranspose(const STensor43& a, const STensor3& b, STensor3& c){
     for (int i=0; i<3; i++){
       for (int j=0; j<3; j++){
@@ -1281,8 +1308,83 @@ namespace STensorOperation{
     a_iso_deriv *= 1./5.;
     a_iso_deriv += sphere_derivative;
   };
+  
+  inline void STensor43Isotropization_Norris(const STensor43& a, STensor43& a_iso){
+    STensor43 I_vol, I_dev;
+    sphericalfunction(I_vol);
+    deviatorfunction(I_dev);
 
+    double a_iso_vol_fac,a_iso_dev_fac;
+    STensor43 t1, t2;
+    multSTensor43(a,I_vol,t1);
+    a_iso_vol_fac = trace(t1);
+    multSTensor43(a,I_dev,t2);
+    a_iso_dev_fac = trace(t2);
 
+    STensor43 a_iso_vol(I_vol);
+    a_iso_vol *= a_iso_vol_fac;
+
+    a_iso=I_dev;
+    a_iso *= 1./5.*a_iso_dev_fac;
+    a_iso += a_iso_vol;
+  };
+  
+  inline void STensor43TransverseIsotropization_Norris(const STensor43& A, int p, STensor43& A_transverseIso){    
+    STensor3 P, Q(1.), U, V, W, X, Y, Z;
+    P(p,p) = 1.;
+    Q -= P;
+    Q *= 1./sqrt(2.);
+    
+    U(0,2) = U(2,0) = 1.;
+    U *= 1./sqrt(2.);
+    V(1,2) = V(2,1) = 1.;
+    V *= 1./sqrt(2.);
+    W(0,1) = W(1,0) = 1.;
+    W *= 1./sqrt(2.);
+    
+    X(2,2) = 1.;
+    X(0,0) = -1.;
+    Y(1,1) = 1.;
+    Y(2,2) = -1.;
+    Z(0,0) = 1.;
+    Z(1,1) = -1.;
+    
+    STensor43 E1, E2, E3, E4, F, G;  
+    prod(P,P,1,E1);
+    prod(Q,Q,1,E2);
+    prod(P,Q,1,E3);
+    prod(Q,P,1,E4);
+    
+    if(p==0)
+    {
+    prod(V,V,1,F);
+    prodAdd(Y,Y,1,F);
+    prod(U,U,1,G);
+    prodAdd(W,W,1,G);
+    }
+    if(p==1)
+    {
+    prod(U,U,1,F);
+    prodAdd(X,X,1,F);
+    prod(V,V,1,G);
+    prodAdd(W,W,1,G);
+    }
+    if(p==2)
+    {
+    prod(W,W,1,F);
+    prodAdd(Z,Z,1,F);
+    prod(U,U,1,G);
+    prodAdd(V,V,1,G);
+    }
+    
+    double a,b,c,f,g;
+    A_transverseIso = a*E1;
+    A_transverseIso += b*E2;
+    A_transverseIso += c*(E3+E4);
+    A_transverseIso += f*F;
+    A_transverseIso += g*G;
+  };
+  
   inline void getThreeInvariantsSTensor3(const STensor3& a, double& I1, double& I2, double& I3){
     I1 = trace(a);
     static STensor3 aa;
@@ -1291,8 +1393,6 @@ namespace STensorOperation{
     I3 = determinantSTensor3(a);
   };
   
-  
-  
   //! Compute the Von Mises equivalent stress from the (stress) tensor.
   inline void getVonMisesStressFromSTensor3( const STensor3& a, double& vonMisesStress ){
     double a0m1 = a(0,0) - a(1,1);
diff --git a/NonLinearSolver/materialLaw/damage.cpp b/NonLinearSolver/materialLaw/damage.cpp
old mode 100755
new mode 100644
diff --git a/NonLinearSolver/materialLaw/elasticPotential.cpp b/NonLinearSolver/materialLaw/elasticPotential.cpp
index 029c35bde96e9d35583d63ae3f374f1e7ff43b40..a82d698775ffd506940c002d599048fc7fdd4676 100644
--- a/NonLinearSolver/materialLaw/elasticPotential.cpp
+++ b/NonLinearSolver/materialLaw/elasticPotential.cpp
@@ -113,6 +113,44 @@ void smallStrainLinearElasticPotential::createElasticTensor(const double Ex, con
     }
   }
 };
+
+void smallStrainLinearElasticPotential::createElasticTensor(const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+                                                            const double C01, const double C02, const double C03, const double C04, const double C05,
+                                                            const double C12, const double C13, const double C14, const double C15,
+                                                            const double C23, const double C24, const double C25,
+                                                            const double C34, const double C35,
+                                                            const double C45,
+                                                            STensor43& CC)
+{
+ 	CC(0,0,0,0)=C00;
+ 	CC(1,1,1,1)=C11;
+	CC(2,2,2,2)=C22;
+	CC(0,1,0,1)=CC(0,1,1,0)=CC(1,0,0,1)=CC(1,0,1,0)=C33/2.;
+	CC(0,2,0,2)=CC(0,2,2,0)=CC(2,0,0,2)=CC(2,0,2,0)=C44/2.;
+	CC(1,2,1,2)=CC(1,2,2,1)=CC(2,1,1,2)=CC(2,1,2,1)=C55/2.;
+	
+	CC(0,0,1,1)=CC(1,1,0,0)=C01;
+	CC(0,0,2,2)=CC(2,2,0,0)=C02;
+	CC(0,0,1,2)=CC(0,0,2,1)=CC(1,2,0,0)=CC(2,1,0,0)=C05;
+	CC(0,0,0,2)=CC(0,0,2,0)=CC(0,2,0,0)=CC(2,0,0,0)=C04;
+	CC(0,0,0,1)=CC(0,0,1,0)=CC(0,1,0,0)=CC(1,0,0,0)=C03;
+
+        CC(1,1,2,2)=CC(2,2,1,1)=C12;
+        CC(1,1,1,2)=CC(1,1,2,1)=CC(1,2,1,1)=CC(2,1,1,1)=C15;
+        CC(1,1,0,2)=CC(1,1,2,0)=CC(0,2,1,1)=CC(2,0,1,1)=C14;
+        CC(1,1,0,1)=CC(1,1,1,0)=CC(0,1,1,1)=CC(1,0,1,1)=C13;
+        
+        CC(2,2,1,2)=CC(2,2,2,1)=CC(1,2,2,2)=CC(2,1,2,2)=C25;
+        CC(2,2,0,2)=CC(2,2,2,0)=CC(0,2,2,2)=CC(2,0,2,2)=C24;
+        CC(2,2,0,1)=CC(2,2,1,0)=CC(0,1,2,2)=CC(1,0,2,2)=C23;
+        
+        CC(0,2,0,1)=CC(0,2,1,0)=CC(2,0,0,1)=CC(2,0,1,0)=CC(0,1,0,2)=CC(0,1,2,0)=CC(1,0,0,2)=CC(1,0,2,0)=C34/2.;
+        CC(1,2,0,1)=CC(1,2,1,0)=CC(2,1,0,1)=CC(2,1,1,0)=CC(0,1,1,2)=CC(0,1,2,1)=CC(1,0,1,2)=CC(1,0,2,1)=C35/2.;
+        
+        CC(1,2,0,2)=CC(1,2,2,0)=CC(2,1,0,2)=CC(2,1,2,0)=CC(0,2,1,2)=CC(0,2,2,1)=CC(2,0,1,2)=CC(2,0,2,1)=C45/2.;
+        
+        CC.print("_ElasticityTensor");
+};
   
 smallStrainLinearElasticPotential::smallStrainLinearElasticPotential(const int num,
                                     const double Ex, const double Ey, const double Ez,
@@ -165,6 +203,17 @@ smallStrainLinearElasticPotential::smallStrainLinearElasticPotential(const int n
   _Cel.print("Cel");
 };
 
+smallStrainLinearElasticPotential::smallStrainLinearElasticPotential(const int num,
+                                    const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+                                    const double C01, const double C02, const double C03, const double C04, const double C05,
+                                    const double C12, const double C13, const double C14, const double C15,
+                                    const double C23, const double C24, const double C25,
+                                    const double C34, const double C35,
+                                    const double C45): elasticPotential(num){
+  smallStrainLinearElasticPotential::createElasticTensor(C00,C11,C22,C33,C44,C55,C01,C02,C03,C04,C05,C12,C13,C14,C15,C23,C24,C25,C34,C35,C45,_Cel);
+  _Cel.print("_Cel");
+};
+
 double smallStrainLinearElasticPotential::get(const STensor3& F) const{
   // small strain value
   static STensor3 E;
diff --git a/NonLinearSolver/materialLaw/elasticPotential.h b/NonLinearSolver/materialLaw/elasticPotential.h
index 6635e8e6644b9f6af30907284fe0e64eb2cac5c6..8ea2239aa8e4eaa613a825689d914c83cd561bc5 100644
--- a/NonLinearSolver/materialLaw/elasticPotential.h
+++ b/NonLinearSolver/materialLaw/elasticPotential.h
@@ -55,6 +55,13 @@ class smallStrainLinearElasticPotential : public elasticPotential{
                                     const double alpha, const double beta, const double gamma);
     smallStrainLinearElasticPotential(const int num, const STensor43& C);
     smallStrainLinearElasticPotential(const int num, const fullMatrix<double>& C);
+    smallStrainLinearElasticPotential(const int num,
+                                      const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+                                      const double C01, const double C02, const double C03, const double C04, const double C05,
+                                      const double C12, const double C13, const double C14, const double C15,
+                                      const double C23, const double C24, const double C25,
+                                      const double C34, const double C35,
+                                      const double C45);
 		#ifndef SWIG
 		smallStrainLinearElasticPotential(const smallStrainLinearElasticPotential& src);
 		virtual ~smallStrainLinearElasticPotential(){};
@@ -80,6 +87,14 @@ class smallStrainLinearElasticPotential : public elasticPotential{
                                     const double Vxy, const double Vxz, const double Vyz,
                                     const double MUxy, const double MUxz, const double MUyz,
                                     const double alpha, const double beta, const double gamma, STensor43& C);
+                                    
+    static void createElasticTensor(const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+                                    const double C01, const double C02, const double C03, const double C04, const double C05,
+                                    const double C12, const double C13, const double C14, const double C15,
+                                    const double C23, const double C24, const double C25,
+                                    const double C34, const double C35,
+                                    const double C45, 
+                                    STensor43& C);
 		#endif //SWIG
 };
 
diff --git a/NonLinearSolver/materialLaw/homogenization.cpp b/NonLinearSolver/materialLaw/homogenization.cpp
old mode 100755
new mode 100644
diff --git a/NonLinearSolver/materialLaw/j2plast.cpp b/NonLinearSolver/materialLaw/j2plast.cpp
old mode 100755
new mode 100644
diff --git a/NonLinearSolver/materialLaw/material.cpp b/NonLinearSolver/materialLaw/material.cpp
old mode 100755
new mode 100644
index 4df8ab33f123443fb9af2ed15c5e598cda41929c..282a1971cc4d211516715d3df8ea0015df99691b
--- a/NonLinearSolver/materialLaw/material.cpp
+++ b/NonLinearSolver/materialLaw/material.cpp
@@ -90,7 +90,13 @@ int Material::constboxSecantMixteGeneric(double* dstrn, double* strs_n,  double*
 double E, double nu, int htype, double sy0, double hexp, double hmod1, double hmod2, double hp0, double alpha_DP, double m_DP, double nup, int viscmodel, double vmod, double vstressy, double vexp, bool evp)
 {
   return (1);
-}          
+}     
+
+void Material::setEuler(double e1, double e2, double e3)
+{
+  printf("Function setEuler is not defined for this material\n");
+  //int a = 1;
+}     
 
 #ifdef NONLOCALGMSH
 int Material::get_pos_mtx_stress () const
@@ -2244,6 +2250,18 @@ void MTSecF_Material::unload_step(double* dstrn, double* strs_n, double* statev_
 
 }
 
+void MTSecF_Material::setEuler(double e1, double e2, double e3)
+{
+  //delete euler;
+  //double* euler = NULL; 
+  //mallocvector(&euler,3);
+  euler[0] = e1;
+  euler[1] = e2;
+  euler[2] = e3;
+  
+  icl_mat->setEuler(e1,e2,e3);
+}
+
 
 //**************************************************************************************************************************************************
 // COMPOSITE - MORI-TANAKA   
@@ -4722,4 +4740,11 @@ void ANEL_Material::unload_step(double* dstrn, double* strs_n, double* statev_n,
 
        printf("unload_step not implemented for ANEL material\n");
 }
+
+void ANEL_Material::setEuler(double e1, double e2, double e3)
+{
+  euler[0] = e1;
+  euler[1] = e2;
+  euler[2] = e3;
+}
 #endif
diff --git a/NonLinearSolver/materialLaw/material.h b/NonLinearSolver/materialLaw/material.h
old mode 100755
new mode 100644
index b2b80b2e68aea817847293f80acaa49aa64021ac..29b90362c91f1e401b005007df130f5ef3c1f9cb
--- a/NonLinearSolver/materialLaw/material.h
+++ b/NonLinearSolver/materialLaw/material.h
@@ -137,6 +137,8 @@ double E, double nu, int htype, double sy0, double hexp, double hmod1, double hm
                 virtual double get_mtx_MaxD(double *statev) const {return -1.; }
                 virtual void set_mtx_MaxD(double *statev, double Dmax) {}
                 
+                virtual void setEuler(double e1, double e2, double e3);
+                
 #ifdef NONLOCALGMSH
 		virtual int get_pos_currentplasticstrainfornonlocal() const = 0;
 		virtual int get_pos_effectiveplasticstrainfornonlocal() const = 0;
@@ -587,6 +589,8 @@ class MTSecF_Material : public MT_Material{
 
 		virtual int constbox(double* dstrn, double* strs_n,  double* strs, double* statev_n, double* statev, double** Cref, double*** dCref, double* tau, double** dtau, double** Calgo, double alpha, double* dpdE, double* strs_dDdp_bar, double *Sp_bar, double** c_g, double* dFd_d_bar, double* dstrs_dFd_bar, double *dFd_dE, double** c_gF,  double* dpdFd, double* dFddp, int kinc, int kstep, double dt);
                 virtual void unload_step(double* dstrn, double* strs_n, double* statev, int kinc, int kstep);
+                
+                virtual void setEuler(double e1, double e2, double e3);
 };
 
 //Composite material homogenized with Mori-Tanaka scheme with incremental secant method, second moment for the elastic predictor
@@ -846,6 +850,9 @@ class ANEL_Material : public Material{
 		virtual int get_pos_dFd_bar() const {  return pos_dFd_bar; } 
 		virtual int get_pos_locFd() const {  return pos_locFd; }
                 virtual int get_pos_euler() const {  return pos_euler; }
+                
+                virtual void setEuler(double e1, double e2, double e3);
+                
 #ifdef NONLOCALGMSH
 		virtual int get_pos_currentplasticstrainfornonlocal() const;
 		virtual int get_pos_effectiveplasticstrainfornonlocal() const;
diff --git a/NonLinearSolver/materialLaw/mlaw.h b/NonLinearSolver/materialLaw/mlaw.h
index a2a24e99a07cb11f4c3bf77c1043da303f22d660..a9223f0cde82561b869b8d5e377d57fc1772362a 100644
--- a/NonLinearSolver/materialLaw/mlaw.h
+++ b/NonLinearSolver/materialLaw/mlaw.h
@@ -115,20 +115,66 @@ class materialLaw{
                                Msg::Error("constitutiveTFA not implemented for this material law");
                                Msg::Exit(0);
                             };
+                            
+  virtual void constitutiveTFA_corr(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            const STensor3& Fn_min,         // updated deformation gradient (input @ time n+1)
+                            const STensor3& Fn_max,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                        // contains the initial values on input
+                            const IPVariable *q0,       // array of initial internal variable
+                            IPVariable *q1,              // updated array of internal variable (in ipvcur on output),
+			     STensor43 &Tangent,         // constitutive tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const
+                            {
+                               Msg::Error("constitutiveTFA not implemented for this material law");
+                               Msg::Exit(0);
+                            };
+                            
+  virtual void constitutiveTFA_incOri(const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            const fullVector<double>& euler,
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                        // contains the initial values on input
+                            const IPVariable *q0,       // array of initial internal variable
+                            IPVariable *q1,              // updated array of internal variable (in ipvcur on output),
+			     STensor43 &Tangent,         // constitutive tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const
+                            {
+                               Msg::Error("constitutiveTFA_incOri not implemented for this material law");
+                               Msg::Exit(0);
+                            };
 
-  virtual void constitutiveIsotropicTangent(
+  virtual void constitutiveIsotropicTangentTFA(const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                        // contains the initial values on input
+                            const IPVariable *q0,       // array of initial internal variable
+                            IPVariable *q1,              // updated array of internal variable (in ipvcur on output),
+			     STensor43 &Tangent,         // constitutive tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const
+                            {
+                               Msg::Error("constitutiveIsotropicTangentTFA not implemented for this material law");
+                               Msg::Exit(0);
+                            };
+
+  virtual void constitutiveResidualSecantTFA(
                             const STensor3& F0,         // previous deformation gradient (input @ time n)
                             const STensor3& Fn,         // current deformation gradient (input @ time n+1)
                             STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
-                            const IPVariable *q0i,       // array of previous internal variables
-                            IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
-                            STensor43 &Tangent,         // tangents (output)
-                            const bool stiff,            // if true compute the tangents
-                            STensor43* elasticTangent = NULL,
-                            const bool dTangent =false,
-                            STensor63* dCalgdeps = NULL) const
+                            const IPVariable *q_unloaded,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Secant,         // constitutive tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps,
+                            const bool tangent_compute =false,
+                            STensor43* Tangent = NULL) const
                             {
-                               Msg::Error("constitutiveIsotropicTangent not implemented for this material law");
+                               Msg::Error("constitutiveResidualSecantTFA not implemented for this material law");
                                Msg::Exit(0);
                             };
 
@@ -220,9 +266,14 @@ class materialLaw{
                                Msg::Exit(0);
                             };
 
-  virtual double geth(const IPVariable *q0, const IPVariable *q1) const {return 0.;};
+  virtual double getH(const IPVariable *q0, const IPVariable *q1) const {return 0.;};
   virtual double getPlasticEqStrainIncrement(const IPVariable *q0i, const IPVariable *q1i) const {return 0.;};
   virtual double getPlasticEqStrain(const IPVariable *qi) const {return 0.;};
+  
+  virtual void getLocalOrientation(fullVector<double> &GaussP, fullVector<double> &vecEulerAngles) const
+                            {
+                               Msg::Error("getLocalOrientation not implemented for this material law");
+                            };
 
 
 
diff --git a/NonLinearSolver/materialLaw/mlawAnisotropic.cpp b/NonLinearSolver/materialLaw/mlawAnisotropic.cpp
index 7a82e79dd2f2d2c5aeab5344696abf42012b581f..340315eb42e540abb88165f1750f5923ee4cc8cf 100644
--- a/NonLinearSolver/materialLaw/mlawAnisotropic.cpp
+++ b/NonLinearSolver/materialLaw/mlawAnisotropic.cpp
@@ -116,6 +116,7 @@ mlawAnisotropic::mlawAnisotropic(const int num,const double rho,
 	else
 		{_poissonMax=Vyz;}
         //Msg::Info("K %e %e %e", _ElasticityTensor(0,0,0,0), _ElasticityTensor(1,1,1,1),_ElasticityTensor(2,2,2,2));
+        _ElasticityTensor.print("_ElasticityTensor");
 } 
 mlawAnisotropic::mlawAnisotropic(const mlawAnisotropic &source) : materialLaw(source),_ElasticityTensor(source._ElasticityTensor),
                                                        _rho(source._rho),_poissonMax(source._poissonMax),_alpha(source._alpha),_beta(source._beta),_gamma(source._gamma)
@@ -227,6 +228,64 @@ void mlawAnisotropic::constitutive(const STensor3& F0,
     
 }
 
+void mlawAnisotropic::constitutiveTFA(const STensor3& F0,         // previous deformation gradient (input @ time n)
+                                      const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                                      STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                                      const IPVariable *q0i,       // array of previous internal variables
+                                      IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                                      STensor43 &Tangent,         // tangents (output)
+                                      STensor3 &epsEig,
+                                      STensor43 &depsEigdeps) const
+{
+    const IPAnisotropic *q0 = dynamic_cast< const IPAnisotropic *> (q0i); 
+    IPAnisotropic *q1 = dynamic_cast< IPAnisotropic *> (q1i);
+    
+    STensor3& sig = q1->_sig;
+
+    static STensor3 FnT;
+    STensorOperation::transposeSTensor3(Fn, FnT);
+    static STensor3 defo;
+    defo=(FnT); // static
+    defo+=Fn;
+    defo*=0.5;
+    defo(0,0)-=1.; 
+    defo(1,1)-=1.; 
+    defo(2,2)-=1.;
+
+    for(int i=0;i<3;i++)
+    {
+      for(int j=0;j<3;j++)
+      {
+        P(i,j) = 0.;
+        for(int k=0;k<3;k++)
+        {
+          for(int l=0;l<3;l++)
+          {
+            P(i,j)+=_ElasticityTensor(i,j,k,l)*defo(k,l);
+          }
+        }
+      }
+    }
+    
+    STensorOperation::zero(epsEig);
+    STensorOperation::zero(depsEigdeps);
+    q1->_elasticEnergy=deformationEnergy(defo,P);
+    q1->_P = P;
+    /*double detJ = STensorOperation::determinantSTensor3(Fn);
+    for (int i = 0; i< 3; i ++){
+      for (int j = 0; j< 3; j ++){
+        sig(i,j) = 0.;
+        for(int k =0; k <3; k++){
+          sig(i,j) += P(i,k)*Fn(j,k)/detJ;
+        }
+      }
+    }*/
+    sig = P;
+    q1->_strain = defo;
+    Tangent=_ElasticityTensor;
+}
+
+
 double mlawAnisotropic::deformationEnergy(const STensor3& defo) const // If i need to compute sigma
 {
     static STensor3 sigma;
@@ -264,3 +323,9 @@ double mlawAnisotropic::deformationEnergy(const STensor3& defo, const STensor3&
 
 }
 
+void mlawAnisotropic::ElasticStiffness(STensor43* elasticTensor) const
+{
+  (*elasticTensor) = _ElasticityTensor;
+};
+
+
diff --git a/NonLinearSolver/materialLaw/mlawAnisotropic.h b/NonLinearSolver/materialLaw/mlawAnisotropic.h
index 1cbcb5fc0edf790eabe0a312ff183734d16a3704..0b97868078e767c14f65edda2792f0d75c54ce7f 100644
--- a/NonLinearSolver/materialLaw/mlawAnisotropic.h
+++ b/NonLinearSolver/materialLaw/mlawAnisotropic.h
@@ -69,7 +69,18 @@ public:
 			    STensor43* elasticTangent = NULL, 
                             const bool dTangent =false,
                             STensor63* dCalgdeps = NULL) const;
+                            
+  virtual void constitutiveTFA(const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const;
+                            
   const STensor43& getElasticityTensor() const { return _ElasticityTensor;};
+  virtual void ElasticStiffness(STensor43* elasticTensor) const;
  protected:
   virtual double deformationEnergy(const STensor3 &defo) const ;
   virtual double deformationEnergy(const STensor3 &defo, const STensor3& sigma) const ;
diff --git a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
index 72035fad59f7299fd0c8b28ccb726eba5aaebfc8..996115438300b4cba78534ff24b37221980ac30b 100644
--- a/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
+++ b/NonLinearSolver/materialLaw/mlawHyperelastic.cpp
@@ -155,10 +155,10 @@ double mlawHyperViscoElastic::viscousEnergy(const IPHyperViscoElastic& q0,const
       DViscous+= q._B[i]*dtrq/3.;
     }    
   }
-  else
-  {
-    Msg::Error("visco elastic method %d has not been defined");
-  }
+  //else
+  //{
+  //  Msg::Error("visco elastic method %d has not been defined");
+  //}
   return DViscous;
 
 }
@@ -205,10 +205,10 @@ void mlawHyperViscoElastic::dViscousEnergydF(const IPHyperViscoElastic& q0, cons
     }
     //HERE WE NEED TO GET WITH RESPECT TO DF -> dlog
   }
-  else
-  {
-    Msg::Error("visco elastic method %d has not been defined");
-  }
+  //else
+  //{
+  //  Msg::Error("visco elastic method %d has not been defined");
+  //}
   for(int i=0.; i<3.;i++)
   {
     for(int J=0.; J<3.;J++)
diff --git a/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.cpp b/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.cpp
index b4de8a0de8594c4d3b6ad6b16af2d635d622f8d2..09ec824d6d808e4d5982078526cca864d1a4c323 100644
--- a/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.cpp
+++ b/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.cpp
@@ -179,31 +179,59 @@ void mlawJ2VMSmallStrain::constitutiveTFA(
 
   IPJ2linear* q1 = static_cast<IPJ2linear*>(q1i);
   const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
-
   predictorCorectorTFA(F0,Fn,P,q0,q1,Tangent,epsEig,depsEigdeps);
 };
 
-void mlawJ2VMSmallStrain::constitutiveIsotropicTangent(
+void mlawJ2VMSmallStrain::constitutiveTFA_corr(
                             const STensor3& F0,         // previous deformation gradient (input @ time n)
                             const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            const STensor3& Fn_min,         // current deformation gradient (input @ time n+1)
+                            const STensor3& Fn_max,         // current deformation gradient (input @ time n+1)
                             STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
                             const IPVariable *q0i,       // array of previous internal variables
                             IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
                             STensor43 &Tangent,         // tangents (output)
-                            const bool stiff,            // if true compute the tangents
-                            STensor43* elasticTangent,
-                            const bool dTangent,
-                            STensor63* dCalgdeps) const{
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const{
 
-  static STensor43 depsEldF;
-  static STensor3 dpdF;
   IPJ2linear* q1 = static_cast<IPJ2linear*>(q1i);
   const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
+  predictorCorectorTFA_corr(F0,Fn,Fn_min,Fn_max,P,q0,q1,Tangent,epsEig,depsEigdeps);
+};
+
+void mlawJ2VMSmallStrain::constitutiveIsotropicTangentTFA(
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0i,       // array of previous internal variables
+                            IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const{
 
-  predictorCorectorIsotropicTangent(F0,Fn,P,q0,q1,Tangent,depsEldF,dpdF,stiff,elasticTangent,dTangent,dCalgdeps);
+  IPJ2linear* q1 = static_cast<IPJ2linear*>(q1i);
+  const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
+  predictorCorectorIsotropicTangentTFA(F0,Fn,P,q0,q1,Tangent,epsEig,depsEigdeps);
 };
 
 
+void mlawJ2VMSmallStrain::constitutiveResidualSecantTFA(
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q_unloadedi,       // array of previous internal variables
+                            IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Secant,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps,
+                            const bool tangent_compute,
+                            STensor43* Tangent) const{
+
+  IPJ2linear* q1 = static_cast<IPJ2linear*>(q1i);
+  const IPJ2linear* q_unloaded = static_cast<const IPJ2linear*>(q_unloadedi);
+  predictorCorectorResidualSecantTFA(F0,Fn,P,q_unloaded,q1,Secant,epsEig,depsEigdeps,tangent_compute,Tangent);
+};
+
 void mlawJ2VMSmallStrain::constitutiveResidualSecant(
                             const STensor3& F0,         // previous deformation gradient (input @ time n)
                             const STensor3& Fn,         // current deformation gradient (input @ time n+1)
@@ -273,11 +301,7 @@ void mlawJ2VMSmallStrain::predictorCorector(const STensor3& F0,         // initi
                             const bool stiff,
                             STensor43* elasticTangent,
                             const bool dTangent,
-                            STensor63* dCalgdeps,
-                            const bool dp,
-                            STensor3* dpdeps,
-                            const bool depsEq,
-                            STensor3* depsEqdeps) const {
+                            STensor63* dCalgdeps) const {
   // same state
   // plastic strain
   STensor3& Ep = q1->_j2lepsp;
@@ -286,24 +310,27 @@ void mlawJ2VMSmallStrain::predictorCorector(const STensor3& F0,         // initi
   
   STensor3& sig = q1->_sig;
   
-  double& sigEig_eq = q1->_eigenstress_eq;
-  sigEig_eq = q0->_eigenstress_eq;
-  STensor3& sigEig = q1->_eigenstress;
-  sigEig = q0->_eigenstress;
-  STensor3 sigEig_dev;
+  double& eigenstress_eq = q1->_eigenstress_eq;
+  eigenstress_eq = q0->_eigenstress_eq;
+  STensor3& eigenstress = q1->_eigenstress;
+  eigenstress = q0->_eigenstress;
+  STensor3 eigenstress_dev;
+
+  STensor3& eigenstrain = q1->_eigenstrain;
 
   const STensor3 &sig_0 = q0->getConstRefToStress();
   Ep = q0->_j2lepsp; // plastic strain tensor (equal I if no plastic occurs)
   gamma = q0->_j2lepspbarre; // equivalent plastic strain
   
+  eigenstrain = Ep;
+  
   static const STensor3 I(1.); // identity tensor
 
   // small strain
-  static STensor3 eps, eps0, devSigtr;
+  static STensor3 eps, devSigtr;
   for (int i=0; i<3; i++){
     for (int j=0; j<3; j++){
       eps(i,j) =   0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
-      eps0(i,j) =  0.5*(F0(i,j)+F0(j,i)) - I(i,j);
     }
   }
   q1->_strain = eps;
@@ -347,13 +374,6 @@ void mlawJ2VMSmallStrain::predictorCorector(const STensor3& F0,         // initi
     STensorOperation::zero(*dCalgdeps);
   }
 
-  if(dp){
-    STensorOperation::zero(*dpdeps);
-  }
-  if (depsEqdeps){
-    STensorOperation::zero(*depsEqdeps);
-  }
-
   // VM stress
   //devSigtr = sig.dev();
   double sigVMtr = sqrt(1.5*devSigtr.dotprod());
@@ -397,14 +417,15 @@ void mlawJ2VMSmallStrain::predictorCorector(const STensor3& F0,         // initi
 
     Ep.daxpy(N,deps);
     q1->_Ee.daxpy(N,-deps);
+    eigenstrain = Ep;
     
     double fact = -2.*_mu*deps;
     P.daxpy(N,fact);
     sig = P;  
     svm = sigVMtr - 3.*_mu*deps;
-    sigEig += fact*N;
-    sigEig_dev = sigEig.dev();
-    sigEig_eq = sqrt(1.5*sigEig_dev.dotprod());
+    eigenstress += fact*N;
+    eigenstress_dev = eigenstress.dev();
+    eigenstress_eq = sqrt(1.5*eigenstress_dev.dotprod());
     
     q1->_plasticPower = (deps*Sy)/this->getTimeStep();
     q1->_plasticEnergy += deps*Sy;
@@ -475,22 +496,6 @@ void mlawJ2VMSmallStrain::predictorCorector(const STensor3& F0,         // initi
           }
         }
       }
-      
-      if (dp){
-        double h;
-        h = 3.*_mu+H;
-        (*dpdeps) = N;
-        (*dpdeps) *= 2.*_mu/h;
-      }
-      if (depsEqdeps){
-        STensor3 eps_incr, eps_incr_dev; 
-  	eps_incr = eps;
-  	eps_incr -= eps0;
-  	eps_incr_dev = eps_incr.dev();
-  	double eps_incrEq = sqrt(2./3.*eps_incr_dev.dotprod());
-        (*depsEqdeps) = eps_incr_dev;
-        (*depsEqdeps) *= 2./(3.*eps_incrEq);
-      }
     }
   }
 
@@ -527,7 +532,8 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
                             IPJ2linear *q1,             // updated array of internal variable (in ipvcur on output),
                             STensor43& Tangent,         // mechanical tangents (output)
                             STensor3& epsEig,
-                            STensor43& depsEigdeps) const {
+                            STensor43& depsEigdeps
+                            ) const {
   // same state
   // plastic strain
   STensor3& Ep = q1->_j2lepsp;
@@ -536,13 +542,12 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
   
   STensor3& sig = q1->_sig;
   
-  double& sigEig_eq = q1->_eigenstress_eq;
-  sigEig_eq = q0->_eigenstress_eq;
-  STensor3& sigEig = q1->_eigenstress;
-  sigEig = q0->_eigenstress;
-  STensor3 sigEig_dev;
+  double& eigenstress_eq = q1->_eigenstress_eq;
+  eigenstress_eq = q0->_eigenstress_eq;
+  STensor3& eigenstress = q1->_eigenstress;
+  eigenstress = q0->_eigenstress;
+  STensor3 eigenstress_dev;
 
-  const STensor3 &sig_0 = q0->getConstRefToStress();
   Ep = q0->_j2lepsp; // plastic strain tensor (equal I if no plastic occurs)
   gamma = q0->_j2lepspbarre; // equivalent plastic strain
   
@@ -576,7 +581,6 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
   // stress
   P = devSigtr;
   P.daxpy(I,p);
-  sig = P;
   // elastic strain
   q1->_Ee = Eetr;
   q1->_plasticPower = 0.;
@@ -586,11 +590,11 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
   if (!_tangentByPerturbation){
     Tangent = _Cel;
   }
+
   epsEig = Ep;
   epsEig -= I;
   STensorOperation::zero(depsEigdeps);
 
-
   // VM stress
   //devSigtr = sig.dev();
   double sigVMtr = sqrt(1.5*devSigtr.dotprod());
@@ -637,20 +641,19 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
     
     double fact = -2.*_mu*deps;
     P.daxpy(N,fact);
-    sig = P;  
     svm = sigVMtr - 3.*_mu*deps;
-    sigEig += fact*N;
-    sigEig_dev = sigEig.dev();
-    sigEig_eq = sqrt(1.5*sigEig_dev.dotprod());
+    eigenstress += fact*N;
+    eigenstress_dev = eigenstress.dev();
+    eigenstress_eq = sqrt(1.5*eigenstress_dev.dotprod());
     
     q1->_plasticPower = (deps*Sy)/this->getTimeStep();
     q1->_plasticEnergy += deps*Sy;
     q1->_j2ldsy = Sy - Sy0;
     
+    epsEig = Ep;
+    epsEig -= I;
 
     if (!_tangentByPerturbation){ 
-      epsEig = Ep;
-      epsEig -= I;
       double h;
       h = 3.*_mu+H;  
       for (int i=0; i<3; i++){
@@ -667,38 +670,291 @@ void mlawJ2VMSmallStrain::predictorCorectorTFA(const STensor3& F0,         // in
   }
 
   q1->_elasticEnergy = deformationEnergy(q1->_Ee);
-
+  q1->_P = P;
+  /*double detJ = STensorOperation::determinantSTensor3(Fn);
+  for (int i = 0; i< 3; i ++){
+    for (int j = 0; j< 3; j ++){
+      sig(i,j) = 0.;
+      for(int k =0; k <3; k++){
+        sig(i,j) += P(i,k)*Fn(j,k)/detJ;
+      }
+    }
+  }*/
+  sig = P;
 };
 
 
-void mlawJ2VMSmallStrain::predictorCorectorIsotropicTangent(const STensor3& F0,         // initial deformation gradient (input @ time n)
+void mlawJ2VMSmallStrain::predictorCorectorTFA_corr(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            const STensor3& Fn_min,
+                            const STensor3& Fn_max,
                             STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
                             const IPJ2linear *q0,       // array of initial internal variable
                             IPJ2linear *q1,             // updated array of internal variable (in ipvcur on output),
                             STensor43& Tangent,         // mechanical tangents (output)
-                            STensor43& depsEldF,
-                            STensor3& dpdF,
-                            const bool stiff,
-                            STensor43* elasticTangent,
-                            const bool dTangent,
-                            STensor63* dCalgdeps) const {
-
-  static STensor43 I_dev;
-  STensorOperation::deviatorfunction(I_dev);
-
+                            STensor3& epsEig,
+                            STensor43& depsEigdeps
+                            ) const {
+  // same state
   // plastic strain
   STensor3& Ep = q1->_j2lepsp;
   double& gamma = q1->_j2lepspbarre;
+  double& svm = q1->_svm;
+  
+  STensor3& sig = q1->_sig;
+  
+  double& eigenstress_eq = q1->_eigenstress_eq;
+  eigenstress_eq = q0->_eigenstress_eq;
+  STensor3& eigenstress = q1->_eigenstress;
+  eigenstress = q0->_eigenstress;
+  STensor3 eigenstress_dev;
+
+  Ep = q0->_j2lepsp; // plastic strain tensor (equal I if no plastic occurs)
+  gamma = q0->_j2lepspbarre; // equivalent plastic strain
+  
+  static const STensor3 I(1.); // identity tensor
+
+  // small strain
+  static STensor3 eps, eps_min, eps_max, eps0, devSigtr;
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      eps(i,j) =   0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
+      eps_min(i,j) =   0.5*(Fn_min(i,j)+Fn_min(j,i)) - I(i,j);
+      eps_max(i,j) =   0.5*(Fn_max(i,j)+Fn_max(j,i)) - I(i,j);
+      eps0(i,j) =  0.5*(F0(i,j)+F0(j,i)) - I(i,j);
+    }
+  }
+  q1->_strain = eps;
+
+  // trial elastic strain Eetr = eps-(Ep-I)
+  static STensor3 Eetr, devEetr;
+  Eetr = (eps);
+  Eetr -= Ep;
+  Eetr += I;
+
+  // trace and dev parts
+  double traceEetr = Eetr.trace();
+  devEetr = Eetr.dev();
+
+  // trial pressure and deviatoric stress
+  double p = _K*traceEetr; // pressure
+  devSigtr = (devEetr); // trial deviatoric stress
+  devSigtr *= (2.*_mu);
+
+  // stress
+  P = devSigtr;
+  P.daxpy(I,p);
+  // elastic strain
+  q1->_Ee = Eetr;
+  q1->_plasticPower = 0.;
+  q1->_plasticEnergy = q0->_plasticEnergy;
+  q1->_j2ldsy = 0.;
+
+  if (!_tangentByPerturbation){
+    Tangent = _Cel;
+  }
+
+  epsEig = Ep;
+  epsEig -= I;
+  STensorOperation::zero(depsEigdeps);
+
+  // VM stress
+  //devSigtr = sig.dev();
+  double sigVMtr = sqrt(1.5*devSigtr.dotprod());
+  svm = sigVMtr;
+  
+
+  static STensor3 Eetr_min, devEetr_min,devSigtr_min;
+  Eetr_min = (eps_min);
+  Eetr_min -= Ep;
+  Eetr_min += I;
+  double traceEetr_min = Eetr_min.trace();
+  devEetr_min = Eetr_min.dev();
+  double p_min = _K*traceEetr_min; // pressure
+  devSigtr_min = (devEetr_min); // trial deviatoric stress
+  devSigtr_min *= (2.*_mu);
+  double sigVMtr_min = sqrt(1.5*devSigtr_min.dotprod());
+  
+  static STensor3 Eetr_max, devEetr_max,devSigtr_max;
+  Eetr_max = (eps_max);
+  Eetr_max -= Ep;
+  Eetr_max += I;
+  double traceEetr_max = Eetr_max.trace();
+  devEetr_max = Eetr_max.dev();
+  double p_max = _K*traceEetr_max; // pressure
+  devSigtr_max = (devEetr_max); // trial deviatoric stress
+  devSigtr_max *= (2.*_mu);
+  double sigVMtr_max = sqrt(1.5*devSigtr_max.dotprod());
+  
+  printf("sigVMtr %.16g,sigVMtrMin %.16g,sigVMtrMax %.16g \n",sigVMtr,sigVMtr_min,sigVMtr_max);
+
+  // get current yield stress
+  _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma, q1->getRefToIPJ2IsotropicHardening());
+  double  Sy0   = q0->getConstRefToIPJ2IsotropicHardening().getR();
+  double H    = q0->getConstRefToIPJ2IsotropicHardening().getDR();
+  double ddR  = q0->getConstRefToIPJ2IsotropicHardening().getDDR();
+
+  double VMCriterion = sigVMtr -Sy0;
+  double VMCriterion_min = sigVMtr_min -Sy0;
+  double VMCriterion_max = sigVMtr_max -Sy0;
+  if (VMCriterion_max > 0. or VMCriterion_min > 0.){
+    // plastic occurs
+    int ite =0, maxite = 1000;
+    double deps_max = 0.;
+    double Sy = Sy0;
+    while (fabs(VMCriterion_max/_j2IH->getYield0())> _tol){
+      // plastic increment
+      deps_max += VMCriterion_max/(3.*_mu+H);
+      // recompute plastic state
+      _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma+deps_max, q1->getRefToIPJ2IsotropicHardening());
+      Sy   = q1->getConstRefToIPJ2IsotropicHardening().getR();
+      H    = q1->getConstRefToIPJ2IsotropicHardening().getDR();
+      ddR  = q1->getConstRefToIPJ2IsotropicHardening().getDDR();
+      
+      VMCriterion_max = sigVMtr_max - 3.*_mu*deps_max - Sy;
+      ite ++;
+
+      if(ite > maxite){
+        Msg::Error("No convergence for plastic correction in j2linearVM small strain !!");
+        break;
+      }
+    }
+    
+    _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma, q1->getRefToIPJ2IsotropicHardening());
+    Sy0   = q0->getConstRefToIPJ2IsotropicHardening().getR();
+    H    = q0->getConstRefToIPJ2IsotropicHardening().getDR();
+    ddR  = q0->getConstRefToIPJ2IsotropicHardening().getDDR();
+    ite =0;
+    double deps_min = 0.;
+    Sy = Sy0;
+    while (fabs(VMCriterion_min/_j2IH->getYield0())> _tol){
+      // plastic increment
+      deps_min += VMCriterion_min/(3.*_mu+H);
+      // recompute plastic state
+      _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma+deps_min, q1->getRefToIPJ2IsotropicHardening());
+      Sy   = q1->getConstRefToIPJ2IsotropicHardening().getR();
+      H    = q1->getConstRefToIPJ2IsotropicHardening().getDR();
+      ddR  = q1->getConstRefToIPJ2IsotropicHardening().getDDR();
+      
+      VMCriterion_min = sigVMtr_min - 3.*_mu*deps_min - Sy;
+      ite ++;
+
+      if(ite > maxite){
+        Msg::Error("No convergence for plastic correction in j2linearVM small strain !!");
+        break;
+      }
+    }
+    
+    _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma, q1->getRefToIPJ2IsotropicHardening());
+    Sy0   = q0->getConstRefToIPJ2IsotropicHardening().getR();
+    H    = q0->getConstRefToIPJ2IsotropicHardening().getDR();
+    ddR  = q0->getConstRefToIPJ2IsotropicHardening().getDDR();
+    ite =0;
+    double deps = 0.;
+    Sy = Sy0;
+    while (fabs(VMCriterion/_j2IH->getYield0())> _tol){
+      // plastic increment
+      deps += VMCriterion/(3.*_mu+H);
+      // recompute plastic state
+      _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma+deps_min, q1->getRefToIPJ2IsotropicHardening());
+      Sy   = q1->getConstRefToIPJ2IsotropicHardening().getR();
+      H    = q1->getConstRefToIPJ2IsotropicHardening().getDR();
+      ddR  = q1->getConstRefToIPJ2IsotropicHardening().getDDR();
+      
+      VMCriterion = sigVMtr - 3.*_mu*deps - Sy;
+      ite ++;
+
+      if(ite > maxite){
+        Msg::Error("No convergence for plastic correction in j2linearVM small strain !!");
+        break;
+      }
+    }
+    
+    printf("deps %.16g,depsMin %.16g,depsMax %.16g \n",deps,deps_min,deps_max);
+    
+    deps += deps_max + deps_min;
+    deps *= 1./3.;
+    
+    gamma += deps;
+    // update plastic strain
+    static STensor3 N;
+    N = (devSigtr);
+    N*= (1.5/sigVMtr);
+
+    Ep.daxpy(N,deps);
+    q1->_Ee.daxpy(N,-deps);
+    
+    double fact = -2.*_mu*deps;
+    P.daxpy(N,fact);
+    svm = sigVMtr - 3.*_mu*deps;
+    eigenstress += fact*N;
+    eigenstress_dev = eigenstress.dev();
+    eigenstress_eq = sqrt(1.5*eigenstress_dev.dotprod());
+    
+    q1->_plasticPower = (deps*Sy)/this->getTimeStep();
+    q1->_plasticEnergy += deps*Sy;
+    q1->_j2ldsy = Sy - Sy0;
+    
+    epsEig = Ep;
+    epsEig -= I;
+
+    if (!_tangentByPerturbation){ 
+      double h;
+      h = 3.*_mu+H;  
+      for (int i=0; i<3; i++){
+        for (int j=0; j<3; j++){
+          for (int k=0; k<3; k++){
+            for (int l=0; l<3; l++){
+              depsEigdeps(i,j,k,l) = 2.*_mu/h*N(i,j)*N(k,l) + 2.*_mu*deps/sigVMtr*(1.5*_I4dev(i,j,k,l)-N(i,j)*N(k,l));
+              Tangent(i,j,k,l) -= 2.*_mu*depsEigdeps(i,j,k,l);
+            }
+          }
+        }
+      }    
+    } 
+  }
 
+  q1->_elasticEnergy = deformationEnergy(q1->_Ee);
+  q1->_P = P;
+  /*double detJ = STensorOperation::determinantSTensor3(Fn);
+  for (int i = 0; i< 3; i ++){
+    for (int j = 0; j< 3; j ++){
+      sig(i,j) = 0.;
+      for(int k =0; k <3; k++){
+        sig(i,j) += P(i,k)*Fn(j,k)/detJ;
+      }
+    }
+  }*/
+  sig = P;
+};
+
+
+void mlawJ2VMSmallStrain::predictorCorectorIsotropicTangentTFA(const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPJ2linear *q0,       // array of initial internal variable
+                            IPJ2linear *q1,             // updated array of internal variable (in ipvcur on output),
+                            STensor43& Tangent,         // mechanical tangents (output)
+                            STensor3& epsEig,
+                            STensor43& depsEigdeps) const {
+
+  STensor3& Ep = q1->_j2lepsp;
+  double& gamma = q1->_j2lepspbarre;
+  double& svm = q1->_svm;
+  
   STensor3& sig = q1->_sig;
+  
+  STensor3& eigenstress = q1->_eigenstress;
+  eigenstress = q0->_eigenstress;
+  STensor3 eigenstress_dev;
 
   Ep = q0->_j2lepsp; // plastic strain tensor (equal I if no plastic occurs)
   gamma = q0->_j2lepspbarre; // equivalent plastic strain
 
-  static const STensor3 I(1.); // identity tensor
+  static STensor43 I_dev;
+  STensorOperation::deviatorfunction(I_dev);
 
-  const STensor3 &sig_0 = q0->getConstRefToStress();
+  static const STensor3 I(1.); // identity tensor
 
   // small strain
   static STensor3 eps, eps_0, epsincr, epsincr_dev;
@@ -740,23 +996,18 @@ void mlawJ2VMSmallStrain::predictorCorectorIsotropicTangent(const STensor3& F0,
   q1->_plasticPower = 0.;
   q1->_plasticEnergy = q0->_plasticEnergy;
   q1->_j2ldsy = 0.;
-
-  if (stiff and !_tangentByPerturbation){
-    Tangent = _Cel;
-    STensorOperation::zero(dpdF);
-    STensorOperation::zero(depsEldF);
-  }
   
-  if (elasticTangent != NULL){
-    (*elasticTangent) =  _Cel;
+  if (!_tangentByPerturbation){
+    Tangent = _Cel;
   }
 
-  if(dTangent){
-    STensorOperation::zero(*dCalgdeps);
-  }
+  epsEig = Ep;
+  epsEig -= I;
+  STensorOperation::zero(depsEigdeps);
 
   // VM stress
   double sigVMtr = sqrt(1.5*devSigtr.dotprod());
+  svm = sigVMtr;
 
   // get current yield stress
   _j2IH->hardening(q0->_j2lepspbarre, q0->getConstRefToIPJ2IsotropicHardening(), gamma, q1->getRefToIPJ2IsotropicHardening());
@@ -801,9 +1052,13 @@ void mlawJ2VMSmallStrain::predictorCorectorIsotropicTangent(const STensor3& F0,
     P.daxpy(N,fact);
     q1->_Ee.daxpy(N,-deps);
     sig = P;
+    svm = sigVMtr - 3.*_mu*deps;
     q1->_plasticPower = (deps*Sy)/this->getTimeStep();
     q1->_plasticEnergy += deps*Sy;
     q1->_j2ldsy = Sy - Sy0;
+    
+    epsEig = Ep;
+    epsEig -= I;
 
     double h = 3.*_mu+H;
     double mu_T;
@@ -819,29 +1074,273 @@ void mlawJ2VMSmallStrain::predictorCorectorIsotropicTangent(const STensor3& F0,
     dev_part *= 2.;
     dev_part *= mu_T;
     Tangent += dev_part;
+    
+    depsEigdeps = _Cel;
+    depsEigdeps -= Tangent;
+    depsEigdeps *= 1./(2*_mu);
+    
+    STensor3 dsig_approx, depsPl_approx;
+    STensor43 Sel;
+    STensorOperation::inverseSTensor43(_Cel,Sel);
+    STensorOperation::multSTensor43STensor3(Tangent,epsincr,dsig_approx);
+    depsPl_approx = epsincr;
+    STensorOperation::multSTensor43STensor3Add(Sel,dsig_approx,-1.,depsPl_approx);
+  }
 
-    if (dTangent)
-    {
-      STensor3 dGdeps, dhdeps;
-      STensor63 dCepdeps;
-      dhdeps = N;
-      dhdeps *= 2.*_mu*ddR/h;
-      dGdeps = dhdeps;
-
-      //dGdeps *= _mu/h*(1.-H/h);
-      //dGdeps *= _mu/(5.*h)*(1.-H/h);
-      dGdeps *= -3.*_mu*_mu/(h*h);
-
-      STensorOperation::TensorProdSTensor43STensor3(I_dev,dGdeps,dCepdeps);
-      dCepdeps *= 2.;
-      (*dCalgdeps) = dCepdeps;
+  q1->_elasticEnergy = deformationEnergy(q1->_Ee);
+  q1->_P = P;
+  /*double detJ = STensorOperation::determinantSTensor3(Fn);
+  for (int i = 0; i< 3; i ++){
+    for (int j = 0; j< 3; j ++){
+      sig(i,j) = 0.;
+      for(int k =0; k <3; k++){
+        sig(i,j) += P(i,k)*Fn(j,k)/detJ;
+      }
     }
+  }*/
+  sig = P;
+
+  q1->_elasticEnergy = deformationEnergy(q1->_Ee);
+};
+
+
+void mlawJ2VMSmallStrain::predictorCorectorResidualSecantTFA(
+                            const STensor3& F_res,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPJ2linear *q_unloaded,       // array of initial internal variable
+                            IPJ2linear *q1,             // updated array of internal variable (in ipvcur on output),
+                            STensor43& Secant,         // mechanical tangents (output)
+                            STensor3& epsEig,
+                            STensor43& depsEigdeps,
+                            const bool tangent_compute,
+                            STensor43 *C_algo) const {
+   // same state
+  // plastic strain
+    STensor3& Ep = q1->_j2lepsp;
+  double& gamma = q1->_j2lepspbarre;
+  double& svm = q1->_svm;
+  
+  STensor3& sig = q1->_sig;
+
+  STensor3& eigenstress = q1->_eigenstress;
+  eigenstress = q_unloaded->_eigenstress;
+  STensor3 eigenstress_dev;
+
+  Ep = q_unloaded->_j2lepsp; // plastic strain tensor (equal I if no plastic occurs)
+  gamma = q_unloaded->_j2lepspbarre; // equivalent plastic strain
+
+  const STensor3 &sig_res = q_unloaded->getConstRefToStress();
+
+  static const STensor3 I(1.); // identity tensor
+
+  // small strain
+  static STensor3 eps, eps_res, eps_reload, sig_reload_tr, sig_reload_tr_dev;
+  for (int i=0; i<3; i++){
+    for (int j=0; j<3; j++){
+      eps(i,j) =  0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
+      eps_res(i,j) =  0.5*(F_res(i,j)+F_res(j,i)) - I(i,j);
+    }
+  }
+  q1->_strain = eps;
+
+  eps_reload = eps;
+  eps_reload -= eps_res;
+  STensorOperation::multSTensor43STensor3(_Cel,eps_reload,sig_reload_tr);
+  sig_reload_tr_dev = sig_reload_tr.dev();
+
+  // trial elastic strain Eetr = eps-(Ep-I)
+  static STensor3 Eetr;
+  Eetr = (eps);
+  Eetr -= Ep;
+  Eetr += I;
+
+  // trace and dev parts
+  double traceEetr = Eetr.trace();
+  static STensor3 devEetr;
+  devEetr = Eetr.dev();
+
+  // trial pressure and deviatoric stress
+  double p = _K*traceEetr; // pressure
+  static STensor3 devSigtr;
+  devSigtr = (devEetr); // trial deviatoric stress
+  devSigtr *= (2.*_mu);
+
+  // stress
+  P = devSigtr;
+  P.daxpy(I,p);
+  sig = P;
+  // elastic strain
+  q1->_Ee = Eetr;
+  q1->_plasticPower = 0.;
+  q1->_j2ldsy = 0.;
+
+  if (!_tangentByPerturbation and tangent_compute){
+  (*C_algo) = _Cel;
   }
+  
+  Secant = _Cel;
+  
+  epsEig = Ep;
+  epsEig -= I;
+  STensorOperation::zero(depsEigdeps);
+
+  // VM stress
+  double sigVMtr = sqrt(1.5*devSigtr.dotprod());
+  svm = sigVMtr;
+  double sig_reloadVMtr = sqrt(1.5*sig_reload_tr_dev.dotprod());
+
+  static STensor3 N, N_reload, N_inv;
+  N = (devSigtr);
+  N*= (1.5/sigVMtr);
+  N_reload = (sig_reload_tr_dev);
+  N_reload*= (1.5/sig_reloadVMtr);
+
+
+  // get current yield stress
+  _j2IH->hardening(q_unloaded->_j2lepspbarre, q_unloaded->getConstRefToIPJ2IsotropicHardening(), gamma, q1->getRefToIPJ2IsotropicHardening());
+  double  Sy0   = q_unloaded->getConstRefToIPJ2IsotropicHardening().getR();
+  double H    = q_unloaded->getConstRefToIPJ2IsotropicHardening().getDR();
+  double ddR  = q_unloaded->getConstRefToIPJ2IsotropicHardening().getDDR();
+
+  double h_reload, h;
+  h = H + 3.*_mu;
+  STensorOperation::inverseSTensor3(N,N_inv);
+  STensorOperation::doubleContractionSTensor3(N_reload,N_inv,h_reload);
+  h_reload *= 1./3.;
+  h_reload *= H;
+  h_reload += 3.*_mu;
+
+  double VMCriterion = sigVMtr -Sy0;
+  if (VMCriterion >0.){
+    // plastic occurs
+    int ite =0, maxite = 1000;
+    double deps = 0.;
+    double Sy = Sy0;
+    while (fabs(VMCriterion/_j2IH->getYield0())> _tol){
+      // plastic increment
+      //deps += VMCriterion/h_reload;
+      deps += VMCriterion/h;
+      // recompute plastic state
+      _j2IH->hardening(q_unloaded->_j2lepspbarre, q_unloaded->getConstRefToIPJ2IsotropicHardening(), gamma+deps, q1->getRefToIPJ2IsotropicHardening());
+      Sy   = q1->getConstRefToIPJ2IsotropicHardening().getR();
+      H    = q1->getConstRefToIPJ2IsotropicHardening().getDR();
+      h = H + 3.*_mu;
+      STensorOperation::inverseSTensor3(N,N_inv);
+      STensorOperation::doubleContractionSTensor3(N_reload,N_inv,h_reload);
+      h_reload *= 1./3.;
+      h_reload *= H;
+      h_reload += 3.*_mu;
+      
+
+      VMCriterion = sigVMtr - 3.*_mu*deps - Sy;
+      ite ++;
+
+      if(ite > maxite){
+        Msg::Error("No convergence for plastic correction in j2linearVM small strain !!");
+        break;
+      }
+
+    }
+
+    gamma += deps;
+
+    // update plastic strain
+    Ep.daxpy(N_reload,deps);
+    double fact = -2.*_mu*deps;
+    P.daxpy(N_reload,fact);
+    q1->_Ee.daxpy(N_reload,-deps);
+
+    /*Ep.daxpy(N,deps);
+    double fact = -2.*_mu*deps;
+    P.daxpy(N,fact);
+    q1->_Ee.daxpy(N,-deps);*/
+
+    sig = P;
+    svm = sigVMtr - 3.*_mu*deps;
+
+    q1->_plasticPower = (deps*Sy)/this->getTimeStep();
+    q1->_j2ldsy = Sy - Sy0;
+    
+    epsEig = Ep;
+    epsEig -= I;
+
+    static STensor3 sig_reload, eps_reload_dev, sig_reload_dev, sig_dev;
+    sig_reload = P;
+    sig_reload -= sig_res;
+    eps_reload_dev=eps_reload.dev();
+    sig_reload_dev=sig_reload.dev();
+    sig_dev=P.dev();
+    double eps_reload_eq = sqrt(2./3.*eps_reload_dev.dotprod());
+    double sig_reloadVM = sqrt(1.5*sig_reload_dev.dotprod());
+    double sigVM = sqrt(1.5*sig_dev.dotprod());
+
+    double mu_ep;
+    mu_ep = sig_reloadVM/(3.*eps_reload_eq);
+
+    static STensor43 dev_part;
+    STensorOperation::sphericalfunction(Secant);
+    STensorOperation::deviatorfunction(dev_part);
+    Secant *= 3.;
+    Secant *= _K;
+    dev_part *= 2.;
+    dev_part *= mu_ep;
+    Secant += dev_part;
+
+    static STensor43 dNdSigpr_reload, dNdSigpr;
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            dNdSigpr_reload(i,j,k,l) = (1.5*_I4dev(i,j,k,l) - N_reload(i,j)*N_reload(k,l))/sig_reloadVMtr;
+            dNdSigpr(i,j,k,l) = (1.5*_I4dev(i,j,k,l) - N(i,j)*N(k,l))/sigVMtr;
+          }
+        }
+      }
+    }
+
+    STensor43 I_dev;
+    STensorOperation::deviatorfunction(I_dev);
+    STensor3 fac3;
+    fac3 = sig_reload_dev;
+    STensor3 fac2(eps_reload_dev), fac1;
+    fac3 *= 1./(6.*mu_ep*eps_reload_eq*eps_reload_eq);
+    fac2 *= -2./(3.*eps_reload_eq*eps_reload_eq)*mu_ep;
+    STensor43 Tangent;
+    Tangent = _Cel;
+    
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        for (int k=0; k<3; k++){
+          for (int l=0; l<3; l++){
+            depsEigdeps(i,j,k,l) = 2.*_mu/h_reload*N_reload(i,j)*N_reload(k,l) + 2.*_mu*deps/sig_reloadVMtr*(1.5*_I4dev(i,j,k,l)-N_reload(i,j)*N_reload(k,l));
+            //depsEigdeps(i,j,k,l) = 2.*_mu/h*N(i,j)*N(k,l) + 2.*_mu*deps/sigVMtr*(1.5*_I4dev(i,j,k,l)-N(i,j)*N(k,l));
+            Tangent(i,j,k,l) -= 2.*_mu*depsEigdeps(i,j,k,l);
+          }
+        }
+      }
+    }
+      
+    if (tangent_compute){
+    STensorOperation::multSTensor3STensor43(fac3,Tangent,fac1);
+    STensor3 dGdeps(fac2);
+    dGdeps += fac1;
+    STensor63 dCsecdeps;
+    STensorOperation::TensorProdSTensor43STensor3(I_dev,dGdeps,dCsecdeps);
+    dCsecdeps *= 2.;
+    
+    STensorOperation::multSTensor63_ind34_STensor3(dCsecdeps,eps_reload,(*C_algo));
+    (*C_algo) += Secant;
+    }
+      
+  }
+
   q1->_elasticEnergy = deformationEnergy(q1->_Ee);
 };
 
 
-void mlawJ2VMSmallStrain::predictorCorectorResidualSecant(const STensor3& F_res,         // initial deformation gradient (input @ time n)
+void mlawJ2VMSmallStrain::predictorCorectorResidualSecant(
+                            const STensor3& F_res,         // initial deformation gradient (input @ time n)
                             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
                             STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
                             const IPJ2linear *q_unloaded,       // array of initial internal variable
@@ -854,12 +1353,7 @@ void mlawJ2VMSmallStrain::predictorCorectorResidualSecant(const STensor3& F_res,
                             const bool dSecant,
                             STensor63* dCsecdeps,
                             const bool Calg_compute,
-                            STensor43* C_algo,
-                            const bool dp,
-                            STensor3* dpdepsreload,
-                            const bool depsEq,
-                            const IPJ2linear *q0,
-                            STensor3* depsEqdeps) const {
+                            STensor43* C_algo) const {
    // same state
   // plastic strain
   STensor3& Ep = q1->_j2lepsp;
@@ -932,14 +1426,6 @@ void mlawJ2VMSmallStrain::predictorCorectorResidualSecant(const STensor3& F_res,
   }
 
 
-  if(dp){
-    STensorOperation::zero(*dpdepsreload);
-  }
-  if (depsEqdeps){
-    STensorOperation::zero(*depsEqdeps);
-  }
-
-
   // VM stress
   double sigVMtr = sqrt(1.5*devSigtr.dotprod());
   double sig_reloadVMtr = sqrt(1.5*sig_reload_tr_dev.dotprod());
@@ -1088,21 +1574,6 @@ void mlawJ2VMSmallStrain::predictorCorectorResidualSecant(const STensor3& F_res,
         STensorOperation::multSTensor63_ind34_STensor3((*dCsecdeps),eps_reload,(*C_algo));
         (*C_algo) += Secant;
       }
-
-      if (dp){
-        (*dpdepsreload) = N_reload;
-        (*dpdepsreload) *= 2.*_mu/h_reload;
-      }
-      if (depsEqdeps){
-        const STensor3 &eps0 = q0->getConstRefToStrain();
-        static STensor3 eps_incr,eps_incr_dev;
-        eps_incr = eps;
-        eps_incr -= eps0;
-        eps_incr_dev = eps_incr.dev();
-        double eps_incrEq = sqrt(2./3.*eps_incr_dev.dotprod());
-        (*depsEqdeps) = eps_reload_dev;
-        (*depsEqdeps) *= 2./(3.*eps_reload_eq);
-      }
     }
   }
 
@@ -1423,15 +1894,7 @@ void mlawJ2VMSmallStrain::elasticUnloading(
   static STensor3 devEetr;
   devEetr = Eetr.dev();
 
-  // trial pressure and deviatoric stress
-  //double p = _K*traceEetr; // pressure
-  //static STensor3 devSigtr;
-  //devSigtr = (devEetr); // trial deviatoric stress
-  //devSigtr *= (2.*_mu);
-
   // stress
-  //P_res = devSigtr;
-  //P_res.daxpy(I,p);
   P_res = sig_0;
   P_res -= sig_unload;
 
@@ -1709,39 +2172,21 @@ void mlawJ2VMSmallStrain::ZeroResidualSecantStiffnessIsotropic(const IPVariable
 };
 
 
-double mlawJ2VMSmallStrain::geth(const IPVariable *q0i, const IPVariable *q1i) const
+double mlawJ2VMSmallStrain::getH(const IPVariable *q0i, const IPVariable *q1i) const
 {
-  const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
   const IPJ2linear* q1 = static_cast<const IPJ2linear*>(q1i);
-  const double& gamma0 = q0->_j2lepspbarre;
-  const double& gamma = q1->_j2lepspbarre;
-  double depspl = gamma-gamma0;
-  double h = 0.;
-  if(depspl>1.e-15)
+  const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
+  double gamma = q1->_j2lepspbarre;
+  double gamma0 = q0->_j2lepspbarre;
+  double dR;
+  if( (gamma - gamma0) < 10.e-10 )
   {
-    h = 3.*_mu;
-    double dR = q1->getConstRefToIPJ2IsotropicHardening().getDR();
-    h += dR;
+    dR = 0.;
   }
-  return h;
-};
-
-double mlawJ2VMSmallStrain::getPlasticEqStrainIncrement(const IPVariable *q0i, const IPVariable *q1i) const
-{
-  const IPJ2linear* q0 = static_cast<const IPJ2linear*>(q0i);
-  const IPJ2linear* q1 = static_cast<const IPJ2linear*>(q1i);
-  const double& gamma0 = q0->_j2lepspbarre;
-  const double& gamma = q1->_j2lepspbarre;
-  double depspl = gamma-gamma0;
-
-  return depspl;
-};
-
-double mlawJ2VMSmallStrain::getPlasticEqStrain(const IPVariable *qi) const
-{
-  const IPJ2linear* q = static_cast<const IPJ2linear*>(qi);
-  const double& gamma = q->_j2lepspbarre;
-
-  return gamma;
+  else
+  {
+    dR = q1->getConstRefToIPJ2IsotropicHardening().getDR();
+  }
+  return dR;
 };
 
diff --git a/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.h b/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.h
index 9f2499df1a794ecf24f132d757246e53aa05a79c..e8ee5520238f6fa1d81651dce5702e04e51d47ad 100644
--- a/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.h
+++ b/NonLinearSolver/materialLaw/mlawJ2VMSmallStrain.h
@@ -76,9 +76,7 @@ class mlawJ2VMSmallStrain : public materialLaw {
     virtual void ResidualSecantStiffnessIsotropic(const IPVariable *q_unloadedi, const IPVariable *q1i, STensor43& Secant) const;
     virtual void ZeroResidualSecantStiffnessIsotropic(const IPVariable *q_unloadedi, const IPVariable *q1i, STensor43& Secant) const;
 
-    virtual double geth(const IPVariable *q0, const IPVariable *q1) const;
-    virtual double getPlasticEqStrainIncrement(const IPVariable *q0i, const IPVariable *q1i) const;
-    virtual double getPlasticEqStrain(const IPVariable *qi) const;
+    virtual double getH(const IPVariable *q0, const IPVariable *q1) const;
 
     // predictor-corrector estimation
     virtual void constitutive(const STensor3& F0,         // previous deformation gradient (input @ time n)
@@ -100,18 +98,40 @@ class mlawJ2VMSmallStrain : public materialLaw {
                             STensor43 &Tangent,         // tangents (output)
                             STensor3 &epsEig,
                             STensor43 &depsEigdeps) const;
-
-    virtual void constitutiveIsotropicTangent(
+                            
+    virtual void constitutiveTFA_corr(
                             const STensor3& F0,         // previous deformation gradient (input @ time n)
                             const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            const STensor3& Fn_min,         // current deformation gradient (input @ time n+1)
+                            const STensor3& Fn_max,         // current deformation gradient (input @ time n+1)
                             STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
-                            const IPVariable *q0i,       // array of previous internal variables
-                            IPVariable *q1i,             // current array of internal variable (in ipvcur on output),
+                            const IPVariable *q0,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
                             STensor43 &Tangent,         // tangents (output)
-                            const bool stiff,            // if true compute the tangents
-                            STensor43* elasticTangent = NULL,
-                            const bool dTangent =false,
-                            STensor63* dCalgdeps = NULL) const;
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const;
+
+    virtual void constitutiveIsotropicTangentTFA(const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const;
+
+    virtual void constitutiveResidualSecantTFA( 
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q_unloaded,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Secant,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps,
+                            const bool tangent_compute =false,
+                            STensor43* Tangent=NULL) const;
+
 
     virtual void constitutiveResidualSecant( 
                             const STensor3& F0,         // previous deformation gradient (input @ time n)
@@ -164,33 +184,50 @@ class mlawJ2VMSmallStrain : public materialLaw {
                             const bool stiff,
                             STensor43* elasticTangent = NULL, 
                             const bool dTangent =false,
-                            STensor63* dCalgdeps = NULL,
-                            const bool dp =false,
-                            STensor3* dpdeps = NULL,
-                            const bool depsEq =false,
-                            STensor3* depsEqdeps = NULL) const;
+                            STensor63* dCalgdeps = NULL) const;
                             
       void predictorCorectorTFA(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& F,         // updated deformation gradient (input @ time n+1)
                             STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
                             const IPJ2linear *q0,       // array of initial internal variable
                             IPJ2linear *q,             // updated array of internal variable (in ipvcur on output),
-                            STensor43& Tangent,         // mechanical tangents (output)
-                            STensor3& epsEig,
-                            STensor43& depsEigdeps) const;
+                            STensor43& Tangent,         // mechanical tangents (output)      
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps
+                            ) const;
+                            
+      void predictorCorectorTFA_corr(const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F,         // updated deformation gradient (input @ time n+1)
+                            const STensor3& F_min,         // updated deformation gradient (input @ time n+1)
+                            const STensor3& F_max,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPJ2linear *q0,       // array of initial internal variable
+                            IPJ2linear *q,             // updated array of internal variable (in ipvcur on output),
+                            STensor43& Tangent,         // mechanical tangents (output)      
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps
+                            ) const;
 
-      void predictorCorectorIsotropicTangent(const STensor3& F0,         // initial deformation gradient (input @ time n)
+      void predictorCorectorIsotropicTangentTFA(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& F,         // updated deformation gradient (input @ time n+1)
                             STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
                             const IPJ2linear *q0,       // array of initial internal variable
                             IPJ2linear *q,             // updated array of internal variable (in ipvcur on output),
-                            STensor43& Tangent,         // mechanical tangents (output)
-                            STensor43& depsEldF,
-                            STensor3& dpdF,
-                            const bool stiff,
-                            STensor43* elasticTangent = NULL, 
-                            const bool dTangent =false,
-                            STensor63* dCalgdeps = NULL) const;
+                            STensor43& Tangent,         // mechanical tangents (output)      
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps
+                            ) const;
+
+      void predictorCorectorResidualSecantTFA(const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& F,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                            const IPJ2linear *q_unloaded,       // array of initial internal variable
+                            IPJ2linear *q,             // updated array of internal variable (in ipvcur on output),
+                            STensor43& Secant,         // mechanical tangents (output)      
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps,
+                            const bool tangent_compute =false,
+                            STensor43* Tangent = NULL) const;
 
       void predictorCorectorResidualSecant(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& F,         // updated deformation gradient (input @ time n+1)
@@ -205,12 +242,7 @@ class mlawJ2VMSmallStrain : public materialLaw {
                             const bool dSecant =false,
                             STensor63* dCsecdeps = NULL,
                             const bool Calg_compute =false,
-                            STensor43* C_algo = NULL,
-                            const bool dp =false,
-                            STensor3* dpdeps = NULL,
-                            const bool depsEq =false,
-                            const IPJ2linear *q0 =NULL, 
-                            STensor3* depsEqdeps = NULL) const;
+                            STensor43* C_algo = NULL) const;
 
       void predictorCorectorZeroSecant(const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& F,         // updated deformation gradient (input @ time n+1)
diff --git a/NonLinearSolver/materialLaw/mlawNonLocalDamage.cpp b/NonLinearSolver/materialLaw/mlawNonLocalDamage.cpp
index 9dd2d908b0d0c9be2f5392fcac967db11f742902..1bf302b69fdfa84393481300ab0cf2316aab5501 100644
--- a/NonLinearSolver/materialLaw/mlawNonLocalDamage.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLocalDamage.cpp
@@ -334,6 +334,25 @@ mlawNonLocalDamage::mlawNonLocalDamage(const int num, const double rho,
     freematrix(chara_Length,3); 
     freematrix(chara_Length_INC,3); 
   }
+  
+  
+void mlawNonLocalDamage::createIPState(IPStateBase* &ips,bool hasBodyForce,const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
+{
+  int nsdv = this->getNsdv();
+  IPVariable* ivi = new IPNonLocalDamage(nsdv);
+  IPVariable* iv1 = new IPNonLocalDamage(nsdv);
+  IPVariable* iv2 = new IPNonLocalDamage(nsdv);
+     
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ivi,iv1,iv2);
+  /*IPNonLocalDamage* qi = static_cast<IPNonLocalDamage*>(ivi);
+  IPNonLocalDamage* q1 = static_cast<IPNonLocalDamage*>(iv1);
+  IPNonLocalDamage* q2 = static_cast<IPNonLocalDamage*>(iv2);
+               
+  createIPState(qi,q1,q2);*/
+}
+
+  
 void mlawNonLocalDamage::createIPState(IPNonLocalDamage *ivi, IPNonLocalDamage *iv1, IPNonLocalDamage *iv2) const
 {
 
@@ -667,6 +686,9 @@ void mlawNonLocalDamage::constitutive(const STensor3& F0,const STensor3& Fn,STen
   if(elasticTangent!=NULL) Msg::Error(" mlawNonLocalDamage STensor43* elasticTangent not defined");
   const IPNonLocalDamage *ipvprev = dynamic_cast<const IPNonLocalDamage *> (ipvprevi);
   IPNonLocalDamage *ipvcur = dynamic_cast<IPNonLocalDamage *> (ipvcuri);
+  
+  STensor3& eigenstrain = ipvcur->_eigenstrain;
+  STensor3& eigenstress = ipvcur->_eigenstress;
 
   //convert F to eps  :order xx yy zz xy xz yz
   if(!mat->isInLargeDeformation())
@@ -1063,7 +1085,19 @@ void mlawNonLocalDamage::constitutive(const STensor3& F0,const STensor3& Fn,STen
     DirrEnergDF(2,0) = dEnePathFollowingdStrain[4]/sq2;
     DirrEnergDF(1,2) = dEnePathFollowingdStrain[5]/sq2;
     DirrEnergDF(2,1) = dEnePathFollowingdStrain[5]/sq2;
-
+    
+    STensor43 Cel, Sel;
+    ElasticStiffness(&Cel);
+    STensorOperation::inverseSTensor43(Cel,Sel);     
+    static STensor3 I(1.);
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        eigenstrain(i,j) =   0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
+      }
+    }
+    STensorOperation::multSTensor43STensor3Add(Sel,P,-1.,eigenstrain);
+    STensorOperation::multSTensor43STensor3(Cel,eigenstrain,eigenstress);
+    eigenstress *= -1.;
 
 /*  if(STensorOperation::isnan(disEne)) 
     Msg::Error("disEne is nan");
@@ -1107,129 +1141,1136 @@ void mlawNonLocalDamage::constitutive(const STensor3& F0,const STensor3& Fn,STen
 
 }
 
-void mlawNonLocalDamage::constitutive(
-                            const STensor3& F0,         // initial deformation gradient (input @ time n)
-                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
-                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
-                                                        // contains the initial values on input
-                            const IPVariable *ipvprevi,       // array of initial internal variable
-                            IPVariable *ipvcuri,             // updated array of internal variable (in ipvcur on output),
-                            STensor43 &Tangent,         // constitutive tangents (output)
-                            std::vector<STensor3>  &dLocalPlasticStrainDStrain,
-  			    std::vector<STensor3>  &dStressDNonLocalPlasticStrain,
-                            fullMatrix<double>     &dLocalPlasticStrainDNonLocalPlasticStrain,
-                            const bool stiff,
-                            STensor43* elasticTangent) const
-{
-  if(elasticTangent!=NULL) Msg::Error(" mlawNonLocalDamage STensor43* elasticTangent not defined");
-  const IPNonLocalDamage *ipvprev = dynamic_cast<const IPNonLocalDamage *> (ipvprevi);
-  IPNonLocalDamage *ipvcur = dynamic_cast<IPNonLocalDamage *> (ipvcuri); 
 
-  mlawNonLocalDamage::constitutive(F0, Fn, P, ipvprev, ipvcur, Tangent, stiff,elasticTangent);
-  if(stiff && !STensorOperation::isnan(P))
-  {
-    dLocalPlasticStrainDStrain[0](0,0) = ipvcur->_nldCouplingEffectiveStrainStress(0); //minus?
-    dLocalPlasticStrainDStrain[0](1,1) = ipvcur->_nldCouplingEffectiveStrainStress(1);
-    dLocalPlasticStrainDStrain[0](2,2) = ipvcur->_nldCouplingEffectiveStrainStress(2);
-    dLocalPlasticStrainDStrain[0](0,1) = ipvcur->_nldCouplingEffectiveStrainStress(3);
-    dLocalPlasticStrainDStrain[0](1,0) = ipvcur->_nldCouplingEffectiveStrainStress(3);
-    dLocalPlasticStrainDStrain[0](0,2) = ipvcur->_nldCouplingEffectiveStrainStress(4);
-    dLocalPlasticStrainDStrain[0](2,0) = ipvcur->_nldCouplingEffectiveStrainStress(4);
-    dLocalPlasticStrainDStrain[0](2,1) = ipvcur->_nldCouplingEffectiveStrainStress(5);
-    dLocalPlasticStrainDStrain[0](1,2) = ipvcur->_nldCouplingEffectiveStrainStress(5);
+void mlawNonLocalDamage::constitutiveTFA(const STensor3& F0,
+                                         const STensor3& Fn,
+                                         STensor3 &P,
+                                         const IPVariable *ipvprevi,
+                                         IPVariable *ipvcuri,
+                                         STensor43 &Tangent,
+                                         STensor3 &epsEig,
+                                         STensor43 &depsEigdeps) const
+{ 
+  //const IPNonLocalDamage *ipvprev = dynamic_cast<const IPNonLocalDamage *> (ipvprevi);
+  //IPNonLocalDamage *ipvcur = dynamic_cast<IPNonLocalDamage *> (ipvcuri);
+  
+  IPNonLocalDamage* ipvcur = static_cast<IPNonLocalDamage*>(ipvcuri);
+  const IPNonLocalDamage* ipvprev = static_cast<const IPNonLocalDamage*>(ipvprevi);  
+  
+  STensorOperation::zero(P);
+  
+  STensor3& eigenstrain = ipvcur->_eigenstrain;
+  STensor3& eigenstress = ipvcur->_eigenstress;
 
-    dStressDNonLocalPlasticStrain[0](0,0) = ipvcur->_nldCouplingStressEffectiveStrain(0);
-    dStressDNonLocalPlasticStrain[0](1,1) = ipvcur->_nldCouplingStressEffectiveStrain(1);
-    dStressDNonLocalPlasticStrain[0](2,2) = ipvcur->_nldCouplingStressEffectiveStrain(2);
-    dStressDNonLocalPlasticStrain[0](0,1) = ipvcur->_nldCouplingStressEffectiveStrain(3);
-    dStressDNonLocalPlasticStrain[0](1,0) = ipvcur->_nldCouplingStressEffectiveStrain(3);
-    dStressDNonLocalPlasticStrain[0](0,2) = ipvcur->_nldCouplingStressEffectiveStrain(4);
-    dStressDNonLocalPlasticStrain[0](2,0) = ipvcur->_nldCouplingStressEffectiveStrain(4);
-    dStressDNonLocalPlasticStrain[0](2,1) = ipvcur->_nldCouplingStressEffectiveStrain(5);
-    dStressDNonLocalPlasticStrain[0](1,2) = ipvcur->_nldCouplingStressEffectiveStrain(5);
+  //convert F to eps  :order xx yy zz xy xz yz
+  if(!mat->isInLargeDeformation())
+  {
+    for(int i=0;i<3;i++)
+    {
+      ipvcur->_nldStrain(i) = Fn(i,i)-1.;
+    }
+    //gamma
+    ipvcur->_nldStrain(3) = Fn(0,1)+Fn(1,0);
+    ipvcur->_nldStrain(4) = Fn(0,2)+Fn(2,0);
+    ipvcur->_nldStrain(5) = Fn(2,1)+Fn(1,2);
+  }
+  else
+  {
+    for(int i=0;i<3;i++)
+    {
+       for(int j=0;j<3;j++)
+       {
+         Ftmp[i][j] = Fn(i,j);
+         Ftmp0[i][j] = F0(i,j);
+       }
+    }
+    Getstrnln(Ftmp, Vstrain);
+    GetdRot(Ftmp0, Ftmp, dR);
+    matrix_to_vect(3, dR, &(ipvprev->_nldStatev[mat->get_pos_dR()]));
+    matrix_to_vect(3, dR, &(ipvcur->_nldStatev[mat->get_pos_dR()]));
 
-    dLocalPlasticStrainDNonLocalPlasticStrain(0,0) = ipvcur->_nldSpBar;
-    if(getNbNonLocalVariables()>1){
-      dLocalPlasticStrainDNonLocalPlasticStrain(1,0) = ipvcur->_nldFddp; 
-      dLocalPlasticStrainDNonLocalPlasticStrain(0,1) = ipvcur->_nldpdFd;
-      dLocalPlasticStrainDNonLocalPlasticStrain(1,1) = ipvcur->_nldFd_d_bar;
+    for(int i=0;i<3;i++){
+      ipvcur->_nldStrain(i) = Vstrain[i];
+      //ipvcur->_nldStatev[i] = Vstrain[i];
+    }
+    for(int i=3;i<6;i++){
+      ipvcur->_nldStrain(i) = Vstrain[i];
+      //ipvcur->_nldStatev[i] = Vstrain[i]/sq2;    //**using the current state varible to pass the total strain*****
     }
+  }
 
-    if(getNbNonLocalVariables()>1){
-      dLocalPlasticStrainDStrain[1](0,0) = ipvcur->_nldFiberDamdStrain(0); 
-      dLocalPlasticStrainDStrain[1](1,1) = ipvcur->_nldFiberDamdStrain(1);
-      dLocalPlasticStrainDStrain[1](2,2) = ipvcur->_nldFiberDamdStrain(2);
-      dLocalPlasticStrainDStrain[1](0,1) = ipvcur->_nldFiberDamdStrain(3);
-      dLocalPlasticStrainDStrain[1](1,0) = ipvcur->_nldFiberDamdStrain(3);
-      dLocalPlasticStrainDStrain[1](0,2) = ipvcur->_nldFiberDamdStrain(4);
-      dLocalPlasticStrainDStrain[1](2,0) = ipvcur->_nldFiberDamdStrain(4);
-      dLocalPlasticStrainDStrain[1](2,1) = ipvcur->_nldFiberDamdStrain(5);
-      dLocalPlasticStrainDStrain[1](1,2) = ipvcur->_nldFiberDamdStrain(5);
+  //get previous strain and stress
+  for(int i=0;i<3;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i);
+    strs_n[i]=(ipvprev->_nldStress)(i);
+    dstrn[i]=(ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i);
+  }
+  for(int i=3;i<6;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i)/sq2;
+    dstrn[i]=((ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i))/sq2;
+    strs_n[i]=(ipvprev->_nldStress)(i)*sq2;
+  }
+
+  //HERE WE SHOULD COPY THE PREVIOUS ONE AND NOT CHANGING IT DIRECTLY
+  //statev_n = ipvprev->_nldStatev;
+  copyvect(ipvprev->_nldStatev, statev_n,nsdv);
 
 
-  
-      dStressDNonLocalPlasticStrain[1](0,0) = ipvcur->_nldStressdFiberDam(0);
-      dStressDNonLocalPlasticStrain[1](1,1) = ipvcur->_nldStressdFiberDam(1);
-      dStressDNonLocalPlasticStrain[1](2,2) = ipvcur->_nldStressdFiberDam(2);
-      dStressDNonLocalPlasticStrain[1](0,1) = ipvcur->_nldStressdFiberDam(3);
-      dStressDNonLocalPlasticStrain[1](1,0) = ipvcur->_nldStressdFiberDam(3);
-      dStressDNonLocalPlasticStrain[1](0,2) = ipvcur->_nldStressdFiberDam(4);
-      dStressDNonLocalPlasticStrain[1](2,0) = ipvcur->_nldStressdFiberDam(4);
-      dStressDNonLocalPlasticStrain[1](2,1) = ipvcur->_nldStressdFiberDam(5);   
-      dStressDNonLocalPlasticStrain[1](1,2) = ipvcur->_nldStressdFiberDam(5);
+  statev_1 = ipvcur->_nldStatev;
+
+  //SHOULD BE MORE GENERAL
+  if( mat->get_pos_effectiveplasticstrainfornonlocal() >=0 )
+  {
+    //should be 66 (-39 for EP)
+    statev_n[mat->get_pos_effectiveplasticstrainfornonlocal()] = ipvprev->_nldEffectivePlasticStrain;
+    statev_n[mat->get_pos_effectiveplasticstrainfornonlocal()+1] = (ipvcur->_nldEffectivePlasticStrain-
+                                                                    ipvprev->_nldEffectivePlasticStrain);
+  }
+  if( mat->get_pos_Fd_bar() > 0 )
+  {
+    statev_n[mat->get_pos_Fd_bar()] =  ipvprev->_nlFiber_d_bar;  
+    statev_n[mat->get_pos_dFd_bar()] = (ipvcur->_nlFiber_d_bar - ipvprev->_nlFiber_d_bar);
+  } 
+
+
+  // to required to use Eshelby tensor of previous step?
+  copyvect(statev_n,statev_1,nsdv);
+  if (ipvcur->dissipationIsBlocked() or ipvprev->dissipationIsBlocked())
+  {
+    for(int nlv=0; nlv< getNbNonLocalVariables(); nlv++)
+    {
+      ipvcur->setCriticalDamage(statev_n,ipvprev->getDamageIndicator(nlv),nlv);
+      ipvcur->setCriticalDamage(statev_1,ipvprev->getDamageIndicator(nlv),nlv);
     }
   }
+  if(mat->isInLargeDeformation())
+  {
+     for(int i=0;i<3;i++){
+         statev_1[i] = Vstrain[i];
+     }
+     for(int i=3;i<6;i++){
+         statev_1[i] = Vstrain[i]/sq2;    //**using the current state varible to pass the total strain*****
+    }
 
-  /*if(STensorOperation::isnan(P)) 
-    Msg::Error("P is nan");
-  if(STensorOperation::isnan(Tangent)) 
-    Msg::Error("Tangent is nan");
-  if(STensorOperation::isnan(dLocalPlasticStrainDStrain[0]))
-    Msg::Error("dLocalPlasticStrainDStrain[0] is nan");
-  if(STensorOperation::isnan(dGradLocalPlasticStrainDStrain[0]))
-    Msg::Error("dGradLocalPlasticStrainDStrain[0] is nan");
-  if(STensorOperation::isnan(dStressDNonLocalPlasticStrain[0]))
-    Msg::Error("dStressDNonLocalPlasticStrain[0] is nan");
-  if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(0,0)))
-    Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[0,0] is nan");
-  if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(0,0)))
-    Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain is nan[0,0]");
-  if(getNbNonLocalVariables()>1){
-    if(STensorOperation::isnan(dLocalPlasticStrainDStrain[1]))
-      Msg::Error("dLocalPlasticStrainDStrain[1] is nan");
-    if(STensorOperation::isnan(dStressDNonLocalPlasticStrain[1]))
-      Msg::Error("dStressDNonLocalPlasticStrain[1] is nan");
-    if(STensorOperation::isnan(dGradLocalPlasticStrainDStrain[1]))
-      Msg::Error("dGradLocalPlasticStrainDStrain[1] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(1,0)))
-      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[1,0] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(0,1)))
-      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[0,1] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(1,1)))
-      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[1,1] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(1,0)))
-      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[1,0] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(0,1)))
-      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[0,1] is nan");
-    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(1,1)))
-      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[1,1] is nan");
-  }*/
+  }
+  int kinc = 1;
+  int kstep = 2;
+  SpBar = 0.0;
+  dFd_d_bar = 0.0;
+  dpdFd = 0.0;
+  dFddp = 0.0;
+  
+  int error= mat->constbox(dstrn, strs_n, strs, statev_n, statev_1, Cref, dCref, tau, dtau, Calgo, 1., dpdE, strs_dDdp_bar, &SpBar, chara_Length, &dFd_d_bar, dstrs_dFd_bar, dFd_dE, chara_Length_INC, &dpdFd, &dFddp, kinc, kstep, _timeStep);
 
-}
+  //recompute becasue could have changed if no convergence and is used for Irreversible energy
+  for(int i=0;i<3;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i);
+    strs_n[i]=(ipvprev->_nldStress)(i);
+    dstrn[i]=(ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i);
+  }
+  for(int i=3;i<6;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i)/sq2;
+    dstrn[i]=((ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i))/sq2;
+    strs_n[i]=(ipvprev->_nldStress)(i)*sq2;
+  }
+  if(error==0)
+  {
+    //update stress and tangent operator
+    updateCharacteristicLengthTensor(chara_Length, statev_1);
+    updateCharacteristicLengthTensor(chara_Length_INC, statev_1);
+    for(int i=0;i<3;i++)
+    {
+      (ipvcur->_nldStress)(i)=strs[i];
+      for(int j=0;j<3;j++){
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j];
+  
+        (ipvcur->_nldCharacteristicLengthMatrix)(i,j) = chara_Length[i][j];                 //by Wu Ling
+        (ipvcur->_nldCharacteristicLengthFiber)(i,j) = chara_Length_INC[i][j];
+      }
+      if( mat->get_pos_damagefornonlocal()>0)
+      {
+        ipvcur->_nldCouplingStressEffectiveStrain(i) = strs_dDdp_bar[i];
+        ipvcur->_nldCouplingEffectiveStrainStress(i) = dpdE[i];
+      }
+      if( mat->get_pos_Fd_bar()>0)
+      {
+        ipvcur->_nldFiberDamdStrain(i) = dFd_dE[i];
+        ipvcur->_nldStressdFiberDam(i) = dstrs_dFd_bar[i];
+      }
+    }
 
-const double mlawNonLocalDamage::bulkModulus() const
-{
-  return 2.*_mu0*(1+_nu0)/3./(1.-2.*_nu0);
-}
-const double mlawNonLocalDamage::shearModulus() const
-{
-  return _mu0;
-}
+    ipvcur->_nldSpBar = SpBar;
+    ipvcur->_nldFd_d_bar = dFd_d_bar;
+    ipvcur->_nldpdFd = dpdFd;
+    ipvcur->_nldFddp = dFddp;
 
-const double mlawNonLocalDamage::poissonRatio() const
-{
-  return _nu0;
-}
+    for(int i=3;i<6;i++)
+    {
+      (ipvcur->_nldStress)(i)=strs[i]/sq2;
+      for(int j=0;j<3;j++)
+      {
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j]/sq2;
+        (ipvcur->_nldMaterialTensor)(j,i)=Calgo[j][i]/sq2;
+      }
+      for(int j=3;j<6;j++)
+      {
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j]/2.;
+      }
+      if( mat->get_pos_damagefornonlocal()>=0)
+      {
+        ipvcur->_nldCouplingStressEffectiveStrain(i) = strs_dDdp_bar[i]/sq2;
+        ipvcur->_nldCouplingEffectiveStrainStress(i) = dpdE[i]/sq2;
+      }
+      if( mat->get_pos_Fd_bar()>0) 
+      {
+        ipvcur->_nldFiberDamdStrain(i) = dFd_dE[i]/sq2;
+        ipvcur->_nldStressdFiberDam(i) = dstrs_dFd_bar[i]/sq2;
+      }
+    }
+    if( mat->get_pos_damagefornonlocal() >= 0)
+    {
+      ipvcur->_nldDamage = statev_1[mat->get_pos_damagefornonlocal()];
+    }
+
+    if( mat->get_pos_currentplasticstrainfornonlocal() >=0)
+    {
+      ipvcur->_nldCurrentPlasticStrain = statev_1[mat->get_pos_currentplasticstrainfornonlocal()];
+    }
+
+    if( mat->get_pos_locFd() >0)
+    {
+      ipvcur->_nlFiber_loc = statev_1[mat->get_pos_locFd()];
+    }
+
+    //convert str to P  :order xx yy zz xy xz yz
+    for(int i=0;i<3;i++)
+    {
+      P(i,i) = ipvcur->_nldStress(i);
+    }
+    P(0,1) = ipvcur->_nldStress(3);
+    P(1,0) = ipvcur->_nldStress(3);
+    P(0,2) = ipvcur->_nldStress(4);
+    P(2,0) = ipvcur->_nldStress(4);
+    P(1,2) = ipvcur->_nldStress(5);
+    P(2,1) = ipvcur->_nldStress(5);
+    if(mat->isInLargeDeformation())
+    {
+      //What we have is actually sigma -> send to P
+      static STensor3 Finv, FinvT;
+      STensorOperation::inverseSTensor3(Fn, Finv);
+      STensorOperation::transposeSTensor3(Finv, FinvT);
+      P*=FinvT;
+      P*=Fn.determinant();
+    }
+
+    //convert MaterialTensor to Tangent  :order xx yy zz xy xz yz
+    Tangent(0,0,0,0) = ipvcur->_nldMaterialTensor(0, 0);
+    Tangent(0,0,0,1) = ipvcur->_nldMaterialTensor(0, 3);
+    Tangent(0,0,0,2) = ipvcur->_nldMaterialTensor(0, 4);
+    Tangent(0,0,1,0) = ipvcur->_nldMaterialTensor(0, 3);
+    Tangent(0,0,1,1) = ipvcur->_nldMaterialTensor(0, 1);
+    Tangent(0,0,1,2) = ipvcur->_nldMaterialTensor(0, 5);
+    Tangent(0,0,2,0) = ipvcur->_nldMaterialTensor(0, 4);
+    Tangent(0,0,2,1) = ipvcur->_nldMaterialTensor(0, 5);
+    Tangent(0,0,2,2) = ipvcur->_nldMaterialTensor(0, 2);
+
+    Tangent(1,1,0,0) = ipvcur->_nldMaterialTensor(1, 0);  
+    Tangent(1,1,0,1) = ipvcur->_nldMaterialTensor(1, 3);
+    Tangent(1,1,0,2) = ipvcur->_nldMaterialTensor(1, 4);
+    Tangent(1,1,1,0) = ipvcur->_nldMaterialTensor(1, 3);
+    Tangent(1,1,1,1) = ipvcur->_nldMaterialTensor(1, 1);
+    Tangent(1,1,1,2) = ipvcur->_nldMaterialTensor(1, 5);
+    Tangent(1,1,2,0) = ipvcur->_nldMaterialTensor(1, 4);
+    Tangent(1,1,2,1) = ipvcur->_nldMaterialTensor(1, 5);
+    Tangent(1,1,2,2) = ipvcur->_nldMaterialTensor(1, 2);
+
+    Tangent(2,2,0,0) = ipvcur->_nldMaterialTensor(2, 0);  
+    Tangent(2,2,0,1) = ipvcur->_nldMaterialTensor(2, 3);
+    Tangent(2,2,0,2) = ipvcur->_nldMaterialTensor(2, 4);
+    Tangent(2,2,1,0) = ipvcur->_nldMaterialTensor(2, 3);
+    Tangent(2,2,1,1) = ipvcur->_nldMaterialTensor(2, 1);
+    Tangent(2,2,1,2) = ipvcur->_nldMaterialTensor(2, 5);
+    Tangent(2,2,2,0) = ipvcur->_nldMaterialTensor(2, 4);
+    Tangent(2,2,2,1) = ipvcur->_nldMaterialTensor(2, 5);
+    Tangent(2,2,2,2) = ipvcur->_nldMaterialTensor(2, 2);
+
+    Tangent(0,1,0,0) = ipvcur->_nldMaterialTensor(3, 0);
+    Tangent(0,1,0,1) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(0,1,0,2) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(0,1,1,0) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(0,1,1,1) = ipvcur->_nldMaterialTensor(3, 1);
+    Tangent(0,1,1,2) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(0,1,2,0) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(0,1,2,1) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(0,1,2,2) = ipvcur->_nldMaterialTensor(3, 2);
+
+    Tangent(1,0,0,0) = ipvcur->_nldMaterialTensor(3, 0);
+    Tangent(1,0,0,1) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(1,0,0,2) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(1,0,1,0) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(1,0,1,1) = ipvcur->_nldMaterialTensor(3, 1);
+    Tangent(1,0,1,2) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(1,0,2,0) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(1,0,2,1) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(1,0,2,2) = ipvcur->_nldMaterialTensor(3, 2);
+
+    Tangent(0,2,0,0) = ipvcur->_nldMaterialTensor(4, 0);
+    Tangent(0,2,0,1) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(0,2,0,2) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(0,2,1,0) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(0,2,1,1) = ipvcur->_nldMaterialTensor(4, 1);
+    Tangent(0,2,1,2) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(0,2,2,0) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(0,2,2,1) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(0,2,2,2) = ipvcur->_nldMaterialTensor(4, 2);
+
+    Tangent(2,0,0,0) = ipvcur->_nldMaterialTensor(4, 0);
+    Tangent(2,0,0,1) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(2,0,0,2) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(2,0,1,0) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(2,0,1,1) = ipvcur->_nldMaterialTensor(4, 1);
+    Tangent(2,0,1,2) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(2,0,2,0) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(2,0,2,1) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(2,0,2,2) = ipvcur->_nldMaterialTensor(4, 2);
+
+    Tangent(2,1,0,0) = ipvcur->_nldMaterialTensor(5, 0);
+    Tangent(2,1,0,1) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(2,1,0,2) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(2,1,1,0) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(2,1,1,1) = ipvcur->_nldMaterialTensor(5, 1);
+    Tangent(2,1,1,2) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(2,1,2,0) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(2,1,2,1) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(2,1,2,2) = ipvcur->_nldMaterialTensor(5, 2);
+
+    Tangent(1,2,0,0) = ipvcur->_nldMaterialTensor(5, 0);
+    Tangent(1,2,0,1) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(1,2,0,2) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(1,2,1,0) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(1,2,1,1) = ipvcur->_nldMaterialTensor(5, 1);
+    Tangent(1,2,1,2) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(1,2,2,0) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(1,2,2,1) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(1,2,2,2) = ipvcur->_nldMaterialTensor(5, 2);
+    
+    /*fullMatrix<double> Calgo_fullMatrix(6,6);
+    for(int i=0;i<6;i++)
+    {
+      for(int j=0;j<6;j++){
+        Calgo_fullMatrix(i,j)=Calgo[i][j];
+      }
+    }
+    for(int i=3;i<6;i++)
+    {
+      for(int j=0;j<3;j++)
+      {
+        Calgo_fullMatrix(i,j)*=(1./sq2);
+        Calgo_fullMatrix(j,i)*=2.;
+        Calgo_fullMatrix(j,i)*=(1./sq2);
+      }
+    }   
+    STensorOperation::fromFullMatrixToSTensor43(Calgo_fullMatrix,Tangent);*/
+
+
+    ipvcur->_elasticEne = mat->getElasticEnergy(statev_1);
+    ipvcur->_plasticEne = mat->getPlasticEnergy(statev_1);
+
+    // we use plastic energy = plastenergy_n + sum Delta eps:(sigma_n+1+sigma_n)2.  
+    // dissipated energy = plastic energy - 1/2 [(sigma_n+1 : Cele^-1 : sigma_n+1   ]
+    ipvcur->_stressWork=ipvprev->_stressWork;
+    for (int i=0; i < 6; i++)
+    {
+      ipvcur->_stressWork+= 0.5*(strs[i]+strs_n[i])*dstrn[i];
+    }
+    mat->get_elOp(statev_1,C0PathFollowing);
+    int errorInv=0;
+    inverse(C0PathFollowing,invC0PathFollowing,&errorInv,6);
+
+    double &disEne=ipvcur->getRefToIrreversibleEnergy();
+    STensor3& DirrEnergDF = ipvcur->getRefToDIrreversibleEnergyDF();
+    double &dIrrDpTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(0);
+
+    //elastic strain
+    for (int i=0; i < 6; i++)
+    {
+      elStrainPathFollowing[i]=0.;
+      for(int j=0; j < 6; j++)
+      {
+        elStrainPathFollowing[i] +=invC0PathFollowing[i][j] *strs[j];
+      }
+    }
+    disEne=ipvcur->_stressWork;
+    dIrrDpTilde=0.;
+    if( mat->get_pos_Fd_bar()>0)
+    {
+      double &dIrrDdamTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(1);
+      dIrrDdamTilde=0.;
+    }
+    for (int i=0; i < 6; i++)
+    {
+      disEne-=0.5*elStrainPathFollowing[i]*strs[i];
+      dEnePathFollowingdStrain[i]=(strs[i]+strs_n[i])*0.5;
+      for(int j=0; j < 6; j++)
+      {
+        dEnePathFollowingdStrain[i] += Calgo[j][i] *(0.5*dstrn[j]-elStrainPathFollowing[j]);
+      }
+      dIrrDpTilde+= strs_dDdp_bar[i]*(0.5*dstrn[i]-elStrainPathFollowing[i]);// dsigma d p tilde
+      if( mat->get_pos_Fd_bar()>0)
+      {
+        double &dIrrDdamTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(1);
+        dIrrDdamTilde+=dstrs_dFd_bar[i]*(0.5*dstrn[i]-elStrainPathFollowing[i]); //d sigma d d tilde d
+      }
+    }
+    for(int i=0;i<3;i++)
+    {
+      DirrEnergDF(i,i) = dEnePathFollowingdStrain[i];
+    }
+    DirrEnergDF(0,1) = dEnePathFollowingdStrain[3]/sq2;
+    DirrEnergDF(1,0) = dEnePathFollowingdStrain[3]/sq2;
+    DirrEnergDF(0,2) = dEnePathFollowingdStrain[4]/sq2;
+    DirrEnergDF(2,0) = dEnePathFollowingdStrain[4]/sq2;
+    DirrEnergDF(1,2) = dEnePathFollowingdStrain[5]/sq2;
+    DirrEnergDF(2,1) = dEnePathFollowingdStrain[5]/sq2;
+    
+    STensor43 Cel, Sel;
+    ElasticStiffness(&Cel);
+    STensorOperation::inverseSTensor43(Cel,Sel);
+      
+    STensor3 eps;
+    static STensor3 I(1.);
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        eps(i,j) =   0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
+      }
+    }
+    epsEig = eps;
+    STensorOperation::multSTensor43STensor3Add(Sel,P,-1.,epsEig);
+    eigenstrain = epsEig;
+    STensorOperation::multSTensor43STensor3(Cel,eigenstrain,eigenstress);
+    eigenstress *= -1.;
+    STensorOperation::unity(depsEigdeps);
+    STensorOperation::multSTensor43Add(Sel,Tangent,-1.,depsEigdeps);  
+  }
+  else
+  {
+    //constbox did not converge
+    P(0,0) = P(1,1) = P(2,2) = sqrt(-1.); // to exist NR and performed next step with a smaller incremenet
+  }
+}
+
+
+
+void mlawNonLocalDamage::constitutiveTFA_incOri(const STensor3& F0,
+                                         const STensor3& Fn,
+                                         const fullVector<double>& euler,
+                                         STensor3 &P,
+                                         const IPVariable *ipvprevi,
+                                         IPVariable *ipvcuri,
+                                         STensor43 &Tangent,
+                                         STensor3 &epsEig,
+                                         STensor43 &depsEigdeps) const
+{ 
+  //const IPNonLocalDamage *ipvprev = dynamic_cast<const IPNonLocalDamage *> (ipvprevi);
+  //IPNonLocalDamage *ipvcur = dynamic_cast<IPNonLocalDamage *> (ipvcuri);
+  
+  IPNonLocalDamage* ipvcur = static_cast<IPNonLocalDamage*>(ipvcuri);
+  const IPNonLocalDamage* ipvprev = static_cast<const IPNonLocalDamage*>(ipvprevi);  
+  
+  double e1 = euler(0);
+  double e2 = euler(1);
+  double e3 = euler(2);
+  mat->setEuler(e1,e2,e3);
+  
+  STensorOperation::zero(P);
+  
+  STensor3& eigenstrain = ipvcur->_eigenstrain;
+  STensor3& eigenstress = ipvcur->_eigenstress;
+
+  //convert F to eps  :order xx yy zz xy xz yz
+  if(!mat->isInLargeDeformation())
+  {
+    for(int i=0;i<3;i++)
+    {
+      ipvcur->_nldStrain(i) = Fn(i,i)-1.;
+    }
+    //gamma
+    ipvcur->_nldStrain(3) = Fn(0,1)+Fn(1,0);
+    ipvcur->_nldStrain(4) = Fn(0,2)+Fn(2,0);
+    ipvcur->_nldStrain(5) = Fn(2,1)+Fn(1,2);
+  }
+  else
+  {
+    for(int i=0;i<3;i++)
+    {
+       for(int j=0;j<3;j++)
+       {
+         Ftmp[i][j] = Fn(i,j);
+         Ftmp0[i][j] = F0(i,j);
+       }
+    }
+    Getstrnln(Ftmp, Vstrain);
+    GetdRot(Ftmp0, Ftmp, dR);
+    matrix_to_vect(3, dR, &(ipvprev->_nldStatev[mat->get_pos_dR()]));
+    matrix_to_vect(3, dR, &(ipvcur->_nldStatev[mat->get_pos_dR()]));
+
+    for(int i=0;i<3;i++){
+      ipvcur->_nldStrain(i) = Vstrain[i];
+      //ipvcur->_nldStatev[i] = Vstrain[i];
+    }
+    for(int i=3;i<6;i++){
+      ipvcur->_nldStrain(i) = Vstrain[i];
+      //ipvcur->_nldStatev[i] = Vstrain[i]/sq2;    //**using the current state varible to pass the total strain*****
+    }
+  }
+
+  //get previous strain and stress
+  for(int i=0;i<3;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i);
+    strs_n[i]=(ipvprev->_nldStress)(i);
+    dstrn[i]=(ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i);
+  }
+  for(int i=3;i<6;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i)/sq2;
+    dstrn[i]=((ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i))/sq2;
+    strs_n[i]=(ipvprev->_nldStress)(i)*sq2;
+  }
+
+  //HERE WE SHOULD COPY THE PREVIOUS ONE AND NOT CHANGING IT DIRECTLY
+  //statev_n = ipvprev->_nldStatev;
+  copyvect(ipvprev->_nldStatev, statev_n,nsdv);
+
+
+  statev_1 = ipvcur->_nldStatev;
+
+  //SHOULD BE MORE GENERAL
+  if( mat->get_pos_effectiveplasticstrainfornonlocal() >=0 )
+  {
+    //should be 66 (-39 for EP)
+    statev_n[mat->get_pos_effectiveplasticstrainfornonlocal()] = ipvprev->_nldEffectivePlasticStrain;
+    statev_n[mat->get_pos_effectiveplasticstrainfornonlocal()+1] = (ipvcur->_nldEffectivePlasticStrain-
+                                                                    ipvprev->_nldEffectivePlasticStrain);
+  }
+  if( mat->get_pos_Fd_bar() > 0 )
+  {
+    statev_n[mat->get_pos_Fd_bar()] =  ipvprev->_nlFiber_d_bar;  
+    statev_n[mat->get_pos_dFd_bar()] = (ipvcur->_nlFiber_d_bar - ipvprev->_nlFiber_d_bar);
+  } 
+
+
+  // to required to use Eshelby tensor of previous step?
+  copyvect(statev_n,statev_1,nsdv);
+  if (ipvcur->dissipationIsBlocked() or ipvprev->dissipationIsBlocked())
+  {
+    for(int nlv=0; nlv< getNbNonLocalVariables(); nlv++)
+    {
+      ipvcur->setCriticalDamage(statev_n,ipvprev->getDamageIndicator(nlv),nlv);
+      ipvcur->setCriticalDamage(statev_1,ipvprev->getDamageIndicator(nlv),nlv);
+    }
+  }
+  if(mat->isInLargeDeformation())
+  {
+     for(int i=0;i<3;i++){
+         statev_1[i] = Vstrain[i];
+     }
+     for(int i=3;i<6;i++){
+         statev_1[i] = Vstrain[i]/sq2;    //**using the current state varible to pass the total strain*****
+    }
+
+  }
+  int kinc = 1;
+  int kstep = 2;
+  SpBar = 0.0;
+  dFd_d_bar = 0.0;
+  dpdFd = 0.0;
+  dFddp = 0.0;
+  
+  int error= mat->constbox(dstrn, strs_n, strs, statev_n, statev_1, Cref, dCref, tau, dtau, Calgo, 1., dpdE, strs_dDdp_bar, &SpBar, chara_Length, &dFd_d_bar, dstrs_dFd_bar, dFd_dE, chara_Length_INC, &dpdFd, &dFddp, kinc, kstep, _timeStep);
+
+  //recompute becasue could have changed if no convergence and is used for Irreversible energy
+  for(int i=0;i<3;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i);
+    strs_n[i]=(ipvprev->_nldStress)(i);
+    dstrn[i]=(ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i);
+  }
+  for(int i=3;i<6;i++){
+    strn_n[i]=(ipvprev->_nldStrain)(i)/sq2;
+    dstrn[i]=((ipvcur->_nldStrain)(i)-(ipvprev->_nldStrain)(i))/sq2;
+    strs_n[i]=(ipvprev->_nldStress)(i)*sq2;
+  }
+  if(error==0)
+  {
+    //update stress and tangent operator
+    updateCharacteristicLengthTensor(chara_Length, statev_1);
+    updateCharacteristicLengthTensor(chara_Length_INC, statev_1);
+    for(int i=0;i<3;i++)
+    {
+      (ipvcur->_nldStress)(i)=strs[i];
+      for(int j=0;j<3;j++){
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j];
+  
+        (ipvcur->_nldCharacteristicLengthMatrix)(i,j) = chara_Length[i][j];                 //by Wu Ling
+        (ipvcur->_nldCharacteristicLengthFiber)(i,j) = chara_Length_INC[i][j];
+      }
+      if( mat->get_pos_damagefornonlocal()>0)
+      {
+        ipvcur->_nldCouplingStressEffectiveStrain(i) = strs_dDdp_bar[i];
+        ipvcur->_nldCouplingEffectiveStrainStress(i) = dpdE[i];
+      }
+      if( mat->get_pos_Fd_bar()>0)
+      {
+        ipvcur->_nldFiberDamdStrain(i) = dFd_dE[i];
+        ipvcur->_nldStressdFiberDam(i) = dstrs_dFd_bar[i];
+      }
+    }
+
+    ipvcur->_nldSpBar = SpBar;
+    ipvcur->_nldFd_d_bar = dFd_d_bar;
+    ipvcur->_nldpdFd = dpdFd;
+    ipvcur->_nldFddp = dFddp;
+
+    for(int i=3;i<6;i++)
+    {
+      (ipvcur->_nldStress)(i)=strs[i]/sq2;
+      for(int j=0;j<3;j++)
+      {
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j]/sq2;
+        (ipvcur->_nldMaterialTensor)(j,i)=Calgo[j][i]/sq2;
+      }
+      for(int j=3;j<6;j++)
+      {
+        (ipvcur->_nldMaterialTensor)(i,j)=Calgo[i][j]/2.;
+      }
+      if( mat->get_pos_damagefornonlocal()>=0)
+      {
+        ipvcur->_nldCouplingStressEffectiveStrain(i) = strs_dDdp_bar[i]/sq2;
+        ipvcur->_nldCouplingEffectiveStrainStress(i) = dpdE[i]/sq2;
+      }
+      if( mat->get_pos_Fd_bar()>0) 
+      {
+        ipvcur->_nldFiberDamdStrain(i) = dFd_dE[i]/sq2;
+        ipvcur->_nldStressdFiberDam(i) = dstrs_dFd_bar[i]/sq2;
+      }
+    }
+    if( mat->get_pos_damagefornonlocal() >= 0)
+    {
+      ipvcur->_nldDamage = statev_1[mat->get_pos_damagefornonlocal()];
+    }
+
+    if( mat->get_pos_currentplasticstrainfornonlocal() >=0)
+    {
+      ipvcur->_nldCurrentPlasticStrain = statev_1[mat->get_pos_currentplasticstrainfornonlocal()];
+    }
+
+    if( mat->get_pos_locFd() >0)
+    {
+      ipvcur->_nlFiber_loc = statev_1[mat->get_pos_locFd()];
+    }
+
+    //convert str to P  :order xx yy zz xy xz yz
+    for(int i=0;i<3;i++)
+    {
+      P(i,i) = ipvcur->_nldStress(i);
+    }
+    P(0,1) = ipvcur->_nldStress(3);
+    P(1,0) = ipvcur->_nldStress(3);
+    P(0,2) = ipvcur->_nldStress(4);
+    P(2,0) = ipvcur->_nldStress(4);
+    P(1,2) = ipvcur->_nldStress(5);
+    P(2,1) = ipvcur->_nldStress(5);
+    if(mat->isInLargeDeformation())
+    {
+      //What we have is actually sigma -> send to P
+      static STensor3 Finv, FinvT;
+      STensorOperation::inverseSTensor3(Fn, Finv);
+      STensorOperation::transposeSTensor3(Finv, FinvT);
+      P*=FinvT;
+      P*=Fn.determinant();
+    }
+
+    //convert MaterialTensor to Tangent  :order xx yy zz xy xz yz
+    Tangent(0,0,0,0) = ipvcur->_nldMaterialTensor(0, 0);
+    Tangent(0,0,0,1) = ipvcur->_nldMaterialTensor(0, 3);
+    Tangent(0,0,0,2) = ipvcur->_nldMaterialTensor(0, 4);
+    Tangent(0,0,1,0) = ipvcur->_nldMaterialTensor(0, 3);
+    Tangent(0,0,1,1) = ipvcur->_nldMaterialTensor(0, 1);
+    Tangent(0,0,1,2) = ipvcur->_nldMaterialTensor(0, 5);
+    Tangent(0,0,2,0) = ipvcur->_nldMaterialTensor(0, 4);
+    Tangent(0,0,2,1) = ipvcur->_nldMaterialTensor(0, 5);
+    Tangent(0,0,2,2) = ipvcur->_nldMaterialTensor(0, 2);
+
+    Tangent(1,1,0,0) = ipvcur->_nldMaterialTensor(1, 0);  
+    Tangent(1,1,0,1) = ipvcur->_nldMaterialTensor(1, 3);
+    Tangent(1,1,0,2) = ipvcur->_nldMaterialTensor(1, 4);
+    Tangent(1,1,1,0) = ipvcur->_nldMaterialTensor(1, 3);
+    Tangent(1,1,1,1) = ipvcur->_nldMaterialTensor(1, 1);
+    Tangent(1,1,1,2) = ipvcur->_nldMaterialTensor(1, 5);
+    Tangent(1,1,2,0) = ipvcur->_nldMaterialTensor(1, 4);
+    Tangent(1,1,2,1) = ipvcur->_nldMaterialTensor(1, 5);
+    Tangent(1,1,2,2) = ipvcur->_nldMaterialTensor(1, 2);
+
+    Tangent(2,2,0,0) = ipvcur->_nldMaterialTensor(2, 0);  
+    Tangent(2,2,0,1) = ipvcur->_nldMaterialTensor(2, 3);
+    Tangent(2,2,0,2) = ipvcur->_nldMaterialTensor(2, 4);
+    Tangent(2,2,1,0) = ipvcur->_nldMaterialTensor(2, 3);
+    Tangent(2,2,1,1) = ipvcur->_nldMaterialTensor(2, 1);
+    Tangent(2,2,1,2) = ipvcur->_nldMaterialTensor(2, 5);
+    Tangent(2,2,2,0) = ipvcur->_nldMaterialTensor(2, 4);
+    Tangent(2,2,2,1) = ipvcur->_nldMaterialTensor(2, 5);
+    Tangent(2,2,2,2) = ipvcur->_nldMaterialTensor(2, 2);
+
+    Tangent(0,1,0,0) = ipvcur->_nldMaterialTensor(3, 0);
+    Tangent(0,1,0,1) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(0,1,0,2) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(0,1,1,0) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(0,1,1,1) = ipvcur->_nldMaterialTensor(3, 1);
+    Tangent(0,1,1,2) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(0,1,2,0) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(0,1,2,1) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(0,1,2,2) = ipvcur->_nldMaterialTensor(3, 2);
+
+    Tangent(1,0,0,0) = ipvcur->_nldMaterialTensor(3, 0);
+    Tangent(1,0,0,1) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(1,0,0,2) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(1,0,1,0) = ipvcur->_nldMaterialTensor(3, 3);
+    Tangent(1,0,1,1) = ipvcur->_nldMaterialTensor(3, 1);
+    Tangent(1,0,1,2) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(1,0,2,0) = ipvcur->_nldMaterialTensor(3, 4);
+    Tangent(1,0,2,1) = ipvcur->_nldMaterialTensor(3, 5);
+    Tangent(1,0,2,2) = ipvcur->_nldMaterialTensor(3, 2);
+
+    Tangent(0,2,0,0) = ipvcur->_nldMaterialTensor(4, 0);
+    Tangent(0,2,0,1) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(0,2,0,2) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(0,2,1,0) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(0,2,1,1) = ipvcur->_nldMaterialTensor(4, 1);
+    Tangent(0,2,1,2) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(0,2,2,0) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(0,2,2,1) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(0,2,2,2) = ipvcur->_nldMaterialTensor(4, 2);
+
+    Tangent(2,0,0,0) = ipvcur->_nldMaterialTensor(4, 0);
+    Tangent(2,0,0,1) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(2,0,0,2) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(2,0,1,0) = ipvcur->_nldMaterialTensor(4, 3);
+    Tangent(2,0,1,1) = ipvcur->_nldMaterialTensor(4, 1);
+    Tangent(2,0,1,2) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(2,0,2,0) = ipvcur->_nldMaterialTensor(4, 4);
+    Tangent(2,0,2,1) = ipvcur->_nldMaterialTensor(4, 5);
+    Tangent(2,0,2,2) = ipvcur->_nldMaterialTensor(4, 2);
+
+    Tangent(2,1,0,0) = ipvcur->_nldMaterialTensor(5, 0);
+    Tangent(2,1,0,1) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(2,1,0,2) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(2,1,1,0) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(2,1,1,1) = ipvcur->_nldMaterialTensor(5, 1);
+    Tangent(2,1,1,2) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(2,1,2,0) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(2,1,2,1) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(2,1,2,2) = ipvcur->_nldMaterialTensor(5, 2);
+
+    Tangent(1,2,0,0) = ipvcur->_nldMaterialTensor(5, 0);
+    Tangent(1,2,0,1) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(1,2,0,2) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(1,2,1,0) = ipvcur->_nldMaterialTensor(5, 3);
+    Tangent(1,2,1,1) = ipvcur->_nldMaterialTensor(5, 1);
+    Tangent(1,2,1,2) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(1,2,2,0) = ipvcur->_nldMaterialTensor(5, 4);
+    Tangent(1,2,2,1) = ipvcur->_nldMaterialTensor(5, 5);
+    Tangent(1,2,2,2) = ipvcur->_nldMaterialTensor(5, 2);
+    
+    /*fullMatrix<double> Calgo_fullMatrix(6,6);
+    for(int i=0;i<6;i++)
+    {
+      for(int j=0;j<6;j++){
+        Calgo_fullMatrix(i,j)=Calgo[i][j];
+      }
+    }
+    for(int i=3;i<6;i++)
+    {
+      for(int j=0;j<3;j++)
+      {
+        Calgo_fullMatrix(i,j)*=(1./sq2);
+        Calgo_fullMatrix(j,i)*=2.;
+        Calgo_fullMatrix(j,i)*=(1./sq2);
+      }
+    }   
+    STensorOperation::fromFullMatrixToSTensor43(Calgo_fullMatrix,Tangent);*/
+
+
+    ipvcur->_elasticEne = mat->getElasticEnergy(statev_1);
+    ipvcur->_plasticEne = mat->getPlasticEnergy(statev_1);
+
+    // we use plastic energy = plastenergy_n + sum Delta eps:(sigma_n+1+sigma_n)2.  
+    // dissipated energy = plastic energy - 1/2 [(sigma_n+1 : Cele^-1 : sigma_n+1   ]
+    ipvcur->_stressWork=ipvprev->_stressWork;
+    for (int i=0; i < 6; i++)
+    {
+      ipvcur->_stressWork+= 0.5*(strs[i]+strs_n[i])*dstrn[i];
+    }
+    mat->get_elOp(statev_1,C0PathFollowing);
+    int errorInv=0;
+    inverse(C0PathFollowing,invC0PathFollowing,&errorInv,6);
+
+    double &disEne=ipvcur->getRefToIrreversibleEnergy();
+    STensor3& DirrEnergDF = ipvcur->getRefToDIrreversibleEnergyDF();
+    double &dIrrDpTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(0);
+
+    //elastic strain
+    for (int i=0; i < 6; i++)
+    {
+      elStrainPathFollowing[i]=0.;
+      for(int j=0; j < 6; j++)
+      {
+        elStrainPathFollowing[i] +=invC0PathFollowing[i][j] *strs[j];
+      }
+    }
+    disEne=ipvcur->_stressWork;
+    dIrrDpTilde=0.;
+    if( mat->get_pos_Fd_bar()>0)
+    {
+      double &dIrrDdamTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(1);
+      dIrrDdamTilde=0.;
+    }
+    for (int i=0; i < 6; i++)
+    {
+      disEne-=0.5*elStrainPathFollowing[i]*strs[i];
+      dEnePathFollowingdStrain[i]=(strs[i]+strs_n[i])*0.5;
+      for(int j=0; j < 6; j++)
+      {
+        dEnePathFollowingdStrain[i] += Calgo[j][i] *(0.5*dstrn[j]-elStrainPathFollowing[j]);
+      }
+      dIrrDpTilde+= strs_dDdp_bar[i]*(0.5*dstrn[i]-elStrainPathFollowing[i]);// dsigma d p tilde
+      if( mat->get_pos_Fd_bar()>0)
+      {
+        double &dIrrDdamTilde = ipvcur->getRefToDIrreversibleEnergyDNonLocalVariable(1);
+        dIrrDdamTilde+=dstrs_dFd_bar[i]*(0.5*dstrn[i]-elStrainPathFollowing[i]); //d sigma d d tilde d
+      }
+    }
+    for(int i=0;i<3;i++)
+    {
+      DirrEnergDF(i,i) = dEnePathFollowingdStrain[i];
+    }
+    DirrEnergDF(0,1) = dEnePathFollowingdStrain[3]/sq2;
+    DirrEnergDF(1,0) = dEnePathFollowingdStrain[3]/sq2;
+    DirrEnergDF(0,2) = dEnePathFollowingdStrain[4]/sq2;
+    DirrEnergDF(2,0) = dEnePathFollowingdStrain[4]/sq2;
+    DirrEnergDF(1,2) = dEnePathFollowingdStrain[5]/sq2;
+    DirrEnergDF(2,1) = dEnePathFollowingdStrain[5]/sq2;
+    
+    STensor43 Cel, Sel;
+    ElasticStiffness_incOri(e1,e2,e3,&Cel);
+    STensorOperation::inverseSTensor43(Cel,Sel);
+      
+    STensor3 eps;
+    static STensor3 I(1.);
+    for (int i=0; i<3; i++){
+      for (int j=0; j<3; j++){
+        eps(i,j) =   0.5*(Fn(i,j)+Fn(j,i)) - I(i,j);
+      }
+    }
+    epsEig = eps;
+    STensorOperation::multSTensor43STensor3Add(Sel,P,-1.,epsEig);
+    eigenstrain = epsEig;
+    STensorOperation::multSTensor43STensor3(Cel,eigenstrain,eigenstress);
+    eigenstress *= -1.;
+    STensorOperation::unity(depsEigdeps);
+    STensorOperation::multSTensor43Add(Sel,Tangent,-1.,depsEigdeps);  
+  }
+  else
+  {
+    //constbox did not converge
+    P(0,0) = P(1,1) = P(2,2) = sqrt(-1.); // to exist NR and performed next step with a smaller incremenet
+  }
+}
+
+
+
+void mlawNonLocalDamage::constitutive(
+                            const STensor3& F0,         // initial deformation gradient (input @ time n)
+                            const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
+                            STensor3 &P,                // updated 1st Piola-Kirchhoff stress tensor (output)
+                                                        // contains the initial values on input
+                            const IPVariable *ipvprevi,       // array of initial internal variable
+                            IPVariable *ipvcuri,             // updated array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // constitutive tangents (output)
+                            std::vector<STensor3>  &dLocalPlasticStrainDStrain,
+  			    std::vector<STensor3>  &dStressDNonLocalPlasticStrain,
+                            fullMatrix<double>     &dLocalPlasticStrainDNonLocalPlasticStrain,
+                            const bool stiff,
+                            STensor43* elasticTangent) const
+{
+  if(elasticTangent!=NULL) Msg::Error(" mlawNonLocalDamage STensor43* elasticTangent not defined");
+  const IPNonLocalDamage *ipvprev = dynamic_cast<const IPNonLocalDamage *> (ipvprevi);
+  IPNonLocalDamage *ipvcur = dynamic_cast<IPNonLocalDamage *> (ipvcuri); 
+
+  mlawNonLocalDamage::constitutive(F0, Fn, P, ipvprev, ipvcur, Tangent, stiff,elasticTangent);
+  if(stiff && !STensorOperation::isnan(P))
+  {
+    dLocalPlasticStrainDStrain[0](0,0) = ipvcur->_nldCouplingEffectiveStrainStress(0); //minus?
+    dLocalPlasticStrainDStrain[0](1,1) = ipvcur->_nldCouplingEffectiveStrainStress(1);
+    dLocalPlasticStrainDStrain[0](2,2) = ipvcur->_nldCouplingEffectiveStrainStress(2);
+    dLocalPlasticStrainDStrain[0](0,1) = ipvcur->_nldCouplingEffectiveStrainStress(3);
+    dLocalPlasticStrainDStrain[0](1,0) = ipvcur->_nldCouplingEffectiveStrainStress(3);
+    dLocalPlasticStrainDStrain[0](0,2) = ipvcur->_nldCouplingEffectiveStrainStress(4);
+    dLocalPlasticStrainDStrain[0](2,0) = ipvcur->_nldCouplingEffectiveStrainStress(4);
+    dLocalPlasticStrainDStrain[0](2,1) = ipvcur->_nldCouplingEffectiveStrainStress(5);
+    dLocalPlasticStrainDStrain[0](1,2) = ipvcur->_nldCouplingEffectiveStrainStress(5);
+
+    dStressDNonLocalPlasticStrain[0](0,0) = ipvcur->_nldCouplingStressEffectiveStrain(0);
+    dStressDNonLocalPlasticStrain[0](1,1) = ipvcur->_nldCouplingStressEffectiveStrain(1);
+    dStressDNonLocalPlasticStrain[0](2,2) = ipvcur->_nldCouplingStressEffectiveStrain(2);
+    dStressDNonLocalPlasticStrain[0](0,1) = ipvcur->_nldCouplingStressEffectiveStrain(3);
+    dStressDNonLocalPlasticStrain[0](1,0) = ipvcur->_nldCouplingStressEffectiveStrain(3);
+    dStressDNonLocalPlasticStrain[0](0,2) = ipvcur->_nldCouplingStressEffectiveStrain(4);
+    dStressDNonLocalPlasticStrain[0](2,0) = ipvcur->_nldCouplingStressEffectiveStrain(4);
+    dStressDNonLocalPlasticStrain[0](2,1) = ipvcur->_nldCouplingStressEffectiveStrain(5);
+    dStressDNonLocalPlasticStrain[0](1,2) = ipvcur->_nldCouplingStressEffectiveStrain(5);
+
+    dLocalPlasticStrainDNonLocalPlasticStrain(0,0) = ipvcur->_nldSpBar;
+    if(getNbNonLocalVariables()>1){
+      dLocalPlasticStrainDNonLocalPlasticStrain(1,0) = ipvcur->_nldFddp; 
+      dLocalPlasticStrainDNonLocalPlasticStrain(0,1) = ipvcur->_nldpdFd;
+      dLocalPlasticStrainDNonLocalPlasticStrain(1,1) = ipvcur->_nldFd_d_bar;
+    }
+
+    if(getNbNonLocalVariables()>1){
+      dLocalPlasticStrainDStrain[1](0,0) = ipvcur->_nldFiberDamdStrain(0); 
+      dLocalPlasticStrainDStrain[1](1,1) = ipvcur->_nldFiberDamdStrain(1);
+      dLocalPlasticStrainDStrain[1](2,2) = ipvcur->_nldFiberDamdStrain(2);
+      dLocalPlasticStrainDStrain[1](0,1) = ipvcur->_nldFiberDamdStrain(3);
+      dLocalPlasticStrainDStrain[1](1,0) = ipvcur->_nldFiberDamdStrain(3);
+      dLocalPlasticStrainDStrain[1](0,2) = ipvcur->_nldFiberDamdStrain(4);
+      dLocalPlasticStrainDStrain[1](2,0) = ipvcur->_nldFiberDamdStrain(4);
+      dLocalPlasticStrainDStrain[1](2,1) = ipvcur->_nldFiberDamdStrain(5);
+      dLocalPlasticStrainDStrain[1](1,2) = ipvcur->_nldFiberDamdStrain(5);
+
+
+  
+      dStressDNonLocalPlasticStrain[1](0,0) = ipvcur->_nldStressdFiberDam(0);
+      dStressDNonLocalPlasticStrain[1](1,1) = ipvcur->_nldStressdFiberDam(1);
+      dStressDNonLocalPlasticStrain[1](2,2) = ipvcur->_nldStressdFiberDam(2);
+      dStressDNonLocalPlasticStrain[1](0,1) = ipvcur->_nldStressdFiberDam(3);
+      dStressDNonLocalPlasticStrain[1](1,0) = ipvcur->_nldStressdFiberDam(3);
+      dStressDNonLocalPlasticStrain[1](0,2) = ipvcur->_nldStressdFiberDam(4);
+      dStressDNonLocalPlasticStrain[1](2,0) = ipvcur->_nldStressdFiberDam(4);
+      dStressDNonLocalPlasticStrain[1](2,1) = ipvcur->_nldStressdFiberDam(5);   
+      dStressDNonLocalPlasticStrain[1](1,2) = ipvcur->_nldStressdFiberDam(5);
+    }
+  }
+
+  /*if(STensorOperation::isnan(P)) 
+    Msg::Error("P is nan");
+  if(STensorOperation::isnan(Tangent)) 
+    Msg::Error("Tangent is nan");
+  if(STensorOperation::isnan(dLocalPlasticStrainDStrain[0]))
+    Msg::Error("dLocalPlasticStrainDStrain[0] is nan");
+  if(STensorOperation::isnan(dGradLocalPlasticStrainDStrain[0]))
+    Msg::Error("dGradLocalPlasticStrainDStrain[0] is nan");
+  if(STensorOperation::isnan(dStressDNonLocalPlasticStrain[0]))
+    Msg::Error("dStressDNonLocalPlasticStrain[0] is nan");
+  if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(0,0)))
+    Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[0,0] is nan");
+  if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(0,0)))
+    Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain is nan[0,0]");
+  if(getNbNonLocalVariables()>1){
+    if(STensorOperation::isnan(dLocalPlasticStrainDStrain[1]))
+      Msg::Error("dLocalPlasticStrainDStrain[1] is nan");
+    if(STensorOperation::isnan(dStressDNonLocalPlasticStrain[1]))
+      Msg::Error("dStressDNonLocalPlasticStrain[1] is nan");
+    if(STensorOperation::isnan(dGradLocalPlasticStrainDStrain[1]))
+      Msg::Error("dGradLocalPlasticStrainDStrain[1] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(1,0)))
+      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[1,0] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(0,1)))
+      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[0,1] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDNonLocalPlasticStrain(1,1)))
+      Msg::Error("dLocalPlasticStrainDNonLocalPlasticStrain[1,1] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(1,0)))
+      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[1,0] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(0,1)))
+      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[0,1] is nan");
+    if(STensorOperation::isnan(dLocalPlasticStrainDGradNonLocalPlasticStrain(1,1)))
+      Msg::Error("dLocalPlasticStrainDGradNonLocalPlasticStrain[1,1] is nan");
+  }*/
+
+}
+
+const double mlawNonLocalDamage::bulkModulus() const
+{
+  return 2.*_mu0*(1+_nu0)/3./(1.-2.*_nu0);
+}
+const double mlawNonLocalDamage::shearModulus() const
+{
+  return _mu0;
+}
+
+const double mlawNonLocalDamage::poissonRatio() const
+{
+  return _nu0;
+}
+
+void mlawNonLocalDamage::ElasticStiffness(STensor43* elasticTensor) const
+{
+  fullMatrix<double> Cel_fullMatrix(6,6);
+  static double **Cel_matrix;
+  static bool init=false;
+  if(init==false)
+  {
+    mallocmatrix(&Cel_matrix,6,6);
+    init=true;
+  }
+  mat->get_elOp(Cel_matrix);
+  for(int i=0;i<6;i++)
+  {
+    for(int j=0;j<6;j++){
+      Cel_fullMatrix(i,j)=Cel_matrix[i][j];
+    }
+  }
+  for(int i=3;i<6;i++)
+  {
+    for(int j=0;j<3;j++)
+    {
+      Cel_fullMatrix(i,j)*=(1./sq2);
+      Cel_fullMatrix(j,i)*=2.;
+      Cel_fullMatrix(j,i)*=(1./sq2);
+    }
+  }
+  STensorOperation::fromFullMatrixToSTensor43(Cel_fullMatrix,(*elasticTensor));
+};
+
+void mlawNonLocalDamage::ElasticStiffnessMtx(double *statev, STensor43* elasticTensor) const
+{
+  fullMatrix<double> Cel_fullMatrix(6,6);
+  static double **Cel_matrix;
+  static bool init=false;
+  if(init==false)
+  {
+    mallocmatrix(&Cel_matrix,6,6);
+    init=true;
+  }
+  mat->get_elOp_mtx(statev,Cel_matrix);
+  for(int i=0;i<6;i++)
+  {
+    for(int j=0;j<6;j++){
+      Cel_fullMatrix(i,j)=Cel_matrix[i][j];
+    }
+  }
+  for(int i=3;i<6;i++)
+  {
+    for(int j=0;j<3;j++)
+    {
+      Cel_fullMatrix(i,j)*=(1./sq2);
+      Cel_fullMatrix(j,i)*=2.;
+      Cel_fullMatrix(j,i)*=(1./sq2);
+    }
+  }
+  STensorOperation::fromFullMatrixToSTensor43(Cel_fullMatrix,(*elasticTensor));
+};
+
+void mlawNonLocalDamage::ElasticStiffnessInc(double *statev, STensor43* elasticTensor) const
+{
+  fullMatrix<double> Cel_fullMatrix(6,6);
+  static double **Cel_matrix;
+  static bool init=false;
+  if(init==false)
+  {
+    mallocmatrix(&Cel_matrix,6,6);
+    init=true;
+  }
+  mat->get_elOp_icl(statev,Cel_matrix);
+  for(int i=0;i<6;i++)
+  {
+    for(int j=0;j<6;j++){
+      Cel_fullMatrix(i,j)=Cel_matrix[i][j];
+    }
+  }
+  for(int i=3;i<6;i++)
+  {
+    for(int j=0;j<3;j++)
+    {
+      Cel_fullMatrix(i,j)*=(1./sq2);
+      Cel_fullMatrix(j,i)*=2.;
+      Cel_fullMatrix(j,i)*=(1./sq2);
+    }
+  }
+  STensorOperation::fromFullMatrixToSTensor43(Cel_fullMatrix,(*elasticTensor));
+};
+
+void mlawNonLocalDamage::ElasticStiffness_incOri(double e1, double e2, double e3, STensor43* elasticTensor) const
+{
+  fullMatrix<double> Cel_fullMatrix(6,6);
+  static double **Cel_matrix;
+  static bool init=false;
+  if(init==false)
+  {
+    mallocmatrix(&Cel_matrix,6,6);
+    init=true;
+  }
+  mat->setEuler(e1,e2,e3);
+  mat->get_elOp(Cel_matrix);
+  for(int i=0;i<6;i++)
+  {
+    for(int j=0;j<6;j++){
+      Cel_fullMatrix(i,j)=Cel_matrix[i][j];
+    }
+  }
+  for(int i=3;i<6;i++)
+  {
+    for(int j=0;j<3;j++)
+    {
+      Cel_fullMatrix(i,j)*=(1./sq2);
+      Cel_fullMatrix(j,i)*=2.;
+      Cel_fullMatrix(j,i)*=(1./sq2);
+    }
+  }
+  STensorOperation::fromFullMatrixToSTensor43(Cel_fullMatrix,(*elasticTensor));
+};
+
+void mlawNonLocalDamage::SecantStiffnessIsotropic(const IPVariable *q1i, STensor43& Secant) const
+{
+  const IPNonLocalDamage* ipvcur = static_cast<const IPNonLocalDamage*>(q1i);
+
+  STensor3 eps, P;
+  for(int i=0;i<3;i++)
+  {
+    P(i,i) = ipvcur->_nldStress(i);
+    eps(i,i) = ipvcur->_nldStrain(i);
+  }
+  P(0,1) = P(1,0) = ipvcur->_nldStress(3);
+  P(0,2) = P(2,0) = ipvcur->_nldStress(4);
+  P(1,2) = P(2,1) = ipvcur->_nldStress(5);
+  eps(0,1) = eps(1,0) = ipvcur->_nldStrain(3);
+  eps(0,2) = eps(2,0) = ipvcur->_nldStrain(4);
+  eps(1,2) = eps(2,1) = ipvcur->_nldStrain(5);
+
+  STensor3 eps_dev = eps.dev();
+  double epsEq = sqrt(2./3.*eps_dev.dotprod());
+  if(epsEq < 1.e-12)
+  {
+    ElasticStiffness(&Secant);
+  }
+  else
+  {
+    STensor3 P_dev = P.dev();
+    double sigEq = sqrt(1.5*P_dev.dotprod());
+    double shearmodulus_secant = sigEq/(3.*epsEq);
+  
+    double p = P(0,0)+P(1,1)+P(2,2);
+    p *= (1./3.);
+    double eps_vol = eps(0,0)+eps(1,1)+eps(2,2);
+    double bulkmodulus_secant = p/eps_vol;
+
+    STensor43 dev_part;
+    STensorOperation::sphericalfunction(Secant);
+    Secant *= 3.;
+    Secant *= bulkmodulus_secant;
+    STensorOperation::deviatorfunction(dev_part);    
+    dev_part *= 2.;
+    dev_part *= shearmodulus_secant;
+    Secant += dev_part;
+  }
+};
 
 MFH::Material* init_material(double *_props,int idmat)
 {
diff --git a/NonLinearSolver/materialLaw/mlawNonLocalDamage.h b/NonLinearSolver/materialLaw/mlawNonLocalDamage.h
index a9bd853999ba58f1b49423a0ba14f131c7fe51ae..2ded6164f8ccdf67f7a070217b723f0bd29e2bc4 100644
--- a/NonLinearSolver/materialLaw/mlawNonLocalDamage.h
+++ b/NonLinearSolver/materialLaw/mlawNonLocalDamage.h
@@ -84,10 +84,7 @@ class mlawNonLocalDamage : public materialLaw
   // function of materialLaw
   virtual matname getType() const{return materialLaw::nonLocalDamage;}
 
-  virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const
-  {
-     Msg::Error("Cannot be called");
-  }
+  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 bool withEnergyDissipation() const {return true;};
   virtual void createIPState(IPNonLocalDamage *ivi, IPNonLocalDamage *iv1, IPNonLocalDamage *iv2) const;
@@ -99,6 +96,10 @@ class mlawNonLocalDamage : public materialLaw
   virtual const double poissonRatio() const;
   virtual int getNbNonLocalVariables() const {return nlVar;};
   virtual void updateCharacteristicLengthTensor(double** chara_Length, double *statev) const {};
+  virtual void ElasticStiffness(STensor43* elasticTensor) const;
+  virtual void ElasticStiffnessMtx(double *statev, STensor43* elasticTensor) const;
+  virtual void ElasticStiffnessInc(double *statev, STensor43* elasticTensor) const;
+  virtual void ElasticStiffness_incOri(double e1, double e2, double e3,STensor43* elasticTensor) const;
   // specific function
  public:
   virtual void constitutive(
@@ -114,6 +115,27 @@ class mlawNonLocalDamage : public materialLaw
                             const bool dTangent =false,
                             STensor63* dCalgdeps = NULL) const;
 
+  virtual void constitutiveTFA(
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const;
+                            
+  virtual void constitutiveTFA_incOri(
+                            const STensor3& F0,         // previous deformation gradient (input @ time n)
+                            const STensor3& Fn,         // current deformation gradient (input @ time n+1)
+                            const fullVector<double>& euler,
+                            STensor3 &P,                // current 1st Piola-Kirchhoff stress tensor (output)
+                            const IPVariable *q0,       // array of previous internal variables
+                            IPVariable *q1,             // current array of internal variable (in ipvcur on output),
+                            STensor43 &Tangent,         // tangents (output)
+                            STensor3 &epsEig,
+                            STensor43 &depsEigdeps) const;
+
   virtual void constitutive(
                             const STensor3& F0,         // initial deformation gradient (input @ time n)
                             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
@@ -128,7 +150,9 @@ class mlawNonLocalDamage : public materialLaw
                             const bool stiff,            // if true compute the tangents
                             STensor43* elasticTangent = NULL) const;
 
-  int getNsdv() const {return nsdv;}
+  int getNsdv() const { return nsdv;}
+  
+  virtual void SecantStiffnessIsotropic(const IPVariable *q1i, STensor43& Secant) const;
 
  #endif // SWIG
 };
diff --git a/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.cpp b/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.cpp
index 90a0c33a512a54fb6f8acacbb4d3b9e2ecd444f5..d321f89867d632c4ac849148e1dd90dcab7db47c 100644
--- a/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.cpp
+++ b/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.cpp
@@ -55,9 +55,9 @@ mlawNonLocalDamage_Stoch::mlawNonLocalDamage_Stoch(const int num, const double r
         //allocate memory if random variable are required
         if (pos_euler != 0){
 	     mallocvector(&_Euler_mean,3);
-	     mallocvector(&_Euler_tmp,3);
-             mallocmatrix(&_Euler_tmp2,3,3);
-             mallocmatrix(&_Euler_tmp3,3,3);
+	     //mallocvector(&_Euler_tmp,3);
+             //mallocmatrix(&_Euler_tmp2,3,3);
+             //mallocmatrix(&_Euler_tmp3,3,3);
              _Euler_mean[0] = euler0;
              _Euler_mean[1] = euler1;
              _Euler_mean[2] = euler2;
@@ -1205,7 +1205,12 @@ void mlawNonLocalDamage_Stoch::updateCharacteristicLengthTensor(double** chara_L
   if(pos_euler != 0)
   {
     //Msg::Info("Non local lengthsi nitial %e, %e, %e, %e, %e, %e, %e, %e, %e", chara_Length[0][0], chara_Length[0][1], chara_Length[0][2], chara_Length[1][0], chara_Length[1][1], chara_Length[1][2], chara_Length[2][0], chara_Length[2][1], chara_Length[2][2]);
-    if(_Euler_tmp==NULL) Msg::Error("mlawNonLocalDamage_Stoch::updateCharacteristicLengthTensor: _Euler_tmp==NULL");
+    //if(_Euler_tmp==NULL) Msg::Error("mlawNonLocalDamage_Stoch::updateCharacteristicLengthTensor: _Euler_tmp==NULL");
+    
+    mallocvector(&_Euler_tmp,3);
+    mallocmatrix(&_Euler_tmp2,3,3);
+    mallocmatrix(&_Euler_tmp3,3,3);
+        
     _Euler_tmp[0]=stv[pos_euler];
     _Euler_tmp[1]=stv[pos_euler+1];
     _Euler_tmp[2]=stv[pos_euler+2];
@@ -1221,6 +1226,49 @@ void mlawNonLocalDamage_Stoch::updateCharacteristicLengthTensor(double** chara_L
     eul_mat33(_Euler_tmp, _Euler_tmp3);
     transpose(_Euler_tmp3,_Euler_tmp3,3,3);  
     rot33(_Euler_tmp3,_Euler_tmp2, chara_Length);
+    
+    delete _Euler_tmp;
+    _Euler_tmp = NULL;
+    for(int i=0;i<3;i++)
+    {
+      delete _Euler_tmp2[i];
+    }
+    delete _Euler_tmp2;
+    _Euler_tmp2 = NULL;
+    for(int i=0;i<3;i++)
+    {
+      delete _Euler_tmp3[i];
+    }
+    delete _Euler_tmp3;
+    _Euler_tmp3 = NULL;
+
+    
     //Msg::Info("Non local lengths %e, %e, %e, %e, %e, %e, %e, %e, %e", chara_Length[0][0], chara_Length[0][1], chara_Length[0][2], chara_Length[1][0], chara_Length[1][1], chara_Length[1][2], chara_Length[2][0], chara_Length[2][1], chara_Length[2][2]);
   }
 }
+
+void mlawNonLocalDamage_Stoch::getLocalOrientation(fullVector<double> &GaussP, fullVector<double> &vecEulerAngles) const
+{
+  double* vec = NULL;
+  mallocvector(&vec,3);
+  
+  SVector3 GP;
+  GP(0) = GaussP(0);
+  GP(1) = GaussP(1);
+  GP(2) = GaussP(2);
+  
+  if(Reuler != NULL){
+  Reuler->RandomGen(GP,vec);}
+  else{
+  vec[0] = 0.;
+  vec[1] = 0.;
+  vec[2] = 0.;
+  }
+  
+  vecEulerAngles(0) = vec[0];
+  vecEulerAngles(1) = vec[1];
+  vecEulerAngles(2) = vec[2];
+  
+  delete vec;
+}
+
diff --git a/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.h b/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.h
index 4dd4ef6967913d3680400b3b3964a74f565e6611..e8ff6b647b0524b1b51b00f1eec3becdc48d7584 100644
--- a/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.h
+++ b/NonLinearSolver/materialLaw/mlawNonLocalDamage_Stoch.h
@@ -91,6 +91,7 @@ class mlawNonLocalDamage_Stoch : public mlawNonLocalDamage
   virtual void createIPState(const SVector3 &GaussP, IPNonLocalDamage *ivi, IPNonLocalDamage *iv1, IPNonLocalDamage *iv2) const;
   virtual void createIPVariable(const SVector3 &GaussP, IPNonLocalDamage *&ipv, bool hasBodyForce, const MElement *ele,const int nbFF, const IntPt *GP, const int gpt) const;
 
+  virtual void getLocalOrientation(fullVector<double> &GaussP, fullVector<double> &vecEulerAngles) const;
  #endif // SWIG
 };
 
diff --git a/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.cpp b/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.cpp
index 1a6afa573532df5007e5f4ea2b7b3ded7761c17e..5c5cc2d5edffae0ac99b75cef487a28df1822839 100644
--- a/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.cpp
+++ b/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.cpp
@@ -104,13 +104,29 @@ void mlawTFAMaterialLaws::loadClusterSummaryAndInteractionTensorsFromFiles(const
   }
 }
 
+void mlawTFAMaterialLaws::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName)
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(clusterSummaryFileName,interactionTensorsFileName);
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
 void mlawTFAMaterialLaws::loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName, 
                                                                    const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                                   const std::string PlasticEqStrainConcentrationHarmonicFileName)
+                                                                   const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                                   const std::string PlasticEqStrainConcentrationPowerFileName)
 {
   if (_reductionModel!=NULL)
   {
-    _reductionModel->loadPlasticEqStrainConcentrationFromFile(PlasticEqStrainConcentrationFileName,PlasticEqStrainConcentrationGeometricFileName,PlasticEqStrainConcentrationHarmonicFileName);
+    _reductionModel->loadPlasticEqStrainConcentrationFromFile(PlasticEqStrainConcentrationFileName,PlasticEqStrainConcentrationGeometricFileName,
+                                                              PlasticEqStrainConcentrationHarmonicFileName,PlasticEqStrainConcentrationPowerFileName);
   }
   else
   {
@@ -121,11 +137,11 @@ void mlawTFAMaterialLaws::loadPlasticEqStrainConcentrationFromFile(const std::st
 
 
 
-void mlawTFAMaterialLaws::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName, const std::string EshelbyInteractionSTD)
+void mlawTFAMaterialLaws::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName)
 {
   if (_reductionModel!=NULL)
   {
-    _reductionModel->loadEshelbyInteractionTensorsFromFile(EshelbyInteractionTensorsFileName,EshelbyInteractionSTD);
+    _reductionModel->loadEshelbyInteractionTensorsFromFile(EshelbyInteractionTensorsFileName);
   }
   else
   {
@@ -164,11 +180,11 @@ void mlawTFAMaterialLaws::loadInteractionTensorsHomogenizedFrameELFromFile(const
 
 
 
-void mlawTFAMaterialLaws::loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD, const std::string InteractionSTD)
+void mlawTFAMaterialLaws::loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD)
 {
   if (_reductionModel!=NULL)
   {
-    _reductionModel->loadClusterStandardDeviationFromFile(ClusterStrainConcentrationSTD, InteractionSTD);
+    _reductionModel->loadClusterStandardDeviationFromFile(ClusterStrainConcentrationSTD);
   }
   else
   {
@@ -192,6 +208,60 @@ void mlawTFAMaterialLaws::loadElasticStrainConcentrationDerivativeFromFile(const
 }
 
 
+void mlawTFAMaterialLaws::loadReferenceStiffnessFromFile(const std::string ReferenceStiffnessFileName)
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->loadReferenceStiffnessFromFile(ReferenceStiffnessFileName);
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
+void mlawTFAMaterialLaws::loadReferenceStiffnessIsoFromFile(const std::string ReferenceStiffnessIsoFileName)
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->loadReferenceStiffnessIsoFromFile(ReferenceStiffnessIsoFileName);
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
+void mlawTFAMaterialLaws::loadInteractionTensorIsoFromFile(const std::string InteractionTensorIsoFileName)
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->loadInteractionTensorIsoFromFile(InteractionTensorIsoFileName);
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
+
+void mlawTFAMaterialLaws::loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName)
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->loadClusterFiberOrientationFromFile(OrientationDataFileName);
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
+
 void mlawTFAMaterialLaws::setTFAMethod(int TFAMethodNum, int dim, int correction, int solverType, int tag)
 {
   if (_ownData)
@@ -201,10 +271,24 @@ void mlawTFAMaterialLaws::setTFAMethod(int TFAMethodNum, int dim, int correction
   }
   
   _ownData = true;
+  bool withFrame = false;
+  bool polarization = false;
   if (TFAMethodNum == 0)
   {
     Msg::Info("IncrementalTangent is used !!!");
-    _reductionModel = new IncrementalTangentTFA(solverType, dim, correction, tag);
+    _reductionModel = new IncrementalTangentTFA(solverType, dim, correction, withFrame, polarization, tag);
+  }
+  else if(TFAMethodNum == 1)
+  {
+    withFrame = true;
+    Msg::Info("IncrementalTangentWithFrame is used !!!");
+    _reductionModel = new IncrementalTangentTFAWithFrame(solverType, dim, correction, withFrame, polarization, tag);
+  }
+  else if(TFAMethodNum == 2)
+  {
+    polarization = true;
+    Msg::Info("IncrementalTangentTFAPolarization is used !!!");
+    _reductionModel = new IncrementalTangentTFAPolarization(solverType, dim, correction, withFrame, polarization, tag);
   }
   else
   {
@@ -212,6 +296,19 @@ void mlawTFAMaterialLaws::setTFAMethod(int TFAMethodNum, int dim, int correction
   }
 }
 
+void mlawTFAMaterialLaws::setClusterIncOrientation()
+{
+  if (_reductionModel!=NULL)
+  {
+    _reductionModel->setClusterIncOrientation();
+  }
+  else
+  {
+    Msg::Error("reduction model must be allocated by the function setTFAMethod first !!!");
+    Msg::Exit(0);
+  }
+}
+
 
 void mlawTFAMaterialLaws::constitutive(
             const STensor3& F0,         // initial deformation gradient (input @ time n)
@@ -226,7 +323,6 @@ void mlawTFAMaterialLaws::constitutive(
             STensor63* dCalgdeps) const
 {
 
-   
   if (_reductionModel != NULL)
   {
     const IPTFA* q0 = static_cast<const IPTFA*>(q0i);
diff --git a/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.h b/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.h
index 42b74a5655338a3135a47f6f09153262bdd18584..4f9ac5936d638082ad7533bd8b32e045586dec28 100644
--- a/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.h
+++ b/NonLinearSolver/materialLaw/mlawTFAMaterialLaws.h
@@ -31,18 +31,28 @@ class mlawTFAMaterialLaws : public materialLaw{
     void setTFAMethod(int TFAMethodNum, int dim, int correction=0, int solverType=0, int tag=1000);
     void loadClusterSummaryAndInteractionTensorsFromFiles(const std::string clusterSummaryFileName, 
                                         const std::string interactionTensorsFileName);
-    void loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD, const std::string InteractionSTD);
+    void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName);
+    void loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD);
 
     void loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName,
                                                   const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName);
+                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                  const std::string PlasticEqStrainConcentrationPowerFileName);
 
     void loadElasticStrainConcentrationDerivativeFromFile(const std::string ElasticStrainConcentrationDerivative);
 
-    void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName, const std::string EshelbyInteractionSTD);
+    void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName);
     void loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName);
     void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string InteractionTensorsHomogenizedFrameELFileName);
     
+    void loadReferenceStiffnessFromFile(const std::string ReferenceStiffnessFileName);
+    void loadReferenceStiffnessIsoFromFile(const std::string ReferenceStiffnessIsoFileName);
+    void loadInteractionTensorIsoFromFile(const std::string InteractionTensorIsoFileName);
+    
+    void setClusterIncOrientation();
+    void loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName);
+    
     void addClusterMaterialLaw(int clusterNb, materialLaw* clusterLaw);
  
     #ifndef SWIG
diff --git a/NonLinearSolver/modelReduction/Clustering.cpp b/NonLinearSolver/modelReduction/Clustering.cpp
index 112353fca632ad53643e776314f87c3c7d2f24b2..d5e2c11649097ba20fd5cc18380cb594effcf5ec 100644
--- a/NonLinearSolver/modelReduction/Clustering.cpp
+++ b/NonLinearSolver/modelReduction/Clustering.cpp
@@ -23,6 +23,7 @@
 #include "meshPartition.h"
 #include "Context.h"
 #include "GModel.h"
+#include "TFATools.h"
 
 #include <iostream>
 
@@ -68,6 +69,12 @@ std::string Clustering::ToString(const int i)
   else if (i == A_55) return "A_55";
   else if (i == A_norm) return "A_norm";
   else if (i == ClusterIndex) return "ClusterIndex";
+  else if (i == PFC_0) return "PFC_0";
+  else if (i == PFC_1) return "PFC_1";
+  else if (i == PFC_2) return "PFC_2";
+  else if (i == PFC_3) return "PFC_3";
+  else if (i == PFC_4) return "PFC_4";
+  else if (i == PFC_5) return "PFC_5";
   else 
   {
     return "undefined";
@@ -119,6 +126,20 @@ void Clustering::getAllClusterIndexes(std::vector<int>& allIndexes) const
   }
 }
 
+const fullVector<double>& Clustering::getPFC(int ele, int gp) const
+{
+  int type = numericalMaterialBase::createTypeWithTwoInts(ele,gp);
+  std::map<int, fullVector<double>>::const_iterator itF = _clusterPFC.find(type);
+  if (itF == _clusterPFC.end())
+  {
+    #ifdef _DEBUG
+    Msg::Warning("ele %d gp %d does not exist in Clustering::getPFC",ele,gp);
+    #endif //_DEBUG
+    return -1;
+  }
+  return (itF->second);
+}
+
 const fullMatrix<double>& Clustering::getStrainConcentrationTensor(int ele, int gp) const
 {
   int type = numericalMaterialBase::createTypeWithTwoInts(ele,gp);
@@ -179,20 +200,21 @@ void Clustering::clearAllClusterData()
   _clusterSTDTensorMap.clear();
 
   _clusterAveragePlasticStrainConcentrationVectorMap.clear();
-  _clusterAverageSigEPConcentrationVectorMap.clear();
+  _clusterAverageTotalStrainConcentrationVectorMap.clear();
   _clusterAveragePlasticEqStrainConcentrationVectorMap.clear();
   _clusterAverageGeometricPlasticEqStrainConcentrationVectorMap.clear();
   _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap.clear();
-  _clusterPlEqSTDVectorMap.clear();
-
-  _clusterInteractionTensorMap.clear();    
-  _clusterInteractionTensorSTDMap.clear();   
-  _clusterInteractionSTDTensorMap.clear();
+  _clusterAveragePowerPlasticEqStrainConcentrationVectorMap.clear();
+  _clusterPlSTDVectorMap.clear();
+  
+  _clusterPFC.clear();
 
+  _clusterInteractionTensorMap.clear();
   _clusterEshelbyInteractionTensorMap.clear();   
-
   _clusterInteractionTensorMatrixFrameELMap.clear();    
   _clusterInteractionTensorHomogenizedFrameELMap.clear();
+  
+  _clusterPositionMap.clear();
 }
 
 void Clustering::strainForLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const
@@ -253,6 +275,131 @@ void Clustering::strainForLoadingCases(int dim, double fact, std::map<int, STens
   }
 };
 
+void Clustering::stressForLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const
+{
+  // xx = 0, yy = 1, zz = 2, xy = yx = 3, xz = zx = 4, yz = zy = 5
+  modes.clear();
+  //double fact = 1e-4;
+  fact *= -1.;
+  if (dim == 2)
+  {
+    STensor3 sig;
+    STensorOperation::zero(sig);
+    sig(0,0) += 1.*fact;
+    modes[0] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(1,1) += 1.*fact;
+    modes[1] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(0,1) += 0.5*fact;
+    sig(1,0) += 0.5*fact;
+    modes[3] = sig;
+  }
+  else if (dim == 3)
+  {
+    STensor3 sig;
+    STensorOperation::zero(sig);
+    sig(0,0) += 1.*fact;
+    modes[0] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(1,1) += 1.*fact;
+    modes[1] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(2,2) += 1.*fact;
+    modes[2] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(0,1) += 0.5*fact;
+    sig(1,0) += 0.5*fact;
+    modes[3] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(0,2) += 0.5*fact;
+    sig(2,0) += 0.5*fact;
+    modes[4] = sig;
+    
+    STensorOperation::zero(sig);
+    sig(1,2) += 0.5*fact;
+    sig(2,1) += 0.5*fact;
+    modes[5] = sig;
+  }
+  else
+  {
+    Msg::Error("missing cases in Clustering::stressForLoadingCases");
+    Msg::Exit(0);
+  }
+};
+
+void Clustering::strainForLoadingCasesVolumePreserving(int dim, double fact, std::map<int, STensor3>& modes) const
+{
+  // xx = 0, yy = 1, zz = 2, xy = yx = 3, xz = zx = 4, yz = zy = 5
+  modes.clear();
+  //double fact = 1e-4;
+  if (dim == 2)
+  {
+    STensor3 eps;
+    STensorOperation::unity(eps);
+    eps(0,0) += 1.*fact;
+    eps(1,1) -= 1.*fact;
+    modes[0] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(1,1) += 1.*fact;
+    eps(0,0) -= 1.*fact;
+    modes[1] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(0,1) += 0.5*fact;
+    eps(1,0) += 0.5*fact;
+    modes[3] = eps;
+  }
+  else if (dim == 3)
+  {
+    STensor3 eps;
+    STensorOperation::unity(eps);
+    eps(0,0) += 1.*fact;
+    eps(1,1) -= 0.5*fact;
+    eps(2,2) -= 0.5*fact;
+    modes[0] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(1,1) += 1.*fact;
+    eps(0,0) -= 0.5*fact;
+    eps(2,2) -= 0.5*fact;
+    modes[1] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(2,2) += 1.*fact;
+    eps(0,0) -= 0.5*fact;
+    eps(1,1) -= 0.5*fact;
+    modes[2] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(0,1) += 0.5*fact;
+    eps(1,0) += 0.5*fact;
+    modes[3] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(0,2) += 0.5*fact;
+    eps(2,0) += 0.5*fact;
+    modes[4] = eps;
+    
+    STensorOperation::unity(eps);
+    eps(1,2) += 0.5*fact;
+    eps(2,1) += 0.5*fact;
+    modes[5] = eps;
+  }
+  else
+  {
+    Msg::Error("missing cases in Clustering::strainForLoadingCase");
+    Msg::Exit(0);
+  }
+};
+
 void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const
 {
   // xx = 0, yy = 1, zz = 2, xy = yx = 3, xz = zx = 4, yz = zy = 5
@@ -272,7 +419,6 @@ void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<i
     modes[1] = eps;
     
     /*double fact_mixed = fact*sqrt(2.)/sqrt(2.5);
-    
     STensorOperation::unity(eps);
     eps(0,0) += 0.5*fact_mixed;
     eps(1,1) -= 0.5*fact_mixed;
@@ -285,7 +431,16 @@ void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<i
     eps(1,1) -= 1.0*fact_mixed;
     eps(0,1) += 0.5*fact_mixed;
     eps(1,0) += 0.5*fact_mixed;
-    modes[3] = eps;*/
+    modes[3] = eps;
+    
+    double fact_mixed2 = fact/2.;
+    STensorOperation::unity(eps);
+    eps(0,0) += 1.0*fact_mixed2;
+    eps(1,1) -= 1.0*fact_mixed2;
+    eps(0,1) += 1.0*fact_mixed2;
+    eps(1,0) += 1.0*fact_mixed2;
+    modes[4] = eps;
+    */
   }
   else if (dim == 3)
   {
@@ -298,16 +453,17 @@ void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<i
     modes[0] = eps;
     
     STensorOperation::unity(eps);
-    eps(0,1) += 1.0*fact;
-    eps(1,0) += 1.0*fact;
-    modes[1] = eps;
-    
-    /*STensorOperation::unity(eps);
     eps(1,1) += 1.0*fact;
     eps(0,0) -= 0.5*fact;
     eps(2,2) -= 0.5*fact;
     modes[1] = eps;
     
+    STensorOperation::unity(eps);
+    eps(0,1) += 1.0*fact;
+    eps(1,0) += 1.0*fact;
+    modes[2] = eps;
+    
+    /*
     STensorOperation::unity(eps);
     eps(2,2) += 1.0*fact;
     eps(1,1) -= 0.5*fact;
@@ -322,7 +478,8 @@ void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<i
     STensorOperation::unity(eps);
     eps(2,1) += 1.0*fact;
     eps(1,2) += 1.0*fact;
-    modes[5] = eps;*/
+    modes[5] = eps;
+    */
 
   }
   else
@@ -332,80 +489,113 @@ void Clustering::strainForInelasticLoadingCases(int dim, double fact, std::map<i
   }
 };
 
-void Clustering::strainForInelasticLoadingCasesPath(int dim, double fact, double ftime, std::map<int, std::map<int,piecewiseScalarFunction>>& modes) const
+void Clustering::strainForInelasticLoadingCasesPath(int dim, double fact, std::map<int, std::map<int,piecewiseScalarFunction>>& modes) const
 {
   // xx = 0, yy = 1, zz = 2, xy = yx = 3, xz = zx = 4, yz = zy = 5
   modes.clear();
-  piecewiseScalarFunction fc00_0;
-  piecewiseScalarFunction fc11_0;
-  piecewiseScalarFunction fc01_0;
-    
-  piecewiseScalarFunction fc00_1;
-  piecewiseScalarFunction fc11_1;
-  piecewiseScalarFunction fc01_1;
-    
-  piecewiseScalarFunction fc00_2;
-  piecewiseScalarFunction fc11_2;
-  piecewiseScalarFunction fc01_2;
-  
-  std::map<int,piecewiseScalarFunction>& fctSet_0 = modes[0];
-  std::map<int,piecewiseScalarFunction>& fctSet_1 = modes[1];
-  std::map<int,piecewiseScalarFunction>& fctSet_2 = modes[2];
-  
-  double eps00_max = fact;
-  double eps01_max = 2.*fact/3.;
-
+  double ftime = 1.;
   if (dim == 2)
-  {   
+  { 
+    std::map<int,piecewiseScalarFunction>& fctSet_0 = modes[0];
+    piecewiseScalarFunction fc00_0;
+    piecewiseScalarFunction fc11_0;
+    piecewiseScalarFunction fc01_0;
+    
     fc00_0.put(0.,0.);
-    fc00_0.put(ftime/2.,eps00_max);
-    fc00_0.put(ftime,eps00_max);
+    fc00_0.put(ftime/2.,fact);
+    fc00_0.put(ftime,fact);
 
     fc11_0.put(0.,0.);
-    fc11_0.put(ftime/2.,-eps00_max);
-    fc11_0.put(ftime,-eps00_max);   
+    fc11_0.put(ftime/2.,-fact);   
+    fc11_0.put(ftime,-fact);
 
     fc01_0.put(0.,0.);
     fc01_0.put(ftime/2.,0.);
-    fc01_0.put(ftime,eps01_max);
+    fc01_0.put(ftime,fact);
     
     fctSet_0[0] = fc00_0;
     fctSet_0[1] = fc11_0;
-    fctSet_0[2] = fc01_0;
+    fctSet_0[2] = fc01_0; 
     
-     
-    fc00_1.put(0.,0.);
-    fc00_1.put(ftime,eps00_max);
     
-    fc11_1.put(0.,0.);
-    fc11_1.put(ftime,-eps00_max);
+    std::map<int,piecewiseScalarFunction>& fctSet_1 = modes[1];
+    piecewiseScalarFunction fc00_1;
+    piecewiseScalarFunction fc11_1;
+    piecewiseScalarFunction fc01_1;
     
+    fc00_1.put(0.,0.);
+    fc00_1.put(ftime/2.,0.);
+    fc00_1.put(ftime,fact);
+
+    fc11_1.put(0.,0.);
+    fc11_1.put(ftime/2.,0.);   
+    fc11_1.put(ftime,-fact);
+
     fc01_1.put(0.,0.);
-    fc01_1.put(ftime,0.);
+    fc01_1.put(ftime/2.,fact);
+    fc01_1.put(ftime,fact);
     
     fctSet_1[0] = fc00_1;
     fctSet_1[1] = fc11_1;
-    fctSet_1[2] = fc01_1;
+    fctSet_1[2] = fc01_1;     
+  }
+  else if (dim == 3)
+  {
+    std::map<int,piecewiseScalarFunction>& fctSet_0 = modes[0];
+    std::map<int,piecewiseScalarFunction>& fctSet_1 = modes[1];
     
-     
-    fc00_2.put(0.,0.);
-    fc00_2.put(ftime,0.);
+    piecewiseScalarFunction fc00_0;
+    piecewiseScalarFunction fc11_0;
+    piecewiseScalarFunction fc01_0;
     
-    fc11_2.put(0.,0.);
-    fc11_2.put(ftime,0.);
+    piecewiseScalarFunction fc00_1;
+    piecewiseScalarFunction fc11_1;
+    piecewiseScalarFunction fc01_1;
+  
+    fc00_0.put(0.,0.);
+    fc00_0.put(ftime/4.,fact);
+    fc00_0.put(ftime/2.,fact);
+    fc00_0.put(3.*ftime/4.,0.);
+    fc00_0.put(ftime,0.);
+
+    fc11_0.put(0.,0.);
+    fc11_0.put(ftime/4.,-fact);
+    fc11_0.put(ftime/2.,-fact);   
+    fc11_0.put(3.*ftime/4.,0.);
+    fc11_0.put(ftime,0.);
+
+    fc01_0.put(0.,0.);
+    fc01_0.put(ftime/4.,0.);
+    fc01_0.put(ftime/2.,fact);
+    fc01_0.put(3.*ftime/4.,fact);
+    fc01_0.put(ftime,0.);
     
-    fc01_2.put(0.,0.);
-    fc01_2.put(ftime,eps01_max);
+    fctSet_0[0] = fc00_0;
+    fctSet_0[1] = fc11_0;
+    fctSet_0[2] = fc01_0;
     
-    fctSet_2[0] = fc00_2;
-    fctSet_2[1] = fc11_2;
-    fctSet_2[2] = fc01_2;
     
-  }
-  else if (dim == 3)
-  {
-    Msg::Error("3D loading pathes yet to be implemented in Clustering::strainForInelasticLoadingCasesPath");
-    Msg::Exit(0);
+    fc00_1.put(0.,0.);
+    fc00_1.put(ftime/4.,-fact);
+    fc00_1.put(ftime/2.,-fact);
+    fc00_1.put(3.*ftime/4.,0.);
+    fc00_1.put(ftime,0.);
+
+    fc11_1.put(0.,0.);
+    fc11_1.put(ftime/4.,fact);
+    fc11_1.put(ftime/2.,fact);   
+    fc11_1.put(3.*ftime/4.,0.);
+    fc11_1.put(ftime,0.);
+
+    fc01_1.put(0.,0.);
+    fc01_1.put(ftime/4.,0.);
+    fc01_1.put(ftime/2.,fact);
+    fc01_1.put(3.*ftime/4.,fact);
+    fc01_1.put(ftime,0.);
+    
+    fctSet_1[0] = fc00_1;
+    fctSet_1[1] = fc11_1;
+    fctSet_1[2] = fc01_1;   
   }
   else
   {
@@ -421,7 +611,9 @@ void Clustering::setNumberOfClustersForMaterial(int matNum, int nbCluster)
   Msg::Info("material %d, number of clusters = %d",matNum,nbCluster);
 }
 
-void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool saveToFile, const std::string strainConcentrationFileName)
+void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, int homStiffnessFromLocal, 
+                                          bool saveToFile, const std::string strainConcentrationFileName, 
+                                          bool saveLocalOrientationDataToFile, const std::string localOrientationFileName)
 {
   // initialize solve if it has not
   if (!solver.isInitialized())
@@ -437,12 +629,19 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
   _materialMap.clear();
   _mapElementNumberOfGPs.clear();
   _mapGaussPoints.clear();
+  _localStiffnessTensorMap.clear();
+  _mapLocalOrientation.clear();
   
   // done
   int dim = solver.getDim();
   std::map<int, STensor3> allStrain;
   double fact_BC = 1.0e-3;
   strainForLoadingCases(dim,fact_BC,allStrain);
+  
+  STensor43 Cel_hom;
+  double Gel_hom, Kel_hom, nuel_hom;
+  double Vtot;
+  
   for (std::map<int, STensor3>::const_iterator it = allStrain.begin(); it!= allStrain.end(); it++)
   {    
     int i = it->first;
@@ -453,6 +652,7 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
     solver.getMicroBC()->setDeformationGradient(F);
       // set tangent averaging flag
     solver.tangentAveragingFlag(false);
+    
     // solve micro problem
     // set view name
     std::string filenamPrefix = "disp_strainMode"+std::to_string(i);
@@ -467,18 +667,39 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
       Msg::Error("solver cannot be solved !!!");
       Msg::Exit(0);
     }
+    
     else
     {
       // get data from IP field
       const IPField* ipf = solver.getIPField();
       const AllIPState* aips = ipf->getAips();
       const std::vector<partDomain*>& domainVector = *(solver.getDomainVector());
+      
+      STensor3 sig_hom;
+      STensorOperation::zero(sig_hom);
+      
+      Vtot = 0.;
+      
       for (int idom=0; idom < domainVector.size(); idom++)
       {
         const partDomain* dom = domainVector[idom];
         const materialLaw* matLaw = dom->getMaterialLaw();
+        
+        if (it == allStrain.begin())
+        {
+          const materialLaw* ml = matLaw->getConstNonLinearSolverMaterialLaw();        
+          STensor43 CelLoc;
+          ml->ElasticStiffness(&CelLoc);
+          CelLoc.print("CelLoc");
+          fullMatrix<double>& CelLoc_mat = _localStiffnessTensorMap[matLaw->getNum()];
+          STensorOperation::fromSTensor43ToFullMatrix(CelLoc,CelLoc_mat);
+        }
+        
         std::map<int, fullMatrix<double> >& mapGPLaw = _concentrationTensorMap[matLaw->getNum()];
         IntPt* GP;
+        double V_phase;
+        V_phase = 0.;
+        STensor3 sig_phase;
         for (elementGroup::elementContainer::const_iterator ite = dom->element_begin(); ite!= dom->element_end(); ite++)
         {
           MElement* ele = ite->second;
@@ -490,8 +711,7 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
             _mapElementNumberOfGPs[ele->getNum()] = npts;
           }
           for (int j=0; j< npts; j++)
-          {
-            
+          {  
             // data of Gauss points and element numbers are set at the first solution,
             //
             // create a unique number of element number and GP number
@@ -511,7 +731,24 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
               vec(1) =pnt.y();
               vec(2) =pnt.z();
               vec(3) =weight*detJ;
+              
+              fullVector<double>& eulerLoc = _mapLocalOrientation[type];
+              eulerLoc.resize(3);              
+              for(int eul=0; eul<3; eul++)
+              {
+                eulerLoc(eul) = 0.;
+              }              
+              fullVector<double> vecGPLocation(3);
+              vecGPLocation(0) = pnt.x();
+              vecGPLocation(1) = pnt.y();
+              vecGPLocation(2) = pnt.z();
+              const materialLaw* ml = matLaw->getConstNonLinearSolverMaterialLaw();
+              ml->getLocalOrientation(vecGPLocation,eulerLoc);
             }
+            fullVector<double> &GP = _mapGaussPoints[type];
+            double weight_local = GP(3);
+            //Vtot += weight_local;
+            V_phase += weight_local;
             
             // strain at Gauss point
             const IPVariable* ipv = (*vips)[j]->getState(IPStateBase::current);
@@ -530,6 +767,9 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
             double sigVM_local = ipv->get(IPField::SVM);
             static STensor3 sig_local;
             ipvfinite->getCauchyStress(sig_local);
+            
+            //sig_hom += weight_local*sig_local;
+            sig_phase += weight_local*sig_local;
 
             // save to map
             if (mapGPLaw.find(type) == mapGPLaw.end())
@@ -568,96 +808,373 @@ void Clustering::solveStrainConcentration(nonLinearMechSolver& solver, bool save
             }
           }
         }
+        sig_phase *= (1./V_phase);
+        //sig_phase.print("STRESS PHASE");
+        //printf("Vphase %.16g \n", V_phase);
+        sig_hom += sig_phase*V_phase;
+        Vtot += V_phase;
+      }
+      //printf("Vtot %.16g \n", Vtot);
+      sig_hom *= (1./Vtot); 
+      if(homStiffnessFromLocal==1)
+      {  
+        if(i==0)
+        {
+          Cel_hom(0,0,0,0) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,0,0) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,0,0) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,0,0) = Cel_hom(1,0,0,0) = sig_hom(0,1)/fact_BC;
+          Cel_hom(0,2,0,0) = Cel_hom(2,0,0,0) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,0,0) = Cel_hom(1,2,0,0) = sig_hom(2,1)/fact_BC;
+        }
+        if(i==1)
+        {
+          Cel_hom(0,0,1,1) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,1,1) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,1,1) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,1,1) = Cel_hom(1,0,1,1) = sig_hom(0,1)/fact_BC;
+          Cel_hom(0,2,1,1) = Cel_hom(2,0,1,1) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,1,1) = Cel_hom(1,2,1,1) = sig_hom(2,1)/fact_BC;
+        }
+        if(i==2)
+        {
+          Cel_hom(0,0,2,2) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,2,2) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,2,2) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,2,2) = Cel_hom(1,0,2,2) = sig_hom(0,1)/fact_BC;
+          Cel_hom(0,2,2,2) = Cel_hom(2,0,2,2) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,2,2) = Cel_hom(1,2,2,2) = sig_hom(2,1)/fact_BC;
+        }
+        if(i==3)
+        {
+          Cel_hom(0,0,0,1) = Cel_hom(0,0,1,0) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,0,1) = Cel_hom(1,1,1,0) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,0,1) = Cel_hom(2,2,1,0) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,0,1) = Cel_hom(1,0,0,1) = Cel_hom(0,1,1,0) = Cel_hom(1,0,1,0) = sig_hom(0,1)/fact_BC; 
+          Cel_hom(0,2,0,1) = Cel_hom(2,0,0,1) = Cel_hom(0,2,1,0) = Cel_hom(2,0,1,0) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,0,1) = Cel_hom(1,2,0,1) = Cel_hom(2,1,1,0) = Cel_hom(1,2,1,0) = sig_hom(2,1)/fact_BC;
+        }
+        if(i==4)
+        {
+          Cel_hom(0,0,0,2) = Cel_hom(0,0,2,0) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,0,2) = Cel_hom(1,1,2,0) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,0,2) = Cel_hom(2,2,2,0) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,0,2) = Cel_hom(1,0,0,2) = Cel_hom(0,1,2,0) = Cel_hom(1,0,2,0) = sig_hom(0,1)/fact_BC;
+          Cel_hom(0,2,0,2) = Cel_hom(2,0,0,2) = Cel_hom(0,2,2,0) = Cel_hom(2,0,2,0) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,0,2) = Cel_hom(1,2,0,2) = Cel_hom(2,1,2,0) = Cel_hom(1,2,2,0) = sig_hom(2,1)/fact_BC;
+        }
+        if(i==5)
+        {
+          Cel_hom(0,0,1,2) = Cel_hom(0,0,2,1) = sig_hom(0,0)/fact_BC;
+          Cel_hom(1,1,1,2) = Cel_hom(1,1,2,1) = sig_hom(1,1)/fact_BC;
+          Cel_hom(2,2,1,2) = Cel_hom(2,2,2,1) = sig_hom(2,2)/fact_BC;
+          Cel_hom(0,1,1,2) = Cel_hom(1,0,1,2) = Cel_hom(0,1,2,1) = Cel_hom(1,0,2,1) = sig_hom(0,1)/fact_BC;
+          Cel_hom(0,2,1,2) = Cel_hom(2,0,1,2) = Cel_hom(0,2,2,1) = Cel_hom(2,0,2,1) = sig_hom(0,2)/fact_BC;
+          Cel_hom(2,1,1,2) = Cel_hom(1,2,1,2) = Cel_hom(2,1,2,1) = Cel_hom(1,2,2,1) = sig_hom(2,1)/fact_BC;
+        }  
       }
+    
       // next step
       // save view
       solver.archiveData(i+1.,i+1,false);
-      solver.nextStep(i+1.,i+1);
+      solver.nextStep(i+1.,i+1);     
     }
   }
   Msg::Info("done estimating concentration tensors");
-  if (saveToFile)
-  {
-    printf("start writing strain concentration tensor to file\n");
-    FILE* f = fopen(strainConcentrationFileName.c_str(),"w");
-    std::string str ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
-    for (int i=0; i<6; i++)
-    {
-      for (int j=0; j<6; j++)
-      {
-        str += " A_"+std::to_string(i)+std::to_string(j);
-      }
-    }
-    fprintf(f,"%s\n",str.c_str());
-    // write data
+  
+  if(homStiffnessFromLocal==0)
+  { 
+    fullMatrix<double> Cel_hom_mat(6,6);
+    Vtot = 0.;
     for (std::map<int, std::map<int, fullMatrix<double> > >::const_iterator it = _concentrationTensorMap.begin();  it!= _concentrationTensorMap.end(); it++)
     { 
       int matNum = it->first;
+      const fullMatrix<double>& Cel_phase = _localStiffnessTensorMap[matNum];
+      //Cel_phase.print("Cel_phase");
+      fullMatrix<double> A_phase(6,6);
+      double V_phase;
+      V_phase = 0.;
       const std::map<int, fullMatrix<double> >& mapIPLaw = it->second;
       for (std::map<int, fullMatrix<double> >::const_iterator itIPMap = mapIPLaw.begin(); itIPMap!=mapIPLaw.end(); itIPMap++)
       {
         int type = itIPMap->first;
+        fullVector<double> &GP = _mapGaussPoints[type];
+        double weight_local = GP(3);
         const fullMatrix<double>& mat = itIPMap->second;
-        int ele, gp;
-        numericalMaterialBase::getTwoIntsFromType(type,ele,gp);
-        fprintf(f,"%d %d %d",ele,gp,matNum);
-        fullVector<double>& pw = _mapGaussPoints[type];
-        fprintf(f," %.16g %.16g %.16g %.16g",pw(0),pw(1),pw(2),pw(3));
-        for (int i=0; i<6; i++)
-        {
-          for (int j=0; j<6; j++)
-          {
-            fprintf(f, " %.16g",mat(i,j));
-          }
-        }
-        fprintf(f, "\n");
-      }
-    }
-    fclose(f);
-    printf("done writing strain concentration tensor to file\n");
-  }
-};
-
-void Clustering::loadStrainConcentrationDataFromFile(const std::string fileName)
-{
-  clearAllClusterData();
-  _concentrationTensorMap.clear();
-  _directMapOfStrainConcentration.clear();
-  _materialMap.clear();
-  _mapElementNumberOfGPs.clear();
-  _mapGaussPoints.clear();
+        A_phase.add(mat,weight_local);
+        V_phase += weight_local;
+      }
+      A_phase.scale(1./V_phase);
+      //A_phase.print("A_phase");
+      //printf("Vp %.16g",V_phase);
+      fullMatrix<double> Cel_hom_mat_summand(6,6);
+      Cel_phase.mult(A_phase,Cel_hom_mat_summand);
+      Cel_hom_mat.add(Cel_hom_mat_summand,V_phase);
+      Vtot += V_phase;
+    }
+    Cel_hom_mat.scale(1./Vtot);
+    Cel_hom_mat.print("Cel_hom_mat");
   
-  FILE* fp = fopen(fileName.c_str(),"r");
-  if (fp !=NULL) {
-    printf("start reading file: %s\n",fileName.c_str());
-    if(!feof(fp))
+    /*int phase = 0;
+    fullMatrix<double> Cel_phase0_mat(6,6), Cel_phase1_mat(6,6), Cel_phase2_mat(6,6);
+    STensor43 Cel_phase0, Cel_phase1, Cel_phase2;
+    for (std::map<int, std::map<int, fullMatrix<double> > >::const_iterator it = _concentrationTensorMap.begin();  it!= _concentrationTensorMap.end(); it++)
     {
-      char what[256];
-      int ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      ok = fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      for (int i=0; i<6; i++)
+      int matNum = it->first;
+      if(phase==0)
       {
-        for (int j=0; j<6; j++)
-        {
-          ok = fscanf(fp, "%s", what);
-          printf("what = %s\n",what);
-        }
+        const fullMatrix<double>& Cel_phase0_mat = _localStiffnessTensorMap[matNum];
+        STensorOperation::fromFullMatrixToSTensor43(Cel_phase0_mat,Cel_phase0);
       }
-      if(strcmp(what, "A_55"))
+      else if(phase==1)
       {
-        Msg::Error("file format is not correct\n");
+        const fullMatrix<double>& Cel_phase1_mat = _localStiffnessTensorMap[matNum];
+        STensorOperation::fromFullMatrixToSTensor43(Cel_phase1_mat,Cel_phase1);
+      }
+      else if(phase==2)
+      {
+        const fullMatrix<double>& Cel_phase2_mat = _localStiffnessTensorMap[matNum];
+        STensorOperation::fromFullMatrixToSTensor43(Cel_phase2_mat,Cel_phase2);
+      }
+      phase += 1;
+    }  
+    Cel_hom_mat = Cel_phase0_mat;*/
+  
+    STensorOperation::fromFullMatrixToSTensor43(Cel_hom_mat,Cel_hom);
+  }
+  
+  
+  Cel_hom.print("CEL");
+  
+  STensor43 Cel_hom_iso, Cel_hom_iso_muFix;
+  STensorOperation::STensor43Isotropization(Cel_hom,Cel_hom_iso);
+
+  Gel_hom = Cel_hom_iso(0,1,0,1);
+  Kel_hom = Cel_hom_iso(0,0,0,0) - 4./3.*Gel_hom;
+  nuel_hom = (3.*Kel_hom - 2.*Gel_hom)/(2.*(3.*Kel_hom + Gel_hom));
+  printf("isotropic elastic props G: %g, K: %g, nu: %g \n", Gel_hom, Kel_hom, nuel_hom);  
+    
+  Cel_hom_iso_muFix(0,0,0,0) = Cel_hom_iso_muFix(1,1,1,1) = Cel_hom_iso_muFix(2,2,2,2) = (1.-nuel_hom)/(1.-2.*nuel_hom);
+  Cel_hom_iso_muFix(0,0,1,1) = Cel_hom_iso_muFix(1,1,0,0) = Cel_hom_iso_muFix(0,0,2,2) = Cel_hom_iso_muFix(2,2,0,0) = Cel_hom_iso_muFix(2,2,1,1) = Cel_hom_iso_muFix(1,1,2,2) 
+                             = nuel_hom/(1.-2.*nuel_hom);
+  Cel_hom_iso_muFix(0,1,0,1) = Cel_hom_iso_muFix(0,1,1,0) = Cel_hom_iso_muFix(1,0,1,0) = Cel_hom_iso_muFix(1,0,0,1) 
+                             = Cel_hom_iso_muFix(0,2,0,2) = Cel_hom_iso_muFix(0,2,2,0) = Cel_hom_iso_muFix(2,0,2,0) = Cel_hom_iso_muFix(2,0,0,2) 
+                             = Cel_hom_iso_muFix(1,2,1,2) = Cel_hom_iso_muFix(1,2,2,1) = Cel_hom_iso_muFix(2,1,1,2) = Cel_hom_iso_muFix(2,1,2,1) 
+                             = 1./2.;
+  Cel_hom_iso_muFix *= 2.*Gel_hom;
+  
+  fullMatrix<double> Cel_hom_mat(6,6), Cel_hom_iso_mat(6,6), Cel_hom_iso_muFix_mat(6,6);
+  STensorOperation::fromSTensor43ToFullMatrix(Cel_hom,Cel_hom_mat);
+  STensorOperation::fromSTensor43ToFullMatrix(Cel_hom_iso,Cel_hom_iso_mat);
+  STensorOperation::fromSTensor43ToFullMatrix(Cel_hom_iso_muFix,Cel_hom_iso_muFix_mat);
+  
+  Cel_hom_iso.print("CEL_ISO");
+  Cel_hom_iso_muFix.print("CEL_ISO_muFix");
+  
+  printf("start writing elastic stiffness tensor to file\n");
+  std::string CelFileName = "ElasticStiffnessHom.csv";
+  FILE* fCel = fopen(CelFileName.c_str(),"w");
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      std::string strCij = "C_el_"+std::to_string(i)+std::to_string(j);
+      if(i==5 and j==5)
+      {
+        fprintf(fCel, "%s\n",strCij.c_str());
+      }
+      else
+      {      
+        fprintf(fCel, "%s ",strCij.c_str());
+      }
+    }
+  }
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      if(i==5 and j==5)
+      {
+      fprintf(fCel, "%.16g\n",Cel_hom_mat(i,j));
+      }
+      else{
+      fprintf(fCel, "%.16g ",Cel_hom_mat(i,j));
+      }
+    }
+  }
+  fclose(fCel);
+  printf("done writing elastic stiffness tensor to file\n");
+  
+  printf("start writing isotropic elastic stiffness tensor to file\n");
+  std::string CelIsoFileName = "ElasticStiffnessHomIso.csv";
+  FILE* fCelIso = fopen(CelIsoFileName.c_str(),"w");
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      std::string strCij = "C_el_"+std::to_string(i)+std::to_string(j);
+      if(i==5 and j==5)
+      {
+        fprintf(fCelIso, "%s\n",strCij.c_str());
+      }
+      else
+      {      
+        fprintf(fCelIso, "%s ",strCij.c_str());
+      }
+    }
+  }
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      if(i==5 and j==5)
+      {
+      fprintf(fCelIso, "%.16g\n",Cel_hom_iso_mat(i,j));
+      }
+      else{
+      fprintf(fCelIso, "%.16g ",Cel_hom_iso_mat(i,j));
+      }
+    }
+  }
+  fclose(fCelIso);
+  printf("done writing isotropic elastic stiffness tensor to file\n");
+  
+  printf("start writing isotropic elastic stiffness tensor with G fix to file\n");
+  std::string CelIsoMuFixFileName = "ElasticStiffnessHomIso_muFix.csv";
+  FILE* fCelIsoMuFix = fopen(CelIsoMuFixFileName.c_str(),"w");
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      std::string strCij = "C_el_"+std::to_string(i)+std::to_string(j);
+      if(i==5 and j==5)
+      {
+        fprintf(fCelIsoMuFix, "%s\n",strCij.c_str());
+      }
+      else
+      {      
+        fprintf(fCelIsoMuFix, "%s ",strCij.c_str());
+      }
+    }
+  }
+  for (int i=0; i<6; i++)
+  {
+    for (int j=0; j<6; j++)
+    {
+      if(i==5 and j==5)
+      {
+      fprintf(fCelIsoMuFix, "%.16g\n",Cel_hom_iso_muFix_mat(i,j));
+      }
+      else{
+      fprintf(fCelIsoMuFix, "%.16g ",Cel_hom_iso_muFix_mat(i,j));
+      }
+    }
+  }
+  fclose(fCelIsoMuFix);
+  printf("done writing isotropic elastic stiffness tensor with G fix to file\n");
+  
+  if (saveToFile)
+  {
+    printf("start writing strain concentration tensor to file\n");
+    FILE* f = fopen(strainConcentrationFileName.c_str(),"w");
+    std::string str ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
+    for (int i=0; i<6; i++)
+    {
+      for (int j=0; j<6; j++)
+      {
+        str += " A_"+std::to_string(i)+std::to_string(j);
+      }
+    }
+    fprintf(f,"%s\n",str.c_str());
+    // write data
+    for (std::map<int, std::map<int, fullMatrix<double> > >::const_iterator it = _concentrationTensorMap.begin();  it!= _concentrationTensorMap.end(); it++)
+    { 
+      int matNum = it->first;
+      const std::map<int, fullMatrix<double> >& mapIPLaw = it->second;
+      for (std::map<int, fullMatrix<double> >::const_iterator itIPMap = mapIPLaw.begin(); itIPMap!=mapIPLaw.end(); itIPMap++)
+      {
+        int type = itIPMap->first;
+        const fullMatrix<double>& mat = itIPMap->second;
+        int ele, gp;
+        numericalMaterialBase::getTwoIntsFromType(type,ele,gp);
+        fprintf(f,"%d %d %d",ele,gp,matNum);
+        fullVector<double>& pw = _mapGaussPoints[type];
+        fprintf(f," %.16g %.16g %.16g %.16g",pw(0),pw(1),pw(2),pw(3));
+        for (int i=0; i<6; i++)
+        {
+          for (int j=0; j<6; j++)
+          {
+            fprintf(f, " %.16g",mat(i,j));
+          }
+        }
+        fprintf(f, "\n");
+      }
+    }
+    fclose(f);
+    printf("done writing strain concentration tensor to file\n");
+  }
+  if (saveLocalOrientationDataToFile)
+  {
+    printf("start writing local orientation to file\n");
+    FILE* f = fopen(localOrientationFileName.c_str(),"w");
+    std::string str ="ELE_NUM GP_NUM MAT_NUM E1 E2 E3";
+    fprintf(f,"%s\n",str.c_str());
+    
+    for (std::map<int, fullVector<double> >::const_iterator itOriMap = _mapLocalOrientation.begin(); itOriMap!=_mapLocalOrientation.end(); itOriMap++)
+    {
+      int type = itOriMap->first;
+      int ele, gp;
+      numericalMaterialBase::getTwoIntsFromType(type,ele,gp);
+      int& matNum = _materialMap[type];    
+      const fullVector<double>& eulerLoc = itOriMap->second;  
+      fprintf(f,"%d %d %d %.16g %.16g %.16g",ele,gp,matNum,eulerLoc(0),eulerLoc(1),eulerLoc(2));
+      fprintf(f, "\n");
+    }
+    fclose(f);
+    printf("done writing local orientation to file\n");
+  }
+};
+
+void Clustering::loadStrainConcentrationDataFromFile(const std::string fileName)
+{
+  clearAllClusterData();
+  _concentrationTensorMap.clear();
+  _directMapOfStrainConcentration.clear();
+  _materialMap.clear();
+  _mapElementNumberOfGPs.clear();
+  _mapGaussPoints.clear();
+  
+  FILE* fp = fopen(fileName.c_str(),"r");
+  if (fp !=NULL) {
+    printf("start reading file: %s\n",fileName.c_str());
+    if(!feof(fp))
+    {
+      char what[256];
+      int ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      for (int i=0; i<6; i++)
+      {
+        for (int j=0; j<6; j++)
+        {
+          ok = fscanf(fp, "%s", what);
+          printf("what = %s\n",what);
+        }
+      }
+      if(strcmp(what, "A_55"))
+      {
+        Msg::Error("file format is not correct\n");
         Msg::Exit(0);
       }
     }
@@ -710,10 +1227,78 @@ void Clustering::loadStrainConcentrationDataFromFile(const std::string fileName)
 }
 
 
+
+
+void Clustering::loadLocalOrientationDataFromFile(const std::string fileNameLocalOrientationData)
+{
+  clearAllClusterData();
+  _mapLocalOrientation.clear();
+  
+  FILE* fp = fopen(fileNameLocalOrientationData.c_str(),"r");
+  if (fp !=NULL) {
+    printf("start reading file: %s\n",fileNameLocalOrientationData.c_str());
+    if(!feof(fp))
+    {
+      char what[256];
+      int ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      for (int i=0; i<3; i++)
+      {
+        ok = fscanf(fp, "%s", what);
+        printf("what = %s\n",what);
+      }
+      if(strcmp(what, "E3"))
+      {
+        Msg::Error("file format is not correct\n");
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(fp))
+        break;
+      int ele, gp, matNum;
+      int type = 0;
+      if (fscanf(fp, "%d %d %d", &ele,&gp,&matNum)==3)
+      {
+        type = numericalMaterialBase::createTypeWithTwoInts(ele,gp);
+      }
+      static fullVector<double> vec(3);
+      for (int i=0; i<3; i++)
+      {
+        double val=0;
+        if (fscanf(fp,"%lf",&val)==1)
+          vec(i) = val;
+      }
+      if (type >0 && matNum > 0)
+      {
+        fullVector<double>& mapLocOri = _mapLocalOrientation[type];
+        mapLocOri = vec;
+      }
+    }
+    printf("done reading file: %s\n",fileNameLocalOrientationData.c_str());
+    fclose(fp);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileNameLocalOrientationData.c_str());
+    Msg::Exit(0);
+  }
+}
+
+
+
+
+
+
 void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverInelastic1, bool saveToFile,
                                                    const std::string PlasticStrainConcentrationFileName,
-                                                   const std::string SigEPConcentrationFileName,
-                                                   const std::string PlasticEqstrainConcentrationFileName)
+                                                   const std::string InelasticStrainConcentrationFileName,
+                                                   const std::string TotalStrainConcentrationFileName,
+                                                   const std::string PlasticEqStrainConcentrationFileName)
 { 
   clearAllClusterData();
   
@@ -721,14 +1306,14 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
   _directMapOfPlasticStrainConcentration.clear();
   _plasticStrainConcentrationVectorMap.clear();
   
-  _directMapOfSigEPConcentration.clear();
-  _sigEPConcentrationVectorMap.clear();
+  _directMapOfInelasticStrainConcentration.clear();
+  _inelasticStrainConcentrationVectorMap.clear();
+  
+  _directMapOfTotalStrainConcentration.clear();
+  _totalStrainConcentrationVectorMap.clear();
   
   _directMapOfPlasticEqStrainConcentration.clear();
   _plasticEqStrainConcentrationVectorMap.clear();
-
-  _plasticEnergyVectorMap.clear();
-  _directMapOfPlasticEnergy.clear();
   
   _SVMPlasticVectorMap.clear();
   _directMapOfSVMPlastic.clear();
@@ -744,10 +1329,9 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
   int dim = solverInelastic1.getDim();
   std::map<int, STensor3> allStrain;
   //std::map<int, std::map<int,piecewiseScalarFunction>> allStrain;
-  double fact_BC = 2.0e-2;
-  double ftime = 1.;
+  double fact_BC = 3.e-2;
   strainForInelasticLoadingCases(dim,fact_BC,allStrain);
-  //strainForInelasticLoadingCasesPath(dim,fact_BC,ftime,allStrain);
+  //strainForInelasticLoadingCasesPath(dim,fact_BC,allStrain);
   int numberCases = allStrain.size();
   for (std::map<int, STensor3>::const_iterator it = allStrain.begin(); it!= allStrain.end(); it++)
   //for (std::map<int, std::map<int,piecewiseScalarFunction>>::const_iterator it = allStrain.begin(); it!= allStrain.end(); it++)
@@ -757,18 +1341,12 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
     nonLinearMechSolver* solverInelastic = solverInelastic1.clone(solverInelastic1.getMeshFileName(),solverInelastic1.getTag());
     // specify all output file with mode index, i, for example, the files E_i_0_* will be generated
     
-    int nstep = 50;
-    double tol = 1.e-6;
-    solverInelastic->snlData(nstep,ftime,tol);
-    solverInelastic->stepBetweenArchiving(int(nstep/10));
     solverInelastic->setControlType(0);
     solverInelastic->stiffnessModification(true);
     solverInelastic->iterativeProcedure(true);
     solverInelastic->setMessageView(true);
     solverInelastic->setMicroProblemIndentification(i+1,0);
     
-    //solverInelastic->setSystemType(1);
-    
     // prescribe homogenized strain
     const STensor3& F = it->second;
     solverInelastic->getMicroBC()->setDeformationGradient(F);
@@ -805,10 +1383,16 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
       const partDomain* dom = domainVector[idom];
       const materialLaw* matLaw = dom->getMaterialLaw();
       std::map<int, fullVector<double> >& mapGPPlasticStrainLaw = _plasticStrainConcentrationVectorMap[matLaw->getNum()];
-      std::map<int, fullVector<double> >& mapGPSigEPLaw = _sigEPConcentrationVectorMap[matLaw->getNum()];
+      std::map<int, fullVector<double> >& mapGPInelasticStrainLaw = _inelasticStrainConcentrationVectorMap[matLaw->getNum()];
+      std::map<int, fullVector<double> >& mapGPTotalStrainLaw = _totalStrainConcentrationVectorMap[matLaw->getNum()];
       std::map<int, fullVector<double> >& mapGPPlasticEqStrainLaw = _plasticEqStrainConcentrationVectorMap[matLaw->getNum()];
-
       IntPt* GP;
+      
+      const materialLaw* ml = matLaw->getConstNonLinearSolverMaterialLaw();        
+      STensor43 CelLoc, SelLoc;
+      ml->ElasticStiffness(&CelLoc);
+      STensorOperation::inverseSTensor43(CelLoc,SelLoc);
+      
       for (elementGroup::elementContainer::const_iterator ite = dom->element_begin(); ite!= dom->element_end(); ite++)
       {
         MElement* ele = ite->second;
@@ -867,52 +1451,61 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
           plasticStrain_local(0,2) = ipv->get(IPField::FP_XZ);
           plasticStrain_local(1,2) = ipv->get(IPField::FP_YZ);
           
-          STensor3 sig_local;
-          sig_local(0,0) = ipv->get(IPField::SIG_XX);
-          sig_local(1,1) = ipv->get(IPField::SIG_YY);
-          sig_local(2,2) = ipv->get(IPField::SIG_ZZ);
-          sig_local(0,1) = ipv->get(IPField::SIG_XY);
-          sig_local(0,2) = ipv->get(IPField::SIG_XZ);
-          sig_local(1,2) = ipv->get(IPField::SIG_YZ);
+          STensor3 eigenstrain_local;
+          eigenstrain_local(0,0) = ipv->get(IPField::EIGENSTRAIN_XX);
+          eigenstrain_local(1,1) = ipv->get(IPField::EIGENSTRAIN_YY);
+          eigenstrain_local(2,2) = ipv->get(IPField::EIGENSTRAIN_ZZ);
+          eigenstrain_local(0,1) = ipv->get(IPField::EIGENSTRAIN_XY);
+          eigenstrain_local(0,2) = ipv->get(IPField::EIGENSTRAIN_XZ);
+          eigenstrain_local(1,2) = ipv->get(IPField::EIGENSTRAIN_YZ);
 
           double plasticEqStrain_local = ipv->get(IPField::PLASTICSTRAIN);
-          double plasticEnergy_local = ipvf->plasticEnergy();
-          double strain_eq_local = ipv->get(IPField::GL_EQUIVALENT_STRAIN);
           double stress_eq_local = ipv->get(IPField::SVM);
           double eigenstress_eq_local = ipv->get(IPField::EQUIVALENT_EIGENSTRESS);
-
+          
           // save to map
           if (mapGPPlasticEqStrainLaw.find(type) == mapGPPlasticEqStrainLaw.end())
           {
             // resize if it not exist before 
             fullVector<double>& veclocPlasticStrain = mapGPPlasticStrainLaw[type];
-            veclocPlasticStrain.resize(12,true);
+            veclocPlasticStrain.resize(36,true);
             _directMapOfPlasticStrainConcentration[type] = &veclocPlasticStrain;
             
-            fullVector<double>& veclocSigEP = mapGPSigEPLaw[type];
-            veclocSigEP.resize(12,true);
-            _directMapOfSigEPConcentration[type] = &veclocSigEP;
+            fullVector<double>& veclocInelasticStrain = mapGPInelasticStrainLaw[type];
+            veclocInelasticStrain.resize(36,true);
+            _directMapOfInelasticStrainConcentration[type] = &veclocInelasticStrain;
+            
+            fullVector<double>& veclocTotalStrain = mapGPTotalStrainLaw[type];
+            veclocTotalStrain.resize(36,true);
+            _directMapOfTotalStrainConcentration[type] = &veclocTotalStrain;
             
             fullVector<double>& veclocPlasticEqStrain = mapGPPlasticEqStrainLaw[type];
             veclocPlasticEqStrain.resize(6,true);
             _directMapOfPlasticEqStrainConcentration[type] = &veclocPlasticEqStrain;
           }
-          
           fullVector<double>& veclocPlasticStrain = mapGPPlasticStrainLaw[type];
           veclocPlasticStrain(i*6+0)  = plasticStrain_local(0,0); // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
           veclocPlasticStrain(i*6+1)  = plasticStrain_local(1,1); // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
           veclocPlasticStrain(i*6+2)  = plasticStrain_local(0,1); // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
           veclocPlasticStrain(i*6+3)  = plasticStrain_local(2,2); // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
           veclocPlasticStrain(i*6+4)  = plasticStrain_local(0,2); // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocPlasticStrain(i*6+5)  = plasticStrain_local(1,2); // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)     
+          veclocPlasticStrain(i*6+5)  = plasticStrain_local(1,2); // A(12)(00 if i==0, 11 if i==1, 22 if i ==2) 
+          
+          fullVector<double>& veclocInelasticStrain = mapGPInelasticStrainLaw[type];
+          veclocInelasticStrain(i*6+0)  = eigenstrain_local(0,0); // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocInelasticStrain(i*6+1)  = eigenstrain_local(1,1); // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocInelasticStrain(i*6+2)  = eigenstrain_local(0,1); // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocInelasticStrain(i*6+3)  = eigenstrain_local(2,2); // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocInelasticStrain(i*6+4)  = eigenstrain_local(0,2); // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocInelasticStrain(i*6+5)  = eigenstrain_local(1,2); // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)     
           
-          fullVector<double>& veclocSigEP = mapGPSigEPLaw[type];
-          veclocSigEP(i*6+0)  = sig_local(0,0); // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocSigEP(i*6+1)  = sig_local(1,1); // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocSigEP(i*6+2)  = sig_local(0,1); // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocSigEP(i*6+3)  = sig_local(2,2); // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocSigEP(i*6+4)  = sig_local(0,2); // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
-          veclocSigEP(i*6+5)  = sig_local(1,2); // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)
+          fullVector<double>& veclocTotalStrain = mapGPTotalStrainLaw[type];
+          veclocTotalStrain(i*6+0)  = eps(0,0); // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocTotalStrain(i*6+1)  = eps(1,1); // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocTotalStrain(i*6+2)  = eps(0,1); // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocTotalStrain(i*6+3)  = eps(2,2); // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocTotalStrain(i*6+4)  = eps(0,2); // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
+          veclocTotalStrain(i*6+5)  = eps(1,2); // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)
   
           fullVector<double>& veclocPlasticEqStrain = mapGPPlasticEqStrainLaw[type];
           veclocPlasticEqStrain(i) = plasticEqStrain_local;
@@ -928,7 +1521,7 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
     printf("start writing plastic strain concentration tensor to file\n");
     FILE* f = fopen(PlasticStrainConcentrationFileName.c_str(),"w");
     std::string str ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
-    for (int i=0; i<12; i++)
+    for (int i=0; i<36; i++)
     {
         str += " A_pl_"+std::to_string(i);
     }
@@ -947,7 +1540,7 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
         fprintf(f,"%d %d %d",ele,gp,matNum);
         fullVector<double>& pw = _mapGaussPoints[type];
         fprintf(f," %.16g %.16g %.16g %.16g",pw(0),pw(1),pw(2),pw(3));
-        for (int i=0; i<12; i++)
+        for (int i=0; i<36; i++)
         {
           fprintf(f, " %.16g",vec(i));
         }
@@ -957,16 +1550,16 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
     fclose(f);
     printf("done writing plastic strain concentration tensor to file\n");  
   
-    printf("start writing stress concentration tensor to file\n");
-    FILE* f2 = fopen(SigEPConcentrationFileName.c_str(),"w");
+    printf("start writing total strain concentration tensor to file\n");
+    FILE* f2 = fopen(TotalStrainConcentrationFileName.c_str(),"w");
     std::string str2 ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
-    for (int i=0; i<12; i++)
+    for (int i=0; i<36; i++)
     {
-        str2 += " B_pl_"+std::to_string(i);
+        str2 += " A_tot_"+std::to_string(i);
     }
     fprintf(f2,"%s\n",str2.c_str());
     // write data
-    for (std::map<int, std::map<int, fullVector<double> > >::const_iterator it = _sigEPConcentrationVectorMap.begin();  it!= _sigEPConcentrationVectorMap.end(); it++)
+    for (std::map<int, std::map<int, fullVector<double> > >::const_iterator it = _totalStrainConcentrationVectorMap.begin();  it!= _totalStrainConcentrationVectorMap.end(); it++)
     { 
       int matNum = it->first;
       const std::map<int, fullVector<double> >& mapIPLaw = it->second;
@@ -979,7 +1572,7 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
         fprintf(f2,"%d %d %d",ele,gp,matNum);
         fullVector<double>& pw = _mapGaussPoints[type];
         fprintf(f2," %.16g %.16g %.16g %.16g",pw(0),pw(1),pw(2),pw(3));
-        for (int i=0; i<12; i++)
+        for (int i=0; i<36; i++)
         {
           fprintf(f2, " %.16g",vec(i));
         }
@@ -987,10 +1580,42 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
       }
     }
     fclose(f2);
-    printf("done writing stress concentration tensor to file\n");  
+    printf("done writing total strain concentration tensor to file\n");  
+    
+    printf("start writing eigenstrain concentration tensor to file\n");
+    FILE* f3 = fopen(InelasticStrainConcentrationFileName.c_str(),"w");
+    std::string str3 ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
+    for (int i=0; i<36; i++)
+    {
+        str3 += " A_in_"+std::to_string(i);
+    }
+    fprintf(f3,"%s\n",str3.c_str());
+    // write data
+    for (std::map<int, std::map<int, fullVector<double> > >::const_iterator it = _inelasticStrainConcentrationVectorMap.begin();  it!= _inelasticStrainConcentrationVectorMap.end(); it++)
+    { 
+      int matNum = it->first;
+      const std::map<int, fullVector<double> >& mapIPLaw = it->second;
+      for (std::map<int, fullVector<double> >::const_iterator itIPMap = mapIPLaw.begin(); itIPMap!=mapIPLaw.end(); itIPMap++)
+      {
+        int type = itIPMap->first;
+        const fullVector<double>& vec = itIPMap->second;
+        int ele, gp;
+        numericalMaterialBase::getTwoIntsFromType(type,ele,gp);
+        fprintf(f3,"%d %d %d",ele,gp,matNum);
+        fullVector<double>& pw = _mapGaussPoints[type];
+        fprintf(f3," %.16g %.16g %.16g %.16g",pw(0),pw(1),pw(2),pw(3));
+        for (int i=0; i<36; i++)
+        {
+          fprintf(f3, " %.16g",vec(i));
+        }
+        fprintf(f3, "\n");
+      }
+    }
+    fclose(f3);
+    printf("done writing eigenstrain concentration tensor to file\n");  
   
     printf("start writing plastic eq. strain concentration to file\n");
-    FILE* fpl = fopen(PlasticEqstrainConcentrationFileName.c_str(),"w");
+    FILE* fpl = fopen(PlasticEqStrainConcentrationFileName.c_str(),"w");
     std::string strpl ="ELE_NUM GP_NUM MAT_NUM X Y Z VOLUME";
     for (int i=0; i<6; i++)
     {
@@ -1019,9 +1644,7 @@ void Clustering::solveStrainConcentrationInelastic(nonLinearMechSolver& solverIn
       }
     }
     fclose(fpl);
-    printf("done writing plastic eq. strain concentration to file\n");
-    
-
+    printf("done writing plastic eq. strain concentration to file\n");    
   }
 };
 
@@ -1052,12 +1675,12 @@ void Clustering::loadPlasticStrainConcentrationDataFromFile(const std::string fi
       printf("what = %s\n",what);
       ok = fscanf(fpPlastic, "%s", what);
       printf("what = %s\n",what);
-      for (int i=0; i<12; i++)
+      for (int i=0; i<36; i++)
       {
         ok = fscanf(fpPlastic, "%s", what);
         printf("what = %s\n",what);
       }
-      if(strcmp(what, "A_pl_11"))
+      if(strcmp(what, "A_pl_35"))
       {
         Msg::Error("file format is not correct\n");
         Msg::Exit(0);
@@ -1075,8 +1698,8 @@ void Clustering::loadPlasticStrainConcentrationDataFromFile(const std::string fi
       fullVector<double> val;
       val.resize(4);
       int ok = fscanf(fpPlastic, "%lf %lf %lf %lf", &(val.getDataPtr()[0]),&(val.getDataPtr()[1]),&(val.getDataPtr()[2]),&(val.getDataPtr()[3]));
-      static fullVector<double> vec(12);
-      for (int i=0; i<12; i++)
+      static fullVector<double> vec(36);
+      for (int i=0; i<36; i++)
       {
         double val=0;
         if (fscanf(fpPlastic,"%lf",&val)==1)
@@ -1099,15 +1722,15 @@ void Clustering::loadPlasticStrainConcentrationDataFromFile(const std::string fi
   }
 }
 
-void Clustering::loadSigEPConcentrationDataFromFile(const std::string fileNameSigEP)
+void Clustering::loadInelasticStrainConcentrationDataFromFile(const std::string fileNamePlastic)
 {
   clearAllClusterData();
-  _sigEPConcentrationVectorMap.clear();
-  _directMapOfSigEPConcentration.clear();
+  _inelasticStrainConcentrationVectorMap.clear();
+  _directMapOfInelasticStrainConcentration.clear();
   
-  FILE* fpPlastic = fopen(fileNameSigEP.c_str(),"r");
+  FILE* fpPlastic = fopen(fileNamePlastic.c_str(),"r");
   if (fpPlastic !=NULL) {
-    printf("start reading file: %s\n",fileNameSigEP.c_str());
+    printf("start reading file: %s\n",fileNamePlastic.c_str());
     if(!feof(fpPlastic))
     {
       char what[256];
@@ -1125,12 +1748,12 @@ void Clustering::loadSigEPConcentrationDataFromFile(const std::string fileNameSi
       printf("what = %s\n",what);
       ok = fscanf(fpPlastic, "%s", what);
       printf("what = %s\n",what);
-      for (int i=0; i<12; i++)
+      for (int i=0; i<36; i++)
       {
         ok = fscanf(fpPlastic, "%s", what);
         printf("what = %s\n",what);
       }
-      if(strcmp(what, "B_pl_11"))
+      if(strcmp(what, "A_in_35"))
       {
         Msg::Error("file format is not correct\n");
         Msg::Exit(0);
@@ -1148,8 +1771,8 @@ void Clustering::loadSigEPConcentrationDataFromFile(const std::string fileNameSi
       fullVector<double> val;
       val.resize(4);
       int ok = fscanf(fpPlastic, "%lf %lf %lf %lf", &(val.getDataPtr()[0]),&(val.getDataPtr()[1]),&(val.getDataPtr()[2]),&(val.getDataPtr()[3]));
-      static fullVector<double> vec(12);
-      for (int i=0; i<12; i++)
+      static fullVector<double> vec(36);
+      for (int i=0; i<36; i++)
       {
         double val=0;
         if (fscanf(fpPlastic,"%lf",&val)==1)
@@ -1157,32 +1780,105 @@ void Clustering::loadSigEPConcentrationDataFromFile(const std::string fileNameSi
       }
       if (type >0 && matNum > 0)
       {
-        std::map<int, fullVector<double> >& mapGPLaw = _sigEPConcentrationVectorMap[matNum];
+        std::map<int, fullVector<double> >& mapGPLaw = _inelasticStrainConcentrationVectorMap[matNum];
         mapGPLaw[type] = vec;
-        _directMapOfSigEPConcentration[type] = &mapGPLaw[type];
+        _directMapOfInelasticStrainConcentration[type] = &mapGPLaw[type];
       }
     }
-    printf("done reading file: %s\n",fileNameSigEP.c_str());
+    printf("done reading file: %s\n",fileNamePlastic.c_str());
     fclose(fpPlastic);
   }
   else
   {
-    Msg::Error("File %s does not exist !!!",fileNameSigEP.c_str());
+    Msg::Error("File %s does not exist !!!",fileNamePlastic.c_str());
     Msg::Exit(0);
   }
 }
 
-
-
-void Clustering::loadPlasticEqStrainConcentrationDataFromFile(const std::string fileNamePlasticEq)
+void Clustering::loadTotalStrainConcentrationDataFromFile(const std::string fileNameTotal)
 {
   clearAllClusterData();
-  _plasticEqStrainConcentrationVectorMap.clear();
-  _directMapOfPlasticEqStrainConcentration.clear();
+  _totalStrainConcentrationVectorMap.clear();
+  _directMapOfTotalStrainConcentration.clear();
   
-  FILE* fpPlasticEq = fopen(fileNamePlasticEq.c_str(),"r");
-  if (fpPlasticEq !=NULL) {
-    printf("start reading file: %s\n",fileNamePlasticEq.c_str());
+  FILE* fpPlastic = fopen(fileNameTotal.c_str(),"r");
+  if (fpPlastic !=NULL) {
+    printf("start reading file: %s\n",fileNameTotal.c_str());
+    if(!feof(fpPlastic))
+    {
+      char what[256];
+      int ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      ok = fscanf(fpPlastic, "%s", what);
+      printf("what = %s\n",what);
+      for (int i=0; i<36; i++)
+      {
+        ok = fscanf(fpPlastic, "%s", what);
+        printf("what = %s\n",what);
+      }
+      if(strcmp(what, "A_tot_35"))
+      {
+        Msg::Error("file format is not correct\n");
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(fpPlastic))
+        break;
+      int ele, gp, matNum;
+      int type = 0;
+      if (fscanf(fpPlastic, "%d %d %d", &ele,&gp,&matNum)==3)
+      {
+        type = numericalMaterialBase::createTypeWithTwoInts(ele,gp);
+      }
+      fullVector<double> val;
+      val.resize(4);
+      int ok = fscanf(fpPlastic, "%lf %lf %lf %lf", &(val.getDataPtr()[0]),&(val.getDataPtr()[1]),&(val.getDataPtr()[2]),&(val.getDataPtr()[3]));
+      static fullVector<double> vec(36);
+      for (int i=0; i<36; i++)
+      {
+        double val=0;
+        if (fscanf(fpPlastic,"%lf",&val)==1)
+          vec(i) = val;
+      }
+      if (type >0 && matNum > 0)
+      {
+        std::map<int, fullVector<double> >& mapGPLaw = _totalStrainConcentrationVectorMap[matNum];
+        mapGPLaw[type] = vec;
+        _directMapOfTotalStrainConcentration[type] = &mapGPLaw[type];
+      }
+    }
+    printf("done reading file: %s\n",fileNameTotal.c_str());
+    fclose(fpPlastic);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileNameTotal.c_str());
+    Msg::Exit(0);
+  }
+}
+
+
+
+void Clustering::loadPlasticEqStrainConcentrationDataFromFile(const std::string fileNamePlasticEq)
+{
+  clearAllClusterData();
+  _plasticEqStrainConcentrationVectorMap.clear();
+  _directMapOfPlasticEqStrainConcentration.clear();
+  
+  FILE* fpPlasticEq = fopen(fileNamePlasticEq.c_str(),"r");
+  if (fpPlasticEq !=NULL) {
+    printf("start reading file: %s\n",fileNamePlasticEq.c_str());
     if(!feof(fpPlasticEq))
     {
       char what[256];
@@ -1435,7 +2131,10 @@ bool Clustering::clusteringByMeshPartition(nonLinearMechSolver& solver, int nbCl
 bool Clustering::computeClustersElasticity(int minNumberElementEachCluster, int maxNbIterations,
                                  bool saveToFile, std::string clusterFileName,
                                  bool saveSummaryFile, std::string summaryFileName,
-                                 bool saveMostStrainIPFile, const std::string saveMostStrainIPFileName
+                                 bool saveMostStrainIPFile, const std::string saveMostStrainIPFileName,
+                                 bool saveStrainConcStDFile, const std::string saveStrainConcStDFileName,
+                                 bool saveClusterPositionFile, const std::string saveClusterPositionFileName,
+                                 bool saveClusterMeanFiberOrientationFile, const std::string saveClusterMeanFiberOrientationFileName
                                  )
 {
   // init cluster 
@@ -1487,6 +2186,14 @@ bool Clustering::computeClustersElasticity(int minNumberElementEachCluster, int
         static fullMatrix<double> Amean(6,6);
         _clusterVolumeMap[clusterNum] = clutering_impls::meanCluster(cluster,_mapGaussPoints,Amean);
         STensorOperation::fromFullMatrixToSTensor43(Amean,_clusterAverageStrainConcentrationTensorMap[clusterNum]);
+        
+        static STensor43 Astd;
+        clutering_impls::Tensor43STDCluster(cluster,_mapGaussPoints,_clusterAverageStrainConcentrationTensorMap[clusterNum],Astd);
+        _clusterSTDTensorMap[clusterNum] = Astd;
+        
+        static double astd;
+        clutering_impls::Tensor43STDScalarCluster(cluster,_mapGaussPoints,_clusterAverageStrainConcentrationTensorMap[clusterNum],astd);
+        _clusterSTDMap[clusterNum] = astd;
 
         _clusterMaterialMap[clusterNum] = matNum;
         
@@ -1496,6 +2203,26 @@ bool Clustering::computeClustersElasticity(int minNumberElementEachCluster, int
         // most strain IP
         mostStrainIP[clusterNum] = clutering_impls::maxConcentrationCluster(cluster);
         Msg::Info("most strain in cluster = %d is IP %d",clusterNum,mostStrainIP[clusterNum]);
+        
+        fullVector<double> cluster_position(3);
+        double x_mean(0.), y_mean(0.), z_mean(0.);
+        clutering_impls::meanClusterPosition(cluster,_mapGaussPoints,x_mean,y_mean,z_mean);
+        cluster_position(0) = x_mean;
+        cluster_position(1) = y_mean;
+        cluster_position(2) = z_mean;
+        _clusterPositionMap[clusterNum] = cluster_position;
+        Msg::Info("position of cluster = %d is %.16g,%.16g,%.16g ",clusterNum,x_mean,y_mean,z_mean);
+        
+        
+        fullVector<double> cluster_fiberOrientation(3);
+        double E1_mean(0.), E2_mean(0.), E3_mean(0.);
+        clutering_impls::meanClusterFiberOrientation(cluster,_mapGaussPoints,_mapLocalOrientation,E1_mean,E2_mean,E3_mean);
+        cluster_fiberOrientation(0) = E1_mean;
+        cluster_fiberOrientation(1) = E2_mean;
+        cluster_fiberOrientation(2) = E3_mean;
+        _clusterMeanFiberOrientationMap[clusterNum] = cluster_fiberOrientation;
+        Msg::Info("inclusion angle in cluster = %d is %.16g,%.16g,%.16g ",clusterNum,E1_mean,E2_mean,E3_mean);
+        
       }
       _totalNumberOfClusters += nbCluster;
       Msg::Info("done clustering for material %d",matNum);
@@ -1524,8 +2251,50 @@ bool Clustering::computeClustersElasticity(int minNumberElementEachCluster, int
     fclose(f);
     printf("done writing data to file: %s \n",fname.c_str());
   }
-
   
+  if (saveClusterPositionFile)
+  {
+    std::vector<std::string> splitFileName = SplitFileName(saveClusterPositionFileName);
+    std::string fname = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* f = fopen(fname.c_str(),"w");
+    printf("start writing cluster position to file: %s\n",fname.c_str());
+    std::string str ="CLUSTER_ID X Y Z";
+    fprintf(f,"%s\n",str.c_str());
+    for (std::map<int, fullVector<double> >::const_iterator it = _clusterPositionMap.begin();  it!= _clusterPositionMap.end(); it++)
+    { 
+      int clusterId = it->first;
+      fullVector<double> xyz = it->second;
+      double x = xyz(0);
+      double y = xyz(1);
+      double z = xyz(2);
+      fprintf(f, "%d %.16g %.16g %.16g\n",clusterId,x,y,z);
+    }
+    fclose(f);
+    printf("done writing cluster position to file: %s \n",fname.c_str());
+  }
+  
+  if (saveClusterMeanFiberOrientationFile)
+  {
+    std::vector<std::string> splitFileName = SplitFileName(saveClusterMeanFiberOrientationFileName);
+    std::string fname = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* f = fopen(fname.c_str(),"w");
+    printf("start writing cluster mean fiber orientation to file: %s\n",fname.c_str());
+    std::string str ="CLUSTER_ID MAT_NUM E1 E2 E3";
+    fprintf(f,"%s\n",str.c_str());
+    for (std::map<int, fullVector<double> >::const_iterator it = _clusterMeanFiberOrientationMap.begin();  it!= _clusterMeanFiberOrientationMap.end(); it++)
+    { 
+      int clusterId = it->first;
+      int matNum = _clusterMaterialMap[clusterId];
+      fullVector<double> angles = it->second;
+      double E1 = angles(0);
+      double E2 = angles(1);
+      double E3 = angles(2);
+      fprintf(f, "%d %d %.16g %.16g %.16g\n",clusterId,matNum,E1,E2,E3);
+    }
+    fclose(f);
+    printf("done writing cluster mean fiber orientation to file: %s \n",fname.c_str());
+  }
+ 
   if (saveToFile)
   {
     std::vector<std::string> splitFileName = SplitFileName(clusterFileName);
@@ -1588,6 +2357,48 @@ bool Clustering::computeClustersElasticity(int minNumberElementEachCluster, int
     fclose(f);
     printf("done writing cluster summary to file: %s \n",fname.c_str());
   }
+  
+  
+  if(saveStrainConcStDFile)
+  {
+    std::vector<std::string> splitFileName = SplitFileName(saveStrainConcStDFileName);
+    std::string fname = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* f = fopen(fname.c_str(),"w");
+    printf("start writing cluster std to file: %s\n",fname.c_str());
+    std::string str ="CLUSTER_ID MAT_NUM VOLUME";
+    // write data
+    for (int i=0; i<6; i++)
+    {
+      for (int j=0; j<6; j++)
+      {
+        str += " STD_A_"+std::to_string(i)+std::to_string(j);
+      }
+    }
+    fprintf(f,"%s\n",str.c_str());
+    // write data
+    for (std::map<int, STensor43>::const_iterator it = _clusterSTDTensorMap.begin();  it!= _clusterSTDTensorMap.end(); it++)
+    { 
+      int cluster = it->first;
+      int matNum = _clusterMaterialMap[cluster];
+      double volume = _clusterVolumeMap[cluster];
+      fprintf(f,"%d %d %.16g",cluster, matNum, volume);
+      const STensor43& Astd = it->second;
+      static fullMatrix<double> mat(6,6);
+      STensorOperation::fromSTensor43ToFullMatrix(Astd,mat);
+      printf("writing data for cluster %d\n",cluster);
+      mat.print("std strain concentration tensor");
+      for (int i=0; i<6; i++)
+      {
+        for (int j=0; j<6; j++)
+        {
+          fprintf(f, " %.16g",mat(i,j));
+        }
+      }
+      fprintf(f, "\n");
+    }
+    fclose(f);
+    printf("done writing cluster std to file: %s \n",fname.c_str());  
+  }  
   return true;
 };
 
@@ -1599,8 +2410,10 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
                                  bool saveSummaryFile, std::string summaryFileName,
                                  bool savePlastStrainConcFile, std::string plastStrainconcFileName,
                                  bool savePlastEqStrainConcFile, std::string plastEqstrainconcFileName,
-                                 bool savePlastEqStrainConcSTDFile, std::string plastEqstrainconcstdevFileName,
-                                 bool saveMostStrainIPFile, const std::string saveMostStrainIPFileName
+                                 bool savePlastStrainConcSTDFile, std::string plastStrainconcstdevFileName,
+                                 bool saveMostStrainIPFile, const std::string saveMostStrainIPFileName,
+                                 bool saveClusterPositionFile, const std::string saveClusterPositionFileName,
+                                 bool saveClusterMeanFiberOrientationFile, const std::string saveClusterMeanFiberOrientationFileName
                                  )
 {
   // init cluster 
@@ -1611,6 +2424,7 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
   }
 
   std::map<int, int > mostStrainIP;
+  std::map<int, int > mostPlastStrainIP;
   
   //
   _totalNumberOfClusters = 0;
@@ -1628,23 +2442,42 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
     {
       const std::map<int, fullMatrix<double> >& dataInMat = itMat->second;
       const std::map<int, fullVector<double> >& dataInMatPlasticStrainConc = _plasticStrainConcentrationVectorMap[itMat->first];
-      const std::map<int, fullVector<double> >& dataInMatSigEPConc = _sigEPConcentrationVectorMap[itMat->first];
+      const std::map<int, fullVector<double> >& dataInMatInelasticStrainConc = _inelasticStrainConcentrationVectorMap[itMat->first];
+      const std::map<int, fullVector<double> >& dataInMatTotalStrainConc = _totalStrainConcentrationVectorMap[itMat->first];
       const std::map<int, fullVector<double> >& dataInMatPlasticEqStrainConc = _plasticEqStrainConcentrationVectorMap[itMat->first];
       
-      std::map<int, fullVector<double> >& dataInMatPlasticEqStrainConcNormalized = _plasticEqStrainConcentrationNormalizedVectorMap[itMat->first];  
-      std::map<int, fullVector<double> >& dataInMatPlasticStrainConcNormalized = _plasticStrainConcentrationNormalizedVectorMap[itMat->first];  
+      //std::map<int, fullVector<double> >& dataInMatTotalStrainConcNormalized = _totalStrainConcentrationNormalizedVectorMap[itMat->first];
+      //clutering_impls::vecNormalizeByOverallNorm(dataInMatTotalStrainConc,_mapGaussPoints,dataInMatTotalStrainConcNormalized); 
       
-      clutering_impls::vecNormalizedByNorm(dataInMatPlasticStrainConc,_mapGaussPoints,dataInMatPlasticStrainConcNormalized);      
-      clutering_impls::vecNormalized(dataInMatPlasticEqStrainConc,_mapGaussPoints,dataInMatPlasticEqStrainConcNormalized);
-
+      //std::map<int, fullVector<double> >& dataInMatPlasticStrainConcNormalized = _plasticStrainConcentrationNormalizedVectorMap[itMat->first];
+      //clutering_impls::vecNormalizeByOverallNorm(dataInMatPlasticStrainConc,_mapGaussPoints,dataInMatPlasticStrainConcNormalized); 
+      
+      std::map<int, fullVector<double> >& dataInMatInelasticStrainConcNormalized = _inelasticStrainConcentrationNormalizedVectorMap[itMat->first];
+      clutering_impls::vecNormalizeByOverallNorm(dataInMatInelasticStrainConc,_mapGaussPoints,dataInMatInelasticStrainConcNormalized);  
+      
+      //std::map<int, fullVector<double> >& dataInMatPlasticFlowDirConc = _plasticFlowDirConcentrationVectorMap[itMat->first];
+      //clutering_impls::vecNormalizeByLocalNorm(dataInMatPlasticStrainConc,dataInMatPlasticFlowDirConc);
+      
+      //std::map<int, fullVector<double> >& dataInMatInelasticStrainSeparatedConc = _inelasticStrainConcentrationSeparatedVectorMap[itMat->first];
+      //clutering_impls::vecSeparate(dataInMatInelasticStrainConc,dataInMatInelasticStrainSeparatedConc);
+      
+      std::map<int, fullVector<double> >& dataInMatPlasticEqStrainConcNormalized = _plasticEqStrainConcentrationNormalizedVectorMap[itMat->first];
+      clutering_impls::vecNormalizeByOverallValue(dataInMatPlasticEqStrainConc,_mapGaussPoints,dataInMatPlasticEqStrainConcNormalized);
+   
       //Msg::Info("start clustering for material %d \n number of clusters = %d, min number in each cluster = %d",matNum, nbCluster,minNumberElementEachCluster);
       std::map<int, std::map<int, const fullMatrix<double>*> > clusterInMat;
       std::map<int, std::map<int, const fullVector<double>*> > clusterInMatPlasticTensor;
-      std::map<int, std::map<int, const fullVector<double>*> > clusterInMatSigEPTensor;
-      std::map<int, std::map<int, const fullVector<double>*> > clusterInMatPlasticEq;
+      std::map<int, std::map<int, const fullVector<double>*> > clusterInMatInelasticTensor;
+      std::map<int, std::map<int, const fullVector<double>*> > clusterInMatTotalStrainTensor;
+
+      //bool ok= clutering_impls::kmean_cluster_FullVectorBased(dataInMatTotalStrainConcNormalized,dataInMat,nbCluster,minNumberElementEachCluster,maxNbIterations,_mapGaussPoints,
+        //                                                      clusterInMatTotalTensor,clusterInMat);
                                                           
-      bool ok= clutering_impls::kmean_cluster_FullVectorBased(dataInMatPlasticStrainConcNormalized,dataInMat,nbCluster,minNumberElementEachCluster,maxNbIterations,_mapGaussPoints,
-                                                              clusterInMatPlasticTensor,clusterInMat);
+      //bool ok= clutering_impls::kmean_cluster_FullVectorBased(dataInMatPlasticStrainConcNormalized,dataInMat,nbCluster,minNumberElementEachCluster,maxNbIterations,_mapGaussPoints,
+        //                                                      clusterInMatPlasticTensor,clusterInMat);
+                                                              
+      bool ok= clutering_impls::kmean_cluster_FullVectorBased(dataInMatInelasticStrainConcNormalized,dataInMat,nbCluster,minNumberElementEachCluster,maxNbIterations,_mapGaussPoints,
+                                                              clusterInMatInelasticTensor,clusterInMat);
 
       if (!ok)
       {
@@ -1665,17 +2498,16 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
         _clusterVolumeMap[clusterNum] = clutering_impls::meanCluster(cluster,_mapGaussPoints,Amean);
         STensorOperation::fromFullMatrixToSTensor43(Amean,_clusterAverageStrainConcentrationTensorMap[clusterNum]);
 
-
-        const std::map<int, const fullVector<double>*>& clusterPlEq = (clusterInMatPlasticEq.find(it->first))->second;
-
         /*const std::map<int, const fullVector<double>*>& clusterPlTensor = (clusterInMatPlasticTensor.find(it->first))->second;
-        const std::map<int, const fullVector<double>*>& clusterSigEPTensor = (clusterInMatSigEPTensor.find(it->first))->second;
-        static fullVector<double> PlTensorMean(12);
+        static fullVector<double> PlTensorMean(36);
         _clusterVolumeMap[clusterNum] = clutering_impls::meanClusterVecLong(clusterPlTensor,_mapGaussPoints,PlTensorMean);
-        _clusterAveragePlasticStrainConcentrationVectorMap[clusterNum] = PlTensorMean;    
-        static fullVector<double> sigEPTensorMean(12);
-        _clusterVolumeMap[clusterNum] = clutering_impls::meanClusterVecLong(clusterSigEPTensor,_mapGaussPoints,sigEPTensorMean);
-        _clusterAverageSigEPConcentrationVectorMap[clusterNum] = sigEPTensorMean;*/
+        _clusterAveragePlasticStrainConcentrationVectorMap[clusterNum] = PlTensorMean;*/
+        
+        //const std::map<int, const fullVector<double>*>& clusterInelTensor = (clusterInMatInelasticTensor.find(it->first))->second;
+           
+        //static fullVector<double> PlTensorMean(36);
+        //clutering_impls::meanClusterVec_FullMatrixBased(dataInMatPlasticEqStrainConcNormalized,cluster,_mapGaussPoints,PlTensorMean);
+        //_clusterAveragePlasticStrainConcentrationVectorMap[clusterNum] = PlTensorMean;
            
         static fullVector<double> PlEqmean(6);
         clutering_impls::meanClusterVec_FullMatrixBased(dataInMatPlasticEqStrainConcNormalized,cluster,_mapGaussPoints,PlEqmean);
@@ -1688,10 +2520,32 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
         static fullVector<double> PlEqHarmonicMeanVec(6);
         clutering_impls::meanHarmonicClusterVec_FullMatrixBased(dataInMatPlasticEqStrainConcNormalized,cluster,_mapGaussPoints,PlEqHarmonicMeanVec);
         _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap[clusterNum] = PlEqHarmonicMeanVec;
+        
+        static fullVector<double> PlEqPowerMeanVec(6);
+        clutering_impls::meanPowerClusterVec_FullMatrixBased(dataInMatPlasticEqStrainConcNormalized,cluster,_mapGaussPoints,PlEqPowerMeanVec);
+        _clusterAveragePowerPlasticEqStrainConcentrationVectorMap[clusterNum] = PlEqPowerMeanVec;
+        
+        for (std::map<int, const fullMatrix<double>*>::const_iterator itset = cluster.begin(); itset != cluster.end(); itset++)
+        {
+          fullVector<double>& pfc= _clusterPFC[itset->first];
+          pfc.resize(6,true);
+          for(int i=0;i<6;i++)
+          {
+            if(PlEqmean(i)>1. and PlEqHarmonicMeanVec(i)>0.8)
+            {
+              pfc(i) = PlEqmean(i)/PlEqHarmonicMeanVec(i);
+            }
+            else
+            {
+              pfc(i) = 1.;
+            }
+          }
+        _clusterPFC[itset->first] = pfc;
+        }
 
-        /*static fullVector<double> stdPlEqVec(6);
-        clutering_impls::VectorSTDCluster(clusterPlEq,_mapGaussPoints,_clusterAveragePlasticEqStrainConcentrationVectorMap[clusterNum],stdPlEqVec);
-        _clusterPlEqSTDVectorMap[clusterNum] = stdPlEqVec;*/
+        static fullVector<double> stdPlVec(36);
+        //clutering_impls::VectorSTDCluster(clusterPlTensor,_mapGaussPoints,_clusterAveragePlasticStrainConcentrationVectorMap[clusterNum],stdPlVec);
+        _clusterPlSTDVectorMap[clusterNum] = stdPlVec;
                                             
         _clusterMaterialMap[clusterNum] = matNum;
         
@@ -1699,8 +2553,37 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
         Amean.print("average strain concentration tensor");
 
         // most strain IP
-        mostStrainIP[clusterNum] = clutering_impls::maxConcentrationCluster(cluster);
-        Msg::Info("most strain in cluster = %d is IP %d",clusterNum,mostStrainIP[clusterNum]);
+        /*mostStrainIP[clusterNum] = clutering_impls::maxConcentrationCluster(cluster);
+        Msg::Info("most elastic strain in cluster = %d is IP %d",clusterNum,mostStrainIP[clusterNum]);*/
+        
+        //mostStrainIP[clusterNum] = clutering_impls::maxConcentrationVecCluster(clusterInelTensor);
+        //Msg::Info("most total inelastic strain in cluster = %d is IP %d",clusterNum,mostStrainIP[clusterNum]);
+        
+        /*mostPlastStrainIP[clusterNum] = clutering_impls::maxConcentrationVecCluster(clusterPlTensor);
+        Msg::Info("most plastic strain in cluster = %d is IP %d",clusterNum,mostPlastStrainIP[clusterNum]);*/
+        
+        mostStrainIP[clusterNum] = 0.;
+        
+        
+        fullVector<double> cluster_position(3);
+        double x_mean(0.), y_mean(0.), z_mean(0.);
+        clutering_impls::meanClusterPosition(cluster,_mapGaussPoints,x_mean,y_mean,z_mean);
+        cluster_position(0) = x_mean;
+        cluster_position(1) = y_mean;
+        cluster_position(2) = z_mean;
+        _clusterPositionMap[clusterNum] = cluster_position;
+        Msg::Info("position of cluster = %d is %.16g,%.16g,%.16g ",clusterNum,x_mean,y_mean,z_mean);
+        
+        
+        fullVector<double> cluster_fiberOrientation(3);
+        double E1_mean(0.), E2_mean(0.), E3_mean(0.);
+        clutering_impls::meanClusterFiberOrientation(cluster,_mapGaussPoints,_mapLocalOrientation,E1_mean,E2_mean,E3_mean);
+        cluster_fiberOrientation(0) = E1_mean;
+        cluster_fiberOrientation(1) = E2_mean;
+        cluster_fiberOrientation(2) = E3_mean;
+        _clusterMeanFiberOrientationMap[clusterNum] = cluster_fiberOrientation;
+        Msg::Info("position of cluster = %d is %.16g,%.16g,%.16g ",clusterNum,E1_mean,E2_mean,E3_mean);
+               
       }
       _totalNumberOfClusters += nbCluster;
       Msg::Info("done clustering for material %d",matNum);
@@ -1729,7 +2612,49 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
     fclose(f);
     printf("done writing data to file: %s \n",fname.c_str());
   }
-
+  
+  if (saveClusterPositionFile)
+  {
+    std::vector<std::string> splitFileName = SplitFileName(saveClusterPositionFileName);
+    std::string fname = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* f = fopen(fname.c_str(),"w");
+    printf("start writing cluster position to file: %s\n",fname.c_str());
+    std::string str ="CLUSTER_ID X Y Z";
+    fprintf(f,"%s\n",str.c_str());
+    for (std::map<int, fullVector<double> >::const_iterator it = _clusterPositionMap.begin();  it!= _clusterPositionMap.end(); it++)
+    { 
+      int clusterId = it->first;
+      fullVector<double> xyz = it->second;
+      double x = xyz(0);
+      double y = xyz(1);
+      double z = xyz(2);
+      fprintf(f, "%d %.16g %.16g %.16g\n",clusterId,x,y,z);
+    }
+    fclose(f);
+    printf("done writing cluster position to file: %s \n",fname.c_str());
+  }
+  
+  if (saveClusterMeanFiberOrientationFile)
+  {
+    std::vector<std::string> splitFileName = SplitFileName(saveClusterMeanFiberOrientationFileName);
+    std::string fname = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* f = fopen(fname.c_str(),"w");
+    printf("start writing cluster mean fiber orientation to file: %s\n",fname.c_str());
+    std::string str ="CLUSTER_ID MAT_NUM E1 E2 E3";
+    fprintf(f,"%s\n",str.c_str());
+    for (std::map<int, fullVector<double> >::const_iterator it = _clusterMeanFiberOrientationMap.begin();  it!= _clusterMeanFiberOrientationMap.end(); it++)
+    { 
+      int clusterId = it->first;
+      int matNum = _clusterMaterialMap[clusterId];
+      fullVector<double> angles = it->second;
+      double E1 = angles(0);
+      double E2 = angles(1);
+      double E3 = angles(2);
+      fprintf(f, "%d %d %.16g %.16g %.16g\n",clusterId,matNum,E1,E2,E3);
+    }
+    fclose(f);
+    printf("done writing cluster mean fiber orientation to file: %s \n",fname.c_str());
+  }
   
   if (saveToFile)
   {
@@ -1793,43 +2718,7 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
     fclose(f);
     printf("done writing cluster summary to file: %s \n",fname.c_str());
   }
-
-
-  /*if (savePlastStrainConcFile)
-  {
-    std::vector<std::string> splitFileName = SplitFileName(plastStrainconcFileName);
-    
-    std::string fnamePl1 = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
-    FILE* fpl1 = fopen(fnamePl1.c_str(),"w");
-    printf("start writing cluster eq. plastic summary to file: %s\n",fnamePl1.c_str());
-    std::string strpl1 ="CLUSTER_ID MAT_NUM VOLUME";
-    // write data
-    for (int i=0; i<12; i++)
-    {
-        strpl1 += " A_pl_"+std::to_string(i);
-    }
-    fprintf(fpl1,"%s\n",strpl1.c_str());
-    // write data
-    for (std::map<int, fullVector<double>>::const_iterator it = _clusterAveragePlasticStrainConcentrationVectorMap.begin();  it!= _clusterAveragePlasticStrainConcentrationVectorMap.end(); it++)
-    { 
-      int cluster = it->first;
-      int matNum = _clusterMaterialMap[cluster];
-      double volume = _clusterVolumeMap[cluster];
-      fprintf(fpl1,"%d %d %.16g",cluster, matNum, volume);
-      const fullVector<double>& plasticmean1 = it->second;
-      printf("writing plastic strain data for cluster %d\n",cluster);
-      plasticmean1.print("plastic average strain concentration tensor");
-      for (int i=0; i<6; i++)
-      {
-        fprintf(fpl1, " %.16g",plasticmean1(i));
-      }
-      fprintf(fpl1, "\n");
-    }
-    fclose(fpl1);
-    printf("done writing cluster plastic strain mean summary to file: %s \n",fnamePl1.c_str());
-  }*/
-    
-  
+      
   if (savePlastEqStrainConcFile)
   {
     std::vector<std::string> splitFileName = SplitFileName(plastEqstrainconcFileName);
@@ -1886,79 +2775,283 @@ bool Clustering::computeClustersPlasticity(int minNumberElementEachCluster, int
       plasticmean.print("geometric mean plastic eq. average strain concentration tensor");
       for (int i=0; i<6; i++)
       {
-        fprintf(fplGeoMean, " %.16g",plasticmean(i));
+        fprintf(fplGeoMean, " %.16g",plasticmean(i));
+      }
+      fprintf(fplGeoMean, "\n");
+    }
+    fclose(fplGeoMean);
+    printf("done writing cluster plastic eq. geometric mean summary to file: %s \n",fnamePlGeoMean.c_str());
+    
+    std::string fnamePlHarMean = splitFileName[1]+"Har_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* fplHarMean = fopen(fnamePlHarMean.c_str(),"w");
+    printf("start writing cluster eq. plastic harmonic mean summary to file: %s\n",fnamePlHarMean.c_str());
+    std::string strplHarMean ="CLUSTER_ID MAT_NUM VOLUME";
+    // write data
+    for (int i=0; i<6; i++)
+    {
+        strplHarMean += " a_pl_"+std::to_string(i);
+    }
+    fprintf(fplHarMean,"%s\n",strplHarMean.c_str());
+    // write data
+    for (std::map<int, fullVector<double>>::const_iterator it = _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap.begin();
+         it!= _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap.end(); it++)
+    { 
+      int cluster = it->first;
+      int matNum = _clusterMaterialMap[cluster];
+      double volume = _clusterVolumeMap[cluster];
+      fprintf(fplHarMean,"%d %d %.16g",cluster, matNum, volume);
+      const fullVector<double>& plasticmean = it->second;
+      printf("writing harmonic mean eq. plastic data for cluster %d\n",cluster);
+      plasticmean.print("harmonic mean plastic eq. average strain concentration tensor");
+      for (int i=0; i<6; i++)
+      {
+        fprintf(fplHarMean, " %.16g",plasticmean(i));
+      }
+      fprintf(fplHarMean, "\n");
+    }
+    fclose(fplHarMean);
+    printf("done writing cluster plastic eq. harmonic mean summary to file: %s \n",fnamePlHarMean.c_str());
+    
+    std::string fnamePlPowMean = splitFileName[1]+"Pow_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
+    FILE* fplPowMean = fopen(fnamePlPowMean.c_str(),"w");
+    printf("start writing cluster eq. plastic power mean summary to file: %s\n",fnamePlPowMean.c_str());
+    std::string strplPowMean ="CLUSTER_ID MAT_NUM VOLUME";
+    // write data
+    for (int i=0; i<6; i++)
+    {
+        strplPowMean += " a_pl_"+std::to_string(i);
+    }
+    fprintf(fplPowMean,"%s\n",strplPowMean.c_str());
+    // write data
+    for (std::map<int, fullVector<double>>::const_iterator it = _clusterAveragePowerPlasticEqStrainConcentrationVectorMap.begin();
+         it!= _clusterAveragePowerPlasticEqStrainConcentrationVectorMap.end(); it++)
+    { 
+      int cluster = it->first;
+      int matNum = _clusterMaterialMap[cluster];
+      double volume = _clusterVolumeMap[cluster];
+      fprintf(fplPowMean,"%d %d %.16g",cluster, matNum, volume);
+      const fullVector<double>& plasticmean = it->second;
+      printf("writing power mean eq. plastic data for cluster %d\n",cluster);
+      plasticmean.print("power mean plastic eq. average strain concentration tensor");
+      for (int i=0; i<6; i++)
+      {
+        fprintf(fplPowMean, " %.16g",plasticmean(i));
+      }
+      fprintf(fplPowMean, "\n");
+    }
+    fclose(fplPowMean);
+    printf("done writing cluster plastic eq. power mean summary to file: %s \n",fnamePlPowMean.c_str());
+  }
+
+  if (savePlastStrainConcSTDFile)
+  {
+    std::vector<std::string> splitFileNameSTD = SplitFileName(plastStrainconcstdevFileName);
+    std::string fnamePlStd = splitFileNameSTD[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileNameSTD[2];
+    FILE* fplstd = fopen(fnamePlStd.c_str(),"w");
+    std::string strPlSTD ="CLUSTER_ID MAT_NUM VOLUME";
+    // write data
+    for (int i=0; i<36; i++)
+    {
+      strPlSTD += " STD_A_pl_"+std::to_string(i);
+    }
+    fprintf(fplstd,"%s\n",strPlSTD.c_str());
+    // write data
+    for (std::map<int, fullVector<double>>::const_iterator it = _clusterPlSTDVectorMap.begin();  it!= _clusterPlSTDVectorMap.end(); it++)
+    { 
+      int cluster = it->first;
+      int matNum = _clusterMaterialMap[cluster];
+      double volume = _clusterVolumeMap[cluster];
+      fprintf(fplstd,"%d %d %.16g",cluster, matNum, volume);
+      const fullVector<double>& plasticSTD = it->second;
+      for (int i=0; i<36; i++)
+      {
+        fprintf(fplstd, " %.16g",plasticSTD(i));
+      }
+      fprintf(fplstd, "\n");
+    }
+    fclose(fplstd);
+    printf("done writing cluster plastic eq. std to file: %s \n",fnamePlStd.c_str());
+  }
+  return true;
+};
+
+
+
+void Clustering::loadClusterSummaryFromFile(const std::string fileName)
+{
+  FILE* f = fopen(fileName.c_str(),"r");
+  if (f !=NULL) {
+    printf("start reading file: %s\n",fileName.c_str());
+    if(!feof(f))
+    {
+      char what[256];
+      fscanf(f, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(f, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(f, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(f, "%s", what);
+      printf("what = %s\n",what);
+
+      for (int i=0; i<6; i++)
+      {
+        for (int j=0; j<6; j++)
+        {
+          fscanf(f, "%s", what);
+          printf("what = %s\n",what);
+        }
+      }
+      if(strcmp(what, "A_55"))
+      {
+        Msg::Error("file format in %s is not correct\n",fileName.c_str());
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(f))
+        break;
+      int cluster =0;
+      int matNum = 0;
+      double volume = 0;
+      double stdev = 0.;
+      if (fscanf(f, "%d %d %lf %lf", &cluster,&matNum,&volume,&stdev)==4)
+      {
+        static fullMatrix<double> matTensor(6,6);
+        for (int i=0; i<6; i++)
+        {
+          for (int j=0; j<6; j++)
+          {
+            double val=0;
+            if (fscanf(f,"%lf",&val)==1)
+              matTensor(i,j) = val;
+          }
+        }
+        if (matNum >0)
+        {
+          printf("load data in cluster %d matnum = %d volume = %e stdev = %e \n",cluster,matNum,volume,stdev);
+          matTensor.print("matTensor");
+          
+          _clusterMaterialMap[cluster] = matNum;
+          _clusterVolumeMap[cluster] = volume;
+          _clusterSTDMap[cluster] = stdev;
+          STensor43& T = _clusterAverageStrainConcentrationTensorMap[cluster];
+          STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
+        }
+      }
+    }
+    printf("done reading file: %s\n",fileName.c_str());
+    fclose(f);
+    
+    _totalNumberOfClusters = _clusterVolumeMap.size();
+    printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileName.c_str());
+    Msg::Exit(0);
+  }
+}
+
+void Clustering::loadReferenceStiffnessFromFile(const std::string fileName)
+{
+  FILE* f = fopen(fileName.c_str(),"r");
+  if (f !=NULL) {
+    printf("start reading file: %s\n",fileName.c_str());
+    if(!feof(f))
+    {
+      char what[256];
+      for (int i=0; i<6; i++)
+      {
+        for (int j=0; j<6; j++)
+        {
+          fscanf(f, "%s", what);
+          printf("what = %s\n",what);
+        }
+      }
+      if(strcmp(what, "C_el_55"))
+      {
+        Msg::Error("file format in %s is not correct\n",fileName.c_str());
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(f))
+        break;
+
+      static fullMatrix<double> matTensor(6,6);
+      for (int i=0; i<6; i++)
+      {
+        for (int j=0; j<6; j++)
+        {
+          double val=0;
+          if (fscanf(f,"%lf",&val)==1)
+            matTensor(i,j) = val;
+        }
       }
-      fprintf(fplGeoMean, "\n");
+      STensor43& T = _referenceStiffness;
+      STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
     }
-    fclose(fplGeoMean);
-    printf("done writing cluster plastic eq. geometric mean summary to file: %s \n",fnamePlGeoMean.c_str());
-    
-    std::string fnamePlHarMean = splitFileName[1]+"Har_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
-    FILE* fplHarMean = fopen(fnamePlHarMean.c_str(),"w");
-    printf("start writing cluster eq. plastic harmonic mean summary to file: %s\n",fnamePlHarMean.c_str());
-    std::string strplHarMean ="CLUSTER_ID MAT_NUM VOLUME";
-    // write data
-    for (int i=0; i<6; i++)
+    printf("done reading file: %s\n",fileName.c_str());
+    fclose(f);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileName.c_str());
+    Msg::Exit(0);
+  }
+}
+
+void Clustering::loadReferenceStiffnessIsoFromFile(const std::string fileName)
+{
+  FILE* f = fopen(fileName.c_str(),"r");
+  if (f !=NULL) {
+    printf("start reading file: %s\n",fileName.c_str());
+    if(!feof(f))
     {
-        strplHarMean += " a_pl_"+std::to_string(i);
-    }
-    fprintf(fplHarMean,"%s\n",strplHarMean.c_str());
-    // write data
-    for (std::map<int, fullVector<double>>::const_iterator it = _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap.begin();
-         it!= _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap.end(); it++)
-    { 
-      int cluster = it->first;
-      int matNum = _clusterMaterialMap[cluster];
-      double volume = _clusterVolumeMap[cluster];
-      fprintf(fplHarMean,"%d %d %.16g",cluster, matNum, volume);
-      const fullVector<double>& plasticmean = it->second;
-      printf("writing harmonic mean eq. plastic data for cluster %d\n",cluster);
-      plasticmean.print("harmonic mean plastic eq. average strain concentration tensor");
+      char what[256];
       for (int i=0; i<6; i++)
       {
-        fprintf(fplHarMean, " %.16g",plasticmean(i));
+        for (int j=0; j<6; j++)
+        {
+          fscanf(f, "%s", what);
+          printf("what = %s\n",what);
+        }
+      }
+      if(strcmp(what, "C_el_55"))
+      {
+        Msg::Error("file format in %s is not correct\n",fileName.c_str());
+        Msg::Exit(0);
       }
-      fprintf(fplHarMean, "\n");
     }
-    fclose(fplHarMean);
-    printf("done writing cluster plastic eq. harmonic mean summary to file: %s \n",fnamePlHarMean.c_str());
-  }
+    while (1){
+      if(feof(f))
+        break;
 
-  /*if (savePlastEqStrainConcSTDFile)
-  {
-    std::vector<std::string> splitFileNameSTD = SplitFileName(plastEqstrainconcstdevFileName);
-    std::string fnamePlStd = splitFileNameSTD[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileNameSTD[2];
-    FILE* fplstd = fopen(fnamePlStd.c_str(),"w");
-    std::string strPlSTD ="CLUSTER_ID MAT_NUM VOLUME";
-    // write data
-    for (int i=0; i<6; i++)
-    {
-      strPlSTD += " STD_a_pl_"+std::to_string(i);
-    }
-    fprintf(fplstd,"%s\n",strPlSTD.c_str());
-    // write data
-    for (std::map<int, fullVector<double>>::const_iterator it = _clusterPlEqSTDVectorMap.begin();  it!= _clusterPlEqSTDVectorMap.end(); it++)
-    { 
-      int cluster = it->first;
-      int matNum = _clusterMaterialMap[cluster];
-      double volume = _clusterVolumeMap[cluster];
-      fprintf(fplstd,"%d %d %.16g",cluster, matNum, volume);
-      const fullVector<double>& plasticSTD = it->second;
+      static fullMatrix<double> matTensor(6,6);
       for (int i=0; i<6; i++)
       {
-        fprintf(fplstd, " %.16g",plasticSTD(i));
+        for (int j=0; j<6; j++)
+        {
+          double val=0;
+          if (fscanf(f,"%lf",&val)==1)
+            matTensor(i,j) = val;
+        }
       }
-      fprintf(fplstd, "\n");
+      STensor43& T = _referenceStiffnessIso;
+      STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
     }
-    fclose(fplstd);
-    printf("done writing cluster plastic eq. std to file: %s \n",fnamePlStd.c_str());
-  }*/
-  return true;
-};
-
-
+    printf("done reading file: %s\n",fileName.c_str());
+    fclose(f);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileName.c_str());
+    Msg::Exit(0);
+  }
+}
 
-void Clustering::loadClusterSummaryFromFile(const std::string fileName)
+void Clustering::loadClusterSummaryHomogenizedFrameFromFile(const std::string fileName)
 {
   FILE* f = fopen(fileName.c_str(),"r");
   if (f !=NULL) {
@@ -2023,7 +3116,12 @@ void Clustering::loadClusterSummaryFromFile(const std::string fileName)
     }
     printf("done reading file: %s\n",fileName.c_str());
     fclose(f);
-    
+    _totalNumberOfClusters = _clusterVolumeMap.size();
+    printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
+    _clusterMaterialMap.erase(_totalNumberOfClusters-1);
+    _clusterVolumeMap.erase(_totalNumberOfClusters-1);
+    _clusterSTDMap.erase(_totalNumberOfClusters-1);
+    _clusterAverageStrainConcentrationTensorMap.erase(_totalNumberOfClusters-1);
     _totalNumberOfClusters = _clusterVolumeMap.size();
     printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
   }
@@ -2034,7 +3132,6 @@ void Clustering::loadClusterSummaryFromFile(const std::string fileName)
   }
 }
 
-
 void Clustering::loadClusterStandDevFromFile(const std::string fileName)
 {
   FILE* f = fopen(fileName.c_str(),"r");
@@ -2285,6 +3382,128 @@ void Clustering::loadClusterPlasticEqSummaryHarmonicFromFile(const std::string f
 }
 
 
+void Clustering::loadClusterPlasticEqSummaryPowerFromFile(const std::string fileName)
+{
+  FILE* fp = fopen(fileName.c_str(),"r");
+  if (fp !=NULL) {
+    printf("start reading file: %s\n",fileName.c_str());
+    if(!feof(fp))
+    {
+      char what[256];
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+
+      for (int i=0; i<6; i++)
+      {
+        fscanf(fp, "%s", what);
+        printf("what = %s\n",what);
+      }
+      if(strcmp(what, "a_pl_5"))
+      {
+        Msg::Error("file format in %s is not correct\n",fileName.c_str());
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(fp))
+        break;
+      int cluster =0;
+      int matNum = 0;
+      double volume = 0;
+      if (fscanf(fp, "%d %d %lf", &cluster,&matNum,&volume)==3)
+      {
+        static fullVector<double> vec(6);
+        for (int i=0; i<6; i++)
+        {
+          double val=0;
+          if (fscanf(fp,"%lf",&val)==1)
+            vec(i) = val;
+        }
+        if (matNum >0)
+        {
+          printf("load data in cluster %d matnum = %d volume = %e \n",cluster,matNum,volume);
+          vec.print("vec");
+          
+          fullVector<double>& t = _clusterAveragePowerPlasticEqStrainConcentrationVectorMap[cluster];
+          t = vec;
+        }
+      }
+    }
+    printf("done reading file: %s\n",fileName.c_str());
+    fclose(fp);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileName.c_str());
+    Msg::Exit(0);
+  }
+}
+
+
+void Clustering::loadClusterFiberOrientationFromFile(const std::string fileNameOri)
+{
+  FILE* fp = fopen(fileNameOri.c_str(),"r");
+  if (fp !=NULL) {
+    printf("start reading file: %s\n",fileNameOri.c_str());
+    if(!feof(fp))
+    {
+      char what[256];
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
+      for (int i=0; i<3; i++)
+      {
+        fscanf(fp, "%s", what);
+        printf("what = %s\n",what);
+      }
+      if(strcmp(what, "E3"))
+      {
+        Msg::Error("file format in %s is not correct\n",fileNameOri.c_str());
+        Msg::Exit(0);
+      }
+    }
+    while (1){
+      if(feof(fp))
+        break;
+      int cluster =0;
+      int matNum = 0;
+      if (fscanf(fp, "%d %d", &cluster,&matNum)==2)
+      {
+        static fullVector<double> vec(3);
+        for (int i=0; i<3; i++)
+        {
+          double val=0;
+          if (fscanf(fp,"%lf",&val)==1)
+            vec(i) = val;
+        }
+        if (matNum >0)
+        {
+          printf("load data in cluster %d matnum = %d \n",cluster,matNum);
+          vec.print("vec");
+
+          fullVector<double>& t = _clusterMeanFiberOrientationMap[cluster];
+          t = vec;
+        }
+      }
+    }
+    printf("done reading file: %s\n",fileNameOri.c_str());
+    fclose(fp);
+  }
+  else
+  {
+    Msg::Error("File %s does not exist !!!",fileNameOri.c_str());
+    Msg::Exit(0);
+  }
+}
+
+
+
+
 void Clustering::saveAllView(int gp)
 {
   std::string id = "";
@@ -2350,7 +3569,7 @@ const STensor3& Clustering::getEigenStrain(int GPIndex, bool homogeneous) const
     std::map<int,STensor3>::const_iterator itF = _allEigenStrains.find(cluster);
     if (itF == _allEigenStrains.end())
     {
-      Msg::Error("eigven strain for cluster %d is not found",cluster);
+      Msg::Error("eigen strain for cluster %d is not found",cluster);
       static STensor3 a;
       return a;
     }
@@ -2367,13 +3586,46 @@ const STensor3& Clustering::getEigenStrain(int GPIndex, bool homogeneous) const
     std::map<int,STensor3>::const_iterator itF = _allEigenStrains.find(cluster);
     if (itF == _allEigenStrains.end())
     {
-      Msg::Error("eigven strain for cluster %d is not found",cluster);
+      Msg::Error("eigen strain for cluster %d is not found",cluster);
       static STensor3 a;
       return a;
     }      
   }
 };
 
+const STensor3& Clustering::getEigenStress(int GPIndex, bool homogeneous) const
+{
+  if (homogeneous)
+  {  
+    int eleNum, gpt;
+    numericalMaterialBase::getTwoIntsFromType(GPIndex,eleNum,gpt);
+    int cluster = getClusterIndex(eleNum,gpt);
+    std::map<int,STensor3>::const_iterator itF = _allEigenStresses.find(cluster);
+    if (itF == _allEigenStresses.end())
+    {
+      Msg::Error("eigen stress for cluster %d is not found",cluster);
+      static STensor3 a;
+      return a;
+    }
+    else
+    {
+      return itF->second;
+    }
+  }
+  else
+  {  
+    int eleNum, gpt;
+    numericalMaterialBase::getTwoIntsFromType(GPIndex,eleNum,gpt);
+    int cluster = getClusterIndex(eleNum,gpt);
+    std::map<int,STensor3>::const_iterator itF = _allEigenStresses.find(cluster);
+    if (itF == _allEigenStresses.end())
+    {
+      Msg::Error("eigen stress for cluster %d is not found",cluster);
+      static STensor3 a;
+      return a;
+    }      
+  }
+};
 
 void Clustering::computeAverageStrainCluster(const IPField* ipf , const std::set<int>& cluster, STensor3& Fhomo) const
 {
@@ -2405,8 +3657,7 @@ void Clustering::computeAverageStrainCluster(const IPField* ipf , const std::set
 }
 
 
-void Clustering::computeInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJI, 
-                                                    std::map<std::pair<int,int>, double >& DJIstd, std::map<std::pair<int,int>, fullMatrix<double> >& DJIstdTensor)
+void Clustering::computeInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJI)
 {
   if (!solver.isInitialized())
   {
@@ -2414,30 +3665,54 @@ void Clustering::computeInteractionTensorForCluster(nonLinearMechSolver& solver,
   }
     
   int dim = solver.getDim();
-  std::map<int, STensor3> allEigenStrain;
-  double fact_eig = 1.0e-3;
-  strainForLoadingCases(dim,fact_eig,allEigenStrain);
-  for (std::map<int, STensor3>::const_iterator it = allEigenStrain.begin(); it!= allEigenStrain.end(); it++)
+   
+  std::map<int, STensor3> allEigenField;
+  allEigenField.clear();
+  double fact_eig = 0.;
+  if(_eigenField==0)
+  {
+    fact_eig = 1.0e-3;
+    strainForLoadingCases(dim,fact_eig,allEigenField); 
+  }
+  else if(_eigenField==1)
+  {
+    fact_eig = 1.0; 
+    stressForLoadingCases(dim,fact_eig,allEigenField);
+  }
+
+  for (std::map<int, STensor3>::const_iterator it = allEigenField.begin(); it!= allEigenField.end(); it++)
   {    
-    int i = it->first;
-    // get eigven strain
-    const STensor3& eigenStrain = it->second;
-    Msg::Info("for Cluster %d loading case: %d", clusterI,i);
-    eigenStrain.print("eigenstrain tensor: ");
-    
-    // init the map
+    int i = it->first;    
     _allEigenStrains.clear();
+    _allEigenStresses.clear();
+    // get eigen strain/stress
     for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
     {
       if (clusterI == itMapMat->first)
       {
-        _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,eigenStrain));
+        if(_eigenField==0)
+        {
+          const STensor3& eigenStrain = it->second;
+          Msg::Info("for Cluster %d loading case: %d", clusterI,i);
+          eigenStrain.print("eigenstrain tensor: ");
+          _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,eigenStrain));
+          _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
+        }
+        else if(_eigenField==1)
+        {
+          const STensor3& eigenStress = it->second;
+          Msg::Info("for Cluster %d loading case: %d", clusterI,i);
+          eigenStress.print("eigenstress tensor: ");
+          _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,eigenStress));
+          _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+        }
       }
       else
       {
         _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+        _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
       }
-    };
+    }
     
     static STensor3 Funity(1.);
     solver.getMicroBC()->setDeformationGradient(Funity);
@@ -2511,112 +3786,6 @@ void Clustering::computeInteractionTensorForCluster(nonLinearMechSolver& solver,
           }
         }
       }
-
-
-      for (std::map<int, int>::const_iterator itMatMap = _clusterMaterialMap.begin(); itMatMap != _clusterMaterialMap.end(); itMatMap++)
-      {
-        int clusterJ = itMatMap->first;
-        std::set<int> clusterJIPSet;
-        getCluster(clusterJ,clusterJIPSet);
-        const fullMatrix<double>& DIJval = DJI[std::pair<int,int>(clusterJ,clusterI)];
-        double DIJvariance=0.;
-        static STensor43 DIJvarianceTensor;
-        STensorOperation::zero(DIJvarianceTensor);
-        double& DIJstdev = DJIstd[std::pair<int,int>(clusterJ,clusterI)];
-        DIJstdev = 0.;
-        fullMatrix<double>& DIJSTDMatrix = DJIstdTensor[std::pair<int,int>(clusterJ,clusterI)];
-        if (DIJSTDMatrix.size1() != 6 and DIJSTDMatrix.size2() != 6)
-        {
-          DIJSTDMatrix.resize(6,6,true);
-        }
-        STensor43 DIJSTDTensor;
-        for (std::set<int>::const_iterator it = clusterJIPSet.begin(); it != clusterJIPSet.end(); it++)
-        {
-          int type = *it;
-          int eleNum, gp;
-          numericalMaterialBase::getTwoIntsFromType(type,eleNum,gp);
-          const IPField* ipf = solver.getIPField();
-          const AllIPState::ipstateElementContainer *vips = ipf->getAips()->getIPstate(eleNum);
-          const IPVariable* ipv = (*vips)[gp]->getState(IPStateBase::current);
-          const ipFiniteStrain* ipfinite = static_cast<const ipFiniteStrain*>(ipv);
-          const STensor3& Flocal = ipfinite->getConstRefToDeformationGradient();
-          static STensor3 epsloc;
-          static STensor3 I(1.);
-          for (int ii =0; ii<3; ii++)
-          {
-            for (int jj=0; jj<3; jj++)
-            {
-              epsloc(ii,jj) = 0.5*(Flocal(ii,jj)+Flocal(jj,ii)) - I(ii,jj);
-            }
-          }
-
-          static fullMatrix<double> DIJlocval;
-          if (DIJlocval.size1() != 6 and DIJlocval.size2() != 6)
-          {
-            //Msg::Warning("DIG is not yet allocated");
-            DIJlocval.resize(6,6,true);
-          }
-          if (i == 0 || i==1 || i==2)
-          {
-            DIJlocval(0,i)  = epsloc(0,0)/fact_eig; // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
-            DIJlocval(1,i)  = epsloc(1,1)/fact_eig; // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
-            DIJlocval(3,i)  = epsloc(0,1)/fact_eig; // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
-            if (dim==3)
-            {
-            DIJlocval(2,i)  = epsloc(2,2)/fact_eig; // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
-            DIJlocval(4,i)  = epsloc(0,2)/fact_eig; // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
-            DIJlocval(5,i)  = epsloc(1,2)/fact_eig; // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)    
-            }         
-          }
-          else
-          {
-            DIJlocval(0,i)  = 2.*epsloc(0,0)/fact_eig; // 2A(00) (01 if i==3, 02 if i==4, 12 if i ==5)
-            DIJlocval(1,i)  = 2.*epsloc(1,1)/fact_eig; // 2A(11) (01 if i==3, 02 if i==4, 12 if i ==5)
-            DIJlocval(3,i)  = 2.*epsloc(0,1)/fact_eig; // 2A(01) (01 if i==3, 02 if i==4, 12 if i ==5)
-            if (dim==3)
-            {
-            DIJlocval(2,i)  = 2.*epsloc(2,2)/fact_eig; // 2A(22) (01 if i==3, 02 if i==4, 12 if i ==5)
-            DIJlocval(4,i)  = 2.*epsloc(0,2)/fact_eig; // 2A(02) (01 if i==3, 02 if i==4, 12 if i ==5)
-            DIJlocval(5,i)  = 2.*epsloc(1,2)/fact_eig; // 2A(12) (01 if i==3, 02 if i==4, 12 if i ==5)   
-            }
-          }
-
-          std::map<int, fullVector<double> >::const_iterator itMapGau = _mapGaussPoints.find(type);
-          const fullVector<double>& gpCorr = itMapGau->second;
-
-          const double& totalvolumeCluster = _clusterVolumeMap[clusterJ];
-
-          static STensor43 DIJval43, DIJdiff, DIJdiff_squ;
-          double DIJdiff_norm;
-          STensorOperation::fromFullMatrixToSTensor43(DIJval,DIJval43);
-          STensorOperation::fromFullMatrixToSTensor43(DIJlocval,DIJdiff);
-          DIJdiff -= DIJval43;
-          STensorOperation::contract4STensor43(DIJdiff,DIJdiff,DIJdiff_norm);
-          DIJvariance += gpCorr(3)/totalvolumeCluster*DIJdiff_norm;
-          for(int a=0; a<3; a++){
-            for(int b=0; b<3; b++){
-              for(int c=0; c<3; c++){
-                for(int d=0; d<3; d++){
-                  DIJdiff_squ(a,b,c,d) = DIJdiff(a,b,c,d)*DIJdiff(a,b,c,d);
-                }
-              }
-            }
-          }
-          DIJvarianceTensor += gpCorr(3)/totalvolumeCluster*DIJdiff_squ;
-        }
-        DIJstdev = sqrt(DIJvariance);
-        for(int a=0; a<3; a++){
-          for(int b=0; b<3; b++){
-            for(int c=0; c<3; c++){
-              for(int d=0; d<3; d++){
-                DIJSTDTensor(a,b,c,d) = sqrt(DIJvarianceTensor(a,b,c,d));
-              }
-            }
-          }
-        }
-        STensorOperation::fromSTensor43ToFullMatrix(DIJSTDTensor,DIJSTDMatrix);
-      }
-
       static int num=0;
       num ++;
       //solver.archiveData(num,num,false);
@@ -2628,41 +3797,65 @@ void Clustering::computeInteractionTensorForCluster(nonLinearMechSolver& solver,
 
 void Clustering::computeEshelbyInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJI)
 {
-  int dim = solver.getDim();
-  std::map<int, STensor3> allEigenStrain;
-  double fact_eig = 1.0e-3;
-  strainForLoadingCases(dim,fact_eig,allEigenStrain);
-  for (std::map<int, STensor3>::const_iterator it = allEigenStrain.begin(); it!= allEigenStrain.end(); it++)
+  int dim = solver.getDim();  
+  
+  std::map<int, STensor3> allEigenField;
+  allEigenField.clear();
+  double fact_eig = 0.;
+  if(_eigenField==0)
+  {
+    fact_eig = 1.0e-3;
+    strainForLoadingCases(dim,fact_eig,allEigenField); 
+  }
+  else if(_eigenField==1)
+  {
+    fact_eig = 1.0; 
+    stressForLoadingCases(dim,fact_eig,allEigenField);
+  }
+
+  for (std::map<int, STensor3>::const_iterator it = allEigenField.begin(); it!= allEigenField.end(); it++)
   {    
     int i = it->first;
-    // get eigven strain
-    const STensor3& eigenStrain = it->second;
-    Msg::Info("for Cluster %d loading case: %d", clusterI,i);
-    eigenStrain.print("eigenstrain tensor: ");
-    
-    // init the map
     _allEigenStrains.clear();
+    _allEigenStresses.clear();
+    // get eigen strain/stress for clusters
     for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
     {
       if (clusterI == itMapMat->first)
       {
-        _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,eigenStrain));
+        if(_eigenField==0)
+        {
+          const STensor3& eigenStrain = it->second;
+          Msg::Info("for Cluster %d loading case: %d", clusterI,i);
+          eigenStrain.print("eigenstrain tensor: ");
+          _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,eigenStrain));
+          _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
+        }
+        else if(_eigenField==1)
+        {
+          const STensor3& eigenStress = it->second;
+          Msg::Info("for Cluster %d loading case: %d", clusterI,i);
+          eigenStress.print("eigenstress tensor: ");
+          _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,eigenStress));
+          _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+        }
       }
       else
       {
         _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+        _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
       }
-    };
+    }
    
-      // set tangent averaging flag
+    // set tangent averaging flag
     //solver.tangentAveragingFlag(false);
     // set eigven strain to material law
     // set view name
     // save view
-    std::string filenamPrefix = "disp_eigenStrainModeEshelby_cluster"+std::to_string(clusterI)+"Mode"+std::to_string(i);
-    solver.getUnknownField()->setFileNamePrefix(filenamPrefix);
-    filenamPrefix = "stress_eigenStrainModeEshelby_cluster"+std::to_string(clusterI)+"Mode"+std::to_string(i);
-    solver.getIPField()->setFileNamePrefix(filenamPrefix);
+    //std::string filenamPrefix = "disp_eigenStrainModeEshelby_cluster"+std::to_string(clusterI)+"Mode"+std::to_string(i);
+    //solver.getUnknownField()->setFileNamePrefix(filenamPrefix);
+    //filenamPrefix = "stress_eigenStrainModeEshelby_cluster"+std::to_string(clusterI)+"Mode"+std::to_string(i);
+    //solver.getIPField()->setFileNamePrefix(filenamPrefix);
     
     // solve problem
     static int num=0;
@@ -2728,280 +3921,63 @@ void Clustering::computeEshelbyInteractionTensorForCluster(nonLinearMechSolver&
         }
       }
       solver.oneStepPostSolve((double)num,num);
-    };
-  }
-};
-
-
-void Clustering::setPerturbatedMaterialLaw(int num, materialLaw* pertLaw)
-{
-  // add new law
-  _pertLaw[num] = pertLaw;
-};
-
-void Clustering::computeDAverageStrainConcentrationDLaw(nonLinearMechSolver& solver,
-                                          materialLaw* clusterLaw,
-                                          bool saveToFile, const std::string fileName)
-{
-  std::map<int, std::set<int> > pertClusters;
-  for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
-  {
-    pertClusters[itMapMat->second].insert(itMapMat->first);
-  };
-  
-  for (std::map<int,materialLaw*>::iterator itlaw = _pertLaw.begin(); itlaw != _pertLaw.end(); itlaw ++)
-  {
-    materialLaw* pertLaw = itlaw->second;
-    std::set<int>& pclusters = pertClusters[itlaw->first];
-    for (std::set<int>::iterator itc = pclusters.begin(); itc != pclusters.end(); itc++)
-    {
-      int cl = *itc;
-      Msg::Info("start perturbation with law %d in cluster %d",itlaw->first, cl);
-      std::map<int, int> savedClusterMaterialMap = _clusterMaterialMap;
-      _clusterMaterialMap[cl] = pertLaw->getNum();
-      
-      // create new solver with pert law
-      nonLinearMechSolver* newSolver = solver.clone(solver.getMeshFileName(),solver.getTag());
-      std::vector<partDomain*>& allDom  =  *(newSolver->getDomainVector());
-      std::map<int, materialLaw*>& allLaw = newSolver->getMaplaw();
-      // add more law
-      newSolver->addMaterialLaw(pertLaw);
-      // clone to make sure the law reupdate the pert law
-      newSolver->addMaterialLaw(clusterLaw->clone());
-      for (int i=0; i< allDom.size(); i++)
-      {
-        partDomain* dom  = allDom[i];
-        dom->setMaterialLawNumber(clusterLaw->getNum());
-      }
-      
-      // init solver
-      newSolver->initMicroSolver();
-      
-      // init eigven strain as unity everywhere, no effect when evaluating stress in clusterLaw
-      _allEigenStrains.clear();
-      for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
-      {
-        _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
-      };
-      
-      // estimate the strain concentration tensor locally
-      std::map<int, fullMatrix<double> > PertStrainConcentration; 
-      //
-      int dim = newSolver->getDim();
-      std::map<int, STensor3> allStrain;
-      double fact_BC = 1.0e-4;
-      strainForLoadingCases(dim,fact_BC,allStrain);
-      for (std::map<int, STensor3>::const_iterator it = allStrain.begin(); it!= allStrain.end(); it++)
-      {    
-        int i = it->first;
-        // one can solve consecutively since linear elastic problems are considered
-        const STensor3& F = it->second;
-        Msg::Info("loading case: %d",i);
-        F.print("strain tensor: ");
-        newSolver->getMicroBC()->setDeformationGradient(F);
-          // set tangent averaging flag
-        newSolver->tangentAveragingFlag(false);
-        // solve micro problem
-        //
-        bool success =  newSolver->microSolve();
-        if (!success)
-        {
-          Msg::Error("solver cannot be solved !!!");
-          Msg::Exit(0);
-        }
-        else
-        {
-          // get data from IP field
-          const IPField* ipf = newSolver->getIPField();
-          const AllIPState* aips = ipf->getAips();
-          const std::vector<partDomain*>& domainVector = *(newSolver->getDomainVector());
-          for (int idom=0; idom < domainVector.size(); idom++)
-          {
-            const partDomain* dom = domainVector[idom];
-            const materialLaw* matLaw = dom->getMaterialLaw();
-
-            IntPt* GP;
-            for (elementGroup::elementContainer::const_iterator ite = dom->element_begin(); ite!= dom->element_end(); ite++)
-            {
-              MElement* ele = ite->second;
-              int npts = dom->getBulkGaussIntegrationRule()->getIntPoints(ele,&GP);
-              const AllIPState::ipstateElementContainer *vips = aips->getIPstate(ele->getNum());
-              for (int j=0; j< npts; j++)
-              {
-                // create a unique number of element number and GP number
-                int type = numericalMaterialBase::createTypeWithTwoInts(ele->getNum(),j);
-                
-                // strain at Gauss point
-                const IPVariable* ipv = (*vips)[j]->getState(IPStateBase::current);
-                const ipFiniteStrain* ipvfinite = dynamic_cast<const ipFiniteStrain*>(ipv);
-                const STensor3& Flocal = ipvfinite->getConstRefToDeformationGradient();
-                // small strain measure
-                static STensor3 eps;
-                static STensor3 I(1.);
-                for (int ii =0; ii<3; ii++)
-                {
-                  for (int jj=0; jj<3; jj++)
-                  {
-                    eps(ii,jj) = 0.5*(Flocal(ii,jj)+Flocal(jj,ii)) - I(ii,jj);
-                  }
-                }
-                // save to map
-                if (PertStrainConcentration.find(type) == PertStrainConcentration.end())
-                {
-                  // resize if it not exist before
-                  fullMatrix<double>& matloc = PertStrainConcentration[type];
-                  matloc.resize(6,6,true);
-                }
-                fullMatrix<double>& mat = PertStrainConcentration[type];
-                if( i==allStrain.begin()->first ){unity_Voigt(mat);}
-                if (i == 0 || i==1 || i==2)
-                {
-                  mat(0,i)  = eps(0,0)/fact_BC; // A(00)(00 if i==0, 11 if i==1, 22 if i ==2)
-                  mat(1,i)  = eps(1,1)/fact_BC; // A(11)(00 if i==0, 11 if i==1, 22 if i ==2)
-                  mat(3,i)  = eps(0,1)/fact_BC; // A(01)(00 if i==0, 11 if i==1, 22 if i ==2)
-                  if (dim==3)
-                  {
-                  mat(2,i)  = eps(2,2)/fact_BC; // A(22)(00 if i==0, 11 if i==1, 22 if i ==2)
-                  mat(4,i)  = eps(0,2)/fact_BC; // A(02)(00 if i==0, 11 if i==1, 22 if i ==2)
-                  mat(5,i)  = eps(1,2)/fact_BC; // A(12)(00 if i==0, 11 if i==1, 22 if i ==2)    
-                  }         
-                }
-                else
-                {
-                  // factor 2 for conversion in STensorOperation::fromSTensor43ToFullMatrix
-                  mat(0,i)  = 2.*eps(0,0)/fact_BC; // 2A(00) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  mat(1,i)  = 2.*eps(1,1)/fact_BC; // 2A(11) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  mat(3,i)  = 2.*eps(0,1)/fact_BC; // 2A(01) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  if (dim==3)
-                  {
-                  mat(2,i)  = 2.*eps(2,2)/fact_BC; // 2A(22) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  mat(4,i)  = 2.*eps(0,2)/fact_BC; // 2A(02) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  mat(5,i)  = 2.*eps(1,2)/fact_BC; // 2A(12) (01 if i==3, 02 if i==4, 12 if i ==5)
-                  }
-                }
-              }
-            }
-          }
-        }
-      }    
-      // compute average averageConstrainTensor on each cluster
-      for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
-      {
-        fullMatrix<double> average;
-        average.resize(6,6,true);
-        double volume = 0;
-        
-        std::set<int> cluster;
-        getCluster(itMapMat->first,cluster);
-        for (std::set<int>::const_iterator it = cluster.begin(); it != cluster.end(); it++)
-        {
-          int type = *it;
-          std::map<int, fullVector<double> >::const_iterator itMapGau = _mapGaussPoints.find(type);
-          const fullVector<double>& gpweightCor = itMapGau->second;
-          average.axpy(PertStrainConcentration[type],gpweightCor(3));
-          average.axpy(*(_directMapOfStrainConcentration[type]),-1.*gpweightCor(3));
-          volume += gpweightCor(3);
-        }
-        if (volume > 0.)
-        {
-          average.scale(1./volume);
-        }
-        Msg::Info("cluster %d cluster %d", cl,itMapMat->first);
-        average.print("average");
-        STensorOperation::fromFullMatrixToSTensor43(average,_DclusterAverageStrainConcentrationTensorMapDLaw[std::pair<int,int>(itMapMat->first,cl)]);
-      };
-      
-      Msg::Info("done perturbation with law %d in cluster %d",itlaw->first, cl);
-      // back to previous map
-      _clusterMaterialMap = savedClusterMaterialMap;
-    }
-  };
-  
-  if (saveToFile)
-  {
-    printf("start writing computeDAverageStrainConcentrationDLaw data to file\n");
-    std::vector<std::string> splitFileName = SplitFileName(fileName);
-    std::string saveFileName = splitFileName[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileName[2];
-    
-    FILE* f = fopen(saveFileName.c_str(),"w");
-    std::string str ="CLUSTER_ID CLUSTER_ID";
-    for (int i=0; i<6; i++)
-    {
-      for (int j=0; j<6; j++)
-      {
-        str += " A_"+std::to_string(i)+std::to_string(j);
-      }
-    }
-    fprintf(f,"%s\n",str.c_str());
-    // write data
-    for (std::map<std::pair<int,int>, STensor43>::const_iterator it = _DclusterAverageStrainConcentrationTensorMapDLaw.begin();  it!= _DclusterAverageStrainConcentrationTensorMapDLaw.end(); it++)
-    { 
-      const std::pair<int,int>& pairij = it->first;
-      const STensor43& Dij = it->second;
-      static fullMatrix<double> mat(6,6);
-      STensorOperation::fromSTensor43ToFullMatrix(Dij,mat);
-      fprintf(f,"%d %d",pairij.first, pairij.second);
-      for (int i=0; i<6; i++)
-      {
-        for (int j=0; j<6; j++)
-        {
-          fprintf(f, " %.16g",mat(i,j));
-        }
-      }
-      fprintf(f,"\n");
     }
-    fclose(f);
-    printf("done writing computeDAverageStrainConcentrationDLaw data to file\n");
   }
 };
 
 
 void Clustering::computeInteractionTensor(nonLinearMechSolver& solver,
                                           materialLaw* clusterLaw,
-                                          bool saveToFile, const std::string fileName,
-                                          bool saveInteractionSTDToFile, const std::string InteractionSTDFileName)
+                                          int eigenField,
+                                          bool saveToFile, const std::string fileName)
 {
   nonLinearMechSolver* newSolver = solver.clone(solver.getMeshFileName(),solver.getTag());
   std::vector<partDomain*>& allDom  =  *(newSolver->getDomainVector());
-  newSolver->addMaterialLaw(clusterLaw);
+  newSolver->addMaterialLaw(clusterLaw);  
   for (int i=0; i< allDom.size(); i++)
   {
     partDomain* dom  = allDom[i];
     dom->setMaterialLawNumber(clusterLaw->getNum());
   }
+
+  _eigenField = eigenField;
+  
   // init micro solver
+  
   _allEigenStrains.clear();
+  _allEigenStresses.clear();
   for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
   {
+    if(_eigenField==1)
+    {
+    _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
+    }
+    else if(_eigenField==0)
+    {
     _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+    }
+    else
+    {
+    Msg::Error("this not implemented");
+    }
   };
-  
   newSolver->initMicroSolver();
   
   std::map<std::pair<int,int>, fullMatrix<double> > allDIJMapFullMatrix;
-  std::map<std::pair<int,int>, fullMatrix<double> > allDIJSTDMapFullMatrix;
 
-  _clusterInteractionTensorSTDMap.clear();
   for (std::map<int, int>::const_iterator itMatMap = _clusterMaterialMap.begin(); itMatMap != _clusterMaterialMap.end(); itMatMap++)
   {
     int clusterI = itMatMap->first;
-    computeInteractionTensorForCluster(*newSolver,clusterI,allDIJMapFullMatrix, _clusterInteractionTensorSTDMap, allDIJSTDMapFullMatrix);
+    computeInteractionTensorForCluster(*newSolver,clusterI,allDIJMapFullMatrix);
   };
   
   _clusterInteractionTensorMap.clear();
-  _clusterInteractionSTDTensorMap.clear();
   for (std::map<std::pair<int,int>, fullMatrix<double> >::const_iterator it = allDIJMapFullMatrix.begin(); it!= allDIJMapFullMatrix.end(); it++)
   {
     STensor43 tensor43;
     STensorOperation::fromFullMatrixToSTensor43(it->second,tensor43);
     _clusterInteractionTensorMap[it->first] = tensor43;
   }
-  for (std::map<std::pair<int,int>, fullMatrix<double> >::const_iterator it = allDIJSTDMapFullMatrix.begin(); it!= allDIJSTDMapFullMatrix.end(); it++)
-  {
-    STensor43 tensor43;
-    STensorOperation::fromFullMatrixToSTensor43(it->second,tensor43);
-    _clusterInteractionSTDTensorMap[it->first] = tensor43;
-  }
 
   
   if (saveToFile)
@@ -3027,7 +4003,7 @@ void Clustering::computeInteractionTensor(nonLinearMechSolver& solver,
       const STensor43& Dij = it->second;
       static fullMatrix<double> mat(6,6);
       STensorOperation::fromSTensor43ToFullMatrix(Dij,mat);
-      fprintf(f,"%d %d %.16g",pairij.first, pairij.second,_clusterInteractionTensorSTDMap[std::pair<int,int>(pairij.first,pairij.second)]);
+      fprintf(f,"%d %d %.16g",pairij.first, pairij.second, 0.);
       for (int i=0; i<6; i++)
       {
         for (int j=0; j<6; j++)
@@ -3040,49 +4016,13 @@ void Clustering::computeInteractionTensor(nonLinearMechSolver& solver,
     fclose(f);
     printf("done writing interation tensor data to file\n");
   }
-
-  if (saveInteractionSTDToFile)
-  {
-    printf("start writing interation tensor data to file\n");
-    std::vector<std::string> splitFileNameSTDInteraction = SplitFileName(InteractionSTDFileName);
-    std::string saveFileNameSTDInteraction = splitFileNameSTDInteraction[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileNameSTDInteraction[2];
-    
-    FILE* fstdInteraction = fopen(saveFileNameSTDInteraction.c_str(),"w");
-    std::string strSTDInteraction ="CLUSTER_ID CLUSTER_ID";
-    for (int i=0; i<6; i++)
-    {
-      for (int j=0; j<6; j++)
-      {
-        strSTDInteraction += " STD_D_"+std::to_string(i)+std::to_string(j);
-      }
-    }
-    fprintf(fstdInteraction,"%s\n",strSTDInteraction.c_str());
-    // write data
-    for (std::map<std::pair<int,int>, STensor43>::const_iterator it = _clusterInteractionSTDTensorMap.begin();  it!= _clusterInteractionSTDTensorMap.end(); it++)
-    { 
-      const std::pair<int,int>& pairij = it->first;
-      const STensor43& Dij_std = it->second;
-      static fullMatrix<double> mat(6,6);
-      STensorOperation::fromSTensor43ToFullMatrix(Dij_std,mat);
-      fprintf(fstdInteraction,"%d %d",pairij.first, pairij.second);
-      for (int i=0; i<6; i++)
-      {
-        for (int j=0; j<6; j++)
-        {
-          fprintf(fstdInteraction, " %.16g",mat(i,j));
-        }
-      }
-      fprintf(fstdInteraction,"\n");
-    }
-    fclose(fstdInteraction);
-    printf("done writing interation tensor data to file\n");
-  }
 };
 
 
 void Clustering::computeEshelbyInteractionTensor(nonLinearMechSolver& solver,
                                           materialLaw* clusterLaw,
-                                          bool saveToFileEshelby, const std::string fileNameEshelby)
+                                          int eigenField,
+                                          bool saveToFile, const std::string fileName)
 {
   nonLinearMechSolver* newSolver = solver.clone(solver.getMeshFileName(),solver.getTag());
   std::vector<partDomain*>& allDom  =  *(newSolver->getDomainVector());
@@ -3093,11 +4033,24 @@ void Clustering::computeEshelbyInteractionTensor(nonLinearMechSolver& solver,
     dom->setMaterialLawNumber(clusterLaw->getNum());
   }
   
+  _eigenField = eigenField;
   
   _allEigenStrains.clear();
+  _allEigenStresses.clear();
   for (std::map<int, int>::const_iterator itMapMat = _clusterMaterialMap.begin(); itMapMat != _clusterMaterialMap.end(); itMapMat++)
   {
+    if(_eigenField==1)
+    {
+    _allEigenStresses.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(0.)));
+    }
+    else if(_eigenField==0)
+    {
     _allEigenStrains.insert(std::pair<int,STensor3>(itMapMat->first,STensor3(1.)));
+    }
+    else
+    {
+    Msg::Error("this not implemented");
+    }
   };
   
   // init solver
@@ -3119,14 +4072,14 @@ void Clustering::computeEshelbyInteractionTensor(nonLinearMechSolver& solver,
     _clusterEshelbyInteractionTensorMap[it->first] = tensor43;
   }
 
-  if (saveToFileEshelby)
+  if (saveToFile)
   {
     printf("start writing eshelby interation tensor data to file\n");
-    std::vector<std::string> splitFileNameEshelby = SplitFileName(fileNameEshelby);
-    std::string saveFileNameEshelby = splitFileNameEshelby[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileNameEshelby[2];
+    std::vector<std::string> splitFileNameEshelby = SplitFileName(fileName);
+    std::string saveFileName = splitFileNameEshelby[1]+"_nbClusters_"+std::to_string(_totalNumberOfClusters)+splitFileNameEshelby[2];
     
-    FILE* fEshelby = fopen(saveFileNameEshelby.c_str(),"w");
-    std::string str ="CLUSTER_ID CLUSTER_ID STD";
+    FILE* fEshelby = fopen(saveFileName.c_str(),"w");
+    std::string str ="CLUSTER_ID CLUSTER_ID";
     for (int i=0; i<6; i++)
     {
       for (int j=0; j<6; j++)
@@ -3142,7 +4095,7 @@ void Clustering::computeEshelbyInteractionTensor(nonLinearMechSolver& solver,
       const STensor43& DijEshelby = it->second;
       static fullMatrix<double> mat(6,6);
       STensorOperation::fromSTensor43ToFullMatrix(DijEshelby,mat);
-      fprintf(fEshelby,"%d %d %.16g",pairij.first, pairij.second);
+      fprintf(fEshelby,"%d %d",pairij.first, pairij.second);
       for (int i=0; i<6; i++)
       {
         for (int j=0; j<6; j++)
@@ -3191,8 +4144,8 @@ void Clustering::loadInteractionTensorsFromFile(const std::string fileName)
       if(feof(fp))
         break;
       int clusterI(0), clusterJ(0);
-      double DIJstdev(0.);
-      if (fscanf(fp, "%d %d %lf", &clusterI,&clusterJ,&DIJstdev)==3)
+      double a;
+      if (fscanf(fp, "%d %d %lf", &clusterI,&clusterJ,&a)==3)
       {
         static fullMatrix<double> matTensor(6,6);
         for (int i=0; i<6; i++)
@@ -3210,7 +4163,6 @@ void Clustering::loadInteractionTensorsFromFile(const std::string fileName)
           //matTensor.print("matTensor");
           STensor43& T = _clusterInteractionTensorMap[std::pair<int,int>(clusterI,clusterJ)];
           STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
-          _clusterInteractionTensorSTDMap[std::pair<int,int>(clusterI,clusterJ)] = DIJstdev;
         }
       }
     }
@@ -3239,8 +4191,6 @@ void Clustering::loadEshelbyInteractionTensorsFromFile(const std::string fileNam
       printf("what = %s\n",what);
       fscanf(fp, "%s", what);
       printf("what = %s\n",what);
-      fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
 
       for (int i=0; i<6; i++)
       {
@@ -3412,75 +4362,9 @@ void Clustering::loadInteractionTensorsHomogenizedFrameELFromFile(const std::str
         }
         if (clusterI >=0 && clusterJ>=0)
         {
-          printf("load data interaction %d %d \n",clusterI,clusterJ);
-          matTensor.print("matTensor");
-          STensor43& T = _clusterInteractionTensorHomogenizedFrameELMap[std::pair<int,int>(clusterI,clusterJ)];
-          STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
-        }
-      }
-    }
-    printf("done reading file: %s\n",fileName.c_str());
-    fclose(fp);
-    
-    _totalNumberOfClusters = (int)(sqrt(_clusterInteractionTensorHomogenizedFrameELMap.size())-1);
-    printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
-  }
-  else
-  {
-    Msg::Error("File %s does not exist !!!",fileName.c_str());
-    Msg::Exit(0);
-  }
-}
-
-
-void Clustering::loadInteractionStandDevFromFile(const std::string fileName)
-{
-  FILE* fp = fopen(fileName.c_str(),"r");
-  if (fp !=NULL) {
-    printf("start reading file: %s\n",fileName.c_str());
-    if(!feof(fp))
-    {
-      char what[256];
-      fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-      fscanf(fp, "%s", what);
-      printf("what = %s\n",what);
-
-      for (int i=0; i<6; i++)
-      {
-        for (int j=0; j<6; j++)
-        {
-          fscanf(fp, "%s", what);
-          printf("what = %s\n",what);
-        }
-      }
-      if(strcmp(what, "STD_D_55"))
-      {
-        Msg::Error("file format in %s is not correct\n",fileName.c_str());
-        Msg::Exit(0);
-      }
-    }
-    while (1){
-      if(feof(fp))
-        break;
-      int clusterI(0), clusterJ(0);
-      if (fscanf(fp, "%d %d", &clusterI,&clusterJ)==2)
-      {
-        static fullMatrix<double> matTensor(6,6);
-        for (int i=0; i<6; i++)
-        {
-          for (int j=0; j<6; j++)
-          {
-            double val=0;
-            if (fscanf(fp,"%lf",&val)==1)
-              matTensor(i,j) = val;
-          }
-        }
-        if (clusterI >=0 && clusterJ>=0)
-        {
-          printf("load interaction standdev %d %d \n",clusterI,clusterJ);
-          matTensor.print("matTensor");
-          STensor43& T = _clusterInteractionSTDTensorMap[std::pair<int,int>(clusterI,clusterJ)];
+          printf("load data interaction %d %d \n",clusterI,clusterJ);
+          //matTensor.print("matTensor");
+          STensor43& T = _clusterInteractionTensorHomogenizedFrameELMap[std::pair<int,int>(clusterI,clusterJ)];
           STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
         }
       }
@@ -3488,8 +4372,10 @@ void Clustering::loadInteractionStandDevFromFile(const std::string fileName)
     printf("done reading file: %s\n",fileName.c_str());
     fclose(fp);
     
-    //_totalNumberOfClusters = (int)(sqrt(_clusterInteractionSTDTensorMap.size()));
-    //printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
+    //std::map<std::pair<int,int>,STensor43>::const_iterator Dfind = getClusterInteractionTensorMap().find(std::pair<int,int>(0,0));
+    
+    _totalNumberOfClusters = (int)(sqrt(_clusterInteractionTensorHomogenizedFrameELMap.size())-1);
+    printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
   }
   else
   {
@@ -3499,7 +4385,7 @@ void Clustering::loadInteractionStandDevFromFile(const std::string fileName)
 }
 
 
-void Clustering::loadEshelbyInteractionStandDevFromFile(const std::string fileName)
+void Clustering::loadInteractionTensorIsoFromFile(const std::string fileName)
 {
   FILE* fp = fopen(fileName.c_str(),"r");
   if (fp !=NULL) {
@@ -3511,6 +4397,8 @@ void Clustering::loadEshelbyInteractionStandDevFromFile(const std::string fileNa
       printf("what = %s\n",what);
       fscanf(fp, "%s", what);
       printf("what = %s\n",what);
+      fscanf(fp, "%s", what);
+      printf("what = %s\n",what);
 
       for (int i=0; i<6; i++)
       {
@@ -3520,7 +4408,7 @@ void Clustering::loadEshelbyInteractionStandDevFromFile(const std::string fileNa
           printf("what = %s\n",what);
         }
       }
-      if(strcmp(what, "STD_D_55"))
+      if(strcmp(what, "D_55"))
       {
         Msg::Error("file format in %s is not correct\n",fileName.c_str());
         Msg::Exit(0);
@@ -3530,7 +4418,8 @@ void Clustering::loadEshelbyInteractionStandDevFromFile(const std::string fileNa
       if(feof(fp))
         break;
       int clusterI(0), clusterJ(0);
-      if (fscanf(fp, "%d %d", &clusterI,&clusterJ)==2)
+      double a;
+      if (fscanf(fp, "%d %d %lf", &clusterI,&clusterJ,&a)==3)
       {
         static fullMatrix<double> matTensor(6,6);
         for (int i=0; i<6; i++)
@@ -3544,15 +4433,16 @@ void Clustering::loadEshelbyInteractionStandDevFromFile(const std::string fileNa
         }
         if (clusterI >=0 && clusterJ>=0)
         {
-          printf("load interaction standdev %d %d \n",clusterI,clusterJ);
-          matTensor.print("matTensor");
-          STensor43& T = _clusterEshelbyInteractionSTDTensorMap[std::pair<int,int>(clusterI,clusterJ)];
+          STensor43& T = _clusterInteractionTensorIsoMap[std::pair<int,int>(clusterI,clusterJ)];
           STensorOperation::fromFullMatrixToSTensor43(matTensor,T);
         }
       }
     }
     printf("done reading file: %s\n",fileName.c_str());
     fclose(fp);
+    
+    _totalNumberOfClusters = (int)(sqrt(_clusterInteractionTensorIsoMap.size()));
+    printf("total number of cluster from file %s = %d\n",fileName.c_str(),_totalNumberOfClusters);
   }
   else
   {
@@ -3685,6 +4575,10 @@ double viewClustering::get(int eleNum, const int cmp, const int gp)const
   static fullMatrix<double> A;
   A.resize(6,6,true);
   double clusterIndex = 0;
+  
+  //static fullVector<double> pfc;
+  //pfc.resize(6,true);
+  
   int npts = _clustering.getNbOfGPsOnElement(eleNum);
   if (gp == -1)
   {
@@ -3695,10 +4589,16 @@ double viewClustering::get(int eleNum, const int cmp, const int gp)const
       int clusterIndex_i = _clustering.getClusterIndex(eleNum,i);
       A += A_i;
       clusterIndex += clusterIndex_i;      
+      //const fullVector<double>& pfc_i = _clustering.getPFC(eleNum,i);
+      //for(int h=0;h<6;h++)
+      //{
+        //pfc(h) += pfc_i(h);
+      //}
     }
     double fact = 1./double(npts);
     A.scale(fact);
     clusterIndex *= (fact);
+    //pfc.scale(fact);
   }
   else if (gp >= npts)
   {
@@ -3764,6 +4664,12 @@ double viewClustering::get(int eleNum, const int cmp, const int gp)const
   {
     return clusterIndex;
   }
+  /*else if (cmp == Clustering::PFC_0) return pfc(0);
+  else if (cmp == Clustering::PFC_1) return pfc(1);
+  else if (cmp == Clustering::PFC_2) return pfc(2);
+  else if (cmp == Clustering::PFC_3) return pfc(3);
+  else if (cmp == Clustering::PFC_4) return pfc(4);
+  else if (cmp == Clustering::PFC_5) return pfc(5);*/
   else
   {
     Msg::Error("field %d does not exist !!!",cmp);
@@ -3804,9 +4710,39 @@ double clutering_impls::getDiffNormVec(const fullVector<double>&a, const fullVec
 double clutering_impls::getDiffNormVecLong(const fullVector<double>&a, const fullVector<double>&b)
 {
   double val = 0;
-  for (int i=0; i< 12; i++)
+  for (int i=0; i< 6; i++)
+  {
+    for (int j=0; j< 6; j++)
+    {
+      val += 1.*(a(i*6+j)-b(i*6+j))*(a(i*6+j)-b(i*6+j));
+    }
+  }
+  return sqrt(val);
+};
+
+double clutering_impls::getDiffNormVecPowerLong(const fullVector<double>&a, const fullVector<double>&b)
+{
+  double val = 0;
+  double exp = 2.;
+  for (int i=0; i< 6; i++)
+  {
+    for (int j=0; j< 6; j++)
+    {
+      val += 1.*(pow(a(i*6+j),exp)-pow(b(i*6+j),exp))*(pow(a(i*6+j),exp)-pow(b(i*6+j),exp));
+    }
+  }
+  return sqrt(val);
+};
+
+double clutering_impls::getDiffShearNormVecLong(const fullVector<double>&a, const fullVector<double>&b)
+{
+  double val = 0;
+  for (int i=0; i< 6; i++)
   {
-    val += 1.*(a(i)-b(i))*(a(i)-b(i));
+    for (int j=0; j< 6; j++)
+    {
+      if(j==2 or j==4 or j==5){val += 1.*(a(i*6+j)-b(i*6+j))*(a(i*6+j)-b(i*6+j));}
+    }
   }
   return sqrt(val);
 };
@@ -3879,6 +4815,42 @@ void clutering_impls::meanClusterVec_FullMatrixBased(const std::map<int, fullVec
   //return totalWeight;
 }
 
+void clutering_impls::meanClusterVecLong_FullMatrixBased(const std::map<int, fullVector<double> >& dataVec,
+                                                       const std::map<int, const fullMatrix<double>* >& cluster,
+                                                       const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                                       fullVector<double>& mean)
+{
+  mean.resize(36,true);
+  double totalWeight = 0;
+  int n = cluster.size();
+  if (n > 0)
+  {
+    for (std::map<int, const fullMatrix<double>* >::const_iterator its = cluster.begin(); its != cluster.end(); its ++)
+    {
+      std::map<int, fullVector<double> >::const_iterator itFind = mapPositionsWeights.find(its->first);
+      std::map<int, fullVector<double> >::const_iterator itVec = dataVec.find(its->first);
+      const fullVector<double>& Vec = itVec->second;
+      //Vec.print("UUUUU");
+      if (itFind==mapPositionsWeights.end())
+      {
+        printf("wrong map of Gauss poing as GP %d is not found in this map",its->first);
+      }
+      else
+      {
+        const fullVector<double>& gpCorr = itFind->second;
+        totalWeight += gpCorr(3);
+        mean.axpy(Vec, gpCorr(3));
+      }
+    }
+    mean.scale(1./totalWeight);    
+  }
+  else
+  {
+    Msg::Error("empty cluster is found");
+  }
+  //return totalWeight;
+}
+
 double clutering_impls::meanClusterVec(const std::map<int, const fullVector<double>* >& cluster,
                             const std::map<int, fullVector<double> >& mapPositionsWeights,
                             fullVector<double>& mean)
@@ -3915,7 +4887,7 @@ double clutering_impls::meanClusterVecLong(const std::map<int, const fullVector<
                             const std::map<int, fullVector<double> >& mapPositionsWeights,
                             fullVector<double>& mean)
 {
-  mean.resize(12,true);
+  mean.resize(36,true);
   double totalWeight = 0;
   int n = cluster.size();
   if (n > 0)
@@ -3943,6 +4915,120 @@ double clutering_impls::meanClusterVecLong(const std::map<int, const fullVector<
   return totalWeight;
 }
 
+void clutering_impls::meanClusterPosition(const std::map<int, const fullMatrix<double>* >& cluster,
+                            const std::map<int, fullVector<double> >& mapPositionsWeights,
+                            double& x_mean, double& y_mean, double& z_mean)
+{
+  double totalWeight = 0;
+  int n = cluster.size();
+  if (n > 0)
+  {
+    for (std::map<int, const fullMatrix<double>* >::const_iterator its = cluster.begin(); its != cluster.end(); its ++)
+    {
+      std::map<int, fullVector<double> >::const_iterator itFind = mapPositionsWeights.find(its->first);
+      if (itFind==mapPositionsWeights.end())
+      {
+        printf("wrong map of Gauss poing as GP %d is not found in this map",its->first);
+      }
+      else
+      {
+        const fullVector<double>& gpCorr = itFind->second;
+        totalWeight += gpCorr(3);
+        x_mean += gpCorr(0)*gpCorr(3);
+        y_mean += gpCorr(1)*gpCorr(3);
+        z_mean += gpCorr(2)*gpCorr(3);
+      }
+    }
+    x_mean *= (1./totalWeight);    
+    y_mean *= (1./totalWeight);      
+    z_mean *= (1./totalWeight);  
+  }
+  else
+  {
+    Msg::Error("empty cluster is found");
+  }
+}
+
+void clutering_impls::meanClusterFiberOrientation(const std::map<int, const fullMatrix<double>* >& cluster,
+                                                  const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                                  const std::map<int, fullVector<double> >& mapLocalFiberOrientations,
+                                                  double& E1_mean, double& E2_mean, double& E3_mean)
+{
+  double totalWeight = 0;
+  int n = cluster.size();
+  
+  double sinE1_mean, sinE2_mean, sinE3_mean, cosE1_mean, cosE2_mean, cosE3_mean;
+  
+  double PI = 3.14159265;
+  
+  if (n > 0)
+  {
+    for (std::map<int, const fullMatrix<double>* >::const_iterator its = cluster.begin(); its != cluster.end(); its ++)
+    {
+      std::map<int, fullVector<double> >::const_iterator itFind = mapPositionsWeights.find(its->first);
+      std::map<int, fullVector<double> >::const_iterator itLocOri = mapLocalFiberOrientations.find(its->first);
+      if (itFind==mapPositionsWeights.end())
+      {
+        printf("wrong map of Gauss poing as GP %d is not found in this map",its->first);
+      }
+      else
+      {
+        const fullVector<double>& gpCorr = itFind->second;
+        const fullVector<double>& locOri = itLocOri->second;
+        totalWeight += gpCorr(3);
+        
+        double e1,e2,e3;
+        e1 = locOri(0);
+        e2 = locOri(1);
+        e3 = locOri(2);        
+        if(locOri(0)<0.)
+        {
+          e1 += 180.;
+        }        
+        if(locOri(1)<0.)
+        {
+          e2 += 180.;
+        }        
+        if(locOri(2)<0.)
+        {
+          e3 += 180.;
+        }
+        
+        double sinE1, sinE2, sinE3, cosE1, cosE2, cosE3;
+        sinE1 = sin(e1*PI/180.);
+        cosE1 = cos(e1*PI/180.);
+        sinE2 = sin(e2*PI/180.);
+        cosE2 = cos(e2*PI/180.);
+        sinE3 = sin(e3*PI/180.);
+        cosE3 = cos(e3*PI/180.);
+        
+        sinE1_mean += sinE1*gpCorr(3);
+        cosE1_mean += cosE1*gpCorr(3);
+        sinE2_mean += sinE2*gpCorr(3);
+        cosE2_mean += cosE2*gpCorr(3);
+        sinE3_mean += sinE3*gpCorr(3);        
+        cosE3_mean += cosE3*gpCorr(3);        
+      }
+    }
+    
+    sinE1_mean *= (1./totalWeight);
+    sinE2_mean *= (1./totalWeight);
+    sinE3_mean *= (1./totalWeight);
+    
+    cosE1_mean *= (1./totalWeight);
+    cosE2_mean *= (1./totalWeight);
+    cosE3_mean *= (1./totalWeight);
+    
+    E1_mean = atan2(sinE1_mean,cosE1_mean)*180./PI;
+    E2_mean = atan2(sinE2_mean,cosE2_mean)*180./PI;
+    E3_mean = atan2(sinE3_mean,cosE3_mean)*180./PI;
+  }
+  else
+  {
+    Msg::Error("empty cluster is found");
+  }
+}
+
 void clutering_impls::meanGeometricClusterVec(const std::map<int, const fullVector<double>* >& cluster,
                                               const std::map<int, fullVector<double> >& mapPositionsWeights,
                                               fullVector<double>& mean)
@@ -4124,6 +5210,51 @@ void clutering_impls::meanGeometricClusterVec_FullMatrixBased(const std::map<int
 }
 
 
+void clutering_impls::meanPowerClusterVec_FullMatrixBased(const std::map<int, fullVector<double> >& dataVec,
+                                             const std::map<int, const fullMatrix<double>* >& cluster,
+                                             const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                             fullVector<double>& mean)
+{
+  mean.resize(6,true);
+  double totalWeight = 0;
+  int n = cluster.size();
+  fullVector<double> meanPower(6);
+  fullVector<double> plastEqLoc(6);
+  double exponent = 2.;
+  double val;
+  if (n > 0)
+  {
+    for (std::map<int, const fullMatrix<double>* >::const_iterator its = cluster.begin(); its != cluster.end(); its ++)
+    {
+      std::map<int, fullVector<double> >::const_iterator itFind = mapPositionsWeights.find(its->first);
+      std::map<int, fullVector<double> >::const_iterator itVec = dataVec.find(its->first);
+      const fullVector<double>& Vec = itVec->second;
+      if (itFind==mapPositionsWeights.end())
+      {
+        printf("wrong map of Gauss poing as GP %d is not found in this map",its->first);
+      }
+      else
+      {
+        const fullVector<double>& gpCorr = itFind->second;
+        totalWeight += gpCorr(3);
+        for(int i=0; i<6; i++)
+        {
+          meanPower(i) += pow(Vec(i),exponent)*gpCorr(3);
+        }
+      }
+    }
+    meanPower.scale(1./totalWeight);
+    for(int i=0; i<6; i++)
+    {
+      mean(i) = pow(meanPower(i),1./exponent);
+    } 
+  }
+  else
+  {
+    Msg::Error("empty cluster is found");
+  }
+}
+
 void clutering_impls::Tensor43STDScalarCluster(const std::map<int, const fullMatrix<double>* >& cluster, 
                        const std::map<int, fullVector<double> >& mapPositionsWeights,
                        const STensor43& AmeanCluster,
@@ -4157,6 +5288,7 @@ void clutering_impls::Tensor43STDScalarCluster(const std::map<int, const fullMat
   }
   clusterVariance *= 1./totalWeight;
   clusterStdev = sqrt(clusterVariance);
+  clusterStdev *= 1./clusterNorm;
 }
 
 
@@ -4210,7 +5342,7 @@ void clutering_impls::VectorSTDCluster(const std::map<int, const fullVector<doub
                        fullVector<double> &clusterSTDVector)
 {
   double totalWeight = 0.;
-  fullVector<double> clusterVar_vector(6);
+  fullVector<double> clusterVar_vector(36);
   double val_diff_squ;
   int n = cluster.size();
   for (std::map<int, const fullVector<double>* >::const_iterator its = cluster.begin(); its != cluster.end(); its ++)
@@ -4222,11 +5354,11 @@ void clutering_impls::VectorSTDCluster(const std::map<int, const fullVector<doub
     }
     else
     {
-      fullVector<double> vec_loc(6);
+      fullVector<double> vec_loc(36);
       vec_loc = *its->second;
       const fullVector<double>& gpCorr = itFind->second;
       totalWeight += gpCorr(3);
-      for(int i=0; i<6; i++){
+      for(int i=0; i<36; i++){
         val_diff_squ = (vec_loc(i)-VecmeanCluster(i))*(vec_loc(i)-VecmeanCluster(i));
         clusterVar_vector(i) += (gpCorr(3)*val_diff_squ);
       }
@@ -4265,6 +5397,40 @@ int clutering_impls::maxConcentrationCluster(const std::map<int, const fullMatri
   return maxIP;
 };
 
+int clutering_impls::maxConcentrationVecCluster(const std::map<int, const fullVector<double>* >& cluster)
+{
+  int maxIP = -1;
+  double maxVal = -1.;
+  for (std::map<int, const fullVector<double>* >::const_iterator it = cluster.begin(); it != cluster.end(); it++)
+  {
+    const fullVector<double>* A = it->second;
+    double Anorm = A->norm();
+    if (Anorm > maxVal)
+    {
+      maxIP = it->first;
+      maxVal = Anorm;
+    }
+  }
+  return maxIP;
+};
+
+int clutering_impls::minConcentrationVecCluster(const std::map<int, const fullVector<double>* >& cluster)
+{
+  int minIP = -1;
+  double minVal = 10e6;
+  for (std::map<int, const fullVector<double>* >::const_iterator it = cluster.begin(); it != cluster.end(); it++)
+  {
+    const fullVector<double>* A = it->second;
+    double Anorm = A->norm();
+    if (Anorm < minVal)
+    {
+      minIP = it->first;
+      minVal = Anorm;
+    }
+  }
+  return minIP;
+};
+
 
 void clutering_impls::printClusters(const std::map<int, std::map<int, const fullMatrix<double>* > >& clusters)
 {
@@ -4326,6 +5492,8 @@ int clutering_impls::getNearestClusterIdVecLong(const std::map<int, fullVector<d
   {
     int newClusterIndex = it->first;
     double newDist = clutering_impls::getDiffNormVecLong(pt,it->second);
+    //double newDist = clutering_impls::getDiffShearNormVecLong(pt,it->second);
+    //double newDist = clutering_impls::getDiffNormVecPowerLong(pt,it->second);
     if (clusterIndex <0 or newDist<dist)
     {
       dist = newDist;
@@ -4599,7 +5767,7 @@ bool clutering_impls::kmean_cluster_FullVectorBased(const std::map<int, fullVect
 }
 
 
-void clutering_impls::vecNormalized(const std::map<int, fullVector<double> >& dataVec,
+void clutering_impls::vecNormalizeByOverallValue(const std::map<int, fullVector<double> >& dataVec,
                                     const std::map<int, fullVector<double> >& mapPositionsWeights,
                                     std::map<int, fullVector<double> >& dataVecNormalized)
 {
@@ -4645,13 +5813,13 @@ void clutering_impls::vecNormalized(const std::map<int, fullVector<double> >& da
   }
 }
 
-void clutering_impls::vecNormalizedByNorm(const std::map<int, fullVector<double> >& dataVec,
+void clutering_impls::vecNormalizeByOverallNorm(const std::map<int, fullVector<double> >& dataVec,
                                           const std::map<int, fullVector<double> >& mapPositionsWeights,
                                           std::map<int, fullVector<double> >& dataVecNormalized)
 {
   //std::map<int, fullVector<double> >::const_iterator dataVec0 = dataVec.find(0);
   //int nb = (dataVec0->second).size();
-  int nb = 12;
+  int nb = 36;
   fullVector<double> mean(nb);
   int nb_Norm = nb/6;
   fullVector<double> meanNorm(nb_Norm);
@@ -4674,13 +5842,11 @@ void clutering_impls::vecNormalizedByNorm(const std::map<int, fullVector<double>
       }
     }
     mean.scale(1./totalWeight);
-    //mean.print("YYYY");
     for(int i=0; i<nb_Norm; i++)
     {
       //meanNorm(i) = sqrt(mean(i*6+0)*mean(i*6+0)+mean(i*6+1)*mean(i*6+1)+mean(i*6+2)*mean(i*6+2)+2.*mean(i*6+3)*mean(i*6+3)+2.*mean(i*6+4)*mean(i*6+4)+2.*mean(i*6+5)*mean(i*6+5));
       meanNorm(i) = sqrt(mean(i*6+0)*mean(i*6+0)+mean(i*6+1)*mean(i*6+1)+mean(i*6+2)*mean(i*6+2));
     }
-    //meanNorm.print("TTTT");
     
     for (std::map<int, fullVector<double> >::const_iterator its = dataVec.begin(); its != dataVec.end(); its ++)
     {  
@@ -4698,7 +5864,43 @@ void clutering_impls::vecNormalizedByNorm(const std::map<int, fullVector<double>
           else if(i>=18 and i<24)
             {vecLocnormalized(i) = vecLoc(i)/meanNorm(3);}
           else if(i>=24 and i<30)
-            {vecLocnormalized(i) = vecLoc(i)/meanNorm(4);}      
+            {vecLocnormalized(i) = vecLoc(i)/meanNorm(4);}   
+          else if(i>=30 and i<36)
+            {vecLocnormalized(i) = vecLoc(i)/meanNorm(5);}      
+        }
+      }
+      dataVecNormalized[its->first] = vecLocnormalized;
+    }
+  }
+  else
+  {
+    Msg::Error("empty vector is found");
+  }
+}
+
+void clutering_impls::vecNormalizeByLocalNorm(const std::map<int, fullVector<double> >& dataVec,
+                                              std::map<int, fullVector<double> >& dataVecNormalized)
+{
+  int nb = 36;
+  int nb_Norm = nb/6;
+  int n = dataVec.size();
+  if (n > 0)
+  {   
+    for (std::map<int, fullVector<double> >::const_iterator its = dataVec.begin(); its != dataVec.end(); its ++)
+    {
+      fullVector<double> vecLocnormalized(nb);
+      const fullVector<double> &vecLoc = its->second;
+      for(int i=0; i<nb_Norm; i++)
+      { 
+        double normLoc = 0.;
+        normLoc = sqrt(vecLoc(6*i+0)*vecLoc(6*i+0)+vecLoc(6*i+1)*vecLoc(6*i+1)+vecLoc(6*i+2)*vecLoc(6*i+2));
+        if(normLoc!=0.){
+          vecLocnormalized(6*i+0) = vecLoc(6*i+0)/normLoc;
+          vecLocnormalized(6*i+1) = vecLoc(6*i+1)/normLoc;
+          vecLocnormalized(6*i+2) = vecLoc(6*i+2)/normLoc;
+          vecLocnormalized(6*i+3) = vecLoc(6*i+3)/normLoc;
+          vecLocnormalized(6*i+4) = vecLoc(6*i+4)/normLoc;
+          vecLocnormalized(6*i+5) = vecLoc(6*i+5)/normLoc;
         }
       }
       dataVecNormalized[its->first] = vecLocnormalized;
@@ -4710,4 +5912,74 @@ void clutering_impls::vecNormalizedByNorm(const std::map<int, fullVector<double>
   }
 }
 
+void clutering_impls::vecSeparate(const std::map<int, fullVector<double> >& dataVec,
+                                              std::map<int, fullVector<double> >& dataVecSeparated)
+{
+  int nb = 36;
+  int nb_Norm = nb/6;
+  int n = dataVec.size();
+  if (n > 0)
+  {   
+    for (std::map<int, fullVector<double> >::const_iterator its = dataVec.begin(); its != dataVec.end(); its ++)
+    {
+      fullVector<double> vecLocSeparated(36);
+      const fullVector<double> &vecLoc = its->second;
+      for(int i=0; i<nb_Norm; i++)
+      { 
+        double normLoc = 0.;
+        normLoc = sqrt(vecLoc(6*i+0)*vecLoc(6*i+0)+vecLoc(6*i+1)*vecLoc(6*i+1)+vecLoc(6*i+2)*vecLoc(6*i+2));
+        if(normLoc!=0.){
+          vecLocSeparated(6*i+0) = vecLoc(6*i+0)/normLoc;
+          vecLocSeparated(6*i+1) = vecLoc(6*i+1)/normLoc;
+          vecLocSeparated(6*i+2) = vecLoc(6*i+2)/normLoc;
+          vecLocSeparated(6*i+3) = vecLoc(6*i+3)/normLoc;
+          vecLocSeparated(6*i+4) = vecLoc(6*i+4)/normLoc;
+          vecLocSeparated(6*i+5) = vecLoc(6*i+5)/normLoc;
+        }
+        vecLocSeparated(6*i+5) = 6.*normLoc;
+      }
+      dataVecSeparated[its->first] = vecLocSeparated;
+    }
+  }
+  else
+  {
+    Msg::Error("empty vector is found");
+  }
+}
+
+void clutering_impls::vecRatio(const std::map<int, fullVector<double> >& dataVecNumerator,
+                               const std::map<int, fullVector<double> >& dataVecDenominator,
+                               std::map<int, fullVector<double> >& dataVecRatio)
+{
+  int nb = 6;
+  double totalWeight = 0;
+  int n = dataVecNumerator.size();
+  if (n > 0)
+  {
+    for (std::map<int, fullVector<double> >::const_iterator its = dataVecNumerator.begin(); its != dataVecNumerator.end(); its ++)
+    {
+      std::map<int, fullVector<double> >::const_iterator itFind = dataVecDenominator.find(its->first);
+      if (itFind==dataVecDenominator.end())
+      {
+        printf("wrong map of Gauss points as GP %d is not found in this map",its->first);
+      }
+      else
+      {
+        fullVector<double> dataVecRatioLoc(nb);
+        for(int i=0; i<nb; i++)
+        {
+          const fullVector<double>& numeratorLoc = its->second;
+          const fullVector<double>& denominatorLoc = itFind->second;
+          dataVecRatioLoc(i) = numeratorLoc(i)/denominatorLoc(i);
+        }
+        dataVecRatio[its->first] = dataVecRatioLoc;
+      }
+    }
+  }
+  else
+  {
+    Msg::Error("empty vector is found");
+  }
+}
+
 
diff --git a/NonLinearSolver/modelReduction/Clustering.h b/NonLinearSolver/modelReduction/Clustering.h
index ebd9b28bd69fcc9e3224a3c667f0a3156f7aa47c..c8d011da8d2794b7c41b51907ebbd37651ec4df4 100644
--- a/NonLinearSolver/modelReduction/Clustering.h
+++ b/NonLinearSolver/modelReduction/Clustering.h
@@ -33,7 +33,7 @@ class Clustering
                  A_30, A_31, A_32, A_33, A_34, A_35,
                  A_40, A_41, A_42, A_43, A_44, A_45,
                  A_50, A_51, A_52, A_53, A_54, A_55,
-                 A_norm, ClusterIndex};
+                 A_norm, ClusterIndex, PFC_0, PFC_1, PFC_2, PFC_3, PFC_4, PFC_5};
     static std::string ToString(const int i);
   protected:
     #ifndef SWIG
@@ -45,21 +45,28 @@ class Clustering
     std::map<int, std::map<int, fullMatrix<double> > > _concentrationTensorMap; 
     std::map<int, std::map<int, fullVector<double> > > _plasticStrainConcentrationVectorMap;
     std::map<int, std::map<int, fullVector<double> > > _plasticStrainConcentrationNormalizedVectorMap;
-    std::map<int, std::map<int, fullVector<double> > > _sigEPConcentrationVectorMap; 
-    std::map<int, std::map<int, fullVector<double> > > _sigEPConcentrationNormalizedVectorMap; 
+    std::map<int, std::map<int, fullVector<double> > > _plasticFlowDirConcentrationVectorMap;
+    
+    std::map<int, std::map<int, fullVector<double> > > _inelasticStrainConcentrationSeparatedVectorMap;
+    
+    std::map<int, std::map<int, fullVector<double> > > _inelasticStrainConcentrationVectorMap;
+    std::map<int, std::map<int, fullVector<double> > > _inelasticStrainConcentrationNormalizedVectorMap;
+    std::map<int, std::map<int, fullVector<double> > > _totalStrainConcentrationVectorMap; 
+    std::map<int, std::map<int, fullVector<double> > > _totalStrainConcentrationNormalizedVectorMap; 
     std::map<int, std::map<int, fullVector<double> > > _plasticEqStrainConcentrationVectorMap; 
     std::map<int, std::map<int, fullVector<double> > > _plasticEqStrainConcentrationNormalizedVectorMap; 
-    std::map<int, std::map<int, fullVector<double> > > _plasticEnergyVectorMap;
     std::map<int, std::map<int, fullVector<double> > > _SVMPlasticVectorMap; 
     std::map<int, std::map<int, fullVector<double> > > _eigenstressEqVectorMap; 
+    
+    std::map<int, fullMatrix<double> > _localStiffnessTensorMap; 
    
     //for the ease of acesse
     // direct access of the _concentrationTensorMap
     std::map<int, fullMatrix<double>* > _directMapOfStrainConcentration;
-    std::map<int, fullVector<double>* > _directMapOfPlasticStrainConcentration; 
-    std::map<int, fullVector<double>* > _directMapOfSigEPConcentration; 
+    std::map<int, fullVector<double>* > _directMapOfPlasticStrainConcentration;
+    std::map<int, fullVector<double>* > _directMapOfInelasticStrainConcentration;
+    std::map<int, fullVector<double>* > _directMapOfTotalStrainConcentration; 
     std::map<int, fullVector<double>* > _directMapOfPlasticEqStrainConcentration; 
-    std::map<int, fullVector<double>* > _directMapOfPlasticEnergy;
     std::map<int, fullVector<double>* > _directMapOfSVMPlastic;
     std::map<int, fullVector<double>* > _directMapOfEigenstressEq;
     
@@ -73,6 +80,11 @@ class Clustering
     // value - X, Y, Z, volume are stored
     std::map<int, fullVector<double> > _mapGaussPoints; 
     
+    
+    // key - element number and GP number - make unique number
+    // value - local euler angles
+    std::map<int, fullVector<double> > _mapLocalOrientation; 
+    
     // map number of gauss points in each element, 
     // key - element number
     // value - number of Gauss point
@@ -80,12 +92,20 @@ class Clustering
     
     // for computation of cluster interaction
     std::map<int,STensor3> _allEigenStrains;
+    std::map<int,STensor3> _allEigenStresses;
+    
+    // for interaction computation, 0: constrain eigenstrain field, 1: constrain eigenstress field
+    int _eigenField;
     
     // cluster map
     // key - element number and GP number using numericalMaterialBase::createTypeWithTwoInts(eleNum, gpNum) to make unique number
     // value - cluster index, note that clusters are numbered from 0, -1 means this part is not clustered
     std::map<int, int> _clusterIndex; 
     
+    // key - element number and GP number using numericalMaterialBase::createTypeWithTwoInts(eleNum, gpNum) to make unique number
+    // value - vector including the pfc values
+    std::map<int, fullVector<double>> _clusterPFC;
+    
     //total number of cluster over all domain
     int _totalNumberOfClusters;
   
@@ -95,6 +115,12 @@ class Clustering
     // map of cluster index - total value in this cluster
     std::map<int, double> _clusterVolumeMap; 
     
+    // map of cluster index - spatial position of this cluster
+    std::map<int, fullVector<double>> _clusterPositionMap; 
+    
+    // map of cluster index - spatial position of this cluster
+    std::map<int, fullVector<double>> _clusterMeanFiberOrientationMap; 
+    
     // map of cluster index - average strain concentration tensor in each cluster
     std::map<int, STensor43> _clusterAverageStrainConcentrationTensorMap;
     std::map<int, STensor43> _clusterSTDTensorMap;   
@@ -103,23 +129,26 @@ class Clustering
       
     // map of cluster index - plastic measures (arithmetic mean plasticEq, geometric mean plasticEq, harmonic mean plasticEq, std plasticEq)
     std::map<int, fullVector<double>> _clusterAveragePlasticStrainConcentrationVectorMap;
-    std::map<int, fullVector<double>> _clusterAverageSigEPConcentrationVectorMap;
+    std::map<int, fullVector<double>> _clusterAverageTotalStrainConcentrationVectorMap;
     std::map<int, fullVector<double>> _clusterAveragePlasticEqStrainConcentrationVectorMap;
     std::map<int, fullVector<double>> _clusterAverageGeometricPlasticEqStrainConcentrationVectorMap;
     std::map<int, fullVector<double>> _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap;
+    std::map<int, fullVector<double>> _clusterAveragePowerPlasticEqStrainConcentrationVectorMap;
+    std::map<int, fullVector<double>> _clusterPlSTDVectorMap;
     std::map<int, fullVector<double>> _clusterPlEqSTDVectorMap;
     
     // map of cluster index pair - interaction tensor
     std::map<std::pair<int,int>, STensor43> _clusterInteractionTensorMap;
-    std::map<std::pair<int,int>, STensor43> _clusterInteractionSTDTensorMap;
-    std::map<std::pair<int,int>, double> _clusterInteractionTensorSTDMap;
 
     std::map<std::pair<int,int>, STensor43> _clusterEshelbyInteractionTensorMap; 
-    std::map<std::pair<int,int>, STensor43> _clusterEshelbyInteractionSTDTensorMap;
     
     std::map<std::pair<int,int>, STensor43> _clusterInteractionTensorMatrixFrameELMap; 
     std::map<std::pair<int,int>, STensor43> _clusterInteractionTensorHomogenizedFrameELMap;
+    
+    STensor43 _referenceStiffness;
+    STensor43 _referenceStiffnessIso;
 
+    std::map<std::pair<int,int>, STensor43> _clusterInteractionTensorIsoMap;
     
     // parameter for clustering
     // key - material law
@@ -137,18 +166,24 @@ class Clustering
   public:
     Clustering();
     // solve strain concentrartion tensor at gauss points and save to file
-    void solveStrainConcentration(nonLinearMechSolver& solver, bool saveToFile=true, const std::string strainConcentrationFileName = "strainConcentrationData.csv");
+    void solveStrainConcentration(nonLinearMechSolver& solver, int homStiffnessFromLocal=0, 
+                                  bool saveToFile=true, const std::string strainConcentrationFileName = "strainConcentrationData.csv", 
+                                  bool saveLocalOrientationDataToFile=true, const std::string localOrientationFileName = "orientationData.csv");
     void solveStrainConcentrationInelastic(nonLinearMechSolver& solverInelastic,bool saveToFile=true, 
                                            const std::string PlasticStrainConcentrationFileName = "plasticStrainConcentrationData.csv",
-                                           const std::string SigEPConcentrationFileName = "sigEPConcentrationData.csv",
-                                           const std::string PlasticEqstrainConcentrationFileName = "plasticEqstrainConcentrationData.csv");
+                                           const std::string InelasticStrainConcentrationFileName = "inelasticStrainConcentrationData.csv",
+                                           const std::string TotalStrainConcentrationFileName = "totalStrainConcentrationData.csv",
+                                           const std::string PlasticEqStrainConcentrationFileName = "plasticEqstrainConcentrationData.csv");                                           
 
     // clustering can be applied using existing file of strain concentration data
     void loadStrainConcentrationDataFromFile(const std::string fileName);
     void loadPlasticStrainConcentrationDataFromFile(const std::string fileNamePlastic);
-    void loadSigEPConcentrationDataFromFile(const std::string fileNameSigEP);
+    void loadInelasticStrainConcentrationDataFromFile(const std::string fileNameInelastic);
+    void loadTotalStrainConcentrationDataFromFile(const std::string fileNameTotal);
     void loadPlasticEqStrainConcentrationDataFromFile(const std::string fileNamePlasticEq);
     void loadPlasticSVMStrainConcentrationDataFromFile(const std::string fileNamePlasticSVM);
+    
+    void loadLocalOrientationDataFromFile(const std::string fileNameLocalOrientationData);
 
     // clustersing with numCluster = number of Cluster
     // clusterFileName is a saved file indicating the map between element number, GP number of this element and 
@@ -160,7 +195,10 @@ class Clustering
     bool computeClustersElasticity(int minNumberElementEachCluster, int maxNbIterations=10000,
                                  bool saveToFile=true, const std::string clusterFileName = "ClusterData.csv", 
                                  bool saveSummaryFile=true, const std::string summaryFileName = "ClusterDataSummary.csv", 
-                                 bool saveMostStrainIPFile = true, const std::string saveMostStrainIPFileName = "MostStrainingIPSummary.csv"
+                                 bool saveMostStrainIPFile = true, const std::string saveMostStrainIPFileName = "MostStrainingIPSummary.csv",
+                                 bool saveStrainConcStDFile = true, const std::string saveStrainConcStDFileName = "ClusterStrainConcStD.csv",
+                                 bool saveClusterPositionFile = true, const std::string saveClusterPositionFileName = "ClusterPosition.csv",
+                                 bool saveClusterMeanFiberOrientationFile=true, const std::string saveClusterMeanFiberOrientationFileName = "ClusterMeanFiberOrientation.csv"
                                  );
                                  
     bool computeClustersPlasticity(int minNumberElementEachCluster, int maxNbIterations=10000,
@@ -168,8 +206,10 @@ class Clustering
                                  bool saveSummaryFile=true, const std::string summaryFileName = "ClusterDataSummary.csv", 
                                  bool savePlastStrainConcFile=true, std::string plastStrainconcFileName = "ClusterPlasticSummary.csv",
                                  bool savePlastEqStrainConcFile=true, std::string plastEqstrainconcFileName = "ClusterPlasticEqSummary.csv",
-                                 bool savePlastEqStrainConcSTDFile=true, std::string plastEqstrainconcstdevFileName = "ClusterPlasticEqSTD.csv",
-                                 bool saveMostStrainIPFile = true, const std::string saveMostStrainIPFileName = "MostStrainingIPSummary.csv"
+                                 bool savePlastStrainConcSTDFile=true, std::string plastStrainconcstdevFileName = "ClusterPlasticStrainTensorSTD.csv",
+                                 bool saveMostStrainIPFile = true, const std::string saveMostStrainIPFileName = "MostStrainingIPSummary.csv",
+                                 bool saveClusterPositionFile = true, const std::string saveClusterPositionFileName = "ClusterPosition.csv",
+                                 bool saveClusterMeanFiberOrientationFile=true, const std::string saveClusterMeanFiberOrientationFileName = "ClusterMeanFiberOrientation.csv"
                                  );
     //
     bool clusteringByMeshPartition(nonLinearMechSolver& solver, int nbClusters, bool onlyLawsWithDissipation, bool saveToFile=true, const std::string clusterFileName = "ClusterData.csv");
@@ -183,34 +223,28 @@ class Clustering
     // >=0 means the th-number Gauss-point
     void saveFieldToView(int name, int gp=-1);  // -1 means average over all GPs of element
     
-    
-    void setPerturbatedMaterialLaw(int num, materialLaw* pertLaw);
-    void computeDAverageStrainConcentrationDLaw(nonLinearMechSolver& solver,
-                                  materialLaw* clusterLaw,
-                                  bool saveToFile=true, 
-                                  const std::string saveFileName = "DInteractionTensorDataDLaw.csv");
-    
     // compute interation matrix
     void computeInteractionTensor(nonLinearMechSolver& solver,
                                   materialLaw* clusterLaw,
+                                  int eigenField=0,
                                   bool saveToFile=true, 
-                                  const std::string saveFileName = "InteractionTensorData.csv",
-                                  bool saveInteractionSTDToFile=true, 
-                                  const std::string saveInteractionSTDFileName = "InteractionTensorSTD.csv");
+                                  const std::string saveFileName = "InteractionTensorData.csv");
 
 
     void computeEshelbyInteractionTensor(nonLinearMechSolver& solver,
                                   materialLaw* clusterLaw,
-                                  bool saveToFileEshelby=true, 
-                                  const std::string saveEshelbyFileName = "EshelbyInteractionTensorData.csv");
-
-    
+                                  int eigenField=0,
+                                  bool saveToFile=true, 
+                                  const std::string saveFileName = "EshelbyInteractionTensorData.csv");
+          
+    // to set method in ClusterDG3DMaterialLaw                
+    int getEigenMethod(){return _eigenField;};
+   
     // data are ready to used
     void clearAllClusterData(); // muste be cleanup the existing data before loading files
     void loadClusterSummaryFromFile(const std::string filename);
+    void loadClusterSummaryHomogenizedFrameFromFile(const std::string filename);
     void loadClusterStandDevFromFile(const std::string filename);
-    void loadInteractionStandDevFromFile(const std::string filename);
-    void loadEshelbyInteractionStandDevFromFile(const std::string filename);
     void loadInteractionTensorsFromFile(const std::string filename);
     void loadEshelbyInteractionTensorsFromFile(const std::string filename);
     void loadElasticStrainConcentrationDerivativeFromFile(const std::string filename);
@@ -218,21 +252,30 @@ class Clustering
     void loadClusterPlasticEqSummaryFromFile(const std::string filename);
     void loadClusterPlasticEqSummaryGeometricFromFile(const std::string filename);
     void loadClusterPlasticEqSummaryHarmonicFromFile(const std::string filename);
+    void loadClusterPlasticEqSummaryPowerFromFile(const std::string filename);
 
     void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string filename);
     void loadInteractionTensorsMatrixFrameELFromFile(const std::string filename);
+    
+    void loadReferenceStiffnessFromFile(const std::string fileNameRefStiff);
+    void loadReferenceStiffnessIsoFromFile(const std::string fileNameRefStiffIso);
+    
+    void loadInteractionTensorIsoFromFile(const std::string filename);
+    
+    void loadClusterFiberOrientationFromFile(const std::string fileNameOri);
+    
     #ifndef SWIG
     ~Clustering(){}
     void computeAverageStrainCluster(const IPField* ipf , const std::set<int>& cluster, STensor3& Fhomo) const;
-    void computeInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJI, 
-                                                                                       std::map<std::pair<int,int>, double >& DJIstd,
-                                                                                       std::map<std::pair<int,int>, fullMatrix<double> >& DJIstdTensor);
+    void computeInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJI);
 
     void computeEshelbyInteractionTensorForCluster(nonLinearMechSolver& solver, int clusterI, std::map<std::pair<int,int>, fullMatrix<double> >& DJIEshelby);
 
     void strainForLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const;
+    void stressForLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const;
+    void strainForLoadingCasesVolumePreserving(int dim, double fact, std::map<int, STensor3>& modes) const;
     void strainForInelasticLoadingCases(int dim, double fact, std::map<int, STensor3>& modes) const;
-    void strainForInelasticLoadingCasesPath(int dim, double fact, double ftime, std::map<int, std::map<int,piecewiseScalarFunction>>& modes) const;
+    void strainForInelasticLoadingCasesPath(int dim, double fact, std::map<int, std::map<int,piecewiseScalarFunction>>& modes) const;
     const fullMatrix<double>& getStrainConcentrationTensor(int ele, int gp) const;
     int getClusterIndex(int ele, int gp) const;
     int getMaterialLawNumberIncluster(int cluster) const;
@@ -242,7 +285,10 @@ class Clustering
     int getNbOfGPsOnElement(const int ele) const;
     void getCluster(int i, std::set<int>& cluster) const; // return a set of all ele+GP belonging to cluster i    
     const STensor3& getEigenStrain(int GPIndex, bool homogeneous) const;
+    const STensor3& getEigenStress(int GPIndex, bool homogeneous) const;
     void unity_Voigt(fullMatrix<double>& mat) const;
+    
+    const fullVector<double>& getPFC(int ele, int gp) const;
 
     // get data for reduction analyses
     const std::map<int,int>& getClusterMaterialMap() const{return _clusterMaterialMap;};
@@ -257,17 +303,21 @@ class Clustering
     const std::map<int,fullVector<double>>& getClusterAveragePlasticEqStrainConcentrationVectorMap() const {return _clusterAveragePlasticEqStrainConcentrationVectorMap;};
     const std::map<int,fullVector<double>>& getClusterAverageGeometricPlasticEqStrainConcentrationVectorMap() const {return _clusterAverageGeometricPlasticEqStrainConcentrationVectorMap;};
     const std::map<int,fullVector<double>>& getClusterAverageHarmonicPlasticEqStrainConcentrationVectorMap() const {return _clusterAverageHarmonicPlasticEqStrainConcentrationVectorMap;};
+    const std::map<int,fullVector<double>>& getClusterAveragePowerPlasticEqStrainConcentrationVectorMap() const {return _clusterAveragePowerPlasticEqStrainConcentrationVectorMap;};
     const std::map<int,fullVector<double>>& getClusterPlasticEqSTDVectorMap() const {return _clusterPlEqSTDVectorMap;};
 
     const std::map<std::pair<int,int>,STensor43>& getClusterInteractionTensorMap() const {return _clusterInteractionTensorMap;};
-    const std::map<std::pair<int,int>,STensor43>& getClusterInteractionSTDTensorMap() const {return _clusterInteractionSTDTensorMap;};
-    const std::map<std::pair<int,int>,double>& getClusterInteractionTensorSTDMap() const {return _clusterInteractionTensorSTDMap;};
-
     const std::map<std::pair<int,int>,STensor43>& getClusterEshelbyInteractionTensorMap() const {return _clusterEshelbyInteractionTensorMap;};
     const std::map<std::pair<int,int>,STensor43>& getClusterInteractionTensorMatrixFrameELMap() const {return _clusterInteractionTensorMatrixFrameELMap;};
     const std::map<std::pair<int,int>,STensor43>& getClusterInteractionTensorHomogenizedFrameELMap() const {return _clusterInteractionTensorHomogenizedFrameELMap;};
 
     const std::map<std::pair<int,int>, STensor43>& getDclusterAverageStrainConcentrationTensorMapDLaw() const {return _DclusterAverageStrainConcentrationTensorMapDLaw;};
+    
+    const STensor43& getReferenceStiffness() const {return _referenceStiffness;};
+    const STensor43& getReferenceStiffnessIso() const {return _referenceStiffnessIso;};
+    const std::map<std::pair<int,int>,STensor43>& getClusterInteractionTensorIsoMap() const {return _clusterInteractionTensorIsoMap;};
+    
+    const std::map<int,fullVector<double>>& getClusterMeanFiberOrientation() const {return _clusterMeanFiberOrientationMap;};
     //
     #endif //SWIG    
 };
@@ -289,6 +339,8 @@ namespace clutering_impls
   double getDiffNorm(const fullMatrix<double>&A, const fullMatrix<double>&B);
   double getDiffNormVec(const fullVector<double>&a, const fullVector<double>&b);
   double getDiffNormVecLong(const fullVector<double>&a, const fullVector<double>&b);
+  double getDiffShearNormVecLong(const fullVector<double>&a, const fullVector<double>&b);
+  double getDiffNormVecPowerLong(const fullVector<double>&a, const fullVector<double>&b);
   
   bool kmean_cluster(const std::map<int, fullMatrix<double> >& data, const int nbClusters,  const int minElemEachCluster,
                      const int maxNbIterations,
@@ -312,6 +364,11 @@ namespace clutering_impls
                                         const std::map<int, const fullMatrix<double>* >& cluster, 
                                         const std::map<int, fullVector<double> >& mapPositionsWeights,
                                         fullVector<double>& mean);
+                                        
+  void meanClusterVecLong_FullMatrixBased(const std::map<int, fullVector<double> >& dataVec,
+                                        const std::map<int, const fullMatrix<double>* >& cluster, 
+                                        const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                        fullVector<double>& mean);
 
   double meanClusterVec(const std::map<int, const fullVector<double>* >& cluster, 
                         const std::map<int, fullVector<double> >& mapPositionsWeights,
@@ -321,9 +378,18 @@ namespace clutering_impls
                         const std::map<int, fullVector<double> >& mapPositionsWeights,
                         fullVector<double>& mean);
                         
+  void meanClusterPosition(const std::map<int, const fullMatrix<double>* >& cluster, 
+                        const std::map<int, fullVector<double> >& mapPositionsWeights,
+                        double& x_mean, double& y_mean, double& z_mean);
+  
+  void meanClusterFiberOrientation(const std::map<int, const fullMatrix<double>* >& cluster, 
+                                   const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                   const std::map<int, fullVector<double> >& mapLocalFiberOrientations,
+                                   double& E1_mean, double& E2_mean, double& E3_mean);
+                        
   void meanGeometricClusterVec(const std::map<int, const fullVector<double>* >& cluster, 
                                const std::map<int, fullVector<double> >& mapPositionsWeights,
-                               fullVector<double>& mean);
+                               fullVector<double>& mean);                      
                         
   void meanHarmonicClusterVec(const std::map<int, const fullVector<double>* >& cluster, 
                               const std::map<int, fullVector<double> >& mapPositionsWeights,
@@ -337,8 +403,15 @@ namespace clutering_impls
                                         const std::map<int, const fullMatrix<double>* >& cluster, 
                                         const std::map<int, fullVector<double> >& mapPositionsWeights,
                                         fullVector<double>& mean);
+                                        
+  void meanPowerClusterVec_FullMatrixBased(const std::map<int, fullVector<double> >& dataVec,
+                                        const std::map<int, const fullMatrix<double>* >& cluster, 
+                                        const std::map<int, fullVector<double> >& mapPositionsWeights,
+                                        fullVector<double>& mean);
                         
   int maxConcentrationCluster(const std::map<int, const fullMatrix<double>* >& cluster);
+  int maxConcentrationVecCluster(const std::map<int, const fullVector<double>* >& cluster);
+  int minConcentrationVecCluster(const std::map<int, const fullVector<double>* >& cluster);
 
   void printClusters(const std::map<int, std::map<int, const fullMatrix<double>* > >& clusters);
   int getNearestClusterId(const std::map<int, fullMatrix<double> >& clusterMean, const fullMatrix<double>& pt);
@@ -361,13 +434,23 @@ namespace clutering_impls
                        fullVector<double>& clusterSTDVector
                        );
                        
-  void vecNormalized(const std::map<int, fullVector<double> >& dataVec,
+  void vecNormalizeByOverallValue(const std::map<int, fullVector<double> >& dataVec,
                      const std::map<int, fullVector<double> >& mapPositionsWeights,
                      std::map<int, fullVector<double> >& dataVecNormalized);
                      
-  void vecNormalizedByNorm(const std::map<int, fullVector<double> >& dataVec,
+  void vecNormalizeByOverallNorm(const std::map<int, fullVector<double> >& dataVec,
                            const std::map<int, fullVector<double> >& mapPositionsWeights,
                            std::map<int, fullVector<double> >& dataVecNormalized);
+                           
+  void vecNormalizeByLocalNorm(const std::map<int, fullVector<double> >& dataVec,
+                               std::map<int, fullVector<double> >& dataVecNormalized);
+                               
+  void vecSeparate(const std::map<int, fullVector<double> >& dataVec,
+                               std::map<int, fullVector<double> >& dataVecSeparated);
+                           
+  void vecRatio(const std::map<int, fullVector<double> >& dataVecNumerator,
+                const std::map<int, fullVector<double> >& dataVecDenominator,
+                std::map<int, fullVector<double> >& dataVecRatio);
 
 
 }
diff --git a/NonLinearSolver/modelReduction/ClusteringData.h b/NonLinearSolver/modelReduction/ClusteringData.h
index fad1c46f1e5c8fb721d413deb2c26ea6d9b4e5f8..9f1bb6588edd09f633bd6003b576cf304679d407 100644
--- a/NonLinearSolver/modelReduction/ClusteringData.h
+++ b/NonLinearSolver/modelReduction/ClusteringData.h
@@ -27,12 +27,74 @@ class ClusteringData
     std::map<int, STensor3> allStresses; // local stress in cluster
     std::map<int, STensor43> allTangents; // local tangent in cluster
     std::map<int, STensor3> allEigenStrains; // eigenstrains used in reduction formulation
+    std::map<int, STensor3> allEigenStresses;
     std::map<int, STensor43> alldEigenStrainsdStrains; // derivarives of eigenstrains
+    std::map<int, STensor43> alldEigenStressesdStrains; // derivarives of eigenstresses
+    std::map<int, STensor43> alldEigenStrainFramedStrainsCluster; // derivarives of eigenstrains
+    std::map<int, STensor43> allSecants;
+    //std::map<int, STensor43> allTangentCompliances;
+    
     STensor3 macroStrain;
+    STensor3 macroStress;
+    STensor3 macroEigenStrain;
+    STensor3 macroEigenStress;
+    STensor3 macroResidualStrain;
+    STensor3 macroResidualStress;
+    STensor3 macroStressRef;
+    STensor3 macroStrainAtRefStress;
+    
+    STensor43 macroTangent;
+    
+    STensor3 strainFrame;
+    STensor3 eigenStrainFrame;
+    STensor3 eigenStressFrame;
+    STensor43 elasticComplianceFrame;
+    
+    STensor43 stiffnessIso;
+    double secantShearModulus;
+    double tangentShearModulus;
+    STensor43 stiffnessIsoInv;
+
+    STensor43 eigenStiffness;
+    STensor43 stiffnessAniso;
+    STensor43 stiffnessAnisoInv;
+    
+    STensor43 dEigenStraindStrainFrame;
+    STensor43 dEigenStressdStrainFrame;
+    
+    std::map<int, STensor3> allPolarizationStrains;
+    std::map<int, STensor3> allPolarizationStresses;
+    
+    std::map<int, STensor3> allResidualStrains; // local residual strain in cluster
+    std::map<int, STensor43> alldResidualStrainsdStrains; // local residual strain in cluster
+    
+    std::map<int, STensor3> allResidualStresses; // local residual stress in cluster
+    std::map<int, STensor43> alldResidualStressesdStrains; // derivarives of residual stresses
+    
+    std::map<int, STensor3> allReloadStresses;
+    std::map<int, STensor3> allReloadStrains;
+    
+    std::map<int, STensor3> allEffectiveStrains;
+    std::map<int, STensor3> allEffectiveStresses;  // eigenstress applied on the subvolume: eigenstress in the surrounding medium around the subvolume
+    
+    double elasticShearModulus;
+    STensor3 deformationDirection;
     
   public:
     ClusteringData(const std::vector<int>& allCl, const std::vector<double>& allVf): clustersNb(allCl.size()), 
-          allClusterIndexes(allCl), allClusterVolumes(allVf), macroStrain(0.)
+          allClusterIndexes(allCl), allClusterVolumes(allVf), macroStrain(0.),macroStress(0.),macroEigenStrain(0.),macroEigenStress(0.),macroResidualStrain(0.),macroResidualStress(0.),
+          strainFrame(0.), eigenStrainFrame(0.), eigenStressFrame(0.), elasticComplianceFrame(0.), dEigenStraindStrainFrame(0.), dEigenStressdStrainFrame(0.),
+          stiffnessIso(0.),
+          stiffnessIsoInv(0.),
+          eigenStiffness(0.),
+          stiffnessAniso(0.),
+          stiffnessAnisoInv(0.),
+          secantShearModulus(0.),
+          tangentShearModulus(0.),
+          elasticShearModulus(0.),
+          macroStressRef(0.),macroStrainAtRefStress(0.),
+          deformationDirection(0.),
+          macroTangent(0.)
     {
       for (int i=0; i< clustersNb; i++)
       {
@@ -41,13 +103,57 @@ class ClusteringData
         allStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
         allTangents.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
         allEigenStrains.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allEigenStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allPolarizationStrains.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allPolarizationStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
         alldEigenStrainsdStrains.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        alldEigenStressesdStrains.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        alldEigenStrainFramedStrainsCluster.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        allSecants.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        allResidualStrains.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        alldResidualStrainsdStrains.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        allResidualStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        alldResidualStressesdStrains.insert(std::pair<int,STensor43>(allClusterIndexes[i],STensor43(0.)));
+        allEffectiveStrains.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allEffectiveStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allReloadStresses.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
+        allReloadStrains.insert(std::pair<int,STensor3>(allClusterIndexes[i],STensor3(0.)));
       }
     }
     ClusteringData(const ClusteringData& src):clustersNb(src.clustersNb), allClusterIndexes(src.allClusterIndexes), allClusterVolumes(src.allClusterVolumes),
                                               allStrains(src.allStrains),allStresses(src.allStresses), allTangents(src.allTangents),
-                                              allEigenStrains(src.allEigenStrains), alldEigenStrainsdStrains(src.alldEigenStrainsdStrains),
-                                              macroStrain(src.macroStrain)
+                                              allEigenStrains(src.allEigenStrains), allEigenStresses(src.allEigenStresses), 
+                                              allPolarizationStrains(src.allPolarizationStrains), allPolarizationStresses(src.allPolarizationStresses),
+                                              alldEigenStrainsdStrains(src.alldEigenStrainsdStrains),
+                                              alldEigenStressesdStrains(src.alldEigenStressesdStrains),
+                                              macroStrain(src.macroStrain), macroStress(src.macroStress), macroEigenStrain(src.macroEigenStrain), macroEigenStress(src.macroEigenStress),
+                                              macroResidualStrain(src.macroResidualStrain), macroResidualStress(src.macroResidualStress),
+                                              alldEigenStrainFramedStrainsCluster(src.alldEigenStrainFramedStrainsCluster),
+                                              allSecants(src.allSecants),
+                                              strainFrame(src.strainFrame),eigenStrainFrame(src.eigenStrainFrame), eigenStressFrame(src.eigenStressFrame),
+                                              elasticComplianceFrame(src.elasticComplianceFrame),
+                                              dEigenStraindStrainFrame(src.dEigenStraindStrainFrame),
+                                              dEigenStressdStrainFrame(src.dEigenStressdStrainFrame),
+                                              allResidualStrains(src.allResidualStrains),
+                                              alldResidualStrainsdStrains(src.alldResidualStrainsdStrains),
+                                              allResidualStresses(src.allResidualStresses),
+                                              alldResidualStressesdStrains(src.alldResidualStressesdStrains),
+                                              allEffectiveStrains(src.allEffectiveStrains),
+                                              allEffectiveStresses(src.allEffectiveStresses),
+                                              stiffnessIso(src.stiffnessIso),
+                                              stiffnessIsoInv(src.stiffnessIsoInv),
+                                              eigenStiffness(src.eigenStiffness),
+                                              stiffnessAniso(src.stiffnessAniso),
+                                              stiffnessAnisoInv(src.stiffnessAnisoInv),
+                                              secantShearModulus(src.secantShearModulus),
+                                              tangentShearModulus(src.tangentShearModulus),
+                                              elasticShearModulus(src.elasticShearModulus),
+                                              macroStressRef(src.macroStressRef),
+                                              macroStrainAtRefStress(src.macroStrainAtRefStress),
+                                              deformationDirection(src.deformationDirection),
+                                              allReloadStresses(src.allReloadStresses),
+                                              allReloadStrains(src.allReloadStrains),
+                                              macroTangent(src.macroTangent)
     {
       allIpvs.clear();
       for (std::map<int, IPVariable*>::const_iterator it = src.allIpvs.begin(); it!=src.allIpvs.end(); it++)
@@ -91,6 +197,29 @@ class ClusteringData
         allClusterIndexes = src.allClusterIndexes;
         allClusterVolumes = src.allClusterVolumes;
         macroStrain = src.macroStrain;
+        macroStress = src.macroStress;
+        macroEigenStrain = src.macroEigenStrain;
+        macroEigenStress = src.macroEigenStress;
+        macroResidualStrain = src.macroResidualStrain;
+        macroResidualStress = src.macroResidualStress;
+        strainFrame = src.strainFrame;
+        eigenStrainFrame = src.eigenStrainFrame;
+        eigenStressFrame = src.eigenStressFrame;
+        elasticComplianceFrame = src.elasticComplianceFrame;
+        dEigenStraindStrainFrame = src.dEigenStraindStrainFrame;
+        dEigenStressdStrainFrame = src.dEigenStressdStrainFrame;
+        stiffnessIso = src.stiffnessIso;
+        stiffnessIsoInv = src.stiffnessIsoInv;
+        eigenStiffness = src.eigenStiffness;
+        stiffnessAniso = src.stiffnessAniso;
+        stiffnessAnisoInv = src.stiffnessAnisoInv;
+        secantShearModulus = src.secantShearModulus;
+        tangentShearModulus = src.tangentShearModulus;
+        elasticShearModulus = src.elasticShearModulus;
+        macroStressRef = src.macroStressRef;
+        macroStrainAtRefStress = src.macroStrainAtRefStress;
+        deformationDirection = src.deformationDirection;
+        macroTangent = src.macroTangent;
         for (int i=0; i< clustersNb; i++)
         {
           const IPVariable* ipvsrc = (src.allIpvs.find(allClusterIndexes[i]))->second;
@@ -98,7 +227,21 @@ class ClusteringData
           const STensor3& stressSrc = (src.allStresses.find(allClusterIndexes[i]))->second;
           const STensor43& tangentSrc = (src.allTangents.find(allClusterIndexes[i]))->second;
           const STensor3& eigenStrainSrc = (src.allEigenStrains.find(allClusterIndexes[i]))->second;
+          const STensor3& eigenStressSrc = (src.allEigenStresses.find(allClusterIndexes[i]))->second;
+          const STensor3& polarizationStrainSrc = (src.allPolarizationStrains.find(allClusterIndexes[i]))->second;
+          const STensor3& polarizationStressSrc = (src.allPolarizationStresses.find(allClusterIndexes[i]))->second;
           const STensor43& deigenStrainSrc = (src.alldEigenStrainsdStrains.find(allClusterIndexes[i]))->second;
+          const STensor43& deigenStressSrc = (src.alldEigenStressesdStrains.find(allClusterIndexes[i]))->second;
+          const STensor43& deigenStrainFramedStrainsClusterSrc = (src.alldEigenStrainFramedStrainsCluster.find(allClusterIndexes[i]))->second;
+          const STensor43& secantSrc = (src.allSecants.find(allClusterIndexes[i]))->second;
+          const STensor3& residualStrainSrc = (src.allResidualStrains.find(allClusterIndexes[i]))->second;
+          const STensor43& dresidualStrainSrc = (src.alldResidualStrainsdStrains.find(allClusterIndexes[i]))->second;
+          const STensor3& residualStressSrc = (src.allResidualStresses.find(allClusterIndexes[i]))->second;
+          const STensor43& dresidualStressSrc = (src.alldResidualStressesdStrains.find(allClusterIndexes[i]))->second;
+          const STensor3& appliedEigenStrainSrc = (src.allEffectiveStrains.find(allClusterIndexes[i]))->second;
+          const STensor3& appliedEigenStressSrc = (src.allEffectiveStresses.find(allClusterIndexes[i]))->second;
+          const STensor3& reloadStressSrc = (src.allReloadStresses.find(allClusterIndexes[i]))->second;
+          const STensor3& reloadStrainSrc = (src.allReloadStrains.find(allClusterIndexes[i]))->second;
           
           if (ipvsrc!=NULL)
           {
@@ -123,7 +266,21 @@ class ClusteringData
           allStresses[allClusterIndexes[i]] = stressSrc;
           allTangents[allClusterIndexes[i]] = tangentSrc;
           allEigenStrains[allClusterIndexes[i]] = eigenStrainSrc;
+          allEigenStresses[allClusterIndexes[i]] = eigenStressSrc;
+          allPolarizationStrains[allClusterIndexes[i]] = polarizationStrainSrc;
+          allPolarizationStresses[allClusterIndexes[i]] = polarizationStressSrc;
           alldEigenStrainsdStrains[allClusterIndexes[i]] = deigenStrainSrc;
+          alldEigenStressesdStrains[allClusterIndexes[i]] = deigenStressSrc;
+          alldEigenStrainFramedStrainsCluster[allClusterIndexes[i]] = deigenStrainFramedStrainsClusterSrc;
+          allSecants[allClusterIndexes[i]] = secantSrc;
+          allResidualStrains[allClusterIndexes[i]] = residualStrainSrc;
+          alldResidualStrainsdStrains[allClusterIndexes[i]] = dresidualStrainSrc;
+          allResidualStresses[allClusterIndexes[i]] = residualStressSrc;
+          alldResidualStressesdStrains[allClusterIndexes[i]] = dresidualStressSrc;
+          allEffectiveStrains[allClusterIndexes[i]] = appliedEigenStrainSrc;
+          allEffectiveStresses[allClusterIndexes[i]] = appliedEigenStressSrc;
+          allReloadStresses[allClusterIndexes[i]] = reloadStressSrc;
+          allReloadStrains[allClusterIndexes[i]] = reloadStrainSrc;
         }
       }
       return *this;
@@ -153,6 +310,7 @@ class ClusteringData
         double vf = allClusterVolumes[icl];
         vToltal += vf;
         const STensor3& sigCl = getConstRefToStress(allClusterIndexes[icl]);
+        //sigCl.print("PPPPPCL");
         sig.daxpy(sigCl, vf);
       }
       sig *= (1./vToltal);
@@ -183,11 +341,48 @@ class ClusteringData
         restartManager::restart(ipv);
       }
       restartManager::restart(macroStrain);
+      restartManager::restart(macroStress);
+      restartManager::restart(macroEigenStrain);
+      restartManager::restart(macroEigenStress);
+      restartManager::restart(macroResidualStrain);
+      restartManager::restart(macroResidualStress);
       restartManager::restart(allStrains);
       restartManager::restart(allStresses);
       restartManager::restart(allTangents);
       restartManager::restart(allEigenStrains);
+      restartManager::restart(allEigenStresses);
+      restartManager::restart(allPolarizationStrains);
+      restartManager::restart(allPolarizationStresses);
       restartManager::restart(alldEigenStrainsdStrains);
+      restartManager::restart(alldEigenStressesdStrains);
+      restartManager::restart(alldEigenStrainFramedStrainsCluster);
+      restartManager::restart(allSecants);
+      restartManager::restart(strainFrame);
+      restartManager::restart(eigenStrainFrame);
+      restartManager::restart(eigenStressFrame);
+      restartManager::restart(elasticComplianceFrame);
+      restartManager::restart(dEigenStraindStrainFrame);
+      restartManager::restart(dEigenStressdStrainFrame);
+      restartManager::restart(allResidualStrains);
+      restartManager::restart(alldResidualStrainsdStrains);
+      restartManager::restart(allResidualStresses);
+      restartManager::restart(alldResidualStressesdStrains);
+      restartManager::restart(allEffectiveStrains);
+      restartManager::restart(allEffectiveStresses);
+      restartManager::restart(stiffnessIso);
+      restartManager::restart(stiffnessIsoInv);
+      restartManager::restart(eigenStiffness);
+      restartManager::restart(stiffnessAniso);
+      restartManager::restart(stiffnessAnisoInv);
+      restartManager::restart(secantShearModulus);
+      restartManager::restart(tangentShearModulus);
+      restartManager::restart(elasticShearModulus);
+      restartManager::restart(macroStressRef);
+      restartManager::restart(macroStrainAtRefStress);
+      restartManager::restart(deformationDirection);
+      restartManager::restart(allReloadStresses);
+      restartManager::restart(allReloadStrains);
+      restartManager::restart(macroTangent);
     };
     
     virtual int getClustersNb() const {return clustersNb;};
@@ -195,6 +390,75 @@ class ClusteringData
     virtual const STensor3& getConstRefToMacroStrain() const {return macroStrain;};
     virtual STensor3& getRefToMacroStrain() {return macroStrain;};
     
+    virtual const STensor3& getConstRefToMacroStress() const {return macroStress;};
+    virtual STensor3& getRefToMacroStress() {return macroStress;};
+    
+    virtual const STensor43& getConstRefToMacroTangent() const {return macroTangent;};
+    virtual STensor43& getRefToMacroTangent() {return macroTangent;};
+    
+    virtual const STensor3& getConstRefToMacroEigenStrain() const {return macroEigenStrain;};
+    virtual STensor3& getRefToMacroEigenStrain() {return macroEigenStrain;};
+    
+    virtual const STensor3& getConstRefToMacroEigenStress() const {return macroEigenStress;};
+    virtual STensor3& getRefToMacroEigenStress() {return macroEigenStress;};
+    
+    virtual const STensor3& getConstRefToMacroResidualStrain() const {return macroResidualStrain;};
+    virtual STensor3& getRefToMacroResidualStrain() {return macroResidualStrain;};
+    
+    virtual const STensor3& getConstRefToMacroResidualStress() const {return macroResidualStress;};
+    virtual STensor3& getRefToMacroResidualStress() {return macroResidualStress;};
+    
+    virtual const STensor3& getConstRefToFrameStrain() const {return strainFrame;};
+    virtual STensor3& getRefToFrameStrain() {return strainFrame;};
+    
+    virtual const STensor3& getConstRefToFrameEigenStrain() const {return eigenStrainFrame;};
+    virtual STensor3& getRefToFrameEigenStrain() {return eigenStrainFrame;};
+    
+    virtual const STensor3& getConstRefToFrameEigenStress() const {return eigenStressFrame;};
+    virtual STensor3& getRefToFrameEigenStress() {return eigenStressFrame;};
+    
+    virtual const STensor43& getConstRefToFrameElasticCompliance() const {return elasticComplianceFrame;};
+    virtual STensor43& getRefToFrameElasticCompliance() {return elasticComplianceFrame;};
+    
+    virtual const STensor43& getConstRefToFramedEigenStraindStrain() const {return dEigenStraindStrainFrame;};
+    virtual STensor43& getRefToFramedEigenStraindStrain() {return dEigenStraindStrainFrame;};
+    
+    virtual const STensor43& getConstRefToFramedEigenStressdStrain() const {return dEigenStressdStrainFrame;};
+    virtual STensor43& getRefToFramedEigenStressdStrain() {return dEigenStressdStrainFrame;};
+    
+    virtual const STensor43& getConstRefToIsotropicStiffness() const {return stiffnessIso;};
+    virtual STensor43& getRefToIsotropicStiffness() {return stiffnessIso;};
+    
+    virtual const STensor43& getConstRefToIsotropicStiffnessInverted() const {return stiffnessIsoInv;};
+    virtual STensor43& getRefToIsotropicStiffnessInverted() {return stiffnessIsoInv;};
+    
+    virtual const STensor43& getConstRefToEigenStiffness() const {return eigenStiffness;};
+    virtual STensor43& getRefToEigenStiffness() {return eigenStiffness;};
+    
+    virtual const STensor43& getConstRefToAnisotropicStiffness() const {return stiffnessAniso;};
+    virtual STensor43& getRefToAnisotropicStiffness() {return stiffnessAniso;};
+    
+    virtual const STensor43& getConstRefToAnisotropicStiffnessInverted() const {return stiffnessAnisoInv;};
+    virtual STensor43& getRefToAnisotropicStiffnessInverted() {return stiffnessAnisoInv;};
+    
+    virtual const double& getConstRefToSecantShearModulus() const {return secantShearModulus;};
+    virtual double& getRefToSecantShearModulus() {return secantShearModulus;};
+    
+    virtual const double& getConstRefToTangentShearModulus() const {return tangentShearModulus;};
+    virtual double& getRefToTangentShearModulus() {return tangentShearModulus;};
+    
+    virtual const double& getConstRefToElasticShearModulus() const {return elasticShearModulus;};
+    virtual double& getRefToElasticShearModulus() {return elasticShearModulus;};
+    
+    virtual const STensor3& getConstRefToMacroStressRef() const {return macroStressRef;};
+    virtual STensor3& getRefToMacroStressRef() {return macroStressRef;};
+    
+    virtual const STensor3& getConstRefToMacroStrainAtRefStress() const {return macroStrainAtRefStress;};
+    virtual STensor3& getRefToMacroStrainAtRefStress() {return macroStrainAtRefStress;};
+    
+    virtual const STensor3& getConstRefToDeformationDirection() const {return deformationDirection;};
+    virtual STensor3& getRefToDeformationDirection() {return deformationDirection;};
+    
     const IPVariable* getConstRefToIPv(int cl) const
     {
       std::map<int,IPVariable*>::const_iterator it = allIpvs.find(cl);
@@ -279,7 +543,186 @@ class ClusteringData
       }
     }
     
-     const STensor43 &getConstRefToTangent(int cl) const
+    const STensor3 &getConstRefToResidualStrain(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allResidualStrains.find(cl);
+      if (it == allResidualStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToResidualStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    STensor3 &getRefToResidualStrain(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allResidualStrains.find(cl);
+      if (it == allResidualStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefToResidualStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToResidualStress(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allResidualStresses.find(cl);
+      if (it == allResidualStresses.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToResidualStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    STensor3 &getRefToResidualStress(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allResidualStresses.find(cl);
+      if (it == allResidualStresses.end())
+      {
+        Msg::Error("ClusteringData::getRefToResidualStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToReloadStress(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allReloadStresses.find(cl);
+      if (it == allReloadStresses.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToReloadStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    STensor3 &getRefToReloadStress(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allReloadStresses.find(cl);
+      if (it == allReloadStresses.end())
+      {
+        Msg::Error("ClusteringData::getRefToReloadStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToReloadStrain(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allReloadStrains.find(cl);
+      if (it == allReloadStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToReloadStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    STensor3 &getRefToReloadStrains(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allReloadStrains.find(cl);
+      if (it == allReloadStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefToReloadStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToEffectiveStrain(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allEffectiveStrains.find(cl);
+      if (it == allEffectiveStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToEffectiveStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor3 &getRefToEffectiveStrain(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allEffectiveStrains.find(cl);
+      if (it == allEffectiveStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefToEffectiveStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToEffectiveStress(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allEffectiveStresses.find(cl);
+      if (it == allEffectiveStresses.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToEffectiveStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor3 &getRefToEffectiveStress(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allEffectiveStresses.find(cl);
+      if (it == allEffectiveStresses.end())
+      {
+        Msg::Error("ClusteringData::getRefToEffectiveStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    
+    const STensor43 &getConstRefToTangent(int cl) const
     {
       std::map<int,STensor43>::const_iterator it = allTangents.find(cl);
       if (it == allTangents.end())
@@ -308,6 +751,35 @@ class ClusteringData
       }
     }
     
+    const STensor43 &getConstRefToSecant(int cl) const
+    {
+      std::map<int,STensor43>::const_iterator it = allSecants.find(cl);
+      if (it == allSecants.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToSecant cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor43 &getRefToSecant(int cl)
+    {
+      std::map<int,STensor43>::iterator it = allSecants.find(cl);
+      if (it == allSecants.end())
+      {
+        Msg::Error("ClusteringData::getRefToSecant cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
     const STensor3 &getConstRefToEigenStrain(int cl) const
     {
       std::map<int,STensor3>::const_iterator it = allEigenStrains.find(cl);
@@ -327,7 +799,94 @@ class ClusteringData
       std::map<int,STensor3>::iterator it = allEigenStrains.find(cl);
       if (it == allEigenStrains.end())
       {
-        Msg::Error("ClusteringData::getConstRefToEigenStrain cluster %d is not found",cl);
+        Msg::Error("ClusteringData::getRefToEigenStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor3 &getConstRefToEigenStress(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allEigenStresses.find(cl);
+      if (it == allEigenStresses.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToEigenStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor3 &getRefToEigenStress(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allEigenStresses.find(cl);
+      if (it == allEigenStresses.end())
+      {
+        Msg::Error("ClusteringData::getRefToEigenStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    const STensor3 &getConstRefToPolarizationStrain(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allPolarizationStrains.find(cl);
+      if (it == allPolarizationStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToPolarizationStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor3 &getRefToPolarizationStrain(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allPolarizationStrains.find(cl);
+      if (it == allPolarizationStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefToPolarizationStrain cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+
+    const STensor3 &getConstRefToPolarizationStress(int cl) const
+    {
+      std::map<int,STensor3>::const_iterator it = allPolarizationStresses.find(cl);
+      if (it == allPolarizationStresses.end())
+      {
+        Msg::Error("ClusteringData::getConstRefToPolarizationStress cluster %d is not found",cl);
+        static STensor3 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor3 &getRefToPolarizationStress(int cl)
+    {
+      std::map<int,STensor3>::iterator it = allPolarizationStresses.find(cl);
+      if (it == allPolarizationStresses.end())
+      {
+        Msg::Error("ClusteringData::getRefToPolarizationStress cluster %d is not found",cl);
         static STensor3 tmp;
         return tmp;
       }
@@ -356,7 +915,7 @@ class ClusteringData
       std::map<int,STensor43>::iterator it = alldEigenStrainsdStrains.find(cl);
       if (it == alldEigenStrainsdStrains.end())
       {
-        Msg::Error("ClusteringData::alldEigenStrainsdStrains cluster %d is not found",cl);
+        Msg::Error("ClusteringData::getRefTodEigenStraindStrain cluster %d is not found",cl);
         static STensor43 tmp;
         return tmp;
       }
@@ -366,6 +925,122 @@ class ClusteringData
       }
     }
     
+    const STensor43 &getConstRefTodEigenStressdStrain(int cl) const
+    {
+      std::map<int,STensor43>::const_iterator it = alldEigenStressesdStrains.find(cl);
+      if (it == alldEigenStressesdStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefTodEigenStressdStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor43 &getRefTodEigenStressdStrain(int cl)
+    {
+      std::map<int,STensor43>::iterator it = alldEigenStressesdStrains.find(cl);
+      if (it == alldEigenStressesdStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefTodEigenStressdStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor43 &getConstRefTodResidualStressdStrain(int cl) const
+    {
+      std::map<int,STensor43>::const_iterator it = alldResidualStressesdStrains.find(cl);
+      if (it == alldResidualStressesdStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefTodResidualStressdStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor43 &getRefTodResidualStressdStrain(int cl)
+    {
+      std::map<int,STensor43>::iterator it = alldResidualStressesdStrains.find(cl);
+      if (it == alldResidualStressesdStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefTodResidualStressdStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    const STensor43 &getConstRefTodResidualStraindStrain(int cl) const
+    {
+      std::map<int,STensor43>::const_iterator it = alldResidualStrainsdStrains.find(cl);
+      if (it == alldResidualStrainsdStrains.end())
+      {
+        Msg::Error("ClusteringData::getConstRefTodResidualStraindStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor43 &getRefTodResidualStraindStrain(int cl)
+    {
+      std::map<int,STensor43>::iterator it = alldResidualStrainsdStrains.find(cl);
+      if (it == alldResidualStrainsdStrains.end())
+      {
+        Msg::Error("ClusteringData::getRefTodResidualStraindStrain cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    
+    
+    const STensor43 &getConstRefTodEigenStrainFramedStrainCluster(int cl) const
+    {
+      std::map<int,STensor43>::const_iterator it = alldEigenStrainFramedStrainsCluster.find(cl);
+      if (it == alldEigenStrainFramedStrainsCluster.end())
+      {
+        Msg::Error("ClusteringData::getConstRefTodEigenStrainFramedStrainCluster cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
+    STensor43 &getRefTodEigenStrainFramedStrainCluster(int cl)
+    {
+      std::map<int,STensor43>::iterator it = alldEigenStrainFramedStrainsCluster.find(cl);
+      if (it == alldEigenStrainFramedStrainsCluster.end())
+      {
+        Msg::Error("ClusteringData::getRefTodEigenStrainFramedStrainCluster cluster %d is not found",cl);
+        static STensor43 tmp;
+        return tmp;
+      }
+      else
+      {
+        return it->second;
+      }
+    }
 };
 
 
diff --git a/NonLinearSolver/modelReduction/TFATools.h b/NonLinearSolver/modelReduction/TFATools.h
index da403e6546f831e6f666d1526e3abae0ebb0abb6..3b98d6ecafae4c644dd301b8a16e5c4c892de840 100644
--- a/NonLinearSolver/modelReduction/TFATools.h
+++ b/NonLinearSolver/modelReduction/TFATools.h
@@ -59,6 +59,24 @@ namespace TFANumericTools{
     return strainEq;  
   }
   
+  inline double Equivalent2DStrain(const STensor3& strainTensor)
+  {
+    STensor3 strainDev = strainTensor;
+    STensor3 I(1.);
+    double eps_mean = (strainTensor(0,0) + strainTensor(1,1))/2.;
+    strainDev -= eps_mean*I;
+    strainDev(0,2) = strainDev(1,2) = strainDev(2,0) = strainDev(2,1) = strainDev(2,2) = 0.;
+    double strainDev_contract = 0.;
+    for(int i=0; i<2; i++){
+      for(int j=0; j<2; j++){
+        strainDev_contract += strainDev(i,j)*strainDev(i,j);
+      }
+    }
+    double strainEq = sqrt(2./3.*strainDev_contract);
+    
+    return strainEq;  
+  }
+  
   inline double EquivalentStress(const STensor3& stressTensor)
   {
     STensor3 stressDev = stressTensor.dev();
@@ -72,6 +90,24 @@ namespace TFANumericTools{
     
     return stressEq;  
   }
+  
+  inline double Equivalent2DStress(const STensor3& stressTensor)
+  {
+    STensor3 stressDev = stressTensor;
+    STensor3 I(1.);
+    double p = (stressTensor(0,0) + stressTensor(1,1))/2.;
+    stressDev -= p*I;
+    stressDev(0,2) = stressDev(1,2) = stressDev(2,0) = stressDev(2,1) = stressDev(2,2) = 0.;
+    double stressDev_contract = 0.;
+    for(int i=0; i<2; i++){
+      for(int j=0; j<2; j++){
+        stressDev_contract += stressDev(i,j)*stressDev(i,j);
+      }
+    }
+    double stressEq = sqrt(1.5*stressDev_contract);
+    
+    return stressEq;  
+  }
 
   inline void StiffnessIsotropic(const double& G, const double& K, STensor43& IsotropicStiffness)
   {
diff --git a/NonLinearSolver/modelReduction/modelReduction.cpp b/NonLinearSolver/modelReduction/modelReduction.cpp
index 6dfb7e5042ea5c03ff9aefe3c5b4815267a07087..299742cb94f5bd4d38803ae0b39c0fa84c3f3338 100644
--- a/NonLinearSolver/modelReduction/modelReduction.cpp
+++ b/NonLinearSolver/modelReduction/modelReduction.cpp
@@ -99,8 +99,8 @@ void ReductionTFA::initializeClusterMaterialMap(const std::map<int,materialLaw*>
   }
 }
 
-ReductionTFA::ReductionTFA(int solver, int d, int correction, int tag) : _solverType(solver), _tag(tag), _ownClusteringData(false), _clusteringData(NULL), 
-_dim(d), _sys(NULL), _isInitialized(false), _correction(correction){}
+ReductionTFA::ReductionTFA(int solver, int d, int correction, bool withFrame, bool polarization, int tag) : _solverType(solver), _tag(tag), _ownClusteringData(false), _clusteringData(NULL), 
+_dim(d), _sys(NULL), _isInitialized(false), _correction(correction), _withFrame(withFrame), _polarization(polarization) {}
 ReductionTFA::~ReductionTFA()
 {
   if (_ownClusteringData)
@@ -141,26 +141,38 @@ void ReductionTFA::loadClusterSummaryAndInteractionTensorsFromFiles(const std::s
   _clusteringData->loadInteractionTensorsFromFile(interactionTensorsFileName);
 };
 
+void ReductionTFA::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName)
+{
+  if (_ownClusteringData)
+  {
+    if (_clusteringData != NULL) delete _clusteringData;
+  }
+  _ownClusteringData = true;
+  _clusteringData = new Clustering();
+  _clusteringData->loadClusterSummaryHomogenizedFrameFromFile(clusterSummaryFileName);
+  _clusteringData->loadInteractionTensorsHomogenizedFrameELFromFile(interactionTensorsFileName);
+};
 
-void ReductionTFA::loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD, const std::string InteractionSTD)
+void ReductionTFA::loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD)
 {
   _clusteringData->loadClusterStandDevFromFile(ClusterStrainConcentrationSTD);
-  _clusteringData->loadInteractionStandDevFromFile(InteractionSTD);
 };
 
-void ReductionTFA::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName, const std::string EshelbyInteractionSTD)
+void ReductionTFA::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName)
 {
   _clusteringData->loadEshelbyInteractionTensorsFromFile(EshelbyInteractionTensorsFileName);
-  _clusteringData->loadEshelbyInteractionStandDevFromFile(EshelbyInteractionSTD);
 };
 
 void ReductionTFA::loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName,
                                                             const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                            const std::string PlasticEqStrainConcentrationHarmonicFileName)
+                                                            const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                            const std::string PlasticEqStrainConcentrationPowerFileName)
 {
   _clusteringData->loadClusterPlasticEqSummaryFromFile(PlasticEqStrainConcentrationFileName);
   _clusteringData->loadClusterPlasticEqSummaryGeometricFromFile(PlasticEqStrainConcentrationGeometricFileName);
   _clusteringData->loadClusterPlasticEqSummaryHarmonicFromFile(PlasticEqStrainConcentrationHarmonicFileName);
+  _clusteringData->loadClusterPlasticEqSummaryPowerFromFile(PlasticEqStrainConcentrationPowerFileName);
 };
 
 
@@ -182,6 +194,27 @@ void ReductionTFA::loadElasticStrainConcentrationDerivativeFromFile(const std::s
   _clusteringData->loadElasticStrainConcentrationDerivativeFromFile(ElasticStrainConcentrationDerivative);
 };
 
+
+void ReductionTFA::loadReferenceStiffnessFromFile(const std::string ReferenceStiffnessFileName)
+{
+  _clusteringData->loadReferenceStiffnessFromFile(ReferenceStiffnessFileName);
+};
+
+void ReductionTFA::loadReferenceStiffnessIsoFromFile(const std::string ReferenceStiffnessIsoFileName)
+{
+  _clusteringData->loadReferenceStiffnessIsoFromFile(ReferenceStiffnessIsoFileName);
+};
+
+void ReductionTFA::loadInteractionTensorIsoFromFile(const std::string InteractionTensorIsoFileName)
+{
+  _clusteringData->loadInteractionTensorIsoFromFile(InteractionTensorIsoFileName);
+};
+
+void ReductionTFA::loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName)
+{
+  _clusteringData->loadClusterFiberOrientationFromFile(OrientationDataFileName);
+};
+
 const STensor43& ReductionTFA::getClusterAverageStrainConcentrationTensor(int cl) const
 {
   std::map<int,STensor43>::const_iterator Afind= _clusteringData->getClusterAverageStrainConcentrationTensorMap().find(cl);
@@ -198,6 +231,7 @@ double ReductionTFA::getClusterNonUniformCorrection(int cl, const STensor3& macr
 {
   std::map<int,fullVector<double>>::const_iterator plasticEqMeanMap_find = _clusteringData->getClusterAveragePlasticEqStrainConcentrationVectorMap().find(cl);
   std::map<int,fullVector<double>>::const_iterator plasticEqHarmonicMeanMap_find = _clusteringData->getClusterAverageHarmonicPlasticEqStrainConcentrationVectorMap().find(cl); 
+  //std::map<int,fullVector<double>>::const_iterator plasticEqPowerMeanMap_find = _clusteringData->getClusterAveragePowerPlasticEqStrainConcentrationVectorMap().find(cl); 
   #ifdef _DEBUG
   if (plasticEqMeanMap_find == _clusteringData->getClusterAveragePlasticEqStrainConcentrationVectorMap().end())
   {
@@ -207,6 +241,7 @@ double ReductionTFA::getClusterNonUniformCorrection(int cl, const STensor3& macr
   #endif //_
   const fullVector<double> p_offline_mean_loc_vector = (plasticEqMeanMap_find)->second;
   const fullVector<double> p_offline_harmean_loc_vector = (plasticEqHarmonicMeanMap_find)->second;
+  //const fullVector<double> p_offline_powermean_loc_vector = (plasticEqPowerMeanMap_find)->second;
   fullVector<double> clusterCorrections(2); 
   for(int j=0; j < 2; j++)
   {
@@ -214,6 +249,7 @@ double ReductionTFA::getClusterNonUniformCorrection(int cl, const STensor3& macr
     clusterCorrections(j) = sqrt(p_offline_mean_loc_vector(j)/p_offline_harmean_loc_vector(j));
     }
     else{clusterCorrections(j) = 1.;}
+    //clusterCorrections(j) = p_offline_powermean_loc_vector(j)/p_offline_mean_loc_vector(j);
   }
   STensor3 macrodeps = macroeps;
   macrodeps -= macroeps0; 
@@ -242,7 +278,21 @@ double ReductionTFA::getClusterNonUniformCorrection(int cl, const STensor3& macr
 
 const STensor43& ReductionTFA::getClusterInteractionTensor(int icl, int jcl) const
 {
-  std::map<std::pair<int,int>,STensor43>::const_iterator Dfind = _clusteringData->getClusterInteractionTensorMap().find(std::pair<int,int>(icl,jcl));
+  std::map<std::pair<int,int>,STensor43>::const_iterator Dfind;
+  if(_withFrame)
+  {
+  Dfind = _clusteringData->getClusterInteractionTensorHomogenizedFrameELMap().find(std::pair<int,int>(icl,jcl));
+  #ifdef _DEBUG
+  if (Dfind == _clusteringData->getClusterInteractionTensorHomogenizedFrameELMap().end())
+  {
+    Msg::Error("cluster %d does not exist!");
+    Msg::Exit(0);
+  }
+  #endif //_  
+  }
+  else
+  {
+  Dfind = _clusteringData->getClusterInteractionTensorMap().find(std::pair<int,int>(icl,jcl));
   #ifdef _DEBUG
   if (Dfind == _clusteringData->getClusterInteractionTensorMap().end())
   {
@@ -250,6 +300,7 @@ const STensor43& ReductionTFA::getClusterInteractionTensor(int icl, int jcl) con
     Msg::Exit(0);
   }
   #endif //_
+  }
   return Dfind->second;
 };
 const materialLaw* ReductionTFA::getLawForCluster(int cl) const
@@ -266,6 +317,64 @@ const materialLaw* ReductionTFA::getLawForCluster(int cl) const
 };
 
 
+const STensor43& ReductionTFA::getClusterStrainConcentrationStDTensor(int cl) const
+{
+  std::map<int,STensor43>::const_iterator Astdfind= _clusteringData->getClusterSTDTensorMap().find(cl);
+  #ifdef _DEBUG
+  if (Astdfind == _clusteringData->getClusterSTDTensorMap().end())
+  {
+    Msg::Error("cluster %d does not exist!");
+    Msg::Exit(0);
+  }
+  #endif //_
+  return Astdfind->second;
+};
+const double& ReductionTFA::getClusterStrainConcentrationStDScalar(int cl) const
+{
+  std::map<int,double>::const_iterator astdfind= _clusteringData->getClusterSTDMap().find(cl);
+  #ifdef _DEBUG
+  if (astdfind == _clusteringData->getClusterSTDMap().end())
+  {
+    Msg::Error("cluster %d does not exist!");
+    Msg::Exit(0);
+  }
+  #endif //_
+  return astdfind->second;
+};
+
+
+const STensor43& ReductionTFA::getClusterInteractionTensorIso(int icl, int jcl) const
+{
+  std::map<std::pair<int,int>,STensor43>::const_iterator Dfind;
+
+  Dfind = _clusteringData->getClusterInteractionTensorIsoMap().find(std::pair<int,int>(icl,jcl));
+  #ifdef _DEBUG
+  if (Dfind == _clusteringData->getClusterInteractionTensorIsoMap().end())
+  {
+    Msg::Error("cluster %d does not exist!");
+    Msg::Exit(0);
+  }
+  #endif //_
+  return Dfind->second;
+};
+
+
+const fullVector<double>& ReductionTFA::getClusterMeanFiberOrientation(int cl) const
+{
+  std::map<int,fullVector<double>>::const_iterator ori;
+
+  ori = _clusteringData->getClusterMeanFiberOrientation().find(cl);
+  #ifdef _DEBUG
+  if (ori == _clusteringData->getClusterMeanFiberOrientation().end())
+  {
+    Msg::Error("cluster %d does not exist!");
+    Msg::Exit(0);
+  }
+  #endif //_
+  return ori->second;
+};
+
+
 void ReductionTFA::evaluate(
             const STensor3& F0,         // initial deformation gradient (input @ time n)
             const STensor3& Fn,         // updated deformation gradient (input @ time n+1)
@@ -309,9 +418,13 @@ void ReductionTFA::initSolve(const ClusteringData *q0,  const ClusteringData *q1
 void ReductionTFA::numberDof()
 {
   _unknown.clear();
-  int numCluster = _clusteringData->getTotalNumberOfClusters();
-  Msg::Info("dof numbering, number of clusters = %d",numCluster);
-  for (int icl =0; icl < numCluster; icl ++)
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if(_withFrame)
+  {
+    nbClusters += 1;
+  }
+  Msg::Info("dof numbering, number of clusters = %d",nbClusters);
+  for (int icl =0; icl < nbClusters; icl ++)
   {
     std::vector<Dof> R;
     getKeys(icl,R);
@@ -334,6 +447,10 @@ void ReductionTFA::numberDof()
 void ReductionTFA::setInitialState(const STensor3& F0, const STensor3& Fn)
 {
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if(_withFrame)
+  {
+    nbClusters += 1;
+  }
   for (int icl = 0; icl < nbClusters; icl++)
   {
     std::vector<Dof> R;
@@ -350,7 +467,7 @@ void ReductionTFA::setInitialState(const STensor3& F0, const STensor3& Fn)
         addToSolution(row,val(j));
       }
     }
-  };
+  }
 };
 
 void ReductionTFA::createSystem(int numR)
@@ -391,13 +508,28 @@ void ReductionTFA::preallocateSystem(const ClusteringData *q0,  const Clustering
   // spasiry 
   if (_sys != NULL)
   {
-    int numCluster = _clusteringData->getTotalNumberOfClusters();
-    for (int icl = 0; icl < numCluster; icl++)
+    int nbClusters = _clusteringData->getTotalNumberOfClusters();
+    if(_withFrame)
+    {
+      nbClusters += 1;
+    }
+    for (int icl = 0; icl < nbClusters; icl++)
     {
       static fullMatrix<double> m;
       std::vector<int> othersId;
-      getBiLinearTerm(icl,q0,q1, othersId, m);
-
+      if(_withFrame)
+      {
+        getBiLinearTermWithFrame(icl,q0,q1, othersId, m);
+      }
+      else if(_polarization)
+      {
+        getBiLinearTermPolarization(icl,q0,q1, othersId, m);
+      }
+      else
+      {
+        getBiLinearTerm(icl,q0,q1, othersId, m);
+      }
+      //printf("Sizes %d x %d \n",m.size1(),m.size2());
       std::vector<Dof> R, C;
       getKeys(icl,R);
       for (int jcl=0; jcl< othersId.size(); jcl++)
@@ -546,8 +678,7 @@ void ReductionTFA::zeroMultipleRHS()
   else
   {
      _multipleRHS.setAll(0.);
-     _multipleSolution.setAll(0.);
-     
+     _multipleSolution.setAll(0.);    
   }
 };
 
@@ -625,66 +756,173 @@ void ReductionTFA::assembleRes(const ClusteringData *q0,  const ClusteringData *
 {
   zeroRHS();
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
-  for (int icl = 0; icl < nbClusters; icl++)
+  static fullVector<double> r;
+  if(_withFrame)
   {
-    static fullVector<double> r;
-    getLinearTerm(icl,q0,q1,r);
-    std::vector<Dof> R;
-    getKeys(icl,R);
-    for (int j=0; j<R.size(); j++)
+    for (int icl = 0; icl < (nbClusters+1); icl++)
     {
-      std::map<Dof,int>::iterator it =  _unknown.find(R[j]);
-      if (it != _unknown.end())
+      getLinearTermWithFrame(icl,q0,q1,r);
+      std::vector<Dof> R;
+      getKeys(icl,R);
+      for (int j=0; j<R.size(); j++)
       {
-        int row = it->second;
-        addToRHS(row,r(j));
+        std::map<Dof,int>::iterator it =  _unknown.find(R[j]);
+        if (it != _unknown.end())
+        {
+          int row = it->second;
+          addToRHS(row,r(j));
+        }
+      }
+    } 
+  }
+  else if(_polarization)
+  {
+    for (int icl = 0; icl < nbClusters; icl++)
+    {
+      getLinearTermPolarization(icl,q0,q1,r);
+      std::vector<Dof> R;
+      getKeys(icl,R);
+      for (int j=0; j<R.size(); j++)
+      {
+        std::map<Dof,int>::iterator it =  _unknown.find(R[j]);
+        if (it != _unknown.end())
+        {
+          int row = it->second;
+          addToRHS(row,r(j));
+        }
+      }
+    }
+  }
+  else
+  {
+    for (int icl = 0; icl < nbClusters; icl++)
+    {
+      getLinearTerm(icl,q0,q1,r);
+      std::vector<Dof> R;
+      getKeys(icl,R);
+      for (int j=0; j<R.size(); j++)
+      {
+        std::map<Dof,int>::iterator it =  _unknown.find(R[j]);
+        if (it != _unknown.end())
+        {
+          int row = it->second;
+          addToRHS(row,r(j));
+        }
       }
     }
   }
 };
-
 void ReductionTFA::assembleDresDu(const ClusteringData *q0,  const ClusteringData *q1)
 {
   //Msg::Info("calling assembleDresDu");
   zeroMatrix();
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
-  for (int icl = 0; icl < nbClusters; icl++)
+  static fullMatrix<double> Ke;
+  std::vector<int> othersId;
+  
+  if(_withFrame)
   {
-    static fullMatrix<double> Ke;
-    std::vector<int> othersId;
-    getBiLinearTerm(icl,q0,q1,othersId,Ke);
-    //Ke.print("Ke");
-    //
-    std::vector<Dof> R, C;
-    getKeys(icl,R);
-    for (int jcl=0; jcl< othersId.size(); jcl++)
+    for (int icl = 0; icl < (nbClusters+1); icl++)
+    {
+      getBiLinearTermWithFrame(icl,q0,q1,othersId,Ke);
+      ///Ke.print("KKKKKKK");
+      std::vector<Dof> R, C;
+      getKeys(icl,R);
+      for (int jcl=0; jcl< othersId.size(); jcl++)
+      {
+        getKeys(othersId[jcl],C);
+      }
+      for (int iR=0; iR < R.size(); iR++)
+      {
+        std::map<Dof,int>::iterator itR =  _unknown.find(R[iR]);
+        if (itR != _unknown.end())
+        {
+          int row = itR->second;
+          for (int iC =0; iC < C.size(); iC++)
+          {
+            std::map<Dof,int>::iterator itC =  _unknown.find(C[iC]);
+            if (itC != _unknown.end())
+            {
+              int col = itC->second;
+              addToMatrix(row,col,Ke(iR,iC));
+            }
+          }
+        }
+      }
+    }
+  }
+  else if(_polarization)
+  {
+    for (int icl = 0; icl < nbClusters; icl++)
     {
-      getKeys(othersId[jcl],C);
+      getBiLinearTermPolarization(icl,q0,q1,othersId,Ke);
+      //Ke.print("Ke");
+      //
+      std::vector<Dof> R, C;
+      getKeys(icl,R);
+      for (int jcl=0; jcl< othersId.size(); jcl++)
+      {
+        getKeys(othersId[jcl],C);
+      }
+      for (int iR=0; iR < R.size(); iR++)
+      {
+        std::map<Dof,int>::iterator itR =  _unknown.find(R[iR]);
+        if (itR != _unknown.end())
+        {
+          int row = itR->second;
+          for (int iC =0; iC < C.size(); iC++)
+          {
+            std::map<Dof,int>::iterator itC =  _unknown.find(C[iC]);
+            if (itC != _unknown.end())
+            {
+              int col = itC->second;
+              addToMatrix(row,col,Ke(iR,iC));
+            }
+          }
+        }
+      }
     }
-    //
-    for (int iR=0; iR < R.size(); iR++)
+  }
+  else
+  {
+    for (int icl = 0; icl < nbClusters; icl++)
     {
-      std::map<Dof,int>::iterator itR =  _unknown.find(R[iR]);
-      if (itR != _unknown.end())
+      getBiLinearTerm(icl,q0,q1,othersId,Ke);
+      //Ke.print("Ke");
+      //
+      std::vector<Dof> R, C;
+      getKeys(icl,R);
+      for (int jcl=0; jcl< othersId.size(); jcl++)
       {
-        int row = itR->second;
-        for (int iC =0; iC < C.size(); iC++)
+        getKeys(othersId[jcl],C);
+      }
+      for (int iR=0; iR < R.size(); iR++)
+      {
+        std::map<Dof,int>::iterator itR =  _unknown.find(R[iR]);
+        if (itR != _unknown.end())
         {
-          std::map<Dof,int>::iterator itC =  _unknown.find(C[iC]);
-          if (itC != _unknown.end())
+          int row = itR->second;
+          for (int iC =0; iC < C.size(); iC++)
           {
-            int col = itC->second;
-            addToMatrix(row,col,Ke(iR,iC));
-          };
-        };
-      };
-    };
-  };
+            std::map<Dof,int>::iterator itC =  _unknown.find(C[iC]);
+            if (itC != _unknown.end())
+            {
+              int col = itC->second;
+              addToMatrix(row,col,Ke(iR,iC));
+            }
+          }
+        }
+      }
+    }
+  }
 };
-
 void ReductionTFA::updateFieldFromUnknown(const ClusteringData *q0,  ClusteringData *q1)
 {
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if(_withFrame)
+  {
+    nbClusters += 1;
+  }
   for (int icl = 0; icl < nbClusters; icl++)
   {
     std::vector<Dof> R;
@@ -707,10 +945,6 @@ void ReductionTFA::updateFieldFromUnknown(const ClusteringData *q0,  ClusteringD
     updateLocalFieldFromDof(icl,val,q0,q1);
   };
 };
-
-
-
-
 bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
                 const ClusteringData *q0,  ClusteringData *q1,  
                 STensor3& P, bool stiff, STensor43& L, 
@@ -726,9 +960,9 @@ bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
   initialZeroSolution();
   //
   setInitialState(F0,F1);
-  //
   updateFieldFromUnknown(q0,q1);
   //estimate strains at each clusters and evaluate constitutive relation
+
   localConstitutive(F0,F1,q0,q1);
 
   if (messageActive)
@@ -745,6 +979,7 @@ bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
     assembleRes(q0,q1);
     //
     double resNorm = normInfRightHandSide();
+    //printf("resNorm0000000 = %.4e\n",resNorm);
     if (iter == 0)
     {
       norm0 = resNorm;
@@ -768,7 +1003,6 @@ bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
       }
       break;
     };
-
     if (resNorm > tol*norm0)
     {
       stiffnessEstimated = true;
@@ -811,6 +1045,9 @@ bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
   {
     // get Stress
     q1->computeHomogenizedStress(P);
+    STensor3& PHom = q1->getRefToMacroStress();
+    PHom = P;
+    //STensor43& CtanHom = q1->getRefToMacroTangent();
     if (stiff)
     {
       if (!stiffnessEstimated)
@@ -818,6 +1055,9 @@ bool ReductionTFA::systemSolve(const STensor3& F0, const STensor3& F1,
         assembleDresDu(q0,q1);
       }
       bool succ = tangentSolve(q0,q1,L);
+      //P.print("STRESS");
+      //L.print("TANGENT");
+      //CtanHom = L;
     }
     //
     return true;
@@ -835,11 +1075,15 @@ bool ReductionTFA::tangentSolve(const ClusteringData *q0, const ClusteringData *
   bool isAllocated=false;
     //
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if (_withFrame)
+  {
+    nbClusters += 1;
+  }
   for (int icl=0; icl < nbClusters; icl++)
   {
-    static fullMatrix<double> m;
+    static fullMatrix<double> m;   
     getTangentTerm(icl,q0,q1,m);
-    
+
     if (!isAllocated)
     {
       strainDim = m.size2();
@@ -882,6 +1126,7 @@ bool ReductionTFA::tangentSolve(const ClusteringData *q0, const ClusteringData *
     vtotal += vCluster;
     static fullMatrix<double> Licluster;
     STensorOperation::fromSTensor43ToFullMatrix( q1->getConstRefToTangent(icl),Licluster);
+    //printf("vCluster: %d \n", icl);
     //
     std::vector<Dof> R;
     getKeys(icl,R);
@@ -935,8 +1180,12 @@ void ReductionTFA::fixDofs()
   if (getDim() == 2)
   {
     _fixedDof.clear();
-    int numCluster = _clusteringData->getTotalNumberOfClusters();
-    for (int clusterId=0; clusterId< numCluster; clusterId++)
+    int nbClusters = _clusteringData->getTotalNumberOfClusters();
+    if(_withFrame)
+    {
+      nbClusters += 1;
+    }
+    for (int clusterId=0; clusterId< nbClusters; clusterId++)
     {
       _fixedDof[Dof(clusterId, Dof::createTypeWithTwoInts(2,_tag))] = 0.;
       _fixedDof[Dof(clusterId, Dof::createTypeWithTwoInts(4,_tag))] = 0.;
@@ -974,77 +1223,79 @@ void ReductionTFA::getDLocalStrainDKeys(int clusterId, const ClusteringData *q0,
 };
 void ReductionTFA::getInitialDofValue(int clusterId, const STensor3& F0, const STensor3& Fn, fullVector<double>& val) const
 {
-  //val.resize(6,true); // set to zero 
-  const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
+  //val.resize(6,true); // set to zero  
   STensor3 Deps;
   Deps = Fn;
-  Deps -= F0;
-  static STensor3 temp;
-  STensorOperation::multSTensor43STensor3(Ai,Deps,temp);
-  STensorOperation::fromSTensor3ToFullVector(temp,val);
+  Deps -= F0;  
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if(clusterId == nbClusters)
+  {
+    STensorOperation::fromSTensor3ToFullVector(Deps,val);
+  }
+  else
+  {
+    const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
+    static STensor3 temp;
+    STensorOperation::multSTensor43STensor3(Ai,Deps,temp);
+    STensorOperation::fromSTensor3ToFullVector(temp,val);
+  }
 };
 void ReductionTFA::updateLocalFieldFromDof(int clusterId, const fullVector<double>& vals, const ClusteringData *q0,  ClusteringData *q1)
 {
-  const STensor3& eps0 = q0->getConstRefToStrain(clusterId);
-  STensor3& eps = q1->getRefToStrain(clusterId);
-  eps = eps0;
-  //
-  static STensor3 Deps;
-  STensorOperation::fromFullVectorToSTensor3(vals,Deps);
-  eps += Deps;
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  if(clusterId == nbClusters)
+  {
+    const STensor3& eps0 = q0->getConstRefToFrameStrain();
+    STensor3& eps = q1->getRefToFrameStrain();
+    eps = eps0;   
+    static STensor3 Deps;
+    STensorOperation::fromFullVectorToSTensor3(vals,Deps);
+    eps += Deps;
+  }
+  else
+  {
+    const STensor3& eps0 = q0->getConstRefToStrain(clusterId);
+    STensor3& eps = q1->getRefToStrain(clusterId);
+    eps = eps0;
+    static STensor3 Deps;
+    STensorOperation::fromFullVectorToSTensor3(vals,Deps);
+    eps += Deps;
+  }
 };
 
 
 void ReductionTFA::getLinearTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const
 {
   int nbClusters = _clusteringData->getTotalNumberOfClusters();
-  const STensor3& eps0 = q0->getConstRefToStrain(clusterId);
-  const STensor3& eps1 = q1->getConstRefToStrain(clusterId);
+  const STensor3& eps0i = q0->getConstRefToStrain(clusterId);
+  const STensor3& eps1i = q1->getConstRefToStrain(clusterId);
   //
   const STensor3& macroeps0 = q0->getConstRefToMacroStrain();
   const STensor3& macroeps1 = q1->getConstRefToMacroStrain();
   
   const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
   static STensor3 resTen;
-  resTen = eps1;
-  resTen -= eps0;
+  resTen = eps1i;
+  resTen -= eps0i;
   STensorOperation::multSTensor43STensor3Add(Ai,macroeps0,1.,resTen);
   STensorOperation::multSTensor43STensor3Add(Ai,macroeps1,-1.,resTen);
- 
-  /*if(_correction==1){
-  double corr_total = 0.;
-  const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
-  double vtotal = 0.;
-  for (std::map<int,double>::const_iterator itc = cluterVolumeMap.begin(); itc != cluterVolumeMap.end(); itc++)
-  {
-    int icl = itc->first;
-    double vCluster = itc->second;
-    vtotal += vCluster;
-    double corr_i = getClusterNonUniformCorrection(icl);
-    corr_total += vCluster*corr_i;  
-  }
-  corr_total *= (1./vtotal);
-  printf("total correction = %.5f \n",corr_total);
-  }*/
   
   for (int jcl =0; jcl < nbClusters; jcl++)
   {
     const STensor43 &Dij =  getClusterInteractionTensor(clusterId,jcl);    
-    const STensor3& eig0 = q0->getConstRefToEigenStrain(jcl);
-    const STensor3& eig1 = q1->getConstRefToEigenStrain(jcl);
     
+    const STensor3& epsEig0j = q0->getConstRefToEigenStrain(jcl);
+    const STensor3& epsEig1j = q1->getConstRefToEigenStrain(jcl);
     
-    //printf("CORR %d \n", _correction);
     if(_correction==1){
     double corr_j = getClusterNonUniformCorrection(jcl,q0->getConstRefToMacroStrain(),q1->getConstRefToMacroStrain());
-    //printf("correction = %.3f \n",corr_j);
-    STensorOperation::multSTensor43STensor3Add(Dij,eig1,1.*corr_j,resTen);
-    STensorOperation::multSTensor43STensor3Add(Dij,eig0,-1.*corr_j,resTen);
+    STensorOperation::multSTensor43STensor3Add(Dij,epsEig1j,1.*corr_j,resTen);
+    STensorOperation::multSTensor43STensor3Add(Dij,epsEig0j,-1.*corr_j,resTen);
     }
     else
     {
-    STensorOperation::multSTensor43STensor3Add(Dij,eig1,1.,resTen);
-    STensorOperation::multSTensor43STensor3Add(Dij,eig0,-1.,resTen);
+    STensorOperation::multSTensor43STensor3Add(Dij,epsEig1j,1.,resTen);
+    STensorOperation::multSTensor43STensor3Add(Dij,epsEig0j,-1.,resTen);    
     }
   };
   STensorOperation::fromSTensor3ToFullVector(resTen,res);
@@ -1059,54 +1310,714 @@ void ReductionTFA::getBiLinearTerm(int clusterId, const ClusteringData *q0,  con
   }
   dres.resize(6,6*nbClusters,true);
   
-  static STensor43 Ifourth(1.,1.);
+  double vtot;
+  vtot = totalVolume();
+  
   for (int jcl=0; jcl< nbClusters; jcl++)
   {
-    static STensor43 dresdeps;
-    if (jcl== clusterId)
-    {
-      dresdeps = Ifourth;
-    }
-    else
-    {
-      STensorOperation::zero(dresdeps);
-    }
-    const STensor43 &Dij =  getClusterInteractionTensor(clusterId,jcl);
-    const STensor43 &deig1dstrain =  q1->getConstRefTodEigenStraindStrain(jcl);
-    if(_correction==1){
-    double corr_j = getClusterNonUniformCorrection(jcl,q0->getConstRefToMacroStrain(),q1->getConstRefToMacroStrain());
-    STensorOperation::multSTensor43Add(Dij,deig1dstrain,1.*corr_j,dresdeps);
-    }
-    else{
-    STensorOperation::multSTensor43Add(Dij,deig1dstrain,1.,dresdeps);
-    }
-    static fullMatrix<double> matFromT;
-    STensorOperation::fromSTensor43ToFullMatrix(dresdeps,matFromT);
+    static STensor43 J_ij;
+    getJac_rs(clusterId,jcl,q0,q1,J_ij);
+    static fullMatrix<double> J_ij_matrix;
+    STensorOperation::fromSTensor43ToFullMatrix(J_ij,J_ij_matrix);
     for (int row=0; row<6; row++)
     {
       for (int col=0; col<6; col++)
       {
-        dres(row, col+6*jcl) += matFromT(row,col);
+        dres(row, col+6*jcl) += J_ij_matrix(row,col);
       }
-    };
-  };
-};
+    }
+  }
+}
+
+void ReductionTFA::getJac_rs(int r, int s, const ClusteringData *q0,  const ClusteringData *q1, STensor43& Jac_rs) const 
+{
+  if (r==s)
+  {
+    STensorOperation::unity(Jac_rs);
+  }
+  else
+  {
+    STensorOperation::zero(Jac_rs);
+  }
+  
+  const STensor43 &Drs =  getClusterInteractionTensor(r,s);
+  const STensor43 &depsEig1dstrains =  q1->getConstRefTodEigenStraindStrain(s);
+  if(_correction==1){
+  double corr_s = getClusterNonUniformCorrection(s,q0->getConstRefToMacroStrain(),q1->getConstRefToMacroStrain());
+  STensorOperation::multSTensor43Add(Drs,depsEig1dstrains,1.*corr_s,Jac_rs);
+  }
+  else{
+  STensorOperation::multSTensor43Add(Drs,depsEig1dstrains,1.,Jac_rs);
+  }
+}
+
 void ReductionTFA::getTangentTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullMatrix<double>& DresDdefo) const
 {
-  const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
-  STensorOperation::fromSTensor43ToFullMatrix(Ai,DresDdefo);
-  DresDdefo.scale(-1.);
+  if(_withFrame)
+  {
+    int nbClusters = _clusteringData->getTotalNumberOfClusters();
+    STensor43 dResdDeps;
+    if(clusterId == nbClusters)
+    {
+      STensorOperation::unity(dResdDeps);
+    }
+    else
+    {
+      STensorOperation::zero(dResdDeps);
+    }
+    STensorOperation::fromSTensor43ToFullMatrix(dResdDeps,DresDdefo);
+  }
+  else if(_polarization)
+  {
+    STensor43 dResdDeps;
+    STensorOperation::unity(dResdDeps);
+    STensorOperation::fromSTensor43ToFullMatrix(dResdDeps,DresDdefo);
+    DresDdefo.scale(-1.);
+  }
+  else
+  {
+    const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
+    STensorOperation::fromSTensor43ToFullMatrix(Ai,DresDdefo);
+    DresDdefo.scale(-1.);
+  }
+};
+
+
+void ReductionTFA::getLinearTermPolarization(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  
+  const STensor3& eps1i = q1->getConstRefToStrain(clusterId);
+  const STensor3& eps0i = q0->getConstRefToStrain(clusterId);
+  
+  const STensor3& macroeps1 = q1->getConstRefToMacroStrain();
+  const STensor3& macroeps0 = q0->getConstRefToMacroStrain();
+  
+  double epsEq = TFANumericTools::EquivalentStrain(macroeps1);
+
+  static STensor3 resTen;  
+  resTen = eps1i;
+  resTen -= eps0i;
+  resTen -= macroeps1;
+  resTen += macroeps0;
+  
+  const STensor43& C0iso = _clusteringData->getReferenceStiffnessIso();
+  //const STensor43& C0 = _clusteringData->getReferenceStiffness();
+  double G0 = C0iso(0,1,0,1);
+  const double& Gtan = q1->getConstRefToTangentShearModulus();
+  
+  //STensor43 Ciso_inv, C_inv;
+  //if(epsEq>1.e-10)
+  //{
+    //const STensor43& CisoUpdate_inv = q1->getConstRefToIsotropicStiffnessInverted();
+    //const STensor43& CanisoUpdate_inv = q1->getConstRefToAnisotropicStiffnessInverted();
+    //Ciso_inv = CisoUpdate_inv;
+    //C_inv = CanisoUpdate_inv;
+  //}
+  //else
+  //{
+    //STensor43 C0iso_inv;
+    //STensorOperation::inverseSTensor43(C0iso,C0iso_inv); 
+    //Ciso_inv = C0iso_inv;
+    
+    //STensor43 C0_inv;
+    //STensorOperation::inverseSTensor43(C0,C0_inv); 
+    //C_inv = C0_inv;
+  //}
+  
+  for (int jcl =0; jcl < nbClusters; jcl++)
+  {
+    const STensor43 &Dij =  getClusterInteractionTensor(clusterId,jcl);
+    
+    const STensor3& sig1j = q1->getConstRefToStress(jcl);
+    const STensor3& eps1j = q1->getConstRefToStrain(jcl);      
+    const STensor3& sig0j = q0->getConstRefToStress(jcl);
+    const STensor3& eps0j = q0->getConstRefToStrain(jcl);
+    
+    STensor3 dsigj(sig1j);
+    dsigj -= sig0j;
+    STensor3 depsj(eps1j);
+    depsj -= eps0j; 
+    
+    STensor3 fac;    
+    fac = dsigj;
+    fac *= G0/Gtan;
+    //STensor43 prefac;
+    //STensorOperation::multSTensor43(C0iso,Ciso_inv,prefac);
+    //STensorOperation::multSTensor43STensor3(prefac,dsigj,fac);
+    STensorOperation::multSTensor43STensor3Add(C0iso,depsj,-1.,fac);
+
+
+    //STensorOperation::multSTensor43(C0,C_inv,prefac);
+    //STensorOperation::multSTensor43STensor3(prefac,dsigj,fac);
+    //STensorOperation::multSTensor43STensor3Add(C0,depsj,-1.,fac);
+    
+         
+    STensorOperation::multSTensor43STensor3Add(Dij,fac,-1.,resTen);          
+  }
+  STensorOperation::fromSTensor3ToFullVector(resTen,res);
 };
+void ReductionTFA::getBiLinearTermPolarization(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& dres) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  othersId.resize(nbClusters);
+  for (int j=0; j< nbClusters; j++)
+  {
+    othersId[j] = j;
+  }
+  dres.resize(6,6*nbClusters,true);
+  
+  double vtot;
+  vtot = totalVolume();
+  
+  for (int jcl=0; jcl< nbClusters; jcl++)
+  {
+    static STensor43 J_ij;
+    getJacPolarization_rs(clusterId,jcl,q0,q1,J_ij);
+    static fullMatrix<double> J_ij_matrix;
+    STensorOperation::fromSTensor43ToFullMatrix(J_ij,J_ij_matrix);
+    for (int row=0; row<6; row++)
+    {
+      for (int col=0; col<6; col++)
+      {
+        dres(row, col+6*jcl) += J_ij_matrix(row,col);
+      }
+    }
+  }
+}
+void ReductionTFA::getJacPolarization_rs(int r, int s, const ClusteringData *q0,  const ClusteringData *q1, STensor43& Jac_rs) const 
+{
+  if (r==s)
+  {
+    STensorOperation::unity(Jac_rs);
+  }
+  else
+  {
+    STensorOperation::zero(Jac_rs);
+  }
+  
+  const STensor3& macroeps1 = q1->getConstRefToMacroStrain(); 
+  double epsEq = TFANumericTools::EquivalentStrain(macroeps1);
+  
+  const STensor43& C0iso = _clusteringData->getReferenceStiffnessIso();
+  //const STensor43& C0 = _clusteringData->getReferenceStiffness();
+  double G0 = C0iso(0,1,0,1);
+  const double& Gtan = q1->getConstRefToTangentShearModulus(); 
+  const STensor43 &Drs =  getClusterInteractionTensor(r,s); 
+  const STensor43 &Calgs = q1->getConstRefToTangent(s);
+  
+  //STensor43 Ciso_inv, C_inv;
+  //if(epsEq>1.e-10)
+  //{
+    //const STensor43& CisoUpdate_inv = q1->getConstRefToIsotropicStiffnessInverted();
+    //const STensor43& CanisoUpdate_inv = q1->getConstRefToAnisotropicStiffnessInverted();   
+    //Ciso_inv = CisoUpdate_inv;
+    //C_inv = CanisoUpdate_inv;
+  //}
+  //else
+  //{
+    //STensor43 C0iso_inv;
+    //STensorOperation::inverseSTensor43(C0iso,C0iso_inv); 
+    //Ciso_inv = C0iso_inv;
+    
+    //STensor43 C0_inv;
+    //STensorOperation::inverseSTensor43(C0,C0_inv); 
+    //C_inv = C0_inv;
+  //}
+  
+  const STensor3& sig1s = q1->getConstRefToStress(s);
+  const STensor3& sig0s = q0->getConstRefToStress(s);   
+  STensor3 dsigs(sig1s);
+  dsigs -= sig0s;
+   
+  STensor43 fac; 
+  fac = Calgs;
+  fac *= G0/Gtan;
+  //STensor43 prefac;
+  //STensorOperation::multSTensor43(C0iso,Ciso_inv,prefac);
+  //STensorOperation::multSTensor43(prefac,Calgs,fac);
+  fac -= C0iso;
+  
+  //STensorOperation::multSTensor43(C0,C_inv,prefac);
+  //STensorOperation::multSTensor43(prefac,Calgs,fac);
+  //fac -= C0;
+  
+  STensorOperation::multSTensor43Add(Drs,fac,-1.,Jac_rs);
+  
+  STensor3 dGtandeps;
+  dtangentShearModulusOveralldeps(q0,q1,s,dGtandeps);
+  STensor3 fac2_part;
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+  for (int p =0; p < nbClusters; p++)
+  {
+    const STensor43 &Drp =  getClusterInteractionTensor(r,p);
+    const STensor3& sig1p = q1->getConstRefToStress(p);
+    const STensor3& sig0p = q0->getConstRefToStress(p); 
+    STensor3 Dsigp(sig1p);
+    Dsigp -= sig0p; 
+    STensorOperation::multSTensor43STensor3Add(Drp,Dsigp,1.,fac2_part);
+  }
+  fac2_part *= G0/(Gtan*Gtan);
+  STensorOperation::prodAdd(fac2_part,dGtandeps,1.,Jac_rs);
+}
 
+void ReductionTFA::elasticStiffnessHom(STensor43& CelHom) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+
+  STensorOperation::zero(CelHom);
+  double vtot;
+  vtot = 0.;
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+    std::map<int,double>::const_iterator itc = cluterVolumeMap.find(icl);
+    double vi = itc->second;
+    vtot += vi;    
+    const materialLaw *law = getLawForCluster(icl); 
+    STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    const STensor43 &Aeli = getClusterAverageStrainConcentrationTensor(icl);
+    STensorOperation::multSTensor43Add(Celi,Aeli,vi,CelHom);
+  }
+  CelHom *= (1./vtot);
+}
+
+void ReductionTFA::elasticTotalTrialStressHom(const ClusteringData *q,STensor3& PtrHom) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+  
+  //const STensor3& macroEps = q->getConstRefToMacroStrain();
+
+  STensorOperation::zero(PtrHom);
+  double vtot;
+  vtot = 0.;
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+    std::map<int,double>::const_iterator itc = cluterVolumeMap.find(icl);
+    double vi = itc->second;
+    vtot += vi;
+    
+    /*const STensor43 &Aeli = getClusterAverageStrainConcentrationTensor(icl);
+    STensor3 epsi;
+    STensorOperation::multSTensor43STensor3(Aeli,macroEps,eps1i);*/
+    
+    const STensor3& eps1i = q->getConstRefToStrain(icl);
+    
+    const materialLaw *law = getLawForCluster(icl); 
+    STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    STensorOperation::multSTensor43STensor3Add(Celi,eps1i,vi,PtrHom);
+  }
+  PtrHom *= (1./vtot);
+}
+
+void ReductionTFA::elasticIncrementalTrialStressHom(const ClusteringData *q0, const ClusteringData *q1, STensor3& DPtrHom) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+
+  STensorOperation::zero(DPtrHom);
+  double vtot;
+  vtot = 0.;
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+    std::map<int,double>::const_iterator itc = cluterVolumeMap.find(icl);
+    double vi = itc->second;
+    vtot += vi;
+    
+    const STensor3& eps0i = q0->getConstRefToStrain(icl);
+    const STensor3& eps1i = q1->getConstRefToStrain(icl);
+    STensor3 depsi;
+    depsi = eps1i;
+    depsi -= eps0i;
+    
+    const materialLaw *law = getLawForCluster(icl); 
+    STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    STensorOperation::multSTensor43STensor3Add(Celi,depsi,vi,DPtrHom);
+  }
+  DPtrHom *= (1./vtot);
+}
+
+
+void ReductionTFA::dsecantShearModulusOveralldeps(const ClusteringData *q0, const ClusteringData *q1, int s, STensor3& dGHomdeps_s) const
+{
+
+  const STensor3& macroEps1 = q1->getConstRefToMacroStrain();
+  const STensor3& macroEps0 = q0->getConstRefToMacroStrain();
+  STensor3 DmacroEps = macroEps1;
+  DmacroEps -= macroEps0;
+  double DepsEq = TFANumericTools::EquivalentStrain(DmacroEps);
+  
+  const STensor3& epsEigMacro0 = q0->getConstRefToMacroEigenStrain();
+  const STensor3& epsEigMacro1 = q1->getConstRefToMacroEigenStrain();
+  STensor3 DepsEigMacro;
+  DepsEigMacro = epsEigMacro1;
+  DepsEigMacro -= epsEigMacro0;
+  double DepsEigEqHom = TFANumericTools::EquivalentStrain(DepsEigMacro);
+  
+  STensor43 CelHom,SelHom;
+  elasticStiffnessHom(CelHom);
+  STensorOperation::inverseSTensor43(CelHom,SelHom);
+  
+  const double& Gel = q1->getConstRefToElasticShearModulus();
+
+  double vtot, vfs;
+  vtot = totalVolume();
+  vfs = clusterVolume(s);
+  vfs *= 1./vtot; 
+  
+  const materialLaw *law = getLawForCluster(s); 
+  STensor43 Cels;
+  law->ElasticStiffness(&Cels);
+  const STensor43& Calgs = q1->getConstRefToTangent(s);
+   
+  STensor3 epsTrMacro,epsTrMacro_dev;
+  epsTrMacro = macroEps1;
+  epsTrMacro -= epsEigMacro0;
+  epsTrMacro_dev = epsTrMacro.dev();
+  double epsTrMacroEq = sqrt(2./3.*epsTrMacro_dev.dotprod());
+  
+  STensor43 Cdiff,ShomCdiff;
+  Cdiff = Calgs;
+  Cdiff -= Cels;
+  STensorOperation::multSTensor43(SelHom,Cdiff,ShomCdiff);
+  STensor3 p1, p2;
+  STensorOperation::multSTensor3STensor43(DepsEigMacro,ShomCdiff,p1);
+  p1 *= 2./3./DepsEigEqHom/epsTrMacroEq;
+  p2 = epsTrMacro_dev;
+  p2 *= 2.*DepsEigEqHom/(3.*epsTrMacroEq*epsTrMacroEq*epsTrMacroEq);
+  
+  if(DepsEigEqHom>1.e-10)
+  {
+  dGHomdeps_s = p1;
+  dGHomdeps_s += p2;
+  dGHomdeps_s *= Gel*vfs;
+  } 
+}
+
+void ReductionTFA::dtangentShearModulusOveralldeps(const ClusteringData *q0, const ClusteringData *q1, int s, STensor3& dGHomdeps_s) const
+{
+  STensorOperation::zero(dGHomdeps_s);
+
+  const STensor3& macroEps1 = q1->getConstRefToMacroStrain();
+  const STensor3& macroEps0 = q0->getConstRefToMacroStrain();
+  STensor3 DmacroEps = macroEps1;
+  DmacroEps -= macroEps0;
+  STensor3 DmacroEps_dev = DmacroEps.dev();
+  double DmacroEpsEq = sqrt(2./3.*DmacroEps_dev.dotprod());
+  
+  /*const STensor3& macroSig1 = q1->getConstRefToMacroStress();
+  const STensor3& macroSig0 = q0->getConstRefToMacroStress();
+  STensor3 DmacroSig = macroSig1;
+  DmacroSig -= macroSig0;
+  STensor3 DmacroSig_dev = DmacroSig.dev();
+  double DmacroSigEq = sqrt(3./2.*DmacroSig_dev.dotprod());*/
+  
+  const double& Gtan = q1->getConstRefToTangentShearModulus(); 
+  STensor3 DmacroSig_dev(DmacroEps_dev);
+  DmacroSig_dev *= 2.*Gtan;
+  double DmacroSigEq = 3.*Gtan*DmacroEpsEq;
+  
+  STensor3 DmacroSigTr;
+  elasticIncrementalTrialStressHom(q0,q1,DmacroSigTr);
+  STensor3 DmacroSigTr_dev = DmacroSigTr.dev();
+  double DmacroSigTrEq = sqrt(3./2.*DmacroSigTr_dev.dotprod());
+
+  double vtot, vfs;
+  vtot = totalVolume();
+  vfs = clusterVolume(s);
+  vfs *= 1./vtot; 
+  
+  const STensor43& Calgs = q1->getConstRefToTangent(s);
+
+  if(DmacroEpsEq>1.e-10)
+  {
+  STensor3 dDmacroEpsEqdeps,dDsigMacroEqdeps;
+  dDmacroEpsEqdeps = DmacroEps_dev;
+  dDmacroEpsEqdeps *= 2./3.*vfs/DmacroEpsEq;
+  
+  STensorOperation::multSTensor3STensor43(DmacroSig_dev,Calgs,dDsigMacroEqdeps);
+  dDsigMacroEqdeps *= 3./2.*vfs/DmacroSigEq;
+  
+  //STensorOperation::multSTensor3STensor43(DmacroSigTr_dev,Calgs,dDsigMacroEqdeps);
+  //dDsigMacroEqdeps *= 3./2.*vfs/DmacroSigTrEq;
+   
+  dGHomdeps_s = dDsigMacroEqdeps;
+  dGHomdeps_s *= 1./(3.*DmacroEpsEq);
+  //dGHomdeps_s.print("dGHomdeps_s");
+  //dGHomdeps_s -= dDmacroEpsEqdeps*DmacroSigEq/(3.*DmacroEpsEq*DmacroEpsEq);
+  }
+}
+
+
+void ReductionTFA::secantStiffnessHom(const ClusteringData *q0, const ClusteringData *q1, STensor43& CsecHom) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+
+  STensorOperation::zero(CsecHom);
+  double vtot;
+  vtot = 0.;
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+    std::map<int,double>::const_iterator itc = cluterVolumeMap.find(icl);
+    double vi = itc->second;
+    vtot += vi;    
+    const materialLaw *law = getLawForCluster(icl); 
+    STensor43 Aseci;
+    //secantStiffness(icl,q0,q1,Cseci);
+    const STensor43& Cseci = q1->getConstRefToSecant(icl);
+    STensorOperation::multSTensor43Add(Cseci,Aseci,vi,CsecHom);
+  }
+  CsecHom *= (1./vtot);
+}
+
+void ReductionTFA::secantStiffness(int r, const ClusteringData *q0, const ClusteringData *q1, STensor43& Csec) const 
+{
+  const materialLaw *law = getLawForCluster(r); 
+  STensor43 Celr;
+  STensorOperation::zero(Celr);
+  law->ElasticStiffness(&Celr);
+  
+  STensor3 P1tr;
+  const STensor3& eps1 = q1->getConstRefToStrain(r);
+  double eps1Eq = TFANumericTools::EquivalentStrain(eps1);
+  const STensor3& eps0 = q0->getConstRefToStrain(r);
+  STensor3 Deps = eps1;
+  Deps -= eps0;
+  double DepsEq = TFANumericTools::EquivalentStrain(Deps);
+  
+  const STensor3& P1 = q1->getConstRefToStress(r);
+  STensorOperation::multSTensor43STensor3(Celr,eps1,P1tr);
+  
+  Csec = Celr;
+  
+  double fac;
+  fac = 1.;
+  if(DepsEq>1.e-10)
+  {
+    STensor3 Ptr_dev = P1tr.dev();
+    double sigEqtr = TFANumericTools::EquivalentStress(P1tr);
+    double shearmodulus_elastic = sigEqtr/(3.*eps1Eq);
+    
+    double sigEq = TFANumericTools::EquivalentStress(P1);
+    double shearmodulus_secant = sigEq/(3.*eps1Eq);
+    
+    fac = shearmodulus_secant/shearmodulus_elastic;
+  }  
+  Csec *= fac;
+  
+  // or
+  // SecantStiffnessIsotropic(q1->getRefToIPv(r),Csec);
+}
+
+double ReductionTFA::totalVolume() const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+  double vtot;
+  vtot = 0.;
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+    std::map<int,double>::const_iterator itc = cluterVolumeMap.find(icl);
+    double vi = itc->second;
+    vtot += vi;
+  }
+  return vtot;
+}
+
+double ReductionTFA::clusterVolume(int r) const 
+{
+  const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+  std::map<int,double>::const_iterator itcr = cluterVolumeMap.find(r);
+  double vr = itcr->second;
+  return vr;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void ReductionTFA::getLinearTermWithFrame(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters(); 
+  static STensor3 resTen;
+  STensorOperation::zero(resTen);
+  
+  if(clusterId == nbClusters)
+  {
+    const STensor3& macroEps0 = q0->getConstRefToMacroStrain();
+    const STensor3& macroEps1 = q1->getConstRefToMacroStrain();
+    double vtot;
+    vtot = 0.;
+    for (int jcl =0; jcl < nbClusters; jcl++)
+    {  
+      const STensor3& eps0j = q0->getConstRefToStrain(jcl);
+      const STensor3& eps1j = q1->getConstRefToStrain(jcl);
+      STensor3 depsj = eps1j;
+      depsj -= eps0j;
+      const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+      std::map<int,double>::const_iterator itc = cluterVolumeMap.find(jcl);
+      double vj = itc->second;
+      vtot += vj;
+      resTen.daxpy(depsj,-vj);
+    }
+    resTen *= (1./vtot);
+    resTen += macroEps1;
+    resTen -= macroEps0;
+  }  
+  else
+  {
+    const STensor3& eps0i = q0->getConstRefToStrain(clusterId);
+    const STensor3& eps1i = q1->getConstRefToStrain(clusterId);
+    const STensor3& frameEps0 = q0->getConstRefToFrameStrain();
+    const STensor3& frameEps1 = q1->getConstRefToFrameStrain();
+    
+    const STensor43 &Ai = getClusterAverageStrainConcentrationTensor(clusterId);
+
+    resTen = eps1i;
+    resTen -= eps0i;
+    STensorOperation::multSTensor43STensor3Add(Ai,frameEps0,1.,resTen);
+    STensorOperation::multSTensor43STensor3Add(Ai,frameEps1,-1.,resTen);
+    //resTen += frameEps0;
+    //resTen -= frameEps1;
+    for (int jcl =0; jcl < nbClusters; jcl++)
+    {
+      const STensor43 &Dij =  getClusterInteractionTensor(clusterId,jcl);
+      const STensor3& epsEig0j = q0->getConstRefToEigenStrain(jcl);
+      const STensor3& epsEig1j = q1->getConstRefToEigenStrain(jcl);
+      const STensor3& sigEig0j = q0->getConstRefToEigenStress(jcl);
+      const STensor3& sigEig1j = q1->getConstRefToEigenStress(jcl);
+      //STensorOperation::multSTensor43STensor3Add(Dij,epsEig1j,1.,resTen);
+      //STensorOperation::multSTensor43STensor3Add(Dij,epsEig0j,-1.,resTen);
+      STensorOperation::multSTensor43STensor3Add(Dij,sigEig1j,-1.,resTen);
+      STensorOperation::multSTensor43STensor3Add(Dij,sigEig0j,1.,resTen);
+    };
+    const STensor43 &Di0 =  getClusterInteractionTensor(clusterId,nbClusters);
+    const STensor3& epsEig0Frame = q0->getConstRefToFrameEigenStrain();
+    const STensor3& epsEig1Frame = q1->getConstRefToFrameEigenStrain();
+    const STensor3& sigEig0Frame = q0->getConstRefToFrameEigenStress();
+    const STensor3& sigEig1Frame = q1->getConstRefToFrameEigenStress();
+
+    //STensorOperation::multSTensor43STensor3Add(Di0,epsEig1Frame,1.,resTen);
+    //STensorOperation::multSTensor43STensor3Add(Di0,epsEig0Frame,-1.,resTen);
+    STensorOperation::multSTensor43STensor3Add(Di0,sigEig1Frame,-1.,resTen);
+    STensorOperation::multSTensor43STensor3Add(Di0,sigEig0Frame,1.,resTen);
+  }
+  STensorOperation::fromSTensor3ToFullVector(resTen,res);
+};
 
+void ReductionTFA::getBiLinearTermWithFrame(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& dres) const 
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  othersId.resize(nbClusters+1);
+  for (int j=0; j< (nbClusters+1); j++)
+  {
+    othersId[j] = j;
+  }
+  dres.resize(6,6*(nbClusters+1),true);
+   
+  if(clusterId == nbClusters)
+  { 
+    for (int jcl=0; jcl< nbClusters; jcl++)
+    { 
+      static STensor43 J_Kj;
+      STensorOperation::unity(J_Kj);
+      const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+      std::map<int,double>::const_iterator itcj = cluterVolumeMap.find(jcl);
+      double vj = itcj->second;  
+      J_Kj *= -vj;  
+      static fullMatrix<double> J_Kj_matrix;
+      STensorOperation::fromSTensor43ToFullMatrix(J_Kj,J_Kj_matrix);
+      for (int row=0; row<6; row++)
+      {
+        for (int col=0; col<6; col++)
+        {
+          dres(row, col+6*jcl) = J_Kj_matrix(row,col);
+        }
+      }
+    }
+    
+    double vtot;
+    vtot = 0.;
+    static STensor43 J_KK;
+    STensorOperation::zero(J_KK);
+    for (int jcl=0; jcl< nbClusters; jcl++)
+    {
+      const STensor43 &Aelj = getClusterAverageStrainConcentrationTensor(jcl);
+      const std::map<int,double>& cluterVolumeMap= _clusteringData->getClusterVolumeMap();
+      std::map<int,double>::const_iterator itc = cluterVolumeMap.find(jcl);
+      double vj = itc->second;
+      vtot += vj;
+      static STensor43 J_KK_term;
+      STensorOperation::zero(J_KK_term);
+      J_KK_term.axpy(-1.,Aelj);
+      J_KK_term *= vj;
+      J_KK.axpy(1.,J_KK_term);
+    }
+    fullMatrix<double> J_KK_matrix;
+    STensorOperation::zero(J_KK);
+    STensorOperation::fromSTensor43ToFullMatrix(J_KK,J_KK_matrix);
+    for (int row=0; row<6; row++)
+    {
+      for (int col=0; col<6; col++)
+      {
+        dres(row, col+6*nbClusters) = J_KK_matrix(row,col);
+      }
+    }   
+    dres.scale(1./vtot); 
+  }
+  else
+  {
+    for (int jcl=0; jcl< nbClusters; jcl++)
+    {
+      static STensor43 J_ij;
+      getJac_rs(clusterId,jcl,q0,q1,J_ij);
+      static fullMatrix<double> J_ij_matrix;
+      STensorOperation::fromSTensor43ToFullMatrix(J_ij,J_ij_matrix);
+      for (int row=0; row<6; row++)
+      {
+        for (int col=0; col<6; col++)
+        {
+          dres(row, col+6*jcl) = J_ij_matrix(row,col);
+        }
+      }
+    }
+ 
+    STensor43 J_iK;
+    STensorOperation::zero(J_iK); 
+    const STensor43 &Di0 =  getClusterInteractionTensor(clusterId,nbClusters);
+    const STensor43& depsEig1FramedepsFrame = q1->getConstRefToFramedEigenStraindStrain();
+    const STensor43& dsigEig1FramedepsFrame = q1->getConstRefToFramedEigenStressdStrain();
+    //STensorOperation::multSTensor43(Di0,depsEig1FramedepsFrame,J_iK);
+    STensorOperation::multSTensor43(Di0,dsigEig1FramedepsFrame,J_iK);
+    J_iK *= -1.;
+    const STensor43 &Aeli = getClusterAverageStrainConcentrationTensor(clusterId);
+    J_iK.axpy(-1.,Aeli);
+    fullMatrix<double> J_iK_matrix;
+    STensorOperation::fromSTensor43ToFullMatrix(J_iK,J_iK_matrix);
+    for (int row=0; row<6; row++)
+    {
+      for (int col=0; col<6; col++)
+      {
+        dres(row, col+6*nbClusters) = J_iK_matrix(row,col);
+      }
+    }
+  }  
+};
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
 
-IncrementalTangentTFA::IncrementalTangentTFA(int solverType, int dim, int correction, int tag): ReductionTFA(solverType, dim, correction, tag){}
+IncrementalTangentTFA::IncrementalTangentTFA(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag): ReductionTFA(solverType, dim, correction, withFrame, polarization, tag){}
 IncrementalTangentTFA::~IncrementalTangentTFA(){}
 
 
 void IncrementalTangentTFA::localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1)
 {
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
   //
   STensor3& eps1 = q1->getRefToMacroStrain();
   for  (int i=0; i<3; i++)
@@ -1119,25 +2030,403 @@ void IncrementalTangentTFA::localConstitutive(const STensor3& F0, const STensor3
   eps1(0,0) -= 1.;
   eps1(1,1) -= 1.;
   eps1(2,2) -= 1.;
+  
+  STensor3 Deps(Fn);
+  Deps -= F0;
+  
+  double vtot;
+  vtot = totalVolume();
     
   // local constitutive behavior
-  int nbClusters = _clusteringData->getTotalNumberOfClusters();
   static STensor3 Isecond(1.);
   for (int icl =0; icl < nbClusters; icl++)
   {
     const materialLaw *law = getLawForCluster(icl); 
-    static STensor3 F0j, F1j;
-    F0j = q0->getConstRefToStrain(icl);
-    F1j = q1->getConstRefToStrain(icl);
-    F0j += Isecond;
-    F1j += Isecond;
-    STensor3& P1j = q1->getRefToStress(icl);
-    STensor43& Tangentj = q1->getRefToTangent(icl);
-    STensor43& deig1deps = q1->getRefTodEigenStraindStrain(icl);
-    STensor3& eig1j = q1->getRefToEigenStrain(icl);
+    static STensor3 F0i, F1i;
+    F0i = q0->getConstRefToStrain(icl);
+    F1i = q1->getConstRefToStrain(icl);
+    F0i += Isecond;
+    F1i += Isecond;
+    STensor3& P1i = q1->getRefToStress(icl);
+    STensor43& Tangenti = q1->getRefToTangent(icl);
+    STensor43& depsEig1depsi = q1->getRefTodEigenStraindStrain(icl);
+    STensor43& dsigEig1depsi = q1->getRefTodEigenStressdStrain(icl);
+    STensor3& epsEig1i = q1->getRefToEigenStrain(icl);
+    STensor3& sigEig1i = q1->getRefToEigenStress(icl);
     //
-    const IPVariable* ipv0j = q0->getConstRefToIPv(icl);
-    IPVariable* ipv1j = q1->getRefToIPv(icl);
-    law->constitutiveTFA(F0j,F1j,P1j,ipv0j,ipv1j,Tangentj,eig1j,deig1deps);
+    const IPVariable* ipv0i = q0->getConstRefToIPv(icl);
+    IPVariable* ipv1i = q1->getRefToIPv(icl);
+    
+    if(_clusterIncOri)
+    {
+      const fullVector<double>& euler_i = getClusterMeanFiberOrientation(icl);
+      law->constitutiveTFA_incOri(F0i,F1i,euler_i,P1i,ipv0i,ipv1i,Tangenti,epsEig1i,depsEig1depsi);
+    }
+    else
+    {
+      law->constitutiveTFA(F0i,F1i,P1i,ipv0i,ipv1i,Tangenti,epsEig1i,depsEig1depsi);
+    }
+    
+    /*const STensor43 &Aelistd = getClusterStrainConcentrationStDTensor(icl);
+    const double &aelistd = getClusterStrainConcentrationStDScalar(icl);
+    STensor3 epsi_std,F1i_max,F1i_min;
+    STensorOperation::multSTensor43STensor3(Aelistd,Deps,epsi_std);
+    epsi_std *= 2.;
+    //epsi_std = 2.*aelistd*Deps;
+    F1i_max = F1i;
+    F1i_max += epsi_std;  
+    F1i_min = F1i;
+    F1i_min -= epsi_std;
+    law->constitutiveTFA_corr(F0i,F1i,F1i_min,F1i_max,P1i,ipv0i,ipv1i,Tangenti,epsEig1i,depsEig1depsi);*/
+   
+    STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    STensorOperation::multSTensor43STensor3(Celi,epsEig1i,sigEig1i);
+    sigEig1i *= -1.;
+    STensorOperation::multSTensor43(Celi,depsEig1depsi,dsigEig1depsi);
+    dsigEig1depsi *= -1.;
+  }
+  
+  STensor3& PHom = q1->getRefToMacroStress();
+  q1->computeHomogenizedStress(PHom);
+  STensor43 CelHom, SelHom;
+  elasticStiffnessHom(CelHom);
+  STensorOperation::inverseSTensor43(CelHom,SelHom);
+
+  STensor3 eps_unloadHom; 
+  STensor3& eps_resHom = q1->getRefToMacroResidualStrain();
+  STensorOperation::multSTensor43STensor3(SelHom,PHom,eps_unloadHom);
+  const STensor3& epsHom = q1->getConstRefToMacroStrain();
+  eps_resHom = epsHom;
+  eps_resHom -= eps_unloadHom; 
+    
+  STensor43 Ifourth(1.,1.);
+  
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const STensor3 eps1i = q1->getConstRefToStrain(icl);
+    const STensor3 P1i = q1->getConstRefToStress(icl);
+    const materialLaw *law = getLawForCluster(icl); 
+    STensor43 Celi,Seli;
+    law->ElasticStiffness(&Celi);
+    STensorOperation::inverseSTensor43(Celi,Seli);
+    const STensor43 &Aeli = getClusterAverageStrainConcentrationTensor(icl);
+   
+    double vfi = clusterVolume(icl);
+    vfi *= (1./vtot);
+    
+    STensor3 eps_unloadi;
+    STensorOperation::multSTensor43STensor3(Aeli,eps_unloadHom,eps_unloadi);   
+    STensor3& sigRes1i = q1->getRefToResidualStress(icl);
+    sigRes1i = P1i;
+    STensorOperation::multSTensor43STensor3Add(Celi,eps_unloadi,-1.,sigRes1i);
+    
+    STensor43& dsigRes1depsi = q1->getRefTodResidualStressdStrain(icl);
+    const STensor43 Calgi = q1->getConstRefToTangent(icl);
+    STensor43 prod3i;
+    STensorOperation::mult3xSTensor43(Aeli,SelHom,Calgi,prod3i);
+    
+    dsigRes1depsi = Calgi;
+    STensorOperation::multSTensor43Add(Celi,prod3i,-vfi,dsigRes1depsi);
+    
+    STensor3& sigEff1i = q1->getRefToEffectiveStress(icl);
+    STensor3 sigApp1i;
+    sigApp1i = PHom;
+    sigApp1i -= vfi*P1i;
+    sigApp1i *= (1./(1.-vfi));
+    sigEff1i = P1i;
+    sigEff1i -= sigApp1i;
   }  
 };
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+IncrementalTangentTFAWithFrame::IncrementalTangentTFAWithFrame(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag): ReductionTFA(solverType, dim, correction, withFrame, polarization, tag){}
+IncrementalTangentTFAWithFrame::~IncrementalTangentTFAWithFrame(){}
+void IncrementalTangentTFAWithFrame::localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1)
+{
+  //
+  STensor3& eps1 = q1->getRefToMacroStrain();
+  for  (int i=0; i<3; i++)
+  {
+    for (int j=0; j<3; j++)
+    {
+      eps1(i,j) = (Fn(i,j)+Fn(j,i))*0.5;
+    }
+  }
+  eps1(0,0) -= 1.;
+  eps1(1,1) -= 1.;
+  eps1(2,2) -= 1.;
+    
+  // local constitutive behavior
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  static STensor3 Isecond(1.);
+  
+  STensor3& epsEig1Frame = q1->getRefToFrameEigenStrain();
+  STensor3& sigEig1Frame = q1->getRefToFrameEigenStress();
+  const STensor3& eps1Frame = q1->getConstRefToFrameStrain();
+  STensor43& depsEig1FramedepsFrame = q1->getRefToFramedEigenStraindStrain();
+  STensor43& dsigEig1FramedepsFrame = q1->getRefToFramedEigenStressdStrain();
+  
+  static STensor43 Ifourth(1.,1.);
+
+  double vtot;
+  vtot = totalVolume();
+  
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const materialLaw *law = getLawForCluster(icl); 
+    static STensor3 F0i, F1i;
+    F0i = q0->getConstRefToStrain(icl);
+    F1i = q1->getConstRefToStrain(icl);
+    F0i += Isecond;
+    F1i += Isecond;
+    STensor3& P1i = q1->getRefToStress(icl);
+    STensor43& Tangenti = q1->getRefToTangent(icl);
+    STensor43& depsEig1depsi = q1->getRefTodEigenStraindStrain(icl);
+    STensor43& dsigEig1depsi = q1->getRefTodEigenStressdStrain(icl);
+    STensor3& epsEig1i = q1->getRefToEigenStrain(icl);
+    STensor3& sigEig1i = q1->getRefToEigenStress(icl);
+    //
+    const IPVariable* ipv0i = q0->getConstRefToIPv(icl);
+    IPVariable* ipv1i = q1->getRefToIPv(icl);
+    law->constitutiveTFA(F0i,F1i,P1i,ipv0i,ipv1i,Tangenti,epsEig1i,depsEig1depsi);
+    
+    static STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    STensorOperation::multSTensor43STensor3(Celi,epsEig1i,sigEig1i);
+    sigEig1i *= -1.;
+    STensorOperation::multSTensor43(Celi,depsEig1depsi,dsigEig1depsi);
+    dsigEig1depsi *= -1.;
+  }
+  q1->computeHomogenizedStress(sigEig1Frame);
+  STensor43 CelHom, SelHom, CsecHom, SsecHom;
+  elasticStiffnessHom(CelHom);
+  STensorOperation::inverseSTensor43(CelHom,SelHom);
+  secantStiffnessHom(q0,q1,CsecHom);
+  STensorOperation::inverseSTensor43(CsecHom,SsecHom);
+  STensorOperation::multSTensor43STensor3Add(CsecHom,eps1Frame,-1.,sigEig1Frame);
+  STensorOperation::multSTensor43STensor3(SelHom,sigEig1Frame,epsEig1Frame);
+  epsEig1Frame *= -1.;
+  
+  dsigEig1FramedepsFrame = CsecHom;
+  dsigEig1FramedepsFrame *= -1.;
+  depsEig1FramedepsFrame = SsecHom;
+};
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+IncrementalTangentTFAPolarization::IncrementalTangentTFAPolarization(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag): ReductionTFA(solverType, dim, correction, withFrame, polarization, tag){}
+IncrementalTangentTFAPolarization::~IncrementalTangentTFAPolarization(){}
+
+
+void IncrementalTangentTFAPolarization::localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1)
+{
+  int nbClusters = _clusteringData->getTotalNumberOfClusters();
+  
+  const STensor43& C0 = _clusteringData->getReferenceStiffness();
+  const STensor43& C0iso = _clusteringData->getReferenceStiffnessIso();
+  double G0 = C0iso(0,1,0,1);
+  double k0 = C0iso(0,0,0,0) - 4./3.*G0;
+  
+  //
+  const STensor3& eps0 = q0->getConstRefToMacroStrain();
+  STensor3& eps1 = q1->getRefToMacroStrain();
+  for  (int i=0; i<3; i++)
+  {
+    for (int j=0; j<3; j++)
+    {
+      eps1(i,j) = (Fn(i,j)+Fn(j,i))*0.5;
+    }
+  }
+  eps1(0,0) -= 1.;
+  eps1(1,1) -= 1.;
+  eps1(2,2) -= 1.;
+  double epsEq = TFANumericTools::EquivalentStrain(eps1);
+  STensor3 Deps;
+  Deps = eps1;
+  Deps -= eps0;
+  double DepsEq = TFANumericTools::EquivalentStrain(Deps);
+  
+  const STensor3& P0hom = q0->getConstRefToMacroStress();
+  const STensor3& epsEigMacro0 = q0->getConstRefToMacroEigenStrain();
+  const STensor3& sigEigMacro0 = q0->getConstRefToMacroEigenStress();
+  STensor3& Phom = q1->getRefToMacroStress();
+  STensor3& epsEigMacro = q1->getRefToMacroEigenStrain();  
+  STensor3& sigEigMacro = q1->getRefToMacroEigenStress();
+  
+  STensor3 PtrHom; 
+  elasticTotalTrialStressHom(q1,PtrHom);
+  
+  STensor3 PtrHom_true;
+  STensorOperation::multSTensor43STensor3(C0,eps1,PtrHom_true);
+    
+  // local constitutive behavior
+  static STensor3 Isecond(1.);
+  for (int icl =0; icl < nbClusters; icl++)
+  {
+    const materialLaw *law = getLawForCluster(icl); 
+    static STensor3 F0i, F1i;
+    F0i = q0->getConstRefToStrain(icl);
+    F1i = q1->getConstRefToStrain(icl);
+    F0i += Isecond;
+    F1i += Isecond;
+    STensor3& P1i = q1->getRefToStress(icl);
+    STensor43& Tangenti = q1->getRefToTangent(icl);
+    STensor43& depsEig1depsi = q1->getRefTodEigenStraindStrain(icl);
+    STensor43& dsigEig1depsi = q1->getRefTodEigenStressdStrain(icl);
+    STensor3& epsEig1i = q1->getRefToEigenStrain(icl);
+    STensor3& sigEig1i = q1->getRefToEigenStress(icl);
+    STensor3& epsResi = q1->getRefToResidualStrain(icl);
+    STensor3& sigResi = q1->getRefToResidualStress(icl);
+    //
+    const IPVariable* ipv0i = q0->getConstRefToIPv(icl);
+    IPVariable* ipv1i = q1->getRefToIPv(icl);
+    STensor43& Secanti = q1->getRefToSecant(icl);    
+    law->constitutiveTFA(F0i,F1i,P1i,ipv0i,ipv1i,Tangenti,epsEig1i,depsEig1depsi);
+    
+    STensor43 Celi;
+    STensorOperation::zero(Celi);
+    law->ElasticStiffness(&Celi);
+    STensorOperation::multSTensor43STensor3(Celi,epsEig1i,sigEig1i);
+    sigEig1i *= -1.;
+    STensorOperation::multSTensor43(Celi,depsEig1depsi,dsigEig1depsi);
+    dsigEig1depsi *= -1.; 
+  }
+  
+  STensor3 DPhom,DepsEigMacro,DsigEigMacro;
+  double sigEqHom,DsigEqHom,DsigEigEqHom,DepsEigEqHom;
+  
+  q1->computeHomogenizedStress(Phom);
+  sigEqHom = TFANumericTools::EquivalentStress(Phom);
+  DPhom = Phom;
+  DPhom -= P0hom;
+  DsigEqHom = TFANumericTools::EquivalentStress(DPhom);
+
+  sigEigMacro = Phom;
+  sigEigMacro -= PtrHom;
+  DsigEigMacro = sigEigMacro;
+  DsigEigMacro -= sigEigMacro0;
+  DsigEigEqHom = TFANumericTools::EquivalentStress(DsigEigMacro);
+  
+  STensor43 SelHom;
+  STensorOperation::inverseSTensor43(C0,SelHom);
+  STensorOperation::multSTensor43STensor3(SelHom,sigEigMacro,epsEigMacro);
+  epsEigMacro *= -1.;
+  DepsEigMacro = epsEigMacro;
+  DepsEigMacro -= epsEigMacro0;
+  DepsEigEqHom = TFANumericTools::EquivalentStrain(DepsEigMacro);
+  
+  double& Gel = q1->getRefToElasticShearModulus();
+  Gel = G0;
+  double& Gtan = q1->getRefToTangentShearModulus();
+  Gtan = G0;
+  double Geig(0.), keig(0.);
+  if(DepsEq>1.e-10)
+  {
+    DepsEigEqHom = DepsEq - DsigEqHom/(3.*G0);
+    Gtan *= (1.-DepsEigEqHom/DepsEq);
+    Geig = -1.*DsigEigEqHom/(3.*DepsEq);
+  }
+  
+  STensor43& Ciso = q1->getRefToIsotropicStiffness();
+  STensor43& Ciso_inv = q1->getRefToIsotropicStiffnessInverted();
+  STensor43 Ivol, Idev;
+  STensorOperation::sphericalfunction(Ivol);
+  STensorOperation::deviatorfunction(Idev);
+  Ciso = 3.*k0*Ivol;
+  Ciso += 2.*Gtan*Idev;
+  STensorOperation::inverseSTensor43(Ciso,Ciso_inv);
+  
+  //STensor43& Caniso = q1->getRefToAnisotropicStiffness();
+  //STensor43& Caniso_inv = q1->getRefToAnisotropicStiffnessInverted();
+  
+  /*double vtot;
+  vtot = totalVolume();
+  
+  STensor43 CtanHom;
+  fullMatrix<double> J_matrix(6*nbClusters,6*nbClusters),J_matrix_inv(6*nbClusters,6*nbClusters);  
+  fullMatrix<double> Ctan_matrix(6,6*nbClusters);  
+  fullMatrix<double> CtanHom_matrix(6,6);  
+  for (int r=0; r < nbClusters; r++)
+  {
+    for (int s=0; s < nbClusters; s++)
+    {
+      double vfs = clusterVolume(s);
+      vfs *= 1./vtot;
+      
+      STensor43 J_rs;
+      fullMatrix<double> J_rs_matrix(6,6);
+      fullMatrix<double> C_tan_s_matrix(6,6);
+      if(r==s)
+      {
+        STensorOperation::unity(J_rs);
+      }
+      else
+      {
+        STensorOperation::zero(J_rs);
+      }
+      STensor43 fac;
+      const STensor43& Ctans = q1->getConstRefToTangent(s);
+      //fac = G0/Gtan*Ctans;
+      
+      STensor43 prefac;
+      STensorOperation::multSTensor43(C0,Caniso_inv,prefac);
+      STensorOperation::multSTensor43(prefac,Ctans,fac);
+      fac -= C0;
+
+      const STensor43 &Drs =  getClusterInteractionTensor(r,s);
+      const STensor43 &Diso_rs =  getClusterInteractionTensorIso(r,s);
+          
+      STensorOperation::multSTensor43Add(Drs,fac,-1.,J_rs);
+      STensorOperation::fromSTensor43ToFullMatrix(J_rs,J_rs_matrix);
+      STensorOperation::fromSTensor43ToFullMatrix(Ctans,C_tan_s_matrix);
+      for(int k=0; k<6; k++)
+      {
+        for(int l=0; l<6; l++)
+        {
+          J_matrix.set(r*6+k,s*6+l,J_rs_matrix(k,l));
+          Ctan_matrix.set(k,s*6+l,vfs*C_tan_s_matrix(k,l));
+        }
+      }
+    }
+  }
+  bool isInverted = J_matrix.invert(J_matrix_inv);
+  
+  fullMatrix<double> A_matrix(6*nbClusters,6);
+  for (int r=0; r < nbClusters; r++)
+  {
+    fullMatrix<double> J_matrix_inv_sum_s(6,6);
+    for (int s=0; s < nbClusters; s++)
+    {
+      for(int k=0; k<6; k++)
+      {
+        for(int l=0; l<6; l++)
+        {
+          J_matrix_inv_sum_s(k,l) += J_matrix_inv(r*6+k,s*6+l);
+        }
+      }
+    }
+    for(int k=0; k<6; k++)
+    {
+      for(int l=0; l<6; l++)
+      {
+        A_matrix(6*r+k,l) = J_matrix_inv_sum_s(k,l);
+      }
+    }
+  }
+  Ctan_matrix.mult(A_matrix,CtanHom_matrix);
+  STensorOperation::fromFullMatrixToSTensor43(CtanHom_matrix,CtanHom);
+  
+  //STensor43& Ceig = q1->getRefToEigenStiffness();
+  //Ceig = 3.*keig*Ivol;
+  //Ceig += 2.*Geig*Idev;
+  
+  //Caniso = C0;
+  //Caniso += Ceig;
+  Caniso = CtanHom;
+  STensorOperation::inverseSTensor43(Caniso,Caniso_inv);*/
+
+};
diff --git a/NonLinearSolver/modelReduction/modelReduction.h b/NonLinearSolver/modelReduction/modelReduction.h
index 16ee3e9b185f13420a0e4134f1747a9930be1985..ca4d7918cdeb224f660abba045c80b31765c2304 100644
--- a/NonLinearSolver/modelReduction/modelReduction.h
+++ b/NonLinearSolver/modelReduction/modelReduction.h
@@ -23,11 +23,7 @@ class nonLinearSystemPETSc;
 class modelReduction
 {
   public:
-    enum ReductionMethod{TFA_IncrementalTangent=0, TFA_IncrementalResidualSecant, TFA_IncrementalZeroSecant, 
-         TFA_IncrementalTangentInelasticNonuniformCorrection, TFA_IncrementalSecantInelasticNonuniformCorrection,
-         TFA_InteractionNonuniformCorrectionTangent,
-         TFA_IncrementalTangentFrameCorrection, TFA_IncrementalResidualSecantFrameCorrection,
-         TFA_IncrementalResidualSecant2ndOrder};
+    enum ReductionMethod{TFA_IncrementalTangent=0, TFA_IncrementalTangentWithFrame, TFA_IncrementalTangentPolarization};
   #ifndef SWIG
   public:
     modelReduction(){}
@@ -56,6 +52,9 @@ class ReductionTFA: public modelReduction
     int _solverType;
     int _dim, _tag;
     int _correction;
+    bool _withFrame;
+    bool _polarization;
+    bool _clusterIncOri;
     bool _ownClusteringData; // true if this object has its own data about clustering
     Clustering* _clusteringData; // clustering data, manage load and save data
     std::map<int, const materialLaw*> _matlawptr; //give the material law pointer for cluster i
@@ -65,24 +64,36 @@ class ReductionTFA: public modelReduction
     // cluster data export by Clustering
     void loadClusterSummaryAndInteractionTensorsFromFiles(const std::string clusterSummaryFileName, 
                                         const std::string interactionTensorsFileName);
-    void loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD, const std::string InteractionSTD);
+    void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName);
+    void loadClusterStandardDeviationFromFile(const std::string ClusterStrainConcentrationSTD);
     void loadElasticStrainConcentrationDerivativeFromFile(const std::string ElasticStrainConcentrationDerivative);
-    void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName, const std::string EshelbyInteractionSTD);
+    void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyInteractionTensorsFileName);
 
     void loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName,
                                                   const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName);
+                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                  const std::string PlasticEqStrainConcentrationPowerFileName);
 
     void loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName);
     void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string InteractionTensorsHomogenizedFrameELFileName);
     
+    void loadReferenceStiffnessFromFile(const std::string ReferenceStiffnessFileName);
+    void loadReferenceStiffnessIsoFromFile(const std::string ReferenceStiffnessIsoFileName);
+    
+    void loadInteractionTensorIsoFromFile(const std::string InteractionTensorIsoFileName);
+    
+    void loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName);
+    
     void setDim(int d);
     int getDim() const;
     
+    void setClusterIncOrientation(){_clusterIncOri=true;}
+    
     void addClusterLawToMap(int clusterNb, materialLaw* clusterLaw);
     
     #ifndef SWIG
-    ReductionTFA(int solver, int dim, int correction, int tag=1000);
+    ReductionTFA(int solver, int dim, int correction, bool withFrame = false, bool polarization = false, int tag=1000);
     virtual ~ReductionTFA();
     //virtual bool withEnergyDissipation() const {return false;};
     virtual const materialLaw* getMaterialLaw(int cluster) const;
@@ -148,7 +159,7 @@ class ReductionTFA: public modelReduction
                 int maxIter, double tol, double absTol, 
                 bool messageActive=false);
                 
-    bool tangentSolve(const ClusteringData *q0, const ClusteringData *q1, STensor43& L); 
+    bool tangentSolve(const ClusteringData *q0, const ClusteringData *q1, STensor43& L);
     
     virtual void localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1) = 0;
     virtual void fixDofs(); 
@@ -157,23 +168,51 @@ class ReductionTFA: public modelReduction
     virtual void getInitialDofValue(int clusterId, const STensor3& F0, const STensor3& Fn, fullVector<double>& val) const;
     virtual void updateLocalFieldFromDof(int clusterId, const fullVector<double>& vals, const ClusteringData *q0,  ClusteringData *q1);
     virtual void getLinearTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const;
-    virtual void getBiLinearTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& Dres) const;
+    virtual void getBiLinearTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& dres) const;
     virtual void getTangentTerm(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullMatrix<double>& DresDdefo) const;
+    //////////////////////////////////////////////////////////////////////////////////////////
+    virtual void getLinearTermWithFrame(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const;
+    virtual void getBiLinearTermWithFrame(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& dres) const;
+    //////////////////////////////////////////////////////////////////////////////////////////
+    virtual void getJac_rs(int r, int s, const ClusteringData *q0,  const ClusteringData *q1, STensor43& Jac_rs) const;
+    
+    virtual void getLinearTermPolarization(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, fullVector<double>& res) const;
+    virtual void getBiLinearTermPolarization(int clusterId, const ClusteringData *q0,  const ClusteringData *q1, std::vector<int>& othersId, fullMatrix<double>& dres) const;
+    virtual void getJacPolarization_rs(int r, int s, const ClusteringData *q0,  const ClusteringData *q1, STensor43& Jac_rs) const;
+    
+    virtual void elasticStiffnessHom(STensor43& CelHom) const;
+    virtual void elasticTotalTrialStressHom(const ClusteringData *q, STensor3& PtrHom) const;
+    virtual void elasticIncrementalTrialStressHom(const ClusteringData *q0, const ClusteringData *q1, STensor3& DPtrHom) const;
+    
+    virtual void secantStiffnessHom(const ClusteringData *q0, const ClusteringData *q1, STensor43& CsecHom) const;
+    virtual void secantStiffness(int r, const ClusteringData *q0, const ClusteringData *q1, STensor43& Csec) const;
+    virtual void dsecantShearModulusOveralldeps(const ClusteringData *q0, const ClusteringData *q1, int s, STensor3& dGHomdeps_s) const;
+    virtual void dtangentShearModulusOveralldeps(const ClusteringData *q0, const ClusteringData *q1, int s, STensor3& dGHomdeps_s) const;
+
+    
+    virtual double totalVolume() const;
+    virtual double clusterVolume(int r) const;
     
     // some functions
     const STensor43& getClusterAverageStrainConcentrationTensor(int cl) const; // matrix A
     const STensor43& getClusterInteractionTensor(int icl, int jcl) const; // matrix D
+    const STensor43& getClusterStrainConcentrationStDTensor(int cl) const;
+    const double& getClusterStrainConcentrationStDScalar(int cl) const;
     double getClusterNonUniformCorrection(int cl, const STensor3& macroeps0, const STensor3& macroeps) const;
     const materialLaw* getLawForCluster(int cl) const;
     
+    const STensor43& getClusterInteractionTensorIso(int icl, int jcl) const; // matrix Diso
+    
+    const fullVector<double>& getClusterMeanFiberOrientation(int cl) const;
+    
     #endif // SWIG
 };
 
 class IncrementalTangentTFA : public ReductionTFA
 {
   public:
-    IncrementalTangentTFA(int solverType, int dim, int correction, int tag=1000);
-    #ifndef SWIG
+    IncrementalTangentTFA(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag=1000);
+  #ifndef SWIG
     virtual ~IncrementalTangentTFA();
     virtual ReductionMethod getMethod() const {return modelReduction::TFA_IncrementalTangent;};
 
@@ -181,6 +220,29 @@ class IncrementalTangentTFA : public ReductionTFA
     virtual void localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1);
   #endif // SWIG
 };
+class IncrementalTangentTFAWithFrame : public ReductionTFA
+{
+  public:
+    IncrementalTangentTFAWithFrame(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag=1000);
+  #ifndef SWIG
+    virtual ~IncrementalTangentTFAWithFrame();
+    virtual ReductionMethod getMethod() const {return modelReduction::TFA_IncrementalTangentWithFrame;};
+
+  protected:
+    virtual void localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1);
+  #endif // SWIG
+};
+class IncrementalTangentTFAPolarization : public ReductionTFA
+{
+  public:
+    IncrementalTangentTFAPolarization(int solverType, int dim, int correction, bool withFrame, bool polarization, int tag=1000);
+  #ifndef SWIG
+    virtual ~IncrementalTangentTFAPolarization();
+    virtual ReductionMethod getMethod() const {return modelReduction::TFA_IncrementalTangentPolarization;};
 
+  protected:
+    virtual void localConstitutive(const STensor3& F0, const STensor3& Fn, const ClusteringData *q0,  ClusteringData *q1);
+  #endif // SWIG
+};
 
 #endif //MODELREDUCTION_H_
diff --git a/NonLinearSolver/nlsolver/nonLinearMechSolver.cpp b/NonLinearSolver/nlsolver/nonLinearMechSolver.cpp
index 48b026357912e0be0dea96c8b5935ad7550a247a..2dc54959cba126d78f47aeee1b22a1d3ea4f830b 100644
--- a/NonLinearSolver/nlsolver/nonLinearMechSolver.cpp
+++ b/NonLinearSolver/nlsolver/nonLinearMechSolver.cpp
@@ -12222,7 +12222,8 @@ void nonLinearMechSolver::microNumberDof(){
 
   bool insystemCondenFlag = false;
 
-  if (_tangentflag and _homogenizeTangentMethod == INSYSTEMCONDEN){
+  if (_tangentflag and (_homogenizeTangentMethod == INSYSTEMCONDEN or computedUdF()))
+  {
     insystemCondenFlag = true;
   };
 
diff --git a/NonLinearSolver/periodicBC/pbcAlgorithm.cpp b/NonLinearSolver/periodicBC/pbcAlgorithm.cpp
index f555ccdad5ddf8bce52479e3d36872aefc468a1a..e0bd2ed30031b57d7f513ac62f7262b856e7e5cb 100644
--- a/NonLinearSolver/periodicBC/pbcAlgorithm.cpp
+++ b/NonLinearSolver/periodicBC/pbcAlgorithm.cpp
@@ -691,10 +691,12 @@ void pbcAlgorithm::allocateConstraintMatrixToSystem(int kinematicDim, int stress
                 pbcsys->setNeedBodyForceVector(true);
 	    pbcsys->allocateConstraintMatrix(size,_solver->getDofManager()->sizeOfR());
 	    pbcsys->setScaleFactor(_scale);
-	if (tangentFlag){
-          pbcsys->allocateKinematicMatrix(size,kinematicDim);
-          pbcsys->allocateStressMatrix(stressDim,_solver->getDofManager()->sizeOfR());
-          if (_solver->computedUdF())
+	if (tangentFlag or _solver->computedUdF()){
+          if(!pbcsys->isAllocatedKinematicMatrix())
+            pbcsys->allocateKinematicMatrix(size,kinematicDim);
+          if(!pbcsys->isAllocatedStressMatrix())
+            pbcsys->allocateStressMatrix(stressDim,_solver->getDofManager()->sizeOfR());
+          if (_solver->computedUdF() and !pbcsys->isAllocatedBodyForceMatrix())
             pbcsys->allocateBodyForceMatrix(_solver->getDofManager()->sizeOfR());
 	}
 	}
diff --git a/dG3D/benchmarks/CMakeLists.txt b/dG3D/benchmarks/CMakeLists.txt
index 86fb956538d2983a6167a53a996e9467519c86ac..93d355d736a6f3d6d8688e77a57482f80f76d96d 100644
--- a/dG3D/benchmarks/CMakeLists.txt
+++ b/dG3D/benchmarks/CMakeLists.txt
@@ -254,4 +254,5 @@ add_subdirectory(wovenROM)
 add_subdirectory(nanoIndentation)
 add_subdirectory(DG_PRI6_numstepTimeInterval)
 add_subdirectory(TFA_offline_onlineUniaxTension)
+add_subdirectory(honeycomb_compression)
 
diff --git a/dG3D/benchmarks/GursonMultipleNonlocal_PathFollowing/Plane_notch.py b/dG3D/benchmarks/GursonMultipleNonlocal_PathFollowing/Plane_notch.py
index f02cd60c36bde1f35a0bf2c3e0219210125b3888..eae29ff050fd7debbe263076bb4adb114cb36fde 100644
--- a/dG3D/benchmarks/GursonMultipleNonlocal_PathFollowing/Plane_notch.py
+++ b/dG3D/benchmarks/GursonMultipleNonlocal_PathFollowing/Plane_notch.py
@@ -176,4 +176,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-1.325725e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-1.439426e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/GursonThomasonFullCoalescence/Plane_notch.py b/dG3D/benchmarks/GursonThomasonFullCoalescence/Plane_notch.py
index 209febf8552615e1c25bb85d543f6c875e626c77..b0d522fd9e68ed1b0c643a71ff88dc15f7c776b4 100644
--- a/dG3D/benchmarks/GursonThomasonFullCoalescence/Plane_notch.py
+++ b/dG3D/benchmarks/GursonThomasonFullCoalescence/Plane_notch.py
@@ -196,4 +196,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-9.126381e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-4)
+check.equal(-9.130936e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-4)
diff --git a/dG3D/benchmarks/GursonThomasonMultipleNonlocalVar_PathFollowing/Plane_notch.py b/dG3D/benchmarks/GursonThomasonMultipleNonlocalVar_PathFollowing/Plane_notch.py
index ac81bb307f47e8430cc50e3273c254dbbeb25d67..fe97c5ec531838e2d58de0f1b963cb54b5da37dc 100644
--- a/dG3D/benchmarks/GursonThomasonMultipleNonlocalVar_PathFollowing/Plane_notch.py
+++ b/dG3D/benchmarks/GursonThomasonMultipleNonlocalVar_PathFollowing/Plane_notch.py
@@ -190,4 +190,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-5.464206e+01,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-5.458367e+01,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/GursonThomasonThermo_NonlocalLogPorosity/Plane_notch.py b/dG3D/benchmarks/GursonThomasonThermo_NonlocalLogPorosity/Plane_notch.py
index 3598bae145cd1b8b9196669f79f6687a9f5d9764..30ae0706ae78624c14f2350d6a4e2eb96c722ac3 100644
--- a/dG3D/benchmarks/GursonThomasonThermo_NonlocalLogPorosity/Plane_notch.py
+++ b/dG3D/benchmarks/GursonThomasonThermo_NonlocalLogPorosity/Plane_notch.py
@@ -199,4 +199,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-1.912423e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-1.912430e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/GursonThomasonThermo_NonlocalPorosity/Plane_notch.py b/dG3D/benchmarks/GursonThomasonThermo_NonlocalPorosity/Plane_notch.py
index cde9dabfe6dc22210133f8d6573b8c92ec540882..e83b8ff51c84bc6abdc1a8ac8c1c62951f18d1a9 100644
--- a/dG3D/benchmarks/GursonThomasonThermo_NonlocalPorosity/Plane_notch.py
+++ b/dG3D/benchmarks/GursonThomasonThermo_NonlocalPorosity/Plane_notch.py
@@ -196,4 +196,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-1.912453e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-1.912460e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/Gurson_PathFollowing/Plane_notch.py b/dG3D/benchmarks/Gurson_PathFollowing/Plane_notch.py
index 7ff45695b85a0d4233a295d3cf53d5ee1f04054e..304ec70afdb59070b3cc4bc0d662a42ca4c2f575 100755
--- a/dG3D/benchmarks/Gurson_PathFollowing/Plane_notch.py
+++ b/dG3D/benchmarks/Gurson_PathFollowing/Plane_notch.py
@@ -169,4 +169,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-6.573797e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-6.573785e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/LocalGurson_PathFollowing/Plane_notch.py b/dG3D/benchmarks/LocalGurson_PathFollowing/Plane_notch.py
index 419b56e05b0d9b75dc3b816500a38fa06d42bf86..c0ce5876331e0a33aec4798b54e5ad41173ab459 100644
--- a/dG3D/benchmarks/LocalGurson_PathFollowing/Plane_notch.py
+++ b/dG3D/benchmarks/LocalGurson_PathFollowing/Plane_notch.py
@@ -155,4 +155,4 @@ mysolver.archivingIPOnPhysicalGroup("Face", 700, IPField.LOCAL_POROSITY,IPField.
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-2.697783e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
+check.equal(-2.697800e+03,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1400, 0),1.e-6)
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.geo b/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.geo
index 2da0b8dc75f0e19adca35e8b5ca972f75223cfb8..d5e4011838b94431123cde486ac750111af24cbb 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.geo
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.geo
@@ -17,10 +17,10 @@ For index In {0:1}
   x2=x[1+2*index];
   z1=z[0+2*index];
   z2=z[1+2*index];
-  Point(100*index+1) = { x1 , 0. , z1, Lc1};
-  Point(100*index+2) = {  x2  , 0. , z1 , Lc1};
-  Point(100*index+5) = { x1 , 0. , z2 , Lc1};
-  Point(100*index+6) = {  x2  , 0. , z2 , Lc1};
+  Point(100*index+1) = { x1 , z1, 0., Lc1};
+  Point(100*index+2) = {  x2  , z1 , 0., Lc1};
+  Point(100*index+5) = { x1 ,  z2 , 0., Lc1};
+  Point(100*index+6) = {  x2  , z2 , 0., Lc1};
 
   // Line between points
   Line(100*index+1) = {100*index+1,100*index+2};
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.py b/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.py
index 720cd89f70d14c7f8b8cd595974c651bd3b50adf..8b5a113d43509ebd150979628fa54324ba6d0117 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.py
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2D2ndOrderTri/squares.py
@@ -57,16 +57,16 @@ mysolver.stepBetweenArchiving(nstepArch)
 mysolver.snlManageTimeStep(50, 4, 2, 10)
 #mysolver.lineSearch(bool(1))
 
-mysolver.displacementBC("Face",nfield1,1,0.)
-mysolver.displacementBC("Face",nfield2,1,0.)
+mysolver.displacementBC("Face",nfield1,2,0.)
+mysolver.displacementBC("Face",nfield2,2,0.)
 #compression along z
 mysolver.displacementBC("Edge",12,0,0.)
-mysolver.displacementBC("Edge",12,2,0.)
+mysolver.displacementBC("Edge",12,1,0.)
 d1=-0.00005
 cyclicFunction1=cycleFunctionTime(0.,0.,ftime/4., d1/2., ftime/2., 0., 3.*ftime/4., d1/2., ftime, d1);
 #cyclicFunction1=cycleFunctionTime(0.,0.,ftime, d1);
 mysolver.displacementBC("Edge",156,0,0.)
-mysolver.displacementBC("Edge",156,2,cyclicFunction1)
+mysolver.displacementBC("Edge",156,1,cyclicFunction1)
 
 #contact
 defoDefoContact1=dG3DNodeOnSurfaceContactDomain(1200, 1, 56, 1,112, penalty, thick)
@@ -86,10 +86,10 @@ mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1)
 mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1)
 mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1)
 mysolver.internalPointBuildView("epl",IPField.PLASTICSTRAIN, 1, 1)
-mysolver.archivingForceOnPhysicalGroup("Edge", 12, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 56, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 112, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
+mysolver.archivingForceOnPhysicalGroup("Edge", 12, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 56, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 112, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 156, 1)
 
 #mysolver.createRestartBySteps(2);
 
@@ -97,6 +97,6 @@ mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
 mysolver.solve()
 
 check = TestCheck()
-check.equal(3.943483e+06,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 2),1.e-6)
+check.equal(3.943483e+06,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 1),1.e-6)
 
 
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.geo b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.geo
index b01f997550db588c7b3d07cd1c11148e12983e06..78aa3ea7bd3bf26ae4482fc2fa207f1453e2e627 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.geo
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.geo
@@ -17,10 +17,10 @@ For index In {0:1}
   x2=x[1+2*index];
   z1=z[0+2*index];
   z2=z[1+2*index];
-  Point(100*index+1) = { x1 , 0. , z1, Lc1};
-  Point(100*index+2) = {  x2  , 0. , z1 , Lc1};
-  Point(100*index+5) = { x1 , 0. , z2 , Lc1};
-  Point(100*index+6) = {  x2  , 0. , z2 , Lc1};
+  Point(100*index+1) = { x1 , z1, 0., Lc1};
+  Point(100*index+2) = { x2 , z1, 0., Lc1};
+  Point(100*index+5) = { x1 , z2, 0., Lc1};
+  Point(100*index+6) = { x2 , z2, 0., Lc1};
 
   // Line between points
   Line(100*index+1) = {100*index+1,100*index+2};
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.py b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.py
index 83cf2d41650af4314dca8c427bb42ba1b99a11c5..c91587b3d6de5f2c9ebba16a944374beefabca07 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.py
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuad/squares.py
@@ -55,8 +55,8 @@ mysolver.Solver(sol)
 mysolver.snlData(nstep,ftime,tol)
 mysolver.stepBetweenArchiving(nstepArch)
 
-mysolver.displacementBC("Face",nfield1,1,0.)
-mysolver.displacementBC("Face",nfield2,1,0.)
+mysolver.displacementBC("Face",nfield1,2,0.)
+mysolver.displacementBC("Face",nfield2,2,0.)
 #compression along z
 mysolver.displacementBC("Edge",12,0,0.)
 mysolver.displacementBC("Edge",12,2,0.)
@@ -64,7 +64,7 @@ d1=-0.00025
 cyclicFunction1=cycleFunctionTime(0.,0.,ftime/4., d1/2., ftime/2., 0., 3.*ftime/4., d1/2., ftime, d1);
 #cyclicFunction1=cycleFunctionTime(0.,0.,ftime, d1);
 mysolver.displacementBC("Edge",156,0,0.)
-mysolver.displacementBC("Edge",156,2,cyclicFunction1)
+mysolver.displacementBC("Edge",156,1,cyclicFunction1)
 
 #contact
 defoDefoContact1=dG3DNodeOnSurfaceContactDomain(1200, 1, 56, 1,112, penalty, thick)
@@ -82,10 +82,10 @@ mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1)
 mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1)
 mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1)
 mysolver.internalPointBuildView("epl",IPField.PLASTICSTRAIN, 1, 1)
-mysolver.archivingForceOnPhysicalGroup("Edge", 12, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 56, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 112, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
+mysolver.archivingForceOnPhysicalGroup("Edge", 12, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 56, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 112, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 156, 1)
 
 #mysolver.createRestartBySteps(2);
 
@@ -93,6 +93,6 @@ mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
 mysolver.solve()
 
 check = TestCheck()
-check.equal(2.451079e+07,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 2),1.e-6)
+check.equal(2.451079e+07,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 1),1.e-6)
 
 
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.geo b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.geo
index b01f997550db588c7b3d07cd1c11148e12983e06..f6276c73a985f523b0f4c064c53c8e2dab8239ba 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.geo
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.geo
@@ -17,10 +17,10 @@ For index In {0:1}
   x2=x[1+2*index];
   z1=z[0+2*index];
   z2=z[1+2*index];
-  Point(100*index+1) = { x1 , 0. , z1, Lc1};
-  Point(100*index+2) = {  x2  , 0. , z1 , Lc1};
-  Point(100*index+5) = { x1 , 0. , z2 , Lc1};
-  Point(100*index+6) = {  x2  , 0. , z2 , Lc1};
+  Point(100*index+1) = { x1 , z1, 0., Lc1};
+  Point(100*index+2) = {  x2 , z1 , 0.,  Lc1};
+  Point(100*index+5) = { x1 , z2 , 0., Lc1};
+  Point(100*index+6) = {  x2  , z2 , 0., Lc1};
 
   // Line between points
   Line(100*index+1) = {100*index+1,100*index+2};
diff --git a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.py b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.py
index 612e3583cb931b2e425db33ba3dc6ffe0a003b25..d7bee5a4d3e0d8fc361cf57800b4b301fb50bd2e 100644
--- a/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.py
+++ b/dG3D/benchmarks/defoDefoContactSlaveEdge2DQuadPert/squares.py
@@ -55,16 +55,16 @@ mysolver.Solver(sol)
 mysolver.snlData(nstep,ftime,tol)
 mysolver.stepBetweenArchiving(nstepArch)
 
-mysolver.displacementBC("Face",nfield1,1,0.)
-mysolver.displacementBC("Face",nfield2,1,0.)
+mysolver.displacementBC("Face",nfield1,2,0.)
+mysolver.displacementBC("Face",nfield2,2,0.)
 #compression along z
 mysolver.displacementBC("Edge",12,0,0.)
-mysolver.displacementBC("Edge",12,2,0.)
+mysolver.displacementBC("Edge",12,1,0.)
 d1=-0.00025
 cyclicFunction1=cycleFunctionTime(0.,0.,ftime/4., d1/2., ftime/2., 0., 3.*ftime/4., d1/2., ftime, d1);
 #cyclicFunction1=cycleFunctionTime(0.,0.,ftime, d1);
 mysolver.displacementBC("Edge",156,0,0.)
-mysolver.displacementBC("Edge",156,2,cyclicFunction1)
+mysolver.displacementBC("Edge",156,1,cyclicFunction1)
 
 #contact
 defoDefoContact1=dG3DNodeOnSurfaceContactDomain(1200, 1, 56, 1,112, penalty, thick)
@@ -84,10 +84,10 @@ mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1)
 mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1)
 mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1)
 mysolver.internalPointBuildView("epl",IPField.PLASTICSTRAIN, 1, 1)
-mysolver.archivingForceOnPhysicalGroup("Edge", 12, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 56, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 112, 2)
-mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
+mysolver.archivingForceOnPhysicalGroup("Edge", 12, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 56, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 112, 1)
+mysolver.archivingForceOnPhysicalGroup("Edge", 156, 1)
 
 #mysolver.createRestartBySteps(2);
 
@@ -95,6 +95,6 @@ mysolver.archivingForceOnPhysicalGroup("Edge", 156, 2)
 mysolver.solve()
 
 check = TestCheck()
-check.equal(2.451079e+07,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 2),1.e-6)
+check.equal(2.451079e+07,mysolver.getArchivedForceOnPhysicalGroup("Edge", 12, 1),1.e-6)
 
 
diff --git a/dG3D/benchmarks/elasticFE2/macro.py b/dG3D/benchmarks/elasticFE2/macro.py
index 96e493d3b1c35c9b16371f9da30c7980f84ec5e2..dd355a662ea734f5b9d2f33ddc015e23f8bdf93d 100644
--- a/dG3D/benchmarks/elasticFE2/macro.py
+++ b/dG3D/benchmarks/elasticFE2/macro.py
@@ -125,5 +125,5 @@ mysolver.archivingForceOnPhysicalGroup("Face",45,1)
 mysolver.solve()
 
 check = TestCheck()
-check.equal(-2.503729e+04,mysolver.getArchivedForceOnPhysicalGroup("Face", 45, 1),1.e-4)
+check.equal(-2.504277e+04,mysolver.getArchivedForceOnPhysicalGroup("Face", 45, 1),1.e-4)
 
diff --git a/dG3D/benchmarks/honeycomb_compression/CMakeLists.txt b/dG3D/benchmarks/honeycomb_compression/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1962ddb23aca0cb674d3cf124e991e636e2445b2
--- /dev/null
+++ b/dG3D/benchmarks/honeycomb_compression/CMakeLists.txt
@@ -0,0 +1,12 @@
+# test file
+
+set(PYFILE multiscale.py)
+
+set(FILES2DELETE 
+  *.csv
+  disp*
+  stress*
+  E*
+)
+
+add_cm3python_mpi_test(4 ${PYFILE} "${FILES2DELETE}")
diff --git a/dG3D/benchmarks/honeycomb_compression/macro4.msh b/dG3D/benchmarks/honeycomb_compression/macro4.msh
new file mode 100644
index 0000000000000000000000000000000000000000..804e983ab1e7715b44c7459a7e999728994c731c
--- /dev/null
+++ b/dG3D/benchmarks/honeycomb_compression/macro4.msh
@@ -0,0 +1,290 @@
+$MeshFormat
+4.1 0 8
+$EndMeshFormat
+$Entities
+4 4 1 0
+1 -32.909 -51 0 1 1 
+2 32.909 -51 0 1 2 
+3 32.909 51 0 1 3 
+4 -32.909 51 0 1 4 
+1 -32.909 -51 0 32.909 -51 0 1 1 2 1 -2 
+2 32.909 -51 0 32.909 51 0 1 2 2 2 -3 
+3 -32.909 51 0 32.909 51 0 1 3 2 3 -4 
+4 -32.909 -51 0 -32.909 51 0 1 4 2 4 -1 
+11 -32.909 -51 0 32.909 51 0 1 11 4 1 2 3 4 
+$EndEntities
+$PartitionedEntities
+4
+0
+9 12 4 0
+5 0 1 1 4 -32.909 -51 0 1 1 
+6 0 2 1 3 32.909 -51 0 1 2 
+7 0 3 1 2 32.909 51 0 1 3 
+8 0 4 1 1 -32.909 51 0 1 4 
+9 2 11 4 1 2 3 4 0 0 0 0 
+10 1 4 2 1 4 -32.909 8.729728051548591e-11 0 0 
+11 1 1 2 3 4 -8.945022500483901e-11 -51 0 0 
+12 1 3 2 1 2 8.945022500483901e-11 51 0 0 
+13 1 2 2 2 3 32.909 -8.729728051548591e-11 0 0 
+5 1 1 1 4 -32.909 -51 0 -8.945022500483901e-11 -51 0 1 1 2 5 -11 
+6 1 1 1 3 -8.945022500483901e-11 -51 0 32.909 -51 0 1 1 2 11 -6 
+7 1 2 1 3 32.909 -51 0 32.909 -8.729728051548591e-11 0 1 2 2 6 -13 
+8 1 2 1 2 32.909 -8.729728051548591e-11 0 32.909 51 0 1 2 2 13 -7 
+9 1 3 1 2 8.945022500483901e-11 51 0 32.909 51 0 1 3 2 7 -12 
+10 1 3 1 1 -32.909 51 0 8.945022500483901e-11 51 0 1 3 2 12 -8 
+11 1 4 1 1 -32.909 8.729728051548591e-11 0 -32.909 51 0 1 4 2 8 -10 
+12 1 4 1 4 -32.909 -51 0 -32.909 8.729728051548591e-11 0 1 4 2 10 -5 
+13 2 11 2 2 3 0 -8.729728051548591e-11 0 32.909 0 0 0 2 9 -13 
+14 2 11 2 1 2 0 0 0 8.945022500483901e-11 51 0 0 2 9 -12 
+15 2 11 2 3 4 -8.945022500483901e-11 -51 0 0 0 0 0 2 9 -11 
+16 2 11 2 1 4 -32.909 0 0 0 8.729728051548591e-11 0 0 2 10 -9 
+12 2 11 1 4 -32.909 -51 0 0 8.729728051548591e-11 0 1 11 4 5 12 -15 -16 
+13 2 11 1 1 -32.909 0 0 8.945022500483901e-11 51 0 1 11 4 10 11 14 16 
+14 2 11 1 3 -8.945022500483901e-11 -51 0 32.909 0 0 1 11 4 6 7 -13 15 
+15 2 11 1 2 0 -8.729728051548591e-11 0 32.909 51 0 1 11 4 8 9 13 -14 
+$EndPartitionedEntities
+$Nodes
+25 81 1 81
+0 5 0 1
+1
+-32.909 -51 0
+0 6 0 1
+2
+32.909 -51 0
+0 7 0 1
+3
+32.909 51 0
+0 8 0 1
+4
+-32.909 51 0
+0 9 0 1
+37
+0 0 0
+0 10 0 1
+27
+-32.909 8.729728051548591e-11 0
+0 11 0 1
+6
+-8.945022500483901e-11 -51 0
+0 12 0 1
+20
+8.945022500483901e-11 51 0
+0 13 0 1
+13
+32.909 -8.729728051548591e-11 0
+1 5 0 3
+5
+8
+9
+-16.45450000004057 -51 0
+-24.68175000001599 -51 0
+-8.227250000065023 -51 0
+1 6 0 3
+7
+10
+11
+16.4544999999518 -51 0
+8.227249999941243 -51 0
+24.68174999997921 -51 0
+1 7 0 3
+12
+15
+16
+32.909 -25.4999999999791 0
+32.909 -38.2499999999825 0
+32.909 -12.75000000003578 0
+1 8 0 3
+14
+17
+18
+32.909 25.49999999995565 0
+32.909 12.74999999994362 0
+32.909 38.24999999997274 0
+1 9 0 3
+19
+22
+23
+16.45450000004057 51 0
+24.68175000001599 51 0
+8.227250000065023 51 0
+1 10 0 3
+21
+24
+25
+-16.4544999999518 51 0
+-8.227249999941243 51 0
+-24.68174999997921 51 0
+1 11 0 3
+26
+29
+30
+-32.909 25.4999999999791 0
+-32.909 38.2499999999825 0
+-32.909 12.75000000003578 0
+1 12 0 3
+28
+31
+32
+-32.909 -25.49999999995565 0
+-32.909 -12.74999999994362 0
+-32.909 -38.24999999997274 0
+1 13 0 3
+40
+68
+77
+16.45449999999618 -4.364775207932325e-11 0
+8.22724999999809 -2.182387603966163e-11 0
+24.68174999999809 -6.547251629740458e-11 0
+1 14 0 3
+38
+59
+62
+4.472511250236228e-11 25.49999999996737 0
+2.236255625118114e-11 12.74999999998369 0
+6.708766875360064e-11 38.24999999998369 0
+1 15 0 3
+36
+56
+53
+-4.472511250236228e-11 -25.49999999996737 0
+-2.236255625118114e-11 -12.74999999998369 0
+-6.708766875360064e-11 -38.24999999998369 0
+1 16 0 3
+34
+57
+46
+-16.45449999999619 4.364864025774295e-11 0
+-8.227249999998094 2.182432012887148e-11 0
+-24.68174999999809 6.547296038661443e-11 0
+2 12 0 9
+33
+42
+43
+44
+45
+47
+54
+55
+58
+-16.45450000001838 -25.49999999996151 0
+-16.45450000002947 -38.24999999998076 0
+-24.68175000000919 -25.49999999995858 0
+-24.68175000001258 -38.24999999997674 0
+-16.45450000000728 -12.74999999995893 0
+-24.68175000000364 -12.74999999995127 0
+-8.227250000031551 -25.49999999996444 0
+-8.227250000048288 -38.24999999998222 0
+-8.227250000014822 -12.74999999997131 0
+2 13 0 9
+35
+48
+49
+50
+51
+52
+60
+61
+63
+-16.45449999997399 25.49999999997323 0
+-16.45449999998509 12.75000000000844 0
+-24.68174999998699 25.49999999997617 0
+-24.68174999999255 12.75000000002211 0
+-16.45449999996289 38.24999999998661 0
+-24.6817499999831 38.24999999998455 0
+-8.227249999964632 25.4999999999703 0
+-8.227249999981362 12.74999999999606 0
+-8.227249999952937 38.24999999998515 0
+2 14 0 9
+39
+64
+65
+66
+67
+69
+75
+76
+78
+16.45449999997399 -25.49999999997323 0
+16.4544999999629 -38.24999999998661 0
+8.227249999964634 -25.4999999999703 0
+8.22724999995294 -38.24999999998515 0
+16.45449999998509 -12.75000000000844 0
+8.227249999981364 -12.74999999999606 0
+24.681749999987 -25.49999999997616 0
+24.6817499999831 -38.24999999998456 0
+24.68174999999254 -12.75000000002211 0
+2 15 0 9
+41
+70
+71
+72
+73
+74
+79
+80
+81
+16.45450000001838 25.49999999996151 0
+16.45450000000728 12.74999999995893 0
+8.227250000031551 25.49999999996444 0
+8.22725000001482 12.74999999997131 0
+16.45450000002947 38.24999999998076 0
+8.227250000048285 38.24999999998222 0
+24.68175000000919 25.49999999995858 0
+24.68175000000364 12.74999999995127 0
+24.68175000001259 38.24999999997675 0
+$EndNodes
+$Elements
+16 36 1 36
+0 5 15 1
+1 1 
+0 6 15 1
+2 2 
+0 7 15 1
+3 3 
+0 8 15 1
+4 4 
+1 5 8 2
+5 1 5 8 
+6 5 6 9 
+1 6 8 2
+7 6 7 10 
+8 7 2 11 
+1 7 8 2
+9 2 12 15 
+10 12 13 16 
+1 8 8 2
+11 13 14 17 
+12 14 3 18 
+1 9 8 2
+13 3 19 22 
+14 19 20 23 
+1 10 8 2
+15 20 21 24 
+16 21 4 25 
+1 11 8 2
+17 4 26 29 
+18 26 27 30 
+1 12 8 2
+19 27 28 31 
+20 28 1 32 
+2 12 10 4
+21 1 5 33 28 8 42 43 32 44 
+22 28 33 34 27 43 45 46 31 47 
+25 5 6 36 33 9 53 54 42 55 
+26 33 36 37 34 54 56 57 45 58 
+2 13 10 4
+23 27 34 35 26 46 48 49 30 50 
+24 26 35 21 4 49 51 25 29 52 
+27 34 37 38 35 57 59 60 48 61 
+28 35 38 20 21 60 62 24 51 63 
+2 14 10 4
+29 6 7 39 36 10 64 65 53 66 
+30 36 39 40 37 65 67 68 56 69 
+33 7 2 12 39 11 15 75 64 76 
+34 39 12 13 40 75 16 77 67 78 
+2 15 10 4
+31 37 40 41 38 68 70 71 59 72 
+32 38 41 19 20 71 73 23 62 74 
+35 40 13 14 41 77 17 79 70 80 
+36 41 14 3 19 79 18 22 73 81 
+$EndElements
diff --git a/dG3D/benchmarks/honeycomb_compression/multiscale.py b/dG3D/benchmarks/honeycomb_compression/multiscale.py
index 90f185b0c17168b23a8d72fa9ae0c129369153aa..7ea2f70b753da5fea5efa6ba6f917c171d10e568 100644
--- a/dG3D/benchmarks/honeycomb_compression/multiscale.py
+++ b/dG3D/benchmarks/honeycomb_compression/multiscale.py
@@ -147,4 +147,7 @@ mysolver.archivingNodeDisplacement(4,1,1)
 
 # solve
 mysolver.solve()
+# test check
+check = TestCheck()
+check.equal(1.947727e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1, 1),1e-3)
 
diff --git a/dG3D/benchmarks/honeycomb_compression/multiscalePert.py b/dG3D/benchmarks/honeycomb_compression/multiscalePert.py
new file mode 100644
index 0000000000000000000000000000000000000000..0173587ef7b14b65d84f59e9d88549455213af15
--- /dev/null
+++ b/dG3D/benchmarks/honeycomb_compression/multiscalePert.py
@@ -0,0 +1,157 @@
+#coding-Utf-8-*-
+from gmshpy import *
+from dG3Dpy import*
+
+import math
+
+#script to launch PBC problem with a python script
+#---------------------------------------------------------------------------------------------------------------#
+#DEFINE MICRO PROBLEM
+
+# micro-material law
+E = 68.9E3 #Young modulus
+nu = 0.33 #Poisson ratio
+K = E/3./(1.-2.*nu)
+mu = E/2./(1+nu)
+sy0 = 276. #Yield stress
+h = E/100 # hardening modulus
+rho = 1.  #density
+# micro-geometry
+
+# creation of material law
+harden1 = LinearExponentialJ2IsotropicHardening(11, sy0, h,  0., 10.)
+law1 = J2LinearDG3DMaterialLaw(11,rho,E,nu,harden1)
+
+# creation of  micro part Domain
+myfield1 = dG3DDomain(1000,11,0,11,0,2)
+
+
+
+microBC = nonLinearPeriodicBC(1000,2)
+microBC.setBCPhysical(1,2,3,4)
+method =1	# Periodic mesh = 0
+degree =11 # Order used for polynomial interpolation 
+addvertex = True  # Polynomial interpolation by mesh vertex = 0, Polynomial interpolation by virtual vertex 
+microBC.setPeriodicBCOptions(method, degree, bool(addvertex))
+
+# DEFINE MACROPROBLEM
+matnum1 = 1;
+macromat1 = hoDGMultiscaleMaterialLaw(matnum1, 1000)
+macromat1.loadAllRVEMeshes("rve")
+
+microSolver1 = macromat1.getMicroSolver()
+microSolver1.loadModel("rve1.msh")
+microSolver1.addDomain(myfield1)
+microSolver1.addMaterialLaw(law1);
+
+microSolver1.addMicroBC(microBC)
+
+#microSolver1.pathFollowing(True,0)
+#microSolver1.setPathFollowingControlType(1)
+#microSolver1.setPathFollowingArcLengthStep(1e-3)
+
+
+microSolver1.snlData(1,1.,1e-5,1e-10)
+microSolver1.setSystemType(1)
+microSolver1.Solver(2)
+
+
+microSolver1.Scheme(1)
+microSolver1.setSameStateCriterion(1e-16)
+microSolver1.stressAveragingFlag(True) # set stress averaging ON- 0 , OFF-1
+microSolver1.setStressAveragingMethod(0)
+microSolver1.tangentAveragingFlag(True) # set tangent averaging ON -0, OFF -1
+microSolver1.setTangentAveragingMethod(2,1e-6);
+
+microSolver1.internalPointBuildView("Green-Lagrange_xx",IPField.GL_XX);
+microSolver1.internalPointBuildView("Green-Lagrange_yy",IPField.GL_YY);
+microSolver1.internalPointBuildView("Green-Lagrange_xy",IPField.GL_XY);
+microSolver1.internalPointBuildView("sig_xx",IPField.SIG_XX);
+microSolver1.internalPointBuildView("sig_yy",IPField.SIG_YY);
+microSolver1.internalPointBuildView("sig_xy",IPField.SIG_XY);
+microSolver1.internalPointBuildView("sig_VM",IPField.SVM);
+
+microSolver1.internalPointBuildView("Equivalent plastic strain",IPField.PLASTICSTRAIN);
+microSolver1.internalPointBuildView("Deformation energy",IPField.DEFO_ENERGY);
+microSolver1.internalPointBuildView("Plastic energy",IPField.PLASTIC_ENERGY);
+
+microSolver1.displacementBC("Face",11,2,0.)
+
+
+#------------------------------------------
+macromeshfile="macro4.msh" # name of mesh file
+
+# solver
+sol = 2  # Gmm=0 (default) Taucs=1 PETsc=2
+soltype =1 # StaticLinear=0 (default) StaticNonLinear=1
+nstep = 200  # number of step (used only if soltype=1)
+ftime =1.   # Final time (used only if soltype=1)
+tol=1.e-5  # relative tolerance for NR scheme (used only if soltype=1)
+nstepArch=1 # Number of step between 2 archiving (used only if soltype=1)
+
+
+# creation of  macro part Domain
+
+dim =2
+fulldg = 1
+beta1 = 1000
+
+#macrodomain1 = FSDomain(1000,11,matnum1,dim)
+macrodomain1 =hoDGDomain(1000,11,0,matnum1,fulldg,dim)
+macrodomain1.stabilityParameters(beta1)
+#macrodomain1.distributeOnRootRank(1)
+macrodomain1.matrixByPerturbation(1,1,1,1.e-8)
+
+# creation of Solver
+mysolver = nonLinearMechSolver(1000)
+mysolver.loadModel(macromeshfile)
+mysolver.addDomain(macrodomain1)
+mysolver.addMaterialLaw(macromat1)
+
+mysolver.Scheme(soltype)
+mysolver.Solver(sol)
+mysolver.snlData(nstep,ftime,tol)
+
+#mysolver.pathFollowing(True,0)
+#mysolver.setPathFollowingControlType(1)
+#mysolver.setPathFollowingArcLengthStep(1e-3)
+
+# boundary condition
+mysolver.displacementBC("Face",11,2,0.0)
+
+mysolver.displacementBC("Node",4,0,0)
+mysolver.displacementBC("Edge",1,1,0)
+
+#mysolver.constraintBC("Edge",3,1)
+#mysolver.forceBC("Edge",3,1,-0.25e2)
+mysolver.displacementBC("Edge",3,1,-5.)
+
+# archivage
+mysolver.internalPointBuildView("Green-Lagrange_xx",IPField.STRAIN_XX, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_yy",IPField.STRAIN_YY, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_zz",IPField.STRAIN_ZZ, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_xy",IPField.STRAIN_XY, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_yz",IPField.STRAIN_YZ, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_xz",IPField.STRAIN_XZ, 1, 1);
+mysolver.internalPointBuildView("sig_xx",IPField.SIG_XX, 1, 1);
+mysolver.internalPointBuildView("sig_yy",IPField.SIG_YY, 1, 1);
+mysolver.internalPointBuildView("sig_zz",IPField.SIG_ZZ, 1, 1);
+mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1);
+mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1);
+mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1);
+mysolver.internalPointBuildView("sig_VM",IPField.SVM, 1, 1);
+mysolver.internalPointBuildView("Equivalent plastic strain",IPField.PLASTICSTRAIN, 1, 1);
+mysolver.internalPointBuildView("High-order strain norm",IPField.HIGHSTRAIN_NORM, 1, 1);
+mysolver.internalPointBuildView("High-order stress norm",IPField.HIGHSTRESS_NORM, 1, 1);
+mysolver.internalPointBuildView("Green -Lagrange strain norm",IPField.GL_NORM, 1, 1);
+mysolver.internalPointBuildView("PK2 stress norm",IPField.STRESS_NORM, 1, 1);
+
+mysolver.archivingForceOnPhysicalGroup("Edge",1,1)
+mysolver.archivingNodeDisplacement(4,1,1)
+
+# solve
+mysolver.solve()
+# test check
+check = TestCheck()
+check.equal(1.947727e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge", 1, 1),1e-3)
+
diff --git a/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer.py b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer.py
index 2ff264b85382ca0e837e638d28e1ac8751c60feb..969035c61945c6460a7ede2f253a72c75475dd30 100644
--- a/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer.py
+++ b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer.py
@@ -71,25 +71,33 @@ nstepArch=1 # Number of step between 2 archiving (used only if soltype=1)
 
 dim =2
 beta1 = 150;
-fdg=0
+fdg=1
 
 nfield1 = 11
 macrodomain1 = hoDGDomain(11,nfield1,0,matnum,fdg,dim)
 macrodomain1.stabilityParameters(beta1)
+macrodomain1.distributeOnRootRank(0)
+macrodomain1.matrixByPerturbation(1,1,1,1e-8)
 
 nfield2 = 12
 macrodomain2 = hoDGDomain(12,nfield2,0,matnum,fdg,dim)
 macrodomain2.stabilityParameters(beta1)
+macrodomain2.distributeOnRootRank(0)
+macrodomain2.matrixByPerturbation(1,1,1,1e-8)
 
 nfield3 = 13
 macrodomain3 = hoDGDomain(13,nfield3,0,matnum,fdg,dim)
 macrodomain3.stabilityParameters(beta1)
+macrodomain3.distributeOnRootRank(0)
+macrodomain3.matrixByPerturbation(1,1,1,1e-8)
 
 interdomain1 = hoDGInterDomain(14,macrodomain1,macrodomain2)
 interdomain1.stabilityParameters(beta1)
+interdomain1.matrixByPerturbation(1,1e-8)
 
 interdomain2 = hoDGInterDomain(15,macrodomain1,macrodomain3)
-interdomain1.stabilityParameters(beta1)
+interdomain2.stabilityParameters(beta1)
+interdomain2.matrixByPerturbation(1,1e-8)
 
 # creation of Solver
 mysolver = nonLinearMechSolver(1000)
@@ -116,8 +124,8 @@ mysolver.displacementBC("Face",12,0,0.0)
 mysolver.displacementBC("Face",13,0,0.0)
 mysolver.displacementBC("Face",13,1,0.5)
 
-mysolver.periodicBC("Edge",1,3,1,4,0)
-mysolver.periodicBC("Edge",1,3,1,4,1)
+#mysolver.periodicBC("Edge",1,3,1,4,0)
+#mysolver.periodicBC("Edge",1,3,1,4,1)
 
 # archivage
 mysolver.internalPointBuildView("Green-Lagrange_xx",IPField.STRAIN_XX, 1, 1);
diff --git a/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer4Parts.msh b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer4Parts.msh
new file mode 100644
index 0000000000000000000000000000000000000000..4d46e444c44f15307ce80aeed76a4e2f1ddccf87
--- /dev/null
+++ b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayer4Parts.msh
@@ -0,0 +1,429 @@
+$MeshFormat
+4.1 0 8
+$EndMeshFormat
+$Entities
+4 4 3 0
+1 0 0 0 1 1 
+2 5 0 0 1 2 
+3 5 0.3 0 1 3 
+4 0 0.3 0 1 4 
+1 0 0 0 0 0 0 1 1 0 
+2 0 0 0 0 0 0 1 2 0 
+3 0 0 0 0 0 0 1 3 0 
+4 0 0 0 0 0 0 1 4 0 
+11 0 0 0 0 0 0 1 11 0 
+15 0 0 0 0 0 0 1 13 0 
+19 0 0 0 0 0 0 1 12 0 
+$EndEntities
+$PartitionedEntities
+4
+0
+10 13 6 0
+5 0 1 1 2 0 0 0 1 1 
+6 0 2 1 3 5 0 0 1 2 
+7 0 3 1 3 5 0.3 0 1 3 
+8 0 4 1 2 0 0.3 0 1 4 
+9 1 3 2 1 2 1.052631578947368 0.3 0 0 
+10 1 3 2 1 4 2.368421052631577 0.3 0 0 
+11 1 3 2 3 4 3.94736842105263 0.3 0 0 
+12 1 1 2 1 2 1.052631578945627 0 0 0 
+13 1 1 2 1 4 2.368421052627578 0 0 0 
+14 1 1 2 3 4 3.947368421051032 0 0 0 
+5 1 1 1 2 0 0 0 1.052631578945627 0 0 1 1 2 5 -12 
+6 1 1 1 1 1.052631578945627 0 0 2.368421052627578 0 0 1 1 2 12 -13 
+7 1 1 1 4 2.368421052627578 0 0 3.947368421051032 0 0 1 1 2 13 -14 
+8 1 1 1 3 3.947368421051032 0 0 5 0 0 1 1 2 14 -6 
+9 1 2 1 3 5 0 0 5 0.3 0 1 2 2 6 -7 
+10 1 3 1 3 3.94736842105263 0.3 0 5 0.3 0 1 3 2 7 -11 
+11 1 3 1 4 2.368421052631577 0.3 0 3.94736842105263 0.3 0 1 3 2 11 -10 
+12 1 3 1 1 1.052631578947368 0.3 0 2.368421052631577 0.3 0 1 3 2 10 -9 
+13 1 3 1 2 0 0.3 0 1.052631578947368 0.3 0 1 3 2 9 -8 
+14 1 4 1 2 0 0 0 0 0.3 0 1 4 2 8 -5 
+15 2 11 2 1 2 1.052631578945627 0 0 1.052631578947368 0.3 0 0 2 9 -12 
+16 2 11 2 1 4 2.368421052627578 0 0 2.368421052631577 0.3 0 0 2 13 -10 
+17 2 11 2 3 4 3.947368421051032 0 0 3.94736842105263 0.3 0 0 2 11 -14 
+20 2 11 1 2 0 0 0 1.052631578947368 0.3 0 1 11 4 5 13 14 -15 
+21 2 11 1 1 1.052631578945627 0 0 2.368421052631577 0.3 0 1 11 4 6 12 15 16 
+22 2 11 1 4 2.368421052627578 0 0 3.94736842105263 0.3 0 1 11 4 7 11 -16 -17 
+23 2 11 1 3 3.947368421051032 0 0 5 0.3 0 1 11 4 8 9 10 17 
+24 2 15 1 3 5 0 0 6 0.3 0 1 13 1 9 
+25 2 19 1 2 -1 0 0 0 0.3 0 1 12 1 14 
+$EndPartitionedEntities
+$Nodes
+29 129 1 129
+0 5 0 1
+1
+0 0 0
+0 6 0 1
+2
+5 0 0
+0 7 0 1
+3
+5 0.3 0
+0 8 0 1
+4
+0 0.3 0
+0 9 0 1
+57
+1.052631578947368 0.3 0
+0 10 0 1
+52
+2.368421052631577 0.3 0
+0 11 0 1
+46
+3.94736842105263 0.3 0
+0 12 0 1
+8
+1.052631578945627 0 0
+0 13 0 1
+13
+2.368421052627578 0 0
+0 14 0 1
+19
+3.947368421051032 0 0
+1 5 0 7
+5
+23
+6
+24
+7
+25
+26
+0.2631578947366048 0 0
+0.1315789473683247 0 0
+0.5263157894732602 0 0
+0.3947368421049207 0 0
+0.7894736842095533 0 0
+0.6578947368414817 0 0
+0.9210526315776059 0 0
+1 6 0 9
+9
+27
+10
+28
+11
+29
+12
+30
+31
+1.3157894736817 0 0
+1.184210526313661 0 0
+1.578947368417774 0 0
+1.447368421049804 0 0
+1.842105263153847 0 0
+1.710526315785808 0 0
+2.105263157890336 0 0
+1.973684210522066 0 0
+2.236842105258925 0 0
+1 7 0 11
+14
+32
+15
+33
+16
+34
+17
+35
+18
+36
+37
+2.631578947364821 0 0
+2.49999999999573 0 0
+2.894736842102063 0 0
+2.763157894733419 0 0
+3.157894736839305 0 0
+3.026315789470684 0 0
+3.421052631576547 0 0
+3.289473684207914 0 0
+3.684210526313789 0 0
+3.552631578945193 0 0
+3.815789473682342 0 0
+1 8 0 7
+20
+38
+21
+39
+22
+40
+41
+4.210526315788274 0 0
+4.07894736841972 0 0
+4.473684210525516 0 0
+4.342105263156888 0 0
+4.736842105262758 0 0
+4.605263157893852 0 0
+4.868421052631485 0 0
+1 9 0 1
+42
+5 0.1499999999996522 0
+1 10 0 7
+43
+61
+44
+62
+45
+63
+64
+4.736842105263158 0.3 0
+4.868421052631579 0.3 0
+4.473684210526315 0.3 0
+4.605263157894695 0.3 0
+4.210526315789473 0.3 0
+4.342105263157816 0.3 0
+4.078947368421024 0.3 0
+1 11 0 11
+47
+65
+48
+66
+49
+67
+50
+68
+51
+69
+70
+3.684210526315787 0.3 0
+3.81578947368423 0.3 0
+3.421052631578945 0.3 0
+3.552631578947585 0.3 0
+3.157894736842103 0.3 0
+3.28947368421053 0.3 0
+2.894736842105261 0.3 0
+3.026315789473684 0.3 0
+2.631578947368419 0.3 0
+2.763157894736886 0.3 0
+2.500000000000441 0.3 0
+1 12 0 9
+53
+71
+54
+72
+55
+73
+56
+74
+75
+2.105263157894735 0.3 0
+2.236842105263046 0.3 0
+1.842105263157894 0.3 0
+1.973684210526332 0.3 0
+1.578947368421052 0.3 0
+1.710526315789394 0.3 0
+1.31578947368421 0.3 0
+1.447368421052609 0.3 0
+1.184210526315798 0.3 0
+1 13 0 7
+58
+76
+59
+77
+60
+78
+79
+0.7894736842105257 0.3 0
+0.9210526315790037 0.3 0
+0.5263157894736841 0.3 0
+0.6578947368419064 0.3 0
+0.2631578947368425 0.3 0
+0.3947368421052024 0.3 0
+0.1315789473684728 0.3 0
+1 14 0 1
+80
+0 0.1500000000002887 0
+1 15 0 1
+87
+1.052631578946497 0.15 0
+1 16 0 1
+97
+2.368421052629578 0.15 0
+1 17 0 1
+109
+3.947368421051831 0.15 0
+2 20 0 7
+81
+82
+83
+84
+85
+86
+88
+0.2631578947367236 0.15 0
+0.1315789473683987 0.1500000000001444 0
+0.5263157894734721 0.15 0
+0.3947368421050615 0.15 0
+0.7894736842100395 0.15 0
+0.6578947368416941 0.15 0
+0.9210526315783047 0.15 0
+2 21 0 9
+89
+90
+91
+92
+93
+94
+95
+96
+98
+1.315789473682955 0.15 0
+1.18421052631473 0.15 0
+1.578947368419413 0.15 0
+1.447368421051206 0.15 0
+1.842105263155871 0.15 0
+1.710526315787601 0.15 0
+2.105263157892536 0.15 0
+1.973684210524199 0.15 0
+2.236842105260985 0.15 0
+2 22 0 11
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+110
+2.63157894736662 0.15 0
+2.499999999998085 0.15 0
+2.894736842103662 0.15 0
+2.763157894735152 0.15 0
+3.157894736840704 0.15 0
+3.026315789472184 0.15 0
+3.421052631577746 0.15 0
+3.289473684209222 0.15 0
+3.684210526314788 0.15 0
+3.552631578946389 0.15 0
+3.815789473683286 0.15 0
+2 23 0 7
+111
+112
+113
+114
+115
+116
+117
+4.210526315788873 0.15 0
+4.078947368420373 0.15 0
+4.473684210525915 0.15 0
+4.342105263157352 0.15 0
+4.736842105262958 0.15 0
+4.605263157894274 0.15 0
+4.868421052631531 0.1499999999998261 0
+2 24 0 6
+119
+118
+122
+120
+121
+123
+6 0.3 0
+6 0 0
+5.499999999996719 0.3 0
+6 0.1499999999996522 0
+5.499999999996719 0 0
+5.499999999996719 0.1499999999996522 0
+2 25 0 6
+125
+124
+128
+126
+127
+129
+-1 0 0
+-1 0.3 0
+-0.4999999999986718 0 0
+-1 0.1500000000002887 0
+-0.4999999999986718 0.3 0
+-0.4999999999986717 0.1500000000002887 0
+$EndNodes
+$Elements
+20 65 1 65
+0 5 15 1
+1 1 
+0 6 15 1
+2 2 
+0 7 15 1
+3 3 
+0 8 15 1
+4 4 
+1 5 8 4
+5 1 5 23 
+6 5 6 24 
+7 6 7 25 
+8 7 8 26 
+1 6 8 5
+9 8 9 27 
+10 9 10 28 
+11 10 11 29 
+12 11 12 30 
+13 12 13 31 
+1 7 8 6
+14 13 14 32 
+15 14 15 33 
+16 15 16 34 
+17 16 17 35 
+18 17 18 36 
+19 18 19 37 
+1 8 8 4
+20 19 20 38 
+21 20 21 39 
+22 21 22 40 
+23 22 2 41 
+1 9 8 1
+24 2 3 42 
+1 10 8 4
+25 3 43 61 
+26 43 44 62 
+27 44 45 63 
+28 45 46 64 
+1 11 8 6
+29 46 47 65 
+30 47 48 66 
+31 48 49 67 
+32 49 50 68 
+33 50 51 69 
+34 51 52 70 
+1 12 8 5
+35 52 53 71 
+36 53 54 72 
+37 54 55 73 
+38 55 56 74 
+39 56 57 75 
+1 13 8 4
+40 57 58 76 
+41 58 59 77 
+42 59 60 78 
+43 60 4 79 
+1 14 8 1
+44 4 1 80 
+2 20 10 4
+45 1 5 60 4 23 81 79 80 82 
+46 5 6 59 60 24 83 78 81 84 
+47 6 7 58 59 25 85 77 83 86 
+48 7 8 57 58 26 87 76 85 88 
+2 21 10 5
+49 8 9 56 57 27 89 75 87 90 
+50 9 10 55 56 28 91 74 89 92 
+51 10 11 54 55 29 93 73 91 94 
+52 11 12 53 54 30 95 72 93 96 
+53 12 13 52 53 31 97 71 95 98 
+2 22 10 6
+54 13 14 51 52 32 99 70 97 100 
+55 14 15 50 51 33 101 69 99 102 
+56 15 16 49 50 34 103 68 101 104 
+57 16 17 48 49 35 105 67 103 106 
+58 17 18 47 48 36 107 66 105 108 
+59 18 19 46 47 37 109 65 107 110 
+2 23 10 4
+60 19 20 45 46 38 111 64 109 112 
+61 20 21 44 45 39 113 63 111 114 
+62 21 22 43 44 40 115 62 113 116 
+63 22 2 3 43 41 42 61 115 117 
+2 24 10 1
+64 2 3 119 118 42 122 120 121 123 
+2 25 10 1
+65 4 1 125 124 80 128 126 127 129 
+$EndElements
diff --git a/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayerPert.py b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayerPert.py
new file mode 100644
index 0000000000000000000000000000000000000000..64faff8a0608097b663e6dafb321d453d9757187
--- /dev/null
+++ b/dG3D/benchmarks/multiscale_2order_shearlayer/shearlayerPert.py
@@ -0,0 +1,153 @@
+#coding-Utf-8-*-
+from gmshpy import *
+from dG3Dpy import*
+
+#script to launch PBC problem with a python script
+
+#DEFINE MICRO PROBLEM
+
+# micro-material law
+lawnum = 11 # unique number of law
+K = 76.E3 	# Bulk mudulus
+mu =26.E3	  # Shear mudulus
+rho = 2700. # Bulk mass
+sy0 = 200
+h = 0.5*sy0
+E = 9.*K*mu/(3.*K+mu)
+nu= (3.*K -2.*mu)/2./(3.*K+mu)
+
+# micro-geometry
+micromeshfile="micro.msh" # name of mesh file
+
+# creation of material law
+law1 = dG3DLinearElasticMaterialLaw(lawnum,rho,E,nu)
+
+# creation of  micro part Domain
+nfield = 11 # number of the field (physical number of entity)
+dim =2
+myfield1 = dG3DDomain(10,nfield,0,lawnum,0,dim)
+
+microBC = nonLinearPeriodicBC(10,2)
+microBC.setOrder(2)
+microBC.setBCPhysical(1,2,3,4)
+
+# periodiodic BC
+method = 0 # Periodic mesh = 0 Langrange interpolation = 1 Cubic spline interpolation =2
+degree = 5 
+addvertex = 0
+microBC.setPeriodicBCOptions(method, degree,bool(addvertex))
+
+# DEFINE MACROPROBLEM
+matnum = 1;
+macromat = hoDGMultiscaleMaterialLaw(matnum, 1000)
+macromat.addViewMicroSolver(45,0)
+macromat.addViewMicroSolver(55,0)
+
+baseSolver1 = macromat.getMicroSolver()
+baseSolver1.loadModel(micromeshfile);
+baseSolver1.addDomain(myfield1)
+baseSolver1.addMaterialLaw(law1);
+baseSolver1.addMicroBC(microBC)
+
+#baseSolver1.snlData(1,1,1e-6,1e-10)
+#baseSolver1.setSystemType(1)
+#baseSolver1.Solver(2)
+#baseSolver1.Scheme(1)
+
+baseSolver1.displacementBC("Face",11,2,0.) # fix out-of-plan displacement 
+
+macromeshfile="shearlayer4Parts.msh" # name of mesh file
+
+# solver
+sol = 2  # Gmm=0 (default) Taucs=1 PETsc=2
+soltype =1 # StaticLinear=0 (default) StaticNonLinear=1
+nstep = 1  # number of step (used only if soltype=1)
+ftime =1.   # Final time (used only if soltype=1)
+tol=1.e-6  # relative tolerance for NR scheme (used only if soltype=1)
+nstepArch=1 # Number of step between 2 archiving (used only if soltype=1)
+
+
+# creation of  macro part Domain
+
+dim =2
+beta1 = 150;
+fdg=1
+
+nfield1 = 11
+macrodomain1 = hoDGDomain(11,nfield1,0,matnum,fdg,dim)
+macrodomain1.stabilityParameters(beta1)
+macrodomain1.matrixByPerturbation(1,1,1,1e-8)
+
+nfield2 = 12
+macrodomain2 = hoDGDomain(12,nfield2,0,matnum,fdg,dim)
+macrodomain2.stabilityParameters(beta1)
+macrodomain2.matrixByPerturbation(1,1,1,1e-8)
+
+nfield3 = 13
+macrodomain3 = hoDGDomain(13,nfield3,0,matnum,fdg,dim)
+macrodomain3.stabilityParameters(beta1)
+macrodomain3.matrixByPerturbation(1,1,1,1e-8)
+
+interdomain1 = hoDGInterDomain(14,macrodomain1,macrodomain2)
+interdomain1.stabilityParameters(beta1)
+interdomain1.matrixByPerturbation(1,1e-8)
+
+interdomain2 = hoDGInterDomain(15,macrodomain1,macrodomain3)
+interdomain2.stabilityParameters(beta1)
+interdomain2.matrixByPerturbation(1,1e-8)
+
+# creation of Solver
+mysolver = nonLinearMechSolver(1000)
+mysolver.loadModel(macromeshfile)
+mysolver.addDomain(macrodomain1)
+mysolver.addDomain(macrodomain2)
+mysolver.addDomain(macrodomain3)
+mysolver.addDomain(interdomain1)
+mysolver.addDomain(interdomain2)
+mysolver.addMaterialLaw(macromat)
+mysolver.setMultiscaleFlag(bool(1))
+mysolver.Scheme(soltype)
+mysolver.Solver(sol)
+mysolver.snlData(nstep,ftime,tol)
+
+
+# boundary condition
+mysolver.displacementBC("Face",11,2,0.0)
+mysolver.displacementBC("Face",12,2,0.0)
+mysolver.displacementBC("Face",13,2,0.0)
+
+mysolver.displacementBC("Face",12,1,0.0)
+mysolver.displacementBC("Face",12,0,0.0)
+mysolver.displacementBC("Face",13,0,0.0)
+mysolver.displacementBC("Face",13,1,0.5)
+
+#mysolver.periodicBC("Edge",1,3,1,4,0)
+#mysolver.periodicBC("Edge",1,3,1,4,1)
+
+# archivage
+mysolver.internalPointBuildView("Green-Lagrange_xx",IPField.STRAIN_XX, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_yy",IPField.STRAIN_YY, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_zz",IPField.STRAIN_ZZ, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_xy",IPField.STRAIN_XY, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_yz",IPField.STRAIN_YZ, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange_xz",IPField.STRAIN_XZ, 1, 1);
+mysolver.internalPointBuildView("sig_xx",IPField.SIG_XX, 1, 1);
+mysolver.internalPointBuildView("sig_yy",IPField.SIG_YY, 1, 1);
+mysolver.internalPointBuildView("sig_zz",IPField.SIG_ZZ, 1, 1);
+mysolver.internalPointBuildView("sig_xy",IPField.SIG_XY, 1, 1);
+mysolver.internalPointBuildView("sig_yz",IPField.SIG_YZ, 1, 1);
+mysolver.internalPointBuildView("sig_xz",IPField.SIG_XZ, 1, 1);
+mysolver.internalPointBuildView("sig_VM",IPField.SVM, 1, 1);
+mysolver.internalPointBuildView("Green-Lagrange equivalent strain",IPField.GL_EQUIVALENT_STRAIN, 1, 1);
+mysolver.internalPointBuildView("Equivalent plastic strain",IPField.PLASTICSTRAIN, 1, 1);
+
+mysolver.archivingForceOnPhysicalGroup("Edge",2,0)
+mysolver.archivingForceOnPhysicalGroup("Edge",2,1)
+
+# solve
+mysolver.solve()
+
+#test check
+check = TestCheck()
+check.equal(9.673969e+02,mysolver.getArchivedForceOnPhysicalGroup("Edge",2,1),1.e-5)
+
diff --git a/dG3D/benchmarks/rveMicromorphisms_planeStress/run.py b/dG3D/benchmarks/rveMicromorphisms_planeStress/run.py
index 2de0be92c348b5779a0d5f402fcbd412036f6cd3..924e338bb19332440ebd40aa7c0039cd8b18bba5 100755
--- a/dG3D/benchmarks/rveMicromorphisms_planeStress/run.py
+++ b/dG3D/benchmarks/rveMicromorphisms_planeStress/run.py
@@ -179,7 +179,9 @@ mysolver.solve()
 # test check
 check = TestCheck()
 import linecache
-homoStress = linecache.getline('E_0_GP_0_stress.csv',-1)
+total_line_number = sum(1 for line in open('E_0_GP_0_stress.csv'))
+homoStress = linecache.getline('E_0_GP_0_stress.csv',total_line_number)
+print(homoStress)
 val = float(homoStress.split(';')[1])
 check.equal(1.030085e+02,val,1.e-4)
 
diff --git a/dG3D/benchmarks/rveMicromorphisms_planeStress_barF/run.py b/dG3D/benchmarks/rveMicromorphisms_planeStress_barF/run.py
index 610b5de1eac6e70e371d8c9a56ef880b7c18d7de..fcff52740cfea31c11c8f0046b39257e9600d00b 100755
--- a/dG3D/benchmarks/rveMicromorphisms_planeStress_barF/run.py
+++ b/dG3D/benchmarks/rveMicromorphisms_planeStress_barF/run.py
@@ -179,8 +179,10 @@ mysolver.solve()
 # test check
 check = TestCheck()
 import linecache
-homoStress = linecache.getline('E_0_GP_0_stress.csv',-1)
+total_line_number = sum(1 for line in open('E_0_GP_0_stress.csv'))
+homoStress = linecache.getline('E_0_GP_0_stress.csv',total_line_number)
+print(homoStress)
 val = float(homoStress.split(';')[1])
-check.equal(1.030085e+02,val,1.e-4)
+check.equal(-0.1285178500350496,val,1.e-4)
 
 
diff --git a/dG3D/benchmarks/shearTest_PBC/run.py b/dG3D/benchmarks/shearTest_PBC/run.py
index fd83b63bdedad90115c86d3eccffb9844a68547d..b37cdaf545ff863d568c5fbf5aab9c2ecaf14cf5 100644
--- a/dG3D/benchmarks/shearTest_PBC/run.py
+++ b/dG3D/benchmarks/shearTest_PBC/run.py
@@ -97,4 +97,4 @@ check = TestCheck()
 import linecache
 homoStress = linecache.getline('Average_P_XY.csv',2)
 val = float(homoStress.split(';')[1])
-check.equal(1.030085e+02,val,1.e-4)
+check.equal(1.015205e+02,val,1.e-4)
diff --git a/dG3D/benchmarks/shiftMultiSystem/fullPlateHoleRes.py b/dG3D/benchmarks/shiftMultiSystem/fullPlateHoleRes.py
index fa63c60b84ac16533cf8b2c38c973e314c8b8db3..ff0b661297a4d4738fdee0add8c259124e14d3c0 100644
--- a/dG3D/benchmarks/shiftMultiSystem/fullPlateHoleRes.py
+++ b/dG3D/benchmarks/shiftMultiSystem/fullPlateHoleRes.py
@@ -268,7 +268,7 @@ check.equal(6.859167e+03,mysolver.getArchivedForceOnPhysicalGroup("Face", 102, 0
 
 data21 = csv.reader(open('force102comp0_part2.csv'), delimiter=';')
 force2 = list(data21)
-checkEqual(1235.17813686061,float(force2[-1][1]),1e-5)
+check.equal(1236.4221149205,float(force2[-1][1]),1e-5)
 
 
 #mysolver.disableResetRestart() #only battery: the second solve mimics a restart
diff --git a/dG3D/benchmarks/shiftMultiSystem/run.py b/dG3D/benchmarks/shiftMultiSystem/run.py
index 989bc9dc50df7b74e4e95b0916fb6558e8e3d00a..c8cf7fda17837c54821f415cd9fd36057b187e2a 100644
--- a/dG3D/benchmarks/shiftMultiSystem/run.py
+++ b/dG3D/benchmarks/shiftMultiSystem/run.py
@@ -22,5 +22,5 @@ else:
 
 data21 = csv.reader(open('force102comp0_part2.csv'), delimiter=';')
 force2 = list(data21)
-checkEqual(1235.17813686061,float(force2[-1][1]),1e-5)
+checkEqual(1236.422114920,float(force2[-1][1]),1e-5)
 
diff --git a/dG3D/benchmarks/smpPhenomenological_Mech/SMP_mech.py b/dG3D/benchmarks/smpPhenomenological_Mech/SMP_mech.py
index cb9d68478a3d289df90815122a302a890cd9e3f2..aed44c17c85d90df5ad4385a92b4737493c31bba 100644
--- a/dG3D/benchmarks/smpPhenomenological_Mech/SMP_mech.py
+++ b/dG3D/benchmarks/smpPhenomenological_Mech/SMP_mech.py
@@ -431,7 +431,7 @@ mysolver.solve()
 
 # ===Test==========================================================================================
 check= TestCheck()		
-check.equal(-9.734636e-05,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1e-5)
+check.equal(-9.276832e-05,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1e-5)
 
 
 
@@ -606,7 +606,7 @@ mysolver.solve()
 
 # ===Test==========================================================================================
 check2 = TestCheck()
-check2.equal(-1.160248e-05,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1e-1)	
+check2.equal(-2.015999e-06,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1e-1)	
 check2.equal(2.359752e-05,mysolver.getArchivedNodalValue(7,2,mysolver.displacement),1e-1)	
 
 
diff --git a/dG3D/benchmarks/smpPhenomenological_Thermo/SMP_thermo.py b/dG3D/benchmarks/smpPhenomenological_Thermo/SMP_thermo.py
index 7a0d39d617b93bb890893ef655d240f75ee03c63..8b3db8ab7abdd0b4bec2f3b4ff2d191e9a6e7de1 100644
--- a/dG3D/benchmarks/smpPhenomenological_Thermo/SMP_thermo.py
+++ b/dG3D/benchmarks/smpPhenomenological_Thermo/SMP_thermo.py
@@ -425,7 +425,7 @@ mysolver.solve()
 
 
 check = TestCheck()
-check.equal(-1.563061e+02,mysolver.getArchivedForceOnPhysicalGroup("Face", 5678, 3),1.e-6)
-check.equal(3.467833e+02,mysolver.getArchivedNodalValue(1,3,mysolver.displacement),1.e-6)
-check.equal(2.053687e-05,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1.e-6)
+check.equal(-1.563127e+02,mysolver.getArchivedForceOnPhysicalGroup("Face", 5678, 3),1.e-6)
+check.equal(3.467839e+02,mysolver.getArchivedNodalValue(1,3,mysolver.displacement),1.e-6)
+check.equal(2.055143e-05,mysolver.getArchivedNodalValue(7,0,mysolver.displacement),1.e-6)
 
diff --git a/dG3D/src/dG3DDomain.cpp b/dG3D/src/dG3DDomain.cpp
index 6578fd5733a19c1edfa174ff41c39e94f25a0c5a..769042e90a7d772660e392dcea23738b15d2a1f4 100644
--- a/dG3D/src/dG3DDomain.cpp
+++ b/dG3D/src/dG3DDomain.cpp
@@ -1894,7 +1894,7 @@ void dG3DDomain::computeStrain(MElement *e, const int npts_bulk, IntPt *GP,
             for (int j = 0; j < npts_bulk; j++) {
                 IPStateBase *ips = (*vips)[j];
                 dG3DIPVariableBase *ipv = static_cast<dG3DIPVariableBase *>(ips->getState(ws));
-                double J = ipv->getJ(_dim);
+                double J = ipv->getJ(_dim); // we assume the domain is in the Oxy plane;
                 ipv->getRefToLocalJ() = J;
                 double weight = GP[j].weight;
                 barJ += J * weight;
@@ -1910,7 +1910,9 @@ void dG3DDomain::computeStrain(MElement *e, const int npts_bulk, IntPt *GP,
                 for(int k=0; k<_dim; k++)
                   for(int l=0; l<_dim; l++)
                     barF(k,l) *= pow(barJ / localJ, 1. / ((double)(_dim)));
-            }
+		if (STensorOperation::isnan(barF))
+			Msg::Error("The domain should be in the Oxy plane");
+	    }
         }
     }
   /**
@@ -2582,10 +2584,10 @@ void dG3DDomain::computeStrain(AllIPState *aips,MInterfaceElement *ie, IntPt *GP
                 dG3DIPVariableBase *ipvm = static_cast<dG3DIPVariableBase *>(ipsm->getState(ws));
                 dG3DIPVariableBase *ipvp = static_cast<dG3DIPVariableBase *>(ipsp->getState(ws));
 
-                double Jm = ipvm->getJ(_dim);
+                double Jm = ipvm->getJ(_dim); // we assume the domain is in the Oxy plane
                 ipvm->getRefToLocalJ() = Jm;
                 barJm += Jm * weight;
-                double Jp = ipvp->getJ(_dim);
+                double Jp = ipvp->getJ(_dim); // we assume the domain is in the Oxy plane
                 ipvp->getRefToLocalJ() = Jp;
                 barJp += Jp * weight;
             }
diff --git a/dG3D/src/dG3DMaterialLaw.cpp b/dG3D/src/dG3DMaterialLaw.cpp
index e1265c3e8c6e3efc17c579b29a65b6242a00e3a7..f98f005a6b2871e551d72cc3db771cc400b61e28 100644
--- a/dG3D/src/dG3DMaterialLaw.cpp
+++ b/dG3D/src/dG3DMaterialLaw.cpp
@@ -88,6 +88,91 @@ void dG3DMaterialLaw::fillElasticStiffness(double E, double nu, STensor43 &K_) c
   K_(2,0,0,2) = mu;
   K_(2,1,1,2) = mu;
 }
+void dG3DMaterialLaw::fillElasticStiffness(double Ex,double Ey,double Ez,double Vxy,double Vxz,double Vyz,
+                                           double MUxy,double MUxz,double MUyz,double alpha,double beta,double gamma,
+                                           STensor43 &K_) const
+{
+  const double Vyx= Vxy*Ey/Ex  ; 
+  const double Vzx= Vxz*Ez/Ex  ; 
+  const double Vzy= Vyz*Ez/Ey  ;
+  const double D=( 1-Vxy*Vyx-Vzy*Vyz-Vxz*Vzx-2*Vxy*Vyz*Vzx ) / ( Ex*Ey*Ez );
+
+  STensor43 ElasticityTensor(0.); 
+  ElasticityTensor(0,0,0,0)=( 1-Vyz*Vzy ) / (Ey*Ez*D );
+  ElasticityTensor(1,1,1,1)=( 1-Vxz*Vzx ) / (Ex*Ez*D );
+  ElasticityTensor(2,2,2,2)=( 1-Vyx*Vxy ) / (Ey*Ex*D );
+
+  ElasticityTensor(0,0,1,1)=( Vyx+Vzx*Vyz ) / (Ey*Ez*D );
+  ElasticityTensor(0,0,2,2)=( Vzx+Vyx*Vzy ) / (Ey*Ez*D );
+  ElasticityTensor(1,1,2,2)=( Vzy+Vxy*Vzx ) / (Ex*Ez*D );
+
+  ElasticityTensor(1,1,0,0)=( Vxy+Vzy*Vxz ) / (Ex*Ez*D );
+  ElasticityTensor(2,2,0,0)=( Vxz+Vxy*Vyz ) / (Ey*Ex*D );
+  ElasticityTensor(2,2,1,1)=( Vyz+Vxz*Vyx ) / (Ey*Ex*D );
+
+  ElasticityTensor(1,2,1,2)=MUyz;ElasticityTensor(1,2,2,1)=MUyz;
+  ElasticityTensor(2,1,2,1)=MUyz;ElasticityTensor(2,1,1,2)=MUyz;
+
+  ElasticityTensor(0,1,0,1)=MUxy;ElasticityTensor(0,1,1,0)=MUxy;
+  ElasticityTensor(1,0,1,0)=MUxy;ElasticityTensor(1,0,0,1)=MUxy;
+
+  ElasticityTensor(0,2,0,2)=MUxz;ElasticityTensor(0,2,2,0)=MUxz;
+  ElasticityTensor(2,0,2,0)=MUxz;ElasticityTensor(2,0,0,2)=MUxz;
+
+
+  double c1,c2,c3,s1,s2,s3;
+  double s1c2, c1c2;
+  double pi(3.14159265359);
+  double fpi = pi/180.;
+
+  c1 = cos(alpha*fpi);
+  s1 = sin(alpha*fpi);
+  c2 = cos(beta*fpi);
+  s2 = sin(beta*fpi);
+  c3 = cos(gamma*fpi);
+  s3 = sin(gamma*fpi);
+
+  s1c2 = s1*c2;
+  c1c2 = c1*c2;
+  
+  STensor3 R;		//3x3 rotation matrix
+  R(0,0) = c3*c1 - s1c2*s3;
+  R(0,1) = c3*s1 + c1c2*s3;
+  R(0,2) = s2*s3;
+  R(1,0) = -s3*c1 - s1c2*c3;
+  R(1,1) = -s3*s1 + c1c2*c3;
+  R(1,2) = s2*c3;
+  R(2,0) = s1*s2;
+  R(2,1) = -c1*s2;
+  R(2,2) = c2;
+
+  for(int i=0;i<3;i++)
+  {
+    for(int j=0;j<3;j++)
+      {
+      for(int k=0;k<3;k++)
+      {
+        for(int l=0;l<3;l++)
+        {
+          K_(i,j,k,l)=0.;
+          for(int m=0;m<3;m++)
+          {
+            for(int n=0;n<3;n++)
+            {
+              for(int o=0;o<3;o++)
+              {
+                for(int p=0;p<3;p++)
+                {
+                  K_(i,j,k,l)+=R(m,i)*R(n,j)*R(o,k)*R(p,l)*ElasticityTensor(m,n,o,p);
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  } 
+}
 
 void dG3DMaterialLaw::initialIPVariable(IPVariable* ipv, bool stiff){
 	IPVariable* ipvTemp = ipv->clone();
@@ -780,6 +865,147 @@ double dG3DLinearElasticMaterialLaw::soundSpeed() const
   return sqrt(E*factornu/_rho);
 };
 
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+dG3DLinearElasticAnisotropicMaterialLaw::dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho, 
+		                                      const double Ex, const double Ey, const double Ez,
+                                                      const double Vxy, const double Vxz, const double Vyz,
+                                                      const double MUxy, const double MUxz, const double MUyz,
+                                                      const double alpha, const double beta, const double gamma):
+	dG3DMaterialLaw(num,rho,false), _elasticLaw(num,Ex,Ey,Ez,Vxy,Vxz,Vyz,MUxy,MUxz,MUyz,alpha,beta,gamma){
+}
+dG3DLinearElasticAnisotropicMaterialLaw::dG3DLinearElasticAnisotropicMaterialLaw(const dG3DLinearElasticAnisotropicMaterialLaw& src):dG3DMaterialLaw(src),
+_elasticLaw(src._elasticLaw){
+};
+
+void dG3DLinearElasticAnisotropicMaterialLaw::initLaws(const std::map<int,materialLaw*> &maplaw){
+	if (!_initialized){
+		elasticStiffness = _elasticLaw.getElasticTensor();
+		_initialized = true;
+	};
+};
+
+void dG3DLinearElasticAnisotropicMaterialLaw::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  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  IPVariable* ipv1 = new  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  IPVariable* ipv2 = new  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void dG3DLinearElasticAnisotropicMaterialLaw::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  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+}
+
+void dG3DLinearElasticAnisotropicMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent)
+{
+  /* get ipvariable */
+  dG3DIPVariableBase* ipvcur = static_cast<dG3DIPVariableBase*>(ipv);;
+  const dG3DIPVariableBase* ipvprev = static_cast<const dG3DIPVariableBase*>(ipvp);;
+  /* strain xyz */
+  const STensor3& F = ipvcur->getConstRefToDeformationGradient();
+  STensor3& P = ipvcur->getRefToFirstPiolaKirchhoffStress();
+	STensor43& H = ipvcur->getRefToTangentModuli();
+	_elasticLaw.constitutive(F,P,stiff,&H);
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+}
+
+double dG3DLinearElasticAnisotropicMaterialLaw::scaleFactor() const{
+	return _elasticLaw.getYoungModulus();
+};
+
+double dG3DLinearElasticAnisotropicMaterialLaw::soundSpeed() const
+{
+	double E = _elasticLaw.getYoungModulus();
+	double nu = _elasticLaw.getPoissonRatio();
+
+  double factornu = (1.-nu)/((1.+nu)*(1.-2.*nu));
+  return sqrt(E*factornu/_rho);
+};
+
+
+dG3DLinearElasticTriclinicMaterialLaw::dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho, 
+		                                      const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+		                                      const double C01, const double C02, const double C03, const double C04, const double C05,
+		                                      const double C12, const double C13, const double C14, const double C15,
+		                                      const double C23, const double C24, const double C25,
+		                                      const double C34, const double C35,
+		                                      const double C45):
+	dG3DMaterialLaw(num,rho,false), _elasticLaw(num,C00,C11,C22,C33,C44,C55,C01,C02,C03,C04,C05,C12,C13,C14,C15,C23,C24,C25,C34,C35,C45){
+}
+dG3DLinearElasticTriclinicMaterialLaw::dG3DLinearElasticTriclinicMaterialLaw(const dG3DLinearElasticTriclinicMaterialLaw& src):dG3DMaterialLaw(src),
+_elasticLaw(src._elasticLaw){
+};
+
+void dG3DLinearElasticTriclinicMaterialLaw::initLaws(const std::map<int,materialLaw*> &maplaw){
+	if (!_initialized){
+		elasticStiffness = _elasticLaw.getElasticTensor();
+		_initialized = true;
+	};
+};
+
+void dG3DLinearElasticTriclinicMaterialLaw::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  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  IPVariable* ipv1 = new  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  IPVariable* ipv2 = new  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+  if(ips != NULL) delete ips;
+  ips = new IP3State(state_,ipvi,ipv1,ipv2);
+}
+
+void dG3DLinearElasticTriclinicMaterialLaw::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  LinearElasticDG3DIPVariable(hasBodyForce,inter);
+}
+
+void dG3DLinearElasticTriclinicMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent)
+{
+  /* get ipvariable */
+  dG3DIPVariableBase* ipvcur = static_cast<dG3DIPVariableBase*>(ipv);;
+  const dG3DIPVariableBase* ipvprev = static_cast<const dG3DIPVariableBase*>(ipvp);;
+  /* strain xyz */
+  const STensor3& F = ipvcur->getConstRefToDeformationGradient();
+  STensor3& P = ipvcur->getRefToFirstPiolaKirchhoffStress();
+	STensor43& H = ipvcur->getRefToTangentModuli();
+	_elasticLaw.constitutive(F,P,stiff,&H);
+  ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
+}
+
+double dG3DLinearElasticTriclinicMaterialLaw::scaleFactor() const{
+	return _elasticLaw.getYoungModulus();
+};
+
+double dG3DLinearElasticTriclinicMaterialLaw::soundSpeed() const
+{
+	double E = _elasticLaw.getYoungModulus();
+	double nu = _elasticLaw.getPoissonRatio();
+
+  double factornu = (1.-nu)/((1.+nu)*(1.-2.*nu));
+  return sqrt(E*factornu/_rho);
+};
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
 //
 dG3DHyperelasticMaterialLaw::dG3DHyperelasticMaterialLaw(const int num, const double rho, const elasticPotential& potential):
 	dG3DMaterialLaw(num,rho,false)
@@ -4330,7 +4556,7 @@ AnisotropicDG3DMaterialLaw::AnisotropicDG3DMaterialLaw(
   double mu = _tilaw.shearModulus();
   double E = 2.*mu*(1.+nu); //Where does this come from? To Have the E corresponding to the Vmax, MUmax
 		            //In the linear & homogeneous & isotropic case ?
-  fillElasticStiffness(E, nu, elasticStiffness); // WTF here? not sure to get it ...
+  fillElasticStiffness(Ex,Ey,Ez,Vxy,Vxz,Vyz,MUxy,MUxz,MUyz,alpha,beta,gamma,elasticStiffness); 
 }
 AnisotropicDG3DMaterialLaw::AnisotropicDG3DMaterialLaw(const AnisotropicDG3DMaterialLaw &source) :
 								     dG3DMaterialLaw(source),
@@ -4340,6 +4566,13 @@ AnisotropicDG3DMaterialLaw::AnisotropicDG3DMaterialLaw(const AnisotropicDG3DMate
 
 }
 
+void AnisotropicDG3DMaterialLaw::initLaws(const std::map<int,materialLaw*> &maplaw){
+	if (!_initialized){
+		elasticStiffness = _tilaw.getElasticityTensor();
+		_initialized = true;
+	};
+};
+
 void AnisotropicDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
 {
   // check interface element
@@ -4353,6 +4586,7 @@ void AnisotropicDG3DMaterialLaw::createIPState(IPStateBase* &ips, bool hasBodyFo
   ips = new IP3State(state_,ipvi,ipv1,ipv2);
 }
 
+
 void AnisotropicDG3DMaterialLaw::createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const
 {
   if(ipv !=NULL) delete ipv;
@@ -4712,7 +4946,6 @@ void ClusterDG3DMaterialLaw::checkInternalState(IPVariable* ipv, const IPVariabl
 };
 
 
-
 void ClusterDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, const bool stiff, const bool checkfrac, const bool dTangent)
 {
   /* get ipvariable */
@@ -4745,10 +4978,28 @@ void ClusterDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, con
   }
 
   // modify current deformation gradient with eigen strain
-  const STensor3& eig = _clusteringData->getEigenStrain(tag,_homogeneous);
+  _eigenMethod = _clusteringData->getEigenMethod();
+  STensor3 Feig(1.);
+  if(_eigenMethod==0)
+  {
+    Feig = _clusteringData->getEigenStrain(tag,_homogeneous);
+  }
+  else if(_eigenMethod==1)
+  {
+    STensor43 Cel,Sel;
+    Cel = this->elasticStiffness;
+    STensorOperation::inverseSTensor43(Cel,Sel);
+    const STensor3& sigEig = _clusteringData->getEigenStress(tag,_homogeneous);
+    STensorOperation::multSTensor43STensor3Add(Sel,sigEig,-1.,Feig);
+  }
+  else
+  {
+    Msg::Error("this not implemented");
+  }
+  
   static STensor3 Fn;
   Fn = ipvcur->getConstRefToDeformationGradient();
-  STensorOperation::multSTensor3(Fn,eig,ipvcur->getRefToDeformationGradient());
+  STensorOperation::multSTensor3(Fn,Feig,ipvcur->getRefToDeformationGradient());  
   itmlaw->second->stress(ipv,ipvp,stiff,checkfrac,dTangent);
   ipvcur->getRefToDeformationGradient() = Fn;
   ipvcur->setRefToDGElasticTangentModuli(this->elasticStiffness);
@@ -4768,7 +5019,7 @@ void ClusterDG3DMaterialLaw::stress(IPVariable* ipv, const IPVariable* ipvp, con
           {
             for (int m=0; m<3; m++)
             {
-              Tangent(i,j,k,l)  += Ttemp(i,j,k,m)*eig(l,m);
+              Tangent(i,j,k,l)  += Ttemp(i,j,k,m)*Feig(l,m);
             }
           }
         }
@@ -4892,17 +5143,25 @@ void TFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsFromFiles(const
   _TFAlaw.loadClusterSummaryAndInteractionTensorsFromFiles(clusterSummaryFileName,interactionTensorsFileName);
 }
 
-void TFADG3DMaterialLaw::loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName, const std::string interactionTensorSTDFileName)
+void TFADG3DMaterialLaw::loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName)
+{
+  _TFAlaw.loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(clusterSummaryFileName,interactionTensorsFileName);
+}
+
+void TFADG3DMaterialLaw::loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName)
 {
-  _TFAlaw.loadClusterStandardDeviationFromFile(clusterSTDFileName,interactionTensorSTDFileName);
+  _TFAlaw.loadClusterStandardDeviationFromFile(clusterSTDFileName);
 }
 
 
 void TFADG3DMaterialLaw::loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName,
                                                                   const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName)
+                                                                  const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                                  const std::string PlasticEqStrainConcentrationPowerFileName)
 {
-  _TFAlaw.loadPlasticEqStrainConcentrationFromFile(PlasticEqStrainConcentrationFileName,PlasticEqStrainConcentrationGeometricFileName,PlasticEqStrainConcentrationHarmonicFileName);
+  _TFAlaw.loadPlasticEqStrainConcentrationFromFile(PlasticEqStrainConcentrationFileName,PlasticEqStrainConcentrationGeometricFileName,
+                                                   PlasticEqStrainConcentrationHarmonicFileName,PlasticEqStrainConcentrationPowerFileName);
 };
 
 void TFADG3DMaterialLaw::loadElasticStrainConcentrationDerivativeFromFile(const std::string ElasticStrainConcentrationDerivative)
@@ -4910,9 +5169,9 @@ void TFADG3DMaterialLaw::loadElasticStrainConcentrationDerivativeFromFile(const
   _TFAlaw.loadElasticStrainConcentrationDerivativeFromFile(ElasticStrainConcentrationDerivative);
 }
 
-void TFADG3DMaterialLaw::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName, const std::string EshelbyinteractionTensorSTDFileName)
+void TFADG3DMaterialLaw::loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName)
 {
-  _TFAlaw.loadEshelbyInteractionTensorsFromFile(EshelbyinteractionTensorsFileName,EshelbyinteractionTensorSTDFileName);
+  _TFAlaw.loadEshelbyInteractionTensorsFromFile(EshelbyinteractionTensorsFileName);
 }
 
 void TFADG3DMaterialLaw::loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName)
@@ -4925,11 +5184,37 @@ void TFADG3DMaterialLaw::loadInteractionTensorsHomogenizedFrameELFromFile(const
   _TFAlaw.loadInteractionTensorsHomogenizedFrameELFromFile(InteractionTensorsHomogenizedFrameELFileName);
 }
 
+void TFADG3DMaterialLaw::loadReferenceStiffnessFromFile(const std::string referenceStiffnessFileName)
+{
+  _TFAlaw.loadReferenceStiffnessFromFile(referenceStiffnessFileName);
+}
+
+void TFADG3DMaterialLaw::loadReferenceStiffnessIsoFromFile(const std::string referenceStiffnessIsoFileName)
+{
+  _TFAlaw.loadReferenceStiffnessIsoFromFile(referenceStiffnessIsoFileName);
+}
+
+void TFADG3DMaterialLaw::loadInteractionTensorIsoFromFile(const std::string interactionTensorsIsoFileName)
+{
+  _TFAlaw.loadInteractionTensorIsoFromFile(interactionTensorsIsoFileName);
+}
+
+void TFADG3DMaterialLaw::loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName)
+{
+  _TFAlaw.loadClusterFiberOrientationFromFile(OrientationDataFileName);
+}
+
+
 void TFADG3DMaterialLaw::setTFAMethod(int TFAMethodNum, int dim, int correction, int solverType,  int tag)
 {
   _TFAlaw.setTFAMethod(TFAMethodNum, dim, correction, solverType, tag);
 }
 
+void TFADG3DMaterialLaw::setClusterIncOrientation()
+{
+  _TFAlaw.setClusterIncOrientation();
+}
+
 
 //
 
diff --git a/dG3D/src/dG3DMaterialLaw.h b/dG3D/src/dG3DMaterialLaw.h
index b111c3cfce2954c762ae2c09f595f231f401628c..68b72d2ec887cf7c073ecd496d458da4cc37653d 100644
--- a/dG3D/src/dG3DMaterialLaw.h
+++ b/dG3D/src/dG3DMaterialLaw.h
@@ -106,6 +106,8 @@ class dG3DMaterialLaw : public materialLaw{
   virtual void stress3DTo2D(IPVariable* ipv, const IPVariable* ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
 
   virtual void fillElasticStiffness(double E, double nu, STensor43 &tangent) const;
+  virtual void fillElasticStiffness(double Ex,double Ey,double Ez,double Vxy,double Vxz,double Vyz,double MUxy,double MUxz,double MUyz,double alpha,double beta,double gamma,
+                                    STensor43 &tangent) const;
   virtual void setElasticStiffness(IPVariable* ipv) const {Msg::Error("define setElasticStiffness if using multiscale simulation");};
   virtual void initialIPVariable(IPVariable* ipv, bool stiff);
   virtual materialLaw* clone() const = 0;
@@ -227,6 +229,87 @@ class dG3DLinearElasticMaterialLaw : public dG3DMaterialLaw{
 #endif //SWIG
 };
 
+class dG3DLinearElasticAnisotropicMaterialLaw : public dG3DMaterialLaw{
+	protected:
+	#ifndef SWIG
+    smallStrainLinearElasticPotential _elasticLaw;
+	#endif
+
+	public:
+		dG3DLinearElasticAnisotropicMaterialLaw(const int num, const double rho, 
+		                                        const double Ex, const double Ey, const double Ez,
+                                                        const double Vxy, const double Vxz, const double Vyz,
+                                                        const double MUxy, const double MUxz, const double MUyz,
+                                                        const double alpha, const double beta, const double gamma);
+		#ifndef SWIG
+		dG3DLinearElasticAnisotropicMaterialLaw(const dG3DLinearElasticAnisotropicMaterialLaw& src);
+		virtual ~dG3DLinearElasticAnisotropicMaterialLaw(){
+		};
+		virtual materialLaw::matname getType() const {return materialLaw::linearElastic;}
+		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;
+  // To allow initialization of bulk ip in case of fracture
+		virtual void createIPVariable(IPVariable* &ipv,bool hasBodyForce,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+		virtual void initLaws(const std::map<int,materialLaw*> &maplaw);
+		virtual void stress(IPVariable* ipv, const IPVariable* ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+		virtual double scaleFactor() const;
+		virtual double soundSpeed() const;
+		virtual materialLaw* clone() const {return new dG3DLinearElasticAnisotropicMaterialLaw(*this);};
+		virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+    virtual bool withEnergyDissipation() const {return false;};
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      Msg::Error("getConstNonLinearSolverMaterialLaw in dG3DLinearElasticAnisotropicMaterialLaw does not exist");
+      return NULL;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      Msg::Error("getNonLinearSolverMaterialLaw in dG3DLinearElasticAnisotropicMaterialLaw does not exist");
+      return NULL;
+    }
+#endif //SWIG
+};
+
+class dG3DLinearElasticTriclinicMaterialLaw : public dG3DMaterialLaw{
+	protected:
+	#ifndef SWIG
+    smallStrainLinearElasticPotential _elasticLaw;
+	#endif
+
+	public:
+		dG3DLinearElasticTriclinicMaterialLaw(const int num, const double rho, 
+		                                      const double C00, const double C11, const double C22, const double C33, const double C44, const double C55,
+		                                      const double C01, const double C02, const double C03, const double C04, const double C05,
+		                                      const double C12, const double C13, const double C14, const double C15,
+		                                      const double C23, const double C24, const double C25,
+		                                      const double C34, const double C35,
+		                                      const double C45);
+		#ifndef SWIG
+		dG3DLinearElasticTriclinicMaterialLaw(const dG3DLinearElasticTriclinicMaterialLaw& src);
+		virtual ~dG3DLinearElasticTriclinicMaterialLaw(){
+		};
+		virtual materialLaw::matname getType() const {return materialLaw::linearElastic;}
+		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;
+  // To allow initialization of bulk ip in case of fracture
+		virtual void createIPVariable(IPVariable* &ipv,bool hasBodyForce,const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
+		virtual void initLaws(const std::map<int,materialLaw*> &maplaw);
+		virtual void stress(IPVariable* ipv, const IPVariable* ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
+		virtual double scaleFactor() const;
+		virtual double soundSpeed() const;
+		virtual materialLaw* clone() const {return new dG3DLinearElasticTriclinicMaterialLaw(*this);};
+		virtual void checkInternalState(IPVariable* ipv, const IPVariable* ipvprev) const{}; // do nothing
+    virtual bool withEnergyDissipation() const {return false;};
+    virtual const materialLaw *getConstNonLinearSolverMaterialLaw() const
+    {
+      Msg::Error("getConstNonLinearSolverMaterialLaw in dG3DLinearElasticTriclinicMaterialLaw does not exist");
+      return NULL;
+    }
+    virtual materialLaw *getNonLinearSolverMaterialLaw()
+    {
+      Msg::Error("getNonLinearSolverMaterialLaw in dG3DLinearElasticTriclinicMaterialLaw does not exist");
+      return NULL;
+    }
+#endif //SWIG
+};
 
 class dG3DHyperelasticMaterialLaw : public dG3DMaterialLaw
 {
@@ -1193,7 +1276,7 @@ class AnisotropicDG3DMaterialLaw : public dG3DMaterialLaw
   virtual materialLaw::matname getType() const {return _tilaw.getType();}
   virtual void createIPState(IPStateBase* &ips, bool hasBodyForce, const bool* state_=NULL,const MElement *ele=NULL, const int nbFF_=0, const IntPt *GP=NULL, const int gpt = 0) const;
   virtual void createIPVariable(IPVariable* &ipv, bool hasBodyForce, const MElement *ele, const int nbFF_, const IntPt *GP, const int gpt) const;
-  virtual void initLaws(const std::map<int,materialLaw*> &maplaw){}
+  virtual void initLaws(const std::map<int,materialLaw*> &maplaw);
   virtual double soundSpeed() const{return _tilaw.soundSpeed();} // or change value ??
   virtual void stress(IPVariable*ipv, const IPVariable*ipvprev, const bool stiff=true, const bool checkfrac=true, const bool dTangent=false);
 	virtual double scaleFactor() const{return _tilaw.scaleFactor();}
@@ -1265,6 +1348,7 @@ class ClusterDG3DMaterialLaw : public dG3DMaterialLaw
   Clustering* _clusteringData;
   std::map<int, dG3DMaterialLaw*> _matlawptr; //give the material law pointer for cluster i
   bool _homogeneous;
+  int _eigenMethod=0; //0: zero-strain BC, 1: zero-stress BC
 
  public:
   ClusterDG3DMaterialLaw(const int num, Clustering* cl, bool homo=true);
@@ -1307,18 +1391,28 @@ class TFADG3DMaterialLaw : public dG3DMaterialLaw
   void setTFAMethod(int TFAMethodNum, int dim, int correction=0, int solverType=0, int tag=1000);
   void loadClusterSummaryAndInteractionTensorsFromFiles(const std::string clusterSummaryFileName,
                                         const std::string interactionTensorsFileName);
-  void loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName, const std::string interactionTensorSTDFileName);
+  void loadClusterSummaryAndInteractionTensorsHomogenizedFrameFromFiles(const std::string clusterSummaryFileName, 
+                                        const std::string interactionTensorsFileName);
+  void loadClusterStandardDeviationFromFile(const std::string clusterSTDFileName);
 
   void loadPlasticEqStrainConcentrationFromFile(const std::string PlasticEqStrainConcentrationFileName,
                                                 const std::string PlasticEqStrainConcentrationGeometricFileName,
-                                                const std::string PlasticEqStrainConcentrationHarmonicFileName);
+                                                const std::string PlasticEqStrainConcentrationHarmonicFileName,
+                                                const std::string PlasticEqStrainConcentrationPowerFileName);
 
   void loadElasticStrainConcentrationDerivativeFromFile(const std::string ElasticStrainConcentrationDerivative);
 
-  void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName, const std::string EshelbyinteractionTensorSTDFileName);
+  void loadEshelbyInteractionTensorsFromFile(const std::string EshelbyinteractionTensorsFileName);
   void loadInteractionTensorsMatrixFrameELFromFile(const std::string InteractionTensorsMatrixFrameELFileName);
   void loadInteractionTensorsHomogenizedFrameELFromFile(const std::string InteractionTensorsHomogenizedFrameELFileName);
-
+  
+  void loadReferenceStiffnessFromFile(const std::string referenceStiffnessFileName);
+  void loadReferenceStiffnessIsoFromFile(const std::string referenceStiffnessIsoFileName);
+  void loadInteractionTensorIsoFromFile(const std::string interactionTensorsIsoFileName);
+  
+  void setClusterIncOrientation();
+  void loadClusterFiberOrientationFromFile(const std::string OrientationDataFileName);
+  
   void addClusterMaterialLaw(int clusterNb, dG3DMaterialLaw* clusterLaw)
   {
     _TFAlaw.addClusterMaterialLaw(clusterNb, clusterLaw->getNonLinearSolverMaterialLaw());
diff --git a/dgshell/CMakeLists.txt b/dgshell/CMakeLists.txt
index 0e804a3886f554661f4b6f48618873ebdf338015..60eedf088c141041f753e51883c31764acff3756 100644
--- a/dgshell/CMakeLists.txt
+++ b/dgshell/CMakeLists.txt
@@ -47,8 +47,8 @@ endif(NOT CM3APPS)
 
 add_subdirectory("src")
 if(NOT CM3APPS)
-include_directories(src ../../gmsh/api ../../gmsh/src/common ../../gmsh/sec/numeric ../../gmsh/src/geo ../../gmsh/src/mesh
-   ../../gmsh/src/solver ../../gmsh/src/post ../../gmsh/src/plugin ../../gmsh/src/graphics ../NonLinearSolver/internalPoints ../NonLinearSolver/nlsolver ../NonLinearSolver ../NonLinearSolver/Interface ../NonLinearSolver/contact ../NonLinearSolver/materialLaw ../NonLinearSolver/Domain ../NonLinearSolver/BoundaryConditions ../NonLinearSolver/nlTerms ../NonLinearSolver/field ../NonLinearSolver/space ../NonLinearSolver/restart ../NonLinearSolver/modelReduction ${GMSH_EXTERNAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/NonLinearSolver/gmsh/rc/common ../../gmsh/contrib/gmm ${CMAKE_CURRENT_BINARY_DIR}/NonLinearSolver ../NonLinearSolver/periodicBC $ENV{NLSMPIINC} )
+include_directories(src ../../gmsh/api ../../gmsh/src/common ../../gmsh/src/numeric ../../gmsh/src/geo ../../gmsh/src/mesh
+   ../../gmsh/src/solver ../../gmsh/src/post ../../gmsh/src/plugin ../../gmsh/src/graphics ../NonLinearSolver/internalPoints ../NonLinearSolver/nlsolver ../NonLinearSolver ../NonLinearSolver/Interface ../NonLinearSolver/contact ../NonLinearSolver/materialLaw ../NonLinearSolver/Domain ../NonLinearSolver/BoundaryConditions ../NonLinearSolver/nlTerms ../NonLinearSolver/field ../NonLinearSolver/space ../NonLinearSolver/restart ../NonLinearSolver/modelReduction ${GMSH_EXTERNAL_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}/NonLinearSolver/gmsh/src/common ../../gmsh/contrib/gmm ${CMAKE_CURRENT_BINARY_DIR}/NonLinearSolver ../NonLinearSolver/periodicBC $ENV{NLSMPIINC} )
 endif(NOT CM3APPS)
 
 file(GLOB HDR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/src *.h)
diff --git a/dgshell/src/dgShellDomain.h b/dgshell/src/dgShellDomain.h
index b56edb89ad39fdef71b6ad29d90f7ac7729f8d65..477945daf14d63c43363ec3031ce824372a9a487 100644
--- a/dgshell/src/dgShellDomain.h
+++ b/dgshell/src/dgShellDomain.h
@@ -49,6 +49,7 @@ class dgLinearShellDomain : public dgPartDomain{
   virtual int getDim() const {return 2;}
   virtual void setDeformationGradientGradient(AllIPState *aips, const STensor33 &GM,const IPStateBase::whichState ws){};    
   virtual void setdFmdFM(AllIPState *aips, std::map<Dof, STensor3> &dUdF,const IPStateBase::whichState ws){};    
+  virtual void setValuesForBodyForce(AllIPState *aips, const IPStateBase::whichState ws){};
   virtual void computeIpv(AllIPState *aips,MElement *e, IPStateBase::whichState ws,
                                   materialLaw *mlaw,fullVector<double> &disp, bool stiff);
   virtual void computeIpv(AllIPState *aips,MInterfaceElement *ie, IntPt *GP,const IPStateBase::whichState ws,