使用 Python 建模泰勒表方法


泰勒表方法是一种非常高效且优雅的方法,用于在考虑特定模板大小的情况下,获得特定导数的有限差分格式。要理解它,必须非常清楚什么是模板。

假设想要评估 $\mathrm{\frac{d^{2}f}{dx^{2}}}$,那么在有限差分方法中,起点是泰勒级数。请参考下图以更好地理解该方法。

点 $\mathrm{x_{i} \: + \: h}$ 处的泰勒级数展开式为

$$\mathrm{f(x_{i} \: + \: h) \: = \: f(x_{i}) \: + \: hf'(x_{i}) \: + \: \frac{h^{2}}{2!}f''(x_{i}) \: + \:\frac{h^{3}}{3!}f'''(x_{i}) \: + \:\frac{h^{3}}{3!}f'''(x_{i}) \: + \: \dotso}$$

$$\mathrm{f(x_{i} \: − \: h) \: = \: f(x_{i}) \: − \: hf'(x_{i}) \: + \: \frac{h^{2}}{2!}f''(x_{i}) \: − \:\frac{h^{3}}{3!}f'''(x_{i}) \: + \:\frac{h^{3}}{3!}f'''(x_{i}) \: − \: \dotso}$$

让我们将以上两个方程相加,并将包含二阶导数的项分离出来

$$\mathrm{f''(x_{i}) \: = \: \frac{f(x_{i} \: + \: h) \: − \: 2f(x_{i}) \: + \: f(x_{i} \: − \: h)}{h^{2}}}$$

现在,这是考虑点 $\mathrm{f(x_{i} \: + \: h) \: , \: f(x_{i})}$ 和 $\mathrm{f(x_{i} \: − \: h)}$ 的二阶导数近似值。这就是我们所说的模板。基本上,模板是用于数值逼近导数的一组点。为了简化书写任务,每当需要写 $\mathrm{f(x_{i})}$ 时,都将简单地写成 $\mathrm{f_{i}}$,类似地,将 $\mathrm{f(x_{i} \: − \: h)}$ 写成 $\mathrm{f_{i − 1}}$ 等等。

现在这很容易,但当任务是考虑模板中非常多的点数,并且必须针对此模板获得某个导数的数值表达式时,问题就会变得非常复杂和困难。假设已经给出需要获得三阶导数 $\mathrm{(f'''(x_{i}))}$,并考虑模板 $\mathrm{f_{i} \: , \: f_{i+1} \: , \: f_{i+2} \: , \: f_{i+3}}$。那么任务将变得非常繁琐且耗时。因此,为了简化任务,泰勒表方法变得非常方便。

该方法可以很容易地解释如下

首先,将导数写成如下形式

$$\mathrm{f'''(x_{i}) \: = \: a \: f_{i} \: + \: b \: f_{i+1} \: + \: c \: f_{i+2} \: + \: d \: f_{i+3}}$$

现在任务是找到 a、b、c 和 d。我们将导数及其系数排列成如下表格的形式。

用黄色突出显示的单元格将填充对应于 $\mathrm{1^{st}}$ 列中显示的模板的泰勒级数的系数。在红色突出显示的单元格中,我们将放置 0,除了对应于 $\mathrm{f'''(x_{i})}$ 的那个单元格。

第一行乘以 a,第二行乘以 b,第三行乘以 c,第四行乘以 d,然后全部相加并与最后一列(考虑维度)相等,得到以下方程

$$\mathrm{a \: + \: b \: + \: c \: + \: d \: = \: 0}$$

$$\mathrm{(0 \: + \: b \: + \: 2c \: + \: 2d) \: = \: 0/h}$$

$$\mathrm{(0 \: + \: b/2 \: + \: 2c \: + \: 9d/2) \: = \: 0/h^{\wedge}2}$$

$$\mathrm{(0 \: + \: b/6 \: + \: 4c/3 \: + \: 9d/2) \: = \: 0/h^{\wedge}3}$$

现在这些可以很容易地排列成矩阵形式,很容易求解。但仍然这是一个非常繁琐的任务,如果模板大小进一步增加,那么它将变得非常困难。因此,本文使用 Python 编程来简化任务。

Python 中泰勒表的实现

我们将要做的第一件事是编写一个代码来获得泰勒级数的系数。通常,泰勒级数写成。

$$\mathrm{f(x_{i} \: + \: \beta h) \: = \: f(x_{i}) \: + \: \beta f'(x_{i})h \: + \: \frac{\beta^{2}}{2!}f''(x_{i})h^{2} \: + \: \frac{\beta^{3}}{3!}f'''(x_{i})h^{3} \: + \: \frac{\beta^{4}}{4!}f''''(x_{i})h^{4} \: + \: \dots}$$

因此,上述级数的 $\mathrm{i^{th}}$ 系数可以写成:$\mathrm{(\frac{\alpha^{i}}{i!})}$。所以首先我们将为它编写函数,如下所示

Importing modules
from numpy import *
from math import *
# Taylor series function
def TSC(n,α):
   """
   n: Number of terms in the series
   α: coefficient of h
   """
   
   # Empty array of coefficients
   c=empty(n)
   for i in range(n):
      c[i]=α**i/factorial(i)
   return c

函数 TSC 将接受级数中的项数和 $\mathrm{\alpha}$。

然后,我们将使用此函数来获得不同模板元素的系数,即之前用黄色突出显示的泰勒表的行。

为了演示它,假设想要使用模板 $\mathrm{(f_{i-1} \: , \: f_{i}, \: and \: f_{i+1})}$ 来评估 $\mathrm{d^{2}f/dx^{2}}$。我们将形成一个模板数组,使其包含以下代码中提到的元素

$$\mathrm{f_{i} \: : \: 0}$$

$$\mathrm{f_{i − 1} \: : \: −1}$$

$$\mathrm{f_{i+1} \: : \: +1}$$

$$\mathrm{f_{i−2} \: : \: −2}$$

$$\mathrm{f_{i+3} \: : \: 3}$$

我们还将提供必须通过泰勒表逼近的导数的阶数。然后,使用 for 循环填充表中的元素,如下所示

# Instruction for setting stencil
#================================#
# 1. f_i --> 0
# 2. f_(i-1)-->-1
# 3. f_(i+1)--> 1
# 4. f_(i-2)-->-2
# 5. f_(i+2)--> 2
#================================#
# Forming Stencil array
st=array([-1,0,1])

# Order of derivative to be evaluated
order=2

# Number of rows and columns in the Taylor table
nt=len(st)

Taylor_Table=empty((nt,nt))
for i in range(nt):
   Taylor_Table[i,:]=TSC(nt,st[i])
Taylor_Table

输出将如下所示

array([[1. , -1. , 0.5],
       [1. , 0. , 0. ],
       [1. , 1. , 0.5]])

现在必须如下设置向量 b

# Right hand vector
b=zeros(nt)

# Setting b as per derivatiev given
b[order]=1
b

这将返回以下输出

$$\mathrm{array([0. \: , \: 0. \: , \: 1.])}$$

在设置向量时,我们已确保给定导数正下方的那个值应为 1。但泰勒表矩阵和向量不能按原样求解,因为它们没有采用正确的形式,因此必须在应用任何内置矩阵求解方法之前进行转置,然后如下求解

a=linalg.solve(transpose(Taylor_Table),transpose(b))

这将产生以下输出

$$\mathrm{array([−0.5 \: , \: 0. \: , \: 0.5])}$$

但是,在最终答案中,我们应该得到这些值除以 h 的某些适当幂。这是借助以下代码完成的

for i in range(nt): 
   print(f"a[{i}] = {a[i]}/h^{order}")

因此,最终答案将如下所示

a[0] = 1.0/h^2
a[1] = -2.0/h^2
a[2] = 1.0/h^2

因此,导数可以写成

$$\mathrm{f''(x_{i}) \: = \: a[0]f_{i-1} \: + \: a[1]f_{i} \: + \: a[2]f_{i+1}}$$

$$\mathrm{f''(x_{i}) \: = \: \frac{f(x_{i} \: + \: h) \: − \: 2f(x_{i}) \: + \: f(x_{i} \: − \: h)}{h^{2}}}$$

完整代码如下

# Importing modules
from numpy import *
from math import *

# Taylor series function
#================================#
def TSC(n,α):
   """
   
   n: Number of terms in the series
   α: coefficient of h
   """
   
   # Empty array of coefficients
   c=empty(n)
   for i in range(n):
      c[i]=α**i/factorial(i)
   return c
#================================#

# Instruction for setting stencil
# 1. f_i --> 0
# 2. f_(i-1)-->-1
# 3. f_(i+1)--> 1
# 4. f_(i-2)-->-2
# 5. F1_(i+2)--> 2
#================================#

# Forming the Stencil array
st=array([-1,0,1])

# Order of derivative term
order=2

# Number of rows and columns in the taylor table
nt=len(st)

Taylor_Table=empty((nt,nt))
for i in range(nt):
   Taylor_Table[i,:]=TSC(nt,st[i])
Taylor_Table
#================================#

# Right hand vector
b=zeros(nt)

# Setting b as per derivatiev given
b[order]=1
#================================#

# Solving the matrix
a=linalg.solve(transpose(Taylor_Table),transpose(b))

#================================#
# Printing the final answer
for i in range(nt):
   print(f"a[{i}] = {a[i]}/h^{order}")
#================================#

在上面的代码中,只需要更改第 33 行和第 36 行的模板和阶数。

让我们解决引言部分中提到的问题。

$$\mathrm{f'''(x_{i}) \: = \: a[0]f_{i} \: + \: a[1]f_{i+1} \: + \: a[2]f_{i+2} \: + \: a[3]f_{i+3}} $$

这里,模板将为:st=array([0,1,2,3]),阶数将为 3。程序输出将如下所示

a[0] = -1.0/h^3
a[1] = 3.0/h^3
a[2] = -3.0/h^3
a[3] = 1.0/h^3

结论

在本教程中,使用 Python 编程实现了泰勒表方法。此外,首先解释了该方法,然后解释了 Python 策略。

更新于: 2023 年 10 月 4 日

208 次查看

开启您的 职业生涯

通过完成课程获得认证

立即开始
广告