參考書籍是:《有限元方法基礎教程》(國際單位制)(第五版)
章節爲:第6章 建立平面應力和平面應變剛度方程
重要的事情繼續強調(有限元的基本計算流程):
Step 1: 選擇單元類型。
Step 2: 選擇位移函數。
Step 3: 定義應變/位移和 應力/應變關係。
Step 4: 推導單元剛度矩陣和方程。
Step 5: 組合單元剛度方程得出總體方程並引進邊界條件。
Step 6: 求解未知自由度。
Step 7:求解單元應變和應力。
Step 8: 解釋結果。
==> 關於三節點三角形單元的剛度矩陣的推導過程,詳見《有限元方法基礎教程》第6章 建立平面應力和平面應變剛度方程
==> 本次主要計算的問題見上圖。
==> 首先創建一個單元類。
==> 關於python中的構造函數(__init__方法)(因爲之前學習java程序,java程序有一個構造函數的說法)傳入的參數包括:三節點的座標,和楊氏模量,泊松比,以及單元的厚度。(單元的面積是根據節點的座標計算出來的)
import numpy as np
class T3(object):
# 接下來首先創建類的構造函數 __init__
# 對傳入的參數進行說明,需要傳入單元節點的座標數據 coordinates
# 傳入材料的楊氏模量E; 材料的泊松比 v
# 單元的厚度 t.
def __init__(self, coors, E, v, t):
self.coors = coors
self.E = E
self.v = v
self.t = t
self.B = None
self.D = None
self.A = None
在初始化中,我們給當前單元增加了B矩陣,D矩陣,A(單元面積)作爲當前單元類的屬性(attribute)。
==> 首先計算出對應的B矩陣,B矩陣的推導公式見《有限元方法基礎教程》。(B矩陣是由N矩陣求偏導得來的)。
def Bmat(self):
# coors中的數據排列規則是 x_i, x_j, x_m, y_i, y_j, y_m
x_i, x_j, x_m, y_i, y_j, y_m = self.coors
# 首先計算出當前對應的行列式
A2 = x_i * (y_j - y_m) + x_j*(y_m - y_i) + x_m*(y_i - y_j)
# 然後計算生成對應的a_i, a_j, a_m
a_i = x_j * y_m - y_j * x_m
a_j = y_i * x_m - x_i * y_m
a_m = x_i * y_j - y_i * x_j
# 計算生成對應的beta
b_i = y_j - y_m
b_j = y_m - y_i
b_m = y_i - y_j
# 計算生成對應的r_i, r_j, r_m
r_i = x_m - x_j
r_j = x_i - x_m
r_m = x_j - x_i
# 然後將上述的所有的數據組合成B矩陣
B = np.zeros((3, 6), dtype=np.float32)
B[0][0] = b_i
B[0][2] = b_j
B[0][4] = b_m
# 然後添加r數據
B[1][1] = r_i
B[1][3] = r_j
B[1][5] = r_m
# 然後下面添加對應的b和r數據
B[2][0] = r_i
B[2][1] = b_i
B[2][2] = r_j
B[2][3] = b_j
B[2][4] = r_m
B[2][5] = b_m
return A2/2, B/A2
此處不僅計算出了B矩陣,還有當前單元的面積。這在單元剛度矩陣的公式中仍有應用。
==> 接下來是計算出對應的D矩陣,D矩陣是應力,應變關係的矩陣,本文主要是針對平面應力問題(注意區分平面應力問題和平面應變問題,兩者最主要的區別,可以按照如下的規則:在3D問題中的,當有一個方向上的尺寸遠小於另外兩個方向上的尺寸時,可將該問題簡化爲平面應力問題;當有一個方向上的尺寸遠大於另外兩個方向上的尺寸時,可將該問題簡化爲平面應變問題)
# 接下來創建一個函數,來生成對應的D矩陣
def Dmat(self):
# 對於三角形三節點的,生成的D矩陣是3*3
D = np.array([[1, self.v, 0],
[self.v, 1, 0],
[0, 0, (1-self.v)/2]])
return D * self.E / (1 - self.v**2)
==> 對應於三節點三角形單元,其對應的單元剛度矩陣的表達式可以寫爲如下形式:
【k】= 【B】^T * 【D】 * 【B】 * t * A;
==>這裏我們需要計算B矩陣的轉置矩陣,可以調用numpy中對於矩陣的轉置操作; 也可以自己添加轉置操作。
def transpose(self, target:(list, np.ndarray)):
# 首先把target包裝成np.ndarray
if isinstance(target, list):
target = np.array(target)
# 然後創建一個新的數據內存
Tmat = np.zeros((target.shape[1], target.shape[0]), dtype=np.float32)
# 然後給Tmat進行遍歷賦值
for row in range(target.shape[0]):
for col in range(target.shape[1]):
Tmat[col][row] = target[row][col]
return Tmat
接下來創建一個生成單元剛度矩陣的函數。
def stiffness_Matrix(self):
# 這裏我麼首先需要獲取B矩陣
if self.B == None or self.A == None:
A, B = self.Bmat()
self.A = A
self.B = B
# 接下來獲取對應的轉置矩陣B_T
B_T = self.transpose(self.B)
# 然後獲取D矩陣
if self.D == None:
D = self.Dmat()
self.D = D
# 首先進行B_T矩陣與D矩陣的相乘
# 創建一個內存空間
Mat_1 = np.zeros((B_T.shape[0], self.D.shape[1]), dtype=np.float32)
# 創建一個臨時求和變量
sum_value = 0
# 然後接下來便是來計算出對應的數值
for row in range(B_T.shape[0]):
for col in range(self.D.shape[1]):
sum_value = 0
for n in range(B_T.shape[1]):
sum_value += B_T[row][n] * self.D[n][col]
else:
# 迭代結束後,當前位置的數據便計算完成了
Mat_1[row][col] = sum_value
# 循環結束後,當前的矩陣相乘便計算完畢了
# 接下來繼續處理Mat_1矩陣和B矩陣相乘的計算過程
# 開闢內存空間
Mat_2 = np.zeros((Mat_1.shape[0], self.B.shape[1]), dtype=np.float32)
for row in range(Mat_1.shape[0]):
for col in range(self.B.shape[1]):
sum_value = 0
for n in range(Mat_1.shape[1]):
sum_value += Mat_1[row][n] * self.B[n][col]
else:
Mat_2[row][col] = sum_value
# 矩陣乘積結束之後,需要做的是去乘t
return Mat_2 * self.t * A
==> 將上述問題的座標信息輸入到程序中去,得到對應的單元剛度矩陣。
對比書上的課後答案如下:
扶貧方式如下: