// 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; } }
// 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.); }
/* 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); }
/* 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); }