def __init__(self,idx,nodelist=[]): self.index = idx self.nodes = nodelist[:] self.sfns = [qsf0,qsf1,qsf2,qsf3] self.dsfns = [[dqsf0d1,dqsf0d2],[dqsf1d1,dqsf1d2], [dqsf2d1,dqsf2d2],[dqsf3d1,dqsf3d2]] for n in self.nodes: n.add_element(self) # Gauss-point-specific data. Initialize plastic strain field # to be zero. self.gpdata = {} for p in self.gausspts(): # Data are the local gamma, the six components of plastic # strain, and the six components of the yield surface # center. self.gpdata[p]=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 ] # Use shape-functions directly to represent the stress. The # shape functions are capable of representing lower-order # objects, so in principle this should not create any # difficulties, and is convenient. They are only used on a # per-element basis, of course. mmtx = smallmatrix.SmallMatrix(4,4) rmtx = smallmatrix.SmallMatrix(4,4) mmtx.clear() rmtx.clear() for i in range(4): rmtx[i,i]=1.0 # Identity matrix. for j in range(4): res = 0.0 for p in self.gausspts(): res += self.shapefn(i,p.xi,p.zeta)* \ self.shapefn(j,p.xi,p.zeta)* \ p.weight*self.jacobian(p.xi,p.zeta) mmtx[i,j]=res r = mmtx.solve(rmtx) if r!=0: print >> sys.stderr, \ "Element mass matrix is singular, run for the hills!" else: self.s_mtx = rmtx
def ycheck(cijkl,yld,stress): eps = 1.0e-10 # Local return-mapping problem -- DOFs are, in order, # lambda, ep00,ep11,ep22,ep12,ep02,ep01 (voigt order). mtx = smallmatrix.SmallMatrix(7,7) rhs = smallmatrix.SmallMatrix(7,1) # ep = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] lmbda = 0.0 # icount = 0 while icount < 10: icount += 1 lstress = [ [ stress[i][j]-sum([ sum([ cijkl[i][j][k][l]*ep[voigt[k][l]] for l in range(3) ]) for k in range(3) ]) for j in range(3) ] for i in range(3) ] mtx.clear() rhs.clear() # Build right-hand-side, check for zeroness. rhs[0,0] = -yld.yeeld(lstress) dy = yld.dyeeld(lstress) d2y = yld.d2yeeld(lstress) for i in range(3): for j in range(i+1): rhs[voigt[i][j]+1,0] = -lmbda*dy[i][j]+ep[voigt[i][j]] # print "\nRHS: ", [ rhs[i,0] for i in range(rhs.rows()) ] mag = sum( [ rhs[i,0]**2 for i in range(rhs.rows()) ] ) if mag<eps: break # out of while loop. # Build matrix. # First row, consistency equation. for k in range(3): for l in range(3): col = voigt[k][l]+1 mtx[0,col] += sum([ sum([ -dy[i][j]*cijkl[i][j][k][l] for j in range(3) ]) for i in range(3) ]) # Subsequent rows: for i in range(3): for j in range(i+1): row = voigt[i][j]+1 # Column zero, easy. mtx[row,0]=dy[i][j] for m in range(3): for n in range(3): col = voigt[m][n]+1 diag = 0.0 if i==m and j==n: diag = 1.0 mtx[row,col] += sum([ sum([ -lmbda*d2y[i][j][k][l]*cijkl[k][l][m][n] for l in range(3) ]) for k in range(3) ])-diag # Solve the resulting linearized system. # for mtxi in range(7): # print [ mtx[mtxi,j] for j in range(7) ] rr = mtx.solve(rhs) if rr==0: # print "Increments: ", [ rhs[i,0] for i in range(7) ] lmbda += rhs[0,0] for i in range(6): ep[i] += rhs[i+1,0] # print "Soln: ", [lmbda] + [ep[i] for i in range(6)] else: print >> sys.stderr, "Error in solving in ycheck, rr=", rr # Broke out of loop. return ep
def ycheck(cijkl,yld,stress,center,gamma): eps = 1.0e-10 # Local return-mapping problem -- DOFs are, in order, # lambda, ep00,ep11,ep22,ep12,ep02,ep01 (voigt order). mtx = smallmatrix.SmallMatrix(14,14) rhs = smallmatrix.SmallMatrix(14,1) # # The variables occur in this order. lmbda = 0.0 dgamma = 0.0 ep = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] dcenter = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # icount = 0 while icount < 100: icount += 1 lstress = [ [ stress[i][j]-sum([ sum([ cijkl[i][j][k][l]*ep[voigt[k][l]] for l in range(3) ]) for k in range(3) ]) for j in range(3) ] for i in range(3) ] mtx.clear() rhs.clear() # Short for "current center"... ccenter = [ [ center[i][j]+dcenter[voigt[i][j]] for j in range(3) ] for i in range(3) ] eptensor = [ [ ep[voigt[i][j]] for j in range(3) ] for i in range(3) ] dy = yld.dyeeld(lstress,ccenter) flow = yld.flow(lstress,ccenter) dflow = yld.dflow(lstress,ccenter) ihard = yld.isohard(eptensor) dihard = yld.disohard(eptensor) khard = yld.khard(eptensor) dkhard = yld.dkhard(eptensor) # Build right-hand-side, check for zeroness. rhs[0,0] = -yld.yeeld(lstress,ccenter,gamma+dgamma) rhs[1,0] = -dgamma + ihard # rhs[1,0] = -dgamma + yld.iso_c*sq_epmag for i in range(3): for j in range(i+1): rhs[voigt[i][j]+2,0] = -lmbda*flow[i][j]+ep[voigt[i][j]] for i in range(3): for j in range(i+1): rhs[voigt[i][j]+8,0] = -dcenter[voigt[i][j]] + khard[i][j] # print "\nRHS: ", [ rhs[i,0] for i in range(rhs.rows()) ] mag = sum( [ rhs[i,0]**2 for i in range(rhs.rows()) ] ) if mag<eps: break # out of while loop. # Build matrix. # First row, consistency equation. mtx[0,1] = -1.0 # Derivative of yield function wrt delta-gamma. for k in range(3): for l in range(3): col = voigt[k][l]+2 mtx[0,col] += sum([ sum([ -dy[i][j]*cijkl[i][j][k][l] for j in range(3) ]) for i in range(3) ]) col = voigt[k][l]+8 # Derivative of yield function wrt delta-c components. mtx[0,col] -= dy[k][l] # Second row, isotropic hardening. No dependence on ccenter. mtx[1,1]=1.0 for k in range(3): for l in range(3): col = voigt[k][l]+2 mtx[1,col] += -dihard[k][l] # Third through eights rows, flow rule. for i in range(3): for j in range(i+1): row = voigt[i][j]+2 # Column zero, easy. mtx[row,0]=dy[i][j] for m in range(3): for n in range(3): col = voigt[m][n]+2 diag = 0.0 if i==m and j==n: diag = 1.0 mtx[row,col] += sum([ sum([ -lmbda*dflow[i][j][k][l]*cijkl[k][l][m][n] for l in range(3) ]) for k in range(3) ])-diag col = voigt[m][n]+8 mtx[row,col] += -lmbda*dflow[i][j][m][n] # Ninth through fourteenth rows, kinematic hardening. for i in range(3): for j in range(i+1): row = voigt[i][j]+8 mtx[row,row]=1.0 # Diagonal part, deriv wrt c's. # Component-wise match-up. for k in range(3): for l in range(3): col = voigt[k][l]+2 mtx[row,col] = -dkhard[i][j][k][l] # Solve the resulting linearized system. # for mtxi in range(8): # print [ mtx[mtxi,j] for j in range(8) ] rr = mtx.solve(rhs) if rr==0: # print "Increments: ", [ rhs[i,0] for i in range(8) ] lmbda += rhs[0,0] dgamma += rhs[1,0] for i in range(6): ep[i] += rhs[i+2,0] dcenter[i] += rhs[i+8,0] # print "Soln: ", [lmbda, dgamma] + [ep[i] for i in range(6)] else: print >> sys.stderr, "Error in solving in ycheck, rr=", rr else: print >> sys.stderr, "Error, ycheck loop did not converge." # Broke out of loop. return [dgamma]+ep+dcenter
def __init__(self,idx,nodelist=[]): self.index = idx self.nodes = nodelist[:] self.sfns = [qsf0,qsf1,qsf2,qsf3] self.dsfns = [[dqsf0d1,dqsf0d2],[dqsf1d1,dqsf1d2], [dqsf2d1,dqsf2d2],[dqsf3d1,dqsf3d2]] for n in self.nodes: n.add_element(self) # Gauss-point-specific data. Initialize plastic strain field # to be zero. self.gpdata = {} for p in self.gausspts(): self.gpdata[p]=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0] # Use shape-functions directly to represent the stress. The # shape functions are capable of representing lower-order # objects, so in principle this should not create any # difficulties, and is convenient. They are only used on a # per-element basis, of course. mmtx = smallmatrix.SmallMatrix(4,4) rmtx = smallmatrix.SmallMatrix(4,4) mmtx.clear() rmtx.clear() for i in range(4): rmtx[i,i]=1.0 # Identity matrix. for j in range(4): res = 0.0 for p in self.gausspts(): res += self.shapefn(i,p.xi,p.zeta)* \ self.shapefn(j,p.xi,p.zeta)* \ p.weight*self.jacobian(p.xi,p.zeta) mmtx[i,j]=res r = mmtx.solve(rmtx) if r!=0: print >> sys.stderr, \ "Element mass matrix is singular, run for the hills!" else: self.s_mtx = rmtx # G-matrix is indexed by triples, i,j,k, where i is the index # of the shape function, j is the index of the shape function # derivative, and k is the component of the derivative, for # which the entry is the integral over the element. self.g_mtx = [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]] for i in range(4): for j in range(4): for k in range(2): res = 0.0 for p in self.gausspts(): res += self.shapefn(i,p.xi,p.zeta)* \ self.dshapefn(j,k,p.xi,p.zeta)* \ p.weight* \ self.jacobian(p.xi,p.zeta) self.g_mtx[i][j][k] = res # Premultiply. self.sg_mtx = [[[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]], [[0.0, 0.0], [0.0, 0.0], [0.0, 0.0], [0.0, 0.0]]] for s in range(4): for j in range(4): for k in range(2): for t in range(4): self.sg_mtx[s][j][k] += self.s_mtx[s,t]*self.g_mtx[t][j][k] self.make_fmtx()