std::vector<XYZ> Gauss::Integrate(const ValueField values) { // Pre- condition int m = values.size(); int n = values[0].size(); assert( m == m_ && n == n_ ); // define std::vector<XYZ> force(num_facenodes_); // normal XYZ normal = Func::GetNormalOf(face_); // area double area = std::sqrt( normal * normal ); // normalization normal = normal / std::sqrt( normal * normal ); for(int inode=0; inode<num_facenodes_; inode++){ for(int i=0; i<m; i++){ for(int j=0; j<n; j++){ XYZ tmp; tmp = -normal * area * 0.25 * Wi_[i] * Wj_[j]; tmp = tmp * values[i][j]; tmp = tmp * ShapeFunction(inode, xi_[i], et_[j]); force.at(inode) += tmp; } } } return force; }
// Take stress at 9 gauss points and map them to 9 nodes in this element // by using coordinate system on the gauss points (numbered as element as // 1,7,9,3,4,8,6,2,5) as mapping to -1 to 1 coordinates. // sgp[i][j] is stress j (1 to 4) at Gauss point i (1 to numGauss) // se[i][j] is output stress j (1 to 4) at node i (1 to numnds) (externed variable) void Lagrange2D::ExtrapolateGaussStressToNodes(double sgp[][5]) { double gpt = 1./0.7745966692414834; double temp,sfxn[10]; int i,j,k; Vector xi; // loop over 9 nodes for(i=1;i<=9;i++) { if(i==1 || i==8 || i==4) xi.x = -gpt; else if(i==5 || i==9 || i==7) xi.x = 0.; else xi.x = gpt; if(i==1 || i==5 || i==2) xi.y = -gpt; else if(i==8 || i==9 || i==6) xi.y = 0.; else xi.y = gpt; ShapeFunction(&xi,FALSE,sfxn,NULL,NULL,NULL,NULL,NULL,NULL); for(j=1;j<=4;j++) { temp=0.; for(k=0;k<9;k++) temp+=sfxn[k]*sgp[gaussOrder[k]][j]; se[i][j] = temp; } } }
void ElementBase::GetShapeFunctionsForCracks(int *numnds,double *fn,int *nds,Vector *pos) const { #ifdef CRACK_POINT Vector xipos; GetNodes(numnds,nds); GetXiPos(pos,&xipos); ShapeFunction(&xipos,FALSE,&fn[1],NULL,NULL,NULL); #else Vector xipos,lp; int ndIDs[maxShapeNodes]; switch(useGimp) { case POINT_GIMP: // Load element noodes, dimensionless position, and shape functinos GetNodes(numnds,nds); GetXiPos(pos,&xipos); ShapeFunction(&xipos,FALSE,&fn[1],NULL,NULL,NULL); break; case LINEAR_CPDI: case QUADRATIC_CPDI: // since no material point, CPDI uses GIMP method case UNIFORM_GIMP: GetXiPos(pos,&xipos); lp.x = mpmgrid.GetParticleSemiLength(); lp.y = lp.x; lp.z = lp.x; GetGimpNodes(numnds,nds,ndIDs,&xipos,lp); GimpShapeFunction(&xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); GimpCompact(numnds,nds,fn,NULL,NULL,NULL); break; case LINEAR_CPDI_AS: // since no material point, CPDI uses GIMP method case UNIFORM_GIMP_AS: GetXiPos(pos,&xipos); lp.x = mpmgrid.GetParticleSemiLength(); lp.y = lp.x; lp.z = lp.x; GetGimpNodes(numnds,nds,ndIDs,&xipos,lp); GimpShapeFunctionAS(&xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); GimpCompact(numnds,nds,fn,NULL,NULL,NULL); break; } #endif }
/* Just get nodes and shape functions Load number of nodes into numnds Load node numbers into nds[1]... Load shape functions into fn[1]... See other GetShapeFunctions() if need to change NOTE: This is called at various places in the time step when shape functions are needed. It should recalculate the ones found at the begnning of the time step using precalculated xipos or CPDI info, which are found in initialization throws CommonException() if too many CPDI nodes */ void ElementBase::GetShapeFunctions(int *numnds,double *fn,int *nds,MPMBase *mpmptr) const { Vector lp; switch(useGimp) { case POINT_GIMP: // load coordinates if not already done GetNodes(numnds,nds); ShapeFunction(mpmptr->GetNcpos(),FALSE,&fn[1],NULL,NULL,NULL); break; case UNIFORM_GIMP: { // GIMP analysis int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); GimpShapeFunction(xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); GimpCompact(numnds,nds,fn,NULL,NULL,NULL); break; } case UNIFORM_GIMP_AS: { // GIMP analysis int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); GimpShapeFunctionAS(xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); GimpCompact(numnds,nds,fn,NULL,NULL,NULL); break; } case LINEAR_CPDI: case LINEAR_CPDI_AS: case QUADRATIC_CPDI: { if(theMaterials[mpmptr->MatID()]->Rigid()) { // GIMP analysis int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); if(fmobj->IsAxisymmetric()) GimpShapeFunctionAS(xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); else GimpShapeFunction(xipos,*numnds,ndIDs,FALSE,&fn[1],NULL,NULL,NULL,lp); GimpCompact(numnds,nds,fn,NULL,NULL,NULL); } else { *numnds = GetCPDIFunctions(nds,fn,NULL,NULL,NULL,mpmptr); } break; } } }
// Find Cartesion position from natural coordinates void ElementBase::GetPosition(Vector *xipos,Vector *xyzpos) { double fn[MaxElNd]; ShapeFunction(xipos,FALSE,&fn[1],NULL,NULL,NULL); int i; ZeroVector(xyzpos); for(i=1;i<=NumberNodes();i++) { xyzpos->x += fn[i]*nd[nodes[i-1]]->x; xyzpos->y += fn[i]*nd[nodes[i-1]]->y; xyzpos->z += fn[i]*nd[nodes[i-1]]->z; } }
XYZ Gauss::GetGaussPoint(const int i, const int j) { // Pre- condition assert( i > -1 && j > -1 ); assert( i < m_ && j < n_ ); XYZ grid(0,0,0); for(int inode=0; inode<num_facenodes_; inode++){ grid += face_.nodes(inode).grid() * ShapeFunction(inode, xi_[i], et_[j]); } return grid; }
/* Find dimensionless coordinates by numerical methods input: pos is position in the element output: xipos is dimensionless position only used in MPM and only here if non-rectangular elements */ void ElementBase::GetXiPos(Vector *pos,Vector *xipos) const { double xt,yt,dxxi,dxeta,dyxi,dyeta; double deter,dxi,deta,dist; double gfn[MaxElNd],gdfnxi[MaxElNd],gdfnet[MaxElNd]; int numnds=NumberNodes(),i,j; // initial guess GetCentroid(xipos); // nodal coordinates Vector eNode[MaxElNd]; for(i=0;i<numnds;i++) { eNode[i].x=nd[nodes[i]]->x; eNode[i].y=nd[nodes[i]]->y; } /* solve for xipos using Newton-Rapheson (see FEA Notes) using shape functions and their derivatives */ for(j=1;j<=MAXITER;j++) { ShapeFunction(xipos,TRUE,gfn,gdfnxi,gdfnet,NULL,NULL,NULL,NULL); xt=-pos->x; yt=-pos->y; dxxi=0.; dxeta=0.; dyxi=0.; dyeta=0.; for(i=0;i<numnds;i++) { xt+=eNode[i].x*gfn[i]; yt+=eNode[i].y*gfn[i]; dxxi+=eNode[i].x*gdfnxi[i]; dxeta+=eNode[i].x*gdfnet[i]; dyxi+=eNode[i].y*gdfnxi[i]; dyeta+=eNode[i].y*gdfnet[i]; } deter=dxxi*dyeta-dxeta*dyxi; dxi=(-xt*dyeta+yt*dxeta)/deter; deta=(xt*dyxi-yt*dxxi)/deter; xipos->x+=dxi; xipos->y+=deta; dist=sqrt(dxi*dxi+deta*deta); if(dist<.001) break; } }
/* Calculate Stiffness Matrix */ void Interface2D::Stiffness(int np) { double fn[MaxElNd],temp,asr; Vector xi; // Load nodal coordinates (ce[]) and material props (pr.C[][]) GetProperties(np); // Zero stiffness (se[][]) and reaction (re[]) ZeroUpperHalfStiffness(); // basic parameters */ MaterialBase *matl=theMaterials[material-1]; double Dn=matl->pr.C[1][1]; double Dt=matl->pr.C[1][2]; double xpxi=(ce[2].x-ce[1].x)/2; double ypxi=(ce[2].y-ce[1].y)/2; double dlxi=sqrt(xpxi*xpxi + ypxi*ypxi); int i; for(i=0;i<GAUSS_INT_PTS;i++) { // get shape function at next xi xi.x=gxi[i]; ShapeFunction(&xi,FALSE,&fn[1],NULL,NULL,&ce[1],NULL,&asr,NULL); // total weight if(np!=AXI_SYM) temp=gwt[i]*GetThickness(); else temp=gwt[i]*asr; // stiffness matrix is force per radian, hence no 2 pi // increment all stiffness elements at this point IncrementStiffnessElements(temp,fn,xpxi,ypxi,dlxi,Dn,Dt); } // Fill in lower half of stiffness matrix FillLowerHalfStiffness(); }
// by non-element methods that need access to grid shape functions only, and those methods are protected void ElementBase::GridShapeFunctions(int *numnds,int *nds,Vector *xipos,double *fn) const { GetNodes(numnds,nds); ShapeFunction(xipos,FALSE,&fn[1],NULL,NULL,NULL); }
// return dimensionless location for material points void ElementBase::MPMPoints(short numPerElement,Vector *mpos) const { int i,j,k; double fxn[MaxElNd],row,zrow; if(NumberSides()==4) { switch(numPerElement) { case 4: // ENI or FNI - 2D only mpos[0].x=-.5; mpos[0].y=-.5; mpos[0].z=0.; mpos[1].x=.5; mpos[1].y=-.5; mpos[1].z=0.; mpos[2].x=-.5; mpos[2].y=.5; mpos[2].z=0.; mpos[3].x=.5; mpos[3].y=.5; mpos[3].z=0.; break; case 1: // CM of square or brick mpos[0].x=0.; mpos[0].y=0.; mpos[0].z=0.; break; case 8: // 3D box mpos[0].x=-.5; mpos[0].y=-.5; mpos[0].z=-.5; mpos[1].x=.5; mpos[1].y=-.5; mpos[1].z=-.5; mpos[2].x=-.5; mpos[2].y=.5; mpos[2].z=-.5; mpos[3].x=.5; mpos[3].y=.5; mpos[3].z=-.5; mpos[4].x=-.5; mpos[4].y=-.5; mpos[4].z=.5; mpos[5].x=.5; mpos[5].y=-.5; mpos[5].z=.5; mpos[6].x=-.5; mpos[6].y=.5; mpos[6].z=.5; mpos[7].x=.5; mpos[7].y=.5; mpos[7].z=.5; break; case 9: // 2D k=0; row = -2./3.; for(j=0;j<3;j++) { mpos[k].x=-2./3.; mpos[k].y=row; mpos[k].z=0.; mpos[k+1].x=0.; mpos[k+1].y=row; mpos[k+1].z=0.; mpos[k+2].x=2./3.; mpos[k+2].y=row; mpos[k+2].z=0.; k += 3; row += 2./3.; } break; case 16: // 2D k=0; row = -0.75; for(j=0;j<4;j++) { mpos[k].x=-0.75; mpos[k].y=row; mpos[k].z=0.; mpos[k+1].x=-.25; mpos[k+1].y=row; mpos[k+1].z=0.; mpos[k+2].x=.25; mpos[k+2].y=row; mpos[k+2].z=0.; mpos[k+3].x=.75; mpos[k+3].y=row; mpos[k+3].z=0.; k += 4; row += 0.5; } break; case 25: // 2D k=0; row = -0.8; for(j=0;j<5;j++) { mpos[k].x=-0.8; mpos[k].y=row; mpos[k].z=0.; mpos[k+1].x=-.4; mpos[k+1].y=row; mpos[k+1].z=0.; mpos[k+2].x=0.; mpos[k+2].y=row; mpos[k+2].z=0.; mpos[k+3].x=.4; mpos[k+3].y=row; mpos[k+3].z=0.; mpos[k+4].x=.8; mpos[k+4].y=row; mpos[k+4].z=0.; k += 5; row += 0.4; } break; case 27: // 3D k=0; zrow = -2./3.; for(i=0;i<3;i++) { row = -2./3.; for(j=0;j<3;j++) { mpos[k].x=-2./3.; mpos[k].y=row; mpos[k].z=zrow; mpos[k+1].x=0.; mpos[k+1].y=row; mpos[k+1].z=zrow; mpos[k+2].x=2./3.; mpos[k+2].y=row; mpos[k+2].z=zrow; k += 3; row += 2./3.; } zrow += 2./3.; } break; default: throw CommonException("Invalid number of material points per element.","ElementBase::MPMPoints"); break; } } // covert to x-y-z locations for(k=0;k<numPerElement;k++) { ShapeFunction(&mpos[k],FALSE,fxn,NULL,NULL,NULL); ZeroVector(&mpos[k]); for(j=0;j<NumberNodes();j++) { mpos[k].x+=nd[nodes[j]]->x*fxn[j]; mpos[k].y+=nd[nodes[j]]->y*fxn[j]; mpos[k].z+=nd[nodes[j]]->z*fxn[j]; } } }
/* Do several element things at once Load number of nodes into numnds Load node numbers into nds[1]... Load shape functions into fn[1]... Load shape function derviatives into xDeriv[1]..., yDeriv[1]..., zDeriv[1]... For axisymmetric load zDeriv with shape function / particle radial position Input zDeriv must not be NULL Input: pointer to material point dimensionless position NOTE: This is called at various places in the time step when gradients are needed. It should recalculate the ones found at the beginning of the time step using the precalculated xipos or CPDI info, which are found in the initialization task throws CommonException() if too many CPDI nodes */ void ElementBase::GetShapeGradients(int *numnds,double *fn,int *nds, double *xDeriv,double *yDeriv,double *zDeriv,MPMBase *mpmptr) const { Vector lp; switch(useGimp) { case POINT_GIMP: // load nodal numbers GetNodes(numnds,nds); // special case for regular mesh if(mpmgrid.GetCartesian()>0) ShapeFunction(mpmptr->GetNcpos(),TRUE,&fn[1],&xDeriv[1],&yDeriv[1],&zDeriv[1]); else { // Load element coordinates Vector ce[MaxElNd]; double fnh[MaxElNd]; GetCoordinates(ce,*numnds,nds); // find shape functions and derviatives ShapeFunction(mpmptr->GetNcpos(),BMATRIX,&fn[1],&xDeriv[1],&yDeriv[1],&ce[1],NULL,NULL,&fnh[1]); } break; case UNIFORM_GIMP: { // uGIMP analysis int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); GimpShapeFunction(xipos,*numnds,ndIDs,TRUE,&fn[1],&xDeriv[1],&yDeriv[1],&zDeriv[1],lp); GimpCompact(numnds,nds,fn,xDeriv,yDeriv,zDeriv); break; } case UNIFORM_GIMP_AS: { // uGIMP analysis int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); GimpShapeFunctionAS(xipos,*numnds,ndIDs,TRUE,&fn[1],&xDeriv[1],&yDeriv[1],&zDeriv[1],lp); GimpCompact(numnds,nds,fn,xDeriv,yDeriv,zDeriv); break; } case LINEAR_CPDI: case LINEAR_CPDI_AS: case QUADRATIC_CPDI: { if(theMaterials[mpmptr->MatID()]->Rigid()) { int ndIDs[maxShapeNodes]; Vector *xipos = mpmptr->GetNcpos(); mpmptr->GetDimensionlessSize(lp); GetGimpNodes(numnds,nds,ndIDs,xipos,lp); if(fmobj->IsAxisymmetric()) GimpShapeFunctionAS(xipos,*numnds,ndIDs,TRUE,&fn[1],&xDeriv[1],&yDeriv[1],&zDeriv[1],lp); else GimpShapeFunction(xipos,*numnds,ndIDs,TRUE,&fn[1],&xDeriv[1],&yDeriv[1],&zDeriv[1],lp); GimpCompact(numnds,nds,fn,xDeriv,yDeriv,zDeriv); } else { *numnds = GetCPDIFunctions(nds,fn,xDeriv,yDeriv,zDeriv,mpmptr); } break; } } }
/* Calculate Stiffness Matrix */ void CSTriangle::Stiffness(int np) { double detjac,asr,dv; double xiDeriv[MaxElNd],etaDeriv[MaxElNd],asbe[MaxElNd],sfxn[MaxElNd]; double bte[MxFree*MaxElNd][5],temp; double thck=thickness,deltaT; int numnds=NumberNodes(); int ind1,ind2,i,j,irow,jcol,nst=2*numnds; MaterialBase *matl=theMaterials[material-1]; Vector xi; // Load nodal coordinates (ce[]), temperature (te[]), and // material props (pr.C[][] and pr.alpha[]) GetProperties(np); // Zero upper hald element stiffness matrix (se[]) and reaction vector (re[]) for(irow=1;irow<=nst;irow++) { re[irow]=0.; for(jcol=irow;jcol<=nst;jcol++) se[irow][jcol]=0.; } /* Call shape routine to calculate element B (be,asbe) matrix and the determinant of the Jacobian - both at centriod */ xi.x=(ce[1].x+ce[2].x+ce[3].x)/3.; xi.y=(ce[1].y+ce[2].y+ce[3].y)/3.; ShapeFunction(&xi,BMATRIX,&sfxn[1],&xiDeriv[1],&etaDeriv[1],&ce[1], &detjac,&asr,&asbe[1]); /* Form matrix product BT E - exploit known sparcity of B matrix and only include multiplications by nonzero elements */ deltaT=0.; ind1=-1; if(np!=AXI_SYM) { dv=thck*detjac; for(i=1;i<=numnds;i++) { ind1=ind1+2; ind2=ind1+1; for(j=1;j<=3;j++) { bte[ind1][j]=dv*(xiDeriv[i]*matl->pr.C[1][j]+etaDeriv[i]*matl->pr.C[3][j]); bte[ind2][j]=dv*(etaDeriv[i]*matl->pr.C[2][j]+xiDeriv[i]*matl->pr.C[3][j]); } deltaT+=te[i]*sfxn[i]; } } else { dv=asr*detjac; for(i=1;i<=numnds;i++) { ind1=ind1+2; ind2=ind1+1; for(j=1;j<=4;j++) { bte[ind1][j]=dv*(xiDeriv[i]*matl->pr.C[1][j]+etaDeriv[i]*matl->pr.C[3][j] +asbe[i]*matl->pr.C[4][j]); bte[ind2][j]=dv*(etaDeriv[i]*matl->pr.C[2][j]+xiDeriv[i]*matl->pr.C[3][j]); } deltaT+=te[i]*sfxn[i]; } } /* Form stiffness matrix by getting BT E B and add in initial strains into element load vector */ for(irow=1;irow<=nst;irow++) { for(j=1;j<=3;j++) { re[irow]+=bte[irow][j]*matl->pr.alpha[j]*deltaT; } if(np!=AXI_SYM) { for(jcol=irow;jcol<=nst;jcol++) { if(IsEven(jcol)) { ind1=jcol/2; temp=bte[irow][2]*etaDeriv[ind1] +bte[irow][3]*xiDeriv[ind1]; } else { ind1=(jcol+1)/2; temp=bte[irow][1]*xiDeriv[ind1] +bte[irow][3]*etaDeriv[ind1]; } se[irow][jcol]+=temp; } } else { re[irow]+=bte[irow][4]*matl->pr.alpha[j]*deltaT; for(jcol=irow;jcol<=nst;jcol++) { if(IsEven(jcol)) { ind1=jcol/2; temp=bte[irow][2]*etaDeriv[ind1] +bte[irow][3]*xiDeriv[ind1]; } else { ind1=(jcol+1)/2; temp=+bte[irow][1]*xiDeriv[ind1] +bte[irow][3]*etaDeriv[ind1] +bte[irow][4]*asbe[ind1]; } se[irow][jcol]+=temp; } } } /* Fill in lower half of stiffness matrix */ for(irow=1;irow<=nst-1;irow++) { for(jcol=irow+1;jcol<=nst;jcol++) { se[jcol][irow]=se[irow][jcol]; } } }
/* Calculate Element forces, stresses, and strain energy */ void CSTriangle::ForceStress(double *rm,int np,int nfree) { double sgp[5],etot[5]; double temp,dv; double xiDeriv[MaxElNd],etaDeriv[MaxElNd],asbe[MaxElNd],sfxn[MaxElNd]; double detjac,asr; double thck=thickness,deltaT; int numnds=3,nst=2*numnds; int i,j,ind1,ind2,ind,indg; MaterialBase *matl=theMaterials[material-1]; Vector xi; // Load element coordinates (ce[]), noodal temperature (te[]), // and material props (pr.C[][] and pr.alpha[]) GetProperties(np); // Load nodal displacements into re[] ind=0; for(j=1;j<=numnds;j++) { indg=nfree*(nodes[j-1]-1); for(i=1;i<=nfree;i++) re[++ind]=rm[indg+i]; } // zero force at each degree of freedom (stored in se[i][7]) for(i=1;i<=nst;i++) se[i][7]=0.; // element strainEnergy strainEnergy=0.; // Zero stress and force vectors to hold results nst=2*numnds; for(i=1;i<=4;i++) sgp[i]=0.; /* Call shape routine to calculate element B (be,asbe) matrix and the determinant of the Jacobian - both at centriod */ xi.x=(ce[1].x+ce[2].x+ce[3].x)/3.; xi.y=(ce[1].y+ce[2].y+ce[3].y)/3.; ShapeFunction(&xi,BMATRIX,&sfxn[1],&xiDeriv[1],&etaDeriv[1],&ce[1], &detjac,&asr,&asbe[1]); // Evaluate volume element if(np!=AXI_SYM) dv=thck*detjac; else dv=asr*detjac; /* Evaluate etot=(B d - e0). In forming B d, avoid multiplications by zero */ deltaT=0.; for(i=1;i<=numnds;i++) deltaT+=te[i]*sfxn[i]; etot[1]=-matl->pr.alpha[1]*deltaT; etot[2]=-matl->pr.alpha[2]*deltaT; etot[3]=-matl->pr.alpha[3]*deltaT; etot[4]=-matl->pr.alpha[4]*deltaT; ind1=-1; for(i=1;i<=numnds;i++) { ind1=ind1+2; ind2=ind1+1; etot[1]+=xiDeriv[i]*re[ind1]; etot[2]+=etaDeriv[i]*re[ind2]; etot[3]+=etaDeriv[i]*re[ind1]+xiDeriv[i]*re[ind2]; if(np==AXI_SYM) etot[4]+=asbe[i]*re[ind1]; } // Multply by stiffness matrix: sig = mdm * etot if(np!=AXI_SYM) { for(i=1;i<=3;i++) { for(j=1;j<=3;j++) sgp[i]+=matl->pr.C[i][j]*etot[j]; } } else { for(i=1;i<=4;i++) { for(j=1;j<=4;j++) sgp[i]+=matl->pr.C[i][j]*etot[j]; } } // Add terms for getting integral(BT sig) which gives nodal forces ind1=-1; for(i=1;i<=numnds;i++) { ind1=ind1+2; ind2=ind1+1; temp=xiDeriv[i]*sgp[1]+etaDeriv[i]*sgp[3]; if(np==AXI_SYM) temp+=asbe[i]*sgp[4]; se[ind1][7]+=temp*dv; temp=etaDeriv[i]*sgp[2]+xiDeriv[i]*sgp[3]; se[ind2][7]+=temp*dv; } // Get initial/thermal strain contribution to strain energy temp=0.; for(i=1;i<=3;i++) temp+=sgp[i]*matl->pr.alpha[i]*deltaT; if(np==AXI_SYM) temp+=sgp[4]*matl->pr.alpha[4]*deltaT; strainEnergy-=0.5*temp*dv; /* When plane strain account for constrained 1D shrinkage effect on strain energy */ if(np==PLANE_STRAIN) strainEnergy+=0.5*matl->pr.C[4][4]*deltaT*deltaT*dv; // Add 1/2 Fd to strain energy temp=0.; for(i=1;i<=nst;i++) temp+=re[i]*se[i][7]; strainEnergy+=0.5*temp; // copy stress to all nodes for(i=1;i<=numnds;i++) { for(j=1;j<=4;j++) se[i][j]=sgp[j]; } /* For plane strain analysis, calculate sigz stress For axisymmetric, multiply force and energy by 2 pi */ if(np==PLANE_STRAIN) { for(i=1;i<=numnds;i++) se[i][4]=matl->GetStressStrainZZ(se[i][1],se[i][2],se[i][3],te[i],angle,np); } else if(np==AXI_SYM) { for(i=1;i<=nst;i++) se[i][7]*=2.*PI_CONSTANT; strainEnergy*=2*PI_CONSTANT; } }