Letztes Mal Ich habe einen Artikel gepostet Jemand hat bereits die Finite-Elemente-Methode (FEM) in Python geschrieben. *** damyarou *** Ich habe mit *** s Quelle gespielt ***, also schreibe ich es als Artikel.
Holen Sie sich die Beispielquelle und die Beispieldaten von damyarous Homepage.
Beispielquelle: [py_fem_3dfrm.py] (http://civilyarou.web.fc2.com/py_FEM/data_3dfrm/py_fem_3dfrm.py) Programm zur Analyse dreidimensionaler Skelettstrukturen
Beispieldaten: inp_3dfrm_grid.txt Eingabedaten für die FEM-Analyse (1)
Informationen zur Verwendung finden Sie auf der [Homepage] von damyarou (http://civilyarou.web.fc2.com/py_FEM/sub_j_py_fem.html#3Dfrm). Das Ergebnis der Beispieldaten ist wie folgt
npoin nele nsec npfix nlod
392 759 4 16 392
sec E po A J Iy Iz theta
sec alpha gamma gkX gkY gkZ
1 2.5500000e+06 2.0000000e-01 6.0000000e-01 0.0000000e+00 1.8000000e-02 5.0000000e-02 0.0000000e+00
・ ・ ・ ・ ・ ・<Unterlassung>・ ・ ・ ・ ・ ・・
758 337 321 2
759 321 303 2
node dis-x dis-y dis-z rot-x rot-y rot-z
1 0.0000000e+00 0.0000000e+00 0.0000000e+00 -1.6243780e-04 1.9410889e-04 0.0000000e+00
2 0.0000000e+00 0.0000000e+00 -1.4268342e-04 -1.1792525e-04 3.1402105e-04 0.0000000e+00
3 0.0000000e+00 0.0000000e+00 -2.2831328e-04 -5.0801073e-05 4.0898102e-04 0.0000000e+00
4 0.0000000e+00 0.0000000e+00 -2.4248770e-04 2.1716711e-05 4.5111583e-04 0.0000000e+00
5 0.0000000e+00 0.0000000e+00 -1.8982394e-04 7.9402252e-05 4.3238604e-04 0.0000000e+00
6 0.0000000e+00 0.0000000e+00 -9.5023442e-05 1.0306705e-04 3.6727765e-04 0.0000000e+00
・ ・ ・ ・ ・ ・<Unterlassung>・ ・ ・ ・ ・ ・・
elem nodei N_i Sy_i Sz_i Mx_i My_i Mz_i
elem nodej N_j Sy_j Sz_j Mx_j My_j Mz_j
1 1 0.0000000e+00 0.0000000e+00 9.9678698e+01 -7.9374360e+01 9.7946784e+01 0.0000000e+00
1 2 0.0000000e+00 0.0000000e+00 -9.9678698e+01 7.9374360e+01 -1.9762548e+02 0.0000000e+00
2 2 0.0000000e+00 0.0000000e+00 5.0466963e+01 -6.2857564e+01 1.9762548e+02 0.0000000e+00
2 3 0.0000000e+00 0.0000000e+00 -5.0466963e+01 6.2857564e+01 -2.4809244e+02 0.0000000e+00
3 3 0.0000000e+00 0.0000000e+00 -1.4652296e+01 -2.7890607e+01 2.4809244e+02 0.0000000e+00
3 4 0.0000000e+00 0.0000000e+00 1.4652296e+01 2.7890607e+01 -2.3344015e+02 0.0000000e+00
・ ・ ・ ・ ・ ・<Folgendes wird weggelassen>・ ・ ・ ・ ・ ・・
Es ist jedoch nicht interessant, nur zu kopieren und zu berechnen Ich habe es in die folgenden Klassen unterteilt.
FramePython.py
from inpData import inpData
from kMatrix import kMatrix
from gMatrix import gMatrix
from fMatrix import fMatrix
from outData import outData
Klasse | Verwenden |
---|---|
inpData | Eingabedaten lesen |
kMatrix | Starrheitsmatrix für jedes Element |
gMatrix | Gesamtsystemsteifigkeitsmatrix |
fMatrix | Laststeifigkeitsmatrix |
outData | Ausgabedaten schreiben |
FramePython.py
fnameR= 'inp_grid.txt'
fnameW= 'out_grid.txt'
inp = inpData(fnameR)
inp.PRINP_3DFRM()
inpData.py
def __init__(self, fnameR):
f=open(fnameR,'r')
self.setdata(f)
f.close()
def setdata(self, f):
text=f.readline()
text=text.strip()
text=text.split()
self.npoin=int(text[0]) # Number of nodes
self.nele =int(text[1]) # Number of elements
self.nsec =int(text[2]) # Number of sections
self.npfix=int(text[3]) # Number of restricted nodes
self.nlod =int(text[4]) # Number of loaded nodes
self.nod=2 # Number of nodes per element
self.nfree=6 # Degree of freedom per node
self.n12=self.nod*self.nfree
self.n = self.nfree*self.npoin
self.x =np.zeros([3, self.npoin], dtype=np.float64) # Coordinates of nodes
self.deltaT=np.zeros(self.npoin, dtype=np.float64) # Temperature change of nodes
self.ae =np.zeros([12, self.nsec], dtype=np.float64) # Section characteristics
self.node =np.zeros([self.nod+1, self.nele], dtype=np.int) # Node-element relationship
self.fp =np.zeros(self.nfree*self.npoin,dtype=np.float64) # External force vector
self.mpfix =np.zeros([self.nfree, self.npoin],dtype=np.int) # Ristrict conditions
self.rdis =np.zeros([self.nfree, self.npoin],dtype=np.float64) # Ristricted displacement
# section characteristics
for i in range(0, self.nsec):
text=f.readline()
text=text.strip()
text=text.split()
self.ae[0,i] =float(text[0]) # E : elastic modulus
self.ae[1,i] =float(text[1]) # po : Poisson's ratio
self.ae[2,i] =float(text[2]) # aa : section area
self.ae[3,i] =float(text[3]) # aix : tortional constant
self.ae[4,i] =float(text[4]) # aiy : moment of inertia aroutd y-axis
self.ae[5,i] =float(text[5]) # aiz : moment of inertia around z-axis
self.ae[6,i] =float(text[6]) # theta : chord angle
self.ae[7,i] =float(text[7]) # alpha : thermal expansion coefficient
self.ae[8,i] =float(text[8]) # gamma : unit weight of material
self.ae[9,i] =float(text[9]) # gkX : acceleration in X-direction
self.ae[10,i]=float(text[10]) # gkY : acceleration in Y-direction
self.ae[11,i]=float(text[11]) # gkZ : acceleration in Z-direction
# element-node
for i in range(0, self.nele):
text=f.readline()
text=text.strip()
text=text.split()
self.node[0,i]=int(text[0]) #node_1
self.node[1,i]=int(text[1]) #node_2
self.node[2,i]=int(text[2]) #section characteristic number
# node coordinates
for i in range(0, self.npoin):
text=f.readline()
text=text.strip()
text=text.split()
self.x[0,i]=float(text[0]) # x-coordinate
self.x[1,i]=float(text[1]) # y-coordinate
self.x[2,i]=float(text[2]) # z-coordinate
self.deltaT[i]=float(text[3]) # Temperature change
# boundary conditions (0:free, 1:restricted)
for i in range(0, self.npfix):
text=f.readline()
text=text.strip()
text=text.split()
lp=int(text[0]) #fixed node
self.mpfix[0,lp-1]=int(text[1]) #fixed in x-direction
self.mpfix[1,lp-1]=int(text[2]) #fixed in y-direction
self.mpfix[2,lp-1]=int(text[3]) #fixed in z-direction
self.mpfix[3,lp-1]=int(text[4]) #fixed in rotation around x-axis
self.mpfix[4,lp-1]=int(text[5]) #fixed in rotation around y-axis
self.mpfix[5,lp-1]=int(text[6]) #fixed in rotation around z-axis
self.rdis[0,lp-1]=float(text[7]) #fixed displacement in x-direction
self.rdis[1,lp-1]=float(text[8]) #fixed displacement in y-direction
self.rdis[2,lp-1]=float(text[9]) #fixed displacement in z-direction
self.rdis[3,lp-1]=float(text[10]) #fixed rotation around x-axis
self.rdis[4,lp-1]=float(text[11]) #fixed rotation around y-axis
self.rdis[5,lp-1]=float(text[12]) #fixed rotation around z-axis
# load
if 0<self.nlod:
for i in range(0, self.nlod):
text=f.readline()
text=text.strip()
text=text.split()
lp=int(text[0]) #loaded node
self.fp[6*lp-6]=float(text[1]) #load in x-direction
self.fp[6*lp-5]=float(text[2]) #load in y-direction
self.fp[6*lp-4]=float(text[3]) #load in z-direction
self.fp[6*lp-3]=float(text[4]) #moment around x-axis
self.fp[6*lp-2]=float(text[5]) #moment around y-axis
self.fp[6*lp-1]=float(text[6]) #moment around z-axis
FramePython.py
gmat = gMatrix(inp.n)
fmat = fMatrix(inp)
for ne in range(0,inp.nele):
k= kMatrix(ne, inp)
gmat.set_kMatrix(k) # assembly of stiffness matrix
fmat.set_fMatrix(k) # assembly of load vectors
kMatrix.py
def __init__(self, ne, input):
self.ne = ne
self.inp = input
self.iNo = self.inp.node[0,self.ne]
self.jNo = self.inp.node[1,self.ne]
self.eNo = self.inp.node[2,self.ne]
i = self.iNo-1
j = self.jNo-1
self.x1= self.inp.x[0,i]
self.y1= self.inp.x[1,i]
self.z1= self.inp.x[2,i]
self.x2= self.inp.x[0,j]
self.y2= self.inp.x[1,j]
self.z2= self.inp.x[2,j]
xx = self.x2-self.x1
yy = self.y2-self.y1
zz = self.z2-self.z1
self.el = np.sqrt(xx**2+yy**2+zz**2)
m = self.eNo-1
self.ee = self.inp.ae[0,m] # elastic modulus
self.po = self.inp.ae[1,m] # Poisson's ratio
self.aa = self.inp.ae[2,m] # section area
self.aix = self.inp.ae[3,m] # tortional constant
self.aiy = self.inp.ae[4,m] # moment of inertia around y-axis
self.aiz = self.inp.ae[5,m] # moment of inertia around z-axis
self.theta = self.inp.ae[6,m] # theta : chord angle
self.alpha = self.inp.ae[7,m] # alpha : thermal expansion coefficient
self.gamma = self.inp.ae[8,m] # gamma : unit weight of material
self.gkX = self.inp.ae[9,m] # gkX : acceleration in X-direction
self.gkY = self.inp.ae[10,m] # gkY : acceleration in Y-direction
self.gkZ = self.inp.ae[11,m] # gkZ : acceleration in Z-direction
self.GJ=self.ee/2/(1+self.po)*self.aix
self.EA=self.ee*self.aa
self.EIy=self.ee*self.aiy
self.EIz=self.ee*self.aiz
# Work vector for matrix assembly
ir = np.zeros(12, dtype=np.int)
ir[11]=6*j+5; ir[10]=ir[11]-1; ir[9]=ir[10]-1; ir[8]=ir[9]-1; ir[7]=ir[8]-1; ir[6]=ir[7]-1
ir[5] =6*i+5; ir[4] =ir[5]-1 ; ir[3]=ir[4]-1 ; ir[2]=ir[3]-1; ir[1]=ir[2]-1; ir[0]=ir[1]-1
self.ir = ir
self.ek = self.SM_3DFRM()
self.tt = self.TM_3DFRM()
def SM_3DFRM(self):
ek = np.zeros([12,12],dtype=np.float64) # local stiffness matrix
ek[ 0, 0]= self.EA/self.el
ek[ 0, 6]=-self.EA/self.el
ek[ 1, 1]= 12*self.EIz/self.el**3
ek[ 1, 5]= 6*self.EIz/self.el**2
ek[ 1, 7]=-12*self.EIz/self.el**3
ek[ 1,11]= 6*self.EIz/self.el**2
ek[ 2, 2]= 12*self.EIy/self.el**3
ek[ 2, 4]= -6*self.EIy/self.el**2
ek[ 2, 8]=-12*self.EIy/self.el**3
ek[ 2,10]= -6*self.EIy/self.el**2
ek[ 3, 3]= self.GJ/self.el
ek[ 3, 9]=-self.GJ/self.el
ek[ 4, 2]= -6*self.EIy/self.el**2
ek[ 4, 4]= 4*self.EIy/self.el
ek[ 4, 8]= 6*self.EIy/self.el**2
ek[ 4,10]= 2*self.EIy/self.el
ek[ 5, 1]= 6*self.EIz/self.el**2
ek[ 5, 5]= 4*self.EIz/self.el
ek[ 5, 7]= -6*self.EIz/self.el**2
ek[ 5,11]= 2*self.EIz/self.el
ek[ 6, 0]=-self.EA/self.el
ek[ 6, 6]= self.EA/self.el
ek[ 7, 1]=-12*self.EIz/self.el**3
ek[ 7, 5]= -6*self.EIz/self.el**2
ek[ 7, 7]= 12*self.EIz/self.el**3
ek[ 7,11]= -6*self.EIz/self.el**2
ek[ 8, 2]=-12*self.EIy/self.el**3
ek[ 8, 4]= 6*self.EIy/self.el**2
ek[ 8, 8]= 12*self.EIy/self.el**3
ek[ 8,10]= 6*self.EIy/self.el**2
ek[ 9, 3]=-self.GJ/self.el
ek[ 9, 9]= self.GJ/self.el
ek[10, 2]= -6*self.EIy/self.el**2
ek[10, 4]= 2*self.EIy/self.el
ek[10, 8]= 6*self.EIy/self.el**2
ek[10,10]= 4*self.EIy/self.el
ek[11, 1]= 6*self.EIz/self.el**2
ek[11, 5]= 2*self.EIz/self.el
ek[11, 7]= -6*self.EIz/self.el**2
ek[11,11]= 4*self.EIz/self.el
return ek
def TM_3DFRM(self):
tt=np.zeros([12,12],dtype=np.float64) # transformation matrix
t1=np.zeros([3,3],dtype=np.float64)
t2=np.zeros([3,3],dtype=np.float64)
theta=np.radians(self.theta)#(self.inp.ae[6,m]) # chord angle
t1[0,0]=1
t1[1,1]= np.cos(theta)
t1[1,2]= np.sin(theta)
t1[2,1]=-np.sin(theta)
t1[2,2]= np.cos(theta)
ll=(self.x2-self.x1)/self.el
mm=(self.y2-self.y1)/self.el
nn=(self.z2-self.z1)/self.el
if self.x2-self.x1==0.0 and self.y2-self.y1==0.0:
t2[0,2]=nn
t2[1,0]=nn
t2[2,1]=1.0
else:
qq=np.sqrt(ll**2+mm**2)
t2[0,0]=ll
t2[0,1]=mm
t2[0,2]=nn
t2[1,0]=-mm/qq
t2[1,1]= ll/qq
t2[2,0]=-ll*nn/qq
t2[2,1]=-mm*nn/qq
t2[2,2]=qq
t3=np.dot(t1,t2)
tt[0:3,0:3] =t3[0:3,0:3]
tt[3:6,3:6] =t3[0:3,0:3]
tt[6:9,6:9] =t3[0:3,0:3]
tt[9:12,9:12]=t3[0:3,0:3]
return tt
def ck(self):
return np.dot(np.dot(self.tt.T,self.ek),self.tt) # Stiffness matrix in global coordinate
gMatrix.py
def __init__(self, n):
self.gk = np.zeros([n,n], dtype=np.float64) # Global stiffness matrix
self.kmat = {}
def set_kMatrix(self, k):
self.kmat[k.ne] = k
ck = k.ck()
for i in range(0,12):
it=k.ir[i]
for j in range(0,12):
jt=k.ir[j]
self.gk[it,jt]=self.gk[it,jt]+ck[i,j]
fMatrix.py
def __init__(self, input):
self.inp = input
self.fp = self.inp.fp.copy()
def set_fMatrix(self, k):
tfe_l=self.TFVEC_3DFRM(k)
tt = k.tt
tfe =np.dot(tt.T,tfe_l) # Thermal load vector in global coordinate
bfe =self.BFVEC_3DFRM( k) # Body force vector in global coordinate
for i in range(0,12):
it=k.ir[i]
self.fp[it]=self.fp[it]+tfe[i]+bfe[i]
def TFVEC_3DFRM(self, k):
# Thermal load vector in local coordinate system
tfe_l=np.zeros(12,dtype=np.float64)
i= k.iNo-1
j= k.jNo-1
E = k.ee # elastic modulus
AA = k.aa # section area
alpha = k.alpha # thermal expansion coefficient
tempe=0.5*(self.inp.deltaT[i]+self.inp.deltaT[j])
tfe_l[0]=-E*AA*alpha*tempe
tfe_l[6]= E*AA*alpha*tempe
return tfe_l
def BFVEC_3DFRM(self, k):
# Body force vector in global coordinate system
bfe_g =np.zeros(12,dtype=np.float64)
AA = k.aa # section area
gamma = k.gamma # unit weight of material
gkX = k.gkX # seismic coefficient in X-direction
gkY = k.gkY # seismic coefficient in Y-direction
gkZ = k.gkZ # seismic coefficient in Z-direction
el = k.el
bfe_g[0]=0.5*gamma*AA*el*gkX
bfe_g[1]=0.5*gamma*AA*el*gkY
bfe_g[2]=0.5*gamma*AA*el*gkZ
bfe_g[6]=0.5*gamma*AA*el*gkX
bfe_g[7]=0.5*gamma*AA*el*gkY
bfe_g[8]=0.5*gamma*AA*el*gkZ
return bfe_g
FramePython.py
# treatment of boundary conditions
for i in range(0,inp.npoin):
for j in range(0,inp.nfree):
if inp.mpfix[j,i]==1:
iz=i*inp.nfree+j
fmat.fp[iz]=0.0
for k in range(0,inp.n):
fmat.fp[k]=fmat.fp[k]-inp.rdis[j,i]*gmat.gk[k,iz]
gmat.gk[k,iz]=0.0
gmat.gk[iz,iz]=1.0
Simultane lineare Gleichungen werden durch numpy.linalg.solve (A, b) gelöst.
FramePython.py
# solution of simultaneous linear equations
result = np.linalg.solve(gmat.gk, fmat.fp)
FramePython.py
out = outData(inp, result, gmat)
out.PROUT_3DFRM(fnameW)
dtime=time.time()-start
print('n={0} time={1:.3f}'.format(inp.n,dtime)+' sec')
fout=open(fnameW,'a')
print('n={0} time={1:.3f}'.format(inp.n,dtime)+' sec',file=fout)
fout.close()
outData.py
def __init__(self, input, result, gmat):
self.inp = input
self.disg = result
self.fsec = np.zeros([self.inp.n12, self.inp.nele], dtype=np.float64) # Section force vector
# recovery of restricted displacements
for i in range(0,self.inp.npoin):
for j in range(0,self.inp.nfree):
if self.inp.mpfix[j,i]==1:
iz=i*self.inp.nfree+j
self.disg[iz]=self.inp.rdis[j,i]
# calculation of section force
work =np.zeros(self.inp.n12, dtype=np.float64) # work vector for section force calculation
for ne in range(0,self.inp.nele):
k = gmat.kmat[ne]
i = k.iNo-1
j = k.jNo-1
ek = k.ek # Stiffness matrix in local coordinate
tt = k.tt # Transformation matrix
E = k.ee # elastic modulus
AA = k.aa # section area
alpha = k.alpha # thermal expansion coefficient
tempe = 0.5*(self.inp.deltaT[i]+self.inp.deltaT[j])
work[0]=self.disg[6*i] ; work[1] =self.disg[6*i+1]; work[2]= self.disg[6*i+2]
work[3]=self.disg[6*i+3]; work[4] =self.disg[6*i+4]; work[5]= self.disg[6*i+5]
work[6]=self.disg[6*j] ; work[7] =self.disg[6*j+1]; work[8]= self.disg[6*j+2]
work[9]=self.disg[6*j+3]; work[10]=self.disg[6*j+4]; work[11]=self.disg[6*j+5]
self.fsec[:,ne]=np.dot(ek,np.dot(tt,work))
self.fsec[0,ne]=self.fsec[0,ne]+E*AA*alpha*tempe
self.fsec[6,ne]=self.fsec[6,ne]-E*AA*alpha*tempe
Die geänderte Quelle ist hier.
$ git clone -b "#2" https://github.com/sasaco/FramePython.git
Wenn die Umgebung bereit ist, wechseln Sie in das Quellcodeverzeichnis und klicken Sie auf FramePython.py, um die Analyse zu starten.
npoin nele nsec npfix nlod
392 759 4 16 392
sec E po A J Iy Iz theta
sec alpha gamma gkX gkY gkZ
1 2.5500000e+06 2.0000000e-01 6.0000000e-01 0.0000000e+00 1.8000000e-02 5.0000000e-02 0.0000000e+00
・ ・ ・ ・ ・ ・<Unterlassung>・ ・ ・ ・ ・ ・・
758 337 321 2
759 321 303 2
node dis-x dis-y dis-z rot-x rot-y rot-z
1 0.0000000e+00 0.0000000e+00 0.0000000e+00 -1.6243780e-04 1.9410889e-04 0.0000000e+00
2 0.0000000e+00 0.0000000e+00 -1.4268342e-04 -1.1792525e-04 3.1402105e-04 0.0000000e+00
3 0.0000000e+00 0.0000000e+00 -2.2831328e-04 -5.0801073e-05 4.0898102e-04 0.0000000e+00
4 0.0000000e+00 0.0000000e+00 -2.4248770e-04 2.1716711e-05 4.5111583e-04 0.0000000e+00
5 0.0000000e+00 0.0000000e+00 -1.8982394e-04 7.9402252e-05 4.3238604e-04 0.0000000e+00
6 0.0000000e+00 0.0000000e+00 -9.5023442e-05 1.0306705e-04 3.6727765e-04 0.0000000e+00
・ ・ ・ ・ ・ ・<Unterlassung>・ ・ ・ ・ ・ ・・
elem nodei N_i Sy_i Sz_i Mx_i My_i Mz_i
elem nodej N_j Sy_j Sz_j Mx_j My_j Mz_j
1 1 0.0000000e+00 0.0000000e+00 9.9678698e+01 -7.9374360e+01 9.7946784e+01 0.0000000e+00
1 2 0.0000000e+00 0.0000000e+00 -9.9678698e+01 7.9374360e+01 -1.9762548e+02 0.0000000e+00
2 2 0.0000000e+00 0.0000000e+00 5.0466963e+01 -6.2857564e+01 1.9762548e+02 0.0000000e+00
2 3 0.0000000e+00 0.0000000e+00 -5.0466963e+01 6.2857564e+01 -2.4809244e+02 0.0000000e+00
3 3 0.0000000e+00 0.0000000e+00 -1.4652296e+01 -2.7890607e+01 2.4809244e+02 0.0000000e+00
3 4 0.0000000e+00 0.0000000e+00 1.4652296e+01 2.7890607e+01 -2.3344015e+02 0.0000000e+00
・ ・ ・ ・ ・ ・<Folgendes wird weggelassen>・ ・ ・ ・ ・ ・・
Die Analyse wurde korrekt durchgeführt.
Recommended Posts