Esempio n. 1
0
// If needed, a material can initialize particle state
// For example, ideal gas initializes to base line pressure
// Such a class must pass on the super class after its own initializations
void MaterialBase::SetInitialParticleState(MPMBase *mptr,int np) const
{
	if(isolatedSystemAndParticles)
    {   // need to add initial heat energy, because special cases in this mode
        // will ignore the Cv dT term
		double Cv = GetHeatCapacity(mptr);            // in nJ/(g-K)
		mptr->AddHeatEnergy(Cv*(mptr->pTemperature-thermal.reference));
        // initial entropy kept to zero, could add something here if ever needed
	}
}
Esempio n. 2
0
// Increment heat energy using Cv(dT-dTq0) - dPhi, where Cv*dTq0 + dPhi = Cv dTad is total
//		dispated energy (it can by provided as either a temperature rise or an energy)
// dTq0 is temperature rise due to material mechanisms if the process was adiabatic
// dPhi is dissipated energy that is converted to temperature rise
void MaterialBase::IncrementHeatEnergy(MPMBase *mptr,double dT,double dTq0,double dPhi) const
{
	double Cv = GetHeatCapacity(mptr);					// in nJ/(g-K)
	double dispEnergy = Cv*dTq0 + dPhi;                     // = Cv dTad
	
	// Isolated means no conduction and no thermal ramp (and in future if have other ways
	//		to change particle temperature, those are not active either)
	// In this mode, adiabatic has dq=0 and isothermal releases all as heat
    if(isolatedSystemAndParticles)
    {   // Here dText = 0
        // If adiabatic, dq = 0 (nothing to add)
        // If isothermal dq = -Cv dTad
		if(!ConductionTask::adiabatic)
        {   mptr->AddHeatEnergy(-dispEnergy);
            mptr->AddEntropy(-dispEnergy/mptr->pPreviousTemperature);
        }
    }
	else
	{	// For non isolated particle use dq = Cv(dT-dTad)
        // If adiabatic, the Cv dT term in next step will include Cv dTad from
        //    this step to give particle dq = 0. If isothermal, it will not and
        //    dq will be disspated heat
        double totalHeat = Cv*dT - dispEnergy;
		mptr->AddHeatEnergy(totalHeat);
        if(ConductionTask::adiabatic)
        {   double dTad = dispEnergy/Cv;
            mptr->AddEntropy(Cv*dT/mptr->pPreviousTemperature - dispEnergy/(mptr->pPreviousTemperature+dTad));
        }
        else
        {   mptr->AddEntropy(totalHeat/mptr->pPreviousTemperature);
        }
	}
    
	// The dispated energy is added here, but only if adiabatic, in which case it will be
    // converted to particle temperature rise later in the calculations. This temperature
    // change works with conduction on or off
    if(ConductionTask::adiabatic)
        mptr->AddDispEnergy(dispEnergy);
}
Esempio n. 3
0
// For Cp heat capacity in nJ/(g-K)
double MaterialBase::GetCpHeatCapacity(MPMBase *mptr) const { return GetHeatCapacity(mptr)+GetCpMinusCv(mptr); }
Esempio n. 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 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);
}
Esempio n. 5
0
								  double delTime,double &dTq0,double &AVEnergy) const
#else
void Viscoelastic::UpdatePressure(MPMBase *mptr,double delV,ResidualStrains *res,double eres,const Matrix3 *dF,
								  double delTime,double &dTq0,double &AVEnergy) const
#endif
{
	if(pressureLaw==LINEAR_PRESSURE)
	{	// pressure change
#ifdef USE_KIRCHOFF_STRESS
		double dP = (detdF-1.)*mptr->GetPressure()-J*Kered*delV;
#else
		double dP = -Kered*delV;
#endif
		
		// artifical viscosity
		// delV is total incremental volumetric strain = total Delta(V)/V
		double QAVred = 0.;
		if(delV<0. && artificialViscosity)
		{	// Wants K/rho
#ifdef USE_KIRCHOFF_STRESS
			QAVred = GetArtificalViscosity(delV/delTime,sqrt(Kered*J));
#else
			QAVred = GetArtificalViscosity(delV/delTime,sqrt(Kered));
#endif
			if(ConductionTask::AVHeating) AVEnergy += fabs(QAVred*delV);
		}
		
		// increment pressure
		mptr->IncrementPressure(dP+QAVred);
		
		// work energy is dU = -P dV + s.de(total)
		// Here do hydrostatic term
		// Work energy increment per unit mass (dU/(rho0 V0)) (nJ/g)
		double avgP = mptr->GetPressure()-0.5*dP;
		mptr->AddWorkEnergyAndResidualEnergy(-avgP*delV,-3.*avgP*eres);
		
		// Isoentropic temperature rise = -(K alpha T)/(rho Cv) (dV/V)
		dTq0 += -Kered*CTE*mptr->pPreviousTemperature*(delV+3*eres)/GetHeatCapacity(mptr);;
	}
	else
	{	// J is total volume change - may need to reference to free-swelling volume if that works
		// Note that swelling looks like a problem because the sums of strains needs to be adjusted
		//		to stress-free state
		
		// history pointer
		double **h =(double **)(mptr->GetHistoryPtr(0));
		
#ifndef USE_KIRCHOFF_STRESS
		// tracking J
		double detdF = dF->determinant();
		double J = detdF*h[mptrHistory][MGJ_HISTORY];
		h[mptrHistory][MGJ_HISTORY] = J;
#endif

		// account for residual strains (needed in tension, but must always track)
		double dJres = exp(3.*CTE*res->dT);
		double Jres = dJres*h[mptrHistory][MGJRES_HISTORY];
		h[mptrHistory][MGJRES_HISTORY] = Jres;
		
		// previous pressure
		double P,P0 = mptr->GetPressure();
		double delVMG = 1. - 1./detdF;			// (Vnp1-Vn)/Vnp1
		double Kred;
		
		// M-G EOS
		// Want specific pressure or pressure over current density (using J = rho0/rho)
		if(J<1.)
		{	// new compression J(k+1) = 1-x(k+1)
			double x = 1.-J;
			
			// compression law
			// denominator = 1 - S1*x - S2*x^2 - S3*x^3
			double denom = 1./(1. - x*(S1 + x*(S2 + x*S3)));
			
			// law not valid if denominator passes zero
			if(denom<0)
			{   
#pragma omp critical (output)
				{	cout << "# Excessive x = " << x << endl;
					mptr->Describe();
				}
			}
			
			// current effective and reduced (by rho0) bulk modulus
			Kred = C0squared*(1.-0.5*gamma0*x)*denom*denom;
			
			// Pressure from bulk modulus and an energy term
			double e = mptr->GetInternalEnergy();
#ifdef USE_KIRCHOFF_STRESS
			P = J*(Kred*x + gamma0*e);
#else
			P = Kred*x + gamma0*e;
#endif
			
			// particle isentropic temperature increment
			dTq0 += -J*gamma0*mptr->pPreviousTemperature*delVMG;
		}
		else
		{   // In tension hyperelastic law P = - K0(J-1)
			double Jeff = J/Jres;
			Kred = C0squared*Jeff;
#ifdef USE_KIRCHOFF_STRESS
			P = -J*C0squared*(Jeff-1.);
#else
			P = -C0squared*(Jeff-1.);
#endif
			
			// particle isentropic temperature increment
			double Kratio = Jeff;
			dTq0 += -J*Kratio*gamma0*mptr->pPreviousTemperature*delVMG;
		}
		
		// artifical viscosity
		// delVMG is total incremental volumetric strain = total Delta(V)/V
		double QAVred = 0.;
		if(delVMG<0. && artificialViscosity)
		{	QAVred = GetArtificalViscosity(delVMG/delTime,sqrt(Kred*J));
			if(ConductionTask::AVHeating) AVEnergy += fabs(QAVred*delVMG);
		}
		
		// set final pressure
		mptr->SetPressure(P+QAVred);
		
		// work energy is dU = -P dV + s.de(total)
		// Here do hydrostatic terms, deviatoric later
		double avgP = 0.5*(P0+P);
		double delVres = 1. - 1./dJres;
		mptr->AddWorkEnergyAndResidualEnergy(-avgP*delVMG,-avgP*delVres);
		
	}
}