1 # Poisson‘s equation之实现 - 有限元法 2 # 注意, 采用Gauss-Legendre Quadrature进行数值积分 3 4 import numpy 5 from matplotlib import pyplot as plt 6 7 8 numpy.random.seed(0) 9 10 11 # Gauss-Legendre Quadrature之实现 12 def getGaussParams(num=6): 13 if num == 1: 14 X = numpy.array([0]) 15 A = numpy.array([2]) 16 elif num == 2: 17 X = numpy.array([numpy.math.sqrt(1/3), -numpy.math.sqrt(1/3)]) 18 A = numpy.array([1, 1]) 19 elif num == 3: 20 X = numpy.array([numpy.math.sqrt(3/5), -numpy.math.sqrt(3/5), 0]) 21 A = numpy.array([5/9, 5/9, 8/9]) 22 elif num == 6: 23 X = numpy.array([0.238619186081526, -0.238619186081526, 0.661209386472165, -0.661209386472165, 0.932469514199394, -0.932469514199394]) 24 A = numpy.array([0.467913934574257, 0.467913934574257, 0.360761573028128, 0.360761573028128, 0.171324492415988, 0.171324492415988]) 25 elif num == 10: 26 X = numpy.array([0.973906528517240, -0.973906528517240, 0.433395394129334, -0.433395394129334, 0.865063366688893, -0.865063366688893, 27 0.148874338981367, -0.148874338981367, 0.679409568299053, -0.679409568299053]) 28 A = numpy.array([0.066671344307672, 0.066671344307672, 0.269266719309847, 0.269266719309847, 0.149451349151147, 0.149451349151147, 29 0.295524224714896, 0.295524224714896, 0.219086362515885, 0.219086362515885]) 30 else: 31 raise Exception(">>> Unsupported num = {} <<<".format(num)) 32 return X, A 33 34 35 def getGaussQuadrature(func, a, b, X, A): 36 ‘‘‘ 37 func: 原始被积函数 38 a: 积分区间下边界 39 b: 积分区间上边界 40 X: 求积节点数组 41 A: 求积系数数组 42 ‘‘‘ 43 term1 = (b - a) / 2 44 term2 = (a + b) / 2 45 term3 = func(term1 * X + term2) 46 term4 = numpy.sum(A * term3) 47 val = term1 * term4 48 return val 49 50 51 class PoissonEq(object): 52 53 def __init__(self, n, order=6): 54 self.__n = n # 子区间划分数 55 self.__order = order # Legendre多项式之阶数 56 57 self.__X = self.__build_gridPoints(n) # 构造网格节点 58 self.__XQuad, self.__AQuad = getGaussParams(order) # 获取数值积分之求积节点、求积系数 59 60 61 def get_solu(self): 62 A = self.__build_A() 63 b = self.__build_b() 64 alpha = numpy.matmul(numpy.linalg.inv(A), b) 65 66 U = numpy.zeros(self.__X.shape) 67 U[1:-1] = alpha.flatten() 68 69 return self.__X, U 70 71 72 def __build_b(self): 73 ‘‘‘ 74 构造列向量b 75 ‘‘‘ 76 self.__xiMinusOne, self.__xi, self.__xiPlusOne = None, None, None 77 78 b = numpy.zeros((self.__n-1, 1)) 79 for i in range(b.shape[0]): 80 self.__xiMinusOne = self.__X[i] 81 self.__xi = self.__X[i+1] 82 self.__xiPlusOne = self.__X[i+2] 83 quadValLeft = getGaussQuadrature(self.__funcLeft, self.__xiMinusOne, self.__xi, self.__XQuad, self.__AQuad) 84 quadValRight = getGaussQuadrature(self.__funcRight, self.__xi, self.__xiPlusOne, self.__XQuad, self.__AQuad) 85 b[i, 0] = quadValLeft + quadValRight 86 return b 87 88 89 def __funcLeft(self, x): 90 val = (x - self.__xiMinusOne) / (self.__xi - self.__xiMinusOne) * numpy.sin(numpy.pi * x) 91 return val 92 93 94 def __funcRight(self, x): 95 val = (self.__xiPlusOne - x) / (self.__xiPlusOne - self.__xi) * numpy.sin(numpy.pi * x) 96 return val 97 98 99 def __build_A(self): 100 ‘‘‘ 101 构造矩阵A 102 ‘‘‘ 103 dPhiLeft = 1 / (self.__X[1:-1] - self.__X[:-2]) 104 dPhiRight = -1 / (self.__X[2:] - self.__X[1:-1]) 105 interval = self.__X[1:] - self.__X[:-1] 106 107 A = numpy.zeros((self.__n-1, self.__n-1)) 108 for i in range(A.shape[0]): 109 for j in range(A.shape[1]): 110 if j == i-1: 111 A[i, j] = dPhiLeft[i] * dPhiRight[j] * interval[i] 112 elif j == i: 113 A[i, j] = dPhiLeft[i] * dPhiLeft[j] * interval[i] + dPhiRight[i] * dPhiRight[j] * interval[i+1] 114 elif j == i+1: 115 A[i, j] = dPhiRight[i] * dPhiLeft[j] * interval[i+1] 116 return A 117 118 119 def __build_gridPoints(self, n): 120 ‘‘‘ 121 随机初始化网格节点 122 ‘‘‘ 123 xMin, xMax = 0, 1 124 X = numpy.sort(numpy.random.uniform(xMin, xMax, n+1)) 125 X[0] = xMin 126 X[-1] = xMax 127 return X 128 129 130 class PoissonPlot(object): 131 132 @staticmethod 133 def plot_fig(poissonObj): 134 X, U = poissonObj.get_solu() 135 136 xMin, xMax = numpy.min(X), numpy.max(X) 137 X_ = numpy.linspace(xMin, xMax, 1000) 138 U_ = numpy.sin(numpy.pi * X_) / numpy.pi ** 2 139 140 fig = plt.figure(figsize=(6, 4)) 141 ax1 = plt.subplot() 142 143 ax1.plot(X, U, marker=‘.‘, ls="--", label="numerical solution") 144 ax1.plot(X_, U_, label="analytical solution") 145 ax1.set(xlabel="$x$", ylabel="$u$") 146 ax1.legend() 147 fig.savefig("plot_fig.png", dpi=100) 148 149 150 151 if __name__ == "__main__": 152 n = 20 153 order = 6 154 poissonObj = PoissonEq(n, order) 155 156 PoissonPlot.plot_fig(poissonObj)
1D Poisson's Equation - Finite Element
原文:https://www.cnblogs.com/xxhbdk/p/14318749.html