UDF Pouejjejejej hehhee heheheheheheeie eheuewer Points.pdf

cryptotackle45 15 views 128 slides Mar 09, 2025
Slide 1
Slide 1 of 128
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53
Slide 54
54
Slide 55
55
Slide 56
56
Slide 57
57
Slide 58
58
Slide 59
59
Slide 60
60
Slide 61
61
Slide 62
62
Slide 63
63
Slide 64
64
Slide 65
65
Slide 66
66
Slide 67
67
Slide 68
68
Slide 69
69
Slide 70
70
Slide 71
71
Slide 72
72
Slide 73
73
Slide 74
74
Slide 75
75
Slide 76
76
Slide 77
77
Slide 78
78
Slide 79
79
Slide 80
80
Slide 81
81
Slide 82
82
Slide 83
83
Slide 84
84
Slide 85
85
Slide 86
86
Slide 87
87
Slide 88
88
Slide 89
89
Slide 90
90
Slide 91
91
Slide 92
92
Slide 93
93
Slide 94
94
Slide 95
95
Slide 96
96
Slide 97
97
Slide 98
98
Slide 99
99
Slide 100
100
Slide 101
101
Slide 102
102
Slide 103
103
Slide 104
104
Slide 105
105
Slide 106
106
Slide 107
107
Slide 108
108
Slide 109
109
Slide 110
110
Slide 111
111
Slide 112
112
Slide 113
113
Slide 114
114
Slide 115
115
Slide 116
116
Slide 117
117
Slide 118
118
Slide 119
119
Slide 120
120
Slide 121
121
Slide 122
122
Slide 123
123
Slide 124
124
Slide 125
125
Slide 126
126
Slide 127
127
Slide 128
128

About This Presentation

Djjd


Slide Content

© 2012 ANSYS, Inc. March 14, 2012 1
Release 14.0
Customer Training Material
14. 0 Release
Advanced Fluent
User-Defined Functions
Chapter 1
Introduction to Fluent
from the Inside

© 2012 ANSYS, Inc. March 14, 2012 2
Release 14.0
Customer Training Material
Introduction to UDF Programming
•Why use UDFs?

Fluent is a general‐purpose tool and cannot anticipate all users needs.

Addition of new physical models for academic research or customer 
proprietary physics.

Customization of boundary conditions.

© 2012 ANSYS, Inc. March 14, 2012 3
Release 14.0
Customer Training Material
What is a User Defined Function (UDF)?
•A UDF is a function or set of functions programmed by the user in C language and 
linked to Fluent to perform a wide variety of operations including:

Initialization

Custom boundary conditions (both space or time dependent)

Material properties

Source terms into any of the flow equations

Chemical reaction rates

Post processing and reporting of modified data

Adding extra flow equations

Mesh motion

Discrete phase model modification

And many more...

© 2012 ANSYS, Inc. March 14, 2012 4
Release 14.0
Customer Training Material
User Access to the Fluent Solver
User-Defined Properties
User-Defined BCs
User Defined
INITIALIZE
Segregated PBCS
Exit Loop
Repeat
Check Convergence
Update Properties
Solve Turbulence Equation(s)
Solve Species Solve Energy
Initialize
Begin Loop
DBCS
Solve Other Transport Equations as required
Solver?
Solve Mass Continuity;
Update Velocity
Solve U-Momentum Solve V-Momentum Solve W-Momentum
Solve Mass
& Momentum
Solve Mass,
Momentum,
Energy,
Species
User-
defined
ADJUST
Source terms
Source terms
Source terms
Source
terms
There are many places within the solution cycle where a UDF
can be added:

© 2012 ANSYS, Inc. March 14, 2012 5
Release 14.0
Customer Training Material
Data Structures
•Each type of UDF is passed different values and data structures 
depending on its function.
•Most UDFs will need geometrical data. This is stored in a hierarchy:

Domainsare collections of threads that make the whole mesh

Threads(or zones) are collections of cells or faces

Cellsand facesare made of Nodes

© 2012 ANSYS, Inc. March 14, 2012 6
Release 14.0
Customer Training Material
Geometrical Entities
•The parts of a mesh are: 

© 2012 ANSYS, Inc. March 14, 2012 7
Release 14.0
Customer Training Material
Data Structures
•The terms ‘Thread’ and ‘Zone’ are interchangeable. The boundary 
and cell zones defined in the User Interface are stored internally as 
threads.

Zones have an associated integer ID seen in the settings panel

In a UDF, the corresponding thread can be identified using this ID

Threads are an internal data type which stores information about the mesh, 
models, properties, BCs all in one place
•A cell has information about its bounding faces and a face has access to 
its neighbouring cells.

© 2012 ANSYS, Inc. March 14, 2012 8
Release 14.0
Customer Training Material
14. 0 Release
Advanced Fluent
User-Defined Functions
Introduction to the C
Programming Language

© 2012 ANSYS, Inc. March 14, 2012 9
Release 14.0
Customer Training Material
C Programming (1)

Basic syntax rules:
•Each statement must be terminated with a semicolon ;
•Comments can be inserted anywhere between  /*and  */
•All variables must be explicitly declared (unlike in FORTRAN)
•Compound statements can be created by enclosing multiple statements by braces: 
{  }
•Function definitions have the following format:
return-value-type function-name(parameter-list)
{ function body }

Built‐in data types: int, float, double, enum, boolean: int niter, a; /* Declare ‘niter’ and ‘a’ as integers */
float dx[10]; /* dxis an array of 10 numbers indexed from 0-9:
dx[0], dx[1] … dx[8], dx[9] */
enum {X, Y, Z}; /* X, Y, Z are enumeration constants = 0, 1, 2 */

© 2012 ANSYS, Inc. March 14, 2012 10
Release 14.0
Customer Training Material
C Programming (2)
•A Pointer is a special kind of variable that contains an addressin memory, not content, of 
another variable
•Pointers are declared using the * notation:
int *ip; /* ip is declared as a pointer to integer */
•We can make a Pointer point to the address of predefined variable as follows:
int a = 1;
int *ip; /* (*ip) contains an integer */
ip = &a; /* &a returns the address of variable a */
printf(“ip is a pointer with value %p”, ip);
printf(“The integer stored at ip = %d”,*ip);
ip is a pointer with value 0x40b2
The integer stored at ip = 1

© 2012 ANSYS, Inc. March 14, 2012 11
Release 14.0
Customer Training Material
C Programming (3)
•Pointers and arrays are closely related:
int ar[10]; /* ar is an array of 10 integers */
int *ip; /* (*ip) contains an integer, */
The name of an array without an index can be 
used as a pointer to the start of the array 
ip = ar; /* ar is the address of its first integer
so this is equivalent to ip = &(ar[0]); */
BUT:
An array name cannot be set to a new value.
It is fixed to the value set when it is defined as an array.
ar = &i; /* This will cause a compilation error */

© 2012 ANSYS, Inc. March 14, 2012 12
Release 14.0
Customer Training Material
C Programming (4)

Operators =(assignment)
+, -, *, /, %(modulus)
<, >, >=, <= , ==, !=
++ increment;   i++is “post‐increment”: use the currentvalue of  iin the 
expression, then increment iby 1 (i=i+1) 
--decrement:   j--post‐decrement, use the current value ofj, then 
decrementj by 1 (j=j-1)
+=addition assignment:
agg += single; /* means: agg = agg + single; */
*=multiplication assignment,
-= subtraction assignment,
/=division assignment

© 2012 ANSYS, Inc. March 14, 2012 13
Release 14.0
Customer Training Material
C Programming (5)

Basic control structures
if ( … )
<statement>;
if ( …)
<statement>;
else
<statement>;
if ( …)
<statement>;
else if ( … )
<statement>;
for loops:
for ( k=0; k < NUM; k++ )
<statement>;
while loops:
while ( … )
<statement>;
Conditional Operator (? : )
( condition ? operand a : operand b )
example:
real At = (rp_axi ? At*2*M_PI : At );

© 2012 ANSYS, Inc. March 14, 2012 14
Release 14.0
Customer Training Material
C Programming (6)

Compound statements may be placed wherever a simple statement is 
allowed:
if ( k > 2 )
{
<statement>;
<statement>;

}
else
{
<statement>;
<statement>;

}
and in loops:
for ( k=0; k < NUM; k++ )
{
<statement>;
<statement>;

}
while ( k < NUM )
{
<statement>;
k++;

}

© 2012 ANSYS, Inc. March 14, 2012 15
Release 14.0
Customer Training Material
C Programming (7)

Structures
•Structures are collections of data that are of different types.
struct car_struct
{
char model_name[25];
int number_of_wheels;
int engine_cc;
real top_speed;
}; /* Need a ‘;’ as variables can be defined here*/
struct car_struct alices_car, bobs_car; /* or here */
/* Set and get values like this: */
alices_car.top_speed = 120.0;
if(bobs_car.top_speed > alices_car.top_speed)

© 2012 ANSYS, Inc. March 14, 2012 16
Release 14.0
Customer Training Material
C Programming (8)

In Fluent, structures are used for many things.
•The most common one is Thread.
•This is actually defined using the typedefstatement so we don’t need to 
use the word structwhen defining new Threads:
typedefstruct thread_struct
{
...
int id;
...
} Thread; /* typedefmakes a new Thread type */
Thread *ct; /* Usually we use pointers to structures */
/* Macros are defined to access structure elements */
#define THREAD_ID(t)((t)->id)
/* Note ‘->’ operator:t->id is the same as (*t).id */

© 2012 ANSYS, Inc. March 14, 2012 17
Release 14.0
Customer Training Material
14. 0 Release
Advanced Fluent
User-Defined Functions
Introduction to UDF
Implementation Using C

© 2012 ANSYS, Inc. March 14, 2012 18
Release 14.0
Customer Training Material
Why UDFs are written in the C
Language
Fluent is written in C because it is a very powerful language. It provides access to high 
level operations such as graphics and networking and low level capabilities such as 
mathematical functions and memory operations.
It enables the linking of extra functionality using “shared objects” in Unix and Dynamic 
Linked Libraries
 (DLLs) in windows systems.
This is a very convenient mechanism for linking in UDFs which allows a seamless 
connection between the main program and the user functions 
Users familiar with other “procedural” languages such as FORTRAN will be familiar with 
most of the ideas and syntax used in C

© 2012 ANSYS, Inc. March 14, 2012 19
Release 14.0
Customer Training Material
Mesh Data Types (1)
•There are several Fluent‐specific data types that are associated with mesh 
components.
•Some of the more commonly used ones are:

Node– stores data associated with a grid point

face_t– identifies a face within a face thread

cell_t– identifies a cell within a cell thread

Thread–stores data that is common to a collection of cells or faces

Domain – stores data associated with a collection of face and cell threads in a mesh
•Each individual cell can be accessed by using a cell index of type cell_tand the 
cell thread (the zone which contains the cell)
•Similarly, each individual face (boundary or internal) can be accessed by using 
the face index of type face_tand the face thread (the zone which contains the 
face)

© 2012 ANSYS, Inc. March 14, 2012 20
Release 14.0
Customer Training Material
Mesh Data Types (2)
•Some mesh or solver data types have a capital letter. These are actually data 
structures in the C language and are usually passed between functions as 
pointers to these structures. 
•Examples of how these data types are defined are shown below:
Type Example Declaration
Domain *d;d is a pointer to a Domain structure
Thread *t;t is a pointer to a Thread structure
cell_t c;c is cell index, a simple integer
face_t f;f is a face index, a simple integer
Node *node;node is pointer to a Node structure

© 2012 ANSYS, Inc. March 14, 2012 21
Release 14.0
Customer Training Material
•Every Zone is associated to a single ID available in the BC panel or the TUI using:
/grid/modify-zones/list-zones
•Given the ID, the thread associated with
that zone can be retrieved as:
int t_id = 7;
Thread *ft;
ft = Lookup_Thread(domain, t_id);
•Once we have the thread we can access
its associated data
•Similarly, a thread’s ID can be retrieved using:
t_id = THREAD_ID(ft);
Mesh Data Types (3)

© 2012 ANSYS, Inc. March 14, 2012 22
Release 14.0
Customer Training Material
C macros and UDF Programming
•C has a very powerful macro definition capabilities. These are used 
extensively in Fluent in many ways. Notable example include 
definitions of:

Data structure looping macros

Geometry macros

Field data Macros

Logic and status control macros

Safe arithmetic and trigonometry functions

Complete set of vector arithmetic operations
•The definition of each UDF also uses a specific DEFINE_  macro.

© 2012 ANSYS, Inc. March 14, 2012 23
Release 14.0
Customer Training Material
Loop Macros in a UDF
•thread_loop_c(t,d) Loop over the cell threads in a domain d
•thread_loop_f(t,d) Loop over face threads in a domain d
•begin_c_loop(c,t) Loop over the cells in a given cell thread
end_c_loop (c,t)
•begin_f_loop(f,t) Loop over the faces in a given face thread
end_f_loop(f,t)

© 2012 ANSYS, Inc. March 14, 2012 24
Release 14.0
Customer Training Material
Geometry Macros

C_CENTROID(pos,c, t) x, y, z coords of cell  centroid

F_CENTROID(pos, f, t) x, y, z coords of face centroid

F_AREA(A, f, t)Area vector of a face; 

NV_MAG(A)Vector magnitude

C_VOLUME(c, t)Volume of a cell

C_VOLUME_2D(c, t)Volume of a 2D cell
(pos& Aare vectors which are discussed later)
(Depth is 1 m in 2D; 2*radians in axi‐symmetric)

NODE_X(nn)Node x‐coord;  (with  Node *nn;)

NODE_Y(nn)Node x‐coord; 

NODE_Z(nn)Node x‐coord;
Many more are available. See the Fluent UDF Manual
Location of cell variables
C_NNODES(c,t) = 8
C_NFACES(c,t) = 6
F_NNODES(f,t) = 4 each
A Hex cell
Faces
Nodes

© 2012 ANSYS, Inc. March 14, 2012 25
Release 14.0
Customer Training Material
Cell‐Face Connectivity
•The cells either side of a face (f,ft) can be accessed using the macros:
ct0 = THREAD_T0(ft);
ct1 = THREAD_T1(ft);
c0 = F_C0(f,ft);
c1 = F_C1(f,ft);
•The macros THREAD_T0(ft)& THREAD_T1(ft)only need the face thread, 
not the face index. This is because in Fluent, an interior zone must connect to the 
same fluid or solid zones on either side.
•Boundary zones 
such as inlets will connect to a cell zone on one side with 
THREAD_T0(ft)but THREAD_T1(ft)will return NULL, a special pointer 
which signifies there is no zone on the other side.
C0
C1

© 2012 ANSYS, Inc. March 14, 2012 26
Release 14.0
Customer Training Material
Cell‐Face Connectivity (2)
•A face’s area is obtained as a vector using:
real A[3];
f = F_AREA(A,f,ft);
The area can be used to calculate the face normal
•The faces that bound a cell can be accessed using this loop :
int nf;
for(nf=0;nf<C_NFACES(c,ct);nf++)
{
f = C_FACE(c,ct,nf);
ft = C_FACE_THREAD(c,ct,nf);
}
C0 A face’s area vector
points from C0 to C1
C1

© 2012 ANSYS, Inc. March 14, 2012 27
Release 14.0
Customer Training Material
Field Variables Macros -Cell
•C_R(c,t)Density
•C_P(c,t)Pressure
•C_U(c,t)
•C_V(c,t)X, Y & Z Velocity Components
•C_W(c,t)
•C_T(c,t)Temperature
•C_H(c,t)Enthalpy
•C_K(c,t)Turbulent Kinetic Energy
•C_D(c,t)Turbulent Energy Dissipation
•C_YI(c,t,i)i‐thSpecies Mass Fraction
•C_UDSI(c,t,i) i‐thUser Defined Scalar
•C_UDMI(c,t,i) i‐thUser Defined Memory
tis a cell‐thread pointer, cis a cell index,  and iis an integer for 
indexing which 
species, UDS and UDM require.

© 2012 ANSYS, Inc. March 14, 2012 28
Release 14.0
Customer Training Material
Macros used for Control
•Data_Valid_P()
Equals 1 if data is available 0 if not. 
if (!Data_Valid_P()) return;
•FLUID_THREAD_P(t0)
Checks to see if thread t0 is a fluid thread
•NULLP(ct)
NULLP checks if a pointer is NULL
•NNULLP(ct)
NNULLP checks if a pointer is NOT NULL
if(NNULLP(THREAD_T1(ft)))
{ ... Do things on neighbouring cell thread.}

© 2012 ANSYS, Inc. March 14, 2012 29
Release 14.0
Customer Training Material
UDF Defining Macros
•All UDFs that will be used in Fluent must be defined using a specific DEFINE_
macro
•Some examples are:
Profiles: DEFINE_PROFILE
Source terms: DEFINE_SOURCE
Properties: DEFINE_PROPERTY
User-defined Scalars: DEFINE_UNSTEADY
DEFINE_FLUX
DEFINE_DIFFUSIVITY
Initialization: DEFINE_INIT
Global Functions: DEFINE_ADJUST
DEFINE_ON_DEMAND
DEFINE_RW_FILE
Refer to the UDF Manual for a complete list

© 2012 ANSYS, Inc. March 14, 2012 30
Release 14.0
Customer Training Material
Additional Information
•Many additional macros are available to implement different physical models
including: 
combustion models
particles‐based models 
•It is also possible to develop additional numerical methods, particularly when 
using User Defined Scalars. Access to low‐level operations is possible, such as:
flux discretisation
variable reconstruction and clipping

© 2012 ANSYS, Inc. March 14, 2012 31
Release 14.0
Customer Training Material
The Header Files
•The UDF macros are defined in the
‘udf.h’
file, for instance:
•The file
udf.h
is a fluent header file in the
{Fluent installed
directory}/FluentX.Y/src/
directory
•The line:
include “udf.h”
must be at the top of every file defining any UDFs

A file may contain more than one UDF function definition

Multiple files can be used to define different related sets of functions
•There are many more header files stored in the same directory which 
can be browsed by users but most are already included automatically 
within 
udf.h
#define DEFINE_PROFILE(name, t, i) void name(Thread *t, int i)
#define DEFINE_PROPERTY(name,c,t) real name(cell_t c, Thread *t)
#define DEFINE_SOURCE(name, c, t, dS, i) \
real name(cell_t c, Thread *t, real dS[], int i)
#define DEFINE_INIT(name, domain) void name(Domain *domain)
#define DEFINE_ADJUST(name, domain) void name(Domain *domain)

© 2011 ANSYS, Inc. March 14, 2012 1
Release 14.0
Customer Training Material
14. 0 Release
Advanced Fluent
User-Defined Functions
Chapter 2
Compilation and Interpretation

© 2012 ANSYS, Inc. March 14, 2012 2
Release 14.0
Customer Training Material
How to use UDFs
UDFs must be compiled and linked to the main code
There are two options: •
Interpreted
–The UDF is translated into assembly code which is executed on a “line‐by‐line” 
basis at run time
–Does not need a separate compiler (completely automatic)
–Slower execution and uses more memory
–Only basic language and FLUENT features implemented
–Restricted functionality in parallel cases

Compiled
–The UDF files are compiled and linked to the main code
–Full C language and all standard libraries
–Access to full FLUENT function set
–Needs a compiler for every OS to be used on

© 2012 ANSYS, Inc. March 14, 2012 3
Release 14.0
Customer Training Material
Interpreted UDFs The interpreter does not have all of the capabilities of the
standard C compiler
Interpreted UDFs cannot contain •
declarations of local structures, unions, pointers to functions,
and arrays of functions

direct structure references
Can access data stored in a FLUENT structure only via a
limited set of macros
Users are strongly encouraged to use compilation for all
but the most simple UDFs

© 2012 ANSYS, Inc. March 14, 2012 4
Release 14.0
Customer Training Material
Define → User Defined → Interpreted
Interpreting the UDFs
Click Interpret
Default stack size might be too small for large
arrays so may need increasing The assembly language code will be
displayed if no errors are found.

© 2012 ANSYS, Inc. March 14, 2012 5
Release 14.0
Customer Training Material
Compiling the UDFs
Define → User Defined → Func?on → Compiled •
Click Build

The compiler will build the shared object files 

Load the shared library 

On Windows to recompile you will need to unload a previously compiled UDF library 
using:
–Define → User Defined → Func?on → Manage
–Select the library and then click Unload

© 2012 ANSYS, Inc. March 14, 2012 6
Release 14.0
Customer Training Material
14. 0 Release
Advanced Fluent
User-Defined Functions
Appendix

© 2012 ANSYS, Inc. March 14, 2012 7
Release 14.0
Customer Training Material
ntx86
w-profile.c
makefile
user_nt.udf
libudf.dll
makefile
user_nt.udf
libudf.dll
src
Windows Tree
libudf
3d
2d
libudf
Makefile
src
ultra
2d
3d
makefile
w-profile.c
libudf.so
makefile
w-profile.c
libudf.so
Unix Tree
w-profile.c
Machine dependent
irix6r10
ultra
hp700
Directory Tree for a Compiled UDF Library
makefile

© 2012 ANSYS, Inc. March 14, 2012 1
Release 14.0
14. 0 Release
Advanced Fluent
User-Defined Functions
Chapter 3
Composing UDFs

© 2012 ANSYS, Inc. March 14, 2012 2
Release 14.0
Using the DEFINE Macros
All UDFs are defined using a macro that starts with “DEFINE_”
The general format of a DEFINE_ macro is:
DEFINE_UDF_TYPE(udf_name, 0 or more variables...) •
udf_name is the name of the function you define
–It is case‐sensitive
–This is the name seen in the pick lists in the GUI panel
Example:
DEFINE_PROFILE(inlet_x_velocity, thread, index) •
Defines boundary profile name “inlet_x_velocity”

threadis the boundary thread which will be changed

indexidentifies which boundary condition value is to be set

© 2012 ANSYS, Inc. March 14, 2012 3
Release 14.0
Boundary Conditions
DEFINE_PROFILE can be used on any boundary zone to set conditions such as 
temperature, velocity  etc.
It is possible to specify a constant value, position‐dependent or time‐dependent 
values
Note that the BCs are applied at the faces of boundary, not the adjacent cells.

© 2012 ANSYS, Inc. March 14, 2012 4
Release 14.0
DEFINE_PROFILE
The following UDF sets the value of x‐velocity at the face of the inlet boundary zone according to 
the equation:
V
x
= V
o
+ A sin(t); V
o
= 20 m/s, A = 5 m/s, = 10 rad/s
•Loop through the faces belonging to the inlet zone
•Specify the x‐velocity component on each face using F_PROFILE(f, ft, var) = …
#include "udf.h"
#define OMEGA 10.0 /*User constants can be set like this */
#define V0 20.0
#define V_AMP 5.0
DEFINE_PROFILE(inlet_x_velocity, ft, var)
{
real flow_time;
face_tf; /* Face index has its own type */
flow_time = CURRENT_TIME; /* Special Fluent macro */
begin_f_loop(f,ft) /* Fluent has special face loop macros too */
{
F_PROFILE(f,ft,var) = V0 +V_AMP * sin(OMEGA*flow_time);
}
end_f_loop(f,ft)
}

© 2012 ANSYS, Inc. March 14, 2012 5
Release 14.0
Time history of the average velocity at the pipe exit shows sinusoidal
oscillation with a mean of 20 m/s and amplitude of 5 m/s
Example 1: Results of Transient Inlet Velocity
Average
Velocity
Magnitude
Flow Time

© 2012 ANSYS, Inc. March 14, 2012 6
Release 14.0
The following UDF sets the temperature on the faces of a wall according to  the 
equation:
T
x
= 300  + 100 sin(π*x/L)
Example 2: Sinusoidal Wall Temperature
#include "udf.h"
#define LENGTH 0.005
#define T_MIN 300.0
#define T_AMP 100.0
DEFINE_PROFILE(wall_temp, ft, var)
{
real temperature;
real pos[ND_ND]; /* How 2D and 3D vectors are defined */
real omega;
face_t f;
omega = M_PI/LENGTH; /* M_PI is standard C value for Pi */
begin_f_loop(f,ft) /* Fluent has special loop macros too */
{
F_CENTROID(pos,f,ft); /* Face centroid set in pos */
temperature = T_MIN + T_AMP * sin(omega * pos[0]); /* x = pos[0] */
F_PROFILE(f,ft,var) = temperature;
}
end_f_loop(f,ft)
}

© 2012 ANSYS, Inc. March 14, 2012 7
Release 14.0
Example 2: Sinusoidal Wall Temperature 
Wall temperature reaches its peak at mid length of the wall
Static Temperature (K)
Cold Inflow
Heated Wall
Adiabatic Wall

© 2012 ANSYS, Inc. March 14, 2012 8
Release 14.0
DEFINE SOURCE
To add source terms to the flow equations use : 
DEFINE_SOURCE(udf_name, cell, thread, dS, eqn)
Source terms can be added to equations for: •
continuity

momentum

k, 

Energy

Multiphase and others 
Energy source term UDFs may also be defined for solid zones
The source term macro is different from the previous macro because it is called for 
each cell separately.
So, there is no need to perform a cell loop!
The units of all source terms are expressed in terms of the volumetricgeneration 
rate.  (total cell source / m3)

© 2012 ANSYS, Inc. March 14, 2012 9
Release 14.0
Source Terms
In Fluent, source terms are linearized as follows:
S(φ) = A + B.Δφ
A is added explicitly and B.Δφ is added implicitly to the solution matrix
A DEFINE_SOURCE  UDF returns the value for the total source, S, but we can also 
specify B if required using  the dS and eqn variables passed
 to the UDF:
dS[eqn] = dS_dPhi;
Setting this term is usually not required and can be set to 0.0, but, if the source terms 
are large and causing convergence problems, then if dS_dPhiis negative, 
setting this term will help stabilise the solution.

© 2012 ANSYS, Inc. March 14, 2012 10
Release 14.0
Example:  Position Dependent Porous Media
The following UDF adds a negative momentum 
source into each cell which is dependent 
on the local flow speedand y position.
x
x
x x
v Chy
dv
dS
B
vv Chy S


2
2
)/(
2/ )/(
 

#include "udf.h"
#define C2 100.0
#define HEIGHT 0.01
DEFINE_SOURCE(mom_source_x, c, ct, dS, eqn)
{
real NV_VEC(pos); /* Another way to define 2D and 3D vectors */
real dS_dU;
C_CENTROID(pos,c,ct); /* Cell centroid set in pos */
/* C_R(c,ct) gives density of material in the cell */
dS_dU = - pos[1] * C2 * C_R(c,ct)* fabs(C_U(c,ct)) / HEIGHT;
dS[eqn] = dS_dU; /* Could be set to 0.0 if unknown or not required */
return dS_dU * C_U(c,ct) / 2.0;
}

© 2012 ANSYS, Inc. March 14, 2012 11
Release 14.0
Source Terms
In Define → Boundary Condi?ons → Fluid
Activate source terms
Attach the Source UDF to 
the matching equation

© 2012 ANSYS, Inc. March 14, 2012 12
Release 14.0
Example: Position Dependent Porous Media
•X‐momentum loss is linear in the y‐position, starting from zero at the symmetry plane
•The fluid flows faster near the midline of the channel where the resistance is least
Velocity Vectors (m/s)
Porous Plug
Inlet
Outlet

© 2012 ANSYS, Inc. March 14, 2012 13
Release 14.0
Initial Conditions
The initial conditions of the flow can be set using a UDF of the form:
DEFINE_INIT(init_sphere_temp, domain)
The UDF is executed once at the beginning of the solution process
It is attached in the UDFs Hooks panel
Define → User Defined → Func?on Hooks

© 2012 ANSYS, Inc. March 14, 2012 14
Release 14.0
This UDF initialises the temperature 
within a sphere of radius 
0.25m
The macro NV_D can be used to set 
a vector
The macro NV_VVcan be used for 
vector arithmetic
The macro NV_MAGcomputes the 
length of a vector
Initialization UDF
(0.0, 0.5, 0.5)
#include "udf.h"
#define RADIUS 0.25
#define T_HIGH 400.0
#define T_LOW 300.0
DEFINE_INIT(init_sphere_temp, domain)
{
cell_t c; /* Cell index has its own type too*/
Thread *ct; /* Threads are pointers to a structure */
real pos[ND_ND];
real centre[ND_ND];
NV_D(centre,=,0.0,0.5,0.5); /* Set a vector */
/* Loop through all the cell threads in the domain */
thread_loop_c(ct,domain)
{/* Loop through the cells in each cell thread */
begin_c_loop(c,ct)
{
C_CENTROID(pos,c,ct);
NV_VV(pos,=,pos,-,centre); /* Vector arithmetic */
if(NV_MAG(pos)< RADIUS)
C_T(c,ct) = T_HIGH;
else
C_T(c,ct) = T_LOW;
}
end_c_loop(c,ct)
}
}

© 2012 ANSYS, Inc. March 14, 2012 15
Release 14.0
Adjust Function
This is similar to DEFINE_INIT but it is executed every iteration.
Is used for reporting or setting up models
before each iteration.
It is attached in the UDF Hooks panel
Define → User Defined → Func?on Hooks

© 2012 ANSYS, Inc. March 14, 2012 16
Release 14.0
Adjust Function
The Following example integrates turbulent dissipation over entire domain
#include "udf.h"
DEFINE_ADJUST(total_dissipation, domain)
{
cell_t c;
Thread *ct;
real total_diss;
total_diss = 0.0; /* Initialise total_dissbefore the loop */
thread_loop_c(ct,domain)
{
begin_c_loop(c,ct)
{
total_diss+=C_D(c,ct) * C_VOLUME(c,ct); /* Use += to sum up values */
}
end_c_loop(c,ct)
}
Message("Volume integral of turbulent dissipation = %f ", total_diss);
}

© 2012 ANSYS, Inc. March 14, 2012 17
Release 14.0
Execute At End Function
This is similar to DEFINE_INIT but is executed at the end of each iteration in a 
steady state run or at the end of each time step in a transient run
Can be used for results reporting and post‐processing.
It is attached in the UDF Hooks panel
Define → User Defi
ned → Func?on Hooks

© 2012 ANSYS, Inc. March 14, 2012 18
Release 14.0
DEFINE_EXECUTE_AT_END UDFs have a slightly different format:
Execute_at_EndFunction 
#include "udf.h"
DEFINE_EXECUTE_AT_END(final_total_dissipation)
{
/* The domain is NOT passed as a parameter to EXECUTE_AT_END UDF. */
/* So a local domain variable must be defined and set internally. */
Domain *domain;
domain = Get_Domain(ROOT_DOMAIN_ID); /* ROOT_DOMAIN_ID = 1 */
/* UDFs defined earlier can be called as normal C functions. */
/* This prevents no duplication of coding. Good practice! */
/* Here we call the Adjust function defined before. */
/* Note that the UDF name is the function name and */
/* the other parameters are the function parameters. */
total_dissipation(domain);
}

© 2012 ANSYS, Inc. March 14, 2012 19
Release 14.0
User Defined I/O 
DEFINE_RW_FILE can be used to read and write 
customized information to case/data files •
Save and restore custom variables common data types 
(integer, real, Boolean, structure elements)

Useful to save model specific information which would be 
lost if the UDF or case file were reloaded.
For example, a user model’s total run time or the number 
times a process has been run.

They are attached in the UDF Hooks panel

© 2012 ANSYS, Inc. March 14, 2012 20
Release 14.0
User Defined I/O (2)
#include "udf.h"
/* A global variable can be defined that is visible to all the */
/*functions in the file. The statickeyword should be used to */
/*hide it from other files for safety. Good Practice! */
static int run_count = 0; /*Always initialise global variables. */
DEFINE_EXECUTE_AT_END(increment_run_count)
{
run_count++; /* Increment the global counter here */
}
DEFINE_RW_FILE(write_count, file_pointer)
{
Message("Writing run counter to data file.");
/* fprintf is a standard C function for writing to a file */
fprintf(file_pointer, "%d", run_count); /* Match the formats! */
}
DEFINE_RW_FILE(read_count, file_pointer)
{
Message("Reading run counter from data file.");
/* fscanf is a standard C function for reading from a file */
fscanf(file_pointer, "%d",&run_count); /*Note use of & operator here */
}

© 2012 ANSYS, Inc. March 14, 2012 21
Release 14.0
Material Properties
To define the properties of the materials : DEFINE_PROPERTY
Can be used for most properties such as: •
Viscosity

Density (small variations only)

Thermal Conductivity

Surface Tension
The property UDF is called on a cell‐by‐cell basis so, like source term UDFs 
does not require a loop.

© 2012 ANSYS, Inc. March 14, 2012 22
Release 14.0
Material Property
Property UDF linked in at Define → Materials

© 2012 ANSYS, Inc. March 14, 2012 23
Release 14.0
Material Properties
The following UDF simulates solidification by specifying temperature 
dependent viscosity
The viscosity is low when
the flow is above T_HOT
The viscosity is high when
the flow is below T_COLD
The viscosity varies linearly
between T_HOTand T_COLD
#include "udf.h"
#define T_HOT 288.0
#define T_COLD 286.0
#define MU_HOT 5.5e-5 /* Low viscosity when hot */
#define MU_COLD 1.0 /* High viscosity when cold */
DEFINE_PROPERTY(freezing_viscosity, c, ct)
{
real temp, mu_laminar;
temp = C_T(c,ct);
if(temp> T_HOT)
mu_laminar = MU_HOT;
else if (temp> T_COLD)
mu_laminar = MU_COLD+ (temp -T_COLD)*
(MU_HOT - MU_COLD)/(T_HOT - T_COLD);
else/* temp<= T_COLD */
mu_laminar = MU_COLD;
return mu_laminar;
}

© 2012 ANSYS, Inc. March 14, 2012 24
Release 14.0
Example: Temperature Dependent Viscosity
Warm fluid enters the channel flowing from left to right.
Viscosity increases as the fluid is cooled by contact with the cold 
upper wall.
Contours of molecular viscosity (kg/ms)

© 2012 ANSYS, Inc. March 14, 2012 25
Release 14.0
Time Step: DEFINE_DELTAT
•In unsteady flows, Fluent allows the 
timestepto be changed based on 
convergence criteria
•Alternatively, the timestepcan be set 
according to any algorithm using a 
DEFINE_DELTAT UDF.

© 2012 ANSYS, Inc. March 14, 2012 26
Release 14.0
Time Step: DEFINE_DELTAT
•If a case is known to require a smaller timestepwhen starting, then the 
timestepcan be ramped up slowly. This is useful in cases where the run 
cannot be monitored, such as batch jobs.
#include "udf.h"
#define START_UP_TIME 0.5
#define START_UP_TIMESTEP 0.1
#define MAIN_TIMESTEP 0.2
DEFINE_DELTAT(start_up_time_steps, domain)
{
real flow_time;
real time_step;
flow_time = CURRENT_TIME;
if (flow_time < START_UP_TIME)
time_step = START_UP_TIMESTEP;
else
time_step = MAIN_TIMESTEP;
return time_step;
}

© 2012 ANSYS, Inc. March 14, 2012 27
Release 14.0
The Most Commonly Used UDFs in Fluent
Boundary Conditions
Initial Conditions
Adjust Function
Source Terms
Material Properties
Execute on Demand
Execute at Exit
Execute at End
Execute from GUI
Execute on Loading
Time step Function
•DEFINE_PROFILE
•DEFINE_INIT
•DEFINE_ADJUST
•DEFINE_SOURCE
•DEFINE_PROPERTY
•DEFINE_ON_DEMAND
•DEFINE_EXECUTE_AT_EXIT
•DEFINE_EXECUTE_AT_END
•DEFINE_EXECUTE_FROM_GUI
•DEFINE_EXECUTE_ON_LOADING
•DEFINE_DELTAT

© 2012 ANSYS, Inc. March 14, 2012 28
Release 14.0
Additional Macros
There are many additional, model specific macros •
You can learn more about these from the UDF manual
DEFINE_CHEM_STEP(name, ifail, n, dt, p, temp, yk)
DEFINE_NET_REACTION_RATE(name, p, temp, yi, rr, jac)
DEFINE_NOX_RATE (name, c, t, nox)
DEFINE_PRANDTL_D (name, c, t)
DEFINE_PR_RATE (name, c, t, r, mw, ci, p, sf,
dif_index, cat_index, rr)
DEFINE_SR_RATE (name, f, t, r, my, yi, rr)
DEFINE_VR_RATE (name, c, t, r, mw, yi, rr, rr_t)
DEFINE_TURB_PREMIX_SOURCE (name, c, t, turb_flame_speed, source) Multiphase specific macros will be discussed later

© 2011 ANSYS, Inc. March 14, 2012 1
Release 14.0
14. 0 Release
Advanced Fluent
User‐Defined FunctionsChapter 4
User Defined Memories and Scalars

© 2011 ANSYS, Inc. March 14, 2012 2
Release 14.0
User Defined Memory
Sometimes it is useful to define extra field variables to store and retrieve
values defined by the user.
User Defined Memories (UDMs) are defined in:
Define → User Defined → User Defined Memory •
Up to 500 UDMs can be used to store and retrieve user values.

They can be plotted in contours and are saved in the data file.

These values are not changed by Fluent, only in a UDF with:
•C_UDMI(c,ct,i)= my_cell_value;
•F_UDMI(f,ft,i)= my_face_value; (Only on boundary faces)

© 2011 ANSYS, Inc. March 14, 2012 3
Release 14.0
User Defined Scalars
In addition to the Continuity, Momentum Equations and Energy
Equations, up to 50 user defined generic scalar transport
equations can be solve.
Each scalar follows the generic transport equation:

To include scalars in the calculations use:
Define → User Defined → User Defined Scalars

Define the unsteady, flux, diffusion, and
source terms in the generic transport equation with UDFs
Unsteady Flux Diffusion Sources

© 2011 ANSYS, Inc. March 14, 2012 4
Release 14.0
User Defined Scalars
Each scalar can be set to only be calculated in fluid zones, solid
zones, all zones or just selected zones.
Each scalar can have a different Flux Function setting.

© 2011 ANSYS, Inc. March 14, 2012 5
Release 14.0
User Defined Scalars
When a UDS is defined, the diffusivity of the scalar must
be defined in the material property panel for each
material:
Define → Material Property •
The default diffusivity for
all scalars is 1.0

This constant can be
changed to a different
value or modified using a
DEFINE_DIFFUSIVITY UDF

© 2011 ANSYS, Inc. March 14, 2012 6
Release 14.0
User Defined Scalars
Boundary conditions for the scalars can be defined using: Define → Boundary Conditions → ....
Options for specifying a
constant value or flux
or use of a UDF Profile
for either.

© 2011 ANSYS, Inc. March 14, 2012 7
Release 14.0
User Defined Scalars
The Source terms for the scalars are set using the standard
DEFINE_SOURCE macro introduced before.
The other terms in the transport equation can be customized
using: −
The Flux term can be modified using:
DEFINE_UDS_FLUX

The Unsteady term is set using:
DEFINE_UDS_UNSTEADY
Note that the values returned by these two DEFINE_UDS_
UDFs must be multiplied by the material density if density
appears in these terms in the transport equation.

© 2011 ANSYS, Inc. March 14, 2012 8
Release 14.0
DEFINE_UDS_FLUX   Example
The following UDF sets the UDS flux according to a velocity field
stored in 3 UDMs. Upwindingcould be used instead.
#include "udf.h"
/* Define 3 new macros to make the UDM values more readable*/
#define C_UDS_U(C,T)C_UDMI((C),(T),0)
#define C_UDS_V(C,T)C_UDMI((C),(T),1)
#define C_UDS_W(C,T)C_UDMI((C),(T),2)
DEFINE_UDS_FLUX(uds_flux, f, ft, uds_index)
{
Thread *t0, *t1;
cell_t c0, c1;
real NV_VEC(av_vel); /* Average velocity at face */
real NV_VEC(A);
real flux;
t0 = F_C0_THREAD(f,ft);
c0 = F_C0(f,ft);
NV_D(av_vel,=,C_UDS_U(c0,t0),C_UDS_V(c0,t0),C_UDS_W(c0,t0));
Continued on next page...

© 2011 ANSYS, Inc. March 14, 2012 9
Release 14.0
DEFINE_UDS_FLUX   Example
Note that the value of the fluxis not multiplied by a UDS value as
Fluent does this according to the sign of fluxand the Spatial
Discretization scheme selected in Solve→ Methods...
...Continued from previous page.
t1 = F_C1_THREAD(f,ft);
if(NNULLP(t1))
{
/* Use velocity on the other side of face to get an average */
c1 = F_C1(f,ft);
/* Add the velocity from the other side to av_vel*/
NV_D(av_vel,+=,C_UDS_U(c1,t1),C_UDS_V(c1,t1),C_UDS_W(c1,t1));
/* Set av_vel to the average */
NV_S(av_vel,/=,2.0); /* NV_S can be used to set or scale a vector */
}
F_AREA(A,f,ft);
flux = NV_DOT(av_vec, A); /* Dot velocity with face area to get flux */
/* If the transport equation requires, multiply flux by density here. */
return flux; /* Fluent does any specified upwinding with this flux value */
}

© 2011 ANSYS, Inc. March 14, 2012 10
Release 14.0
Example
The following UDF modifies User-Defined Scalar time derivatives
using DEFINE_UDS_UNSTEADY
The unsteady UDF actually sets a volumetric source term (= −V.dφ/dt) with
an implicitpart and an explicitpart:
#include "udf.h"
DEFINE_UDS_UNSTEADY(uds_unsteady, c, ct, i, s_imp, s_exp)
{
/* Note the values to be set are passed as pointers: real *s_imp, real *s_exp*/
real factor, phi_old;
factor = C_VOLUME(c,t)/CURRENT_TIMESTEP; /* Standard Macro for timestep*/
/* If the transport equation requires, multiply factor by density here. */
*s_imp= - factor; /* Implicit part */
phi_old = C_UDSI_M1(c,ct,i); /* Value of UDS at previous time */
*s_exp= factor * phi_old; /* Explicit part */
/* The second order time derivative can be set using C_UDSI_M2 & PREVIOUS_TIMESTEP */
}
− V.dφ/dt≈ (–V/∆t).φ
new
+ V.φ
old
/∆t

© 2011 ANSYS, Inc. March 14, 2012 11
Release 14.0
Post Processing with UDMs
This ADJUST UDF sets a UDM to the magnitude of the
spatial gradient vector of a UDS so that contours and
other post-processing can be done on the gradient.
#include "udf.h"
DEFINE_ADJUST(set_uds0_gradient_magnitude, domain)
{
Thread *ct;
cell_t c;
int index;
index = 0; /* Could do a loop over N_UDS, the number of UDSs */
/* or over N_UDM, the number of UDMs defined. */
thread_loop_c(ct,domain)
{
begin_c_loop(c,ct)
{
/* The gradient vector of many calculated values can be got*/
/* by adding _G to the standard variable name: C_T_G(c,ct) */
C_UDMI(c,ct,index) = NV_MAG(C_UDSI_G(c,ct,index));
}
end_c_loop(c,ct)
}
}

© 2011 ANSYS, Inc. March 14, 2012 1
Release 14.0
14. 0 Release
Advanced Fluent
User‐Defined FunctionsChapter 5
UDFs for the Discrete Phase Model 

© 2011 ANSYS, Inc. March 14, 2012 2
Release 14.0
DPM Macros (1)
The most important datatypefor DPM model is Tracked_Particle
Tracked_Particle *p;
DPM tracks particles by performaing“Lagrangian” tracking 
Particle data at current position •
P_DIAM(p) Particle diameter

P_VEL(p)[I] Particle Velocity

P_T(p) Particle Temperature

P_RHO(p) Particle density 

P_MASS(p) Particle mass

P_TIME(p) Current time for particle

P_DT(p) Particle time step

P_LF(p) Particle liquid fraction

P_VFF(p) Particle volatile fraction
Many more particle data macros are available

© 2011 ANSYS, Inc. March 14, 2012 3
Release 14.0
DPM Macros (2)
Values of particle properties at entry to current cell –
P_DIAM0(p)
Diameter

P_VEL0(p)[i]
Velocity

P_TO(p)
Temperature

P_RHO0(p)
Density

P_MASS0(p)
Mass

P_TIME0(p)
Time

P_LF0(p)
Liquid fraction
Values of particle properties at injection into domain –
P_INIT_DIAM(p)
Diameter

P_INIT_MASS(p)
Mass

P_INIT_RHO(p)
Density

P_INIT_TEMP(p)
Temperature

P_INIT_LF(p)
Liquid fraction

© 2011 ANSYS, Inc. March 14, 2012 4
Release 14.0
DPM Macros (3)

P_EVAP_SPECIES_INDEX(p) Evaporating species index in mixture

P_DEVOL_SPECIES_INDEX(p) Devolatilizingspecies index in mixture

P_OXID_SPECIES_INDEX(p) Oxidizing species index in mixture

P_PROD_SPECIES_INDEX(p) Combustion product species index in 
mixture

P_CURRENT_LAW(p) Current law index

P_NEXT_LAW(p) Next particle law index

© 2011 ANSYS, Inc. March 14, 2012 5
Release 14.0
DPM Macros (4)
MaterialPropertiesforparticles

P_MATERIAL(p)
Material pointer for particles

DPM_SWELLING_COEFFI(p)
Swell coefficient for devolatilization

DPM_EMISSIVITY(p)
Particle radiation emissivity

DPM_SCATT_FACTOR(p)
Particle radiation scattering factor

DPM_EVAPORATION_TEMPERATURE(p)
Evaporation temperature

DPM_BOILING_TEMPERATURE(p)
Boiling temperature

DPM_LATENT_HEAT(p)
Latent Heat

DPM_HEAT_OF_PYROLYSIS(p)
Heat of pyrolysis

DPM_HEAT_OF_REACTION(p)
Heat of reaction

DPM_VOLATILE_FRACTION(p)
Volatile fraction

DPM_CHAR_REACTION(p)
Char fraction 

DPM_SPECIFIC_HEAT(p, t)
Specific Heat at temperature t

© 2011 ANSYS, Inc. March 14, 2012 6
Release 14.0
DPM Functions (1)
•The following  interactions on particles can be customized by UDFs:

Body force‐custom body forces on the particles

Drag‐user defined drag coefficient between 
particles and fluid

Source Terms‐access particle source terms

Output‐user can modify what is written out to the 
sampling plane output

Erosion‐called when particle encounters 
“reflecting” surface

DPM Law‐custom laws for particles

Scalar Update‐allows users to update a scalar every 
time a particle position is updated

Switch‐change the criteria for switching between laws

© 2011 ANSYS, Inc. March 14, 2012 7
Release 14.0
DPM Functions: An Example
The function below implements a custom law to model swelling.
“p” is a pointer to data structure of type Tracked_Particle
#include "udf.h“
DEFINE_DPM_LAW(Evapor_Swelling_Law, p, ci)
{
real swelling_coeff = 1.1;
/* First, call standard evaporation routine
to calculate mass and heat transfer */
Vaporization_Law(p);
/* Compute new particle diameter and density */
P_DIAM(p) = P_INIT_DIAM(p)*(1.0 + (swelling_coeff - 1.0)*
(P_INIT_MASS(p) - P_MASS(p))/
(DPM_VOLATILE_FRACTION(p)*P_INIT_MASS(p)));
P_RHO(p) = P_MASS(p) /
(M_PI*P_DIAM(p)*P_DIAM(p)*P_DIAM(p)/6.0);
/* Limit the density */
P_RHO(p) = MAX(0.1, MIN(1.0e5, P_RHO(p)));
}

© 2011 ANSYS, Inc. March 14, 2012 1
Release 14.0
14. 0 Release
Advanced Fluent
User‐Defined FunctionsChapter 6
UDFs for Multiphase Flows

© 2011 ANSYS, Inc. March 14, 2012 2
Release 14.0
The Multi‐Domain Architecture
•In multiphase flows each phase has its set of material properties and may have 
its own set of variables

For VOF model: 

For Mixture model:

For Eulerianmodel: 
•Some variables and geometry are shared among phases.

In VOF it is U, T, k, ε.  In mixture model, T, k, ε, and in Eulerian kand ε.
•Therefore, an architecture that stores the phases in separate overlaid domains 
was devised.
•This multi‐domain construction can be thought of as multiple versions of Fluent 
running together, but which communicate between each other at the level of the 
cells.
i
k k
Y,
i
k k k k k k
Y kT U,,,, , 

i
k k k
Y U, ,

© 2011 ANSYS, Inc. March 14, 2012 3
Release 14.0
The Multi‐Domain Architecture
•All of the domains are in a hierarchy that has the super domain at the top.
•The super domain is where the mixture of the phases is stored and so is 
often called the mixture domain.
•Shared values such as global settings are stored in the super domain.
•Each phase 
has its own domain known as a sub domain or phase domain.
Phase Domain Interaction
Phase Subdomains
Superdomain
P1 Domain
P2 Domain
P0 Domain

© 2011 ANSYS, Inc. March 14, 2012 4
Release 14.0
The Multi‐Domain Architecture
•Each Domain, Superdomainor Phase Domain, has its own version of all 
the threads which each have their own cells or faces.
Superthreads
Cells or Faces
Superdomain
P1 Threads
P1 Cells or Faces
P1 Domain
P0 Threads
P0 Cells or Faces
P0 Domain
P2 Threads
P2 Cells or Faces
P2 Domain

© 2011 ANSYS, Inc. March 14, 2012 5
Release 14.0
•Each thread is also in a hierarchy that matches that of the domains.
•The superthreads are where the mixture of the phases is stored and so 
are often called the mixture threads.
•Shared values such as the grid geometry are stored in the super thread.
•Each phase has its own 
set of threads known as a sub threads or phase 
thread.
Phase Thread Interaction
Phase Sub threads
Superthreads
P1 Threads
P2 Threads
P0 Threads
The Multi‐Domain Architecture

© 2011 ANSYS, Inc. March 14, 2012 6
Release 14.0
/* Mixture or Phase thread can be used for loop*/
begin_c_loop(c,t_primary)
{
Message(“Total VOF = %f = 1.0”,
C_VOF(c,t_primary) +
C_VOF(c,t_secondary1) +
C_VOF(c,t_secondary2))
}
end_c_loop(c,t_primary)
The Multi‐Domain Architecture
•Because the threads are all duplicated for each phase, each cell is also 
duplicated.
•The advantage of this is that the same value for cell c corresponds to the 
same cell on different duplicated threads, so for a multiphase problem 
with 3 phases there will be three phase threads: t_primary,
 t_secondary1, 
and t_secondary2.

© 2011 ANSYS, Inc. March 14, 2012 7
Release 14.0
The Multi‐Domain Architecture
•Some data that is useful to the super threads and the phase threads is 
available to both types of the thread. 
•The data is not repeated, but instead each thread points to the same 
data. 

The most common example is the geometry thread.
•Many UDFs are passed a thread as a parameter.  This thread is either a 
phase thread or a superthread.  In many cases, we may want the 
superthreadof a phase thread or all the phase threads of a superthread.
•There is a new set of macros to get this information about 
the hierarchy.  
These are discussed next.

© 2011 ANSYS, Inc. March 14, 2012 8
Release 14.0
Architecture‐Related Macros
•If we are passed a thread, phase_t, that we know is a phase thread, we 
can obtain its super thread using:
•We can obtain the domain which owns a thread using
Thread *super_t; /* All threads are of the same type*/
super_t = THREAD_SUPER_THREAD(phase_t);
Domain *d;
d = THREAD_DOMAIN(t);

© 2011 ANSYS, Inc. March 14, 2012 9
Release 14.0
Architecture‐Related Macros
•If, as in the case of the DEFINE_ADJUST UDF, we are passed the super domain, 
then we need some methods for obtaining the phase domains.
•We might want to obtain the primary phase domain from the super domain:
where p_index is 0 for primary phase; 1 for the first secondary phase,
 2 for the 
second etc.
•To get a sub thread for a secondary phase we can use a similar macro and specify 
the phase index, p_index. 
Domain *d_p0;
d_p0 = DOMAIN_SUB_DOMAIN(superdomain, p_index);
Thread *t_phase;
t_phase = THREAD_SUB_THREAD(superthread, p_index);

© 2011 ANSYS, Inc. March 14, 2012 10
Release 14.0
Architecture‐Related Macros
•The domain ID is another way that can be used to specify which phase 
you want to use or check which phase you are working with.
•We can get a Domain with a specified ID using the function Domain
*Get_Domain(int id)
•If you already have a domain, the macro DOMAIN_ID(d)returns the 
integer ID of a domain.
Domain *d;
int d_id;
d_id = DOMAIN_ID(d);

© 2011 ANSYS, Inc. March 14, 2012 11
Release 14.0
•The number that is returned by  DOMAIN_ID(d) and the number that  
should put into Get_Domain(id) are directly related to the phases that 
have been set up.
•To see the correspondence between the phases and Domain IDs, look at 
the Phases panel.
The corresponding
Domain ID is shown here
(Note how they may
not be consecutive )
P_index
0
1
2Architecture‐Related Macros

© 2011 ANSYS, Inc. March 14, 2012 12
Release 14.0
Architecture‐Related Macros
•We now have a way 
of checking if a 
domain or the 
domain to which a 
thread t belongs is 
the water phase 
domain
#include "udf.h"
#define RADIUS 1.0
#define WATER_ID 4/* Get ID from Phases panel */
/* INIT UDFs always get sent the mixture domain */
DEFINE_INIT(init_sphere, mixture_domain)
{
cell_t c;
Thread *phase_ct;
Domain *phase_domain;
real pos[ND_ND], centre[ND_ND];
phase_domain = Get_Domain(WATER_ID);
NV_D(centre,=,0.0,0.5,0.5); /* Set the sphere's centre */
thread_loop_c(phase_ct, phase_domain)
{
Continued on next page......

© 2011 ANSYS, Inc. March 14, 2012 13
Release 14.0
Architecture‐Related Macros
•Some information, 
such as cell 
geometry, is 
available on sub‐
threads too.
Continued from previous page......
begin_c_loop(c,phase_ct)
{
/* Geometric information is still available
on the sub-thread cells */
C_CENTROID(pos,c,phase_ct);
NV_VV(pos,=,pos,-,centre);
if(NV_MAG(pos) < RADIUS)
C_VOF(c,phase_ct) = 1.0;
else
C_VOF(c,phase_ct) = 0.0;
}
end_c_loop(c,phase_ct)
} /* End of Thread Loop */
}/* End of DEFINE_INIT UDF */

© 2011 ANSYS, Inc. March 14, 2012 14
Release 14.0
DEFINE_SOURCE(x_mom_src, c, thread, dS, eqn)
{
real source
real constant = 1.0;
source = -constant * C_U(c,thread) * C_VOF(c,thread);
dS[eqn] = constant * C_VOF(c,thread);
return source;
}
Obtaining Data for a Specific Phase
•Several examples on how to access phase‐specific variables will be 
discussed.
•Consider a simple example of a source term for the momentum equation. 
Looking at the basic form there is no obvious way the correct phase 
thread is obtained:

© 2011 ANSYS, Inc. March 14, 2012 15
Release 14.0
DEFINE_SOURCE(x_water_mom_src, c, phase_ct, dS, eqn)
{
real source;
real constant = 1.0;
source = -constant * C_U(c, phase_ct) * C_VOF(c,phase_ct);
dS[eqn] = constant * C_VOF(c,phase_ct);
return source;
}
Obtaining Data for a Specific Phase
•This UDF is hooked to the momentum equation of the phase of interest in 
the Eulerian model.  This sets the argument threadto the phase thread 
and C_U(cell,thread)is equal to the velocity component of this 
phase and C_VOF(cell,thread)is the volume fraction of this phase.
•To make this clearer, we rename
 the UDF and parameter thread, to
phase_ct

© 2011 ANSYS, Inc. March 14, 2012 16
Release 14.0
Obtaining Data for a Specific Phase
•If the UDF is hooked to the mixturemomentum equation in either the 
VOF or mixture model, then C_U(cell,thread)is equal to the x‐
velocity of the mixturephase.
•Note: C_VOF(cell,thread)does not exist for mixtures.
•Next, imagine that the source UDF is hooked to a phase momentum 
equation but we also 
need to access variables related to other phases 
(mixture and others). 
For instance:
The code will look like the following:


primary secondary x
U UC S


© 2011 ANSYS, Inc. March 14, 2012 17
Release 14.0
Obtaining Data for a Specific Phase
#define CONST 10.0
DEFINE_SOURCE(x_water_mom_src, cell, phase_t, dS, eqn)
{
Thread *mt; /* Mixture or Super thread*/
Thread **all_phase_threads; /* An array of all the phase threads*/
mt= THREAD_SUPER_THREAD(phase_t);
all_phase_threads= THREAD_SUB_THREADS(mt);
/* all_phase_threads[0] is primary thread, */
/* all_phase_threads[1] first secondary phase thread */
return CONST * (C_U(cell, all_phase_threads[0])-
C_U(cell, all_phase_threads[1]));
}

© 2011 ANSYS, Inc. March 14, 2012 18
Release 14.0
Model /
equation
Mass
(Volume
fraction)
Momentum
(Velocity
components)
Energy
(Temperature,
enthalpy)
Scalar
(Turbulence
variables,
scalars)
Eulerian Phase Phase Phase Phase/Mixture
Mixture Phase Mixture Mixture Mixture
VOF Phase Mixture Mixture MixtureObtaining Data for a Specific Phase
•In order to access phase related variables correctly in a UDF, one needs to clearly 
know the following:

Which multiphase model one is going to use the UDF with.

Whether the variable or property of interest is associated with the phase or 
associated with the mixture.
•Below is a table which summarizes phase association for variables in Fluent 
multiphase models (Pressure is always related to the Mixture)

© 2011 ANSYS, Inc. March 14, 2012 19
Release 14.0
Phase Interaction
•We have briefly mentioned how the interaction between phases involves 
another set of domains called interaction domains.
•Even an advanced user is unlikely to need to know more about the lower level 
operations within Fluent than has been discussed already.
•However, users will sometimes want to modify the interaction behavior 
between 
phases and this is done through the
Phase Interaction panel:

© 2011 ANSYS, Inc. March 14, 2012 20
Release 14.0
Phase Interaction
•The Phase Interaction panel allows the user to provide user‐defined interaction 
model instead of one of the standard models governing Interphase Drag, Lift, 
Collisions, Slip, Heat Transfer, Mass Transfer, Reactions and Surface Tension

© 2011 ANSYS, Inc. March 14, 2012 21
Release 14.0
Phase Interaction
•There are 5 multiphase macros for customizing interfacial 
heat/mass/momentum transfer
•Four macros return a scalar exchange rate

DEFINE_CAVITATION_RATE

DEFINE_EXCHANGE_PROPERTY

DEFINE_HET_RXN_RATE

DEFINE_MASS_TRANSFER
•And one prescribes the interphase slip velocity vector

DEFINE_VECTOR_EXCHANGE_PROPERTY
•Each prescribes a specific interaction between pairs of phases

NOTE that if there are Nphases, there will be N(N –1) / 2 pairs of phases

© 2011 ANSYS, Inc. March 14, 2012 22
Release 14.0
Example –Define Cavitation Rate
•The rate of cavitation (kg/(m
3
∙s)) can be prescribed using: 
DEFINE_CAVITATION_RATE
#define C_EVAP 1.0
#define C_COND 0.1
DEFINE_CAVITATION_RATE(cav_rate, c, ct, p, rhoV, rhoL, vofV, p_v, cigma,
f_gas, m_dot)
{
real p_vapor, dp, dp0, source;
p_vapor = my_vapor_pres(*p_v, C_R(c,ct), C_K(c,ct)); /* Defined elsewhere */
dp = p_vapor - (C_P(c,ct) + op_pres); /* op_pres is a global value for
current operating pressure */
dp0 = fabs(dp);
dp0 = MAX(0.1,dp0);
source = dp0*sqrt(rhoL[c] * 2.0/3.0);/* Some data passed in arrays */
if(dp > 0.0) *m_dot = C_EVAP*rhoV[c]*source;
else *m_dot = -C_COND*rhoL[c]*source;
}

© 2011 ANSYS, Inc. March 14, 2012 23
Release 14.0
Example –Define Cavitation Rate
•It’s good practice to move auxilliarycalculations  into new functions.
•In this case, the vapor pressure is quite a complex function with its own 
constants which is probably going to be used in other places so should be 
made into a new function:
#define VC1 0.195
#define VC2 5.0
real my_vapor_pres(real fluent_p_v, real dens, real turb_k)
{
real p1, p2;
p1 = VC1* dens * turb_k;
p2 = VC2* fluent_p_v;
return fluent_p_v+ MIN(p1,p2); /* MIN is a standard macro in Fluent */
}

© 2011 ANSYS, Inc. March 14, 2012 24
Release 14.0
Phase Interaction
•Be aware of the values Fluent expects to be returned by 
DEFINE_EXCHANGE_PROPERTY UDFs for every phase interaction:

For the drag law:

For the lift force :

For Heat transfer :
) (
dragq p pq
pq
u u K F



 


f s f f s L
u u u C K







 
lift


q p pq pq
T T h Q


returned be must
pq
K
returned be must
L
C
returned be must
pq
h

© 2011 ANSYS, Inc. March 14, 2012 25
Release 14.0
Phase Interaction –Mass Transfer Rate
•You can model mass transfer between phases , such as boiling or simple reactions, using 
DEFINE_MASS_TRANSFER
•The following UDF specifies a simple boiling rate :
#define BOIL_CONST 0.1
DEFINE_MASS_TRANSFER(simple_boiling, c, mix_ct, from_phase_index, from_species_index,
to_phase_index, to_species_index)
{
real mass_transfer;
real T_SAT, T_gas, T_liq;
Thread *gas , *liq;
gas= THREAD_SUB_THREAD(mix_ct, from_phase_index);
liq= THREAD_SUB_THREAD(mix_ct, to_phase_index);
T_gas= C_T(c,gas);
T_liq= C_T(c,liq);
T_SAT = 373.15;
mass_transfer = 0.0;
if(T_gas < T_SAT) /* Gas Condenses, mass transfer positive from gas to liquid */
mass_transfer+=BOIL_CONST*C_VOF(c,gas)*C_R(c,gas)*(T_SAT - T_gas)/T_SAT;
if(T_liq > T_SAT) /* Liquid Evaporates, mass transfer in negative*/
mass_transfer-=BOIL_CONST*C_VOF(c,liq)*C_R(c,liq)*(T_liq - T_SAT)/T_SAT;
return(mass_transfer);
}

© 2011 ANSYS, Inc. March 14, 2012 26
Release 14.0
Phase Interaction –Define Heat Transfer Rate
DEFINE_EXCHANGE_PROPERTY(heat_exchange, c, mix_ct, i, j)
{
Thread *ti, *tj;
ti = THREAD_SUB_THREAD(mix_ct, i); /* Continuous phase thread */
tj = THREAD_SUB_THREAD(mix_ct, j); /* Dispersed phase thread */
/* Use another function for the interphase Heat Transfer Coefficient */
return heat_ranz_marshall(c, ti, tj);
}
•The heat transfer rates between phases as well as drag and lift coefficient 
functions can be set : DEFINE_EXCHANGE_PROPERTY
•Eulerianmodel –net heat transfer rate, drag and lift coefficients
•Mixture model –drag coefficient only.

© 2011 ANSYS, Inc. March 14, 2012 27
Release 14.0
Phase Interaction –Define Heat Transfer Rate
•The interphase HTC is defined as a separate function :
/* Macros can be used to define simple functions. */
/* Each parameter is protected in extra brackets. */
#define PR_NUMBER(CP,MU,K)((CP)*(MU)/(K))
#define IP_HEAT_COEFF(VOF,K,NU,D)(6.0*(VOF)*(K)*(NU)/((D)*(D)))
static real heat_ranz_marshall(cell_t c, Thread *ti, Thread *tj)
{
real d, k;
real vel[ND_ND];
real Re, Pr, Nu;
d = C_PHASE_DIAMETER(c,tj); /* Particulate phase */
k = C_K_L(c,ti); /* Continuous phase */
/* Relative velocity between phases */
NV_DD(vel,=,C_U(c,ti),C_V(c,ti),C_W(c,ti),-,C_U(c,tj),C_V(c,tj),C_W(c,tj));
Re = RE_NUMBER(C_R(c,ti), NV_MAG(vel),d,C_MU_L(c,ti)); /* Standard Macro */
Pr = PR_NUMBER(C_CP(c,ti),C_MU_L(c,ti),k);
Nu = 2.0 + 0.6 * sqrt(Re) * cbrt(Pr); /* cbrt is the same as pow(Pr,1./3.) */
return IP_HEAT_COEFF(C_VOF(c,tj),k,Nu,d);
}

© 2011 ANSYS, Inc. March 14, 2012 1
Release 14.0
14. 0 Release
Advanced Fluent
User‐Defined FunctionsChapter 7
UDFs for Calculations in Parallel 

© 2011 ANSYS, Inc. March 14, 2012 2
Release 14.0
Parallel Fluent Architecture
•Host process is labeled 
999999
•Cortex is the front end 
process which connects 
only to the host process 
•Compute Node processes 
are labeled consecutively 
starting at 0
•Each compute node is 
virtually connected to 
every other compute 
node by the Message 
Passing (MP) interface

© 2011 ANSYS, Inc. March 14, 2012 3
Release 14.0
Command Transfer in Parallel Fluent
“(%iterate 5)”
Cortex
Host
Compute-Node-0
Compute-Node-1 Compute-Node-2 Compute-Node-3
“(%iterate 5)”

Host communicates with
Node 0

Node 0 communicates with
all other nodes

All Nodes (>=1)
communicates with host
through Node 0
scheme

© 2011 ANSYS, Inc. March 14, 2012 4
Release 14.0
Parallelizing a Serial UDF code
•In general, UDF codes need to be parallelized in order to make sure the codes are 
executed properly as either a host or node process
•To parallelize a UDF we need to modify a serial code such that it will run 
successfully on both serial and parallel modes
•We use 
compiler directives (preprocessor commands) inserted into the original C 
code to distinguish which part of the program is executed by the host or by the 
nodes when the UDF is compiled
•The syntax of the #ifcompiler directive is quite simple:
#ifis a compiler directive  (similar to #define)
#endifis used to
 close an #if

© 2011 ANSYS, Inc. March 14, 2012 5
Release 14.0
Basic Compiler Directives
#if RP_HOST
/* Coding here only performed on HOST process */
#endif
#if RP_NODE
/* Coding here only performed on NODE processes */
#endif
#if PARALLEL
/* Coding here only performed on HOST & NODE processes */
#endifDifferent parts of the UDF code have to be performed on either the host or
node processes. These parts can be selected using:

© 2011 ANSYS, Inc. March 14, 2012 6
Release 14.0
Negated Compiler Directives
#if !PARALLEL
/* Coding here only performed on SERIAL process */
#endif
#if !RP_HOST
/* Coding here only performed on NODE & SERIAL processes */
#endif
#if !RP_NODE
/* Coding here only performed on HOST & SERIAL processes */
#endif
Since many of the operations will also be required in the serial version, the
negated versions are more commonly used:

© 2011 ANSYS, Inc. March 14, 2012 7
Release 14.0
Partitioning (1)
•Domain Decomposition : Splits the cells in the domain across Compute Nodes
•Because Fluent’s algorithms expect a cell to be on both sides of an interior face, 
copies of the neighboring partition’s cells are kept on each Node
•Compute Node 0 has copies of the cells on the other side 
of all partition faces 
and Compute Node 1 has corresponding cell copies from Node 0
Domain Decomposition
Compute Node 0
Compute Node 1
Distribution across Compute
Nodes

© 2011 ANSYS, Inc. March 14, 2012 8
Release 14.0
Partitioning (2)
•The main cells of each partition are designated as “Interior” cells and the 
additional copied cells from other Compute Nodes are designated as “Exterior” 
cells.  The Partition Boundary Faces are a special type of Interior face
Partition Boundary Face Interior Faces
Exterior Cell
Compute Node 0
Surface Boundary
Zone Face
Interior Cells

© 2011 ANSYS, Inc. March 14, 2012 9
Release 14.0
Partitioned Thread Loop (1)
•The loop macro for cells in serial is:
begin_c_loop(c,t)
{ }
end_c_loop(c,t)
•In parallel, this serial form loops through both interior and exterior cells
•Use  begin_c_loop_int(c,t)  in UDFs that are to be parallelized:
begin_c_loop_int(c,t)
{
}
end_c_loop_int(c,t)
•This loop excludes the exterior cells so they don’t get visited twice.
•Another loop construct loops through the 
exterior cells only : 
begin_c_loop_ext(c,t)
{
}
end_c_loop_ext(c,t)
but it is rarely used in UDFs and does nothing if compiled in the serial version

© 2011 ANSYS, Inc. March 14, 2012 10
Release 14.0
Partitioned Thread Loop (2)
•Similar loops exist for faces:
begin_f_loop_all(f,t)
{…}
end_f_loop_all(f,t)
begin_f_loop_int(f,t)
{…}
end_f_loop_int(f,t)
•But these have a slightly different use so instead, use the standard loop and check to see if 
the face is allocated to this node by using PRINCIPAL_FACE_P(f,t):
begin_f_loop (f,t)
{
if(PRINCIPAL_FACE_P(f,t))
{…Only gets done once per face…}
}
end_f_loop(f,t)

© 2011 ANSYS, Inc. March 14, 2012 11
Release 14.0
Inter-Process Communication (1)
•Each compute node maintain local cache of individual variables
•Synchronization or make global reduction of such data involves
communication in a particular order
•Consider the simple operation of passing a user defined cortex
parameter that is set using scheme but is used in a UDF
Serial Version
#include “udf.h“
DEFINE_INIT(init_temp, domain)
{
real init_temp; /* Variable declaration */
Thread *ct;
cell_t c;
init_temp = RP_Get_Real(“my-init-temp“); /* Scheme communication */
thread_loop_c(ct,domain) /* Solution data handling */
begin_c_loop(c,ct)
{
C_T(c,ct) = init_temp;
}
end_c_loop(c,ct)
}

© 2011 ANSYS, Inc. March 14, 2012 12
Release 14.0
Inter-Process Communication (2)
Combined (Serial & Parallel ) Code
#include “udf.h“
DEFINE_INIT(init_temp, domain)
{
real init_temp; /* Variable declaration. Some variables used in all versions. */
#if !RP_HOST
Thread *ct; /* These variable only used on the nodes and in serial */
cell_t c;
#endif
#if !RP_NODE
init_temp = RP_Get_Real(“my-init-temp“); /* Scheme communication on host and serial */
#endif
#if PARALLEL
host_to_node_real_1(init_temp);/* Host sends data to nodes (Does nothing in serial) */
#endif
#if !RP_HOST
thread_loop_c(ct,domain) /* Solution data handling only on nodes and serial */
begin_c_loop(c,ct)
{
C_T(c,ct) = init_temp;
}
end_c_loop(c,ct)
#endif
}

© 2011 ANSYS, Inc. March 14, 2012 13
Release 14.0
Inter-Process Communication (3)

The macro host_to_node_real_1(init_temp)is defined as 
a Sendcommand in the Host versionand a Receivecommand in 
the Compute Nodes. It does nothing in the Serial version so the 
#if PARALLEL directive is not really needed in this case. 

The reverse node to host data transfer macro for 1 real number is 
node_to_host_real_1(report_temp)
Note however that this command only sends the value of 
report_tempfrom Node‐0 to the Host.
(It does nothing in the serial version)
So, some way of gathering data onto Node‐0 before it is sent is 
required.

© 2011 ANSYS, Inc. March 14, 2012 14
Release 14.0
Global Reduction
•Operations that collect data from all compute nodes and reduce the numbers into a single 
value or an array of values are called Global Reduction macros
•Depending the objectives, 

If you want the total value over all the Nodes, use a Summation Reduction

If you want the Max or Min over all the Nodes use a High or Low Reduction

If you want a logical test over all nodes, use an And or Or Reduction
•There are different macros depending on what data type you’re sending:

© 2011 ANSYS, Inc. March 14, 2012 15
Release 14.0
Example UDF (1)

Find totals and averages of 
a property over all the 
cells 

Purpose is to write an UDF 
that works for both 
Parallel and Serial solvers

© 2011 ANSYS, Inc. March 14, 2012 16
Release 14.0
Message0
•Message0() prints directly to the cortex window from Node‐0. 
It is ignored on all other compute nodes and the host node.
•Works for the serial process in the same way as Message() Message0("Average pressure over Thread-%d ",thread_id);
Message0("is %f Pa",pres_sum/vol_sum); •Cuts done on inter‐process communication for messages.
•Note the identical syntax of the function Message0with Messageand 
the C standard printfcommands

© 2011 ANSYS, Inc. March 14, 2012 17
Release 14.0
Summary
•A UDF that works for the Serial solver will usually not work in Parallel 
without some modification.
•The UDF has to be separated into sections that will be done on either the 
host or on the node (and on the serial version).
•This can be done in a single file 
with compiler directives so the same UDF 
will work in serial too.
•Some extra communication functions between the host and nodes may 
be needed.
•Results data may need to be “reduced” before being reported.
•There is a comprehensive dedicated chapter in the UDF Manual for 
additional information and examples for using
 UDFs in parallel Fluent.
Tags