偏微分方程的有限元方法
在多个科学分支中遇到的一类常见方程是偏微分方程。因此,在本文中,我将介绍一个名为 FreeFem++ 的软件包,该软件包旨在帮助您计算这些偏微分方程。
一种流行的求解这些类型方程的方法,也是 FreeFem++ 使用的方法,是有限元方法。此方法的基本思想是将整个问题域细分为较小区域的网格。然后,您应用仍然在局部有效的偏微分方程的简化版本。这使得问题成为一个可处理的问题,实际上可以在合理的时间内解决。
FreeFem++ 有几个不同的版本。早期的版本名为 freefem、freefem3D 和 freefem+。最新版本称为 FreeFem++,是用 C++ 编写的。它可以编译并在所有三个主要的操作系统 Windows、Mac OS X 和 Linux 上运行。由于这是Linux Journal,因此我在此处重点介绍 Linux。在基于 Debian 的发行版上,安装非常容易,只需执行以下操作:
sudo apt-get install freefem++
其他版本也可以作为 freefem 和 freefem3d 软件包提供。
尽管我在本文中专门讨论求解电磁场,但 FreeFem++ 是一个通用的有限元方法求解器。这意味着它应该能够处理大多数偏微分方程。
安装完成后,您将希望开始使用它。首先要注意的是,FreeFem++ 被设计用于“生产级”工作——意味着活跃的、高水平的研究工作。因此,它没有漂亮的前端来帮助新用户完成他们的首次尝试。最好将 FreeFem++ 视为一种编程语言,您可以使用它编写程序来解决您的问题。
第一步是定义您问题的几何形状。此步骤通常称为网格划分或构建网格。FreeFem++ 不包含任何 CAD 功能来直接构建几何形状。但是,您可以从一组边界描述中自动生成网格。FreeFem++ 可以接受一组描述您几何形状的方程,并基于 Delaunay-Voronoi 算法生成网格。作为一个简单的例子,假设您想要构建一个正方形对象。您可以使用以下命令创建相关的网格:
int sides = 8;
mesh Th = square(sides, sides);
从第一个示例中,您应该注意到 FreeFem++ 使用的语言与 C/C++ 非常相似。变量是类型化的,并且只能存储该类型的值。该语言也是多态的,因此命令和操作将根据参数或操作数的类型执行不同的操作。
您可以使用边界函数定义更复杂的形状。一个例子看起来像这样:
border aa(t=0, 2*pi) {x=cos(t); y=sin(t);}
然后,您可以将这些类型的对象传递给 buildmesh()
函数,以生成与您从更高级别的 square()
函数获得的相同类型的网格。
如果您想查看这些方程的实际外观(以验证您是否正确),您可以使用 plot()
函数来可视化它们。您可以传入您可能创建的边界函数,甚至是从 buildmesh()
获取的网格对象。
创建网格后,您需要从此网格创建一组二维空间,以便解决您的问题。这可以使用 fespace
函数完成:
fespace Vh(Th, P1);
Vh u,v;
P1
参数告诉 fespace
您想要的有限元类型,无论是连续的还是不连续的、光滑的、线性的还是带有气泡的。(有相当多的可能性可供选择,这将留给亲爱的读者作为练习。)
接下来,您需要在新生成的空间内定义有限元函数——在本例中为 u
和 v
。
现在您已经构建了所有的背景支架,您需要在您的问题几何形状中定义您的问题并解决它。您可以使用 problem
类型来定义更复杂的问题。例如,您可能想查看热板的冷却。以下代码将为您设置问题:
mesh Th=square(30,5,[6*x,y]);
fespace Vh(Th, P1);
Vh u=u0, v, uold;
problem thermic(u,v)=int2d(Th)(u*v/dt + k*(dx(u)
↪* dx(v) + dy(u) * dy(v)))
+ int1d(Th,1,3)(alpha*u*v)
- int1d(Th,1,3)(alpha*ue*v)
- int2d(Th)(uold*v/dt) + on(2,4,u=u0);
变量名 thermic
现在是一个函数调用。当您发出命令 thermic
时,FreeFem++ 将继续解决您定义的这个问题。此方法的目的是能够定义您的问题并在实际解决之前进行更改和调整。
如果问题更容易定义,您可以使用 solve
命令来定义您的问题并立即执行求解步骤。例如,如果您想模拟膜上的运动,您可以使用类似这样的代码:
solve Laplace(phi,w)=int2d(Th)(dx(phi)*dx(w)
↪+ dy(phi)*dy(w))
- int2d(Th)(f*w) + on(Gamma1, phi=z);
其中已定义了适当的有限元空间和函数。一旦 FreeFem++ 解决了您的问题,您就可以使用 plot
和有限元函数来可视化此数值解的实际结果。
虽然能够立即可视化您的工作结果很重要,但您需要有一种保存这项工作的方法,这样您就不需要不必要地重复任何计算。您可以使用 savemesh
函数保存生成的网格。您只需要传入要保存的网格和要使用的文件名:
savemesh(Th, "my_mesh.msh");
您可以在稍后使用 readmesh
命令重新加载此网格,例如:
mesh Sh = readmesh("my_mesh.msh");
输出结果有点麻烦。您可以访问标准的 C++ 输入/输出流,特别是 cin 和 cout,因此您可以通过这种方式转储数值结果。您还可以使用 ofstream
创建一个新的输出流,将内容写入特定文件,而不是重定向到标准输出的内容。通过这种方式,您可以完全控制保存哪些数据,以及此文件及其数据使用的格式。
现在您已经阅读了 FreeFem++ 的这篇介绍,您应该查看 Web 上的其他教程和文档。有几个很好的示例可供参考,应该至少为您提供一个起点,以解决您正在研究的特定问题。如果您尝试解决的问题特别大,FreeFem++ 也支持 MPI。通过这种方式,您可以将计算分布在数百个 CPU 上,并有望完成更多工作。