fenics入门笔记

fenics入门笔记fenics 名称释义 fe finiteelemen 的简写 cs computationa 的简写 ni 有了 fe 和 cs 后 由于最初 fenics 软件是在芝加哥大学 简称为 phoe

大家好,欢迎来到IT知识分享网。

fenics名称释义:

fe:finite element的简写

cs:computational software的简写

ni:有了fe和cs后,由于最初fenics软件是在芝加哥大学(简称为phoenix)编译的,故而在其间加入ni就很自然而然了。其实就是取个谐音。

 

fenics有如下几个核心部件:

1. dolfin:

dynamic object-oriented library for finite element computation的简写。

意思就是用于有限元计算的动态面向对象库。它本质上是fenics的C++后端,配了python的接口,它实现了mesh、function space、finite element assembly、 refinement等数据结构及算法。

 

2. UFL:

The Unified Form Language的简写,这是一种用于声明有限元离散变分格式(variational form)的专用语言,它是建立在python语言上的,所以可以看作是一种推广了的python语言。具体地讲,利用这种语言我们可以以非常贴近数学记法的方式来编写计算程序。

 

dolfin和UFL都是FEniCS项目的一部分,前者可看作是用于求解问题的环境,它提供了积分域、边界条件等信息;后者则可视为前者的工具,也就是说:dolfin使用UFL的语法来指定(表出)具体的变分形式。

 

3. FFC:

The Fenics Form Compiler,也就是fenics中有限元变分型的编译器,可以把用UFL语言写的多线性型编译为更高效的C++代码。例如,把定义了一个变分问题的双线性型(左端)和线性型(右端)编译成能被用于组装对应的线性系统的代码。

 

4.FIAT:

Finite element automatic tabulator:在线段、三角形、四面体上生成任意阶的有限元

 

5. mshr:

fenics的网格生成器。

 

不同组件间的交互关系:

————————————————————————–

应用层          fenics apps

————————————————————————–

接口              dolfin

————————————————————————–

核心组件       ufl    syfi     ffc     ufc                                         ufl:unified form language;ffc:form compiler;

                      fiat   instant     ferari                                         ufc:unified form-assembly code

————————————————————————–

外部库           pets  numpy …

————————————————————————–

fenics特点:在python/C++语法基础上,进一步针对有限元的数学语言进行了语法抽象,从而可以以一种非常贴近数学语言的方式来编写有限元程序。其实就是fenics花了大功夫自己写了一套有限元语言的编译器,从而可以自动生成底层代码。由于用户在非常高的抽象层次上进行编程,所以不需要考虑很多底层的处理。例如矩阵组装,数值积分,线性代数处理等等。

如果采用python接口,只需提供一个.py文件;如果采用C++接口,需提供.ufl和.cc文件。大多数fenics提供的C++库都可以通过python来调用,故而使用python和C++在效率上可能不会差太多。

先采用UFL语言来编写程序。写好之后,使用ffc编译器可将其编译成低级的按UFC(Unified Form-assembly Code)格式的C++代码。生成的这些代码可以被基于UFC的组装器,例如DOLFIN,组装成离散的方程组。

使用C++利用fenics的方式如图示:

demo.ufl——(FFC)——>demo.h

                                        demo.cpp——(C++ compiler)——>demo

在这里,form compiler FFC生成了头文件demo.h,它定义了一些适用于特定问题的类,这些类可以被用在main程序中,也可以被传递给dolfin库。它们提供了有限元组装过程的最内层循环所需要的函数功能,即:

* 基函数及其导数值的求取

* 局部自由度到全局自由度的映射关系

* 局部单元上刚度矩阵的求取

实现这些函数功能的的代码是由.ufl文件中所提供的顶层描述经form compiler解释后自动生成的。相反地,如果使用python写程序的话, 则form compiler会在需要的时候被自动调用(just in time)。

一个例子(.ufl+.cpp):

解Poisson方程。

1. 第一步,写ufl文件。

先使用ufl语言来表述变分形式,下面这些是写在文件example_poisson.ufl中的:

element = FiniteElement("Lagrange", triangle, 1) u = TrialFunction(element) v = TestFunction(element) f = Coefficient(element) g = Coefficient(element) a = inner(grad(u), grad(v))*dx L = f*v*dx + g*v*ds

2. 第二步,生成当前问题所用的C++对象。

对上一步编写的ufl文件进行编译(解释),使用FFC编译得到一个头文件example_poisson.h,命令为:

ffc -l dolfin example_poisson.ufl

此时,FFC会自动生成如下类:FunctionSpace,BilinearForm和LinearForm。

3. 第三步,编写Poisson C++ code。

此时进行main程序的编写,在其中会用到dolfin下的类Function,SubDomain,UnitSquare,Constant,DirichletBC,VariationalProblem和File。此外,也会用到example_poisson.h头文件中我们自己定义的FunctionSpace,BilinearForm和LinearForm类。

#include <dolfin.h> #include "example_poisson.h" // For convenience using namespace dolfin;

然后进行源项、边界法向导数和dirichlet边界条件的定义。这些都采用dolfin类的派生类来定义,我们只需要自己定义这些项的函数功能即可。

// Source term (right-hand side) class Source : public Expression { void eval(Array<double>& values, const Array<double>& x) const { // The indexes are the dimension (x-dim := x[0], y-dim := x[1]) // dx and dy are not derivatives, just differences. double dx = x[0] - 0.5; double dy = x[1] - 0.5; // values is passed by reference, so the output to the function is // is not void as one may suspect. values[0] = 10*exp(-(dx*dx + dy*dy) / 0.02); } }; // Normal derivative (Neumann boundary condition) class dUdN : public Expression { void eval(Array<double>& values, const Array<double>& x) const { values[0] = sin(5*x[0]); } }; // Sub domain for Dirichlet boundary condition class DirichletBoundary : public SubDomain { bool inside(const Array<double>& x, bool on_boundary) const { // if x = 0 or x = 1 within epsilon (machine precision) return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS; } };

然后是main函数,我们将其分为两个部分:建立问题和求解问题两部分。

int main() { // Create mesh and function space UnitSquare mesh(32, 32); // Unit Square Mesh [0x1], [0x1] with 32 rectangles in each direction Poisson::FunctionSpace V(mesh); // Define the FEM space relative to the mesh // Direchlet BC setup Constant u0(0.0); // The constant value DirichletBoundary boundary; // WHERE the BC exists (defined in class above) DirichletBC bc(V, u0, boundary); // Apply the constant to the boundary on the mesh // Define the variational problem // The coefficient matrices example_poisson::BilinearForm a(V,V); example_poisson::LinearForm L(V); Source f; // the source term dUdN g; // the boundary flux // attach the source and boundary terms to the linear term (sum matrices) L.f = f; L.g = g; ========================================================================================= // Setup the problem VariationalProblem problem(a, L, bc); Function u(V); // Solve the variational problem problem.parameters["linear_solver"] = "iterative"; problem.solve(u); File file("poisson.pvd"); // Save solution in VTK format file << u; plot(u); // Plot the solution return 0; }

Note:

注意用C++和python来写同样一套程序时在语法上的区别。例如创建对象的时候,在C++中是采用Class obj;的形式,而在python中是obj = Class();的形式。

一个例子(全python):

打开python交互窗口,输入如下代码:

>>> from dolfin import * >>> mesh = UnitSquareMesh(16, 16) >>> V=FunctionSpace(mesh, 'Lagrange', 3) 此时会调用即时编译器,在交互窗口会显示:Calling FFC just-in-time (JIT) compiler, this may take some time。

这里会使用FFC生成C++代码再利用C++编译器来编译。这只执行一次,结果缓存在~/.instant

>>>f=Expression("sin(6.0*pi*x[0])*sin(2.0*pi*x[1])", degree=2) 此时会调用即时编译器

生成的C++表达式用于计算会很省时

>>>def boundary(x, on_boundary): ...     return on_boundary #注意这里的缩进 ...  >>>bc=DirichletBC(V, 0.0, boundary)

函数boundary定义了计算域的边界,bc代表了空间V上的狄利克雷边界条件

>>>u=TrialFunction(V) >>>v=TestFunction(V) >>>a=inner(grad(u), grad(v))*dx >>>L=f*v*dx

上面这段代码使用了UFL语言定义了双线性型a和线性型L

>>>u=Function(V) >>>solve(a==L, u, bc) 调用即时编译器 调用即时编译器 求解线性变分问题

最后我们在空间V上创建了有限元函数u(TRialFunction和TESTFunction仅仅被看作是多线性型的参数而已,并不是在内存中有实际值的函数)。然后要求DOLFIN组装出线性系统并使用后端的线性代数工具进行求解。对于前者,也是由FFC来生成C++代码,再使用C++编译器来编译。这也是与网格无关的,因此即便网格被加密,这也不会再次执行。

>>>plot(u, interactive=True)

上述过程也可以写到一个.py脚本中,再在shell中执行。

 

FFC组件的介绍

我对于fenics中的FFC组件比较感兴趣,它能将专门的ufl语言翻译并自动生成C++代码,用到一些较高级的编程技术。所以我在这里专门做一些介绍。

在上面介绍到,使用命令ffc -l dolfin example_poisson.ufl可自动生成一个C++头文件,它里面将包含了在当前问题中可能用到的有限元类。这一看上去挺高级的技术是怎么实现的呢?在fenics book中对此进行了介绍。FFC把编译过程分为了如下几个阶段,每一阶段的输出结果会作为下一阶段的输入。

compile stage 0:Parsing:在这个阶段,用户指定的form被解释并保存为UFL abstract syntax tree(AST)。实际的parsing过程被交给python,从.ufl文件到UFL form对象的转化则通过UFL的操作符重载来实现。

input:python code或.ufl文件,output:UFL form

compile stage 1:Analysis:在这个阶段对UFL form进行预处理,抽取出form元数据(FormData),例如:用于定义form的是哪种有限元,系数的个数,单元类型(间隔,三角形或四面体)。

input:UFL form,output:预处理的UFL form和form元数据(metadata)

compile stage 2:Code representation:这个阶段检查输入并生成所有代码生成所需的数据。包括有限元基函数的生成,自由度映射的数据,可能的积分预计算。绝大多数复杂的翻译过程都发生在这一阶段。中间数据被保持为一个字典dictionary,把UFC函数名映射为代码生成所需的数据。最简单的情况,例如ufc::form::rank,这个数据可能是个简单数字,如2。更复杂的情况,如ufc::cell_tensor::tabulate_tensor,这个数据可能是个复杂的数据结构。

input:预处理的UFL form和form元数据,output:中间代表(intermediate representation)

compile stage 3:Optimization:这一阶段检查intermediate representation并实施优化。保存在intermediate representation字典中的数据被替换为优化后的数据,它编码了问题所需函数的优化版本。

input:intermediate representation,output:optimized intermediate representation

compile stage 4:Code generation:这个阶段检查优化后的IR并生成实际对应了每个UFC函数的C++代码。这个代码被保存为一个字典,它把UFC函数名映射为包含了C++代码的string。例如,ufc::form::rank生成的数据可能是字符串“return 2;”。把2/3/4三个阶段分开是有重要意义的,它使得阶段2和3可以将重心放在有关有限元和变分形式的算法方面,而阶段4则只集中于生成C++代码。

input:优化后的intermediate representation(OIR),output:C++代码

compile stage 5:Code formatting:这个阶段检查生成的C++代码,并将它按照UFC的代码格式进行格式化,生成一个或多个.h/.cpp文件。这里是实际写出C++代码文件的地方。这一阶段依赖于UFC代码的模板。

input:C++代码,output:C++代码文件。

 

 

卸载fenics:

1. 仅仅卸载fenics

sudo apt-get remove fenics

2. 卸载fenics及其依赖文件

sudo apt-get remove –auto-remove fenics

3. 清除本地的config/data

sudo apt-get purge fenics

或:sudo apt-get purge –auto-remove fenics

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/112401.html

(0)
上一篇 2026-01-18 16:45
下一篇 2026-01-18 17:10

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信