ABAQUS是支持C++子程序开发的,相比于传统的Fortran,C++作为高级语言的优势不言而喻,再搭配优秀的C++程序库,使得我们的编程效率大大提高,尤其是对于熟悉C++编程的开发者,不失为一种更好的选择。
1 软件配置
1.1 环境准备
我使用的开发软件搭配是Abaqus 2022 + Visual Studio 2019 + OneAPI 2022。虽然我们使用C++进行子程序开发,但是使用Intel的OneAPI中的Fortran模块是必须的,否则在编译链接C++源程序时,会发生如下错误:
LINK: fatal error LNK1104: cannot open file “LIBIFCOREMD.LIB”
“LIBIFCOREMD.LIB” 这个库是Intel的Fortran库,所以必须要使用到OneAPI中的Fortran模块。
要特别注意Visual Studio和OneAPI版本搭配的问题,否则在安装OneAPI的时候会无报错闪退。我曾经尝试Visual Studio 2019 + OneAPI 2021,结果OneAPI安装时总是在continue后无情退出,当卸载VS后,就可以正常安装了,所以一定要注意相关软件版本的搭配,避开这些bug的折磨。
1.2 软件安装
软件的安装顺序需要保证VS2019的安装在OneAPI之前,因为其安装需要依赖VS2019。
(1)Abaqus 2022安装网上有很多教程,正常安装就行;
(2)VS2019安装社区版,组件只需要勾选C++桌面开发选项;
(3)OneAPI只需要安装HPCKit中的Fortran模块。(节省磁盘空间。。)
1.3 软件关联
找到abq2022.bat编辑打开。
添加如下语句:
call "C:\Program Files (x86)\Intel\oneAPI\compiler\2022.2.1\env\vars.bat" intel64 vs2019
1.4 关联测试
这里给出一段测试代码,将其放在Abaqus Command命令执行目录下,如果能正常编译,说明关联没有问题。
#include <cmath>
#include <aba_for_c.h>extern "C" void FOR_NAME(dload,DLOAD) (double & F, // VALUE TO BE RETURNED: Magnitude of the distributed loadconst int & KSTEP, // Step numberconst int & KINC, // Increment numberconst double(& TIME)[2], // (1) step time; (2) total timeconst int & NOEL, // Element numberconst int & NPT, // Load integration point numberconst int & LAYER, // Layer numberconst int & KSPT, // Section point number within the current layerconst double(& COORDS)[3], // Array containing the coordinates of the load integration pointconst int & JLTYPE, // Load type for which this call to DLOAD is madeconst char (&SNAME)[80] // Surface name
) {F = 100;
}
编译后生成目标文件。
1.5 计算库配置
为了后续发挥出C++编程的优势,我们配置好第三方科学计算库,方便直接调用。这里我使用Armadillo(C++ library for linear algebra & scientific computing)。
将下载好的Armadillo文件夹里/examples/lib_win64路径下的 libopenblas.lib
复制C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\lib\x64
到路径下,而libopenblas.dll
复制到C:\Windows\System32
。
当然还需要告诉VS2019 Armadillo的头文件的位置。直接将下载的Armadillo中include文件夹下的两个文件,复制到此路径C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include
下,这样VS就可以找到相关头文件了。
在VS中测试下使用效果:
#include <armadillo>
#include <iostream>using namespace std;
using namespace arma;int main() {// construct a matrix according to given size and form of element initialisationmat A(2, 3, fill::zeros);// .n_rows and .n_cols are read onlycout << "A.n_rows: " << A.n_rows << endl;cout << "A.n_cols: " << A.n_cols << endl;system("pause");return 0;
}
为了后续能够使用Abaqus方式编译,我们需要将此文件C:\SIMULIA\EstProducts\2022\win_b64\SMA\site\win86_64.env
中的link_sl变量末尾添加文件名:libopenblas.lib
。
2 子程序开发练习
2.1 开发基础
Abaqus的C++子程序开发在帮助文档中很少提及,但是文档在About User Subroutines and Utilities还是进行了简单介绍。只要C++代码外形按照格式开始编写,里面的内容就可以自由发挥啦。关于外形格式我们可以参照Fortran进行编写。
2.2 DLOAD
上面其实我们已经给出了Dload子程序的C++形式,我们可以将其与帮助文档给出的Fortran格式,做个对比,可以看到函数参数是一致的。所以对于任意Fortran格式的子程序,完全可以改写为C++格式。
SUBROUTINE DLOAD(F,KSTEP,KINC,TIME,NOEL,NPT,LAYER,KSPT,1 COORDS,JLTYP,SNAME)
CINCLUDE 'ABA_PARAM.INC'
CDIMENSION TIME(2), COORDS (3)CHARACTER*80 SNAMEuser coding to define FRETURNEND
下面我们通过上述子程序对一个平板表面施加一个压力F=100(Distribution选择User-defined),和直接在abaqus给定的压力做一个对比,验证子程序是否能够正确运行。
上述选项选择编译好的main-std.obj,提交分析。
Job-1是使用子程序计算的结果,Job-2是未使用子程序,二者结果比较在合理误差范围内。
后续将会尝试使用UEL子程序进行一个简单问题的求解,在此之前推荐阅读《有限元方法基础教程》的第十章——等参数公式描述。
点个赞呗👍