Exemple #1
0
// When becomes active update J, set pressure deviatoric stress from current elastic B
void Neohookean::BeginActivePhase(MPMBase *mptr,int np,int historyOffset) const
{	double J = mptr->GetRelativeVolume();
	mptr->SetHistoryDble(J_History,J,historyOffset);
	
    // account for residual stresses
	double Jres = mptr->GetHistoryDble(J_History+1,historyOffset);
	double resStretch = pow(Jres,1./3.);
	double Jres23 = resStretch*resStretch;
	double Jeff = J/Jres;
	
	// get pointer to new left Cauchy strain
    Tensor *B = mptr->GetAltStrainTensor();
	
    // update pressure
	double Pterm = J*GetVolumetricTerms(Jeff,pr.Lamesp) + Jres*pr.Gsp*((B->xx+B->yy+B->zz)/(3.*Jres23) - 1.);
    mptr->SetPressure(-Pterm);
	
    // Account for density change in specific stress
    // i.e.. Get (Kirchoff Stress)/rho0
	double GJeff = resStretch*pr.Gsp;		// = J*(Jres^(1/3) G/J) to get Kirchoff
    
	// find deviatoric (Cauchy stress)J/rho0 = deviatoric (Kirchoff stress)/rho0
	Tensor *sp=mptr->GetStressTensor();
    double I1third = (B->xx+B->yy+B->zz)/3.;
	sp->xx = GJeff*(B->xx-I1third);
	sp->yy = GJeff*(B->yy-I1third);
	sp->zz = GJeff*(B->zz-I1third);
	sp->xy = GJeff*B->xy;
    if(np==THREED_MPM)
	{	sp->xz = GJeff*B->xz;
        sp->yz = GJeff*B->yz;
    }
}
Exemple #2
0
// To allow better subclassing it is better to separate out calculations
//  of dilation energy. This version updates pressure (i.e. dilational
//  contribution to normal stress) and adds incremental energy to strain energy
// J = V(T,c)/V0(T,c), Jeff = V(T,c)/V0(Tref,cref), Jres = V0(T,c)/V0(Tref,cref) = J/Jeff
// Jn+1 = (detdF/detdFres) Jn, Jresn+1 = detdFres Jresn, Jtot = detdF Jtotn
// detdFres = (1+dres)^3 (approximately)
// Here Tref and cref are starting conditions and T and c are current temperature and moisture
void HEIsotropic::UpdatePressure(MPMBase *mptr,double J,double detdF,int np,double Jeff,
								 double delTime,HEPlasticProperties *p,ResidualStrains *res,double detdFres,int offset,
								 double &dTq0,double &AVEnergy) const
{
	double Kterm = J*GetVolumetricTerms(Jeff,p->Kred);       // times J to get Kirchoff stress
    double P0 = mptr->GetPressure();
    
    // artifical viscosity
	// delV is total incremental volumetric strain = total Delta(V)/V, here it is (Vn+1-Vn)/Vn+1
	double delV = 1. - 1./detdF;
    double QAVred = 0.;
    if(delV<0. && artificialViscosity)
	{	QAVred = GetArtificalViscosity(delV/delTime,sqrt(p->Kred*J),mptr);
        if(ConductionTask::AVHeating) AVEnergy += fabs(QAVred*delV);
    }
    double Pfinal = -Kterm + QAVred;
    mptr->SetPressure(Pfinal);
    
    // work energy is dU = -P dV + s.de(total)
	// Here do hydrostatic term
    // Internal energy increment per unit mass (dU/(rho0 V0)) (nJ/g)
	// Also get residual energy from -P (Vresn+1-Vresn)/Vresn+1 = -P delVres
    double avgP = 0.5*(P0+Pfinal);
	double delVres = 1. - 1./detdFres;
    mptr->AddWorkEnergyAndResidualEnergy(-avgP*delV,-avgP*delVres);
	
	// elastic particle isentropic temperature increment
	double Kratio;				// = rho_0 K/(rho K_0)
	switch(UofJOption)
	{   case J_MINUS_1_SQUARED:
			Kratio = Jeff;
			break;
			
		case LN_J_SQUARED:
			Kratio = (1-log(Jeff))/(Jeff*Jeff);
			break;
			
		case HALF_J_SQUARED_MINUS_1_MINUS_LN_J:
		default:
			Kratio = 0.5*(Jeff + 1./Jeff);
			break;
	}
	dTq0 = -J*Kratio*gammaI*mptr->pPreviousTemperature*delV;
}
/* Take increments in strain and calculate new Particle: strains, rotation strain,
		stresses, strain energy,
	dvij are (gradient rates X time increment) to give deformation gradient change
	For Axisymmetry: x->R, y->Z, z->theta, np==AXISYMMEtRIC_MPM, otherwise dvzz=0
	This material tracks pressure and stores deviatoric stress only in particle stress tensor
 */
void ClampedNeohookean::MPMConstitutiveLaw(MPMBase *mptr,Matrix3 du,double delTime,int np,void *properties,
										   ResidualStrains *res,int historyOffset) const
{
	// Update total deformation gradient, and calculate trial B
    Tensor Btrial;
	double detDF = IncrementDeformation(mptr,du,&Btrial,np);
    
	// global J
	double J = detDF * mptr->GetHistoryDble(J_History,historyOffset);
	mptr->SetHistoryDble(J_History,J,historyOffset);
	
	// convert Btrial to matrix to get eigenvalues and check for clamping
	Matrix3 Belas(Btrial.xx,Btrial.xy,Btrial.xz,
				  Btrial.xy,Btrial.yy,Btrial.yz,
				  Btrial.xz,Btrial.yz,Btrial.zz);
	if(np!=THREED_MPM) Belas.setIs2D(true);
		
	// get Eigenvalues and Eigenvectors
	Vector lam2 = Belas.Eigenvalues();
	
	// clamp eigenvalues if needed
	bool clamped = false;
	if(lam2.x<lamMin2 || lam2.x>lamMax2 || lam2.y<lamMin2 || lam2.y>lamMax2 || lam2.z<lamMin2 || lam2.z>lamMax2)
		clamped = true;
	
	// Get Je and Jp, adjusting if clamped
	double Je,Jp;
	Matrix3 Ucol;
	if(clamped)
	{	// Find Belas = U.LAM.UT
		Ucol = Belas.Eigenvectors(lam2);
		// clamp values now
		if(lam2.x<lamMin2)
			lam2.x = lamMin2;
		else if(lam2.x>lamMax2)
			lam2.x = lamMax2;
		if(lam2.y<lamMin2)
			lam2.y = lamMin2;
		else if(lam2.y>lamMax2)
			lam2.y = lamMax2;
		if(lam2.z<lamMin2)
			lam2.z = lamMin2;
		else if(lam2.z>lamMax2)
			lam2.z = lamMax2;
		Matrix3 UcolT = Ucol.Transpose();
		Matrix3 Lam(lam2.x,0.,0.,lam2.y,lam2.z);
		Matrix3 LamUcolT = Lam*UcolT;
		Belas = Ucol*LamUcolT;
		
		// get Je and Jp
		Je = sqrt(lam2.x*lam2.y*lam2.z);
		Jp = J/Je;
		mptr->SetHistoryDble(JP_HISTORY,Jp,historyOffset);
	}
	else
	{	Jp = mptr->GetHistoryDble(JP_HISTORY,historyOffset);
		Je = J/Jp;
		if(elasticModel==ELASTIC_DISNEY)
			Ucol = Belas.Eigenvectors(lam2);
	}
	
	// store B elastic
	Tensor *sp=mptr->GetStressTensor();
    Tensor *B = mptr->GetAltStrainTensor();
	B->xx = Belas(0,0);
	B->yy = Belas(1,1);
	B->zz = Belas(2,2);
	B->xy = Belas(0,1);
	if(np==THREED_MPM)
	{	B->xz = Belas(0,2);
		B->yz = Belas(1,2);
	}
	
	// change mechanical properties by hardening
	double arg = exp(hardening*(1.-Jp));
	double altGsp = pr.Gsp*arg;
	double altLamesp = pr.Lamesp*arg;

	// account for residual stresses
	double dJres = GetIncrementalResJ(mptr,res);
	double Jres = dJres*mptr->GetHistoryDble(J_History+1,historyOffset);
	mptr->SetHistoryDble(J_History+1,Jres,historyOffset);
	double resStretch = pow(Jres,1./3.);
	double Jres23 = resStretch*resStretch;
		
	// account for residual stresses relative to elastic J
	double Jeff = Je/Jres;
		
	// for incremental energy, store initial stress and pressure
	Tensor *sporig=mptr->GetStressTensor();
	Tensor st0 = *sporig;
	double Pfinal,p0=mptr->GetPressure();
	
	if(elasticModel==ELASTIC_DISNEY)
	{	// Use model from Disney paper
		
		// Get Cauchy stress/rho0
		double sig[3][3];
		double lam[3];
		lam[0]=sqrt(lam2.x)/resStretch;
		lam[1]=sqrt(lam2.y)/resStretch;
		lam[2]=sqrt(lam2.z)/resStretch;
		for(int i=0;i<3;i++)
		{	for(int j=i;j<3;j++)
			{	sig[i][j] = 0.;
				for(int k=0;k<3;k++)
				{	sig[i][j] += (2.*altGsp*lam[k]*(lam[k]-1)/Jeff + altLamesp*(Jeff-1))*Ucol(i,k)*Ucol(j,k);
				}
			}
		}
		
		// update pressure (*J to get Kirchoff pressure)
		Pfinal = -J*(sig[0][0]+sig[1][1]+sig[2][2])/3.;
		mptr->SetPressure(Pfinal);

		// get and set deviatoric stress
		// find eviatoric (Kirchoff stress)/rho0 = deviatoric (Cauchy stress)J/rho0
		sp->xx = J*sig[0][0]+Pfinal;
		sp->yy = J*sig[1][1]+Pfinal;
		sp->zz = J*sig[2][2]+Pfinal;
		sp->xy = J*sig[0][1];
		if(np==THREED_MPM)
		{	sp->xz = J*sig[0][2];
			sp->yz = J*sig[1][2];
		}
	}
	else
	{	// Use standard neo-Hookean law
		
		// update pressure (*J to get Kirchoff pressure)
		Pfinal = -J*(GetVolumetricTerms(Jeff,altLamesp) + (altGsp/Jeff)*((B->xx+B->yy+B->zz)/(3.*Jres23) - 1.));
		mptr->SetPressure(Pfinal);
		
		// Account for density change in specific stress
		// i.e.. Get (Kirchoff Stress)/rho0
		double GJeff = J*resStretch*altGsp/Je;		// = J*(Jres^(1/3) G/Je) to get Kirchoff
		
		// find deviatoric (Kirchoff stress)/rho0 = deviatoric (Cauchy stress)J/rho0
		double I1third = (B->xx+B->yy+B->zz)/3.;
		sp->xx = GJeff*(B->xx-I1third);
		sp->yy = GJeff*(B->yy-I1third);
		sp->zz = GJeff*(B->zz-I1third);
		sp->xy = GJeff*B->xy;
		if(np==THREED_MPM)
		{	sp->xz = GJeff*B->xz;
			sp->yz = GJeff*B->yz;
		}
	}
	
	// work and residual energies
    double delV = 1. - 1./detDF;                        // total volume change
    double avgP = 0.5*(p0+Pfinal);
    double dilEnergy = -avgP*delV;
	
	// incremental residual energy
	double delVres = 1. - 1./dJres;
	double resEnergy = -avgP*delVres;

	// incremental work energy = shear energy
    double shearEnergy = 0.5*((sp->xx+st0.xx)*du(0,0) + (sp->yy+st0.yy)*du(1,1) + (sp->zz+st0.zz)*du(2,2)+
							  (sp->xy+st0.xy)*(du(0,1)+du(1,0)));
    if(np==THREED_MPM)
    {   shearEnergy += 0.5*((sp->xz+st0.xz)*(du(0,2)+du(2,0)) + (sp->yz+st0.yz)*(du(1,2)+du(2,1)));
    }
	
    // strain energy
    double dU = dilEnergy + shearEnergy;
    mptr->AddWorkEnergyAndResidualEnergy(dU,resEnergy);
	
	// thermodynamics heat and temperature
	// Should find energy dissipated by plasticity and add in third term
	IncrementHeatEnergy(mptr,res->dT,0.,0.);
}
Exemple #4
0
/* Take increments in strain and calculate new Particle: strains, rotation strain,
	stresses, strain energy,
	dvij are (gradient rates X time increment) to give deformation gradient change
	For Axisymmetry: x->R, y->Z, z->theta, np==AXISYMMETRIC_MPM, otherwise dvzz=0
	This material tracks pressure and stores deviatoric stress only in particle stress
	tensor
*/
void Neohookean::MPMConstitutiveLaw(MPMBase *mptr,Matrix3 du,double delTime,int np,void *properties,
									ResidualStrains *res,int historyOffset) const
{
	// Update strains and rotations and Left Cauchy strain
	double detDf = IncrementDeformation(mptr,du,NULL,np);
	
	// get pointer to new left Cauchy strain
    Tensor *B = mptr->GetAltStrainTensor();
	
    // account for residual stresses
	double dJres = GetIncrementalResJ(mptr,res);
	double Jres = dJres*mptr->GetHistoryDble(J_History+1,historyOffset);
	mptr->SetHistoryDble(J_History+1,Jres,historyOffset);
	double resStretch = pow(Jres,1./3.);
	double Jres23 = resStretch*resStretch;
	
	// Deformation gradients and Cauchy tensor differ in plane stress
	if(np==PLANE_STRESS_MPM)
	{	// Find B->zz required to have zero stress in z direction
		double arg = B->xx*B->yy - B->xy*B->xy;
		double xn;
		Tensor *ep=mptr->GetStrainTensor();
		
		switch(UofJOption)
		{   case J_MINUS_1_SQUARED:
			{	double a = pr.Lamesp*arg + pr.Gsp*pow(Jres,4./3.);
				double b = pr.Lamesp*sqrt(arg);
				xn = Jres*(b + sqrt(b*b + 4.*pr.Gsp*a))/(2.*a);
				xn *= xn;
				break;
			}
			case LN_J_SQUARED:
			{	xn = B->zz;
				double fx,fxp,xnp1,Jres23 = pow(Jres,2./3.);
				int iter=1;
				while(iter<20)
				{	// get f and df/dxn
					fx = pr.Gsp*(xn-Jres23) + 0.5*pr.Lamesp*Jres23*log(xn*arg/(Jres*Jres));
					fxp = pr.Gsp + pr.Lamesp*Jres23/(2*xn);
					
					// new prediction for solution
					xnp1 = xn - fx/fxp;
					if(fabs(xn-xnp1)<1e-10) break;
					xn = xnp1;
					iter+=1;
				}
				break;
			}
			case HALF_J_SQUARED_MINUS_1_MINUS_LN_J:
			default:
				xn = Jres*Jres*(pr.Lamesp+2.*pr.Gsp)/(pr.Lamesp*arg+2.*pr.Gsp*pow(Jres,4./3.));
				break;
		}
		
        // Done and xn = new B->zz = Fzz^2 = dFzz*(old Bzz)*dFzz = dFzz^2*(old Bzz),
		//    and Fzz = dFzz*(old Fzz) = 1 + ep->zz
        //cout << xn << "," << pow(Jres,2./3.)*pr.Lamesp*(xn*arg/(Jres*Jres)-1.) + 2.*pr.Gsp*(xn-pow(Jres,2./3.)) << endl;;
        double dFzz = sqrt(xn/B->zz);
        B->zz = xn;
		
		// particle strain ezz now known
		ep->zz = dFzz*(1.+ep->zz) - 1.;
        
        // incremental J changes
        detDf *= dFzz;
	}
    
    // Increment J and save it in history data
    double J = detDf*mptr->GetHistoryDble(J_History,historyOffset);
    mptr->SetHistoryDble(J_History,J,historyOffset);
	
	// for incremental energy, store initial stress
	Tensor *sporig=mptr->GetStressTensor();
	Tensor st0 = *sporig;
	
	// account for residual stresses
	double Jeff = J/Jres;
	
    // update pressure
	double p0=mptr->GetPressure();
	double Pterm = J*GetVolumetricTerms(Jeff,pr.Lamesp) + Jres*pr.Gsp*((B->xx+B->yy+B->zz)/(3.*Jres23) - 1.);
	
    // artifical viscosity
    double delV = 1. - 1./detDf;                        // total volume change
    double QAVred = 0.,AVEnergy=0.;
    if(delV<0. && artificialViscosity)
	{	QAVred = GetArtificalViscosity(delV/delTime,sqrt(pr.Ksp)*J);
        if(ConductionTask::AVHeating) AVEnergy = fabs(QAVred*delV);
    }
    double Pfinal = -Pterm + QAVred;
    
    // set the pressure
    mptr->SetPressure(Pfinal);
	
	// incremental energy - dilational part
    double avgP = 0.5*(p0+Pfinal);
    double dilEnergy = -avgP*delV;
	
	// incremental residual energy
	double delVres = 1. - 1./dJres;
	double resEnergy = -avgP*delVres;
	
    // Account for density change in specific stress
    // i.e.. Get (Kirchoff Stress)/rho0
	double GJeff = resStretch*pr.Gsp;		// = J*(Jres^(1/3) G/J) to get Kirchoff
    
	// find deviatoric (Cauchy stress)J/rho0 = deviatoric (Kirchoff stress)/rho0
	Tensor *sp=mptr->GetStressTensor();
    
    double I1third = (B->xx+B->yy+B->zz)/3.;
	sp->xx = GJeff*(B->xx-I1third);
	sp->yy = GJeff*(B->yy-I1third);
	sp->zz = GJeff*(B->zz-I1third);
	sp->xy = GJeff*B->xy;
    if(np==THREED_MPM)
	{	sp->xz = GJeff*B->xz;
        sp->yz = GJeff*B->yz;
    }
    
	// incremental work energy = shear energy
    double shearEnergy = 0.5*((sp->xx+st0.xx)*du(0,0) + (sp->yy+st0.yy)*du(1,1) + (sp->zz+st0.zz)*du(2,2)+
							  (sp->xy+st0.xy)*(du(0,1)+du(1,0)));
    if(np==THREED_MPM)
    {   shearEnergy += 0.5*((sp->xz+st0.xz)*(du(0,2)+du(2,0)) + (sp->yz+st0.yz)*(du(1,2)+du(2,1)));
    }
    
    // strain energy
    double dU = dilEnergy + shearEnergy;
    mptr->AddWorkEnergyAndResidualEnergy(dU,resEnergy);
	
	// particle isentropic temperature increment
	double Kratio;				// = rho_0 K/(rho K_0)
    double Jeff1third = pow(Jeff,1./3.);
    double Gterm = pr.Gsp*(1. - Jeff1third*Jeff1third + 2./(3.*Jeff1third));
	switch(UofJOption)
	{   case J_MINUS_1_SQUARED:
			Kratio = pr.Lamesp+Jeff + Gterm;
			break;
			
		case LN_J_SQUARED:
			Kratio = pr.Lamesp*(1-log(Jeff))/(Jeff*Jeff) + Gterm;
			break;
			
		case HALF_J_SQUARED_MINUS_1_MINUS_LN_J:
		default:
			Kratio = 0.5*(Jeff + 1./Jeff);
			break;
	}
    Kratio /= pr.Ksp;
    double dTq0 = -J*Kratio*gamma0*mptr->pPreviousTemperature*delV;
    
    // thermodynamics heat and temperature
	IncrementHeatEnergy(mptr,res->dT,dTq0,QAVred);
}
Exemple #5
0
/* Take increments in strain and calculate new Particle: strains, rotation strain,
        stresses, strain energy,
    dvij are (gradient rates X time increment) to give deformation gradient change
    For Axisymmetry: x->R, y->Z, z->theta, np==AXISYMMETRIC_MPM, otherwise dvzz=0
    This material tracks pressure and stores deviatoric stress only in particle stress
        tensor
*/
void Mooney::MPMConstitutiveLaw(MPMBase *mptr,Matrix3 du,double delTime,int np,void *properties,
								ResidualStrains *res,int historyOffset) const
{
	// incremental energy, store initial stress
	Tensor *sporig=mptr->GetStressTensor();
	Tensor st0 = *sporig;
	
	// Update strains and rotations and Left Cauchy strain
	double detDf = IncrementDeformation(mptr,du,NULL,np);
    
    // get pointer to new left Cauchy strain
    Tensor *B = mptr->GetAltStrainTensor();
	
    // account for residual stresses
	double dJres = GetIncrementalResJ(mptr,res);
	double Jres = dJres*mptr->GetHistoryDble(J_History+1,historyOffset);
	mptr->SetHistoryDble(J_History+1,Jres,historyOffset);

	// Deformation gradients and Cauchy tensor differ in plane stress
	if(np==PLANE_STRESS_MPM)
	{	// Find B->zz required to have zero stress in z direction
		
		// fixed arguments
		double arg = B->xx*B->yy - B->xy*B->xy;
		double arg12 = sqrt(arg);
		double arg16 = pow(arg,1./6.);
		double arg2 = B->xx+B->yy;
		
		// Newton-Rapheson starting at B.zz = 1
		// In tests finds answer in 3 or less steps
		Tensor *ep=mptr->GetStrainTensor();
		double xn16,xn12,xnp1,xn = (1.+ep->zz)*(1.+ep->zz);
		double fx,fxp,J13,J0,J2,Jeff;
		int iter=1;
        double mJ2P,mdJ2PdJ;
        
        // solution for B.zz in xn and J = sqrt(xn*arg) with dJ/dxn = arg/(2 sqrt(xn*arg))
        // Solving f=0 where f = 3J^2 Kterm + Jres*G1(2*xn-arg2)J^(1/3) + Jres*G2(xn*arg2 - 2*arg)/J^(1/3)
		//			where J^(1/3) = (xn*arg)^(1/6)
		// df/dxn = d(3J^2 Kterm)/dJ dJ/dxn
		//				+ Jres*G1((14*xn-arg2)/(6*xn))J^(1/3)
		//				+ Jres*G2((5*xn*arg2+2*arg)/(6*xn))/J^(1/3)
		while(iter<20)
		{	xn16 = pow(xn,1./6.);
			xn12 = sqrt(xn);
			J13 = xn16*arg16;
			J0 = xn12*arg12;
			J2 = J0*J0;
            Jeff = J0/Jres;
            
            // get f and df/dxn
            GetNewtonPressureTerms(Jeff, Ksp, mJ2P, mdJ2PdJ);
            fx = 3.*Jres*mJ2P + G1sp*(2.*xn-arg2)*J13 + G2sp*(xn*arg2-2.*arg)/J13;
            fxp = (1.5*J0/xn)*mdJ2PdJ + G1sp*J13*(14.*xn-arg2)/(6.*xn) + G2sp*(2.*arg+5.*xn*arg2)/(6.*J13*xn);
            
            // new prediction for solution
			xnp1 = xn - fx/fxp;
			//cout << iter << ": " << xn << "," << xnp1 << "," << fabs(xn-xnp1) << endl;
			if(fabs(xn-xnp1)<1e-10) break;
			xn = xnp1;
			iter+=1;
		}
        
        if(iter>=20) cout << "# Not enough iterations in plane stress Mooney-Rivlin material" << endl;
        
        // Done and xn = new B->zz = Fzz^2 = dFzz*(old Bzz)*dFzz = dFzz^2*(old Bzz),
		//    and Fzz = dFzz*(old Fzz) = 1 + ep->zz
        double dFzz = sqrt(xn/B->zz);
        B->zz = xn;
		
		// particle strain ezz now known
		ep->zz = dFzz*(1.+ep->zz) - 1.;
        
        // incremental J changes
        detDf *= dFzz;
	}
    
    // Increment J and save it in history data
    double J = detDf*mptr->GetHistoryDble(J_History,historyOffset);
    mptr->SetHistoryDble(J_History,J,historyOffset);
	
	// account for residual stresses
	double Jeff = J/Jres;
	
    // update pressure
	double p0=mptr->GetPressure();
	double Kterm = J*GetVolumetricTerms(Jeff,Ksp);       // times J to get Kirchoff stress
	
    // artifical viscosity
    double delV = 1. - 1./detDf;                        // total volume change
    double QAVred = 0.,AVEnergy=0.;
    if(delV<0. && artificialViscosity)
	{	QAVred = GetArtificalViscosity(delV/delTime,sqrt(Ksp*J),mptr);
        if(ConductionTask::AVHeating) AVEnergy = fabs(QAVred*delV);
    }
    double Pfinal = -Kterm + QAVred;
    
    // set the pressure
    mptr->SetPressure(Pfinal);
	
	// incremental energy - dilational part
    double avgP = 0.5*(p0+Pfinal);
    double dilEnergy = -avgP*delV;
	
	// incremental residual energy
	double delVres = 1. - 1./dJres;
	double resEnergy = -avgP*delVres;
	
    // Account for density change in specific stress
    // i.e.. Get (Cauchy Stress)/rho = J*(Cauchy Stress)/rho0 = (Kirchoff Stress)/rho0
	double J23 = pow(J, 2./3.);
	double J43 = J23*J23;
	double JforG1 = J23/Jres;                   // J^(5/3)/(Jres J) = J^(2/3)/Jres to get Kirchoff stress
	double JforG2 = J43/Jres;                   // J^(7/3)/(Jres J) = J^(4/3)/Jres to get Kirchoff stress
	
	//JforG1 *= Jres;			// this uses Jeff to get Kirchoff stress
	//JforG2 *= Jres;			// this uses Jeff to get Kirchoff stress
    
	// find deviatoric (Cauchy stress)J/rho0 = deviatoric (Kirchoff stress)/rho0
	Tensor *sp=mptr->GetStressTensor();
    
	sp->xx = (2*B->xx-B->yy-B->zz)*G1sp/(3.*JforG1)
            + (B->xx*(B->yy+B->zz)-2*B->yy*B->zz-B->xy*B->xy)*G2sp/(3.*JforG2);
	sp->yy = (2*B->yy-B->xx-B->zz)*G1sp/(3.*JforG1)
            + (B->yy*(B->xx+B->zz)-2*B->xx*B->zz-B->xy*B->xy)*G2sp/(3.*JforG2);
	sp->zz = (2*B->zz-B->xx-B->yy)*G1sp/(3.*JforG1)
            + (B->zz*(B->xx+B->yy)-2*B->xx*B->yy+2.*B->xy*B->xy)*G2sp/(3.*JforG2);
	sp->xy = B->xy*G1sp/JforG1 + (B->zz*B->xy)*G2sp/JforG2;
    
    if(np==THREED_MPM)
    {   sp->xx += (2.*B->yz*B->yz-B->xz*B->xz)*G2sp/(3.*JforG2);
        sp->yy += (2.*B->xz*B->xz-B->yz*B->yz)*G2sp/(3.*JforG2);
        sp->zz -= (B->xz*B->xz+B->yz*B->yz)*G2sp/(3.*JforG2);
        sp->xy -= B->xz*B->yz*G2sp/JforG2;
	    sp->xz = B->xz*G1sp/JforG1 + (B->yy*B->xz-B->xy*B->yz)*G2sp/JforG2;
        sp->yz = B->yz*G1sp/JforG1 + (B->xx*B->yz-B->xy*B->xz)*G2sp/JforG2;
    }
    
	// incremental work energy = shear energy
    double shearEnergy = 0.5*((sp->xx+st0.xx)*du(0,0) + (sp->yy+st0.yy)*du(1,1) + (sp->zz+st0.zz)*du(2,2)+
							  (sp->xy+st0.xy)*(du(0,1)+du(1,0)));
    if(np==THREED_MPM)
    {   shearEnergy += 0.5*((sp->xz+st0.xz)*(du(0,2)+du(2,0)) + (sp->yz+st0.yz)*(du(1,2)+du(2,1)));
    }
    
    // strain energy
    double dU = dilEnergy + shearEnergy;
    mptr->AddWorkEnergyAndResidualEnergy(dU,resEnergy);
	
    // thermodynamics depends on whether or not this is a rubber
	double dTq0;
    if(rubber)
    {   // convert internal energy to temperature change
		dTq0 = dU/GetHeatCapacity(mptr);
	}
	else
	{	// elastic particle isentropic temperature increment
		double Kratio;				// = rho_0 K/(rho K_0)
		switch(UofJOption)
		{   case J_MINUS_1_SQUARED:
				Kratio = Jeff;
				break;
				
			case LN_J_SQUARED:
				Kratio = (1-log(Jeff))/(Jeff*Jeff);
				break;
				
			case HALF_J_SQUARED_MINUS_1_MINUS_LN_J:
			default:
				Kratio = 0.5*(Jeff + 1./Jeff);
				break;
		}
		dTq0 = -J*Kratio*gamma0*mptr->pPreviousTemperature*delV;
	}
	IncrementHeatEnergy(mptr,res->dT,dTq0,QAVred);
}