有限元法(FEM,Finite Element Method)是一种求解偏微分方程问题的数值方法。随着电子计算机的发展,有限元方法迅速发展成一种现代计算方法,在固体力学、流体力学、热传导、电磁学、声学、生物力学等方面有着广泛的应用。今天就先介绍有限元方法之前处理,利用Gmsh剖网格。
Gmsh是一个自动的三维有限元网格生成带有内置在CAD和后期处理器。当然其也可以生成一维和二维的有限元网格。
可以去官网下载安装包Gmsh官网
可以在Download处
Download Gmsh for Windows 64-bit, Windows 32-bit, Linux 64-bit, Linux
32-bit or MacOS
点击自己电脑对应的系统下载,安装成功后会在电脑上有如下图所示的软件:
打开后去用其打开下载的"*.geo"(在Download处点击 Download the source code里面可以找到)文件,之后在Gmsh软件界面内点击点击Mesh下的2D,可以得到如下图的网格
注:Gmsh软件上方的菜单栏亦有将网格数据导出的功能,可以导出多种标准格式。
在官网的Download处点击下载
Download the source code
注:此处链接失效的话可以去前面提到的官网对应位置下载。
解压后有"README.txt"文件里面介绍了如何安装,以下为详细步骤:
注: 其中第5步时间可能稍长,耐心等待就行。
可在源码的同级目录下建立demo文件夹,里面放自己学习的代码。将如下代码拷贝到"demo.cpp"文件中
#include
#include
#include
#include
#include
using namespace std;
void writeNodes(vector<double>& nodes, string s)
{
string filename = s + ".txt";
ofstream outfileb(filename.c_str(), ios::out);
for(int i = 0; i < nodes.size(); i++)
{
outfileb<<(nodes[i])<<endl;
}
outfileb.close();
}
void writeElements(vector<std::vector<std::size_t> >& elements, string s)
{
string filename = s + ".txt";
ofstream outfileb(filename.c_str(), ios::out);
for(int i = 0; i < elements[1].size(); i++)
{
outfileb<<(elements[1][i])<<endl;
}
outfileb.close();
}
int main(int argc, char **argv)
{
gmsh::initialize();
gmsh::model::add("Test1");
double lcc = 0.05;//2e-1;
gmsh::model::geo::addPoint(1.0/3, 1.0/3, 0, lcc, 100);
gmsh::model::geo::addPoint(2.0/3, 1.0/3, 0, lcc, 101);
gmsh::model::geo::addPoint(2.0/3, 2.0/3, 0, lcc, 102);
gmsh::model::geo::addPoint(1.0/3, 2.0/3, 0, lcc, 103);
gmsh::model::geo::addLine(100, 101, 100);
gmsh::model::geo::addLine(101, 102, 101);
gmsh::model::geo::addLine(102, 103, 102);
gmsh::model::geo::addLine(103, 100, 103);
gmsh::model::geo::addCurveLoop({100, 101, 102, 103}, 100);
double lc = 0.2;//2e-1;
gmsh::model::geo::addPoint(-1, 0, 0, lc, 1);
gmsh::model::geo::addPoint(1, 0, 0, lc, 2);
gmsh::model::geo::addPoint(1, 1, 0, lc, 3);
gmsh::model::geo::addPoint(-1, 1, 0, lc, 4);
gmsh::model::geo::addPoint(0, 0, 0, lc, 555);
gmsh::model::geo::addLine(1, 555, 1);
gmsh::model::geo::addLine(555, 2, 555);
gmsh::model::geo::addLine(2, 3, 2);
gmsh::model::geo::addLine(3, 4, 3);
gmsh::model::geo::addLine(4, 1, 4);
gmsh::model::geo::addCurveLoop({1, 555, 2, 3, 4}, 1);
gmsh::model::geo::addPlaneSurface({1, -100}, 1);
gmsh::model::geo::addPoint(1, 2, 0, lc, 5);
gmsh::model::geo::addPoint(-1, 2, 0, lc, 6);
gmsh::model::geo::addLine(3, 5, 5);
gmsh::model::geo::addLine(5, 6, 6);
gmsh::model::geo::addLine(6, 4, 7);
gmsh::model::geo::addCurveLoop({-3, 5, 6, 7}, 2);
gmsh::model::geo::addPlaneSurface({2}, 2);
gmsh::model::setPhysicalName(2, 6, "My surface");
gmsh::model::geo::synchronize();
// We can then generate a 2D mesh...
gmsh::model::mesh::generate(2);
//gmsh::model::mesh::refine();
// get mesh information
// Nodes
vector<double> nodes,y;
vector<std::size_t> nodeTags;
gmsh::model::mesh::getNodes(nodeTags, nodes, y, -2, -1, false, true);
cout<<"The number of nodes: "<<nodes.size()/3<<endl;
#if 0
cout<<endl;
for(int i = 0; i < nodes.size(); i++)
{
cout<<nodes[i]<<endl;
}
#endif
writeNodes(nodes, "nodes");
//Elements
vector<int> elementTypes;
vector<std::vector<std::size_t> > elementTags, nodeTags2;
gmsh::model::mesh::getElements(elementTypes, elementTags, nodeTags2, -2, -1);
cout<<"The number of elements: "<<nodeTags2[1].size()/3<<endl;
#if 0
cout<<endl;
for(int j = 0; j < nodeTags2[1].size(); j++)
{
cout<<nodeTags2[1][j]<<endl;
}
#endif
writeElements(nodeTags2, "elements");
gmsh::write("demo.msh");
gmsh::finalize();
return 0;
}
然后在终端进入到有"demo.cpp"文件的目录下,输入如下命令:
g++ demo.cpp -std=c++11 -Iinclude -lgmsh -o exe
之后再输入:
./exe
则会在终端有如下的输出:
The number of nodes: 239
The number of elements: 410
同时文件夹下会多出"demo.msh", “elements.txt”, "nodes.txt"三个文件,用图形画的Gmsh软件,打开"demo.msh"文件,既可以看到如下图所示的网格:
以上事例程序写的比较粗糙,仅作为测试,可去我的GitHub网站下载学习。通过写C++程序调用Gmsh的API接口,自己也用了很长一段时间了,也写了不少EXample程序,后面时间充足会都总结上传到我的GitHub仓库中,欢迎大家一起学习讨论。