65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Python 解决计算物理学问题

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (11投票s)

2016年3月21日

CPOL

6分钟阅读

viewsIcon

91927

本文演示了如何使用 Python 和 Numpy 库以及 Matplotlib 来求解简单的拉普拉斯方程,并绘制方程的解。我们还将看到,使用 Python 可以写更少的代码,做更多的事情。

引言

拉普拉斯方程是一个简单的二阶偏微分方程。它也是椭圆型偏微分方程中最简单的例子。这个方程在科学,尤其是在物理学中非常重要,因为它描述了电势和引力势的行为,以及热传导。在热力学(热传导)中,我们将拉普拉斯方程称为稳态热方程或热传导方程。

在本文中,我们将使用数值方法而不是解析/微积分方法来求解拉普拉斯方程。当我们说数值方法时,我们指的是“离散化”。离散化是将微分方程的连续形式“转换”为微分方程的离散形式的过程;这也意味着通过离散化,我们可以将微积分问题转化为矩阵代数问题,这是编程所偏爱的。

在这里,我们将使用有限差分法来解决一个简单的热传导问题。我们将使用 Python 编程语言、Numpy(Python 的数值库)和 Matplotlib(用于在 Python 中绘制和可视化数据的库)作为工具。我们还将看到,使用 Python 可以写更少的代码,做更多的事情。

背景

在计算物理学中,我们“总是”使用编程来解决问题,因为计算机程序可以“快速”地进行大规模和复杂的计算。计算物理学可以用下图表示。

如今,有许多编程语言被用来解决许多数值问题,例如 Matlab。但在这里,我们将使用 Python,这是一种“易于学习”的编程语言,当然,它是免费的。它还拥有强大的数值、科学和数据可视化库,如 Numpy、Scipy 和 Matplotlib。Python 还提供并行执行,我们可以在计算机集群上运行它。

回到拉普拉斯方程,我们将在下一节中使用 Python 求解一个简单的二维热传导问题。这里,我假设读者对有限差分法有基本了解,因此我不详细介绍有限差分法的细节、离散化误差、稳定性、一致性、收敛性以及最快/最优迭代算法。我们将在此处跳过许多计算公式的步骤。

我们不进行数值-解析验证来求解问题,而是仅演示如何使用 Python、Numpy 和 Matplotlib 求解问题,当然,还会带有一些简化的计算物理学概念,以便不专门研究计算物理学的普通读者也能理解这里的源代码。

准备工作

为了生成下面的结果,我使用了这个环境

  • 操作系统:Linux Ubuntu 14.04 LTS
  • Python:Python 2.7
  • Numpy:Numpy 1.10.4
  • Matplotlib:Matplotlib 1.5.1

如果您正在运行 Ubuntu,您可以使用 pip 安装 Numpy 和 Matplotlib,或者您可以在终端中运行此命令。

$ sudo apt-get install python-numpy

并使用此命令安装 Matplotlib

$ sudo apt-get install python-matplotlib

请注意,Python 已预装在 Ubuntu 14.04 中。要尝试 Python,只需在终端中输入 Python 并按 Enter 键。

您也可以在 Windows 操作系统中使用 Python、Numpy 和 Matplotlib,但我更喜欢使用 Ubuntu。

Using the Code

这是二维笛卡尔坐标系下的拉普拉斯方程(对于热方程)

其中 T 是温度,x 是 x 维度,y 是 y 维度。x 和 y 是笛卡尔坐标系中位置的函数。如果您有兴趣查看上述方程的解析解,可以从这里查看。

这里,我们只需要求解拉普拉斯方程的二维形式。要解决的问题如下所示

我们将要做的,是找出上述二维平板内的稳态温度(这也意味着拉普拉斯方程的解),并给定边界条件(平板边缘的温度)。接下来,我们将离散化平板区域,并将其划分为网格,然后我们使用有限差分法离散化上述拉普拉斯方程。这是平板的离散化区域。

我们设 Δx = Δy = 1 cm,然后作成如下网格

请注意,绿色节点是我们想要知道温度(解)的节点,白色节点是边界条件(已知温度)。这里是上述拉普拉斯方程的离散形式。

在我们的例子中,最终的离散方程如下所示。

现在,我们准备好求解上述方程了。为了求解它,我们使用内部网格(绿色节点)的“猜测值”,这里我们将其设为 30 摄氏度(或者我们可以将其设为 35 度或其他值),因为我们不知道网格内部的值(当然,这些是我们想要知道的值)。然后,我们将迭代方程,直到迭代前的值与迭代后的值之差“足够小”,我们称之为收敛。在迭代过程中,内部网格的温度值会自我调整,它是“自纠正”的,所以当我们设置的猜测值越接近实际解,我们就能越快得到“实际”解。

我们已准备好编写源代码。为了使用 Numpy 库,我们需要在源代码中导入 Numpy,我们还需要导入 Matplotlib.Pyplot 模块来绘制我们的解。因此,第一步是导入必要的模块。

    import numpy as np
    import matplotlib.pyplot as plt

然后,我们将初始变量设置到我们的 Python 源代码中

    # Set maximum iteration
    maxIter = 500

    # Set Dimension and delta
    lenX = lenY = 20 #we set it rectangular
    delta = 1

    # Boundary condition
    Ttop = 100
    Tbottom = 0
    Tleft = 0
    Tright = 0

    # Initial guess of interior grid
    Tguess = 30

接下来,我们将设置“绘图窗口”和 meshgrid。这是代码

    # Set colour interpolation and colour map.
    # You can try set it to 10, or 100 to see the difference
    # You can also try: colourMap = plt.cm.coolwarm
    colorinterpolation = 50
    colourMap = plt.cm.jet

    # Set meshgrid
    X, Y = np.meshgrid(np.arange(0, lenX), np.arange(0, lenY))

np.meshgrid() 为我们创建网格(我们用它来绘制解),第一个参数是 x 维度,第二个参数是 y 维度。我们使用 np.arange() 来安排一个从某个值到某个值的元素值的一维数组,在我们的例子中,是从 0lenX 和从 0lenY。然后我们设置区域:我们定义一个二维数组,定义大小并将数组填充为猜测值,然后我们设置边界条件,请注意上面这里填充数组元素的语法。

    # Set array size and set the interior value with Tguess
    T = np.empty((lenX, lenY))
    T.fill(Tguess)

    # Set Boundary condition
    T[(lenY-1):, :] = Ttop
    T[:1, :] = Tbottom
    T[:, (lenX-1):] = Tright
    T[:, :1] = Tleft

然后我们就可以将最终方程应用到下面的 Python 代码中。我们使用 for 循环来迭代方程。

    # Iteration (We assume that the iteration is convergence in maxIter = 500)
    print("Please wait for a moment")
    for iteration in range(0, maxIter):
    	for i in range(1, lenX-1, delta):
	    	for j in range(1, lenY-1, delta):
		    	T[i, j] = 0.25 * (T[i+1][j] + T[i-1][j] + T[i][j+1] + T[i][j-1])

    print("Iteration finished")

您应该注意上面的代码缩进,Python 不使用括号,而是使用空格或缩进。好了,主要逻辑已经完成了。接下来,我们编写代码来绘制解,使用 Matplotlib。

    # Configure the contour 
    plt.title("Contour of Temperature")
    plt.contourf(X, Y, T, colorinterpolation, cmap=colourMap)

    # Set Colorbar
    plt.colorbar()

    # Show the result in the plot window
    plt.show()

    print("")

就这样,这是 **完整代码**。

    # Simple Numerical Laplace Equation Solution using Finite Difference Method
    import numpy as np
    import matplotlib.pyplot as plt

    # Set maximum iteration
    maxIter = 500

    # Set Dimension and delta
    lenX = lenY = 20 #we set it rectangular
    delta = 1

    # Boundary condition
    Ttop = 100
    Tbottom = 0
    Tleft = 0
    Tright = 30

    # Initial guess of interior grid
    Tguess = 30

    # Set colour interpolation and colour map
    colorinterpolation = 50
    colourMap = plt.cm.jet #you can try: colourMap = plt.cm.coolwarm

    # Set meshgrid
    X, Y = np.meshgrid(np.arange(0, lenX), np.arange(0, lenY))

    # Set array size and set the interior value with Tguess
    T = np.empty((lenX, lenY))
    T.fill(Tguess)

    # Set Boundary condition
    T[(lenY-1):, :] = Ttop
    T[:1, :] = Tbottom
    T[:, (lenX-1):] = Tright
    T[:, :1] = Tleft

    # Iteration (We assume that the iteration is convergence in maxIter = 500)
    print("Please wait for a moment")
    for iteration in range(0, maxIter):
	    for i in range(1, lenX-1, delta):
		    for j in range(1, lenY-1, delta):
			    T[i, j] = 0.25 * (T[i+1][j] + T[i-1][j] + T[i][j+1] + T[i][j-1])

    print("Iteration finished")

    # Configure the contour 
    plt.title("Contour of Temperature")
    plt.contourf(X, Y, T, colorinterpolation, cmap=colourMap)

    # Set Colorbar
    plt.colorbar()

    # Show the result in the plot window
    plt.show()

    print("")

它相当简短,*不是吗*?好的,您可以复制粘贴并保存源代码,将其命名为 findif.py。要执行 Python 源代码,请打开您的终端,然后进入您存放源代码的目录,键入

$ python findif.py

然后按 **Enter**。然后将出现绘图窗口。

您可以尝试更改边界条件的值,例如,将右侧边缘温度的值更改为 30 摄氏度(Tright = 30),结果将如下所示

关注点

Python 是一种“易于学习”的动态类型编程语言,它为计算物理学或其他科学学科提供了(开源的)强大库。由于 Python 是一种解释型语言,与 C 或 C++ 等编译型语言相比,它的速度较慢,但同样,它易于学习。我们也可以用更少的代码做更多的事情,这样我们就不会在编程上挣扎,而是可以专注于我们想要解决的问题。

在计算物理学中,使用 Numpy 和 Scipy(Python 的数值和科学库),我们可以解决许多复杂问题,因为它提供了矩阵求解器(特征值和特征向量求解器)、线性代数运算,以及信号处理、傅里叶变换、统计、优化等。

除了在计算物理学中的应用,Python 也被用于机器学习,甚至 Google 的 TensorFlow 也使用 Python。

历史

  • 2016 年 3 月 21 日:初始版本
© . All rights reserved.