一步一步学习使用 Gmsh 下载本文

一步一步学习使用 Gmsh

1简介

下面我们讨论的是 Gmsh 所附带的例子。这些例子使用 C 和 C++ 的方式进行了比较详细的注释, Gmsh 的各种用法被逐渐引进来,我们从 t1.geo 开始1。 为了使用 Gmsh 来运行这些例子,我们有两种方案(事实上,运行的方式根据操作系统的不同会有更多的不一样,我们假设您是在一个类 UNIX 操作系统的 Shell 中来运行)。第一种运行 Gmsh 的方式是交互式的图形界面方式,您只需要在命令行下键入 $ gmsh

就可以了。软件会打开两个窗口:一个是图形窗口,其中有一个位于底部的状态条;另一个是菜单窗口,其中有一个菜单条和一些和上下文有关的按钮。您选择 File->Open 菜单,就能够去选择打开 t1.geo 这个文件。为了能够产生网格,您在 Module 菜单中选择 Mesh ,然后在上下文相关的按钮中选择您想要的维数,其中 1D 会在所有的线上分布网格、2D 会将所有的表面上产生网格、 3D 会在所有的立体中产生网格。您再选择保存,就能够将获得的网格存储起来。您还可以在菜单中选择存储的形式。存储的文件的文件名一般是输入文件的主文件名

2

加上和存储格式有关的扩展名。

另外一个交互式运行 Gmsh 的方法更加方便,您可以直接在命令行上加参数运行 $ gmsh t1.geo

另一个运行 Gmsh 的模式是非交互的模式。在这种模式下,没有图形界面,所有的操作都是非交互的。比如您想对于第一个例子产生二维的网格,您可以敲入 $ gmsh t1.geo -2

如果您想基于一个已有的背景网格 'bgmesh.pos' 来产生出网格,您就可以使用 $ gmsh t1.geo -2 -bgm -bgmesh.pos 5

Gmsh 能够同时读入好几个文件。第一个文件定义了这个项目,其他文件都被附加在其后。您可以使用 File->Merge 菜单来将这些文件合并到一起,当然,命令行也能做这件事情。这个功能对于后处理是有用的。比如,使用命令 $ gmsh t1.geo view1.pos view2.pos

就能够将后处理视图 'view1.pos' 和 'view2.pos' 与第一个例子 't1.geo' 合并起来。在 Post-Processing 模块中,会出现两个按钮,分别叫做 \scalar

34

map\和 \vector map\。左键点击按钮就会看到相应的视图,右键点击则会出现该视图的选项。如果您希望对于一个视图的选项的修改能够应用到所有的视图上,选择 'Apply next change to all views' 或者 'Force same options for

6

all view' 就可以了,这些功能在菜单 Options->Post-proccessing 中。

[1]

这个说明中没有解释网格和后处理文件的格式。请在 FORMATS 文件中找到相应的内容。

[2]

几乎所有的交互式命令都有快捷键。您在菜单 Help->Shortcuts 可以看到这些快捷键都是什么。

[3]

扩展名 .geo 可以去掉。

[4]

虽然直接在输入文件中定义变量和点非常方便,如果您通过交互的方式来定义曲线、表面和立体会觉得更加方便。请在模块 Geometry 中根据上下文相关按钮来完成这样的操作。比如您想加入一条样条曲线,您可以选择下面的按钮序列:Elementary->Add->New->Spline。然后在图形窗口的状态条中就会被要求选择一系列的点,然后点击 'e' 完成选择(点击 'q' 取消)。当整个的交互式命令完成后,您打开的文件的尾部就会添加上一个字符串来描述这条曲线。

[5]

如果您想使用背景网格,请阅读 'bgmesh.pos' 中的注释。

[6]

所有的交互式输入的选项也都能够通过文本输入文件实现。所有的有效选项以及它们当前的值,能够使用选择菜单 File->Save as

->Geometry->Gmsh current options 来存储到文件中。直接点击状态条上的问号 '?' 也能达到同样的效果。如果您想将现在的选项保存起来作为缺省的偏好设置,以便将来启动 Gmsh 时使用,请使用 Options->Save options now 菜单。

例子 1

/********************************************************************* *

* Gmsh tutorial 1 *

* 变量,基本实体,物理实体,背景网格 *

*********************************************************************/

// Gmsh 中所有几何体的描述使用是一种类似于 C 的语言。最简单的 // 构造这种语言的方法是 \

// 所有的命令都使用分号结尾。下面的行定义了一个叫做 'lc' 的变 // 量,并且设置其值为 0.007 :

lc = 0.007 ;

// 这个新创建的变量能够被用来定义一个 Gmsh 的基本实体:一个点 // 'Point'。一个点能够用四个数的表来表示,包括它的坐标 x, y, z // 以及一个特征长度用来指定该点处产生出来的网格尺度:

Point(1) = {0, 0, 0, 9.e-1 * lc} ;

// 网格尺度指的是网格中线段的长度、三角形的外接圆的半径和四面 // 体的外接球的半径。实际上的网格尺度的分布是使用的预先指定的 // 点上的特征尺度通过插值得到的。指定特征长度还有其他方法:比 // 如 吸引子(参考 t7.geo)和背景网格(参考 bgmesh.pos)。

// 如同上面的这个定义,更加复杂的表达式也能够通过变量构造出来。 // 这里,上面的变量 'lc' 被乘上了常数 9.e-1 作为了上面定义这个 // 点的第四个参数。 //

// 下面的一般的语法规则能够应用到定义所有的几何实体上: //

// “如果一个数定义了一个新的实体,它就是放在一对小括号 // 中,如果一个数引用了一个以前定义的实体,那么它就是 // 放在一对花括号中。” //

// 下面我们又定义了三个点:

Point(2) = {.1, 0, 0, lc} ; Point(3) = {.1, .3, 0, lc} ; Point(4) = {0, .3, 0, lc} ;

// Gmsh 中的第二种基本几何实体是曲线。直线是曲线中最简单的一 // 种。一条直线可以用一串点定义出来,比如下面的 Line 1 是从 // 点 1 出发的,到点 2 截止:

Line(1) = {1,2} ; Line(2) = {3,2} ; Line(3) = {3,4} ; Line(4) = {4,1} ;

// 第三种基本实体是曲面。为了使用上面的四条线定义一个简单的 // 矩形曲面,我们要先定义一个曲线闭环(line loop)。一个曲线闭 // 环是一串连接着的线,每条线上都带着一个符号,用来表示这条 // 线的方向。

Line Loop(5) = {4,1,-2,3} ;

// The surface is then defined as a list of line loops (only one // here):

// 然后这个曲面就能够使用一系列的曲线闭环来定义了(这里只有 // 一个):

Plane Surface(6) = {5} ;

// 这时候,Gmsh 知道所有的关于怎么显示这个矩形曲面和布上网格 // 的信息。但是我们还需要提供对网格中不同的元素(包括点、线、 // 三角形)指定区域指标(region number)。这可以通过定义物理实体 // 的方法实现。物理实体能够将网格中的元素分成组,给定一个区 // 域指标,并指定其定向。 //

// 比如,下面我们就将点 1 和点 2 组合到物理实体 1 中了:

Physical Point(1) = {1,2} ;

// 从而,两个元素会被同时输出到输出文件中,并具有区域指标 1。 // 对于曲线和曲面,也能这样指定相应的区域指标:

Physical Line(10) = {1,2,4} ; MySurface = 100;

Physical Surface(MySurface) = {6} ;

// 所有的在剖分曲线 1、2、4的时候产生的线元素都会被存储为区域 // 指标为 10,所有在剖分曲面 6 时产生的三角形都具有区域指标 100。 //

// 如果没有定义物理实体,网格中所有的元素都被直接存储为缺省的 // 定向,其区域指标为它们的基本区域指标。请参考 FORMATS 文件 // 了解网格和后处理的格式。

例子 2

/********************************************************************* *

* Gmsh tutorial 2 *

* 文件包含、几何变换、几何体推移、立体的几何实体和物理实体 *

*********************************************************************/

// 我们可以使用 Include 将第一个例子包含进来作为这里的基础:

Include \

// 为了能够从前面的 t1.geo 中建立更加复杂的几何体,有几个可能的方式。 //

// 我们可以先加入新的点、线、曲面,就象在 t1.geo 中做的那样:

Point(5) = {0, .4, 0, lc} ; Line(5) = {4, 5} ;

// 我们还可以通过几何变换来移动、加入或者推移基本的几何实体。比如, // 我们可以将点 3 向左移动 0.05:

Translate {-0.05,0,0} { Point{3} ; }

// 得到的这个点能够复制一个并沿着 y 轴移动 0.1:

Translate {0,0.1,0} { Duplicata{ Point{3} ; } }

// 当然,移动、旋转和推移命令不光能够用在点上,也能够用在曲线和曲 // 面上。下面的命令就是将 t1.geo 中曲面 6 和一个新的曲面 11 沿着 z // 轴推出去 'h':

h = 0.12 ;

Extrude Surface { 6, {0, 0, h} } ;

Line(7) = {3, 6} ; Line(8) = {6,5} ; Line Loop(10) = {5,-8,-7,3};

Plane Surface(11) = {10};

Extrude Surface { 11, {0, 0, h} } ;

// 所有的几何变换自动的会产生新的几何体,下面的命令允许手工指定 // 自动产生的点的特征长度:

Characteristic Length{6,22,2,3,16,12} = lc * 2 ;

// 如果说变换工具对于产生复杂的几何体非常方便的话,有时候产生一个 // 和已有的几何实体相同的平面几何体也是非常有用的。这可以通过菜单 // File->Save as->Geometry->Gmsh unrolled geometry 或者命令行 //

// $ gmsh t2.geo -0 //

// 来实现。

// 立体是 Gmsh 中的第四种基本几何体。和先定义了闭环曲线再定义曲面 // 一样,我们现在需要先定义闭环曲面(suface loop)。下面的立体是一 // 个单连通的,没有洞的体(所以只需要一个闭环曲面来定义它):

Surface Loop(145) = {121,11,131,135,139,144}; Volume(146) = {145};

Surface Loop(146) = {121,6,109,113,117,122}; Volume(147) = {146};

// 我们定义下面的物理立体实体使得所有剖分得到的四面体具有区域指标 1:

Physical Volume (1) = {146,147} ;

// 恭喜了!您现在已经得到了您的第一个无结构的三维四面体网格!

例子 3

/********************************************************************* *

* Gmsh tutorial 3 *

* 网格推移、选项 *

*********************************************************************/

// 我们还是先将例子 1 包含进来:

Include \

// 和 't2.geo' 中一样,我们也做一个沿着 z 骤的推移:

h = 0.1 ;

// 和 't2.geo' 中不同的是,我们不仅仅推移了几何体,而且推移了二维的 // 网格。命令还是相同的 Extrude,但是通过设置层数(这里,我们有四层, // 分别是 8, 4, 2, 1 个单元深度),立体数(从 9000 到 9003)以及相应 // 的高度为 h/4 来实现了网格的推移:

Extrude Surface { 6, {0,0,h} } {

Layers { {8,4,2,1}, {9000:9003}, {0.25,0.5,0.75,1} } ; } ;

// 和用平移进行推移一样,我们也可以使用一个旋转来进行推移,这样 // 得到的网格能够重组为三棱柱(如果曲面上的网格是三角形)或者 // 是六面体(如果曲面上的网格是四边形)。每个旋转通过一个轴向

// ({0,1,0})、一个轴心点({-0.1,0,0.1})以及一个角度(-Pi/2)来指定:

Extrude Surface { 122, {0,1,0} , {-0.1,0,0.1} , -Pi/2 } { Recombine ; Layers { 7, 9004, 1 } ; };

// 一个平移 ({-2*h,0,0}) 和一个旋转 ({1,0,0}, {0,0.15,0.25}, Pi/2) 能 // 够组合起来使用:

Extrude Surface {news-1, {-2*h,0,0}, {1,0,0} , {0,0.15,0.25} , Pi/2}{ Layers {10,9004,1}; Recombine; };

Physical Volume(101) = {9000:9004};

// 所有交互方式输入的选项都能够直接在输入文件中指定。比如下面 // 我们指定了一个全局的特征长度因子,重新设定了一些背景颜色, // 并设定不显示坐标轴,选择了一个初始给定的视图,禁止掉了交互 // 式的旋转选择视图:

Mesh.CharacteristicLengthFactor = 4;

General.Color.Background = {120,120,120}; General.Color.Foreground = {255,255,255};

General.Color.Text = White;

Geometry.Color.Points = Orange; General.Axes = 0;

General.Trackball = 0; General.RotationX = 10; General.RotationY = 70;

General.TranslationX = -0.2;

// 颜色可以通过文字方式或者 RGB 方式给定,比如 'General.Color.Background

// = Red' 与 'General.Color.Background = {255,0,0}' 是完全一样的。 // 这些选项就和用户定义的变量一样,能够用作任何的左值和右值, // 比如

Geometry.Color.Surfaces = Geometry.Color.Points;

// 将会把曲面的颜色设置得和点的颜色一样。

// 点击状态条上的问号 '?' 会将当前的左右选项打印在终端上,使用

// 菜单 File->Save as->Geometry->Gmsh current options 会将这些选项存 // 储到文件中。菜单 Options->Save options now 会将当前选项存储起 // 来作为将来的缺省选项。

例子 4

/********************************************************************* *

* Gmsh tutorial 4 *

* 内部函数、洞 *

*********************************************************************/

cm = 1e-02 ;

e1 = 4.5*cm ; e2 = 6*cm / 2 ; e3 = 5*cm / 2 ;

h1 = 5*cm ; h2 = 10*cm ; h3 = 5*cm ; h4 = 2*cm ; h5 = 4.5*cm ;

R1 = 1*cm ; R2 = 1.5*cm ; r = 1*cm ;

ccos = ( -h5*R1 + e2 * Hypot(h5,Hypot(e2,R1)) ) / (h5^2 + e2^2) ; ssin = Sqrt(1-ccos^2) ;

Lc1 = 0.01 ; Lc2 = 0.003 ;

// 下面是所有的操作符的列表,除了 '^' 以外,这些操作符和 C、C++ // 语言中都是一样的: //

// '-' (in both unary and binary versions, i.e. as in '-1' and '1-2') // '!' (the negation) // '+' // '*' // '/'

// '%' (the rest of the integer division) // '<' // '>' // '<=' // '>=' // '==' // '!='

// '&&' (and) // '||' (or) // '||' (or) // '^' (power)

// '?' ':' (the ternary operator) //

// 使用括号可以将表达式结合 //

// 除了这些操作符以外,所有的 C 数学函数也能够使用(注意首字母 // 要大写): //

// Exp(x) // Log(x) // Log10(x) // Sqrt(x) // Sin(x) // Asin(x) // Cos(x) // Acos(x) // Tan(x) // Atan(x)

// Atan2(x,y) // Sinh(x) // Cosh(x) // Tanh(x) // Fabs(x) // Floor(x) // Ceil(x) // Fmod(x,y) //

// 我们还有增加的函数: //

// Hypot(x,y) computes Sqrt(x^2+y^2)

// Rand(x) generates a random number in [0,x] //

// Gmsh 中唯一预定义的常数就是 Pi.

Point(1) = { -e1-e2, 0.0 , 0.0 , Lc1}; Point(2) = { -e1-e2, h1 , 0.0 , Lc1}; Point(3) = { -e3-r , h1 , 0.0 , Lc2}; Point(4) = { -e3-r , h1+r , 0.0 , Lc2}; Point(5) = { -e3 , h1+r , 0.0 , Lc2}; Point(6) = { -e3 , h1+h2, 0.0 , Lc1}; Point(7) = { e3 , h1+h2, 0.0 , Lc1}; Point(8) = { e3 , h1+r , 0.0 , Lc2}; Point(9) = { e3+r , h1+r , 0.0 , Lc2}; Point(10)= { e3+r , h1 , 0.0 , Lc2}; Point(11)= { e1+e2, h1 , 0.0 , Lc1}; Point(12)= { e1+e2, 0.0 , 0.0 , Lc1}; Point(13)= { e2 , 0.0 , 0.0 , Lc1};

Point(14)= { R1 / ssin , h5+R1*ccos, 0.0 , Lc2}; Point(15)= { 0.0 , h5 , 0.0 , Lc2}; Point(16)= { -R1 / ssin , h5+R1*ccos, 0.0 , Lc2}; Point(17)= { -e2 , 0.0 , 0.0 , Lc1};

Point(18)= { -R2 , h1+h3 , 0.0 , Lc2}; Point(19)= { -R2 , h1+h3+h4, 0.0 , Lc2}; Point(20)= { 0.0 , h1+h3+h4, 0.0 , Lc2}; Point(21)= { R2 , h1+h3+h4, 0.0 , Lc2}; Point(22)= { R2 , h1+h3 , 0.0 , Lc2}; Point(23)= { 0.0 , h1+h3 , 0.0 , Lc2};

Point(24)= { 0 , h1+h3+h4+R2, 0.0 , Lc2}; Point(25)= { 0 , h1+h3-R2, 0.0 , Lc2};

Line(1) = {1 ,17}; Line(2) = {17,16};

// 圆弧是通过三个给定的点来定义的,分别表示起始点、中心点和 // 截止点。所有的圆弧都是逆时针的。这三个点不应该在同一条直 // 线上,否则您应该指定这个圆弧位于那个平面上如 //

// Circle(num) = {start,center,end} Plane {nx,ny,nz}

Circle(3) = {14,15,16}; Line(4) = {14,13}; Line(5) = {13,12}; Line(6) = {12,11}; Line(7) = {11,10};

Circle(8) = { 8, 9,10}; Line(9) = { 8, 7}; Line(10) = { 7, 6}; Line(11) = { 6, 5};

Circle(12) = { 3, 4, 5}; Line(13) = { 3, 2}; Line(14) = { 2, 1}; Line(15) = {18,19};

Circle(16) = {21,20,24}; Circle(17) = {24,20,19}; Circle(18) = {18,23,25}; Circle(19) = {25,23,22}; Line(20) = {21,22};

Line Loop(21) = {17,-15,18,19,-20,16}; Plane Surface(22) = {21};

// 这个曲面有两条闭环曲线构造出来,从而它会有一个洞:

Line Loop(23) = {11,-12,13,14,1,2,-3,4,5,6,7,-8,9,10}; Plane Surface(24) = {23,21};

Physical Surface(1) = {22}; Physical Surface(2) = {24};

例子 5

/********************************************************************* *

* Gmsh tutorial 5 *

* 特征长度、变量数组、函数、循环 *

*********************************************************************/

// 先定义几个特征长度:

lcar1 = .1; lcar2 = .0005; lcar3 = .075;

// 为了能够不修改文件,而全局的改变这些长度,我们能够在

// 命令行指定一个因子或者指定 Mesh.CharacteristicLengthFactor // 选项来达成。例如 //

// $ gmsh t5 -clscale 1 //

// 将会产生一个大约两千个节点和一万个四面体的网格(在一台 // 666M 主频的 Alpha Workstation 上需要约 3 秒钟)。而 //

// $ gmsh t5 -clscale 0.2 //

// 会将所有的特征长度都缩小 5 倍,得到的网格将有大约 17 万 // 个节点,和大约 100 万个四面体,在同样的机器上,这需要花 // 费大约 16 分钟的时间,Gmsh 还需要很多改进来达到更高的效 // 率。

Point(1) = {0.5,0.5,0.5,lcar2}; Point(2) = {0.5,0.5,0,lcar1}; Point(3) = {0,0.5,0.5,lcar1}; Point(4) = {0,0,0.5,lcar1}; Point(5) = {0.5,0,0.5,lcar1}; Point(6) = {0.5,0,0,lcar1}; Point(7) = {0,0.5,0,lcar1}; Point(8) = {0,1,0,lcar1}; Point(9) = {1,1,0,lcar1}; Point(10) = {0,0,1,lcar1}; Point(11) = {0,1,1,lcar1}; Point(12) = {1,1,1,lcar1}; Point(13) = {1,0,1,lcar1}; Point(14) = {1,0,0,lcar1};

Line(1) = {8,9}; Line(2) = {9,12}; Line(3) = {12,11}; Line(4) = {11,8}; Line(5) = {9,14}; Line(6) = {14,13}; Line(7) = {13,12}; Line(8) = {11,10}; Line(9) = {10,13};

Line(10) = {10,4}; Line(11) = {4,5}; Line(12) = {5,6}; Line(13) = {6,2}; Line(14) = {2,1}; Line(15) = {1,3}; Line(16) = {3,7}; Line(17) = {7,2}; Line(18) = {3,4}; Line(19) = {5,1}; Line(20) = {7,8}; Line(21) = {6,14};

Line Loop(22) = {11,19,15,18}; Plane Surface(23) = {22}; Line Loop(24) = {16,17,14,15}; Plane Surface(25) = {24}; Line Loop(26) = {-17,20,1,5,-21,13}; Plane Surface(27) = {26}; Line Loop(28) = {4,1,2,3}; Plane Surface(29) = {28}; Line Loop(30) = {7,-2,5,6}; Plane Surface(31) = {30}; Line Loop(32) = {6,-9,10,11,12,21}; Plane Surface(33) = {32}; Line Loop(34) = {7,3,8,9}; Plane Surface(35) = {34}; Line Loop(36) = {10,-18,16,20,-4,8}; Plane Surface(37) = {36}; Line Loop(38) = {-14,-13,-12,19}; Plane Surface(39) = {38};

// 除了使用文件包含机制以外,我们还能定义函数。在下面的函数中, // 我们使用了保留词 'newp',这样能够自动的选择一个新的点数。这 // 个数是当前最大数加一得到的。相似的,'newreg' 保留词是所有除 // 去点以外的实体数中最大的加一。 //

// 这里还没有局部变量,在将来的版本中,我们会加入相应的功能。

Function CheeseHole

p1 = newp; Point(p1) = {x, y, z, lcar3} ; p2 = newp; Point(p2) = {x+r,y, z, lcar3} ; p3 = newp; Point(p3) = {x, y+r,z, lcar3} ; p4 = newp; Point(p4) = {x, y, z+r,lcar3} ; p5 = newp; Point(p5) = {x-r,y, z, lcar3} ; p6 = newp; Point(p6) = {x, y-r,z, lcar3} ; p7 = newp; Point(p7) = {x, y, z-r,lcar3} ;

c1 = newreg; Circle(c1) = {p2,p1,p7}; c2 = newreg; Circle(c2) = {p7,p1,p5}; c3 = newreg; Circle(c3) = {p5,p1,p4}; c4 = newreg; Circle(c4) = {p4,p1,p2}; c5 = newreg; Circle(c5) = {p2,p1,p3}; c6 = newreg; Circle(c6) = {p3,p1,p5}; c7 = newreg; Circle(c7) = {p5,p1,p6}; c8 = newreg; Circle(c8) = {p6,p1,p2}; c9 = newreg; Circle(c9) = {p7,p1,p3}; c10 = newreg; Circle(c10) = {p3,p1,p4}; c11 = newreg; Circle(c11) = {p4,p1,p6}; c12 = newreg; Circle(c12) = {p6,p1,p7};

// 下面我们定义了一些约束曲面:

l1 = newreg; Line Loop(l1) = {c5,c10,c4}; Ruled Surface(newreg) = {l1};

l2 = newreg; Line Loop(l2) = {c9,-c5,c1}; Ruled Surface(newreg) = {l2};

l3 = newreg; Line Loop(l3) = {-c12,c8,c1}; Ruled Surface(newreg) = {l3};

l4 = newreg; Line Loop(l4) = {c8,-c4,c11}; Ruled Surface(newreg) = {l4};

l5 = newreg; Line Loop(l5) = {-c10,c6,c3}; Ruled Surface(newreg) = {l5};

l6 = newreg; Line Loop(l6) = {-c11,-c3,c7}; Ruled Surface(newreg) = {l6};

l7 = newreg; Line Loop(l7) = {c2,c7,c12}; Ruled Surface(newreg) = {l7};

l8 = newreg; Line Loop(l8) = {-c6,-c9,c2}; Ruled Surface(newreg) = {l8};

// 曲面上的网格是通过将二维的网格投影到曲面的平均曲面上得到 // 的,这样只有当曲率很小的时候才能够得到比较好的效果,否则 // 的话,您需要将曲面手工分成很小的小片。

// 变量数组能够和变量一样进行操作。注意:对于一个没有初始化 // 的变量的读写会产生不可预知的结果。数组中的所有元素能够同 // 时初始化,如 l[]={1,2,7}。

theloops[t] = newreg ;

Surface Loop(theloops[t]) = {l8+1, l5+1, l1+1, l2+1, -(l3+1), -(l7+1), l6+1, l4+1};

thehole = newreg ;

Volume(thehole) = theloops[t] ;

Return

x = 0 ; y = 0.75 ; z = 0 ; r = 0.09 ;

// 这里使用一个 For 循环来产生立方体中的五个洞:

For t In {1:5}

x += 0.166 ; z += 0.166 ;

// 调用函数 CheeseHole,除了定义函数以外,我们如果写一个文件 // 包含相同的代码,并且使用 Include 命令将这个文件包含在其中 // 也能够达到同样的效果。

Call CheeseHole ;

// 每个 Cheese 洞定义为一个物理立体指标

Physical Volume (t) = thehole ;

// Printf 函数可以将变量的值打印在终端上,和 C 语言的 printf // 使用方法相似:

Printf(\number %g!\

t, x, y, z, r, thehole) ;

// 所有的 Gmsh 变量在内部都是当成 double 来处理的。所以上面的 // 格式化字符串都是使用的 %g ,请参看 C 或者 C++ 语言的参考资 // 料得到进一步的信息。

EndFor

// 这是这个曲面外部的曲面闭环:

theloops[0] = newreg ;

Surface Loop(theloops[0]) = {35,31,29,37,33,23,39,25,27} ;

// 这个包含 5 个 Cheese 洞的立体,是使用了六个曲面闭环定义出来 // 的(外部曲面闭环和内部的 5 个曲面闭环)。为了能够引用数组中 // 的所有元素,使用其名称加上 '[]' 的形式:

Volume(186) = {theloops[]} ;

// 最后,我们将这个立体中剖分出的四面体给定区域指标 10。

Physical Volume (10) = 186 ;

例子 6

/********************************************************************* *

* Gmsh tutorial 6 *

* Transfinite meshes *

*********************************************************************/

r_int = 0.05 ; r_ext = 0.051 ; r_far = 0.125 ; r_inf = 0.4 ;

phi1 = 30. * (Pi/180.) ; angl = 45. * (Pi/180.) ;

nbpt_phi = 5 ; nbpt_int = 20 ; nbpt_arc1 = 10 ; nbpt_arc2 = 10 ;

nbpt_shell = 10 ; nbpt_far = 25 ; nbpt_inf = 15 ;

lc0 = 0.1 ; lc1 = 0.1 ; lc2 = 0.3 ;

Point(1) = {0, 0, 0, lc0} ; Point(2) = {r_int, 0, 0, lc0} ; Point(3) = {r_ext, 0, 0, lc1} ; Point(4) = {r_far, 0, 0, lc2} ; Point(5) = {r_inf, 0, 0, lc2} ; Point(6) = {0, 0, r_int, lc0} ; Point(7) = {0, 0, r_ext, lc1} ; Point(8) = {0, 0, r_far, lc2} ; Point(9) = {0, 0, r_inf, lc2} ;

Point(10) = {r_int*Cos(phi1), r_int*Sin(phi1), 0, lc0} ; Point(11) = {r_ext*Cos(phi1), r_ext*Sin(phi1), 0, lc1} ; Point(12) = {r_far*Cos(phi1), r_far*Sin(phi1), 0, lc2} ; Point(13) = {r_inf*Cos(phi1), r_inf*Sin(phi1), 0, lc2} ;

Point(14) = {r_int/2, 0, 0, lc2} ; Point(15) = {r_int/2*Cos(phi1), r_int/2*Sin(phi1), 0, lc2} ;

Point(16) = {r_int/2, 0, r_int/2, lc2} ; Point(17) = {r_int/2*Cos(phi1), r_int/2*Sin(phi1), r_int/2, lc2} ;

Point(18) = {0, 0, r_int/2, lc2} ;

Point(19) = {r_int*Cos(angl), 0, r_int*Sin(angl), lc2} ;

Point(20) = {r_int*Cos(angl)*Cos(phi1), r_int*Cos(angl)*Sin(phi1), r_int*Sin(angl), lc2} ;

Point(21) = {r_ext*Cos(angl), 0, r_ext*Sin(angl), lc2} ;

Point(22) = {r_ext*Cos(angl)*Cos(phi1), r_ext*Cos(angl)*Sin(phi1), r_ext*Sin(angl), lc2} ;

Point(23) = {r_far*Cos(angl), 0, r_far*Sin(angl), lc2} ;

Point(24) = {r_far*Cos(angl)*Cos(phi1), r_far*Cos(angl)*Sin(phi1), r_far*Sin(angl), lc2} ;

Point(25) = {r_inf, 0, r_inf, lc2} ; Point(26) = {r_inf*Cos(phi1), r_inf*Sin(phi1), r_inf, lc2} ;

Circle(1) = {2,1,19}; Circle(2) = {19,1,6}; Circle(3) = {3,1,21}; Circle(4) = {21,1,7}; Circle(5) = {4,1,23}; Circle(6) = {23,1,8}; Line(7) = {5,25}; Line(8) = {25,9};

Circle(9) = {10,1,20}; Circle(10) = {20,1,6}; Circle(11) = {11,1,22}; Circle(12) = {22,1,7}; Circle(13) = {12,1,24}; Circle(14) = {24,1,8}; Line(15) = {13,26}; Line(16) = {26,9};

Circle(17) = {19,1,20}; Circle(18) = {21,1,22}; Circle(19) = {23,1,24}; Circle(20) = {25,1,26}; Circle(21) = {2,1,10}; Circle(22) = {3,1,11}; Circle(23) = {4,1,12}; Circle(24) = {5,1,13};

Line(25) = {1,14}; Line(26) = {14,2}; Line(27) = {2,3}; Line(28) = {3,4};

Line(29) = {4,5}; Line(30) = {1,15}; Line(31) = {15,10}; Line(32) = {10,11};

Line(33) = {11,12}; Line(34) = {12,13}; Line(35) = {14,15}; Line(36) = {14,16};

Line(37) = {15,17}; Line(38) = {16,17}; Line(39) = {18,16}; Line(40) = {18,17};

Line(41) = {1,18}; Line(42) = {18,6}; Line(43) = {6,7}; Line(44) = {16,19};

Line(45) = {19,21}; Line(46) = {21,23}; Line(47) = {23,25}; Line(48) = {17,20};

Line(49) = {20,22}; Line(50) = {22,24}; Line(51) = {24,26}; Line(52) = {7,8};

Line(53) = {8,9};

Line Loop(54) = {39,-36,-25,41}; Ruled Surface(55) = {54}; Line Loop(56) = {44,-1,-26,36}; Ruled Surface(57) = {56};

Line Loop(58) = {3,-45,-1,27}; Ruled Surface(59) = {58}; Line Loop(60) = {5,-46,-3,28}; Ruled Surface(61) = {60}; Line Loop(62) = {7,-47,-5,29}; Ruled Surface(63) = {62}; Line Loop(64) = {-2,-44,-39,42}; Ruled Surface(65) = {64}; Line Loop(66) = {-4,-45,2,43}; Ruled Surface(67) = {66}; Line Loop(68) = {-6,-46,4,52}; Ruled Surface(69) = {68}; Line Loop(70) = {-8,-47,6,53}; Ruled Surface(71) = {70}; Line Loop(72) = {-40,-41,30,37}; Ruled Surface(73) = {72}; Line Loop(74) = {48,-9,-31,37}; Ruled Surface(75) = {74}; Line Loop(76) = {49,-11,-32,9}; Ruled Surface(77) = {76}; Line Loop(78) = {-50,-11,33,13}; Ruled Surface(79) = {78}; Line Loop(80) = {-51,-13,34,15}; Ruled Surface(81) = {80}; Line Loop(82) = {10,-42,40,48}; Ruled Surface(83) = {82}; Line Loop(84) = {12,-43,-10,49}; Ruled Surface(85) = {84}; Line Loop(86) = {14,-52,-12,50}; Ruled Surface(87) = {86}; Line Loop(88) = {16,-53,-14,51}; Ruled Surface(89) = {88}; Line Loop(90) = {-30,25,35}; Ruled Surface(91) = {90}; Line Loop(92) = {-40,39,38}; Ruled Surface(93) = {92}; Line Loop(94) = {37,-38,-36,35}; Ruled Surface(95) = {94}; Line Loop(96) = {-48,-38,44,17}; Ruled Surface(97) = {96}; Line Loop(98) = {18,-49,-17,45}; Ruled Surface(99) = {98}; Line Loop(100) = {19,-50,-18,46}; Ruled Surface(101) = {100}; Line Loop(102) = {20,-51,-19,47}; Ruled Surface(103) = {102}; Line Loop(104) = {-2,17,10}; Ruled Surface(105) = {104}; Line Loop(106) = {-9,-21,1,17}; Ruled Surface(107) = {106}; Line Loop(108) = {-4,18,12}; Ruled Surface(109) = {108}; Line Loop(110) = {-11,-22,3,18}; Ruled Surface(111) = {110}; Line Loop(112) = {-13,-23,5,19}; Ruled Surface(113) = {112}; Line Loop(114) = {-6,19,14}; Ruled Surface(115) = {114}; Line Loop(116) = {-15,-24,7,20}; Ruled Surface(117) = {116}; Line Loop(118) = {-8,20,16}; Ruled Surface(119) = {118}; Line Loop(120) = {-31,-35,26,21}; Ruled Surface(121) = {120}; Line Loop(122) = {32,-22,-27,21}; Ruled Surface(123) = {122}; Line Loop(124) = {33,-23,-28,22}; Ruled Surface(125) = {124}; Line Loop(126) = {34,-24,-29,23}; Ruled Surface(127) = {126};

Surface Loop(128) = {93,-73,-55,95,-91}; Volume(129) = {128}; // int

Surface Loop(130) = {107,-75,-97,95,57,121}; Volume(131) = {130}; // int b Surface Loop(132) = {105,-65,-97,-83,-93}; Volume(133) = {132}; // int h Surface Loop(134) = {99,-111,77,123,59,107}; Volume(135) = {134}; // shell b

Surface Loop(136) = {99,-109,67,105,85}; Volume(137) = {136}; // shell h

Surface Loop(138) = {113,79,-101,-111,-125,-61}; Volume(139) = {138}; // ext b Surface Loop(140) = {115,-69,-101,-87,-109}; Volume(141) = {140}; // ext h Surface Loop(142) = {103,-117,-81,113,127,63}; Volume(143) = {142}; // inf b Surface Loop(144) = {89,-119,71,103,115}; Volume(145) = {144}; // inf h

// Transfinite Line 这个命令能够显式的指定点数和他们的分布。 // 'Progression 2' 意思是说这个系列中的所有线段会是前一个的 // 两倍。

Transfinite Line{35,21,22,23,24,38,17,18,19,20} = nbpt_phi ; Transfinite Line{31,26,48,44,42} = nbpt_int Using Progression 0.88;

Transfinite Line{41,37,36,9,11,1,3,13,5,15,7} = nbpt_arc1 ; Transfinite Line{30,25,40,39,10,2,12,4,14,6,16,8} = nbpt_arc2 ; Transfinite Line{32,27,49,45,43} = nbpt_shell ; Transfinite Line{33,28,46,50,52} = nbpt_far Using Progression 1.2 ;

Transfinite Line{34,29,51,47,53} = nbpt_inf Using Progression 1.05;

// 所有的二维和三维的 Transfinite 实体都是通过点的 Transfinite // 来定义的。其中点的顺序表示了网格中元素的顺序。

Transfinite Surface{55} = {1,14,16,18}; Transfinite Surface{57} = {14,2,19,16}; Transfinite Surface{59} = {2,3,21,19}; Transfinite Surface{61} = {3,4,23,21}; Transfinite Surface{63} = {4,5,25,23}; Transfinite Surface{73} = {1,15,17,18}; Transfinite Surface{75} = {15,10,20,17}; Transfinite Surface{77} = {10,11,22,20}; Transfinite Surface{79} = {11,12,24,22}; Transfinite Surface{81} = {12,13,26,24}; Transfinite Surface{65} = {18,16,19,6}; Transfinite Surface{67} = {6,19,21,7}; Transfinite Surface{69} = {7,21,23,8}; Transfinite Surface{71} = {8,23,25,9}; Transfinite Surface{83} = {17,18,6,20};

Transfinite Surface{85} = {20,6,7,22}; Transfinite Surface{87} = {22,7,8,24}; Transfinite Surface{89} = {24,8,9,26}; Transfinite Surface{91} = {1,14,15};

Transfinite Surface{95} = {15,14,16,17}; Transfinite Surface{93} = {18,16,17}; Transfinite Surface{121} = {15,14,2,10}; Transfinite Surface{97} = {17,16,19,20}; Transfinite Surface{123} = {10,2,3,11}; Transfinite Surface{99} = {20,19,21,22}; Transfinite Surface{107} = {10,2,19,20}; Transfinite Surface{105} = {6,20,19}; Transfinite Surface{109} = {7,22,21}; Transfinite Surface{111} = {11,3,21,22}; Transfinite Surface{101} = {22,21,23,24}; Transfinite Surface{125} = {11,3,4,12}; Transfinite Surface{115} = {8,24,23}; Transfinite Surface{113} = {24,12,4,23}; Transfinite Surface{127} = {12,13,5,4}; Transfinite Surface{103} = {24,23,25,26}; Transfinite Surface{119} = {9,26,25}; Transfinite Surface{117} = {13,5,25,26};

// 和做曲面推移的时候一样,重组命令 Recombine 告诉 Gmsh // 在可能的情况下将单纯形重新组合成为四边形、三棱柱或者 // 六面体。下面的列表中的分号的效果就像一个循环一样(和 // Matlab 中的用法相似):所有编号 55 到 127 之间的曲面 // 都在考虑之列。

Recombine Surface {55:127};

// 所有的二维和三维的 Transfinite 实体都是通过点的 Transfinite // 来定义的。其中点的顺序表示了网格中元素的顺序。

Transfinite Volume{129} = {1,14,15,18,16,17};

Transfinite Volume{131} = {17,16,14,15,20,19,2,10}; Transfinite Volume{133} = {18,17,16,6,20,19};

Transfinite Volume{135} = {10,2,19,20,11,3,21,22}; Transfinite Volume{137} = {6,20,19,7,22,21};

Transfinite Volume{139} = {11,3,4,12,22,21,23,24}; Transfinite Volume{141} = {7,22,21,8,24,23};

Transfinite Volume{143} = {12,4,5,13,24,23,25,26}; Transfinite Volume{145} = {8,24,23,9,26,25};

VolInt = 1000 ; SurfIntPhi0 = 1001 ; SurfIntPhi1 = 1002 ; SurfIntZ0 = 1003 ;

VolShell = 2000 ; SurfShellInt = 2001 ; SurfShellExt = 2002 ; SurfShellPhi0 = 2003 ; SurfShellPhi1 = 2004 ; SurfShellZ0 = 2005 ; LineShellIntPhi0 = 2006 ; LineShellIntPhi1 = 2007 ; LineShellIntZ0 = 2008 ; PointShellInt = 2009 ;

VolExt = 3000 ; VolInf = 3001 ; SurfInf = 3002 ; SurfExtInfPhi0 = 3003 ; SurfExtInfPhi1 = 3004 ; SurfExtInfZ0 = 3005 ; SurfInfRight = 3006 ; SurfInfTop = 3007 ;

Physical Volume (VolInt) = {129,131,133} ; Physical Surface (SurfIntPhi0) = {55,57,65} ; Physical Surface (SurfIntPhi1) = {73,75,83} ; Physical Surface (SurfIntZ0) = {91,121} ;

Physical Volume (VolShell) = {135,137} ; Physical Surface (SurfShellInt) = {105,107} ; Physical Surface (SurfShellExt) = {109,111} ; Physical Surface (SurfShellPhi0) = {59,67} ; Physical Surface (SurfShellPhi1) = {77,85} ; Physical Surface (SurfShellZ0) = {123} ; Physical Line (LineShellIntPhi0) = {1,2} ; Physical Line (LineShellIntPhi1) = {9,10} ; Physical Line (LineShellIntZ0) = 21 ; Physical Point (PointShellInt) = 6 ;

Physical Volume (VolExt) = {139,141} ; Physical Volume (VolInf) = {143,145} ;

Physical Surface (SurfExtInfPhi0) = {61,63,69,71} ;

Physical Surface (SurfExtInfPhi1) = {79,87,81,89} ; Physical Surface (SurfExtInfZ0) = {125,127} ; Physical Surface (SurfInfRight) = {117} ; Physical Surface (SurfInfTop) = {119} ;

例子 7

/********************************************************************* *

* Gmsh tutorial 7 *

* 各向异性网格、吸引子 *

*********************************************************************/

// 我们可以选择新的二维的各向异性网格生成器:

Mesh.Algorithm = 2 ;

// 我们强行使用 4 步 Laplacian 迭代将网格磨光:

Mesh.Smoothing = 4 ;

lc = .1;

Point(1) = {0.0,0.0,0,lc}; Point(2) = {1.2,-0.2,0,lc}; Point(3) = {1,1,0,lc}; Point(4) = {0,1,0,lc};

Line(1) = {3,2}; Line(2) = {2,1}; Line(3) = {1,4}; Line(4) = {4,3};

Line Loop(5) = {1,2,3,4}; Plane Surface(6) = {5};

Point(5) = {0.1,0.2,0,lc};

Point(11) = {0.5,0.5,-1,lc}; Point(12) = {0.5,0.5,0,lc}; Point(22) = {0.6,0.6,1,lc};

Line(5) = {11,22};

Spline(7) = {4,5,12,2};

// 各向异性的吸引子能够定义在点和线上:

Attractor Line{5} = {.1, 0.01, 17};

Attractor Line{1,2} = {0.1, 0.005, 3}; Attractor Line{7} = {0.1, 0.05, 3};

例子 8

/********************************************************************* *

* Gmsh tutorial 8 *

* 后处理、脚本、动画、选项 *

*********************************************************************/

// 先包含进来例 1,以及一些后处理视图(请参看 FORMATS 文件关于后处理 // 文件的格式):

Include \Include \Include \Include \

// 设定一些共同的选项:

General.Trackball = 0 ; General.RotationX = 0 ; General.RotationY = 0 ; General.RotationZ = 0 ;

General.Color.Background = White ; General.Color.Foreground = Black ; General.Color.Text = Black ; General.Orthographic = 0 ; General.Axes = 0 ;

General.SmallAxes = 0 ;

// 每个后处理视图还有一些各自的选项:

View[0].IntervalsType = 2 ; View[0].OffsetZ = 0.05 ; View[0].RaiseZ = 0 ; View[0].Light = 1 ; View[0].ShowScale = 0;

View[0].SmoothNormals = 1;

View[1].IntervalsType = 1 ;

View[1].ColorTable = { Green, Blue } ; View[1].NbIso = 10 ; View[1].ShowScale = 0;

View[2].Name = \View[2].IntervalsType = 2 ; View[2].Type = 2;

View[2].IntervalsType = 2 ; View[2].AutoPosition = 0; View[2].PositionX = 85; View[2].PositionY = 50; View[2].Width = 200; View[2].Height = 150;

View[3].Type = 3;

View[3].RangeType = 2;

View[3].IntervalsType = 4 ; View[3].ShowScale = 0; View[3].Grid = 0;

View[3].CustomMin = View[2].CustomMin; View[3].CustomMax = View[2].CustomMax; View[3].AutoPosition = 0;

View[3].PositionX = View[2].PositionX; View[3].PositionY = View[2].PositionY; View[3].Width = View[2].Width; View[3].Height = View[2].Height;

// 从 1 到 255 做循环,这里的语法和 Matlab 是相似的,您还可以 // 使用 {0.5:1.5:0.1} 表示从 0.5 到 1.5 做循环,步长为 0.1。

t = 0 ;

For num In {1:255}

View[0].TimeStep = t ; View[1].TimeStep = t ; View[2].TimeStep = t ; View[3].TimeStep = t ;

t = (View[0].TimeStep < View[0].NbTimeStep-1) ? t+1 : 0 ;

View[0].RaiseZ += 0.01*t ;

If (num == 3)

// 当 num == 3 的时候,我们使得图形的大小为 320x240 : General.GraphicsWidth = 320 ; General.GraphicsHeight = 240 ; EndIf

// 循环是可以嵌套的: For num2 In {1:50}

General.RotationX += 10 ;

General.RotationY = General.RotationX / 3 ; General.RotationZ += 0.1 ;

Sleep 0.01; // 等待 0.01 秒钟 Draw; // 重画

If ((num == 3) && (num2 < 10))

// Sprintf 函数能够用变量来产生复杂的字符串: Print Sprintf(\ Print Sprintf(\ EndIf

If ((num == 3) && (num2 >= 10))

Print Sprintf(\ Print Sprintf(\ EndIf

EndFor

If(num == 3)

// System 命令能够使用一个系统调用。下面这行能用来

// 产生一个 mpeg 文件(如果您安装有 mpeg_encode 的话)。 // System \ EndIf

EndFor

// 下面是支持的脚本命令列表: //

// Merge string; (合并一个文件) // Draw; (重画)

// Mesh int; (产生网格; 'int' = 0, 1, 2 or 3) // Save string; (存储网格)

// Print string; (打印图形窗口) // Sleep expr; (睡眠给定的秒数) // Delete View[int]; (释放视图 int) // Delete Meshes; (释放所有网格)

// System string; (执行一个系统调用)

例子 9

/********************************************************************* *

* Gmsh tutorial 9 *

* 后处理、插件 *

*********************************************************************/

// Gmsh 支持添加插件以扩展其功能。比如,后处理插件能够修改一个 // 视图,或者基于先前的视图构造出一个新的视图。有几个缺省的插件 // 被静态的连接进了 Gmsh,包括 CutMap, CutPlane, CutSphere, // Skin, Transform 和 Smooth。

// 我们先载入一个三维的标量视图:

Include \

// 插件能够像其他的选项一样被操控。比如 CutMap 插件(该插件能够 // 从一个三维标量视图中截取一个等值面)既能够从图形界面上进行操 // 控,也能够在文件中输入其参数:

Plugin(CutMap).A = 0.67 ; // iso-value level

Plugin(CutMap).iView = 0 ; // source view is View[0] Plugin(CutMap).Run ;

// 下面是运行 CutPlane 插件:

Plugin(CutPlane).A = 0 ; Plugin(CutPlane).B = 0.2 ; Plugin(CutPlane).C = 1 ; Plugin(CutPlane).D = 0 ; Plugin(CutPlane).Run ;

View[0].Light = 1;

View[0].IntervalsType = 2; View[0].NbIso = 6;

View[0].SmoothNormals = 1;

View[1].IntervalsType = 2;

View[2].IntervalsType = 2; Draw;