//Jacobian for stress update algorithm void FiniteStrainPlasticMaterial::getJac(RankTwoTensor sig, RankFourTensor E_ijkl, Real flow_incr, RankFourTensor* dresid_dsig) { RankTwoTensor sig_dev, flow_tensor, flow_dirn; RankTwoTensor dfi_dft,dfi_dsig; RankFourTensor dft_dsig,dfd_dft,dfd_dsig; Real sig_eqv/*,val*/; Real f1,f2,f3; RankFourTensor temp; sig_dev=getSigDev(sig); sig_eqv=getSigEqv(sig); getFlowTensor(sig,&flow_tensor); flow_dirn=flow_tensor; f1=3.0/(2.0*sig_eqv); f2=f1/3.0; f3=9.0/(4.0*pow(sig_eqv,3.0)); for (int i=0;i<3;i++) for (int j=0;j<3;j++) for (int k=0;k<3;k++) for (int l=0;l<3;l++) dft_dsig(i,j,k,l)=f1*deltaFunc(i,k)*deltaFunc(j,l)-f2*deltaFunc(i,j)*deltaFunc(k,l)-f3*sig_dev(i,j)*sig_dev(k,l); dfd_dsig=dft_dsig; *dresid_dsig=E_ijkl.invSymm()+dfd_dsig*flow_incr; }
//Jacobian for stress update algorithm void FiniteStrainRatePlasticMaterial::getJac(const RankTwoTensor & sig, const RankFourTensor & E_ijkl, Real flow_incr, Real yield_stress, RankFourTensor & dresid_dsig) { unsigned i, j, k ,l; RankTwoTensor sig_dev, flow_tensor, flow_dirn,fij; RankTwoTensor dfi_dft; RankFourTensor dft_dsig, dfd_dft, dfd_dsig, dfi_dsig; Real sig_eqv; Real f1, f2, f3; Real dfi_dseqv; sig_dev = sig.deviatoric(); sig_eqv = getSigEqv(sig); getFlowTensor(sig, yield_stress, flow_tensor); flow_dirn = flow_tensor; dfi_dseqv = _ref_pe_rate * _dt * _exponent * std::pow(macaulayBracket(sig_eqv / yield_stress - 1.0), _exponent - 1.0) / yield_stress; for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dfi_dsig(i,j,k,l) = flow_dirn(i,j) * flow_dirn(k,l) * dfi_dseqv; //d_flow_increment/d_sig f1 = 0.0; f2 = 0.0; f3 = 0.0; if (sig_eqv > 1e-8) { f1 = 3.0 / (2.0 * sig_eqv); f2 = f1 / 3.0; f3 = 9.0 / (4.0 * std::pow(sig_eqv, 3.0)); } for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dft_dsig(i,j,k,l) = f1 * deltaFunc(i,k) * deltaFunc(j,l) - f2 * deltaFunc(i,j) * deltaFunc(k,l) - f3 * sig_dev(i,j) * sig_dev(k,l); //d_flow_dirn/d_sig - 2nd part dfd_dsig = dft_dsig; //d_flow_dirn/d_sig dresid_dsig = E_ijkl.invSymm() + dfd_dsig * flow_incr + dfi_dsig; //Jacobian }
//Jacobian for stress update algorithm void FiniteStrainRatePlasticMaterial::getJac(const RankTwoTensor & sig, const RankFourTensor & E_ijkl, Real flow_incr, Real yield_stress, RankFourTensor & dresid_dsig) { RankTwoTensor sig_dev, flow_tensor, flow_dirn,fij; RankTwoTensor dfi_dft; RankFourTensor dfd_dft, dfd_dsig, dfi_dsig; Real sig_eqv; Real f1, f2, f3; Real dfi_dseqv; sig_dev = sig.deviatoric(); sig_eqv = getSigEqv(sig); getFlowTensor(sig, yield_stress, flow_tensor); flow_dirn = flow_tensor; dfi_dseqv = _ref_pe_rate * _dt * _exponent * std::pow(macaulayBracket(sig_eqv / yield_stress - 1.0), _exponent - 1.0) / yield_stress; dfi_dsig = flow_dirn.outerProduct(flow_dirn) * dfi_dseqv; //d_flow_increment/d_sig f1 = 0.0; f2 = 0.0; f3 = 0.0; if (sig_eqv > 1e-8) { f1 = 3.0 / (2.0 * sig_eqv); f2 = f1 / 3.0; f3 = 9.0 / (4.0 * std::pow(sig_eqv, 3.0)); } dfd_dsig = f1 * _deltaMixed - f2 * _deltaOuter - f3 * sig_dev.outerProduct(sig_dev); //d_flow_dirn/d_sig - 2nd part //Jacobian dresid_dsig = E_ijkl.invSymm() + dfd_dsig * flow_incr + dfi_dsig; }
void RedbackMechMaterialCC::getJac(const RankTwoTensor & sig, const RankFourTensor & E_ijkl, Real flow_incr, Real sig_eqv, Real pressure, Real p_yield_stress, Real q_yield_stress, Real pc, RankFourTensor & dresid_dsig) { unsigned i, j, k, l; RankTwoTensor sig_dev, flow_dirn_vol, flow_dirn_dev, fij, flow_dirn, flow_tensor; RankTwoTensor dfi_dft; RankFourTensor dfd_dsig, dfi_dsig; Real f1, f2; Real dfi_dseqv_dev, dfi_dseqv_vol, dfi_dseqv; pc *= -1; sig_dev = sig.deviatoric(); dfi_dseqv = getDerivativeFlowIncrement(sig, pressure, sig_eqv, pc, q_yield_stress, p_yield_stress); getFlowTensor(sig, sig_eqv, pressure, pc, flow_dirn); /* The following calculates the tensorial derivative (Jacobian) of the residual with respect to stress, dr_dsig * It consists of two terms: The first is * dr_dsig = (dfi_dseqv_dev*flow_dirn_dev(k,l)) * flow_dirn_dev(i,j) * which is the tensorial product of the flow increment tensor times the flow direction tensor * * The second is the product of the flow increment tensor times the derivative of the flow direction tensor * with respect to the stress tensor. See also REDBACK's documentation * */ // This loop calculates the first term for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dfi_dsig(i, j, k, l) = flow_dirn(i, j) * flow_dirn(k, l) * dfi_dseqv; // Real flow_tensor_norm = flow_dirn.L2norm(); // This loop calculates the second term. Read REDBACK's documentation // (same as J2 plasticity case) f1 = 0.0; f2 = 0.0; if (sig_eqv > 1e-8) { f1 = 3.0 / (_slope_yield_surface * _slope_yield_surface); f2 = 2.0 / 9.0 - 1.0 / (_slope_yield_surface * _slope_yield_surface); } for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dfd_dsig(i, j, k, l) = f1 * deltaFunc(i, k) * deltaFunc(j, l) - f2 * deltaFunc(i, j) * deltaFunc(k, l); // d_flow_dirn/d_sig - 2nd part (J2 plasticity) // dfd_dsig = dft_dsig1/flow_tensor_norm - 3.0 * dft_dsig2 / // (2*sig_eqv*flow_tensor_norm*flow_tensor_norm*flow_tensor_norm); //d_flow_dirn/d_sig // TODO: check if the previous two lines (i.e normalizing the flow vector) should be activated or not. Currently we // are using the non-unitary flow vector dresid_dsig = E_ijkl.invSymm() + dfd_dsig * flow_incr + dfi_dsig; // Jacobian }
/* *Solves for incremental plastic rate of deformation tensor and stress in unrotated frame. *Input: Strain incrment, 4th order elasticity tensor, stress tensor in previous incrmenent and *plastic rate of deformation tensor gradient. */ void FiniteStrainPlasticMaterial::solveStressResid(RankTwoTensor sig_old,RankTwoTensor delta_d,RankFourTensor E_ijkl, RankTwoTensor *dp, RankTwoTensor *sig) { RankTwoTensor sig_new,delta_dp,dpn; RankTwoTensor flow_tensor, flow_dirn; RankTwoTensor resid,ddsig; RankFourTensor dr_dsig,dr_dsig_inv; Real /*sig_eqv,*/flow_incr,f,dflow_incr; Real err1,err2,err3; unsigned int plastic_flag; unsigned int iter,maxiter=100; Real eqvpstrain,eqvpstrain_old,deqvpstrain,fq,rep; Real yield_stress; sig_new=sig_old+E_ijkl*delta_d; eqvpstrain_old=eqvpstrain=_eqv_plastic_strain_old[_qp]; yield_stress=getYieldStress(eqvpstrain); plastic_flag=isPlastic(sig_new,yield_stress);//Check of plasticity for elastic predictor if (plastic_flag==1) { iter=0; dflow_incr=0.0; flow_incr=0.0; delta_dp.zero(); deqvpstrain=0.0; sig_new=sig_old+E_ijkl*delta_d; getFlowTensor(sig_new,&flow_tensor); flow_dirn=flow_tensor; resid=flow_dirn*flow_incr-delta_dp;//Residual 1 - refer Hughes Simo f=getSigEqv(sig_new)-yield_stress;//Residual 2 - f=0 rep=-eqvpstrain+eqvpstrain_old+flow_incr;//Residual 3 rep=0 err1=resid.L2norm(); err2=fabs(f); err3=fabs(rep); while ((err1 > _rtol || err2 > _ftol || err3 > _eptol) && iter < maxiter )//Stress update iteration (hardness fixed) { iter++; getJac(sig_new,E_ijkl,flow_incr,&dr_dsig);//Jacobian dr_dsig_inv=dr_dsig.invSymm(); fq=getdYieldStressdPlasticStrain(eqvpstrain); dflow_incr=(f-flow_tensor.doubleContraction(dr_dsig_inv*resid)+fq*rep)/(flow_tensor.doubleContraction(dr_dsig_inv*flow_dirn)-fq); ddsig=dr_dsig_inv*(-resid-flow_dirn*dflow_incr); flow_incr+=dflow_incr; delta_dp-=E_ijkl.invSymm()*ddsig; sig_new+=ddsig; deqvpstrain=rep+dflow_incr; eqvpstrain+=deqvpstrain; getFlowTensor(sig_new,&flow_tensor); flow_dirn=flow_tensor; resid=flow_dirn*flow_incr-delta_dp; f=getSigEqv(sig_new)-yield_stress; rep=-eqvpstrain+eqvpstrain_old+flow_incr; err1=resid.L2norm(); err2=fabs(f); err3=fabs(rep); } if (iter>=maxiter) { _stress[_qp](2,2)=1e6; printf("Constitutive Error: Too many iterations %f %f %f \n",err1,err2, err3);//Convergence failure return; } dpn=*dp+delta_dp; } *dp=dpn;//Plastic strain in unrotated configuration *sig=sig_new; _eqv_plastic_strain[_qp]=eqvpstrain; }
void RedbackMechMaterialCC::getJac(const RankTwoTensor & sig, const RankFourTensor & E_ijkl, Real flow_incr, Real sig_eqv, Real pressure, Real p_yield_stress, Real q_yield_stress, Real yield_stress, RankFourTensor & dresid_dsig) { unsigned i, j, k, l; RankTwoTensor sig_dev, flow_dirn_vol, flow_dirn_dev, fij, flow_dirn, flow_tensor; RankTwoTensor dfi_dft; RankFourTensor dfd_dsig, dfi_dsig; Real f1, f2, f3; Real dfi_dp, dfi_dseqv; Real pc = -yield_stress; sig_dev = sig.deviatoric(); getDerivativeFlowIncrement(dfi_dp, dfi_dseqv, sig, pressure, sig_eqv, pc, q_yield_stress, p_yield_stress); getFlowTensor(sig, sig_eqv, pressure, q_yield_stress, p_yield_stress, yield_stress, flow_dirn); /* The following calculates the tensorial derivative (Jacobian) of the *residual with respect to stress, dr_dsig * It consists of two terms: The first is * dr_dsig = (dfi_dseqv_dev*flow_dirn_dev(k,l)) * flow_dirn_dev(i,j) * which is the tensorial product of the flow increment tensor times the flow *direction tensor * * The second is the product of the flow increment tensor times the derivative *of the flow direction tensor * with respect to the stress tensor. See also REDBACK's documentation * */ f1 = 0.0; f2 = 0.0; f3 = 0.0; if (sig_eqv > 1e-10) { f1 = 3.0 / (_slope_yield_surface * _slope_yield_surface); f2 = 2.0 / 9.0 - 1.0 / (_slope_yield_surface * _slope_yield_surface); f3 = 3.0 / (2.0 * sig_eqv); } // This loop calculates the first term for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dfi_dsig(i, j, k, l) = flow_dirn(i, j) * (f3 * sig_dev(k, l) * dfi_dseqv + dfi_dp * deltaFunc(k, l) / 3.0); // This loop calculates the second term. for (i = 0; i < 3; ++i) for (j = 0; j < 3; ++j) for (k = 0; k < 3; ++k) for (l = 0; l < 3; ++l) dfd_dsig(i, j, k, l) = f1 * deltaFunc(i, k) * deltaFunc(j, l) + f2 * deltaFunc(i, j) * deltaFunc(k, l); dresid_dsig = E_ijkl.invSymm() + dfd_dsig * flow_incr + dfi_dsig; // Jacobian }
/* *Solves for incremental plastic rate of deformation tensor and stress in unrotated frame. *Input: Strain incrment, 4th order elasticity tensor, stress tensor in previous incrmenent and *plastic rate of deformation tensor. */ void FiniteStrainRatePlasticMaterial::returnMap(const RankTwoTensor & sig_old, const RankTwoTensor & delta_d, const RankFourTensor & E_ijkl, RankTwoTensor & dp, RankTwoTensor & sig) { RankTwoTensor sig_new, delta_dp, dpn; RankTwoTensor flow_tensor, flow_dirn; RankTwoTensor resid,ddsig; RankFourTensor dr_dsig, dr_dsig_inv; Real flow_incr, flow_incr_tmp; Real err1, err3, tol1, tol3; unsigned int iterisohard, iter, maxiterisohard = 20, maxiter = 50; Real eqvpstrain; Real yield_stress, yield_stress_prev; tol1 = 1e-10; tol3 = 1e-6; iterisohard = 0; eqvpstrain = std::pow(2.0/3.0,0.5) * dp.L2norm(); yield_stress = getYieldStress(eqvpstrain); err3 = 1.1 * tol3; while (err3 > tol3 && iterisohard < maxiterisohard) //Hardness update iteration { iterisohard++; iter = 0; delta_dp.zero(); sig_new = sig_old + E_ijkl * delta_d; flow_incr=_ref_pe_rate*_dt * std::pow(macaulayBracket(getSigEqv(sig_new) / yield_stress - 1.0), _exponent); getFlowTensor(sig_new, yield_stress, flow_tensor); flow_dirn = flow_tensor; resid = flow_dirn * flow_incr - delta_dp; err1 = resid.L2norm(); while (err1 > tol1 && iter < maxiter) //Stress update iteration (hardness fixed) { iter++; getJac(sig_new, E_ijkl, flow_incr, yield_stress, dr_dsig); //Jacobian dr_dsig_inv = dr_dsig.invSymm(); ddsig = -dr_dsig_inv * resid; sig_new += ddsig; //Update stress delta_dp -= E_ijkl.invSymm() * ddsig; //Update plastic rate of deformation tensor flow_incr_tmp = _ref_pe_rate * _dt * std::pow(macaulayBracket(getSigEqv(sig_new) / yield_stress - 1.0), _exponent); if (flow_incr_tmp < 0.0) //negative flow increment not allowed mooseError("Constitutive Error-Negative flow increment: Reduce time increment."); flow_incr = flow_incr_tmp; getFlowTensor(sig_new, yield_stress, flow_tensor); flow_dirn = flow_tensor; resid = flow_dirn * flow_incr - delta_dp; //Residual err1=resid.L2norm(); } if (iter>=maxiter)//Convergence failure mooseError("Constitutive Error-Too many iterations: Reduce time increment.\n"); //Convergence failure dpn = dp + delta_dp; eqvpstrain = std::pow(2.0/3.0, 0.5) * dpn.L2norm(); yield_stress_prev = yield_stress; yield_stress = getYieldStress(eqvpstrain); err3 = std::abs(yield_stress-yield_stress_prev); } if (iterisohard>=maxiterisohard) mooseError("Constitutive Error-Too many iterations in Hardness Update:Reduce time increment.\n"); //Convergence failure dp = dpn; //Plastic rate of deformation tensor in unrotated configuration sig = sig_new; }