ダウンロード
ソースコード
シンプルな三角形1次元要素の2次元FEM
- # -*- coding: utf-8 -*-
-
- import math
-
- class Material:
- def __init__(self,no):
- self.no = no
- self.young = .0
- self.poisson = .0
- self.thickness = .0
-
- class Node:
- def __init__(self,no):
- self.no = no # 節点番号
- self.x = .0 # X座標値
- self.y = .0 #
- self.disp = [.0,.0] # 強制変位
- self.cond = [0,0] # 拘束条件の有無
- self.force = [.0,0] # 節点荷重
-
- class Element:
- def __init__(self,no):
- self.no = no
- self.node = [0,0,0] # 節点番号
- self.x = [.0,.0,.0] # 節点番号のX座標
- self.y = [.0,.0,.0]
- self.u = [.0 for i in range(6)] # 節点番号の変位
- self.elNode = [0,0,0,0,0,0]
- self.matNo = 0
- self.area = .0
- self.Bmat = [[.0 for i in range(6)] for j in range(3)]
- self.Smat = [[.0 for i in range(6)] for j in range(3)]
- self.Dmat = [[.0 for i in range(3)] for j in range(3)]
- self.Kmat = [[.0 for i in range(6)] for j in range(6)]
- self.stress = [.0 for i in range(9)] # 要素の応力
-
- def setDmatrix(self,mat):
- a = mat.young / (1+mat.poisson) / (1-mat.poisson)
- b = a * mat.poisson
- c = 0.5 * mat.young / (1+mat.poisson)
- self.Dmat = [[a,b,0,],
- [b,a,0,],
- [0,0,c]]
-
- def setBmatrix(self):
- self.elNode = [2*self.node[0],2*self.node[0]+1,
- 2*self.node[1],2*self.node[1]+1,
- 2*self.node[2],2*self.node[2]+1]
- Ai = self.y[1] - self.y[2]
- Aj = self.y[2] - self.y[0]
- Ak = self.y[0] - self.y[1]
- Bi = self.x[2] - self.x[1]
- Bj = self.x[0] - self.x[2]
- Bk = self.x[1] - self.x[0]
- dl = Bk * Aj - Ak * Bj
- self.area = 0.5 * dl
- self.Bmat = [[Ai/dl, 0,Aj/dl, 0,Ak/dl, 0],
- [ 0,Bi/dl, 0,Bj/dl, 0,Bk/dl],
- [Bi/dl,Ai/dl,Bj/dl,Aj/dl,Bk/dl,Ak/dl]]
-
- def setSmatrix(self):
- for i in range(3):
- for j in range(6):
- s = 0
- for k in range(3):
- s += self.Dmat[i][k]*self.Bmat[k][j]
- self.Smat[i][j] = s
-
- def setKmatrix(self,mat): #要素剛性行列の設定
- v = mat.thickness * self.area
- for i in range(6):
- for j in range(6):
- s = 0
- for k in range(3):
- s += self.Bmat[k][i]*self.Smat[k][j]
- self.Kmat[i][j] = v * s
-
- def calcStress(self):
- for i in range(3):
- s = 0
- for j in range(6):
- s += self.Smat[i][j] * self.u[j]
- self.stress[i] = s
- cc = 0.5 * (self.stress[0] + self.stress[1])
- ss = 0.5 * (self.stress[0] - self.stress[1])
- cr = math.sqrt(ss*ss+self.stress[2]*self.stress[2])
- self.stress[3] = cc + cr
- self.stress[4] = cc - cr
- self.stress[5] = cr
- if cr <= ss:
- self.stress[6] = 0
- else:
- wk = abs((ss+cr)/(ss-cr))
- self.stress[6] = 57.29577951 * math.atan(math.sqrt(wk))
- if self.stress[6] < 0:
- self.stress[6] = -self.stress[6]
- self.stress[6] = 90 - self.stress[6]
- self.stress[7] = math.sqrt(self.stress[3]*self.stress[3]
- - self.stress[3] * self.stress[4]
- + self.stress[4] * self.stress[4])
- if self.stress[4] > 0:
- self.stress[8] = self.stress[3]
- elif self.stress[3] > 0:
- self.stress[8] = self.stress[3] - self.stress[4]
- else:
- self.stress[8] = - self.stress[4]
-
- class Fem2D():
- def __init__(self):
- self.nodes = []
- self.mats = []
- self.elems = []
- self.numberOfNode = 0
- self.numberOfElement = 0
- self.bandWidth = 0
- self.totalMat = []
-
- def readNodeData(self,fp='input_node.txt'):
- '''節点データの読込'''
- f = open(fp,'r')
- lines = f.readlines()
- f.close()
- lines = lines[1:]
- self.nodes = []
- for line in lines:
- line = line.strip('\n')
- d = line.split('\t')
- d = [x if x is not '' else 0 for x in d] + [0,0,0,0]
- n = Node(int(d[0])-1)
- n.x = float(d[1])
- n.y = float(d[2])
- n.cond = [int(d[3]),int(d[4])]
- n.disp = [float(d[5]), float(d[6])]
- n.force = [float(d[7]),float(d[8])]
- self.nodes.append(n)
-
- self.numberOfNode = len(self.nodes)
- print('Loaded Nodes:%d' % self.numberOfNode)
-
- def readMaterialData(self,fp='input_material.txt'):
- '''材料データの読込'''
- f = open(fp)
- lines = f.readlines()
- lines = lines[1:]
- f.close()
-
- self.mats = []
- for line in lines:
- line = line.strip('\n')
- d = line.split('\t')
- m = Material(int(d[0])-1)
- m.young = float(d[1])
- m.poisson = float(d[2])
- m.thickness = float(d[3])
- self.mats.append(m)
- print('Loaded Materials:%d' % len(self.mats))
-
- def readElementData(self,fp='input_element.txt'):
- '''要素データの読込'''
- f = open(fp)
- lines = f.readlines()
- lines = lines[1:]
- f.close()
-
- self.elems = []
- for line in lines:
- d = line.split('\t')
- e = Element(int(d[0])-1)
- n0 = int(d[1])-1
- n1 = int(d[2])-1
- n2 = int(d[3])-1
- e.node = [n0,n1,n2]
- e.matNo = int(d[4])-1
- e.x[0] = self.nodes[n0].x
- e.x[1] = self.nodes[n1].x
- e.x[2] = self.nodes[n2].x
- e.y[0] = self.nodes[n0].y
- e.y[1] = self.nodes[n1].y
- e.y[2] = self.nodes[n2].y
- self.elems.append(e)
- self.numberOfElement = len(self.elems)
- print('Loaded Elements:%d' % self.numberOfElement)
-
- def setElementMatrix(self):
- '''要素剛性行列'''
- for i in range(self.numberOfElement):
- n = self.elems[i].matNo
- self.elems[i].setDmatrix(self.mats[n])
- self.elems[i].setBmatrix()
- self.elems[i].setSmatrix()
- self.elems[i].setKmatrix(self.mats[n])
-
- def setBandWidth(self):
- n = 0
- for k in range(self.numberOfElement):
- for i in range(6):
- for j in range(6):
- ii = self.elems[k].elNode[i]
- jj = self.elems[k].elNode[j]-ii
- if jj > n:
- n = jj
- self.bandWidth = n
- print('BandWidth:%d' % n)
-
- def setTotalMatrix(self):
- '''全体剛性行列'''
- i = self.numberOfNode*2
- j = self.bandWidth+1
- self.totalMat = [[0 for a in range(j)] for b in range(i)]
- for k in range(self.numberOfElement):
- for i in range(6):
- for j in range(6):
- ii = self.elems[k].elNode[i]
- jj = self.elems[k].elNode[j] - ii
- if jj >= 0:
- self.totalMat[ii][jj] += self.elems[k].Kmat[i][j]
-
- def setBoundaryCondition(self):
- '''境界条件による全体剛性行列,荷重ベクトルの変更'''
- for i in range(self.numberOfNode):
- node = self.nodes[i]
- for j in range(2):
- if node.cond[j] != 0:
- self.totalMat[2*i+j][0] = 1e30
- node.force[j] = self.totalMat[2*i+j][0]*node.disp[j]
-
- def solve(self):
- '''連立方程式の解(ガウスの消去法)'''
- n1 = self.bandWidth + 1
- n2 = self.numberOfNode*2
- akj = [0 for i in range(n2)]
- aik = [0 for i in range(n2)]
- for k in range(n2):
- m = self.bandWidth + 1
- if k+self.bandWidth+1 > n2:
- m = n2 - k
- for j in range(1,m):
- akj[j] = self.totalMat[k][j]/self.totalMat[k][0]
- aik[j] = self.totalMat[k][j]
- for i in range(1,m):
- it = i + k
- im1 = i
- for j in range(i,m):
- jt = j - im1
- self.totalMat[it][jt] -= aik[i]*akj[j]
- for n in range(self.numberOfNode):
- for j in range(2):
- k = 2*n+j
- self.nodes[n].force[j] /= self.totalMat[k][0]
- m = self.bandWidth + 1
- if (k+self.bandWidth+1)>n2:
- m = n2 - k
- for i in range(1,m):
- nt,jt = divmod(i+k,2)
- diff = self.totalMat[k][i]*self.nodes[n].force[j]
- self.nodes[nt].force[jt] -= diff
- if n == self.numberOfNode:
- break
- self.nodes[-1].disp[1] = self.nodes[-1].force[1]/self.totalMat[-1][0]
- for n in range(self.numberOfNode-1,-1,-1):
- for j in [1,0]:
- k = 2*n+j
- s = 0
- m = self.bandWidth + 1
- if (k+self.bandWidth+1)> n2:
- m = n2-k
- for i in range(1,m):
- nt,jt = divmod(i+k,2)
- s += self.totalMat[k][i]*self.nodes[nt].disp[jt]
- disp = self.nodes[n].force[j] - s / self.totalMat[k][0]
- self.nodes[n].disp[j] = disp
-
- def setStress(self):
- '''応力の設定'''
- for i in range(self.numberOfElement):
- e = self.elems[i]
- for j in range(3):
- e.u[2*j] = self.nodes[e.node[j]].disp[0]
- e.u[2*j+1] = self.nodes[e.node[j]].disp[1]
- e.calcStress()
-
- def saveTotalMatrix(self,fp='output_matrix.txt'):
- '''全体剛性行列の保存'''
- f = open(fp,'w')
- for i in range(self.numberOfNode*2):
- for j in range(self.bandWidth+1):
- f.write(str(self.totalMat[i][j])+'\t')
- f.write('\n')
- f.close()
- print('Saved TotalMatrix: %s' % fp)
-
- def saveDisp(self,fp='output_disp.txt'):
- '''節点変位の保存'''
- f = open(fp,'w')
- f.write('節点番号\tX変位\tY変位\n')
- for i in range(self.numberOfNode):
- f.write('%d\t' % (i+1))
- f.write('%f\t' % self.nodes[i].disp[0])
- f.write('%f\n' % self.nodes[i].disp[1])
- f.close()
- print('Saved NodeDisp: %s' % fp)
-
- def saveForce(self,fp='output_force.txt'):
- '''節点力の保存'''
- f = open(fp,'w')
- f.write('節点番号\tX\tY\n')
- for i in range(self.numberOfNode):
- f.write('%d\t' % (i+1))
- f.write('%f\t' % self.nodes[i].force[0])
- f.write('%f\n' % self.nodes[i].force[1])
- f.close()
- print('Saved NodeDisp: %s' % fp)
-
- def saveStress(self,fp='output_stress.txt'):
- '''要素応力の保存'''
- f = open(fp,'w')
- f.write('Element\tX-Stress\tY\tXY\tMAX\tMin\tMax-T\tTheta\tEq-S\tTau_Max\n')
- for i in range(self.numberOfElement):
- f.write(str(i+1)+'\t')
- for j in range(9):
- f.write(str(self.elems[i].stress[j])+'\t')
- f.write('\n')
- f.close()
- print('Saved Stress: %s' % fp)
-
- def main(self):
- self.readNodeData()
- self.readMaterialData()
- self.readElementData()
- self.setElementMatrix()
- self.setBandWidth()
- self.setTotalMatrix()
- self.setBoundaryCondition()
- self.saveForce()
- self.saveTotalMatrix()
- self.solve()
- self.saveDisp()
- self.setStress()
- self.saveStress()
-
- def main():
- fem = Fem2D()
- fem.main()
-
- if __name__ == '__main__':
- main()
-