Fluent UDF中經(jīng)常需要用到一些常見算法,例如插值、擬合、矩陣運算等等,這些在UDF中是沒有現(xiàn)成函數(shù)實現(xiàn)的,理論上需要我們自己去寫函數(shù)。另一方面我們又注意到這些運算恰恰是Matlab的強(qiáng)項,幾乎調(diào)用一個現(xiàn)成的函數(shù)就完成了目的。所以我們有什么辦法把Matlab函數(shù)給UDF直接調(diào)用呢?
這里提供一種借助于VC++ UDF Studio插件實現(xiàn)調(diào)用Matlab函數(shù)的方法,且編譯好以后的UDF庫拿到?jīng)]有安裝對應(yīng)Matlab版本的機(jī)器上仍然可以使用。以前硫酸亞銅博客(https://www.cnblogs.com/liusuanyatong/p/12128082.html)提供的方法是依賴于Matlab運行庫,編譯好的UDF庫如果拿到?jīng)]有安裝相應(yīng)Matlab版本機(jī)器上是沒法運行的。
???????? 前面博客文章已經(jīng)介紹過用VC++ UDF Studio插件實現(xiàn)調(diào)用誤差函數(shù)erf的例子(https://www.cnblogs.com/SuperUDF/articles/16114086.html)。但是該函數(shù)輸入?yún)?shù)是標(biāo)量,和矩陣輸入?yún)?shù)還是有所不同。所以,這里再以調(diào)用Matlab中的interp2二維插值函數(shù)為例來說明矩陣作為輸入?yún)?shù)時的使用過程。
1. 官網(wǎng)下載VC++ UDF Studio插件并安裝:VC++ UDF Studio,建議下載學(xué)術(shù)版(如想進(jìn)一步采購注冊,對高校老師學(xué)生比較優(yōu)惠)
2.?安裝Visual Studio(插件2022R2開始支持VS2010~2019社區(qū),專業(yè)或旗艦版,建議安裝VS2010旗艦版), C++和C#一起安裝,對于64位Fluent還要勾選X64編譯器。
?
?3.?安裝Matlab 2014a ~ 2021b任一版本,必須勾選Matlab Coder,其它視自己喜好安裝。
?
4.?管理員權(quán)限打開桌面圖標(biāo),選擇需要的版本并勾選“調(diào)用Matlab”后會自動啟動Fluent,讀入case并點擊Fluent嵌入菜單中的“Start Visual Studio”子菜單。
?
5.?把自帶的matlab函數(shù)文件MatlabAdd.m改名為MatlabInterpolate.m,另外一個自動生成的文件MatlabFunctionTester.m是用來在Matlab中測試調(diào)試函數(shù)文件用的,下一步會介紹用法,這一步不用管。然后雙擊打開編輯MatlabInterpolate.m,輸入以下自定義Matlab函數(shù)體。?
function [resultValue]= MatlabInterpolate(X,Y,V,Xi,Yi)
resultValue=interp2(X,Y,V,Xi,Yi);
end
??
6.?雙擊打開MatlabFunctionTester.m,輸入如下測試代碼,從而便于測試我們前面定義的MatlabInterpolate函數(shù)。
clear all
[X,Y]=meshgrid(-2:0.75:2); %6*6的均布網(wǎng)格,每隔0.75一個點
R=sqrt(X.^2+Y.^2)+1E-6;
V=sin(R)./(R); %每個網(wǎng)格點的對應(yīng)函數(shù)值
surf(X,Y,V); %畫出曲面
xlim([-2 2]); %限制顯示x坐標(biāo)區(qū)域為[-2,2]
ylim([-2 2]); %限制顯示y坐標(biāo)區(qū)域為[-2,2]
Xi=0; %要插值點的x坐標(biāo)
Yi=0; %要插值點的y坐標(biāo)
Vi=MatlabInterpolate(X,Y,V,Xi,Yi); %Vi就是插值得到的x=0,y=0處的值
?7.?鼠標(biāo)右鍵在MatlabFunctionTester.m文件上單擊彈出菜單,選擇“用Matlab打開”,這樣就可以在Matlab里面一步一步調(diào)試我們定義的MatlabInterpolate函數(shù),排除錯誤后關(guān)閉Matlab。
?
?畫出來的曲面和各矩陣值如下,插值運算得到Vi結(jié)果為0.9590。
?
8.?點擊工具欄上“將.m文件轉(zhuǎn)為C/C++”按鈕,輸入?yún)?shù)均設(shè)為float類型(雙精度fluent時為double),設(shè)置矩陣尺寸請點擊“矩陣”按鈕,然后勾選“動態(tài)”并確定。注意:試用版沒法開啟“矩陣“作為輸入?yún)?shù),必須購買注冊后才能使用。
?
?
?其中,Dyn*Dyn代表該矩陣行和列都是“動態(tài)尺寸”,例如第一個參數(shù)X轉(zhuǎn)換成C/C++代碼后就會表示為
const emxArray_real32_T *X
?其中,emxArray_real32_T是一個存放動態(tài)數(shù)組的結(jié)構(gòu)體,其定義為
struct emxArray_real32_T
{
float *data; //指向存放數(shù)據(jù)的數(shù)組
int *size; //存放維數(shù)的數(shù)組,實際就是兩個元素size[0]和size[1]
int allocatedSize; //總的元素個數(shù),等于行數(shù)乘以列數(shù)
int numDimensions; //數(shù)組的維數(shù),插件中永遠(yuǎn)是2,代表數(shù)組有行和列2個維數(shù)
boolean_T canFreeData; //是否需要調(diào)用free來釋放由calloc或malloc開辟的data數(shù)組
};
?9.?等待片刻,轉(zhuǎn)換完成后,會自動將對應(yīng)的轉(zhuǎn)換得到的C++頭文件MatlabLibrary.h加入到UDF工程中。
?轉(zhuǎn)換后的C/C++函數(shù)原型為
float MatlabInterpolate(const emxArray_real32_T *X, const emxArray_real32_T *Y, const emxArray_real32_T *V, float Xi, float Yi);
10.?在udf_source.cpp文件中輸入如下示例源代碼,并點擊“編譯UDF”按鈕直到編譯通過。有任何錯誤提示,可以雙擊提示行直接定位到源碼中的錯誤行。編譯通過后按“UDF庫加載到Fluent”按鈕即可載入到Fluent中。
#include "udf.h"
extern "C"
{
#include "MatlabLibrary.h"
}
#define MATRIX_SIZE 6
DEFINE_ON_DEMAND(Interpolate)
{
int X_size[2]={MATRIX_SIZE, MATRIX_SIZE}; //X_size指定X_data的尺寸,本例為6*6矩陣
int Y_size[2]={MATRIX_SIZE, MATRIX_SIZE}; //Y_size指定Y_data的尺寸,本例為6*6矩陣
int V_size[2]={MATRIX_SIZE, MATRIX_SIZE}; //V_size指定V_data的尺寸,本例為6*6矩陣
float X_data[]={ // X_data的具體數(shù)據(jù),C++語言是行優(yōu)先的,所以數(shù)據(jù)應(yīng)該是Matlab矩陣數(shù)據(jù)按照列優(yōu)先排列
-2.0,-2.0,-2.0,-2.0,-2.0,-2.0,
-1.25, -1.25,-1.25,-1.25,-1.25,-1.25,
-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,
0.25,0.25,0.25,0.25,0.25,0.25,
1.0,1.0,1.0,1.0,1.0,1.0,
1.75,1.75,1.75,1.75,1.75,1.75
};
float Y_data[]={ // Y_data的具體數(shù)據(jù),C++語言是行優(yōu)先的,所以數(shù)據(jù)應(yīng)該是Matlab矩陣數(shù)據(jù)按照列優(yōu)先排列
-2.0,-1.25,-0.5,0.25,1.0,1.75,
-2.0,-1.25,-0.5,0.25,1.0,1.75,
-2.0,-1.25,-0.5,0.25,1.0,1.75,
-2.0,-1.25,-0.5,0.25,1.0,1.75,
-2.0,-1.25,-0.5,0.25,1.0,1.75,
-2.0,-1.25,-0.5,0.25,1.0,1.75
};
float V_data[MATRIX_SIZE*MATRIX_SIZE]; // V_data存儲坐標(biāo)x,y處對應(yīng)的散點值,即Matlab程序中的V
int RowSize=X_size[0]; // 獲得矩陣的行尺寸
int ColSize=X_size[1]; // 獲得矩陣的列尺寸
for(int i=0;i<RowSize;i++) // 填充坐標(biāo)x,y對應(yīng)的散點值
{
for(int j=0;j<ColSize;j++)
{
float Radius = sqrt(pow(X_data[i*RowSize+j],2)+pow(Y_data[i*RowSize+j],2))+1E-6; //即Matlab程序中的R
V_data[i*RowSize+j]=sin(Radius)/Radius;
}
}
emxArray_real32_T X, Y, V;
X.data = X_data; //指向定長一維數(shù)組X_data
X.size = X_size; //指向定長二維數(shù)組X_size
X.allocatedSize = X_size[0] * X_size[1]; //行數(shù)乘以列數(shù),MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
X.numDimensions = 2; //永遠(yuǎn)為2,代表二維數(shù)組,行和列,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
X.canFreeData = false; //因為X_data不是由calloc或malloc開辟的動態(tài)數(shù)組,所以不需要free,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
Y.data = Y_data; //指向定長一維數(shù)組Y_data
Y.size = Y_size; //指向定長二維數(shù)組Y_size
Y.allocatedSize = Y_size[0] * Y_size[1]; //行數(shù)乘以列數(shù),MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
Y.numDimensions = 2; //永遠(yuǎn)為2,代表二維數(shù)組,行和列,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
Y.canFreeData = false; //因為Y_data不是由calloc或malloc開辟的動態(tài)數(shù)組,所以不需要free,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
V.data = V_data; //指向定長一維數(shù)組V_data
V.size = V_size; //指向定長二維數(shù)組V_size
V.allocatedSize = V_size[0] * V_size[1]; //行數(shù)乘以列數(shù),MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
V.numDimensions = 2; //永遠(yuǎn)為2,代表二維數(shù)組,行和列,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
V.canFreeData = false; //因為V_data不是由calloc或malloc開辟的動態(tài)數(shù)組,所以不需要free,MatlabInterpolate函數(shù)中實際并未用到,此行也可以不寫
float Xi=0, Yi=0; //插值的目標(biāo)x,y值
float Vi=MatlabInterpolate(&X,&Y,&V, Xi,Yi); //調(diào)用Matlab插值函數(shù)
Message0("The interpolated value at coordinate (0,0) is %g\n", Vi);
}
如果出現(xiàn)INFINITY,NAN未聲明的標(biāo)識符的錯誤,那么請使用較高版本的Visual Studio,例如Visual Studio2015或更高。
11.?執(zhí)行DEFINE宏,本例由于插值函數(shù)放在DEFINE_ON_DEMAND宏中,所以在Execute On Demand對話框里面手動執(zhí)行。
?
?12.?Fluent中運行結(jié)果如下,和前面直接Matlab里面的結(jié)果是一致的。文章來源:http://www.zghlxwxcb.cn/news/detail-698531.html
?文章來源地址http://www.zghlxwxcb.cn/news/detail-698531.html
到了這里,關(guān)于Fluent UDF中調(diào)用Matlab矩陣運算函數(shù)(以二維插值為例)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!