例子 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("The cheese hole %g (center = {%g,%g,%g}, radius = %g) has 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 ;