Skip to content
Snippets Groups Projects
Select Git revision
  • 4686d5a591fd2f21385c38c235855606111e06e5
  • master default protected
  • juan_Stoch_DP
  • Tianyu
  • kevinMFH
  • juanMFH
  • juan
  • jrothkegel
  • juanNew
  • ling
  • layers
  • mohamed
  • 1-identification-with-gaussian
  • test_bracnh
14 results

j2plast.c

Blame
  • j2plast.c 66.52 KiB
    #ifndef J2PLAST_C
    #define J2PLAST_C 1
    
    //#ifndef max
    //#define max(a,b) ( ((a) > (b)) ? (a) : (b) )
    //#endif
    
    #include <math.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    
    #include "j2plast.h"
    #include "matrix_operations.h"
    #include "elasticlcc.h"
    
    #ifdef NONLOCALGMSH
    #include "ID.h"
    using namespace MFH;
    #endif
    
    #define DP_MIN 1e-60
    
    
    //ELASTO-PLASTIC CONSTITUTIVE BOX
    int constbox_ep(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0,
    	double hexp, double *dstrn, double *strs_n, double *strs, double* pstrn_n, double* pstrn,
    	double p_n, double *p, double *twomu_iso, double* dtwomu_iso, double** Calgo, double*** dCalgo, double* dpdE, bool residual)
    
    {
    	int i,j,k,it,error;
    	double strseqtr, trstrstr,strseqtrNor0;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G;    //Variables for the correction phase 
    	double kp;
    	double Dp;  
    	double h, tmp1, tmp2;
    	double cp=0.;
    	double tol = 1.e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    	double mu_iso, k_iso;
    	double G3, h3;
            double sq2;
    
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    	k_iso = E/(3.*(1.-(2.*nu)));
    	G3 = G*G*G;
    
            static bool initialized=false;
            // initialize only once!
    	static double **Cel=NULL;
    	static double **NoN=NULL;
    	static double **Idev=NULL;
    	static double **mat1=NULL;
    	static double *strstr=NULL;
    	static double *Str=NULL;              //used to compute the modified normal
    	static double *Ntr=NULL;              //used to compute the modified normal
    	static double *Stau=NULL;
    	static double *dstrs=NULL;
            static double *strstrNor0=NULL;      //used to compute the modified normal
            bool stay=true;
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&strstr,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6);
              mallocvector(&Stau,6);
              mallocvector(&dstrs,6);
              mallocvector(&strstrNor0,6);
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(mat1);
            cleartens2(strstr);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(Stau);
            cleartens2(dstrs);
            cleartens2(strstrNor0);
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial stress
    	contraction42(Cel, dstrn, dstrs);
    
    	addtens2(1., strs_n, 1., dstrs, strstr);
    	strseqtr = vonmises(strstr);
            strseqtrNor0 = vonmises(dstrs);  
    	//normal to the yield surface
            if(!residual)
            {
      	  dev(strstr, Str);
      	  if(strseqtr > 0){
    		addtens2(1.5/strseqtr, Str, 0, Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
    	  }
            }
            else
            {
              dev(dstrs, Str);
              if(strseqtrNor0 > 0){
                    addtens2(1.5/strseqtrNor0, Str, 0, Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
              }
            }
    	//elastic increment
    	Dp=DP_MIN;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
    	h = (3.*G) + dR;
    	kp = strseq + 3.*G*Dp - strseqtr;
    
    	if(kp>=0.){
    		//printf("elastic: !");
    		copyvect(strstr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
          //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           cleartens2(dpdE);
    
    
           //******* By Wu Ling 06/04/2011**********************************************************************************
    
    	}
    	//Plastic correction: return mapping algorithm 
    	else{
    		Dp = fmax(DP_MIN,-kp/h);  //correction must be such that Dp >= DP_MIN
    
    		it=0;
    		res=1.;
    		res0=res;
    		while(res>tol && stay){
    		
    			it++;
    			if(it>20){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);
    				stay=false;
                                    Dp=1.;
    				//return(1);
    			}
    
    			*p=p_n+Dp;
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    			kp = 3.*G*Dp + R + sy0 - strseqtr;
          
    			res = fabs(kp)/G;
    
    			if(it==1||res<res0){
    				res0=res;
    				cp =  - kp/(3.*G+dR);
    				tmp1 = 0.99*(DP_MIN-Dp);
    				if(cp<tmp1) {
    					//printf("new Dp below Dpmin : correction!\n");
    					cp=tmp1;
    				}
    				Dp+=cp;
    			}
    			else{
    				//printf("residual is not decreasing: correction!\n");
    				cp=cp/2.;
    				Dp=Dp-cp;
    				res0=res;
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    		strseq = sy0 + R;
    
    		addtens2(1., strstr,-2.*G*(Dp), Ntr, strs);
    		h=(3.*G) + dR;
    		
    		addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
    
    		h3 = h*h*h;
    		tmp1 = 4.*G*G/h;
    		tmp2 = 4.*G*G*(*p-p_n)/strseqtr;
    
    		addtens4(1.,Cel,(-tmp1+tmp2),NoN, Calgo);
    		addtens4(1.,Calgo,-1.5*tmp2,Idev,Calgo);
    
    		addtens4(1.5,Idev,-1.,NoN,mat1);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k] = (8.*G3*ddR/h3)*NoN[i][j]*Ntr[k] - (16.*G3/(h*strseqtr))*Ntr[i]*mat1[j][k] - mat1[i][j]*8.*G3*Ntr[k]*((1./(h*strseqtr))-(Dp/(strseqtr*strseqtr))) + (16.*G3*Dp/(strseqtr*strseqtr))*Ntr[i]*mat1[j][k];
    				}
    			}
    		}
    
           //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2((2.*G/h), Ntr, 0, Ntr, dpdE);
    
    
           //******* By Wu Ling 06/04/2011**********************************************************************************
    
    
    	} //end case plastic correction
    
    
    	//compute isoJ2 tangent operator and its derivative w.r.t. strain increment
    	if(Dp<DP_MIN){		//that is, Dp=0 	
    		mu_iso=G;
    		for(i=0;i<6;i++){
    			dtwomu_iso[i]=0.;
    		}
    	}
    		
    	else {
    		mu_iso = G*(1.-(3.*G/h));
    		for(i=0;i<6;i++){
    			dtwomu_iso[i] = 12.*pow(G/h,3)*ddR*Ntr[i];
    		}
    	}
      
    	*twomu_iso = 2.*mu_iso;
    
    //      no free as initialized once        
    //     	freematrix(Cel, 6);
    //	freematrix(Idev,6);
    //	freematrix(NoN,6);
    //	freematrix(mat1,6);
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    
    int constbox_ep_res(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0,
    	double hexp, double *dstrn, double *strs_n, double *strs, double* pstrn_n, double* pstrn,
    	double p_n, double *p, double *twomu_iso, double* dtwomu_iso,  double** Calgo, double*** dCalgo, double* dpdE, bool residual)
    
    {
    	int i,j,k,it,error;
    	double strseqtr, strseqtrNor0, trstrstr;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G;    //Variables for the correction phase 
    	double kp;
    	double Dp;  
    	double h, tmp1, tmp2;
    	double cp=0.;
    	double tol = 1.e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    	double mu_iso, k_iso;
    	double G3, h3;
            double sq2;
    
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    	k_iso = E/(3.*(1.-(2.*nu)));
    	G3 = G*G*G;
    
            static bool initialized=false;
            // initialize only once!
    	static double **Cel=NULL;
    	static double **NoN=NULL;
    	static double **Idev=NULL;
    	static double **mat1=NULL;
    	static double *strstr=NULL;
    	static double *strstrNor0=NULL;              //used to compute the modified normal
    	static double *Str=NULL;              //used to compute the modified normal
    	static double *Ntr=NULL;              //used to compute the modified normal
    	static double *Stau=NULL;
    	static double *dstrs=NULL;
            bool stay=true;
    
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&strstr,6);
              mallocvector(&strstrNor0,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6);
              mallocvector(&Stau,6);
              mallocvector(&dstrs,6);
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(mat1);
            cleartens2(strstr);
            cleartens2(strstrNor0);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(Stau);
            cleartens2(dstrs);
    
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial stress
    	contraction42(Cel, dstrn, dstrs);
    
    	addtens2(1.0, strs_n, 1.0, dstrs, strstr);
            strseqtrNor0 = vonmises(dstrs);
    	strseqtr = vonmises(strstr);
      
    	//normal to the yield surface
    	dev(dstrs, Str);
      
    	if(strseqtrNor0 > 0){
    		addtens2(1.5/strseqtrNor0, Str, 0, Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
    	}
    
    
    	//elastic increment
    	Dp=DP_MIN;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
    	h = (3.*G) + dR;
    	kp = strseq + 3.*G*Dp - strseqtr;
    
    	if(kp>=0.){
    		//printf("elastic: !");
    		copyvect(strstr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
          //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           cleartens2(dpdE);
    
    
           //******* By Wu Ling 06/04/2011**********************************************************************************
    
    	}
    	//Plastic correction: return mapping algorithm 
    	else{
    		Dp = fmax(DP_MIN,-kp/h);  //correction must be such that Dp >= DP_MIN
    
    		it=0;
    		res=1.;
    		res0=res;
    		while(res>tol && stay){
    		
    			it++;
    			if(it>20){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);
    				
    				//return(1);
                                    stay=false;
                                    Dp=1.;
    
    			}
    
    			*p=p_n+Dp;
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    			kp = 3.*G*Dp + R + sy0 - strseqtr;
          
    			res = fabs(kp)/G;
    
    			if(it==1||res<res0){
    				res0=res;
    				cp =  - kp/(3.*G+dR);
    				tmp1 = 0.99*(DP_MIN-Dp);
    				if(cp<tmp1) {
    					//printf("new Dp below Dpmin : correction!\n");
    					cp=tmp1;
    				}
    				Dp+=cp;
    			}
    			else{
    				//printf("residual is not decreasing: correction!\n");
    				cp=cp/2.;
    				Dp=Dp-cp;
    				res0=res;
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    		strseq = sy0 + R;
    
    		addtens2(1., strstr,-2.*G*(Dp), Ntr, strs);
    		h=(3.*G) + dR;
    		
    		addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
    
    		h3 = h*h*h;
    		tmp1 = 4.*G*G/h;
    		tmp2 = 4.*G*G*(*p-p_n)/strseqtr;
    
    		addtens4(1.,Cel,(-tmp1+tmp2),NoN, Calgo);
    		addtens4(1.,Calgo,-1.5*tmp2,Idev,Calgo);
    
    		addtens4(1.5,Idev,-1.,NoN,mat1);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k] = (8.*G3*ddR/h3)*NoN[i][j]*Ntr[k] - (16.*G3/(h*strseqtr))*Ntr[i]*mat1[j][k] - mat1[i][j]*8.*G3*Ntr[k]*((1./(h*strseqtr))-(Dp/(strseqtr*strseqtr))) + (16.*G3*Dp/(strseqtr*strseqtr))*Ntr[i]*mat1[j][k];
    				}
    			}
    		}
    
           //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2((2.*G/h), Ntr, 0, Ntr, dpdE);
    
    
           //******* By Wu Ling 06/04/2011**********************************************************************************
    
    
    	} //end case plastic correction
    
    
    	//compute isoJ2 tangent operator and its derivative w.r.t. strain increment
    	if(Dp<DP_MIN){		//that is, Dp=0 	
    		mu_iso=G;
    		for(i=0;i<6;i++){
    			dtwomu_iso[i]=0.;
    		}
    	}
    		
    	else {
    		mu_iso = G*(1.-(3.*G/h));
    		for(i=0;i<6;i++){
    			dtwomu_iso[i] = 12.*pow(G/h,3)*ddR*Ntr[i];
    		}
    	}
      
    	*twomu_iso = 2.*mu_iso;
    
    //      no free as initialized once        
    //     	freematrix(Cel, 6);
    //	freematrix(Idev,6);
    //	freematrix(NoN,6);
    //	freematrix(mat1,6);
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    
    
    
    
    //PRESSURE SENSITIVE ELASTO-PLASTIC CONSTITUTIVE BOX
    int constbox_ep(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0, double alpha_DP, double m_DP, double nup, double hexp, double *dstrn, double *strs_n, double *strs, double* pstrn_n, double* pstrn, double p_n, double *p, double *twomu_iso, double* dtwomu_iso, double *twok_iso, double* dtwok_iso, double** Calgo, double*** dCalgo, double* dpdE, bool residual)
    {
    	int i,j,k,it,error;
    	double strseqtr, trstrstr,strseqtrNor0;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G, kappa_el, dkp_dDp, dDp_dGamma, dkp_dGamma, Deriv_kp;    //Variables for the correction phase 
    	double kp;
    	double beta;
    	double Dp, DGAMMA_MIN, Gamma, phitr, phires;           
    	double h, tmp1, tmp2, ka, NR1_prime_eq, NR2_prime, NR1_eq, NR2;
    	double cGamma=0.;
    	double tol = 1.e-8;    //tolerance on the residual 
    	double res, res0;    		 //residual
    	double mu_iso, k_iso;
    	double G3, h3;
            double sq2;
    	
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    	kappa_el = E/(3.*(1.-(2.*nu)));
            ka = 1./sqrt(1.+2.*pow(nup,2));
    	G3 = G*G*G;
            beta = (9.-18.*nup)/(2.*nup+2.);
            static bool initialized=false;
            // initialize only once
    	static double **Cel=NULL;
    	static double **tmp_tens4=NULL;
    	static double **tmp_tens42=NULL;
    	static double **NoN=NULL;
    	static double **Idev=NULL;
    	static double **Ivol=NULL;
    	static double **mat1=NULL;
    	static double *Identity=NULL;
    	static double *tmp_tens2=NULL;
    	static double *tmp_tens22=NULL;
    	static double *dkp_dE=NULL;
    	static double *dGamma_dEr=NULL;
    	static double *NR1_prime=NULL;
    	static double *NR1=NULL;
    	static double *NR1_dev=NULL;
    	static double *NR1_prime_dev=NULL;
    	static double *strstr=NULL;
    	static double *StrVol=NULL;
    	static double *Str=NULL;              
    	static double *StrVoltmp=NULL;
    	static double *Strtmp=NULL;              
    	static double *Ntr=NULL;              
    	static double *Stau=NULL;
    	static double *dstrs=NULL;
            static double *strstrNor0=NULL;      
            bool stay=true;
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
              mallocmatrix(&tmp_tens4, 6, 6);
              mallocmatrix(&tmp_tens42, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&Ivol,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&Identity,6);
              mallocvector(&tmp_tens2,6);
              mallocvector(&tmp_tens22,6);
              mallocvector(&dkp_dE,6);
              mallocvector(&dGamma_dEr,6);
              mallocvector(&NR1_prime,6);
              mallocvector(&NR1,6);
              mallocvector(&NR1_dev,6);
              mallocvector(&NR1_prime_dev,6);
              mallocvector(&strstr,6);
              mallocvector(&StrVol,6);
              mallocvector(&Str,6);
              mallocvector(&StrVoltmp,6);
              mallocvector(&Strtmp,6);
              mallocvector(&Ntr,6);
              mallocvector(&Stau,6);
              mallocvector(&dstrs,6);
              mallocvector(&strstrNor0,6);
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(tmp_tens4);
            cleartens4(tmp_tens42);
            cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(Ivol);
    	cleartens4(mat1);
            cleartens2(Identity);
            cleartens2(tmp_tens2);
            cleartens2(tmp_tens22);
            cleartens2(dkp_dE);
            cleartens2(dGamma_dEr);
            cleartens2(NR1_prime);
            cleartens2(NR1);
            cleartens2(NR1_dev);
            cleartens2(NR1_prime_dev);
            cleartens2(strstr);
            cleartens2(StrVol);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(Stau);
            cleartens2(dstrs);
            cleartens2(strstrNor0);
    	//deviatoric operator and Identity
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
                Ivol[i][j]=1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
              Identity[i]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial stress
    	contraction42(Cel, dstrn, dstrs);
    
    	addtens2(1., strs_n, 1., dstrs, strstr);
    	strseqtr = vonmises(strstr);
            strseqtrNor0 = vonmises(dstrs);  
    	//normal to the yield surface
            if(!residual)
            {
      	  dev(strstr, Str); 
              addtens2(1./3.*trace(strstr),Identity,0.,Identity,StrVol);
      	  if(strseqtr > 0){
    		addtens2(3., Str, 2.*beta/3., StrVol, Ntr); 
    		produit_tensoriel(Ntr,Ntr,NoN); 
    
    	  }
            }
            else
            {
              dev(dstrs, Str);
              addtens2(1./3.*trace(dstrs),Identity,0.,Identity,StrVol);
              if(strseqtrNor0 > 0){
                    addtens2(3., Str, 2.*beta/3., StrVol, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
              }
            }
    	//elastic increment
    	Dp=DP_MIN;
            DGAMMA_MIN = DP_MIN/100.;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
            phitr = 1./3.*trace(strstr);
    
            kp = pow(strseqtr,alpha_DP)/pow(strseq,alpha_DP)-3.*(pow(m_DP,alpha_DP)-1.)/((m_DP+1.)*strseq)*phitr - (pow(m_DP,alpha_DP)+m_DP)/(m_DP+1.);
    
    
    	if(kp<=0.){
    		//printf("elastic: !");
    		copyvect(strstr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
           //***** By Juan Manuel Calleja 12/2020************************************************************************************
           //compute dpdE  accumulate plastic strain p derivative w.r.t. strain increment
    
           cleartens2(dpdE);
    
    
    
    
           //******* By Juan Manuel Calleja 12/2020**********************************************************************************
    
    	}
    	//Plastic correction: return mapping algorithm 
    	else{
    	  Gamma = DGAMMA_MIN; 
    
    		it=0;
    		res=1.;
    		res0=res;
    		*p=p_n;
    		while(res>tol && stay){
    		  if(it>20)
      		          printf("Return mapping algorithm, p: %.10e, Gamma: %.10e, res: %.10e\n",*p, Gamma, res);
    			it++;
    			if(it>200){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);
    				stay=false;
                                    //Gamma +=0.5 ;
    				//return(1);
    			}
    
    			if(!residual)
    			{
                                    phires = 0.;
    				addtens2(1./(1.+6.*G*(Gamma)),strstr,0.,strs_n,NR1_prime);
    				//dev(NR1_prime, NR1_prime_dev);
    				dev(strstr, NR1_prime_dev);
    				addtens2(1./(1.+6.*G*(Gamma)),NR1_prime_dev,0.,strs_n,NR1_prime_dev);
                                   	NR1_prime_eq = vonmises(NR1_prime);
                                    NR2_prime = phitr/(1.+2.*kappa_el*(Gamma)*beta);
    			}
    			else
    			{
                                    phires = 1./3.*trace(strs_n);
    				addtens2(1./(1.+6.*G*(Gamma)),dstrs,0.,strs_n,NR1_prime);
                                    //dev(NR1_prime, NR1_prime_dev);
                                    dev(dstrs, NR1_prime_dev);
    				addtens2(1./(1.+6.*G*(Gamma)),NR1_prime_dev,0.,strs_n,NR1_prime_dev);
                                   	NR1_prime_eq = vonmises(NR1_prime);
                                    NR2_prime = (phitr-phires)/(1.+2.*kappa_el*(Gamma)*beta);     
    			}
    
    		        Dp = ka*(Gamma)*sqrt(6.*pow(NR1_prime_eq,2.)+4.*pow(beta,2.)/3.*pow(NR2_prime,2.));
    
                            *p = p_n+Dp;
    
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
                            strseq = sy0 + R;
          
    
    
    			if(!residual)
    			{
    				addtens2(1./(1.+6.*G*(Gamma)),strstr,0.,strstr,NR1);
                                    NR1_eq = vonmises(NR1);
    				NR2 = phitr/(1.+2.*kappa_el*(Gamma)*beta);
    			}
    			else
    			{
    				addtens2(1./(1.+6.*G*(Gamma)),dstrs,1.,strs_n,NR1);
                                    NR1_eq = vonmises(NR1);
    				NR2 = (phitr-phires)/(1.+2.*kappa_el*(Gamma)*beta)+phires;
    			}
    
                            tmp1 = pow(NR1_eq,alpha_DP)/pow(strseq,alpha_DP)-3.*NR2*(pow(m_DP,alpha_DP)-1.)/((m_DP+1.)*strseq);
    		        kp = tmp1 - (pow(m_DP,alpha_DP)+m_DP)/(m_DP+1.);
    
    			res = fabs(kp); 
                            
    			
    			if(it==1 || res<res0){
    				res0=res;
    
                                    dkp_dDp = -pow(NR1_eq,alpha_DP)*alpha_DP/pow(strseq,alpha_DP+1.)*dR+3.*(pow(m_DP,alpha_DP)-1.)/((m_DP+1.)*pow(strseq,2.))*dR*NR2;
    
    				if(!residual)
    				{
                                    	tmp1 = 72.*G*pow(strseqtr,2.)/pow(1.+6.*G*(Gamma),3.)+16.*pow(beta,3.)*kappa_el/3.*pow(phitr,2.)/pow(1.+2.*kappa_el*(Gamma)*beta,3.);
    				}
    				else
    				{
                                          	tmp1 = 72.*G*pow(strseqtrNor0,2.)/pow(1.+6.*G*(Gamma),3.)+16.*pow(beta,3.)*kappa_el/3.*pow(phitr-phires,2.)/pow(1.+2.*kappa_el*(Gamma)*beta,3.);
    				}
                                    dDp_dGamma = ka*sqrt(6.*pow(NR1_prime_eq,2.)+4.*pow(beta,2.)/3.*pow(NR2_prime,2.))-ka*(Gamma)/(2.*sqrt(6.*pow(NR1_prime_eq,2.)+4.*pow(beta,2.)/3.*pow(NR2_prime,2.)))*tmp1;
                                    dev(NR1,NR1_dev);
                                    dkp_dGamma = -alpha_DP*pow(NR1_eq/strseq,alpha_DP-1.)*(9.*G*contraction22(Str,NR1_dev))/(strseq*pow(1.+6.*G*(Gamma),2.)*NR1_eq)+3.*(pow(m_DP,alpha_DP)-1.)/((m_DP+1.)*strseq)*(1./3.*trace(StrVol)/pow(1.+2.*kappa_el*(Gamma)*beta,2.)*2.*kappa_el*beta);
    				
    				Deriv_kp = dkp_dDp*dDp_dGamma+dkp_dGamma;
    				cGamma =  - kp/Deriv_kp; // -kp / derivative of kp w.r.t. dp. Newton-Raphson correction.
    
    				tmp1 = 0.99*(DGAMMA_MIN-Gamma);
    				if(cGamma<tmp1) {
    					printf("new Dp below DGAMMA_MIN : correction!\n");
    					cGamma=tmp1;
    				}
    				Gamma+=cGamma;
    			}
    			else{
    			  res0=res;
    			  printf("residual is not decreasing: correction!\n");
     	     	          cGamma=0.5*cGamma;
    			  Gamma-=cGamma; 
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    		strseq = sy0 + R;
    
                    addtens2(1./(1.+6.*G*Gamma),Str, 0., Str, Strtmp);
                    addtens2(1./(1.+(2.*kappa_el*Gamma*beta)),StrVol, 0., StrVol, StrVoltmp);
    
    
                    addtens2(1.,Strtmp, 1., StrVoltmp, strs);
                    if(residual)
    		{
                            addtens2(1.,strs, 1., strs_n, strs);       
    		}
    
    		//addtens2(1.,pstrn_n, 3.*Gamma, NR1_prime, pstrn);
                    addtens2(1.,pstrn_n, 3.*Gamma, NR1_prime_dev, pstrn);
    		addtens2(1.,pstrn, 2.*beta/3.*Gamma*NR2_prime, Identity, pstrn);
    
    
    		
                    //Computation of Calgo
    
                    contraction44(Idev,Cel,tmp_tens4); //ORDER 4
                    addtens4(1./(1.+6.*G*(Gamma)),tmp_tens4,0.,tmp_tens4,tmp_tens4); //ORDER 4
                    contraction42(tmp_tens4,NR1_dev,tmp_tens2); //ORDER 2
                    addtens2(3./2.*alpha_DP * (pow(NR1_eq,alpha_DP-1.)/NR1_eq),tmp_tens2,0.,tmp_tens2,tmp_tens2); //ORDER 2 58.1
                  
                    addtens2(kappa_el/(1.+2.*kappa_el*(Gamma)*beta),Identity,0.,Identity,tmp_tens22);  //ORDER 2 58.2
    
                    addtens2(1/pow(strseq,alpha_DP),tmp_tens2,-3.*(pow(m_DP,alpha_DP)-1.)/((m_DP+1.)*strseq),tmp_tens22, dkp_dE); //ORDER 2 57
    
                    addtens2(-1./Deriv_kp,dkp_dE,0.,dkp_dE,dGamma_dEr); //ORDER 2 56
      
    
    
                    //*************************************************************
                    addtens2(1.+6.*G*(Gamma),dGamma_dEr,-6.*G*(Gamma),dGamma_dEr,tmp_tens2); //ORDER 2
                    addtens2(1./pow(1.+6.*G*(Gamma),2.),tmp_tens2,0.,tmp_tens2,tmp_tens2); //ORDER 2
                    produit_tensoriel(Str,tmp_tens2,tmp_tens4); //ORDER 4
    
                    addtens2(1.+2.*kappa_el*beta*(Gamma),dGamma_dEr,-2.*kappa_el*beta*(Gamma),dGamma_dEr,tmp_tens2); //ORDER 2
                    addtens2(1./pow(1.+2.*kappa_el*beta*(Gamma),2.),tmp_tens2,0.,tmp_tens2,tmp_tens2); //ORDER 2
                    produit_tensoriel(StrVol,tmp_tens2,tmp_tens42); //ORDER 4
     
                    addtens4(2.*G*(Gamma)/(1.+6.*G*(Gamma)),Idev,1.,tmp_tens4,tmp_tens4); //ORDER 4
                    addtens4(3.*kappa_el*(Gamma)/(1.+2.*beta*kappa_el*(Gamma)),Ivol,1.,tmp_tens42,tmp_tens42); //ORDER 4
                    //************************************************************
                    addtens4(1.,Cel,-6.*G,tmp_tens4,Calgo);
                    addtens4(1.,Calgo,-2.*kappa_el*beta,tmp_tens42,Calgo);
    
           //*****************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2(dDp_dGamma,dGamma_dEr, 0., dGamma_dEr, dpdE); //ORDER 2 
           
    
           //*****************************************************************************************
    
    
    	} //end case plastic correction
    
    
    	//compute isoJ2 tangent operator and its derivative w.r.t. strain increment
    	if(Dp<DP_MIN){		//that is, Dp=0 	
    		mu_iso=G;
                    k_iso=kappa_el;
    		for(i=0;i<6;i++){
    			dtwomu_iso[i]=0.;
                            dtwok_iso[i]=0.;
    		}
    	}
    		
    	else {
    		mu_iso = G*(1-(6.*G*Gamma)/(1.+6.*G*Gamma));
                    k_iso= kappa_el*(1.-(2.*beta*kappa_el*Gamma)/(1.+2.*beta*kappa_el*Gamma));
                    addtens2(-6.*pow(G,2.)/pow(1.+6.*G*Gamma,2.),dGamma_dEr,0.,dGamma_dEr,dtwok_iso);
                    addtens2(-2.*beta*pow(kappa_el,2.)/pow(1.+2.*kappa_el*Gamma*beta,2.),dGamma_dEr,0.,dGamma_dEr,dtwok_iso);
    	}
      
    	*twomu_iso = 2.*mu_iso;
            *twok_iso = 2.*k_iso;
    
    //      no free as initialized once        
    //     	freematrix(Cel, 6);
    //	freematrix(Idev,6);
    //	freematrix(NoN,6);
    //	freematrix(mat1,6);
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    
    //****************************************************
    /**********J2 plasticity for large deformation***/
    //******************************************************
    int constbox_ep(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0, double hexp, double *strstr, double *Rstrs_n, double *strs, double* pstrn_n, double* pstrn, double p_n, double *p,  double** Calgo, double*** dCalgo, double* dpdE, bool residual)
    
    {
    	int i,j,k,it,error;
    	double strseqtr,strseqtr0, trstrstr;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G;    //Variables for the correction phase 
    	double kp;
    	double Dp;  
    	double h, tmp1, tmp2;
    	double cp=0.;
    	double tol = 1.e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    	double mu_iso, k_iso;
    	double G3, h3;
            double sq2;
    
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    	k_iso = E/(3.*(1.-(2.*nu)));
    	G3 = G*G*G;
    
            static bool initialized=false;
            // initialize only once!
    	static double **Cel;
    	static double **NoN;
    	static double **Idev;
    	static double **mat1;
    	static double *strstrNor0=NULL;              //used to compute the modified normal
    	static double *Str=NULL;              //used to compute the modified normal
    	static double *Ntr=NULL;              //used to compute the modified normal
    	static double *Stau=NULL;
    	static double *dstrs=NULL;
            bool stay=true;
    
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&strstrNor0,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6);
              mallocvector(&Stau,6);
              mallocvector(&dstrs,6);
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(mat1);
            cleartens2(strstrNor0);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(Stau);
            cleartens2(dstrs);
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	
    	strseqtr = vonmises(strstr);
      
    	//normal to the yield surface
            //dev(strstr, Str);
      
            //normal to the residual stress
            addtens2(1.0, strstr, -1.0, Rstrs_n, strstrNor0);
    	dev(strstrNor0, Str);
    	strseqtr0 = vonmises(strstrNor0);
    
    	if(strseqtr > 0.){
    		addtens2(1.5/strseqtr0, Str, 0., Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
    	}
    
    
    	//elastic increment
    	Dp=DP_MIN;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
    	h = (3.*G) + dR;
    	kp = strseq + 3.*G*Dp - strseqtr;
    
    	if(kp>=0.){
    		//printf("elastic: !");
    		copyvect(strstr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
          //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           cleartens2(dpdE);
    
    
           //******* By Wu Ling 06/04/2011**********************************************************************************
    
    	}
    	//Plastic correction: return mapping algorithm 
    	else{
    		Dp = fmax(DP_MIN,-kp/h);  //correction must be such that Dp >= DP_MIN
    
    		it=0;
    		res=1.;
    		res0=res;
    		while(res>tol && stay){
    		
    			it++;
    			if(it>20){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);
    				stay=false;
                                    Dp=1.;
    
    				//return(1);
    			}
    
    			*p=p_n+Dp;
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    			kp = 3.*G*Dp + R + sy0 - strseqtr;
          
    			res = fabs(kp)/G;
    
    			if(it==1||res<res0){
    				res0=res;
    				cp =  - kp/(3.*G+dR);
    				tmp1 = 0.99*(DP_MIN-Dp);
    				if(cp<tmp1) {
    					//printf("new Dp below Dpmin : correction!\n");
    					cp=tmp1;
    				}
    				Dp+=cp;
    			}
    			else{
    				//printf("residual is not decreasing: correction!\n");
    				cp=cp/2.;
    				Dp=Dp-cp;
    				res0=res;
    			    
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    		strseq = sy0 + R;
    
    		addtens2(1., strstr,-2.*G*(Dp), Ntr, strs);
    		h=(3.*G) + dR;
    		
    		addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
    
    		h3 = h*h*h;
    		tmp1 = 4.*G*G/h;
    		tmp2 = 4.*G*G*(*p-p_n)/strseqtr0;
    
    		addtens4(1.,Cel,(-tmp1+tmp2),NoN, Calgo);
    		addtens4(1.,Calgo,-1.5*tmp2,Idev,Calgo);
    
    		addtens4(1.5,Idev,-1.,NoN,mat1);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k] = (8.*G3*ddR/h3)*NoN[i][j]*Ntr[k] - (16.*G3/(h*strseqtr0))*Ntr[i]*mat1[j][k] - mat1[i][j]*8.*G3*Ntr[k]*((1./(h*strseqtr0))-(Dp/(strseqtr*strseqtr0))) + (16.*G3*Dp/(strseqtr0*strseqtr0))*Ntr[i]*mat1[j][k];
    				}
    			}
    		}
    
           //***** By Wu Ling 06/04/2011************************************************************************************
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2((2.*G/h), Ntr, 0., Ntr, dpdE);
    
    
    	} //end case plastic correction
    
    
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    //end elastoPlastic for large deformation
    
    
    // EVALUATION OF THE HARDENING FUNCTION 
    void j2hard (double p, double sy0, int htype, double hmod1, double hmod2, double hp0, double hexp, double* R, double* dR, double* ddR){
    
    	double tmp;
    
    	//Perfect plasticity
    	if(hmod1 == 0){
    		
    		*R = 0.;
    		*dR = 0.;
    		*ddR = 0.;
    		return;
    
    	}
    
    	switch(htype) {
    	
    	//POWER LAW HARDENING
    	case H_POW:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			if(hexp<1.0){
    				*dR = 1e20;
    				*ddR = -1e20;
    			}
    			else{
    				*dR = hmod1;
    				*ddR = 0.;
    			}		
    		}	
    		else{
    			*R=hmod1*pow(p,hexp);
    			*dR = (*R)*hexp/p;
    			*ddR = (*dR)*(hexp-1.)/p;
    		}
    
    		break;	
    	//POWER LAW HARDENING FOR DRUCKER PRAGER
    	case H_POW_DP:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			if(hexp<1.0){
    				*dR = 1e20;
    				*ddR = -1e20;
    			}
    			else{
    				*dR = hmod1;
    				*ddR = 0.;
    			}		
    		}	
    		else{
    			*R=hmod1*pow(p,hexp);
    			*dR = (*R)*hexp/p;
    			*ddR = (*dR)*(hexp-1.)/p;
    		}
    
    		break;	
    			
    	//EXPONENTIAL HARDENING
    	case H_EXP:
    	
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			*dR = hmod1*hexp;
    			*ddR = -hexp*(*dR);
    		} 
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*(1.-tmp);
    			*dR = hmod1*hexp*tmp;
    			*ddR = -hexp*(*dR);
    		}
    		break;
    
    
    
    	//EXPONENTIAL HARDENING FOR DRUCKER PRAGER
    	case H_EXP_DP:
    	
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			*dR = hmod1*hexp;
    			*ddR = -hexp*(*dR);
    		} 
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*(1.-tmp);
    			*dR = hmod1*hexp*tmp;
    			*ddR = -hexp*(*dR);
    		}
    		break;
    
    	
    	//SWIFT LAW
    	case H_SWIFT:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			*dR = sy0*hmod1*hexp;
    			*ddR = (*dR)*(hexp-1.)*hmod1;
    		}
    		else{
    			tmp = 1.+hmod1*p;
    			*R = sy0*pow(tmp,hexp) - sy0;
    			tmp = hmod1/tmp;
    			*dR = (*R)*hexp*tmp;
    			*ddR = (*dR)*(hexp-1.)*tmp;
    		}
    		break;
    
    	//SWIFT LAW FOR DRUCKER PRAGER
    	case H_SWIFT_DP:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			*dR = sy0*hmod1*hexp;
    			*ddR = (*dR)*(hexp-1.)*hmod1;
    		}
    		else{
    			tmp = 1.+hmod1*p;
    			*R = sy0*pow(tmp,hexp) - sy0;
    			tmp = hmod1/tmp;
    			*dR = (*R)*hexp*tmp;
    			*ddR = (*dR)*(hexp-1.)*tmp;
    		}
    		break;
    
    	//LINEAR-EXPONENTIAL HARDENING
    	case H_LINEXP:
    	
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R = 0;
    			*dR = hmod1 + hmod2*hexp;
    			*ddR = -hmod2*hexp*hexp;
    		}
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*p + hmod2*(1.-tmp);
    			*dR = hmod1 + hmod2*hexp*tmp;
    			*ddR = - hmod2*hexp*hexp*tmp; 
    		}
    		break;
    
    	//LINEAR-EXPONENTIAL HARDENING FOR DRUCKER PRAGER
    	case H_LINEXP_DP:
    	
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R = 0;
    			*dR = hmod1 + hmod2*hexp;
    			*ddR = -hmod2*hexp*hexp;
    		}
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*p + hmod2*(1.-tmp);
    			*dR = hmod1 + hmod2*hexp*tmp;
    			*ddR = - hmod2*hexp*hexp*tmp; 
    		}
    		break;
    
    	//POWER LAW HARDENING EXTRAPOLATED AFTER 16% DEFO TO MIMIC DIGIMAT TO ABAQUS
    	case H_POW_EXTRAPOL:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			if(hmod1<1){
    				*dR = 1e20;
    				*ddR = -1e20;
    			}
    			else{
    				*dR = hmod1;
    				*ddR = 0.;
    			}		
    		}	
    		else if(p<hp0)
                    {
    			*R=hmod1*pow(p,hexp);
    			*dR = (*R)*hexp/p;
    			*ddR = (*dR)*(hexp-1.)/p;
    		}
    		else if(p<10.*hp0)
                    {
    			*R=hmod1*pow(hp0,hexp)+hmod2*(p-hp0);
    			*dR = hmod2;
    			*ddR = 0.;
    		}
    		else
    		{
                           *R=hmod1*pow(hp0,hexp)+hmod2*(10.*hp0-hp0)+hmod2*(p-10.*hp0)/1000.;
                           *dR = hmod2/1000.;
                           *ddR = 0.;
     
    		}
    
    		break;	
    
    	//POWER LAW HARDENING EXTRAPOLATED AFTER 16% DEFO TO MIMIC DIGIMAT TO ABAQUS DRUCKER PRAGER
    	case H_POW_EXTRAPOL_DP:
    		if(p<DP_MIN){
    			//printf("Should not be here: p: %.10e\n",p);
    			*R=0.;
    			if(hmod1<1){
    				*dR = 1e20;
    				*ddR = -1e20;
    			}
    			else{
    				*dR = hmod1;
    				*ddR = 0.;
    			}		
    		}	
    		else if(p<hp0)
                    {
    			*R=hmod1*pow(p,hexp);
    			*dR = (*R)*hexp/p;
    			*ddR = (*dR)*(hexp-1.)/p;
    		}
    		else if(p<10.*hp0)
                    {
    			*R=hmod1*pow(hp0,hexp)+hmod2*(p-hp0);
    			*dR = hmod2;
    			*ddR = 0.;
    		}
    		else
    		{
                           *R=hmod1*pow(hp0,hexp)+hmod2*(10.*hp0-hp0)+hmod2*(p-10.*hp0)/1000.;
                           *dR = hmod2/1000.;
                           *ddR = 0.;
     
    		}
    
    		break;	
          
            //POWER EXPONENTIAL HARDENING
    	case H_POW_EXP:	
    		if(p<DP_MIN){
                            *R = 0.0;
                            *dR = 0.0;
    			if(hmod2<1.0){
    				*ddR = 1e20;
    			}
    			else{
    				*ddR = 0.;
    			}
    		}
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*pow(p,hmod2)*(1.-tmp);
    			*dR = hmod2*hmod1*pow(p,hmod2-1.)*(1.-tmp) + hexp*hmod1*pow(p,hmod2)*tmp;
    			*ddR = hmod2*(hmod2-1.0)*hmod1*pow(p,hmod2-2.)*(1.-tmp) + 2.0*hmod2*hexp*hmod1*pow(p,hmod2-1.0)*tmp - hexp*hexp*hmod1*pow(p,hmod2)*tmp; 
    		}
    		break;
    
            //POWER EXPONENTIAL HARDENING FOR DRUCKER PRAGAER
    	case H_POW_EXP_DP:	
    		if(p<DP_MIN){
                            *R = 0.0;
                            *dR = 0.0;
    			if(hmod2<1.0){
    				*ddR = 1e20;
    			}
    			else{
    				*ddR = 0.;
    			}
    		}
    		else{
    			tmp = exp(-hexp*p);
    			*R = hmod1*pow(p,hmod2)*(1.-tmp);
    			*dR = hmod2*hmod1*pow(p,hmod2-1.)*(1.-tmp) + hexp*hmod1*pow(p,hmod2)*tmp;
    			*ddR = hmod2*(hmod2-1.0)*hmod1*pow(p,hmod2-2.)*(1.-tmp) + 2.0*hmod2*hexp*hmod1*pow(p,hmod2-1.0)*tmp - hexp*hexp*hmod1*pow(p,hmod2)*tmp; 
    		}
    		break;
    	
    	default:
    		printf("Bad choice of hardening law in j2hard: %d\n",htype);
    		break;
    		
    	}
    
    	//printf("p: %lf\t, R: %.10e, \t dR: %.10e \t, ddR: %.10e \n",p, *R,*dRdp,*ddRdp);
     
    }
    
    /***********************************************
     * COMPUTATION OF ALGORITHMIC TANGENT OPERATOR
     * FROM STATE VARIABLES 
     * ********************************************/
    void algoJ2(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0, double hexp, 
    	double* strs, double p, double dp, double** Calgo){
    
    	int i,j;
    	double seqtr;
    	double R,dR,ddR;
    	double mu;
    	static double *N=NULL;
            static double *devstrs=NULL;
            static double **Cel=NULL;
            static double **mat1=NULL;
            static double **mat2=NULL;
            static double ** NoN=NULL;
            static double ** Idev=NULL;
    	double h, tmp1, tmp2;
    
            if(N==NULL)
            {
     	  mallocvector(&devstrs,6);
    	  mallocvector(&N,6);
    	  mallocmatrix(&Cel,6,6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&mat1,6,6);
    	  mallocmatrix(&mat2,6,6);
    	  mallocmatrix(&Idev,6,6);
            }
            cleartens2(devstrs);
    	cleartens2(N);
    	cleartens4(Cel);
    	cleartens4(NoN);
    	cleartens4(mat1);
    	cleartens4(mat2);
    	cleartens4(Idev);
    
            //deviatoric operator
            for(i=0;i<3;i++){
    		for(j=0;j<3;j++){
    		  Idev[i][j]=-1./3.;
    
    		}
    		Idev[i][i]+=1.;
    		Idev[i+3][i+3]=1.;
    	}
      //reset tangent operators to zero
    	mu = E/(2.*(1.+nu));
    
    	compute_Hooke(E,nu,Cel);
    
    	dev(strs,devstrs);
    	
    	j2hard (p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR, &ddR);
    
    	addtens2(1.5/(sy0+R),devstrs,0.,devstrs,N);
    	seqtr = 3*mu*dp + sy0 + R;
    	produit_tensoriel(N,N,NoN);
    	
    	h = 3.*mu + dR;
    	tmp1 = 4.*mu*mu/h;
    	tmp2 = 4.*mu*mu*dp/seqtr;
    
    	addtens4(tmp1,NoN,0,NoN,mat1);
    	addtens4(3.*tmp2/2.,Idev,-tmp2,NoN,mat2);
    
    	addtens4(1.,Cel,-1.,mat1,Calgo);
    	addtens4(1.,Calgo,-1.,mat2,Calgo);
    
    	//free(devstrs);
    	//free(N);
    	//freematrix(Cel,6);
    	//freematrix(mat1,6);
    	//freematrix(mat2,6);
    	//freematrix(Idev,6);
    	//freematrix(NoN,6);
    
    
    }
    
    
    
    //ELASTO-PLASTIC CONSTITUTIVE BOX for second moment mehtod
    int constbox_ep(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0, double hexp, double *DE, double *dstrn, double *strs_n, double eq2strs_n, double *eq2strs, double dstrseq_tr, double *dstrseq_trdDE, double *strs, double* pstrn_n, double* pstrn, double p_n, double *p, FY2nd *FY2){
    
    	int i,j,it;
    	double strseqtr2;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq2, mu_el;    //Variables for the correction phase 
    	double Dp, temp1, temp2;
    	double cp=0.0;
    	double tol = 1e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	mu_el = E/(2.*(1.+nu));  
    	
            static bool initialized=false;
            // initialize only once!
    	static double **Cel=NULL;
    	static double **Idev=NULL;
    	static double *dstrstr=NULL;
    	static double *dstrstr_dev=NULL;
    	static double *Str=NULL;
    	static double *Ntr=NULL;
    	static double *strs_ndev=NULL;
    	static double *mat1=NULL;
            bool stay=true;
    
    	
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&Idev,6,6);
              mallocvector(&dstrstr,6);
              mallocvector(&dstrstr_dev,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6);
              mallocvector(&strs_ndev,6);
              mallocvector(&mat1,6);
              initialized = true;
            }
            cleartens4(Cel);
    	cleartens4(Idev);
            cleartens2(dstrstr);
            cleartens2(dstrstr_dev);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(strs_ndev);
            cleartens2(mat1);
            
    
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial incremental stress
    	contraction42(Cel, dstrn, dstrstr);
    	contraction42(Idev, dstrstr, dstrstr_dev);
            contraction42(Idev, strs_n, strs_ndev);
    
    	if(dstrseq_tr > 0.){
    		addtens2(1.5/dstrseq_tr, dstrstr_dev, 0., dstrstr_dev, Ntr);
    	}
                    addtens2(1.0, strs_n, 1.0, dstrstr, Str);
           //1. elastic increment
                Dp=DP_MIN;
    	    j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	    strseq2= (sy0 + R)*(sy0 + R);
    
               //1.1 trial (eq_stress)^2 
                 addtens2(1.0, dstrstr_dev, -2.0*mu_el*Dp, Ntr, mat1);
    
                 int scheme = 1;
                 //if(contraction22(strs_ndev,Str)<=0.0){
                 //     scheme = 1;
                 //}
                 if(scheme==1){
                       strseqtr2 =  (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp);
                 }
                 else if(scheme==2){
                        strseqtr2 = (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp) + 3.0*contraction22(strs_ndev,mat1);
                 }
                 else{
                        strseqtr2 = eq2strs_n + (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp) + 3.0*contraction22(strs_ndev,mat1);
                 }
                 FY2->f = strseqtr2 - strseq2; 
    
              //1.2 check yielding condition 
    
           	if(FY2->f<=0.){
    
                    *eq2strs = strseqtr2;
    		copyvect(Str, strs,6);
                    copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    
                    // clean structure FY2
                    FY2->f=0.0;
                    FY2->dfdp=0.0;	
    	        for(i=0;i<6;i++){
    	                FY2->dfdstrn_m[i]=0.0;
                            FY2->dfdstrn_c[i]=0.0;
    	                FY2->dpdstrn_m[i]=0.0;
                            FY2->dpdstrn_c[i]=0.0; 
                    }		
    	}
    	//2. Plastic correction: return mapping algorithm 
    	else{
                 it=0;
    	     res=1.0;
    	     res0=res; 
    	     while(res>tol && stay){
    		  it++;
    		  if(it>20){
    			 printf(":( no convergence in return mapping algorithm, p: %lf\n",*p);
    			 stay=false;
                             Dp=1.;
    			//return(1);
    		  }
    
    		  *p=p_n+Dp;
    		  j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
                      strseq2= (sy0 + R)*(sy0 + R);
                      addtens2(1.0, dstrstr_dev, -2.0*mu_el*Dp, Ntr, mat1);
    
                 	  if(scheme==1){
                         strseqtr2 =  (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp);
                      }
                      else if(scheme==2){
                         strseqtr2 = (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp) +  3.0*contraction22(strs_ndev,mat1);
                      }
                      else{
                        strseqtr2 = eq2strs_n + (dstrseq_tr-3.0*mu_el*Dp)*(dstrseq_tr-3.0*mu_el*Dp) + 3.0*contraction22(strs_ndev,mat1);
                      }
    
    
                      FY2->f = strseqtr2 - strseq2; 
      
    		  res = fabs(FY2->f)/strseq2; //mu_el;
             	  if(it==1||res<res0){
    		     res0=res;
                     // 2.1 newton-raphson iteration , compute Dp
     
                         if(scheme==1 ){
                             FY2->dfdp = -6.0*mu_el*((dstrseq_tr-3.0*mu_el*Dp))-2.0*(sy0 + R)*dR; 
                         }
                         else{
                             FY2->dfdp = -6.0*mu_el*((dstrseq_tr-3.0*mu_el*Dp) + contraction22(strs_ndev, Ntr))-2.0*(sy0 + R)*dR;
                         }
                         cp = -FY2->f/FY2->dfdp;          
    
                         temp1 = 0.99*(DP_MIN-Dp);
    		     if(cp<temp1) {
    			//printf("new Dp below Dpmin : correction!\n");
    			cp=temp1;
    		     }
    		     Dp+=cp;
    		   }
    		   else{
    			//printf("residual is not decreasing: correction!\n");
    			cp=cp/2.;
    			Dp=Dp-cp;
    			res0=res;
    		   }
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    	     }
                 // 2.2 After obtainning the value of Dp, compute the out put variables 
    		*eq2strs = (sy0 + R)*(sy0 + R);
    		addtens2(1., Str,-2.*mu_el*Dp, Ntr, strs);
    		addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
    
                 //2.3 compute the derivatives of f and p
                    if(scheme==1){
                    temp1 = 0.0;
                    temp2 = 2.0*(dstrseq_tr-3.0*mu_el*Dp);
                    }
                    else{
                    temp1 = 6.0*mu_el*(1.0-3.0*mu_el*Dp/dstrseq_tr); 
                    temp2 = 2.0*(dstrseq_tr-3.0*mu_el*Dp)+ 9.0*mu_el*Dp*contraction22(strs_ndev, dstrstr_dev)/dstrseq_tr/dstrseq_tr;
                    }
                    for(i=0;i<6;i++){
                          FY2->dfdstrn_m[i] = temp1*strs_ndev[i];
                          FY2->dpdstrn_m[i] = -FY2->dfdstrn_m[i]/FY2->dfdp;
    
                          FY2->dfdstrn_c[i] = temp2*dstrseq_trdDE[i];
                          FY2->dpdstrn_c[i] = -FY2->dfdstrn_c[i]/FY2->dfdp;
                    }
        
      	} //end case plastic correction
            if(!stay) return(1); //no convergence
    
    	return(0);
    }
    
    
    
    /////**********************************************///////
    //****  ELASTO-VISCOPLASTIC CONSTITUTIVE BOX  ************
    /////*******  07.2016, By Ling Wu    **************///////
    /////**********************************************///////
    
    int constbox_evp(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0,
    	double hexp, int viscmodel, double vmod, double vstressy, double vexp, double *dstrn, double *strs_n, double *strs, double* pstrn_n, 
            double* pstrn, double p_n, double *p, double *twomu_iso, double* dtwomu_iso,  double** Calgo, double*** dCalgo, 
            double* dpdE, bool residual, double dt)
    
    {
    	int i,j,k,it,error;
    	double strseqtr, strseqtrNor0, trstrstr;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G;    //Variables for the correction phase 
            double gv, hv, dgdf, dhvdSeq, dhvdp;
    	double kp;
    	double Dp;  
    	double h, tmp1, tmp2;
    	double cp=0.;
    	double tol = 1.e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    	double mu_iso, k_iso;
    	double G3, h3;
            double sq2;
    
            double eq2strs_n;
    
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    //	k_iso = E/(3.*(1.-(2.*nu)));
    	G3 = G*G*G;
    
            static bool initialized=false;
            // initialize only once!
    	static double **Cel=NULL;
    	static double **NoN=NULL;
    	static double **Idev=NULL;
    	static double **mat1=NULL;
    	static double *strstr=NULL;
    	static double *strstrNor0=NULL;
    	static double *Str=NULL;
    	static double *Ntr=NULL;
    	static double *dstrs=NULL;
            bool stay=true;
    
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&strstr,6);
              mallocvector(&strstrNor0,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6);
              mallocvector(&dstrs,6);
    
              initialized = true;
            }
            cleartens4(Cel);
    	cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(mat1);
            cleartens2(strstr);
            cleartens2(strstrNor0);
            cleartens2(Str);
            cleartens2(Ntr);
            cleartens2(dstrs);
    
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial stress
    	contraction42(Cel, dstrn, dstrs);
    
            addtens2(1., strs_n,   1., dstrs, strstrNor0);
    
    	addtens2(1., strs_n, 1., dstrs, strstr);
            strseqtrNor0 = vonmises(strstrNor0);
           // strseqtrNor0 = vonmises(dstrs);
    	strseqtr = vonmises(strstr);
      
    	//normal to the yield surface
    	dev(strstrNor0, Str);
            //  dev(dstrs, Str);
    
      
    	if(strseqtrNor0 > 0.){
    		addtens2(1.5/strseqtrNor0, Str, 0., Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
    	}
    
             
    	//elastic increment
    	Dp=DP_MIN;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
    	kp = strseq + 3.*G*Dp - strseqtr;
    
    	if(kp>=0.){
    		//printf("elastic: !");
    		copyvect(strstr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
          //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           cleartens2(dpdE);
         
    	}
    	//ViscoPlastic correction: return mapping algorithm 
    	else{
                    Dp = DP_MIN;  //correction must be such that Dp >= DP_MIN
    
    		it=0;
    		res=1.;
    		res0=res;
    		while(res>tol && stay){
    			it++;
    			if(it>20){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);				
    				//return(1);
                                   	stay=false;
                                    Dp=1.;
    
    			}
    
    			*p=p_n+Dp;
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    
    		        strseq = strseqtr-3.*G*Dp;
    
                            solve_gv(viscmodel, vmod, vstressy, vexp, G, strseq, sy0, dt, R, dR, ddR, &gv, &hv, &dgdf, &dhvdSeq, &dhvdp,eq2strs_n);
    
    			kp = Dp - gv*dt;                           
    			res = fabs(kp);
                            h=hv;
    
    			if(it==1||res<res0){
    				res0=res;
    				cp =  - kp/(h*dgdf*dt);
    				tmp1 = 0.99*(DP_MIN-Dp);
    				if(cp<tmp1) {
    					//printf("new Dp below Dpmin : correction!\n");
    					cp=tmp1;
    				}
    				Dp+=cp;
    			}
    			else{
    				//printf("residual is not decreasing: correction!\n");
    				cp=cp/2.;
    				Dp=Dp-cp;
    				res0=res;
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    
         	        addtens2(1., strstr,-2.*G*(Dp), Ntr, strs);
    	        addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
                 
    	        h3 = h*h*h;
    		tmp1 = 4.*G*G/h;
    		tmp2 = 4.*G*G*(*p-p_n)/strseqtr;
    
    		addtens4(1.,Cel,(-tmp1+tmp2),NoN, Calgo);
    		addtens4(1.,Calgo,-1.5*tmp2,Idev,Calgo);  
    
    		addtens4(1.5,Idev,-1.,NoN,mat1);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k] = (8.*G3/(h*h))*(dhvdSeq*(1.0-3.0*G/h) + dhvdp/h)*NoN[i][j]*Ntr[k] - (16.*G3/(h*strseqtr))*Ntr[i]*mat1[j][k] - mat1[i][j]*8.*G3*Ntr[k]*((1./(h*strseqtr))-(Dp/(strseqtr*strseqtr))) + (16.*G3*Dp/(strseqtr*strseqtr))*Ntr[i]*mat1[j][k];
    				}
    			}
    		}
    
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2((2.*G/h), Ntr, 0, Ntr, dpdE);
    
    
    	} //end case plastic correction
    
    
          
    
    
    	//compute isoJ2 tangent operator and its derivative w.r.t. strain increment
    	if(Dp<DP_MIN){		//that is, Dp=0 	
    		mu_iso=G;
    		for(i=0;i<6;i++){
    			dtwomu_iso[i]=0.;
    		}
    	}
    		
    	else {
    		mu_iso = G*(1.-(3.*G/h));
    		for(i=0;i<6;i++){
    			dtwomu_iso[i] = 12.*pow(G/h,3.)*ddR*Ntr[i];
    		}
    	}
      
    	*twomu_iso = 2.*mu_iso;
    
    //      no free as initialized once        
    //     	freematrix(Cel, 6);
    //	freematrix(Idev,6);
    //	freematrix(NoN,6);
    //	freematrix(mat1,6);
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    
    //ELASTO-VISCOPLASTIC CONSTITUTIVE BOX for second moment mehtod
    int constbox_evp(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0, double hexp, int viscmodel, double vmod, double vstressy, double vexp, double *DE, double *dstrn, double *strs_n, double eq2strs_n, double *eq2strs, double dstrseq_tr, double *dstrseq_trdDE, double *strs, double* pstrn_n, double* pstrn, double p_n, double *p, FY2nd *FY2, double dt, ELcc *LCC){
    
    	int i,j,it;
    	double strseqtr;       	//Variables for the elastic prediction 
            double gv, hv, dgdf, dhvdSeq, dhvdp;
    	double R, dR, ddR, strseq, mu_el;    //Variables for the correction phase 
            double kp;
    	double Dp, temp0, temp1, temp2;
    	double cp=0.0;
    	double tol = 1e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	mu_el = E/(2.*(1.+nu));  
    	
            static bool initialized=false;
            // initialize only once!
    	static double **Cel=NULL;
    	static double **Idev=NULL;
    	static double **I=NULL;
    	//static double **ImA=NULL;
    	static double *dstrstr=NULL;
    	static double *dstrstr_dev=NULL;
    	static double *Str=NULL;
    	static double *Ntr=NULL;
    	static double *strs_ndev=NULL;
    	//static double *Edstrn_i=NULL;
    	//static double *Edstrn_m=NULL;
    	static double *mat1=NULL;
    	//static double *Edstrstr=NULL;
    	//static double *Edstrstr_dev=NULL;
    	//static double *P;
            bool stay=true;
    		
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&I,6,6);
    	  //mallocmatrix(&ImA,6,6);
    	  mallocvector(&dstrstr,6);
    	  mallocvector(&dstrstr_dev,6);
    	  mallocvector(&Str,6);
    	  mallocvector(&Ntr,6);
    	  mallocvector(&strs_ndev,6);
    	  //mallocvector(&Edstrn_i,6);
    	  //mallocvector(&Edstrn_m,6);
    	  mallocvector(&mat1,6);
    	  //mallocvector(&Edstrstr,6);
    	  //mallocvector(&Edstrstr_dev,6);
    	  //mallocvector(&P,6);
    
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(Idev);
    	cleartens4(I);
    	//cleartens4(ImA);
    	cleartens2(dstrstr);
    	cleartens2(dstrstr_dev);
    	cleartens2(Str);
    	cleartens2(Ntr);
    	cleartens2(strs_ndev);
    	//cleartens2(Edstrn_i);
    	//cleartens2(Edstrn_m);
    	cleartens2(mat1);
    	//cleartens2(Edstrstr);
    	//cleartens2(Edstrstr_dev);
    	//cleartens2(P);
    
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    
    	for(i=0;i<6;i++){
    		I[i][i] = 1.;
    	}
    
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	//compute trial incremental stress
    	contraction42(Cel, dstrn, dstrstr);
    	contraction42(Idev, dstrstr, dstrstr_dev);
            contraction42(Idev, strs_n, strs_ndev);
    
    
            //double v1= LCC->v1;
            //double v0 = 1.0 - v1;		
    	//contraction42(LCC->A, DE, Edstrn_i);              //unloading strain of inclusion at tn
            //addtens2 (1./v0, DE, -1.*v1/v0, Edstrn_i, Edstrn_m); //unloading strain of matrix at tn
    
            //addtens4(1.0/v0, I, -1.0*v1/v0, LCC->A, ImA);
    
    
    	//compute trial incremental stress
       	//contraction42(Cel, dstrn, Edstrstr);
    
    	
    	//contraction42(Idev, Edstrstr, Edstrstr_dev);
            //contraction42(Idev, strs_n, strs_ndev);
    
    	//contraction42(ImA, strs_ndev,P);
            //addtens2(1.0, strs_n, 1.0, Edstrstr, Str);
            addtens2(1.0, strs_n, 1.0, dstrstr, Str);
    
    
           //1. elastic increment
                Dp=DP_MIN;
    	    j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    
               //1.1 trial (eq_stress)^2 
                 strseqtr =  dstrseq_tr;
                 int soft_inclusions=0;
                 if(soft_inclusions==1)
                 {
                    // for soft inclusion, a modification is applied-----------
                    temp0 = (dstrseq_tr*dstrseq_tr)+6.0*mu_el*contraction22(strs_ndev, dstrn)+ 1.5*contraction22(strs_ndev,strs_ndev);
                    strseqtr =  fabs(pow(temp0,0.5)-3.0*mu_el*Dp);     
                 }
                 if(dstrseq_tr > 0.){
                   addtens2(1.5/dstrseq_tr, dstrstr_dev, 0., strs_ndev, Ntr);
                   //old version
                   //addtens2(1.5/dstrseq_tr, dstrstr_dev, 1.5, strs_ndev, Ntr);
                  //addtens2(1.5/strseqtr, dstrstr_dev, 1.5/strseqtr, strs_ndev, Ntr);
                     //addtens2(1.5/strseqtr, dstrstr_dev, 1.5/strseqtr, strs_ndev, Ntr);
                  //----------------------------------------------------------------------
    	    }           
    
                 FY2->f = strseqtr - (sy0 + R);
    
              //1.2 check yielding condition 
    
           	if(FY2->f<=0.){
    
                    *eq2strs = strseqtr*strseqtr;
    		copyvect(Str, strs,6);
                    copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    
                    // clean structure FY2
                    FY2->f=0.0;
                    FY2->dfdp=0.0;	
    	        for(i=0;i<6;i++){
    	                FY2->dfdstrn_m[i]=0.0;
                            FY2->dfdstrn_c[i]=0.0;
    	                FY2->dpdstrn_m[i]=0.0;
                            FY2->dpdstrn_c[i]=0.0; 
                    }		
    	}
    	//2. Plastic correction: return mapping algorithm 
    	else{
                 it=0;
    	     res=1.0;
    	     res0=res;
    	     while(res>tol && stay){
    		  it++;
    		  if(it>20){
    			printf("no convergence in return mapping algorithm, p: %lf\n",*p);
    			stay=false;
                            Dp=1.;
    			//return(1);
    		  }
    
    		  *p=p_n+Dp;
                      j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    
                   	  strseq =  strseqtr-3.0*mu_el*Dp;
                      solve_gv(viscmodel, vmod, vstressy, vexp, mu_el, strseq, sy0, dt, R, dR, ddR, &gv, &hv, &dgdf, &dhvdSeq, &dhvdp,eq2strs_n);
    
                      kp = Dp - gv*dt;                           
    		  res = fabs(kp);
                     
                      if(it==1||res<res0){
    			res0=res;
    			cp = - kp/(hv*dgdf*dt);
    			temp1 = 0.99*(DP_MIN-Dp);
    			if(cp<temp1) {
    			   //printf("new Dp below Dpmin : correction!\n");
    			    cp=temp1;
    			}
    			Dp+=cp;
    		  }
    		  else{
    			 //printf("residual is not decreasing: correction!\n");
    			cp=cp/2.;
    			Dp=Dp-cp;
    			res0=res;
    		  }
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    	     }
    
                 // 2.2 After obtainning the value of Dp, compute the out put variables 
    
    		*eq2strs = strseq*strseq;
    		addtens2(1., Str,-2.*mu_el*Dp, Ntr, strs);
    		addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
    
                 //2.3 compute the derivatives of f and p
                    for(i=0;i<6;i++){
                          FY2->dpdstrn_m[i] = 0.0;                    
    
                         if(soft_inclusions==1)
                         {
                           // for soft inclusion, a modification is applied-----------
    
                           FY2->dpdstrn_m[i] = strs_ndev[i]*3.0*mu_el/(strseqtr)/hv;
                           //---------------------
                         }
                         FY2->dpdstrn_c[i] = dstrseq_trdDE[i]/hv;
                    }
        
      	} //end case plastic correction
            if(!stay) return(1); //no convergence
    
    	return(0);
    }
    
    //****************************************************
    /**********J2 viscoplasticity for large deformation***/
    //******************************************************
    int constbox_evp(double E, double nu, double sy0, int htype, double hmod1, double hmod2, double hp0,
    	double hexp, int viscmodel, double vmod, double vstressy, double vexp, double *strs_tr, double *Rstrs_n, double *strs, double* pstrn_n, 
            double* pstrn, double p_n, double *p, double** Calgo, double*** dCalgo, double* dpdE, bool residual, double dt)
    
    {
    	int i,j,k,it,error;
    	double strseqtr,strseqtr0;       	//Variables for the elastic prediction 
    	double R, dR, ddR, strseq, G;    //Variables for the correction phase 
            double gv, hv, dgdf, dhvdSeq, dhvdp;
    	double kp;
    	double Dp;  
    	double h, tmp1, tmp2;
    	double cp=0.0;
    	double tol = 1.e-12;    //tolerance on the residual 
    	double res, res0;    		 //residual 
    	double G3, h3;
            double sq2;
    
            double eq2strs_n;
            bool stay=true;
    
            sq2 = sqrt(2.);
    	R=0.;
    	dR=0.;
    	ddR=0.;
    
    	G = E/(2.*(1.+nu));  
    //	k_iso = E/(3.*(1.-(2.*nu)));
    	G3 = G*G*G;
    
            static bool initialized=false;
            // initialize only once!
    	static double **Cel;
    	static double **NoN;
    	static double **Idev;
    	static double **mat1;
    	static double *Str;
            static double *Ntr;
            static double *strstrNor0;
    
            if(!initialized)
            {
              mallocmatrix(&Cel, 6, 6);
    	  mallocmatrix(&NoN,6,6);
    	  mallocmatrix(&Idev,6,6);
    	  mallocmatrix(&mat1,6,6);
              mallocvector(&Str,6);
              mallocvector(&Ntr,6); 
              mallocvector(&strstrNor0,6);
              initialized = true;
            }
            cleartens4(Cel);
            cleartens4(NoN);
    	cleartens4(Idev);
    	cleartens4(mat1);
    	cleartens2(Str);
    	cleartens2(Ntr);
            cleartens2(strstrNor0);
    	//deviatoric operator
    	for(i=0;i<3;i++){
    	  for(j=0;j<3;j++){
    	    Idev[i][j]=-1./3.;
              }
    	  Idev[i][i]+=1.;
    	  Idev[i+3][i+3]=1.;
    	}
    	//reset tangent operators to zero
    	for(i=0;i<6;i++){
    		for(j=0;j<6;j++){
    			Calgo[i][j]=0.;
    		}
    	}
    
    	//elastic predictor
    	compute_Hooke(E,nu,Cel);
    
    	strseqtr = vonmises(strs_tr);
      
    	//normal to the yield surface
            //dev(strs_tr, Str);
      
            //normal to the residual stress
            addtens2(1.0, strs_tr, -1.0, Rstrs_n, strstrNor0);
    	dev(strstrNor0, Str);
    	strseqtr0 = vonmises(strstrNor0);
    
    	if(strseqtr > 0.){
    		addtens2(1.5/strseqtr0, Str, 0., Str, Ntr);
    		produit_tensoriel(Ntr,Ntr,NoN);
    	}
             
    	//elastic increment
    	Dp=DP_MIN;
    	j2hard (p_n+Dp, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    	strseq= sy0 + R;
    	kp = strseq + 3.*G*Dp - strseqtr;
    
    	if(kp>=0.){
    		//printf("elastic: !");
    		copyvect(strs_tr, strs, 6);
    		copyvect(pstrn_n, pstrn,6);
        		*p = p_n;
    		Dp=0.;
    		copymatr(Cel,Calgo,6,6);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k]=0.;
    				}
    			}
    		}
          //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
            cleartens2(dpdE);
         
    	}
    	//ViscoPlastic correction: return mapping algorithm 
    	else{
                    Dp = DP_MIN;  //correction must be such that Dp >= DP_MIN
    
    		it=0;
    		res=1.;
    		res0=res;
    		while(res>tol && stay){
    			it++;
    			if(it>20){
    				printf("no convergence in return mapping algorithm, p: %lf\n",*p);			
                                    stay=false;
                                    Dp=1.;
    	
    				//return(1);
    			}
    
    			*p=p_n+Dp;
    			j2hard (*p, sy0, htype, hmod1, hmod2, hp0, hexp, &R, &dR,&ddR);
    
    		        strseq = strseqtr-3.*G*Dp;
    
                            solve_gv(viscmodel, vmod, vstressy, vexp, G, strseq, sy0, dt, R, dR, ddR, &gv, &hv, &dgdf, &dhvdSeq, &dhvdp,eq2strs_n);
    
    			kp = Dp - gv*dt;                           
    			res = fabs(kp);
                            h=hv;
    
    			if(it==1||res<res0){
    				res0=res;
    				cp =  - kp/(h*dgdf*dt);
    				tmp1 = 0.99*(DP_MIN-Dp);
    				if(cp<tmp1) {
    					//printf("new Dp below Dpmin : correction!\n");
    					cp=tmp1;
    				}
    				Dp+=cp;
    			}
    			else{
    				//printf("residual is not decreasing: correction!\n");
    				cp=cp/2.;
    				Dp=Dp-cp;
    				res0=res;
    			}
    
    			//printf("j2plast iteration: %d, res: %.10e, p: %.10e\n",it,res,*p);
    		}
    		//printf("Number of iterations in radial return algorithm: %d\n",it); 
    
         	        addtens2(1., strs_tr,-2.*G*(Dp), Ntr, strs);
    	        addtens2(1.,pstrn_n, Dp, Ntr, pstrn);
                 
    	        h3 = h*h*h;
    		tmp1 = 4.*G*G/h;
    		tmp2 = 4.*G*G*(*p-p_n)/strseqtr;
    
    		addtens4(1.,Cel,(-tmp1+tmp2),NoN, Calgo);
    		addtens4(1.,Calgo,-1.5*tmp2,Idev,Calgo);  
    
    		addtens4(1.5,Idev,-1.,NoN,mat1);
    		for(i=0;i<6;i++){
    			for(j=0;j<6;j++){
    				for(k=0;k<6;k++){
    					dCalgo[i][j][k] = (8.*G3/(h*h))*(dhvdSeq*(1.0-3.0*G/h) + dhvdp/h)*NoN[i][j]*Ntr[k] - (16.*G3/(h*strseqtr))*Ntr[i]*mat1[j][k] - mat1[i][j]*8.*G3*Ntr[k]*((1./(h*strseqtr))-(Dp/(strseqtr*strseqtr))) + (16.*G3*Dp/(strseqtr*strseqtr))*Ntr[i]*mat1[j][k];
    				}
    			}
    		}
    
           //compute dpdE  accumulate plastice strain p derivative w.r.t. strain increment
    
           addtens2((2.*G/h), Ntr, 0, Ntr, dpdE);
    
    
    	} //end case plastic correction
    
    
    
    //      no free as initialized once        
    //     	freematrix(Cel, 6);
    //	freematrix(Idev,6);
    //	freematrix(NoN,6);
    //	freematrix(mat1,6);
            if(!stay) return(1); //no convergence
    	return(0);
    }
    
    
    /***********************************************************
     * SOLVE VISCOPLASTIC FUNCTION gv *
     **********************************************************/
    
    void solve_gv(int viscmodel, double vmod, double vstressy, double vexp, double mu, double strseq, double yldstrs, double dt, double R, double dR, double ddR, double *gv, double *hv, double *dgdf, double *dhvdSeq, double *dhvdp, double eq2strs_n){
    
    	double f;
            double tmp1,tmp2, dgdR;
            double ddgdSdR, ddgdR;
         	
            f = strseq - yldstrs - R;
    
    	if(f < 0.0){
    		printf("f < 0 Should be elastic, f = %.10e\n",f);
    		return;
    	}
            
    	switch(viscmodel){
    		case V_NORTON:
                            *gv = vmod*pow(f/yldstrs,vexp);
                            tmp1 = vmod*vexp/yldstrs*pow(f/yldstrs,vexp-1.0);
                            *dgdf = tmp1;
                    
                            *hv = 1.0/(tmp1*dt)+3.0*mu + dR;
    
                            tmp2 = vmod*vexp*(vexp-1.0)/(yldstrs*yldstrs)*pow(f/yldstrs,vexp-2.0); //ddgvdSeq
                            *dhvdSeq = -1.0/(tmp1*tmp1*dt)*tmp2;
                            *dhvdp = 1.0/(tmp1*tmp1*dt)*tmp2*dR + ddR;
    
    			break;
    		
    		//PERZYNA law with drag stress implemented in Abaqus 
    		case V_PERZYNA:
    			*gv = vmod*pow(f/(yldstrs+R),vexp);
                            tmp1 = vmod*vexp/(yldstrs+R)*pow(f/(yldstrs+R),vexp-1.0);
                            *dgdf = tmp1;
    
                            dgdR = -tmp1-vmod*vexp/(yldstrs+R)*pow(f/(yldstrs+R),vexp);
                            *hv = 1.0/(tmp1*dt) + 3.0*mu - dgdR/tmp1*dR ;
    
                            tmp2 = vmod*vexp*(vexp-1.0)/((yldstrs+R)*(yldstrs+R))*pow(f/(yldstrs+R),vexp-2.0); //ddgvdSeq
                            ddgdSdR = -tmp2*(1.0 + vexp*f/(yldstrs+R)/(vexp-1.0));
                            ddgdR = tmp2*(1.0 + 2.0*vexp*f/(yldstrs+R)/(vexp-1.0) + (vexp+1.0)*f/(yldstrs+R)*f/(yldstrs+R)/(vexp-1.0));
    
                            *dhvdSeq = 1.0/(tmp1*tmp1)*tmp2*(-1.0/dt + dgdR*dR) - ddgdSdR*dR/tmp1;
                            *dhvdp = (-1.0/dt + dgdR*dR)/(tmp1*tmp1)*ddgdSdR*dR - (ddgdR*dR*dR+ dgdR*ddR)/tmp1; 
    
    			break;
    				
    		//Power law 
    		case V_POWER:
    			*gv = vmod*pow(strseq/(yldstrs+R),vexp);
                            tmp1 = vmod*vexp/(yldstrs+R)*pow(strseq/(yldstrs+R),vexp-1.0);
                            *dgdf = tmp1;
    
                            dgdR = -vmod*vexp/(yldstrs+R)*pow(strseq/(yldstrs+R),vexp);
                            *hv = 1.0/(tmp1*dt) + 3.0*mu - dgdR/tmp1*dR ;
    
                            tmp2 = vmod*vexp*(vexp-1.0)/((yldstrs+R)*(yldstrs+R))*pow(strseq/(yldstrs+R),vexp-2.0); //ddgvdSeq
                            ddgdSdR = -tmp1*vexp/(yldstrs+R);
                            ddgdR = vmod*vexp*(vexp+1.0)/(yldstrs+R)/(yldstrs+R)*pow(strseq/(yldstrs+R),vexp);
    
                            *dhvdSeq = 1.0/(tmp1*tmp1)*tmp2*(-1.0/dt + dgdR*dR) - ddgdSdR*dR/tmp1;
                            *dhvdp = (-1.0/dt + dgdR*dR)/(tmp1*tmp1)*ddgdSdR*dR - (ddgdR*dR*dR+ dgdR*ddR)/tmp1; 
    
    			break;	
    
    		case V_PRANDTL:
                            double Beta;
                            Beta = 10.0;
    
                            *gv = vmod*pow(sinh(f/Beta),vexp);
                            tmp1 = vmod*vexp/Beta*pow(sinh(f/Beta),vexp-1.0)*cosh(f/Beta);
                            *dgdf = tmp1;
                    
                            *hv = 1.0/(tmp1*dt)+3.0*mu + dR;
    
                            tmp2 = vmod*vexp/Beta/Beta*((vexp-1.0)*pow(sinh(f/Beta),vexp-2.0)*cosh(f/Beta)*cosh(f/Beta)+
                                   pow(sinh(f/Beta),vexp)); //ddgvdSeq
                            *dhvdSeq = -1.0/(tmp1*tmp1*dt)*tmp2;
                            *dhvdp = 1.0/(tmp1*tmp1*dt)*tmp2*dR + ddR;
    
    			break;
    		//Power law with hardening: vmod is actually dot eps0/sy0^n
    		case V_POWER_NO_HARDENING:
                      	*gv = vmod*pow(strseq/vstressy,vexp);
                            tmp1 = vmod/vstressy*vexp*pow(strseq/vstressy,vexp-1.0);
                            *dgdf = tmp1;
                            dgdR = 0.;
                            *hv = 1.0/(tmp1*dt) + 3.0*mu  ;
    
                            tmp2 = vmod*vexp*(vexp-1.0)/vstressy/vstressy*pow(strseq/vstressy,vexp-2.0); //ddgvdSeq
                            ddgdSdR = 0.0;
                            ddgdR = 0.0;
                            if(vexp == 1.0){
                                *dhvdSeq = 0.0;
                                *dhvdp =0.0; 
                            }
                            else{
                                *dhvdSeq = -1.0/(dt*tmp1*tmp1)*tmp2;
                                *dhvdp =  0.0; 
                            } 
    			break;	
    		default:
    			printf("Invalid viscosity law: %d\n", viscmodel);
    			break;
    	}
    
    	return;
    }
    	
    
    
    
    
    #endif