乐于分享
好东西不私藏

Ansys Fluent文档-UDF篇:通用DEFINE宏(二)

Ansys Fluent文档-UDF篇:通用DEFINE宏(二)

6DEFINE_EXECUTE_ON_LOADING

①描述

DEFINE_EXECUTE_ON_LOADING是一种通用宏,可用于指定在编译的UDF库加载到Fluent后立即执行的函数。当在加载UDF库时初始化或设置UDF模型时,此功能非常有用。(另外,如果在加载共享库时保存案例文件,则后续每次读取该案例文件时都会执行该UDF。)

编译后的UDF库可通过“编译UDF”功能或UDF库管理器对话框加载。EXECUTE_ON_LOADING类型的UDF是特定库中预留用户自定义标量(UDS)和用户自定义内存(UDM)的最佳位置,同时也可设置UDSUDM名称。

重要提示:DEFINE_EXECUTE_ON_LOADING只能作为已编译的UDF执行。注意:不建议使用DEFINE_EXECUTE_ON_LOADING重命名DPM标量,因为在读取包含此类UDFDPM案例时可能导致Fluent异常终止。该问题的成因在于DEFINE_EXECUTE_ON_LOADING类型UDF会在启用DPM模型之前执行。建议改用DEFINE_EXECUTE_AFTER_CASE来实现此功能。

②用法

DEFINE_EXECUTE_ON_LOADING (name, libname)

nameUDF名称;

char *libnameFluent中已加载的UDF库名称;

DEFINE_EXECUTE_ON_LOADING有两个参数:namelibname。需要为UDF提供一个名称,Fluent将在报告正在运行的EXECUTE_ON_LOADING UDF时使用该名称。libnameFluent设置为指定的库名称(例如libudf),该名称由您输入或保留默认的libudf。传递libname是为了在UDF的消息中使用它。

③示例1

以下名为report_version的简单UDF会在控制台打印一条消息,其中包含正在加载的库的版本号和发行号。

#include"udf.h"// 定义两个静态整型变量,用于存储版本信息// static关键字使这些变量仅在当前源文件中可见 static int version = 1;   // 主版本号,初始化为1 static int release = 2;   // 次版本号(发布版本号),初始化为2 DEFINE_EXECUTE_ON_LOADING(report_version, libname) {    // 输出加载信息到Fluent控制台和信息窗口    Message("\nLoading %s version %d.%d\n",libname,version,release); }// 定义更详细的版本信息#include"udf.h"static int major_version = 2;static int minor_version = 1;static int patch_version = 3;static char *build_date = "2024-01-15";static char *author = "Your Name";DEFINE_EXECUTE_ON_LOADING(report_version, libname){    Message("\n========================================\n");    Message("Loading UDF Library: %s\n", libname);    Message("Version: %d.%d.%d\n", major_version, minor_version, patch_version);    Message("Build Date: %s\n", build_date);    Message("Author: %s\n", author);    Message("========================================\n");}

④示例2

以下源代码包含两个用户自定义函数(UDF)。第一个UDFEXECUTE_ON_LOADING函数,用于为库保留三个UDM(通过Reserve_User_Memory_Vars)并为UDM存储位置设置唯一名称(通过Set_User_Memory_Name)。第二个UDFON_DEMAND函数,用于在求解初始化后设置UDM存储位置的值。该ON_DEMAND通过udm_offset(在加载UDF中定义)设置UDM存储位置的初始值。请注意,必须在求解初始化after执行该按需UDF以重置UDM的初始值。

include"udf.h"// 定义宏,表示需要预留的用户自定义内存(UDM)数量为3define NUM_UDM 3 // 声明静态全局变量udm_offset,用于存储预留的UDM起始索引// 初始化为UDM_UNRESERVED(通常为-1),表示尚未预留static int udm_offset = UDM_UNRESERVED;// 定义在UDF库加载时自动执行的函数// on_loading: 函数名// libname: 库名称参数,由Fluent在加载时自动传入DEFINE_EXECUTE_ON_LOADING(on_loading, libname){    // 如果udm_offset为未预留状态,则尝试预留NUM_UDM个UDM变量    if (udm_offset == UDM_UNRESERVED)         udm_offset = Reserve_User_Memory_Vars(NUM_UDM);  // 预留UDM,返回起始索引    // 检查预留是否成功(返回值仍为UDM_UNRESERVED表示失败)    if (udm_offset == UDM_UNRESERVED)        // 预留失败,输出提示信息要求用户在GUI中定义更多UDM        Message("\nYou need to define up to %d extra UDMs in GUI and "               "then reload current library %s\n", NUM_UDM, libname);    else  // 预留成功    {        // 输出成功预留UDM的信息        Message("%d UDMs have been reserved by the current "               "library %s\n", NUM_UDM, libname);        // 为预留的UDM设置描述性名称,便于在Fluent界面中识别        Set_User_Memory_Name(udm_offset, "lib1-UDM-0");      // 第一个UDM        Set_User_Memory_Name(udm_offset + 1"lib1-UDM-1");  // 第二个UDM        Set_User_Memory_Name(udm_offset + 2"lib1-UDM-2");  // 第三个UDM    }    // 输出当前库的UDM起始偏移量    Message("\nUDM Offset for Current Loaded Library = %d", udm_offset);}// 定义ON_DEMAND函数,可以通过Fluent界面手动执行// set_udms: 函数名DEFINE_ON_DEMAND(set_udms){    Domain *d;      // 声明域指针    Thread *ct;     // 声明线程指针    cell_t c;       // 声明单元索引    int i;          // 声明循环计数器    // 获取域指针(主域或混合物域)    d = Get_Domain(1);    // 检查UDM是否已成功预留    if(udm_offset != UDM_UNRESERVED)    {        // UDM已预留,开始设置UDM的值        Message("Setting UDMs\n");        // 循环遍历预留的每个UDM(共NUM_UDM个)        for (i = 0; i < NUM_UDM; i++)        {            // 遍历域中的所有单元线程            thread_loop_c(ct, d)            {                // 在当前线程中遍历所有单元                begin_c_loop(c, ct)                {                    // 将当前单元的当前UDM设置为特定值                    // udm_offset+i: UDM的实际索引(起始偏移量 + 序号)                    // 3.0 + i/10.0: 设置的值,例如:                    //   i=0 -> 3.0 + 0/10.0 = 3.0                    //   i=1 -> 3.0 + 1/10.0 = 3.1                    //   i=2 -> 3.0 + 2/10.0 = 3.2                    C_UDMI(c, ct, udm_offset + i) = 3.0 + i / 10.0;                }                end_c_loop(c, ct)  // 结束单元循环            }        }    }    else  // UDM未预留    {        // 输出错误信息        Message("UDMs have not yet been reserved for library 1\n");    }}

7DEFINE_EXECUTE_AFTER_CASE/DATA

①描述

DEFINE_EXECUTE_AFTER_CASEDEFINE_EXECUTE_AFTER_DATA是通用宏,可用于指定在Fluent中读取案例文件和/或数据文件后执行的函数。这非常有用,因为它提供了在读取案例文件和/或数据文件后访问UDF函数的能力。

重要提示:DEFINE_EXECUTE_AFTER_CASEDEFINE_EXECUTE_AFTER_DATA只能作为编译型UDF执行。

②用法

DEFINE_EXECUTE_AFTER_CASE/DATA (name,libname)

nameUDF名称;

char *libnameFluent中已加载的UDF库名称;

DEFINE_EXECUTE_AFTER_CASEDEFINE_EXECUTE_AFTER_DATA有两个参数:namelibname。需要提供一个名称,Fluent将在报告正在运行的 EXECUTE_AFTER_CASEEXECUTE_AFTER_DATA时使用该名称。libnameFluent设置为指定的库名称(例如libudf)(通过输入名称或保留默认的libudf)。传递libname是为了可以在UDF的消息中使用它。

③示例

以下名为after_caseafter_data的简单UDF,会向控制台打印一条包含正在加载库名称的消息。

#include "udf.h" DEFINE_EXECUTE_AFTER_CASE(after_case, libname) {      Message("EXECUTE_AFTER_CASE called from $s\n", libname);  } DEFINE_EXECUTE_AFTER_DATA(after_data, libname {      Message("EXECUTE_AFTER_DATA called from $s\n", libname); }

8DEFINE_INIT

①描述

DEFINE_INIT是一种通用宏,可用于为求解设定初始值。DEFINE_INIT通过用户自定义函数(UDF)实现与修补相同的效果,但实现方式不同。DEFINE_INIT函数在每次初始化时执行一次,并在求解器完成默认初始化后立即调用。由于该函数在流场初始化完成后才被调用,因此通常用于设置流量的初始值。

②用法

DEFINE_INIT (name, d)

nameUDF名称;

Domain *d:指向初始化函数所要应用的域。域参数提供对网格中所有单元和面线程的访问。对于多相流,求解器传递给函数的指针是混合物级别的域。

DEFINE_INIT有两个参数:named。需要提供UDF的名称name,而d则由Fluent求解器传递给UDF

③示例

以下名为my_init_funcUDF用于初始化解决方案中的流场变行。该函数在求解过程开始时执行一次,可在Fluent中作为解释型或编译型UDF执行。

 #include"udf.h"// 定义初始化函数,在求解器初始化阶段执行(在迭代开始前执行一次)// my_init_func: 函数名// d: 域指针,指向整个计算域DEFINE_INIT(my_init_func, d){    cell_t c;        // 声明单元索引,用于遍历网格单元    Thread *t;       // 声明线程指针,用于遍历不同的网格区域    real xc[ND_ND];  // 声明实型数组,用于存储单元中心坐标    /* loop over all cell threads in the domain */    // 循环遍历域中的所有单元线程    thread_loop_c(t, d)    {        /* loop over all cells */        // 开始在当前线程中循环遍历所有单元        begin_c_loop_all(c, t)        {            // 获取当前单元的中心坐标,存储在xc数组中            // ND_ND: Fluent宏,表示空间维度数(2D时为2,3D时为3)            // xc[0], xc[1], xc[2] 分别对应x, y, z坐标            C_CENTROID(xc, c, t);            // 计算当前单元中心到点(0.5, 0.5, 0.5)的欧几里得距离            // ND_SUM: 对参数求和,用于处理不同维度的情况            // pow(xc[0] - 0.5, 2.): 计算(x-0.5)²            // pow(xc[1] - 0.5, 2.): 计算(y-0.5)²            // pow(xc[2] - 0.5, 2.): 计算(z-0.5)²(如果是2D,此项为0)            // sqrt(...): 计算平方根,得到距离            if (sqrt(ND_SUM(pow(xc[0] - 0.52.),                           pow(xc[1] - 0.52.),                           pow(xc[2] - 0.52.))) < 0.25)                // 如果距离小于0.25,设置单元温度为400K                C_T(c, t) = 400.;            else                // 否则,设置单元温度为300K                C_T(c, t) = 300.;        }        end_c_loop_all(c, t)  // 结束单元循环    }}

9DEFINE_ON_DEMAND

①描述

DEFINE_ON_DEMAND是一种通用宏,可用于指定在Fluent中“按需”执行的UDF,而不是由Fluent在计算过程中自动调用。UDF在激活后会立即执行,但在求解器迭代期间不可访问。请注意,域指针d不会作为参数显式传递给DEFINE_ON_DEMAND。因此,若要在按需函数中使用域变量,需要先使用Fluent提供的Get_Domain实用程序获取该变量。

②用法

DEFINE_ON_DEMAND (name)

nameUDF名称。

DEFINE_ON_DEMAND 只有一个参数:name,需要定义UDF的名称。

③示例

以下名为on_demand_calcUDF会计算并输出当前数据字段的最低、最高和平均温度,随后计算温度函数,并将其存储在用户定义的0内存位置。挂载按需UDF后,该字段值将在Fluent后处理对话框的下来列表中可用。可以通过选择“用户定义内存”类别中的“用户内存0”来选定此字段。执行UDF后若写入数据文件,用户定义内存字段将保存至数据文件中。

include"udf.h"DEFINE_ON_DEMAND(on_demand_calc){    Domain *d; /* declare domain pointer since it is not passed as an       argument to the DEFINE macro */  // 声明域指针(ON_DEMAND函数没有域参数)    // 声明并初始化温度统计变量    real tavg = 0.;  // 体积平均温度    real tmax = 0.;  // 最高温度    real tmin = 0.;  // 最低温度    // 声明局部变量    real temp, volume, vol_tot;  // 临时温度、单元体积、总体积    Thread *t;  // 声明线程指针    cell_t c;   // 声明单元索引    d = Get_Domain(1);  /* Get the domain using Ansys Fluent utility */  // 获取域指针    /* Loop over all cell threads in the domain */    // 循环遍历域中的所有单元线程    thread_loop_c(t, d)    {        // 重置体积累加器(注意:应该在循环开始前初始化vol_tot)        vol_tot = 0.        /* Compute max, min, volume-averaged temperature */        /* Loop over all cells */        // 开始在当前线程中循环遍历所有单元,计算温度统计值        begin_c_loop(c, t)        {            volume = C_VOLUME(c, t);  /* get cell volume */  // 获取单元体积            temp = C_T(c, t);         /* get cell temperature */  // 获取单元温度            // 更新最低温度            if (temp < tmin || tmin == 0.                tmin = temp;            // 更新最高温度            if (temp > tmax || tmax == 0.                tmax = temp;            vol_tot += volume;    // 累加总体积            tavg += temp * volume; // 累加温度×体积(用于计算体积加权平均值)        }        end_c_loop(c, t)  // 结束单元循环        // 计算体积平均温度        tavg /= vol_tot;  // 平均温度 = 总和(温度×体积) / 总体积        // 输出温度统计结果到控制台        printf("\n Tmin = %g  Tmax = %g  Tavg = %g\n", tmin, tmax, tavg);        /* Compute temperature function and store in user-defined memory*/        /* (location index 0) */        // 计算温度归一化值并存储到用户自定义内存(UDM)索引0        begin_c_loop(c, t)        {            temp = C_T(c, t);  // 获取单元温度            // 计算归一化温度:(温度 - 最低温度) / (最高温度 - 最低温度)            C_UDMI(c, t, 0) = (temp - tmin) / (tmax - tmin);        }        end_c_loop(c, t)  // 结束单元循环    }}

Get_Domain是一个用于获取域指针的宏。由于域指针未作为显式参数传递给DEFINE_ON_DEMAND,因此必须使用此宏来获取域指针。该函数名为on_demand_calc,不接受任何显式参数。在函数内部主体部分,首先定义并初始化函数要使用的变量。变量声明之后,使用循环宏对域中的每个单元线程进行循环。在该循环内部,另一个循环用于遍历所有单元。在内层循环中,计算总体积以及最小、最大和体积平均温度。这些计算值将输出到Fluent控制台。随后对每个单元进行第二次循环用于计算函数f(x)并将其存储在用户自定义内存0位置。

10DEFINE_REPORT_DEFINITION_FN

①描述

DEFINE_REPORT_DEFINITION_FN是一个宏,可以使用它来指定用于报告单值表达式的UDF,该表达式可以被绘制、写入或打印到控制台作为报告定义。

②用法

DEFINE_REPORT_DEFINITION_FN (name)

name:用户自定义报告定义函数的名称。

DEFINE_REPORT_DEFINITION_FN只有一个参数:name,需要定义UDF的名称。

③示例

该函数计算入口处的体积流量,展示了在输入变量上执行操作的能力,并将结果输出用于绘图、打印或作为用户自定义报告定义的一部分写入文件。

 #include "udf.h" DEFINE_REPORT_DEFINITION_FN(volume_flow_rate_inlet) {   real inlet_velocity = Get_Input_Parameter("vel_in");   real inlet_area  =  0.015607214;  real volumeFlow = inlet_velocity*inlet_area;    return volumeFlow; }

参考资料:Ansys Fluent UDF Manual》 2023R1

CFD理论基础合集(持续更新中):

Ansys Fluent帮助文档-UDF篇:用户自定义函数概述(UDFs)(一)

Ansys Fluent帮助文档-UDF篇:用户自定义函数概述(UDFs)(二)

Ansys Fluent帮助文档-UDF篇:通用DEFINE宏(一)

特别感谢您的阅读、点赞、转发、推荐!

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » Ansys Fluent文档-UDF篇:通用DEFINE宏(二)

评论 抢沙发

1 + 9 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮