You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
5.4 KiB

3 years ago
import numpy as np
from scipy.sparse import coo_matrix
from scipy.sparse.linalg import spsolve
def FEA(nelx, nely, x, penal):
# dofs:
ndof = 2*(nelx+1)*(nely+1)
xPhys = x.copy()
KE = lk()
edofMat = np.zeros((nelx*nely, 8), dtype=int)
for elx in range(nelx):
for ely in range(nely):
el = ely+elx*nely
n1 = (nely+1)*elx+ely
n2 = (nely+1)*(elx+1)+ely
edofMat[el, :] = np.array(
#[2*n1+2, 2*n1+3, 2*n2+2, 2*n2+3, 2*n2, 2*n2+1, 2*n1, 2*n1+1])
[2*n1, 2*n1+1, 2*n2, 2*n2+1, 2*n2+2, 2*n2+3, 2*n1+2, 2*n1+3 ])
# Construct the index pointers for the coo format
iK = np.kron(edofMat, np.ones((8, 1))).flatten()
jK = np.kron(edofMat, np.ones((1, 8))).flatten()
# BC's and support
dofs = np.arange(2*(nelx+1)*(nely+1))
#fixed = np.union1d(dofs[0:2*(nely+1):2], np.array([2*(nelx+1)*(nely+1)-1]))
fixed = dofs[0:2*(nely+1)]
free = np.setdiff1d(dofs, fixed)
# Solution and RHS vectors
f = np.zeros((ndof, 1))
u = np.zeros((ndof, 1))
# Set load
#f[1, 0] = -1
#f[ndof-1,0] = -1
# CASE 1
#loaddof=np.array(range(2*(nely+1)*nelx,2*(nely+1)*(nelx+1),2))
#f[loaddof,0]=1
# CASE 2
loaddof=np.array(range(2*(nely+1)*nelx+2,2*(nely+1)*(nelx+1)-2,2))
f[loaddof,0]=1
f[2*(nely+1)*nelx,0]=0.5
f[2*(nely+1)*(nelx+1)-2,0]=0.5
#sK = ((KE.flatten()[np.newaxis]).T*(Emin+(xPhys)
# ** penal*(Emax-Emin))).flatten(order='F')
sK = ((KE.flatten()[np.newaxis]).T*((xPhys)** penal)).flatten(order='F')
K = coo_matrix((sK, (iK, jK)), shape=(ndof, ndof)).tocsc()
# Remove constrained dofs from matrix
K = K[free, :][:, free]
# Solve system
u[free, 0] = spsolve(K, f[free, 0])
return u
def CompuStress(nelx, nely, x, penal, u):
D=ElasticTensor()
B=StrainDispMat()
SMat = np.zeros([(nelx+1)*(nely+1),3])
NumCount = np.zeros([(nelx+1)*(nely+1),1])
strs = np.zeros([(nelx+1)*(nely+1)*3,1])
for elx in range(nelx):
for ely in range(nely):
el = ely+elx*nely
n1 = (nely+1)*elx+ely
n2 = (nely+1)*(elx+1)+ely
edof = np.array(
[2*n1, 2*n1+1, 2*n2, 2*n2+1, 2*n2+2, 2*n2+3, 2*n1+2, 2*n1+3 ])
ue=u[edof,0]
n3 = n2 + 1
n4 = n1 + 1
SMat[n1,:]=SMat[n1,:]+x[el]**penal*D@B[0,:,:]@ue
SMat[n2,:]=SMat[n2,:]+x[el]**penal*D@B[1,:,:]@ue
SMat[n3,:]=SMat[n3,:]+x[el]**penal*D@B[2,:,:]@ue
SMat[n4,:]=SMat[n4,:]+x[el]**penal*D@B[3,:,:]@ue
NumCount[[n1,n2,n3,n4],0]=NumCount[[n1,n2,n3,n4],0]+[1,1,1,1]
for i in range((nelx+1)*(nely+1)):
strs[[i*3,i*3+1,i*3+2],0]=SMat[i,:]/NumCount[i]
return strs
#element stiffness matrix
def lk():
E=1
# E=10**6
nu=0.3
k=np.array([1/2-nu/6,1/8+nu/8,-1/4-nu/12,-1/8+3*nu/8,-1/4+nu/12,-1/8-nu/8,nu/6,1/8-3*nu/8])
KE = E/(1-nu**2)*np.array([ [k[0], k[1], k[2], k[3], k[4], k[5], k[6], k[7]],
[k[1], k[0], k[7], k[6], k[5], k[4], k[3], k[2]],
[k[2], k[7], k[0], k[5], k[6], k[3], k[4], k[1]],
[k[3], k[6], k[5], k[0], k[7], k[2], k[1], k[4]],
[k[4], k[5], k[6], k[7], k[0], k[1], k[2], k[3]],
[k[5], k[4], k[3], k[2], k[1], k[0], k[7], k[6]],
[k[6], k[3], k[4], k[1], k[2], k[7], k[0], k[5]],
[k[7], k[2], k[1], k[4], k[3], k[6], k[5], k[0]] ])
return (KE)
def ElasticTensor():
E=1
nu=0.3
D = E/(1-nu**2)*np.array([[1,nu,0],
[nu,1,0],
[0,0,(1-nu)/2] ])
return D
def StrainDispMat():
B=np.zeros([4,3,8],dtype=float)
B[0,:,:]=np.array([ [-1, 0, 1, 0, 0, 0, 0, 0],
[0, -1, 0, 0, 0, 0, 0, 1],
[-1, -1, 0, 1, 0, 0, 1, 0] ])
B[1,:,:]=np.array([ [-1, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, -1, 0, 1, 0, 0],
[0, -1, -1, 1, 1, 0, 0, 0] ])
B[2,:,:]=np.array([ [0, 0, 0, 0, 1, 0, -1, 0],
[0, 0, 0, -1, 0, 1, 0, 0],
[0, 0, -1, 0, 1, 1, 0, -1] ])
B[3,:,:]=np.array([ [0, 0, 0, 0, 1, 0, -1, 0],
[0, -1, 0, 0, 0, 0, 0, 1],
[-1, 0, 0, 0, 0, 1, 1, -1] ])
return B
def ComputeTarget(input):
# x np.array [bs, 1, 20, 40]
nelx = 40
nely = 20
penal = 3.0
bs = input.shape[0]
result = np.zeros([bs, 5, 21, 41], dtype=float)
data = input.transpose([0,1,3,2]).reshape(-1,800)
# data = input.permute([0,1,3,2]).contiguous().view(-1,800)
for i in range(bs):
xx = data[i]
u = FEA(nelx, nely, xx, penal)
strs=CompuStress(nelx, nely, xx, penal, u)
ux = u[range(0,1722,2)]
uy = u[range(1,1722,2)]
sx = strs[range(0,2583,3)]
sy = strs[range(1,2583,3)]
sxy = strs[range(2,2583,3)]
result[i] = np.concatenate([ux,uy,sx,sy,sxy],1).T.reshape(5,41,21).transpose([0,2,1])
return result
if __name__ == "__main__":
# Default input parameters
nelx = 40
nely = 20
penal = 3.0
volfrac = 0.4
x = volfrac * np.ones(nely*nelx, dtype=float)
# 0.001 <= x <= 1
u = FEA(nelx, nely, x, penal)
print(u[42:84:1])
#print(u[43:84:2])
strs=CompuStress(nelx, nely, x, penal, u)
print(strs[0:14:1])