一、关于netgen在CSDN上有非常全面的介绍
这些博文围绕下载、编译和连接进行了全面细致的讲解。但是……(见下文)
1.netgen.5.0.0下载地址与Windows下编译方法(https://blog.csdn.net/zhouschina/article/details/9050373?utm_medium=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.add_param_isCf&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-OPENSEARCH-1.add_param_isCf)
4.Netgen mesh library : nglib(https://blog.csdn.net/weixin_34200628/article/details/93595772?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.add_param_isCf&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-1.add_param_isCf)
二、写本篇博文的原因
原因有二,下载地址失效了;没有必要重新编译。
1.Netgen从1994年诞生,之后数度“搬家”,3.x,4.x和5.x等多个版本的下载地址(http://sourceforge.net/projects/netgen-mesher )现在不存在了。新家(https://ngsolve.org/downloads)只提供6.2.x系列版本,这些版本从2017年开始,每月都有更新。
2.在Windows系统中使用VS下的VC++编程,在调用Netgen的库函数(nglib)时,不用重新编译。从3.x到6.2.x版本都有安装包,或是exe,或是msi文件。正常安装就会生成编程所需的库函数文件,它们是nglib.h、nglib.lib和nglib.dll文件,分别在安装目录的include、lib和bin目录下。我使用过VS2008和VS2015编程调用nglib,具体说调用过4.9.13版,5.0.0版,5.1版,6.2.2008版的nglib,都是在自己没有编译的情况下调用成功的。后面会说下调用的注意事项。
三、Netgen的安装
上面说过5.x及以前的版本,已经在官网上找不到了,如果需要只能搜索下有没有人转存过。6.2.x版本在官网上可以容易找到,不多说了。6.2.x版本都是64位的,所以你如果在VS中配置win32的程序,那肯定是不行的。
安装Netgen很容易,不过我遇到两次“意外”,介绍给大家。
一次是,安装的默认目录是系统盘的\Program Files (x86)\目录,出错了,提示不能写入某某文件。出错的原因可能是目录中含有空格或者是括号,不讨论这个问题了。直接安装在根目录就可以了,不会有上面的错误。
另一次是,安装成功后,没有在环境变量中生成NETGENDIR变量,它的值应该是Netgen安装目录下的bin目录,比如C:\Netgen-5.1_Win32\bin。没有这个变量的后果是点击开始菜单里的Netgen,没有反应,不能启动Netgen。只能到C:\Netgen-5.1_Win32\bin下点击netgen.exe文件才能启动。所以要手动在环境变量里加入NETGENDIR变量,变量值就是netgen.exe所在的目录,比如C:\Netgen-5.1_Win32\bin。
四、调用nglib接口函数的注意事项
上面说过,我的经历是不用重新编译nglib。不管你用的是哪个版本的VS,还是用的哪个版本的netgen,都不用重新编译nglib。要想调用成功,需要正确设置nglib.h、nglib.lib和nglib.dll文件。前两个不用多说,有太多的介绍资料可查。关于dll文件,有多种设置方法可用,推荐将它所在的目录加入到环境变量的PATH值里面,比如把C:\Netgen-5.1_Win32\bin加入到PATH里面。
五、VC++代码
如果下面这段代码运行成功,说明一切顺利。
#include "stdafx.h"
#include <stdio.h>
namespace nglib {
#include <nglib.h>
}
int main()
{
using namespace nglib;
Ng_Init();//初始化Netgen
Ng_Exit();//退出
return 0;
}
六、如果重新编译的话
版本4.*和5.0的编译,见“一、关于netgen在CSDN上有非常全面的介绍”。对5.1版本的编译,要下在第三方库zlib,它是开源的,处理方法与pthread一样。编译好的文件放在哪了?
netgen的windows目录下有两个解决方案,即sln文件。一个时nglib,另一个时netgen。netgen.sln编译完,会生成netgen.exe,同时会用一个nginterface.lib,这个lib也可以调用,具体可以看nginterface.h。
如果你的windows系统中有环境变量NETGENDIR这个变量的话,他是安装netgen是产生的,编译好的文件就存在这个变量的值下面。这可以在编译器的“输出”栏里看到:
1> Environment variable NETGENDIR found: C:\Netgen-5.1_Win32\bin
1> POSTBUILD Script for nglib ........
1> Installing required files into C:\Netgen-5.1_Win32\bin\.. ....
1> 复制了 1 个文件
1> Installing nglib.dll: Completed OK!!
1> 复制了 1 个文件
1> Installing nglib.lib: Completed OK!!
1> Installing nglib.h into C:\Netgen-5.1_Win32\bin\..\include ....
1> 复制了 1 个文件
1> Installing nglib.h: Completed OK!!
1> Installing NgSolve dependent header files into C:\Netgen-5.1_Win32\bin\..\include ....
如果没有NENGENDIR的话,会按默认值创建一个目录,来存储文件:.h, .lib和.dll文件。同样看“输出”栏里的提示。
七、增加自己的接口函数
在“四、调用nglib的注意事项”里说过,调用原版的接口函数不用重新编译。那既然重新编译了,就是要增加自己的接口了。nglib中没有加载geo文件的接口函数,增加这个接口的过程如下:
1.在nglib.h中增加函数声明:
DLL_HEADER Ng_CSG_Geometry * Ng_CSG_LoadGeometry(const char * filename);
2.在nglib.cpp中增加函数的定义:
DLL_HEADER Ng_CSG_Geometry * Ng_CSG_LoadGeometry(const char * filename)
{
ifstream iFile(filename);
if (!iFile.good())
{
cout << "No file is found" << endl;
return NULL;
}
CSGeometry* geom = ParseCSG(iFile);
std::cout << "A Ng_CSG_Geometry is constructed:" << geom->GetNSolids() << " solids is found!" << endl;
if (!geom)
throw NgException("geo-file should start with 'algebraic3d'");
geom->FindIdenticSurfaces(1e-5 * geom->MaxSize());
return (Ng_CSG_Geometry*)geom;
}
说明a:在上面代码中,调用了ParseCSG(),所以的在调用之前声明一下他是个外部函数:
namespace netgen {
extern CSGeometry * ParseCSG(istream & istr);
}
因为ParseCSG()是在名称空间netgen中定义的,而正在增加的接口函数Ng_CSG_LoadGeometry()是在nglib名称空间中定义的,所以要注意名称空间的问题,否则编译不能通过。
说明b:在配置为win32,用4.913版代码编译上面Ng_CSG_LoadGeometry()函数时,编译顺利通过。但在调用时,有异常提示:内存位置0x0112e0c0处的std::bad_alloc。据说是内存不足。用5.1版,配置x64,就不会出现上面提示。
说明c:parse出来的几何体,必须要进行 geom->FindIdenticSurfaces(1e-5 * geom->MaxSize());否则在GenerateMesh时就完成不了,出问题的地方在find surface时一直运行不出结果。系数可以是1e-8等。
持续完善中……