开始只是想学SOFA, 谁知道这个坑深似海,还要先学GMSH。。。。。

一步步来吧,可恶啊。

官方教程

GMSH的安装

安装没啥难度,按照官网的提示走

http://gmsh.info/




python2 gmssl下载 gmsh python_python2 gmssl下载


这里,更建议直接使用python的pip进行安装(因为直接下载源文件可能需要自己再配置些东西。。。):

pip install --upgrade gmsh

需要注意的是,这样操作的话软件包是被安装到当前使用的Python的路径下了,

如果使用了conda的话,可以在Python安装目录下的Lib\site-packages\找到gmsh-4.11.1.dist-info,如果在pycharm里import时报错,可以将这个site-packages添加到内容根试试。(一般不会遇到)

可以在Python安装目录下的share\doc\gmsh文件夹里找到教程和示例的源代码。

如果是使用pip安装的话,可以使用以下命令打开:

gmsh

(使用了conda的话要注意,启动软件时要保证环境是安装gmsh时的那个环境,因为这个东西是安装到当时的环境里的,不是直接安装到系统)

启动之后会显示这样的界面:


python2 gmssl下载 gmsh python_Powered by 金山文档_02


基本介绍(太长可不看部分)

Gmsh接口的两个默认内核是内置内核和OpenCASCADE内核。
在.geo脚本中选择CAD内核是使用SetFactory命令完成的。
在写 .geo脚本时,标签的数字是不能重复使用的。另外Gmsh保留零或负标签供内部使用。

Gmsh教程从t1开始,是学习如何使用几何模块的最佳场所:它包含基于内置和OpenCASCADE内核的复杂度增加的示例。

几何模块 Geometry

模型实体可以在几何模块Geometry中以各种方式进行操作和转换,但操作始终直接在其各自的CAD内核中执行。
同样,可以通过每个CAD内核自己的导入机制在几何模块中导入模型。例如,默认情况下,Gmsh通过OpenCASCADE导入STEP和IGES文件,这将导致创建具有内部OpenCASCADE表示的模型实体.

除了CAD类型的几何实体(其几何结构由CAD内核提供)之外,Gmsh还支持由网格定义的离散模型实体(例如STL)。Gmsh不会对这些离散实体执行几何运算,但可以通过所谓的“重新参数化”程序1为它们配备几何图形。然后将参数化用于网格,其方式与CAD实体完全相同。示例参见t13

网格模块 Mesh

2D非结构化算法生成三角形和/或四边形(当使用重组命令或选项时)。三维非结构化算法生成四面体或四面体和金字塔(当边界网格包含四边形时)。
默认情况下,2D结构化算法(超限和拉伸)生成三角形,但可以通过使用复合命令或选项获得四边形。3D结构化算法生成四面体、六面体、棱柱和金字塔,这取决于它们所基于的曲面网格的类型。

教程 的1.2.1~1.2.3部分介绍了•选择正确的非结构化算法•指定网格元素大小•基本实体与物理组,如果有需要可详细查看。

求解器模块 Solver

Gmsh实现了ONELAB服务器,用于与外部解算器或其他代码(称为“客户端”)交换数据。ONELAB接口允许调用这些客户端,并让它们共享参数和建模信息。

后处理模块 Post-processing

感觉挺厉害的,主要是后处理时的视图及视图效果和功能。锦上添花。

Gmsh优势

  • 使用内置脚本语言快速描述简单和/或“重复”的几何图形;
  • 参数化几何图形;
  • 以标准交换格式从其他CAD软件导入几何图形;
  • 生成非结构化1D、2D和3D简单有限元网格,并对单元大小进行精细控制;
  • 。。。。

Gmsh 劣势

  • Gmsh生成的所有网格在有限元网格的意义上都是一致的
  • Gmsh的图形用户界面只展示了有限数量的可用功能

实例

本部分为教程文档里的第二章,这部分只有代码,没有代码的讲解。代码太长就不粘贴过来了。

实例有:


t1

几何基础、基本实体、物理组

t15

嵌入点、线和表面

t2

变换、拉伸几何体、体积

t16

构造实体几何,OpenCASCADE几何内核

t3

拉伸网格、ONELAB

t17

各向异性背景网格

t4

内置函数、曲面中的孔、注释、实体颜色

t18

周期网格

t5

网格大小、宏、循环、体积中的孔

t19

穿透、圆角、管道、曲率网格尺寸

t6

超限网格、删除实体

t20

STEP导入和操作、几何分区

t7

背景网格

t21

网格分区

t8

后处理,图像导出和动画

x1

几何和网格数据

t9

插件

x2

网格导入、离散实体、混合模型、,地形网格化

t10

网格大小字段

x3

后处理数据导入:基于列表

t11

非结构化四边形网格

x4

后处理信息导入:基于模型

t12

与化合物的交叉面片网格

x5

附加几何数据:参数化、法线、曲率

t13

在没有基础CAD模型的情况下修复STL文件

x6

附加网格数据:积分点、雅可比函数和基函数

t14

同调和上同调计算

x7

附加网格数据:内部边和面


可根据需要去找对应的示例, 不必全看。

教程正文

对应官方教程第三章

启动

gmsh


python2 gmssl下载 gmsh python_3D_03


添加几何实体

在 geometry -> elementary entities -> add 里可以添加几何实体

这里添加矩形rectangle:


python2 gmssl下载 gmsh python_结构化_04


可以用鼠标拖动,按e确定,或者在弹出来的弹窗里填写数值,


python2 gmssl下载 gmsh python_python2 gmssl下载_05


这个矩形添加后,可以到左边结构树里找到geometry ->Edit Script, 查看上面的添加矩形操作后的 .geo文件:


python2 gmssl下载 gmsh python_结构化_06


如果要编辑这个 .geo文件,则编辑且保存后,应该在软件里进行更新: geometry ->Reload Script

在使用Gmsh这个软件时,比较常见的方式就是图形界面和 .geo脚本文件混合使用,共同编辑。

画网格

在软件左边 Mesh里选择需要的网格维度,这里选择2D:


python2 gmssl下载 gmsh python_Powered by 金山文档_07


此时在软件中点击 File ->save mesh, 或者‘File->Export可以导出网格文件。使用导出功能时,可以自行指定格式,如vtk。软件会根据目标格式自动调整格式。

在图窗区域双击可以弹出一个快速快捷菜单,可用于快速切换网格实体(如曲面)的可见性、重置视口、选择旋转中心、显示轴或访问完整模块选项

gmsh可以同时加载多个文件,比如将.pos文件和.msh文件与第一个教程的文件 t1合并,可以输入以下命令:

gmsh t1.geo view1.pos view5.msh

加载一个或多个后处理视图时,树菜单中会出现“后处理”条目。使用上一个命令,“后处理”下的树菜单中将出现三个视图,分别标记为“A scalar map”、“Nodal scalar map”和“Element 1 vector”。在本例中,视图包含多个时间步骤:您可以使用状态栏左侧的快捷键图标循环查看这些步骤。鼠标单击视图名称将切换所选视图的可见性,而单击右侧的箭头按钮将提供对视图选项的访问。

请注意,以交互方式指定的所有选项也可以直接在脚本文件中指定。gmsh可以以 .opt格式的文件保存操作后的各种配置,方便下次直接读取,保存方式为 File->Save Model Options。若想将某视角保存为默认视角,则可选择File->Save Options As Default

本段基础教程结束。

鼠标操作

左键:旋转、选择实体或接受套作缩放或套索选择

Ctrl+左键: 开始套索缩放或套索(取消)选择

中键:缩放//取消选择实体//接受套索缩放或取消选择套索

Ctrl+中键:正交显示

右键:平移//取消套索缩放或套索(取消)选择//后处理视图按钮上的弹出菜单

Ctrl+右键:重置为默认视点

(对于没有中键的鼠标:中键等于shift+左键)

键盘操作

太多了,挑几个可能有用的:

数字0:重新载入模型(所以轻易别按)

Ctrl+0 或9: 重新载入整个项目(更是轻易别按)

数字1或F1:画线的网格

数字2或F2:画面的网格

数字3或F3:画体积的网格

g:转到几何模块

m:转到网格模块

p:转到后处理模块

s:转到解算器模块

e:在几何体创建模式下结束/接受选择

q:在几何体创建模式下中止选择

x,y,z:在几何体创建模式下切换x,y,z坐标冻结

shift+x,y,z:在几何体创建模式中仅沿x,y,z坐标移动

alt+b:隐藏/显示边界框

alt+x,y,z:设置x,y,z视图

alt+shift+x,y,z:设置x,y,z负轴视图

alt+l,p,s,v:隐藏/显示几何线条,点,面,体积

alt+shift+l,p,s,v:隐藏/显示网格的线条,点,面,体积

脚本语言

太多了,选几个常用的提一下吧。。

  1. 注释:/*alskdjfalsdfj*/, or //
  2. 看实例 t1.geo
// -----------------------------------------------------------------------------
//  Gmsh GEO tutorial 1
//  Geometry basics, elementary entities, physical groups
// -----------------------------------------------------------------------------

//首先定义一个新的变量,这个变量将被用于点的定义
lc = 1e-2;
// 定义点,前三个变量表示空间位置XYZ,第四个变量表示这个点附近的网格大小
// 实例t10.geo里有直接定义通用网格大小的字段。
Point(1) = {0, 0, 0, lc};
Point(2) = {.1, 0,  0, lc};
Point(3) = {.1, .3, 0, lc};
Point(4) = {0,  .3, 0, lc};

// 定义曲线,大括号里的是点的标签。注意这里的曲线方向,第二条是从点3到点2
Line(1) = {1, 2};
Line(2) = {3, 2};
Line(3) = {3, 4};
Line(4) = {4, 1};

// 利用刚才定义的线来定义一个封闭环,大括号里的是线的标签
// 在纸上画一下刚才定义的四条线,可以发现大括号里的顺序可以闭环。
Curve Loop(1) = {4, 1, -2, 3};

// 根据闭环定义曲面,大括号里是封闭环的标签
// 实例4里有如何画带孔洞的封闭环的代码
Plane Surface(1) = {1};

// 以上内容已经足以告诉gmsh怎么画出这个矩形曲面和网格了
// 还有一些高端操作,将机和实体分组,这里将第1,2,4直线定义为一个物理曲线组
// 将1号曲面(即定义的矩形曲面)定义为一个平面组
Physical Curve(5) = {1, 2, 4};
Physical Surface("My surface") = {1};

// 现在写的这个.geo文件可以在gmsh中通过 file->open打开,也可以在文件所在目录中通过命令:
// gmsh xxxx.geo 来打开,这里的xxxx用文件的实际名称代替。

// *************重要,在脚本中输出网格**************
// 若在文件最后添加下面的指令,则打开文件会自动生成2D网格并保存为msh文件
//   Mesh 2;
//   Save "t1.msh";

// 也可以通过改变后缀来保存为其他格式的网格文件,比如:
// msh1, msh2, msh22, msh3, msh4, msh40, msh41, msh, unv, vtk, wrl, mail, stl, 
// p3d, mesh, bdf, cgns, med, diff, ir3, inp, ply2, celum, su2, x3d, dat, neu, 
// m, key, off, rad 


// 若使用 OpenCASCADE内核, 可以更简单地定义矩形曲面:
//   Rectangle(2) = {.2, 0, 0, .1, .3};
// 确定CAD内核为 OpenCASCADE,在文件开头加入指令: SetFactory("OpenCASCADE");
  1. 看教程t20.geo,将其中注释翻译一下,可以应对大部分使用场景,如果有不清楚的,可以到官方教程里按ctrl+f搜索关键词,然后比对更多示例猜测使用方法。
// -----------------------------------------------------------------------------
//  Gmsh GEO tutorial 20
//  STEP导入和操作、几何分区
// -----------------------------------------------------------------------------

// 本文件目的:加载step格式的模型并修改,将其切片

SetFactory("OpenCASCADE");    //确定CAD内核为 OpenCASCADE

// 加载STEP文件,使用“ShapeFromFile”,将文件加载到变量v()
v() = ShapeFromFile("t20_data.step");

// 如果在读入文件之前输入以下语句:
// Geometry.OCCTargetUnit = "M";
// 则表示将单位设置为 米,若未指定,则默认情况下认为单位为 毫米

// 使用以下几个命令来获取刚才导入的物体的体积边界框,分别为三个轴向的投影的最小和最大值。
bbox() = BoundingBox Volume{v()};
xmin = bbox(0);
ymin = bbox(1);
zmin = bbox(2);
xmax = bbox(3);
ymax = bbox(4);
zmax = bbox(5);

// 我们希望将模型分割成N个切片,并保留体积切片或仅切割获得的曲面:
// DefineConstant[ string = { expression|string-expression, onelab-options } <, ...>];
// 使用值表达式创建新的表达式标识符字符串
// 下面调用这个模块的作用是,在图形界面的树形图最下面会出现代码下方图1所示的选项。
DefineConstant[
  N = {5, Min 2, Max 100, Step 1, Name "Parameters/0Number of slices"}
  dir = {0, Choices{0="X", 1="Y", 2="Z"}, Name "Parameters/1Direction"}
  surf = {0, Choices{0, 1}, Name "Parameters/2Keep only surfaces?"}
];

dx = (xmax - xmin);    // 定义体积的长宽高变量
dy = (ymax - ymin);
dz = (zmax - zmin);
L = (dir == 0) ? dz : dx;//与C中的语法相似,若满足括号条件则取冒号左端值,否则取右端。
H = (dir == 1) ? dz : dy;

// 创建一个切割面
s() = {news}; 
// news 表示新的表面,
// 同理,newc/newcl/newsl/newv分别表示新曲线、曲线环、新曲面、曲面环和新体积
Rectangle(s(0)) = {xmin, ymin, zmin, L, H};

// 旋转和平移模块的使用
/*
将5号点沿着x轴移动-0.02(单位为默认)
Translate {-0.02, 0, 0} { Point{5}; } 
将5号点绕着{0,0.3,0}点旋转 -pi/4,第一个括号里的内容是旋转轴,第二个括号里的是中心点。
Rotate {{0,0,1}, {0,0.3,0}, -Pi/4} { Point{5}; }
将3号点复制并沿Y轴平移0.05。
3号点可以被复制并沿Y轴平移0.05。新的点会被顺延分配标签。
*/
If(dir == 0)
  Rotate{ {0, 1, 0}, {xmin, ymin, zmin}, -Pi/2 } { Surface{s(0)}; }
ElseIf(dir == 1)
  Rotate{ {1, 0, 0}, {xmin, ymin, zmin}, Pi/2 } { Surface{s(0)}; }
EndIf

// 共分为N层,设置每层的高度,然后将新的层放到该切片的位置
tx = (dir == 0) ? dx / N : 0;
ty = (dir == 1) ? dy / N : 0;
tz = (dir == 2) ? dz / N : 0;
Translate{tx, ty, tz} { Surface{s(0)}; }

// 将物体切成N片
For i In {1:N-2}
  s() += Translate{i * tx, i * ty, i * tz} { Duplicata{ Surface{s(0)}; } };
EndFor

// 用所有的切割平面分割(即相交)体积。这里体积与曲面相交,delete 表示不产生重复界面。
BooleanFragments{ Volume{v()}; Delete; }{ Surface{s()}; Delete; }

// 移除不在体积边界上的所有曲面,曲面的多余部分。
Recursive Delete { Surface{:}; }

// 这句没看懂是想干嘛,在软件里点选上就啥也不显示了,大概是某种高端的选项吧。
If(surf)
  // If we want to only keep the surfaces, retrieve the surfaces in bounding
  // boxes around the cutting planes...
  eps = 1e-4;
  s() = {};
  For i In {1:N-1}
    xx = (dir == 0) ? xmin : xmax;
    yy = (dir == 1) ? ymin : ymax;
    zz = (dir == 2) ? zmin : zmax;
    s() += Surface In BoundingBox
      {xmin - eps + i * tx, ymin - eps + i * ty, zmin - eps + i * tz,
       xx + eps + i * tx, yy + eps + i * ty, zz + eps + i * tz};
  EndFor
  // ...and remove all the other entities:
  dels = Surface{:};
  dels -= s();
  Delete { Volume{:}; Surface{dels()}; Curve{:}; Point{:}; }
EndIf

// 指定全局网格大小
// 这个东西有用
Mesh.MeshSizeMin = 3;
Mesh.MeshSizeMax = 3;

// 可以在教程 t21 中查看划分网格而不是几何体的代码
//+
// 创建一个字符串类型的新字段(带有标记表达式)。最后这两行到底是啥意思,不清数
Field[1] = Max;
//+
Delete Field [1];

在编写完这个geo文件后,在gmsh 软件中打开。

若要修改文件,点geometry里的edit script,打开文件后修改,然后保存,在geometry里点reload

脚本画3D网格

Mesh 3;

脚本导出网格

注意,如果使用脚本导出,则每次打开文件的时候都会顺便导出网格文件。

Save "t1.msh";

Save "t1.vtk";

图1.


python2 gmssl下载 gmsh python_Powered by 金山文档_08


软件操作

如果觉得脚本写的太麻烦了,可以先写好引入模型的语句(通常是STEP文件),然后就在软件里操作。最简单的操作是使用默认网格大小,在导入模型后点击mesh->3D。

改变网格大小

在使用过程中,默认的网格大小通常难以满足需求,导致某些孔位或曲面太过粗糙,在软件中可以使用如下操作:

0. 导入模型文件。(在空项目中编辑脚本打开.step文件或者在软件中点击file->open打开都可以。),显示如下图:


python2 gmssl下载 gmsh python_学习_09


(注:若想改变此时模型显示的信息,可以在旁边空白处双击鼠标左键,弹出菜单后点击“All geometry options”,在Geometry的visibility里可选显示哪些信息(如下图)。同理,在Mesh里也可以选择显示哪些东西。)


python2 gmssl下载 gmsh python_学习_10


  1. 设置点周围的网格大小。点击左侧树形的Mesh->Define->Size at points。弹窗如下图所示,里面的数字就是将要选取的点周围的网格大小。


python2 gmssl下载 gmsh python_Powered by 金山文档_11


此时屏幕上提示选点,按住ctrl,用鼠标框选想要设置为当前数值的点,框选后按e键确认;然后修改弹窗里的数值,继续选其他点,将其他点周围网格大小设置为新的数值并确认;当所有点都这样设置完后,按q退出设置。

  1. 画网格。点击mesh->3D(或2D,按需选择),生成符合预期的网格导出即可。(我遇到了模型中可选的点比较少的情况,或许会影响画出来的网格效果,不过不重要,总算能够出一个比较满意的网格了)

删除网格

生成网格后(1D/2D/3D都适用),点击下图的删除element:


python2 gmssl下载 gmsh python_3D_12


按照提示,先用Ctrl+鼠标左键框选要删除的网格,再按“e”确认,就可以看到网格被删除了。这里框选网格时,只要被框碰到的都会被删除。删除完成后按“q”退出。

接下来导出网格为想要的格式就行。

网格导出

在软件里打开

点file:


python2 gmssl下载 gmsh python_python2 gmssl下载_13


这些都可以选,最常见的方式是直接点export,然后输入文件名时把自己想输出的格式的后缀也打上去。

软件画好网格后在软件中点击 File ->save mesh, 或者‘File->Export可以导出网格文件。使用导出功能时,可以自行指定格式,如vtk。软件会根据目标格式自动调整格式。如果有弹窗让选择编码格式,一般来说选择二进制binary。

结语

看起来好像这个软件的作者更希望大家直接使用脚本。如果有长期使用需求的话,更建议学习使用Python编写,因为这个软件提供的API功能挺全的,且使用Python更方便集成到其他项目中,能够使自动化程度更高。

写到这里时还没测试生成的网格能不能满足SOFA的实验需求,如果有其他问题再回来编辑。

补充:

  1. 在SOFA里使用时用vtk文件做网格,用stl文件做模型外观,出现了stl无法跟着vtk一起旋转平移的情况。在这里找了好久的bug,最后通过对比官方的stl文件和我的stl文件,发现可能是因为官方的stl文件也是gmsh生成的,而我的是SolidWorks生成的。于是试着使用gmsh生成stl文件,问题解决。stl文件生成方法:将模型step文件导入gmsh,划分网格后export为stl格式,编码选择二进制binary。