Sei sulla pagina 1di 136

FLUENT 5.

5 UDF User's Guide


Fluent Inc.

September 2000

Licensee acknowledges that use of Fluent Inc.'s products can only provide an imprecise
estimation of possible future performance and that additional testing and analysis, independent of the Licensor's products, must be conducted before any product can be nally
developed or commercially introduced. As a result, Licensee agrees that it will not rely
upon the results of any usage of Fluent Inc.'s products in determining the nal design,
composition or structure of any product.

Copyright c 2000 by Fluent Inc.


All rights reserved. No part of this document may be reproduced or otherwise used in
any form without express written permission from Fluent Inc.
Airpak, FIDAP, FLUENT, GAMBIT, Icepak, MixSim, and POLYFLOW are registered
trademarks of Fluent Inc. ImageMagick is Copyright c 1996 E. I. du Pont de Nemours

and Company. All other products or name brands are trademarks of their respective
holders.
Fluent Inc.
Centerra Resource Park
10 Cavendish Court
Lebanon, NH 03766

About This Document


User-de ned functions (UDFs) provide the capability to customize FLUENT 5 code and
can signi cantly enhance the capability of FLUENT. This UDF User's Guide presents
more detailed information than was presented in the FLUENT 5 User's Guide on how
to write, compile, and use UDFs in FLUENT 5. Additional examples have also been
included. For your convenience, material from the FLUENT 5 User's Guide chapter on
user-de ned functions (Chapter 24) has been included in this document.
Information in this manual is divided into the following sections:
 Chapter 1: Overview
 Chapter 2: Writing User-De ned Functions
 Chapter 3: Compiling and Linking User-De ned Functions
 Chapter 4: Using UDFs in Your FLUENT Model
 Chapter 5: Examples of UDFs
 Chapter 6: Sample Applications
This document does not provide an introduction to the C programming language,
and assumes that you have some programming experience with the C language. If
you are unfamiliar with C, please consult a C language reference for basic information (e.g., Kernighan and Ritchie's \The C Programming Language", Prentice
Hall, 1988).
This document does not imply responsibility on the part of Fluent Inc. for the accuracy or stability of solutions obtained using UDFs that are either user-generated
or provided by Fluent Inc. Support for current license holders will be limited to
guidance related to communication between a UDF and the FLUENT solver. Other
aspects of the UDF development process that include conceptual function design,
implementation (writing C code), compilation and debugging of C source code, execution of the UDF, and function design veri cation will remain the responsibility
of the UDF author.

About This Document

ii

Fluent Inc. September 14, 2000

Contents
1 Overview

2 Writing User-De ned Functions

1.1 Basic Steps for Writing UDFs . . . . . . . . . . . . . . . . . . . . . . . .


1.2 Interpreted vs. Compiled . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1
2.2
2.3
2.4

Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . .
UDF Format . . . . . . . . . . . . . . . . . . . . . . . . . .
Including the udf.h File . . . . . . . . . . . . . . . . . . . .
De ning Your Function . . . . . . . . . . . . . . . . . . . .
2.4.1 Introduction . . . . . . . . . . . . . . . . . . . . . .
2.4.2 #define Statements in the udf.h File . . . . . . . .
2.4.3 DEFINE Macros . . . . . . . . . . . . . . . . . . . . .
2.5 General-Use DEFINE Macros and the Functions They De ne
2.5.1 DEFINE ADJUST . . . . . . . . . . . . . . . . . . . . .
2.5.2 DEFINE DIFFUSIVITY . . . . . . . . . . . . . . . . .
2.5.3 DEFINE HEAT FLUX . . . . . . . . . . . . . . . . . . .
2.5.4 DEFINE INIT . . . . . . . . . . . . . . . . . . . . . .
2.5.5 DEFINE ON DEMAND . . . . . . . . . . . . . . . . . . .
2.5.6 DEFINE PROFILE . . . . . . . . . . . . . . . . . . . .
2.5.7 DEFINE PROPERTY . . . . . . . . . . . . . . . . . . .
2.5.8 DEFINE RW FILE . . . . . . . . . . . . . . . . . . . .
2.5.9 DEFINE SCAT PHASE FUNC . . . . . . . . . . . . . . .
2.5.10 DEFINE SOURCE . . . . . . . . . . . . . . . . . . . . .
2.5.11 DEFINE SR RATE . . . . . . . . . . . . . . . . . . . .
2.5.12 DEFINE UDS FLUX . . . . . . . . . . . . . . . . . . .
2.5.13 DEFINE UDS UNSTEADY . . . . . . . . . . . . . . . . .

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

2
3

5
5
6
6
6
7
8
10
10
10
11
11
12
12
12
13
13
13
14
14
14

CONTENTS

2.6

2.7
2.8
2.9

2.10

iv

2.5.14

...........................
DEFINE Macros for the Discrete Phase Model and the Functions They De ne
2.6.1 DEFINE DPM BODY FORCE . . . . . . . . . . . . . . . . . . . . . . .
2.6.2 DEFINE DPM DRAG . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.3 DEFINE DPM EROSION . . . . . . . . . . . . . . . . . . . . . . . .
2.6.4 DEFINE DPM INJECTION INIT . . . . . . . . . . . . . . . . . . . .
2.6.5 DEFINE DPM LAW . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.6 DEFINE DPM OUTPUT . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.7 DEFINE DPM PROPERTY . . . . . . . . . . . . . . . . . . . . . . . .
2.6.8 DEFINE DPM SCALAR UPDATE . . . . . . . . . . . . . . . . . . . . .
2.6.9 DEFINE DPM SOURCE . . . . . . . . . . . . . . . . . . . . . . . . .
2.6.10 DEFINE DPM SWITCH . . . . . . . . . . . . . . . . . . . . . . . . .
DEFINE Macros for Multiphase Models and the Functions They De ne .
2.7.1 DEFINE DRIFT DIAM . . . . . . . . . . . . . . . . . . . . . . . . .
2.7.2 DEFINE SLIP VELOCITY . . . . . . . . . . . . . . . . . . . . . . .
Determining the Pointer to a Thread . . . . . . . . . . . . . . . . . . . .
Function Body . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.2 Restrictions on Interpreted UDFs . . . . . . . . . . . . . . . . .
2.9.3 Function Tasks . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.4 Returning a Value . . . . . . . . . . . . . . . . . . . . . . . . . .
2.9.5 Modifying an Argument . . . . . . . . . . . . . . . . . . . . . . .
2.9.6 Returning a Value and Modifying an Argument . . . . . . . . . .
2.9.7 Modifying a FLUENT Variable . . . . . . . . . . . . . . . . . . .
2.9.8 Writing to or Reading from a Case or Data File . . . . . . . . . .
Solver Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.10.2 Miscellaneous Geometry . . . . . . . . . . . . . . . . . . . . . . .
2.10.3 Cell Coordinates and Areas . . . . . . . . . . . . . . . . . . . . .
2.10.4 Node Coordinates and Node (Grid) Velocities . . . . . . . . . . .
DEFINE VR RATE

15
16
16
16
17
17
17
18
18
19
19
20
21
21
21
22
23
23
23
24
25
26
27
28
29
31
31
32
32
33

Fluent Inc. September 14, 2000

CONTENTS

2.10.5 Face Variables . . . . . . . . . . . . . . . . . .


2.10.6 Cell Variables . . . . . . . . . . . . . . . . . .
2.10.7 Looping Macros . . . . . . . . . . . . . . . . .
2.10.8 Protection Against Accessing Unavailable Data
2.10.9 Function for Setting Face Values . . . . . . . .
2.11 DPM Macros . . . . . . . . . . . . . . . . . . . . . . .
2.11.1 Macros for Particle Variables . . . . . . . . . .
2.11.2 Macros for Particle Material Properties . . . .

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.

33
34
36
37
37
38
38
39

3 Compiling and Linking User-De ned Functions

41

4 Using UDFs in Your FLUENT Model

57

3.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
3.2 Interpreted UDFs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
3.2.1 Compiling an Interpreted UDF . . . . . . . . . . . . . . . . . . . 43
3.2.2 Directory Structure for Windows NT Parallel Networks . . . . . 45
3.2.3 Debugging Interpreted UDFs . . . . . . . . . . . . . . . . . . . . 46
3.2.4 Common Errors Made While Compiling Your Interpreted UDF . 46
3.3 Compiled UDFs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
3.3.1 Setting Up the Directory Structure . . . . . . . . . . . . . . . . . 48
3.3.2 Compiling and Building Your Shared Library . . . . . . . . . . . 52
3.3.3 Linking Your Shared Library to the FLUENT Executable . . . . . 55
3.3.4 Common Errors Made While Compiling or Linking Your Compiled
UDF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4.1
4.2
4.3
4.4
4.5
4.6
4.7

Boundary Conditions . . . . . . .
Source Terms . . . . . . . . . . .
Property De nitions . . . . . . .
Discrete Phase Model . . . . . .
Solution Initialization . . . . . .
Adjustment of Computed Values
Wall Heat Fluxes . . . . . . . . .

Fluent Inc. September 14, 2000

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

.
.
.
.
.
.
.

58
59
60
62
63
63
64
v

CONTENTS

4.8
4.9
4.10
4.11
4.12
4.13

Reaction Rates . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Slip Velocity for the Algebraic Slip Mixture Model . . . . . . . . .
Particle or Droplet Diameter for the Algebraic Slip Mixture Model
Reading from and Writing to Case and Data Files . . . . . . . . . .
Executing a UDF On Demand . . . . . . . . . . . . . . . . . . . .
Accessing Memory for Storage of Variables . . . . . . . . . . . . . .

5 Examples of UDFs

5.1 Boundary Conditions . . . . . . . . . . . . . . . . . . . . .


5.1.1 Parabolic Pressure Inlet Pro le for a Turbine Vane
5.1.2 Fully-Developed Turbulent Inlet Pro les . . . . . .
5.1.3 Sinusoidal Wall Temperature Pro le . . . . . . . .
5.2 Source Terms . . . . . . . . . . . . . . . . . . . . . . . . .
5.2.1 Spatially Dependent Porous Media . . . . . . . . .
5.2.2 Swirl Generator in a Fluid Zone . . . . . . . . . .
5.3 User-De ned Scalar Transport Equations . . . . . . . . . .
5.4 Discrete Phase Model . . . . . . . . . . . . . . . . . . . .
5.4.1 Melting Index Along a Particle Trajectory . . . . .
5.4.2 Magnetic Force on a Charged Particle . . . . . . .
5.4.3 Particle Drag Coecient . . . . . . . . . . . . . .
5.5 Solution Initialization . . . . . . . . . . . . . . . . . . . .
5.6 Wall Heat Flux . . . . . . . . . . . . . . . . . . . . . . . .
5.7 Postprocessing Using User-De ned Scalars . . . . . . . . .
5.8 Executing On Demand . . . . . . . . . . . . . . . . . . . .

6 Sample Applications

6.1 Boundary Condition Applications . . . . . . . . . . . . . .


6.1.1 Parabolic Velocity Inlet Pro le in a Turbine Vane
6.1.2 Transient Velocity Inlet Pro le for Flow in a Tube
6.2 Source Term Application . . . . . . . . . . . . . . . . . . .
6.2.1 Adding a Momentum Source to a Duct Flow . . .

vi

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

64
64
65
66
66
67
69

70
70
72
76
77
77
79
81
85
85
88
89
90
91
92
95

97

97
97
103
109
109

Fluent Inc. September 14, 2000

CONTENTS

6.3 Physical Property Application . . . . . . . . . . . . . . . . . .


6.3.1 Solidi cation via a Temperature-Dependent Viscosity
6.4 Reaction Rate Application . . . . . . . . . . . . . . . . . . . .
6.4.1 A Custom Volume Reaction Rate . . . . . . . . . . . .

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

.
.
.
.

114
114
118
118

A DEFINE Macro De nitions from udf.h

123

B C Library Functions

125

A.1 General-Use DEFINE Macros . . . . . . . . . . . . . . . . . . . . . . . . . 123


A.2 Discrete Phase DEFINE Macros . . . . . . . . . . . . . . . . . . . . . . . 124
A.3 Multiphase DEFINE Macros . . . . . . . . . . . . . . . . . . . . . . . . . 124
B.1 Trigonometric Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
B.2 Miscellaneous Mathematical Functions . . . . . . . . . . . . . . . . . . . 125
B.3 Standard I/O Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 126

Fluent Inc. September 14, 2000

vii

CONTENTS

viii

Fluent Inc. September 14, 2000

Chapter 1. Overview
User-de ned functions (UDFs) are functions that you can write to enhance the standard
features of FLUENT. UDFs are written in the C programming language and have two
di erent modes of execution: interpreted and compiled. Interpreted UDFs are simpler to
use but have coding and speed limitations. Compiled UDFs execute much more quickly
and have no coding limitations, but require more e ort to set up and use.
You can use UDFs to customize:











boundary conditions
source terms
property de nitions (except speci c heat)
surface and volume reaction rates
user-de ned scalar transport equations
discrete phase model (e.g., body force, drag, source terms)
algebraic slip mixture model (slip velocity and particle size)
solution initialization
wall heat uxes
postprocessing using user-de ned scalars

Boundary condition UDFs can be used to generate pro les as a function of time, distance, and ow- eld value. For example, you may want to specify an x-velocity boundary
condition as a function of ow time, or you may want to specify a temperature boundary
condition as a function of position. Boundary condition pro le UDFs are de ned using
the DEFINE PROFILE macro. Examples of boundary condition UDFs are provided in Section 5.1. Sample applications of boundary condition UDFs are presented in Section 6.1.
Source term UDFs can be used to modify source terms in any of the transport equations except for the DO radiation model. Source term UDFs are de ned using the
DEFINE SOURCE macro. Examples of UDFs that modify source terms are provided in
Section 5.2. See Section 6.2 for an application of a source term UDF.
Property UDFs can be used to specify custom physical properties, except for speci c heat.
For example, you may want to specify viscosity as a function of temperature. Property

Overview

UDFs are de ned using the DEFINE PROPERTY macro. An application of a property UDF
in FLUENT is presented in Section 6.3.
Reaction rate UDFs can be used to generate custom surface or volume reaction rates.
These UDFs are de ned using the DEFINE SR RATE and DEFINE VR RATE macros, respectively. See Section 6.4 for a sample application.
You can also use UDFs to specify custom parameters for the discrete phase model. UDFs
for the discrete phase model are de ned using DEFINE DPM macros. See Section 5.4 for
examples of UDFs that are speci c to the discrete phase model.
UDFs can also be written to customize a user-de ned scalar transport equation, initialize
a solution, specify a wall heat ux, or compute and store a value of a variable (using userde ned scalars or user-de ned memory) that can subsequently be used for postprocessing.
Examples of UDFs for each type of application can be found in the following sections:
Section 5.3 (user-de ned scalar transport equations); Section 5.5 (solution initialization);
Section 5.6 (wall heat ux); and Section 5.7 (postprocessing using user-de ned scalars).
Although the UDF capability in FLUENT 5 can address a wide range of applications, it
is not possible to address every application in the present document. If you are unsure
whether a particular problem can be handled using a UDF, you can contact your technical
support engineer for assistance.
1.1 Basic Steps for Writing UDFs
There are ve basic steps that typically occur during the process of writing UDFs and
using them e ectively in your FLUENT model:

1. Conceptual function design


2. Implementation (writing C code)
3. Compiling and debugging C source code
4. Executing UDF in FLUENT
5. Analyzing results and comparing to expected results
The rst step in the process is the conceptual design phase, which results in a set of
mathematical equation(s) that describe the function you wish to model. The second
step involves the translation of your function design into C source code. Step 3 involves
compiling and debugging your UDF C source code. In step 4, you will execute your
UDF in FLUENT. The last step involves analyzing the results from your simulation, and
comparing them to expected results. You may loop through this process more than once,
depending on the results of your analysis.

Fluent Inc. September 14, 2000

1.2 Interpreted vs. Compiled

1.2 Interpreted vs. Compiled


Compiled UDFs are built in the same way that the FLUENT executable itself is built. A
Makefile is used to invoke the system C compiler to build a native object code library.
The object code library contains the native machine language translation of your higherlevel C source code. This library is then linked to the FLUENT process at runtime by a
process called \dynamic loading". Once linked, the association with the shared library
is saved in your case le, so that when you read the case le in a later FLUENT session,
the compiled library will be automatically linked to the FLUENT process. These libraries
are speci c to the computer architecture being used, as well as to the particular version
of the FLUENT executable being used. The libraries must therefore be rebuilt any time
FLUENT is upgraded, when the computer's operating system level changes, or when the
job is run on a di erent type of computer.
Interpreted UDFs, on the other hand, are compiled and loaded directly from the C
source code at runtime. Inside the FLUENT process, the source code is compiled into an
intermediate, architecture-independent machine code. This machine code then executes
on an internal emulator, or interpreter, when the UDF is invoked. Once compiled, the
name and contents of your C function(s) will be stored in your case le. When you read
your case le in a later session, the function(s) will be automatically compiled during the
reading process. This extra layer of architecture-independent code incurs a performance
penalty, but allows the UDF to be e ortlessly shared between di erent architectures,
operating systems, and FLUENT versions. If execution speed does become an issue, the
UDF can be run in compiled mode without modi cation.
When deciding which type of UDF to use in your FLUENT model, keep in mind the
following characteristics:
 Interpreted UDFs
{
{
{
{

are architecture-independent.
can all be run as compiled UDFs.
cannot be linked to compiled system or user libraries.
are less powerful than compiled UDFs due to limitations in the C language
supported by the interpreter. In particular, interpreted UDFs cannot contain:
 goto statements
 non ANSI-C prototypes for syntax
 declarations of local structures, unions, pointers to functions, and arrays
of functions
 direct structure references
Interpreted UDFs can indirectly access data stored in a FLUENT structure
if the data are accessed using one of the Fluent-provided macros listed in
Section 2.10.

Fluent Inc. September 14, 2000

Overview

 Compiled UDFs
{
{
{
{
{

run much faster than interpreted UDFs.


are not restricted in the use of the C programming language.
can be compiled with any ANSI-compliant C compiler.
require that you create a shared library for each version of FLUENT (2D or
3D) needed for your machine architecture.
cannot necessarily be run as interpreted UDFs if they contain certain elements
of the C language that the interpreter cannot handle (see list above).

In summary, when deciding which type of UDF to use for your FLUENT model:
 Use interpreted UDFs for small, straightforward functions.
 Use compiled UDFs for complex functions that
{
{
{

have a signi cant CPU requirement (e.g., a property UDF that is called on a
per-cell basis every iteration).
require access to a compiled library.
require access to a variable for which there is not a Fluent-provided macro.

Fluent Inc. September 14, 2000

Chapter 2. Writing User-De ned Functions


2.1 Overview
The process for writing a user-de ned C function and the general format of a UDF are
the same whether your UDF will be executed as compiled or interpreted. The major
di erence between writing compiled UDFs and writing interpreted UDFs lies in the utilization of elements of the C language. Compiled UDFs can use all elements in the
C programming language, whereas interpreted UDFs are limited to a subset of C (see
Section 1.2 for restrictions).
2.2 UDF Format
The general format of a UDF consists of three parts:
 De nitions of constants and le include statement(s) (see Section 2.3)
 UDF function de nition using a DEFINE macro (see Section 2.4)
 Function body (see Section 2.9)
Your compiled or interpreted UDF must
 contain an include statement for the udf.h le (and other header les (sg.h, mem.h,
prop.h, dpm.h, etc.) as needed).
 be de ned using a DEFINE macro.
 specify all quantities in SI units.
 specify all function name arguments in the DEFINE statement in lower case.
In addition to the other requirements, your interpreted UDF must
 access data stored in a FLUENT structure using one of the Fluent-provided macros
listed in Section 2.10.
 not contain any of the following:
{ goto statements
{ non ANSI-C prototypes for syntax
{ direct structure references
{ declarations of local structures, unions, pointers to functions, and arrays of
functions

Writing User-De ned Functions

2.3 Including the udf.h File


The udf.h le contains the de nitions of the DEFINE macros that will be used to de ne
your UDF. Therefore, you must include it at the beginning of your C function, so that
the contents of the le will be included during compilation.
#include "udf.h"

2.4 De ning Your Function


2.4.1 Introduction
Fluent Inc. has provided you with a set of macros to help you de ne your UDF. These
macros are referred to in this document as DEFINE (all capitals) macros. The sole purpose
of a DEFINE macro is to de ne a function. De nitions for DEFINE macros (beginning with
#define) are located in the udf.h le, and for this reason you must include the udf.h
le in your UDF code. For your convenience, de nition statements for DEFINE macros,
as taken from the udf.h le, are listed in Appendix A.
Your UDF must be de ned using a DEFINE macro. The name of your UDF will be the
rst argument in the DEFINE macro.
For example, the macro
DEFINE_PROFILE(inlet_x_velocity, thread, position)

de nes a function named inlet x velocity.


! All user-de ned function name arguments must be speci ed in lower case (no capitals).
Immediately following the name argument in a DEFINE macro are the input arguments
to the DEFINE function. For example, in the DEFINE PROFILE macro above, the function
inlet x velocity has two arguments: thread and position. thread is de ned in
the udf.h le as a pointer to a Thread, and position is de ned as an integer (see
Section 2.4.3 for a description of the di erent data types).
Once your UDF has been compiled (and linked), its name will become visible in dropdown lists during your FLUENT session. For the boundary condition pro le de ned by
the DEFINE macro in the above example, you will be able to select inlet x velocity as
the x-velocity condition in the appropriate boundary condition panel (e.g., the Velocity
Inlet panel).

Fluent Inc. September 14, 2000

2.4 De ning Your Function

2.4.2 #define Statements in the udf.h File


The udf.h le contains de nitions of DEFINE macros (see Appendix A). Each de nition
begins with the statement #define as shown in the example below:
#define DEFINE_PROFILE(name, t, i)

void name(Thread *t, int i)

The general form of a macro de nition is


#define

macro replacement-text

Before compilation, the C preprocessor (e.g., cpp) performs a macro substitution using
the #define information provided in the udf.h le. For every #define statement included in your UDF by the #include "udf.h" statement, the preprocessor performs a
simple substitution and expands the occurrence of each argument in macro using the
replacement-text.
For example, the macro
DEFINE_PROFILE(inlet_x_velocity, thread, position)

expands to
void inlet_x_velocity(Thread *thread, int position)

The function that is named in the DEFINE macro will either return a value of a particular
data type (e.g., real), or not return any value if the name argument in the DEFINE macro
is de ned as void. For example, the function inlet x velocity does not return a
value since it is declared as a void data type. The function that is named in any
DEFINE PROPERTY macro, for example, returns a real value since it is declared as a real
data type in the udf.h le.

Fluent Inc. September 14, 2000

Writing User-De ned Functions

2.4.3

Macros
DEFINE macros are used to de ne UDFs. They are divided into three categories: general
use, discrete phase, and multiphase DEFINE macros, which are listed below. Each macro
begins with the pre x DEFINE (all caps). You can get a general idea of what a particular
function (that is de ned by a macro) does by looking at the part of the name following the
DEFINE pre x. For example, the DEFINE SOURCE macro de nes a function that modi es
source terms, while DEFINE PROPERTY is used to de ne a function that allows you to
customize a material property.
Descriptions of functions that are de ned using general-use DEFINE macros are presented
in Section 2.5. Functions for the discrete phase model macros are described in Section 2.6,
and functions for multiphase models are described in Section 2.7. In addition to a description, each function's arguments, argument types, and return type are provided in
a table for easy reference. Refer to Appendix A for DEFINE macro de nitions (from the
udf.h le).
DEFINE
















DEFINE ADJUST
DEFINE DIFFUSIVITY
DEFINE HEAT FLUX
DEFINE INIT
DEFINE ON DEMAND
DEFINE PROFILE
DEFINE PROPERTY
DEFINE RW FILE
DEFINE SCAT PHASE FUNC
DEFINE SOURCE
DEFINE SR RATE
DEFINE UDS FLUX
DEFINE UDS UNSTEADY
DEFINE VR RATE

Fluent Inc. September 14, 2000

2.4 De ning Your Function

For the discrete phase model:













DEFINE DPM BODY FORCE


DEFINE DPM DRAG
DEFINE DPM EROSION
DEFINE DPM INJECTION INIT
DEFINE DPM LAW
DEFINE DPM OUTPUT
DEFINE DPM PROPERTY
DEFINE DPM SCALAR UPDATE
DEFINE DPM SOURCE
DEFINE DPM SWITCH

For multiphase models:





DEFINE DRIFT DIAMETER


DEFINE SLIP VELOCITY

Declaration of Data Types


In addition to the standard C language data types (e.g., int for integer), there are
FLUENT-speci c data types used in DEFINE functions. Some of the more commonly-used
data types are: Thread, cell t, face t, Node, and Domain. These argument types are
case-sensitive.
Thread is a structure that corresponds to a boundary or cell zone. cell t describes
an individual control volume and is used in the de nition of source terms or properties.
face t corresponds to a grid face, and is, for example, the location where inlet boundary
conditions are being de ned. Node corresponds to the corner of a cell (or face), and
Domain is a structure that consists of the sum of all other groups: all threads, cells, faces,
and nodes.
! Note that the data types Thread, cell t, face t, Node, and Domain are case-sensitive.

Fluent Inc. September 14, 2000

Writing User-De ned Functions

2.5 General-Use DEFINE Macros and the Functions They De ne


DEFINE macros are used to de ne UDFs. The functions that these macros de ne are
referred to in this document as DEFINE functions, and the name of the function to be
de ned is the rst argument of the DEFINE macro. For example, the DEFINE PROFILE
macro is used to de ne a function that is referred to as a DEFINE PROFILE function. A
description of each general-use DEFINE function is presented in the following sections.
Sections 2.6 and 2.7 contain descriptions of functions for the discrete phase model and
for the multiphase models.
2.5.1

DEFINE ADJUST
Name

Arguments Argument Type Return Type

DEFINE ADJUST domain

Domain *domain

void

A DEFINE ADJUST function is called at the beginning of every iteration, just before solving
the transport equations. It can be used to modify ow variables, compute integrals, etc.
The Domain pointer argument domain is passed to the function by the solver to give
access to all the cell and face threads in the domain. The function does not return a
value.
See Section 4.6 for information about activating the function within FLUENT. Examples
of UDFs that are de ned using the DEFINE ADJUST macro can be found in Sections 5.3,
5.6, and 5.7.
2.5.2

DEFINE DIFFUSIVITY
Name
Arguments Argument Type
DEFINE DIFFUSIVITY c, t, i

Return Type

cell t c, Thread *t, int i real

A DEFINE DIFFUSIVITY function is used to specify the di usivity for the species equations
or user-de ned scalar equations. The argument c is the index of the cell, Thread pointer
t points to the thread of the cell, and i is the index of the species or user-de ned scalar
(with its value passed to the UDF by the solver). The function returns the real value
of di usivity.
An example of a UDF that is de ned using the DEFINE DIFFUSIVITY macro can be found
in Section 5.3.

10

Fluent Inc. September 14, 2000

2.5 General-Use DEFINE Macros and the Functions They De ne

2.5.3

DEFINE HEAT FLUX

Name

Arguments Argument Type

DEFINE HEAT FLUX f, t, c0,


t0, cid,
cir

Return Type

face t f, Thread *t, cell t c, void


Thread *t0, real cid[],
real cir[]

A DEFINE HEAT FLUX function allows you to customize how di usive and radiative heat
uxes between a cell and a neighboring wall are to be computed in the energy equation.
You can use this DEFINE macro to specify one or both types of heat uxes. The argument
f is the index of the wall face, Thread pointer t points to the thread of the wall face, c0
is the index of the cell next to the wall, and Thread pointer t0 points to the thread of the
cell. Your UDF needs to specify the di usive heat ux coecient (cid), and the radiative
heat ux coecient (cir). With these inputs, di usive heat ux (qid) and radiative heat
ux (qir), respectively, will then be computed by FLUENT using the following equations:
qid = cid[0] + cid[1]*C_T(c0,t0) - cid[2]*F_T(f,t) - cid[3]*pow(F_T(f,t),4)
qir = cir[0] + cir[1]*C_T(c0,t0) - cir[2]*F_T(f,t) - cir[3]*pow(F_T(f,t),4)

The function does not return a value.


See Section 4.7 for information about activating the function within FLUENT. An example
of a UDF that is de ned using the DEFINE HEAT FLUX macro can be found in Section 5.6.
2.5.4

DEFINE INIT
Name

Arguments Argument Type Return Type

DEFINE INIT domain

Domain *domain

void

Customized initialization functions can be implemented with the DEFINE INIT macro.
Note that this function will be called after the default initialization is performed. The
Domain pointer argument domain is passed into the function by the solver to give access
to all the cell and face threads. The function does not return a value.
See Section 4.5 for information about selecting the function within FLUENT. Examples
of UDFs that are de ned using the DEFINE INIT macro can be found in Sections 5.4.1
and 5.5.

Fluent Inc. September 14, 2000

11

Writing User-De ned Functions

2.5.5

DEFINE ON DEMAND
Name
Arguments Argument Type Return Type
DEFINE ON DEMAND

void

A DEFINE ON DEMAND macro is used to de ne a UDF that you want to execute on demand
in FLUENT, rather than having FLUENT call it automatically during the calculation.
See Section 4.12 for information about selecting and executing the function within FLUENT. An example of a UDF that is de ned using the DEFINE ON DEMAND macro can be
found in Section 5.8.
2.5.6

DEFINE PROFILE
Name
Arguments Argument Type Return Type
DEFINE PROFILE t, i

Thread *t, int i

void

A DEFINE PROFILE function is used to specify pro le boundary conditions (i.e., boundary
conditions varying as functions of spatial coordinates or time). Arguments are Thread
pointer t, which points to the thread on which the boundary condition is to be applied,
and i, which is the index of the location where the boundary condition is to be stored
(with its value passed to the UDF by the solver). The function should loop over all the
faces in the boundary thread, and the boundary condition for faces on a thread is stored
in F PROFILE(f,t,i) for all faces with index f that are on the thread pointed to by t.
The function does not return a value.
See Section 4.1 for information about selecting the function within FLUENT. Examples of
UDFs that are de ned using the DEFINE PROFILE macro can be found in Sections 5.1.1,
5.1.2, 5.1.3, 5.3, 6.1.1, and 6.1.2.
2.5.7

DEFINE PROPERTY
Name
Arguments Argument Type
DEFINE PROPERTY c, t

Return Type

cell t c, Thread *t real

A DEFINE PROPERTY function is used to customize material properties. The argument


c is the index of the cell, and Thread pointer t points to the thread of the cell. The
function returns the value of the property.
See Section 4.3 for information about selecting the function within FLUENT. An example
of a UDF that is de ned using the DEFINE PROPERTY macro can be found in Section 6.3.1.

12

Fluent Inc. September 14, 2000

2.5 General-Use DEFINE Macros and the Functions They De ne

2.5.8

DEFINE RW FILE
Name
Arguments Argument Type Return Type
DEFINE RW FILE fp

FILE *fp

void

A DEFINE RW FILE macro is used to de ne customized information that is to be written


to a case or data le, or read from a case or data le. The argument fp is a pointer that
points to the le to or from which you are writing or reading.
See Section 4.11 for information about activating the function within FLUENT. An example of a UDF that is de ned using the DEFINE RW FILE macro can be found in Section 2.9.8.
2.5.9

DEFINE SCAT PHASE FUNC


Name
Arguments Argument Type Return Type
DEFINE SCAT PHASE FUNC c, f

real c, real *f

real

A DEFINE SCAT PHASE FUNC function can be used to de ne the radiation scattering phase
function for the discrete ordinates model. This function computes two values: the fraction
of radiation energy scattered from direction i to direction j , and the forward scattering
factor. The real variable c is the cosine of the angle between the two directions. The
fraction of radiation energy scattered from direction i to direction j is returned by the
function, and the forward scattering factor is stored in the real variable that is referenced
by the real pointer f. The solver computes and stores a scattering matrix for each
material by calling this function for each unique pair of discrete ordinates.
2.5.10

DEFINE SOURCE
Name
Arguments Argument Type
DEFINE SOURCE c, t,
dS, i

Return Type

cell t c, Thread *t, real


real dS[], int i

A DEFINE SOURCE function is used to specify source terms for any of the solved transport
equations except for the DO radiation model. The function typically loops over cells in
a cell thread and computes the source term. The argument c is the index of the cell,
and Thread pointer t points to the thread of the cell. Array dS is used to specify the
derivatives of the source with respect to the coupled equations (i.e., equations that are
coupled together for solution). These derivatives are used in linearizing the source term
to enhance the stability of the solver. The index i is the index of the equation for which
the source is being speci ed (with its value passed to the UDF by the solver). Note that if
the source is being speci ed for an equation that is not coupled with any other equation,

c

Fluent Inc. September 14, 2000

13

Writing User-De ned Functions

then only the derivative with respect to the solved variable needs to be speci ed (i.e.,
only dS[i]). The function returns the value of the source term.
See Section 4.2 for information about selecting the function within FLUENT. Examples
of UDFs that are de ned using the DEFINE SOURCE macro can be found in Sections 5.2.1,
5.2.2, 5.3, and 6.2.1.
2.5.11

DEFINE SR RATE
Name
Arguments Argument Type
DEFINE SR RATE f, t,
r, mw,
yi, rr

Return Type

face t f, Thread *t,


void
Reaction *r, real *mw,
real *yi, real *rr

A DEFINE SR RATE function can be used to customize a surface reaction rate. Here f
is the index of the face, Thread pointer t points to the thread of the face, Reaction
pointer r points to the reaction structure, mw is a pointer to a real array containing
the species molecular weights, and yi is a pointer to a real array containing the species
mass fractions. The value referenced by the real pointer rr is to be set in the function.
The function does not return a value.
See Section 4.8 for information about activating the function within FLUENT.
2.5.12

DEFINE UDS FLUX


Name
Arguments Argument Type
DEFINE UDS FLUX f, t, i

Return Type

face t f, Thread *t, int i real

A DEFINE UDS FLUX function is used to specify how the convective ux is to be computed
for the user-de ned scalar transport equations. Here f is the index of the face on which
the ux is required, Thread pointer t points to the thread of the face, and i is the index
of the user-de ned scalar (with its value passed to the UDF by the solver).
2.5.13

DEFINE UDS UNSTEADY

Name

Arguments Argument Type

DEFINE UDS UNSTEADY c, t, i,


apu, su

Return Type

cell t c, Thread *t, int i, void


real *apu, real *su

A DEFINE UDS UNSTEADY function is used to specify unsteady terms for a user-de ned
scalar transport equation. Here c is the index of the cell, Thread pointer t points to the
14

Fluent Inc. September 14, 2000

2.5 General-Use DEFINE Macros and the Functions They De ne

thread of the cell, and i is the index of the user-de ned scalar (with its value passed to
the UDF by the solver).
In FLUENT, the unsteady term is moved to the RHS and discretized as follows:
unsteady term =


@
() dV
" @t n
() ()n 1 #  V
t
V n V n 1
 +

|
{zt }
| t {z }
apu

(2.5-1)

su

and su are the parts of the unsteady term corresponding to the central coecient
and the source term, respectively.
This function does not return a value.
apu

2.5.14

DEFINE VR RATE
Name
Arguments Argument Type
DEFINE VR RATE c, t,
r, mw,
yi, rr, rr t

Return Type

cell t c, Thread *t,


void
Reaction *r real, real *mw,
real *yi, real *rr, real *rr t

A DEFINE VR RATE function can be used to customize a volume reaction rate. Here c
is the index of the cell, Thread pointer t points to the thread of the cell, Reaction
pointer r points to the reaction structure, mw is a real pointer array of the species
molecular weights, and yi is a real pointer array of the species mass fractions. The
values referenced by the real pointers rr and rr t are to be set to the laminar and
turbulent reaction rates in the function. The function does not return a value.
See Section 4.8 for information about activating the function within FLUENT. An example
of a UDF that is de ned using the DEFINE VR RATE macro can be found in Section 6.4.1.

Fluent Inc. September 14, 2000

15

Writing User-De ned Functions

2.6

Macros for the Discrete Phase Model and the


Functions They De ne
A description of each DEFINE macro that is used to customize the discrete phase model
(DPM), and the function it de nes are presented in the following sections. In the argument list for most of these macros, there is a pointer to a Tracked Particle structure
(typically called p). This pointer can be used to obtain particle properties and information using the macros de ned in Section 2.11.
DEFINE

2.6.1

DEFINE DPM BODY FORCE

Name

Arguments Argument Type

DEFINE DPM BODY FORCE p, i

Return Type

Tracked Particle *p, int i real

A DEFINE DPM BODY FORCE function can be used to specify a body force on the particle other than a gravitational or drag force. The argument p is a pointer to the
Tracked Particle being tracked, and i is the index (0, 1, or 2, with its value passed to
the UDF by the solver) for the Cartesian component of the force to be returned. The
returned value is an acceleration.
See Section 4.4 for information about activating the function within FLUENT. An example of a UDF that is de ned using the DEFINE DPM BODY FORCE macro can be found in
Section 5.4.2.
2.6.2

DEFINE DPM DRAG


Name
Arguments Argument Type
DEFINE DPM DRAG Re, p

Return Type

real Re, Tracked Particle *p real

A DEFINE DPM DRAG function can be used to specify the drag coecient, CD , de ned by
the following equation:
FD =

18 CD Re
p Dp2 24

The argument Re is the particle Reynolds number based on the particle diameter and
relative gas velocity, and p is a pointer to the Tracked Particle being tracked. The
value returned will be dimensionless and represent 18 * Cd * Re / 24.
See Section 4.4 for information about activating the function within FLUENT. An example
of a UDF that is de ned using the DEFINE DPM DRAG macro can be found in Section 5.4.3.
16

Fluent Inc. September 14, 2000

2.6 DEFINE Macros for the Discrete Phase Model and the Functions They De ne

2.6.3

DEFINE DPM EROSION

Name

Arguments

DEFINE DPM EROSION p,


t, f,
normal, alpha,
Vmag, mdot

Argument Type

Return Type

Tracked Particle *p,


void
Thread *t, face t f,
real normal[], real alpha,
real Vmag, real mdot

A DEFINE DPM EROSION function allows access to the erosion and accretion rates calculated as the particle stream strikes a wall surface. The arguments for the function are
the pointer p to the Tracked Particle being tracked; the pointer t to the Thread of
the face the particle is hitting; the index f of the face the particle is hitting; the array normal, which contains the unit vector normal to the face; the impact angle alpha
between the particle path and the face (in radians); the magnitude of the particle velocity Vmag; and the ow rate mdot of the particle stream as it hits the face. The
calculated values for the erosion rate and/or accretion rate will be stored at the faces in
F STORAGE R(f,t,SV DPMS EROSION) and F STORAGE R(f,t,SV DPMS ACCRETION). The
function does not return a value.
See Section 4.4 for information about activating the function within FLUENT.
2.6.4

DEFINE DPM INJECTION INIT


Name
Arguments Argument Type Return Type
DEFINE DPM INJECTION INIT I

Injection *I

void

A DEFINE DPM INJECTION INIT function can be used to specify particle properties at the
time of injection. The argument I is a pointer to the Injection for which the particles
are being created. This function is called twice for each Injection before the rst DPM
iteration, and then called once for each Injection before the particles are injected into
the domain at each subsequent DPM iteration. Initial particle properties such as location,
diameter, and velocity can be modi ed. The function does not return a value.
2.6.5

DEFINE DPM LAW


Name
Arguments Argument Type
DEFINE DPM LAW p, ci

Return Type

Tracked Particle *p, int ci void

A DEFINE DPM LAW function can be used to specify the heat and mass transfer rates for
droplets and combusting particles. The arguments are the pointer p to the Tracked Particle
currently being tracked; and the integer ci, which indicates if the continuous and discrete

c

Fluent Inc. September 14, 2000

17

Writing User-De ned Functions

phases are coupled (equal to 1 if coupled, otherwise 0). The particle's properties (mass,
diameter, temperature, etc.) are modi ed as the droplet or particle exchanges mass and
energy with its surroundings. The function does not return a value.
2.6.6

DEFINE DPM OUTPUT

Name

Arguments Argument Type

DEFINE DPM OUTPUT header, fp,


p, t,
plane

Return Type

int header, FILE *fp,


void
Tracked Particle *p, Thread *t,
Plane *plane

A DEFINE DPM OUTPUT function allows access to the variables that are written as a particle
passes through a sample plane (see Section 14.10.6 in the FLUENT 5 User's Guide). The
arguments are header, which is set to 1 at the rst call of the function before particles
are tracked and set to 0 for subsequent calls; the le index fp to which the information
is being written; the pointer p to the Tracked Particle being tracked; the pointer t to
the Thread the particle is passing through if it is a grid surface (otherwise t is NULL);
and the pointer plane to the Plane structure (dpm.h) if the particle is passing through a
planar (line in 2D) slice (plane is NULL if the particle is passing through a grid surface).
The output will be written to the le indicated by fp. The function does not return a
value.
An example of a UDF that is de ned using the DEFINE DPM OUTPUT macro can be found
in Section 5.4.1.
2.6.7

DEFINE DPM PROPERTY


Name
Arguments Argument Type
DEFINE DPM PROPERTY c, t,
p

Return Type

cell t c, Thread *t, real


Tracked Particle *p

A DEFINE DPM PROPERTY function is used for specifying properties of discrete phase materials. It has the same arguments as the DEFINE PROPERTY function (described in Section 2.5.7), with the addition of the pointer to the Tracked Particle p. The argument
c is the index of the cell, and Thread pointer t points to the thread of the cell. The
function returns the value of the discrete phase property.

18

Fluent Inc. September 14, 2000

2.6 DEFINE Macros for the Discrete Phase Model and the Functions They De ne

2.6.8

DEFINE DPM SCALAR UPDATE


Name
Arguments Argument Type
DEFINE DPM SCALAR UPDATE c, t,
initialize,
p

Return Type

cell t c, Thread *t, void


int initialize,
Tracked Particle *p

A DEFINE DPM SCALAR UPDATE function allows particle-related variables to be updated


or integrated over the life of the particle. Particle values can be stored in an array
associated with the Tracked Particle (accessed with the macro P USER REAL(p,i)).
Values calculated and stored in the array can be used to color the particle trajectory.
The arguments are c, the cell index cell t that the particle is currently in; t, the cell
Thread that the particle is currently in; the integer initialize, which has a value of 1
when the function is called at the start of the particle integration and 0 thereafter; and
the pointer p to the Tracked Particle being tracked. The function is called at the start
of the particle integration (initialize equal to 1) and then after each time step for the
particle trajectory integration. The size of the user real array available for storage should
be set in the Discrete Phase Model panel in the Number of Scalars eld. The function does
not return a value.
See Section 4.4 for information about activating the function within FLUENT. An example
of a UDF that is de ned using the DEFINE DPM SCALAR UPDATE macro can be found in
Section 5.4.1.
2.6.9

DEFINE DPM SOURCE


Name
Arguments Argument Type
DEFINE DPM SOURCE c, t,
S, strength
p

Return Type

cell t c, Thread *t,


void
dpms t *S, real strength
Tracked Particle *p

A DEFINE DPM SOURCE function allows access to the accumulated source terms for a particle in a given cell before they are added to the mass, momentum, and energy exchange
terms for coupled DPM calculations. The arguments are c, the cell index cell t that the
particle is currently in; t, the cell Thread that the particle is currently in; S, the pointer
to the source structure dpms t which contains the source terms for the cell; strength, the
particle number ow rate in particles/second (divided by the number of tries if stochastic tracking is used); and p, the pointer to the Tracked Particle being tracked. The
modi ed source terms will be stored in S. The function does not return a value.
See Section 4.4 for information about activating the function within FLUENT.

Fluent Inc. September 14, 2000

19

Writing User-De ned Functions

2.6.10

DEFINE DPM SWITCH


Name
Arguments Argument Type
DEFINE DPM SWITCH p, ci

Return Type

Tracked Particle *p, int ci void

The DEFINE DPM SWITCH function can be used to control the switching between the userde ned particle laws and the default particle laws, or between di erent user-de ned or
default particle laws. The arguments are the pointer p to the Tracked Particle currently
being tracked; and the integer ci, which indicates if the continuous and discrete phases
are coupled (equal to 1 if coupled, otherwise 0). The function does not return a value.

20

Fluent Inc. September 14, 2000

2.7 DEFINE Macros for Multiphase Models and the Functions They De ne

2.7

Macros for Multiphase Models and the Functions


They De ne
A description of each DEFINE macro that is used to customize a multiphase model, and
the function it de nes are presented in the following sections.
DEFINE

2.7.1

DEFINE DRIFT DIAM


Name
Arguments Argument Type
DEFINE DRIFT DIAM c, t

Return Type

cell t c, Thread *t real

A DEFINE DRIFT DIAM function can be used to de ne the particle or droplet diameter for
the algebraic slip mixture model. The argument c is the index of the cell, and Thread
pointer t points to the thread of the cell. The function returns the value of the particle
or droplet diameter.
See Section 4.10 for information about selecting the function within FLUENT.
2.7.2

DEFINE SLIP VELOCITY


Name
Arguments Argument Type Return Type
DEFINE SLIP VELOCITY domain

Domain *domain

void

A DEFINE SLIP VELOCITY function can be used to de ne the slip velocity for the algebraic
slip mixture model. The Domain pointer argument domain is passed into the function by
the solver to give access to all the cell and face threads. The function does not return a
value.
See Section 4.9 for information about selecting the function within FLUENT.

Fluent Inc. September 14, 2000

21

Writing User-De ned Functions

2.8 Determining the Pointer to a Thread


In many UDF applications, you will need to nd the pointer to a particular thread you
want to work with. The pointer to the thread is normally used in subsequent cell or
face operations (cell or face loops). Once you determine the ID number of a thread (by
checking the ID number for the associated zone in the Boundary Conditions panel), you
can nd the pointer to the thread using the Lookup Thread macro.
In the example below, the function Print Thread Face Centroids uses the Lookup Thread
macro to determine the pointer to a thread, and then writes to a le the face centroids
of all the faces in a speci ed thread. The DEFINE ON DEMAND function get coords calls
Print Thread Face Centroids for two speci ed threads.
#include "udf.h"
extern Domain *domain;
FILE *fout;
static void
Print_Thread_Face_Centroids(Domain *domain, int id)
{
real FC[2];
face_t f;
Thread *t = Lookup_Thread(domain, id);

fprintf(fout,"thread id %d\n", id);


begin_f_loop(f,t)
{
F_CENTROID(FC,f,t);
fprintf(fout, "f%d %g %g %g\n", f, FC[0], FC[1], FC[2]);
}
end_f_loop(f,t)
fprintf(fout, "\n");

DEFINE_ON_DEMAND(get_coords)
{
fout = fopen("faces.out", "w");
Print_Thread_Face_Centroids(domain, 2);
Print_Thread_Face_Centroids(domain, 4);
fclose(fout);
}

22

Fluent Inc. September 14, 2000

2.9 Function Body

2.9 Function Body


2.9.1 Introduction
The body of your user-de ned function is contained within curly braces immediately
following the DEFINE statement, as shown in the example below. This corresponds to the
standard C function body de nition.
DEFINE_PROPERTY(cell_viscosity, cell, thread)
{
real mu_lam;
real temp = C_T(cell, thread);
if (temp > 288.)
mu_lam = 5.5e-3;
else if (temp > 286.)
mu_lam = 143.2135 - 0.49725 * temp;
else
mu_lam = 1.;
}

return mu_lam;

! All quantities in user-de ned functions must be speci ed in SI units.


2.9.2 Restrictions on Interpreted UDFs
Recall that if you are writing a UDF that will be executed as an interpreted UDF, your
function body cannot contain
 goto statements.
 non ANSI-C prototypes for syntax.
 declarations of local structures, unions, pointers to functions, and arrays of func-

tions.
 direct structure references
All data stored in a FLUENT structure must be accessed using one of the Fluentprovided macros listed in Section 2.10.

Fluent Inc. September 14, 2000

23

Writing User-De ned Functions

2.9.3 Function Tasks


There are ve types of tasks UDFs can perform:






Return a value
Modify an argument
Return a value and modify an argument
Modify a FLUENT variable (not passed as an argument)
Write information to (or read information from) a case or data le

Functions that are de ned with a DEFINE macro return a value unless they are de ned
as void in the udf.h le (see #define statements for the DEFINE macros in the udf.h
le). If they do not return a value, they may either modify an argument, or modify a
variable stored in memory.
Examples of UDFs that perform each of the ve function tasks are presented in the
following sections.

24

Fluent Inc. September 14, 2000

2.9 Function Body

2.9.4 Returning a Value


The following UDF is a function that returns a value. The UDF is used to compute a
temperature-dependent viscosity.
The C source code (viscosity.c) for this UDF is given below:
/***********************************************************************/
/* viscosity.c
*/
/* UDF for specifying a temperature-dependent viscosity property
*/
/***********************************************************************/
#include "udf.h"
DEFINE_PROPERTY(cell_viscosity, cell, thread)
{
real mu_lam;
real temp = C_T(cell, thread);
if (temp > 288.)
mu_lam = 5.5e-3;
else if (temp > 286.)
mu_lam = 143.2135 - 0.49725 * temp;
else
mu_lam = 1.;
}

return mu_lam;

The function cell viscosity is de ned using the DEFINE PROPERTY macro (described in
Section 2.5.7). Two real variables are introduced: mu lam, the laminar viscosity computed
by the function; and temp, the value of C T(cell,thread) which is the temperature value
in the cell under consideration. The value of the temperature is checked, and based upon
the range into which it falls, the appropriate value of mu lam is computed. At the end
of the function, the computed value for mu lam is returned. See Section 6.3.1 for more
details about this UDF.

Fluent Inc. September 14, 2000

25

Writing User-De ned Functions

2.9.5 Modifying an Argument


The following UDF performs its task by modifying one of the function's arguments. The
UDF generates a custom volume reaction rate for a simple system of two gaseous species.
/**************************************************************/
/* rate.c
*/
/* UDF for specifying a reaction rate in a porous media
*/
/**************************************************************/
#include "udf.h"
#define K1 2.0e-2
#define K2 5.
DEFINE_VR_RATE(user_rate, cell, thread, r, mole_weight, species_mf, rate, rr_t)
{
real s1 = species_mf[0];
real mw1 = mole_weight[0];

if (FLUID_THREAD_P(thread) && THREAD_VAR(thread).fluid.porous)


*rate = K1*s1/pow((1.+K2*s1),2.0)/mw1;
else
*rate = 0.;

A function named user rate is de ned using the DEFINE VR RATE macro (described in
Section 2.5.14). The UDF performs a test if the current cell under consideration is in
a porous region, and only applies the reaction rate equation in porous regions. The
real pointer variable rate is an argument passed to the function. The UDF assigns the
value of the reaction rate to the dereferenced pointer *rate. By using the dereferencing
operator *, the object that the pointer rate points to is set to the reaction rate (see
Kernighan and Ritchie's \The C Programming Language", Prentice Hall, 1988 for more
details on dereferencing). In this way, the word that is stored in memory at the pointer
address is changed, and not the pointer address itself. See Section 6.4.1 for more details
about this UDF.

26

Fluent Inc. September 14, 2000

2.9 Function Body

2.9.6 Returning a Value and Modifying an Argument


The following UDF modi es an argument and returns a value.
The C source code (swirl.c) for this UDF is given below:
/**************************************************************/
/* swirl.c
*/
/* UDF for specifying a swirl-velocity source term
*/
/**************************************************************/
#include "udf.h"
#define OMEGA 50.
/* rotational speed of swirler */
#define WEIGHT 1.e20 /* weighting coefficients in linearized equation */
DEFINE_SOURCE(user_swirl, cell, thread, dS, eqn)
{
real w_vel, x[ND_ND], y, source;
C_CENTROID(x, cell, thread);
y = x[1];
w_vel = y*OMEGA; /* linear w-velocity at the cell */
source = WEIGHT*(w_vel - C_WSWIRL(cell,thread));
dS[eqn] = -WEIGHT;
}

return source;

In this UDF, a function named user swirl is de ned using the DEFINE SOURCE macro
(described in Section 2.5.10). The function speci es a source term for swirl velocity. It
takes the argument dS, and modi es it by setting it equal to the derivative of the source
term. The function also computes the value of the source term, source, and returns this
value to the solver. See Section 5.2.2 for more details about this UDF.

Fluent Inc. September 14, 2000

27

Writing User-De ned Functions

2.9.7 Modifying a FLUENT Variable


The following UDF is a function that modi es a FLUENT variable stored in memory.
The UDF speci es an x-velocity pro le boundary condition.
/*************************************************************************/
/* vprofile.c
*/
/* UDF for specifying a steady-state velocity profile boundary condition */
/*************************************************************************/
#include "udf.h"
DEFINE_PROFILE(inlet_x_velocity, thread, position)
{
real x[ND_ND]; /* this will hold the position vector */
real y;
face_t f;

begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y = x[1];
F_PROFILE(f, thread, position) = 20. - y*y/(.0745*.0745)*20.;
}
end_f_loop(f, thread)

In this UDF, a function named inlet x velocity is de ned using the DEFINE PROFILE
macro (described in Section 2.5.6). Its arguments are thread and position. thread is
a pointer to the face's thread, and position is an integer that is a numerical label for
the variable being set within each loop.
The function begins by declaring variable f as a face t data type. A one-dimensional
array x and variable y are real data types. A looping macro is then used to loop over each
face in the zone to create a pro le, or an array of data. Within each loop, F CENTROID
outputs the value of the face centroid (array x) for the face with index f that is on the
thread pointed to by thread. The y coordinate stored in x[1] is assigned to variable y,
which is then used to calculate the x velocity. This value is then assigned to F PROFILE,
which uses the integer position (passed to it by the solver) to set the x-velocity value
in memory at the face.

28

Fluent Inc. September 14, 2000

2.9 Function Body

2.9.8 Writing to or Reading from a Case or Data File


The UDFs in the C source code below (rw.c) illustrate how to compute a static variable
(kount), write it to a data le, and then read it back in. To make use of the UDFs that
read and write, you will need to specify them as described in Section 4.11. See Section 4.6
for information about using an ADJUST function to compute a static variable.
/**************************************************************/
/*
*/
/* rw.c
*/
/* UDF for incrementing a static variable, writing it to a
*/
/* data file, and reading it back in
*/
/*
*/
/**************************************************************/
#include "udf.h"
int kount = 0;

/* define static variable kount */

DEFINE_ADJUST(demo_calc, domain)
{
kount++;
printf("kount = %d\n",kount);
}
DEFINE_RW_FILE(writer, fp)
{
printf("Writing UDF data to data file...\n");
fprintf(fp, "%d",kount); /* write out kount to data file */
}
DEFINE_RW_FILE(reader, fp)
{
printf("Reading UDF data from data file...\n");
fscanf(fp, "%d",&kount); /* read kount from data file */
}

At the top of the listing, the integer kount is de ned and initialized to zero. The rst
function (demo calc) is an ADJUST function that increments the value of kount at each
iteration, since the ADJUST function is called once per iteration. (See Section 2.5.1 for
more information about ADJUST functions.) The second function (writer) instructs

c

Fluent Inc. September 14, 2000

29

Writing User-De ned Functions

to write the current value of kount to the data le, when the data le is
saved. The third function (reader) instructs FLUENT to read the value of kount from
the data le, when the data le is read.
The functions work together as follows. If, for example, you run your calculation for 10
iterations (hence kount has been incremented to a value of 10) and save the data le,
the current value of kount (10) will be written to your data le. If you read the data
back into FLUENT and continue the calculation, kount will start at a value of 10 and be
incremented from there at each iteration.
Note that you can save as many static variables as you want, but you must be sure to
read them in the same order that they are written.
FLUENT

30

Fluent Inc. September 14, 2000

2.10 Solver Functions

2.10 Solver Functions


2.10.1 Overview
In most cases, your UDF will need to access FLUENT solver data. Some examples of
types of solver data that can be accessed are:
 solution variables and their derivatives (e.g., velocity, temperature, turbulence

quantities)
 cell and face metrics (e.g., face area, cell volume, cell center coordinates)
 properties (e.g., density, viscosity, conductivity)

! Note that you can access speci c heat data, but you cannot modify it.
You can access solver data in your UDF by using Fluent-provided functions that are listed
in the following sections. The word \function" is used loosely here, since these functions
are implemented in FLUENT as functions or macros. To obtain a precise de nition for a
particular \function" described below, refer to the appropriate .h source le.
! Note that if you are writing a UDF that will be executed as an interpreted UDF, you
can access solver data only using a Fluent-provided function.
Solver functions can be used in the body of your C code, along with C library functions,
to specify your UDF. For your convenience, a list of commonly-used C library functions
is provided in Appendix B.
Each of the Fluent-provided functions in the following sections is listed with its arguments, argument types, returned value, and name of the source le that contains the
de nition statements. Arguments are either inputs to the function, or outputs.
For example, the function
C_CENTROID(x,c,t)

has three arguments: x, c, and t. In this case, c and t are input arguments, while the
variable x[ND ND] (the cell centroid) is output to the solver.

Fluent Inc. September 14, 2000

31

Writing User-De ned Functions

2.10.2 Miscellaneous Geometry


This section contains several higher-level miscellaneous geometry functions. The integer
variables C NNODES and C NFACES return the number of nodes or faces, respectively, for
a given cell. The integer variable F NNODES returns the number of nodes associated with
a face.
Name(Arguments) Argument Types
C NNODES(c,t)
C NFACES(c,t)
F NNODES(f,t)

cell t c, Thread *t
cell t c, Thread *t
face t f, Thread *t

Returns

Source

number of cell nodes mem.h


number of cell faces mem.h
number of face nodes mem.h

2.10.3 Cell Coordinates and Areas


The real functions listed below are broken up into three groups. The rst group demonstrates how the centroid of a cell or face can be obtained. The next group shows the
calculation of the face area vector and its magnitude. The last group shows how the cell
volume is obtained for 2D, 3D, and axisymmetric simulations.
Name(Arguments) Argument Types

32

Returns

Source

C CENTROID(x,c,t)
F CENTROID(x,f,t)

real x[ND ND], cell t c, Thread *t


real x[ND ND], face t f, Thread *t

x (cell centroid)
x (face centroid)

metric.h
metric.h

F AREA(A,f,t)
NV MAG(A)

A[ND ND], face t f, Thread *t


A[ND ND]

A (area vector)

metric.h
metric.h

C VOLUME(c,t)

cell t c, Thread *t

cell volume
mem.h
for 2D or 3D,
cell volume/2
for axisymmetric

area magnitude

Fluent Inc. September 14, 2000

2.10 Solver Functions

2.10.4 Node Coordinates and Node (Grid) Velocities


The real variables listed below correspond to the Cartesian coordinates of the cell node
(at the cell corner), and the components of the velocity of the node. The node velocities
are relevant in moving mesh simulations, for example.
Name(Arguments) Argument Types Returns
NODE
NODE
NODE
NODE
NODE
NODE

X(node)
Y(node)
Z(node)
GX(node)
GY(node)
GZ(node)

Node
Node
Node
Node
Node
Node

x coordinate of node
y coordinate of node
z coordinate of node
x component of node velocity
y component of node velocity
z component of node velocity

*node
*node
*node
*node
*node
*node

Source
metric.h
metric.h
metric.h
mem.h
mem.h
mem.h

2.10.5 Face Variables


For segregated solver applications, a number of variables are available at the boundary
faces of a cell, and are listed below. These quantities are not available in the coupled
solvers.
Name(Arguments) Argument Types
F
F
F
F
F
F
F
F

P(f,t)
U(f,t)
V(f,t)
W(f,t)
T(f,t)
H(f,t)
K(f t)
D(f,t)

F YI(f,t,i)
F UDSI(f,t,i)
F UDMI(f,t,i)

Fluent Inc. September 14, 2000

Source

pressure
mem.h (all)
u velocity
v velocity
w velocity
temperature
enthalpy
turbulent kinetic energy
turbulent energy
dissipation
face t f, Thread *t, int i species mass fraction
face t f, Thread *t, int i user-de ned scalar
face t f, Thread *t, int i user-de ned memory
face
face
face
face
face
face
face
face

t
t
t
t
t
t
t
t

f,
f,
f,
f,
f,
f,
f,
f,

Returns

Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread

*t,
*t,
*t,
*t,
*t,
*t,
*t,
*t,

33

Writing User-De ned Functions

2.10.6 Cell Variables


The following real variables are de ned on a cell, in contrast to those in Section 2.10.5,
which were de ned at a face. (The cell variables are available in both the segregated and
the coupled solvers.)
Solution Variables
Name(Arguments)

Argument Types

C
C
C
C
C
C
C
C
C
C
C

P(c,t)
U(c,t)
V(c,t)
W(c,t)
T(c,t)
H(c,t)
YI(c,t,i)
UDSI(c,t,i)
UDMI(c,t,i)
K(c,t)
D(c,t)

cell
cell
cell
cell
cell
cell
cell
cell
cell
cell
cell

t
t
t
t
t
t
t
t
t
t
t

C
C
C
C
C
C
C

RUU(c,t)
RVV(c,t)
RWW(c,t)
RUV(c,t)
RVW(c,t)
RUW(c,t)
FMEAN(c,t)

cell
cell
cell
cell
cell
cell
cell

t
t
t
t
t
t
t

C FMEAN2(c,t)

cell t

C FVAR(c,t)

cell t

C FVAR2(c,t)

cell t

C PREMIXC(c,t)

cell t

C
C
C
C

cell
cell
cell
cell

LAM FLAME SPEED(c,t)


CRITICAL STRAIN RATE(c,t)
POLLUT(c,t,i)
VOF(c,t,0)

C VOF(c,t,1)

34

t
t
t
t

cell t

c,
c,
c,
c,
c,
c,
c,
c,
c,
c,
c,

Returns

Source

pressure
mem.h
u velocity
v velocity
w velocity
temperature
enthalpy
species mass fraction
user-de ned scalar
user-de ned memory
turb. kinetic energy
turbulent energy
dissipation
c, Thread *t
uu Reynolds stress
sg mem.h
c, Thread *t
vv Reynolds stress
c, Thread *t
ww Reynolds stress
c, Thread *t
uv Reynolds stress
c, Thread *t
vw Reynolds stress
c, Thread *t
uw Reynolds stress
c, Thread *t
primary mean
mixture fraction
c, Thread *t
secondary mean
mixture fraction
c, Thread *t
primary mixture
fraction variance
c, Thread *t
secondary mixture
fraction variance
c, Thread *t
reaction progress
variable
c, Thread *t
laminar ame speed
c, Thread *t
critical strain rate
c, Thread *t, int i pollutant species
c, Thread *t
volume fraction for
primary phase
c, Thread *t
volume fraction for
secondary phase
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread

*t
*t
*t
*t
*t
*t
*t, int i
*t, int i
*t, int i
*t
*t

Fluent Inc. September 14, 2000

2.10 Solver Functions

Derivatives
Name(Arguments)

Argument Types

C
C
C
C
C
C
C
C
C
C
C

cell
cell
cell
cell
cell
cell
cell
cell
cell
cell
cell

DUDX(c,t)
DUDY(c,t)
DUDZ(c,t)
DVDX(c,t)
DVDY(c,t)
DVDZ(c,t)
DWDX(c,t)
DWDY(c,t)
DWDZ(c,t)
DP(c,t)[i]
D DENSITY(c,t)[i]

t
t
t
t
t
t
t
t
t
t
t

c,
c,
c,
c,
c,
c,
c,
c,
c,
c,
c,

Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread
Thread

Returns

*t
*t
*t
*t
*t
*t
*t
*t
*t
*t, int i
*t, int i

Source

velocity derivatives mem.h


velocity derivatives
velocity derivatives
velocity derivatives
velocity derivatives
velocity derivatives
velocity derivatives
velocity derivatives
velocity derivatives
pressure gradient
density gradient

Properties
Name(Arguments) Argument Types
C
C
C
C
C
C

R(c,t)
MU L(c,t)
MU T(c,t)
MU EFF(c,t)
K L(c,t)
K T(c,t)

t
t
t
t
t
t

c,
c,
c,
c,
c,
c,

Thread
Thread
Thread
Thread
Thread
Thread

C K EFF(c,t)

cell t c, Thread

C CP(c,t)
C RGAS(c,t)
C DIFF L(c,t,i,j)

cell t
cell t
cell t
int j
cell t
cell t
cell t

C DIFF EFF(c,t,i)
C ABS COEFF(c,t)
C SCAT COEFF(c,t)

cell
cell
cell
cell
cell
cell

Fluent Inc. September 14, 2000

c, Thread
c, Thread
c, Thread

Returns

density
laminar viscosity
turbulent viscosity
e ective viscosity
thermal conductivity
turbulent thermal
conductivity
*t
e ective thermal
conductivity
*t
speci c heat
*t
gas constant
*t, int i, laminar species di usivity
*t
*t
*t
*t
*t
*t

c, Thread *t, int i


c, Thread *t
c, Thread *t

Source
mem.h

e ective species di usivity


absorption coecient
scattering coecient

35

Writing User-De ned Functions

2.10.7 Looping Macros


Looping macros are useful for \looping", or performing repeated operations, over threads,
cells, or faces. Two types of looping macros are presented below. The rst looping macro
contains a begin and end loop statement. These macros loop over cells or faces in a
thread, according to the function de ned in the braces. The second type of looping
macro loops over threads, and consists of a single loop statement, followed by the action
to be taken in braces.
cell_t
face_t
Thread
Domain

36

c;
f;
*t;
*d;

begin_c_loop(c,t)
{
}
end_c_loop(c,t)

/* loops over cells in a cell thread

*/

begin_f_loop(f,t)
{
}
end_f_loop(f,t)

/* loops over faces in a face thread

*/

thread_loop_c(t,d)
{
}

/* loops over cell threads */

thread_loop_f(t,d)
{
}

/* loops over face threads

*/

Fluent Inc. September 14, 2000

2.10 Solver Functions

2.10.8 Protection Against Accessing Unavailable Data


It is important that the cell values of the variables that appear in your function are accessible before you compute the function. To check this, you should use the Data Valid P
function. This function returns 1 (true) if the data is valid, and 0 (false) if it is not.
\* from file case.h */
int Data_Valid_P();

For example, suppose you read a case le and, in the process, load a user-de ned function.
If that function performs a calculation using variables that have not yet been initialized,
such as the velocity at interior cells, an error will occur. To avoid this kind of error, an
if else condition can be added to your code. If (if) the data are available, the function
can be computed in the normal way. If not (else), no (or some trivial) calculation can be
performed instead. Once the ow eld has been initialized, the function can be reinvoked
so that the correct calculation can be performed.
2.10.9 Function for Setting Face Values
The macro F PROFILE is used to set the value of a variable at a face. This function is
used when you are generating boundary condition pro les.
face_t f;
Thread *t;
F_PROFILE(f,t,nvar)

/*

from mem.h

*/

The arguments of F PROFILE are the indices of the face f, a pointer to the face's thread
t, and an integer nvar. The value that is used for nvar is passed to the UDF by the
solver. You do not specify this value in your UDF.
The integer nvar is a numerical label for the variable that is being set at a particular
boundary. For example, an inlet boundary may have a total pressure and a total temperature associated with it (both of which can be functions). One of these will be identi ed
by the integer 0, and the other by the integer 1. If, instead, the inlet has three velocity
components and a static temperature, they will be identi ed by integers 0 through 3, and
so forth. The solver sets these integers once you have de ned your boundary conditions
using the Boundary Conditions panel in a FLUENT session.
! The integer nvar is a quantity that you should not change. Its value will be passed to
your UDF by FLUENT.

c

Fluent Inc. September 14, 2000

37

Writing User-De ned Functions

2.11 DPM Macros


These discrete phase model macros should be used whenever possible to ensure compatibility with future releases. The macros listed below are de ned in the header le dpm.h.
The variable p indicates a pointer to the Tracked Particle structure (Tracked Particle
*p).
2.11.1 Macros for Particle Variables
 Values of particle properties at current position:

particle diameter
particle velocity, i=0,1,2
particle temperature
particle density
particle mass
current time for particle
particle time step
particle liquid fraction (wet combusting particles only)
particle volatile fraction (combusting particles only)
 Values of particle properties at entry to the current cell:
P_DIAM(p)
P_VEL(p)[i]
P_T(p)
P_RHO(p)
P_MASS(p)
P_TIME(p)
P_DT(p)
P_LF(p)
P_VFF(p)

P_DIAM0(p)
P_VEL0(p)[i]
P_T0(p)
P_RHO0(p)
P_MASS0(p)
P_TIME0(p)
P_LF0(p)

38

particle diameter
particle velocity, i=0,1,2
particle temperature
particle density
particle mass
particle time
particle liquid fraction (wet combusting particles only)

Fluent Inc. September 14, 2000

2.11 DPM Macros

 Values of particle properties at injection into domain:


P_INIT_DIAM(p)
P_INIT_MASS(p)
P_INIT_RHO(p)
P_INIT_TEMP(p)
P_INIT_LF(p)
P_EVAP_SPECIES_INDEX(p)
P_DEVOL_SPECIES_INDEX(p)
P_OXID_SPECIES_INDEX(p)
P_PROD_SPECIES_INDEX(p)
P_CURRENT_LAW(p)
P_NEXT_LAW(p)
P_USER_REAL(p,i)

particle diameter
particle mass
particle density
particle temperature
particle liquid fraction (wet combusting particles only)
evaporating species index in mixture
devolatizing species index in mixture
oxidizing species index in mixture
combustion products species index in mixture
current particle law index
next particle law index
storage array for user-de ned values (indexed by i)

2.11.2 Macros for Particle Material Properties


 Macros for particle material properties:
P_MATERIAL(p)
DPM_SWELLING_COEFF(p)
DPM_EMISSIVITY(p)
DPM_SCATT_FACTOR(p)
DPM_EVAPORATION_TEMPERATURE(p)
DPM_BOILING_TEMPERATURE(p)
DPM_LATENT_HEAT(p)
DPM_HEAT_OF_PYROLYSIS(p)
DPM_HEAT_OF_REACTION(p)
DPM_VOLATILE_FRACTION(p)
DPM_CHAR_FRACTION(p)
DPM_SPECIFIC_HEAT(p,t)

Fluent Inc. September 14, 2000

material pointer for particle material


particle material swelling coecient
for devolatilization
particle material emissivity for radiation model
particle material scattering factor
for radiation model
particle material evaporation temperature
particle material boiling temperature
particle material latent heat
particle material heat of pyrolysis
particle material heat of reaction
particle material volatile fraction
particle material char fraction
particle material speci c heat at temperature t

39

Writing User-De ned Functions

40

Fluent Inc. September 14, 2000

Chapter 3. Compiling and Linking


User-De ned Functions
Once you have written your UDF as described in Chapter 2, you are ready to compile
(and link) it. Follow the instructions in Section 3.2 or Section 3.3, depending on whether
your UDF will be executed as an interpreted UDF or a compiled (shared object library)
UDF.
3.1 Overview
Interpreted and compiled UDFs are both compiled, but the way the source code is compiled and the code that results from the compilation process are di erent for the two types
of UDFs. Compiled UDFs are compiled into a native object code library by a system C
compiler using a Makefile. This process takes place before you begin a FLUENT session.
The resulting shared library can then be linked to a FLUENT executable at runtime by
a process known as \dynamic loading".
Interpreted UDFs, on the other hand, are compiled at runtime into an intermediate,
architecture-independent machine code, or \pseudocode". This machine code then executes on an internal emulator, or interpreter, when the UDF is invoked. This extra layer
of architecture-independent code incurs a performance penalty, but allows the UDF to
be e ortlessly shared between di erent architectures, operating systems, and FLUENT
versions. If execution speed does become an issue, the UDF can be run in compiled mode
without modi cation.
To make this distinction, the Interpreted UDFs and Compiled UDFs panels in FLUENT look
di erent. The Interpreted UDFs panel has a Compile push button, which, when clicked,
will compile your source code in real-time. The Compiled UDFs panel has an Open push
button, which, when clicked, will \open" or link your object code library (which was
created before you started FLUENT) to the FLUENT executable.
Once your compiled UDF library is linked to the FLUENT process at runtime, the association with the shared library is saved with your case le. Consequently, the library will be
automatically linked to the FLUENT process whenever the case le is subsequently read.
Similarly, once an interpreted UDF is compiled at runtime, the name and contents of your
C function(s) will be stored in your case le, and the function(s) will be automatically
compiled whenever the case le is subsequently read.
Note that object code libraries for compiled UDFs are speci c to the computer architecture being used, as well as to the particular version of the FLUENT executable. Your
libraries must therefore be rebuilt any time FLUENT is upgraded, when the computer's
operating system level changes, or when the job is run on a di erent type of computer.

Compiling and Linking User-De ned Functions

Recall that UDFs are de ned using DEFINE macros that are stored in the udf.h le.
Consequently, before you compile your UDF, the udf.h le needs to be accessible in
your path, or saved locally within your working directory.
The location of the udf.h le is:
+

path /Fluent.Inc/fluent5.x /src/udf.h

where path is the directory in which you have placed the release directory, Fluent.Inc,
and x is replaced by the appropriate number for the release you have (e.g., 0 for fluent5.0).
! In general, you should not copy udf.h from the release area. The compiler is designed to
look for this le locally (in your current directory) rst. If it is not found in your current
directory, the compiler will look in the /src directory automatically. In the event that
you upgrade your release area, but do not remove an old copy of udf.h from your working
directory, you will not be accessing the most recent version of this le.
! You should not, under any circumstances, alter the le udf.h.

42

Fluent Inc. September 14, 2000

3.2 Interpreted UDFs

3.2 Interpreted UDFs


This section presents the steps for compiling an interpreted UDF. Once your interpreted
UDF is compiled, the name and contents of your C function(s) will be stored in your
case le, and the functions will be automatically compiled whenever the case le is read.
3.2.1 Compiling an Interpreted UDF
The general procedure for compiling an interpreted UDF is as follows:

1. Make sure that the C source code for your UDF, and your case le (if previously
set up) reside in your working directory, unless you are using the parallel version of
FLUENT on a network of Windows NT machines, in which case you should follow
the instructions in Section 3.2.2.
If your source code is not in your working directory, then when you compile the
UDF you must enter the le's complete path in the Interpreted UDFs panel, instead
of just the lename.
2. Start FLUENT from your working directory.
3. Read (or set up) your case le.
4. Compile your UDF (e.g., vprofile.c) using the Interpreted UDFs panel.
De ne ! User-De ned ! Functions ! Interpreted...

Figure 3.2.1: The Interpreted UDFs Panel


(a) Enter the name of the C source code (e.g., vprofile.c) under Source File
Name.
If your C source code is not located in your working directory, then you must
type the complete path to your C function.

!

c

Fluent Inc. September 14, 2000

43

Compiling and Linking User-De ned Functions

The name of your source code le (or the complete path to it) will be stored
in your case le when you write it.
(b) Specify the C preprocessor to be used in the CPP Command Name eld.
If you installed the /contrib component from the \PrePost" CD, then by
default, the cpp preprocessor will appear in the panel. For Windows NT
users, the standard Windows NT installation of the FLUENT product includes
the cpp preprocessor.
There are also a number of other ANSI C preprocessors that may be available on your system, including gcc -E and cc -E. Check with your computer
system administrator for details.
(c) Keep the default Stack Size setting of 10000, unless the number of local variables in your function will cause the stack to over ow. In this case, set the
Stack Size to a number that is greater than the number of local variables used.
(d) Click Compile to compile your UDF.
The name and contents of your C routine will be stored in your case le when
you write the case le. If the Display Assembly Listing option in the Interpreted
UDFs panel is on (the default status), a listing of assembly language code will
appear in your console window when the function compiles. In addition, this
option will be saved in your case le, so that when you read the case in a
subsequent FLUENT session, the code will appear in the console window as
the function compiles.

44

Fluent Inc. September 14, 2000

3.2 Interpreted UDFs

inlet_x_velocity:
.local.pointer thread (r0)
.local.int nv (r1)
0
.local.end
0
save
.local.int f (r3)
1
push.int 0
.local.pointer x (r4)
3
begin.data 8 bytes, 0 bytes initialized:
7
save
.
.
.
.
.
.
156
pre.inc.int f (r3)
158
pop.int
159
b .L3 (22)
.L2:
161
restore
162
restore
163
ret.v

(e) Click Close when the compilation has nished.


If you want to make use of more than one interpreted user-de ned function
in a simulation, you can concatenate the functions together into a single C
le, all.c, for example. You can then compile the concatenated le using the
Interpreted UDFs panel. The component functions will then be available for
selection as boundary conditions, source terms, properties, etc.

3.2.2 Directory Structure for Windows NT Parallel Networks


If you are using the parallel version of FLUENT on a network of Windows NT machines,
you need to organize your les in a special way. Follow the steps below in place of the
rst step in Section 3.2.1.

1. In the Fluent.Inc directory, create a subdirectory called udf with write permission.
2. Create a subdirectory under udf (e.g., Fluent.Inc\udf\myudf) and put the C
source code for your UDF in this directory. If multiple users are running jobs on
the same cluster, each user can create his or her own subdirectory under udf (e.g.,
Fluent.Inc\udf\abcudf and xyzudf).
Since your source code is not in your working directory, when you compile the UDF
you must enter the le's complete path in the Interpreted UDFs panel, instead of just
the lename. For example, to compile example.c, you would enter the following:

Fluent Inc. September 14, 2000

45

Compiling and Linking User-De ned Functions


\\<fileserver>\Fluent.Inc\udf\myudf\example.c

replacing <fileserver> with the name of the computer on which FLUENT is installed (e.g., myserver).
3. If you have already set up your case le, make sure that it resides in your working
directory.
3.2.3 Debugging Interpreted UDFs
If there are compilation errors when you compile your UDF, they will appear in the
console window. However, you may not see all the error messages if they scroll o the
screen too quickly. For this reason, you may want to turn o the Display Assembly Listing
option while debugging your UDF.
If you keep the Interpreted UDFs panel open while you are in the process of debugging
your UDF, the Compile button can be used repeatedly since you can make changes with
an editor in a separate window. Then, you can continue to debug and compile until no
errors are reported.
3.2.4 Common Errors Made While Compiling Your Interpreted
UDF
Specifying the Source File Name
You can type just the name of your C source code (e.g., vprofile.c) in the Interpreted
UDFs panel only if you launched FLUENT from your working directory and your case le
and C source code le are located in your working directory. If the C source code you
want to compile is located in a di erent directory, then you must type the complete path
to the C source code le when you compile the UDF. If you forget to do this, you'll get
the following error:
gcc: vprofile.c: No such file or directory
gcc: No input files
Error: vprofile.c: line 1: syntax error.

If you compile your UDF, write the case le, and subsequently move your C source code
to a di erent location, then when you try to read the case le during a later FLUENT
session, you will get the same error message noted above.
Workaround
To work around this error, type the complete path to the C source code under Source
File Name in the Interpreted UDFs panel, and click Compile. When you write the case le,
the new path to your C source code will be saved.
46

Fluent Inc. September 14, 2000

3.3 Compiled UDFs

3.3 Compiled UDFs


This section presents the steps you will need to follow to compile and link a compiled
UDF. Once a compiled UDF library is linked to the FLUENT process at runtime, the
association with the shared library is saved in your case le. Consequently, the compiled
library will be automatically linked to the FLUENT process whenever the case le is
subsequently read. A message will appear in your console window that reports the status
of the linkage:
Opening library "libp1/ultra/2d/libudf.so"...
p1_adjust
energy_source
p1_source
p1_diffusivity
p1_bc
Done.

The general procedure for compiling and linking a compiled UDF is as follows:
1. In your working directory, set up the speci ed directory structure (see Section 3.3.1).
2. Compile your UDF and build the shared library (see Section 3.3.2).
3. Start FLUENT from your working directory.
4. Read (or set up) your case le. (Make sure that your case le, if previously set up,
is saved in your working directory.)
5. Link your shared library to the FLUENT executable (see Section 3.3.3).

Fluent Inc. September 14, 2000

47

Compiling and Linking User-De ned Functions

3.3.1 Setting Up the Directory Structure


The directory structures for UNIX and Windows NT systems are di erent, so the procedure for setting up the directory structure is described separately for each.
UNIX Systems
For compiled UDFs on UNIX systems, two Fluent Inc. les are required to build your
compiled UDF library: Makefile and makefile. The le makefile has a user-modi able
section that allows you to enter your source function(s), as well as the path to your
FLUENT release directory, Fluent.Inc. The complete path to each of these les is:
+

path /Fluent.Inc/fluent5.x /src/Makefile.udf


+

path /Fluent.Inc/fluent5.x /src/makefile.udf

where path is the directory in which you have placed the release directory, Fluent.Inc,
and x is replaced by the appropriate number for the release you have (e.g., 0 for fluent5.0).
The procedure below outlines steps that you need to follow in order to set up the directory
structure required for the shared library. To better illustrate the process, an example
directory structure is provided. Please refer to Figure 3.3.1 during speci c steps of the
procedure.
Note that the directory structure shown in Figure 3.3.1 is for two versions of FLUENT:
single-precision serial 2D and single-precision parallel 2D.
! Do not put any les in the version directories (2d, 2d host, etc.). The les shown there
in Figure 3.3.1 will be placed there automatically when you compile your libraries as
described in Section 3.3.2.
libudf

src

Makefile
makefile

ultra

udfexample.c

2d

makefile udfexample.c

libudf.so

2d_host

makefile udfexample.c

2d_node

libudf.so

makefile udfexample.c

libudf.so

Figure 3.3.1: Sample Library Directory Setup for a Compiled UDF (UNIX)
48

Fluent Inc. September 14, 2000

3.3 Compiled UDFs

1. In your working directory, make a directory that will store your library (e.g.,
libudf).
2. Copy Makefile.udf from the directory shown above to your library directory (e.g.,
libudf), and name it Makefile.
3. In the library directory you just created, make a source directory for your source
code, and name it src.
4. Copy your source code (e.g., udfexample.c) to your /src directory.
5. Copy makefile.udf from the directory shown above to your /src directory, and
name it makefile.
6. Identify the architecture of the machine that you will run FLUENT on.
(a) Start FLUENT.
(b) Scroll up the FLUENT console window to the message that begins with \Starting",
and identify the FLUENT architecture (e.g., ultra).
(c) Exit FLUENT.
If the architecture is irix6.5, you will need to make an extra modi cation to the
makefile. See Section 3.3.2 for details.
7. Create directories for the versions you want to build for your architecture (e.g.,
ultra/2d and ultra/3d). Possible versions are as follows:
 single-precision serial 2D or 3D: 2d or 3d
 double-precision serial 2D or 3D: 2ddp or 3ddp
 single-precision parallel 2D or 3D: 2d node and 2d host or 3d node and 3d host
 double-precision parallel 2D or 3D: 2ddp node and 2ddp host or 3ddp node
and 3ddp host
Note that you must create two build directories for each parallel version of the solver
(two for the 3D version, two for the 2D double-precision version, etc.), regardless
of the number of compute nodes.
Do not put any les in the version directories (2d, 2d host, etc.). The les shown
there in Figure 3.3.1 will be placed there automatically when you compile your
libraries as described in Section 3.3.2.

!
!

Fluent Inc. September 14, 2000

49

Compiling and Linking User-De ned Functions

Windows NT Systems
For compiled UDFs on Windows NT systems, two Fluent Inc. les are required to build
your compiled UDF library: makefile nt.udf and user nt.udf. The le user nt.udf
has a user-modi able section that allows you to enter your source function(s) and other
information.
The procedure below outlines steps that you need to follow in order to set up the directory
structure required for the shared library. To better illustrate the process, an example
directory structure is provided. Please refer to Figure 3.3.2 during speci c steps of the
procedure.
Note that the directory structure shown in Figure 3.3.2 is for two versions of FLUENT:
single-precision serial 2D and single-precision parallel 2D.
libudf

src

ntx86

udfexample.c

2d

makefile

user_nt.udf

2d_host

makefile

user_nt.udf

2d_node

makefile

user_nt.udf

Figure 3.3.2: Sample Library Directory Setup for a Compiled UDF (Windows NT)
1. In your working directory, create a directory that will store your library (e.g.,
libudf).
2. In the library directory you just created, make a source directory for your source
code, and name it src.
3. Copy your source code (e.g., udfexample.c) to your src directory.
4. Create a directory for the architecture of the machine that you will run FLUENT
on: use ntx86 for Intel systems running Windows NT, or ntalpha for DEC Alpha
systems running Windows NT.
5. Create directories for the versions you want to build for your architecture (e.g.,
ntx86\2d). Possible versions are as follows:
 single-precision serial 2D or 3D: 2d or 3d
 double-precision serial 2D or 3D: 2ddp or 3ddp
50

Fluent Inc. September 14, 2000

3.3 Compiled UDFs

 single-precision parallel 2D or 3D: 2d node and 2d host or 3d node and 3d host


 double-precision parallel 2D or 3D: 2ddp node and 2ddp host or 3ddp node

and 3ddp host


Note that you must create two build directories for each parallel version of the solver
(two for the 3D version, two for the 2D double-precision version, etc.), regardless
of the number of compute nodes.
6. Copy makefile nt.udf and user nt.udf to the build directory for the appropriate
version (e.g., 2d).
For a parallel version, be sure to copy both les to the host and node directories
(e.g., 2d node and 2d host, as shown in Figure 3.3.2).
The complete path to each of these les is:

path\Fluent.Inc\fluent5.x \src\makefile_nt.udf
+

path\Fluent.Inc\fluent5.x \src\user_nt.udf

where path is the directory in which you have placed the release directory, Fluent.Inc,
and x is replaced by the appropriate number for the release you have (e.g., 2 for
fluent5.2).
Be sure that you use the most up-to-date version of these les. If you install
a new version of FLUENT 5, remember to copy the new makefile nt.udf and
user nt.udf les to the appropriate build directory.
7. Change the name of makefile nt.udf to makefile.

Fluent Inc. September 14, 2000

51

Compiling and Linking User-De ned Functions

3.3.2 Compiling and Building Your Shared Library


The procedures for compiling and building a shared library on UNIX and Windows NT
systems are di erent, so they are described separately for each.
UNIX Systems
After you have set up your directory and put the les in the proper places, you can
compile and build your shared library.

1. Edit the le makefile in your src directory to set the following parameters:
 SOURCES = the user-de ned function(s) to be compiled
 FLUENT INC = the path to your release directory
An excerpt from a sample makefile is shown below:
#-----------------------------------------------------------#
# makefile for user defined functions.
#
# sccs id: @(#)makefile.udf
1.6 06/26/98
#-----------------------------------------------------------#
#-----------------------------------------------------------#
# User modifiable section.
#-----------------------------------------------------------#
SOURCES= udfexample.c
FLUENT_INC= /path/Fluent.Inc
#-----------------------------------------------------------#
# Build targets (do not modify below this line).
#-----------------------------------------------------------#
.
.
.

52

Fluent Inc. September 14, 2000

3.3 Compiled UDFs

2. If your architecture is irix6.5, make the following additional change to the makefile.
(a) Find the following line in the makefile:
CFLAGS_IRIX6R10=

-KPIC -ansi -fullwarn -O -n32

CFLAGS_IRIX6R10=

-KPIC -xansi -fullwarn -O -n32

(b) Change -ansi to -xansi:

For all other architectures, do not make any further changes to the makefile.
3. In your library directory (e.g., libudf), execute the Makefile by typing a command
that begins with make and includes the architecture of the machine you will run
FLUENT on that you identi ed in a previous step (e.g., ultra).
make "FLUENT ARCH=ultra"

The following messages will be displayed:


#
#
#
#
#
#

linking to ../../src/udfexample.c in ultra/2d


linking to ../../src/makefile in ultra/2d
building library in ultra/2d
linking to ../../src/udfexample.c in ultra/3d
linking to ../../src/makefile in ultra/3d
building library in ultra/3d

For the sample makefile above, the user-de ned function udfexample.c will be
compiled and stored in the shared library named libudf.so for the versions you
have speci ed (2d, 2d host, and 2d node in this case, as shown in Figure 3.3.1).
Although only one C function was used in this example, you can specify multiple
sources (separated by spaces) under SOURCES = in the makefile.

Fluent Inc. September 14, 2000

53

Compiling and Linking User-De ned Functions

Windows NT Systems
After you have set up your directory and put the les in the proper places, you can
compile and build your shared library.

1. Using a text editor, edit the le user nt.udf to set the following parameters:
 SOURCES = the user-de ned function(s) to be compiled. Use the pre x $(SRC)
before each lename (e.g., $(SRC)udfexample.c for one function, or
$(SRC)udfexample.c $(SRC)udfexample2.c for two functions).
 VERSION = the version of the solver you are using, which will be the name of the
build directory in which user nt.udf is located, as shown in Figure 3.3.2 (2d,
3d, 2ddp, 3ddp, 2d host, 2d node, 3d host, 3d node, 2ddp host, 2ddp node,
3ddp host, or 3ddp node).
 PARALLEL NODE = the parallel communications library. Specify none for a
serial version of the solver. The possible inputs are as follows:
{ none: serial
{ smpi: parallel using shared memory (for multiprocessor machines)
{ vmpi: parallel using shared memory or network with vendor MPI software
{ net: parallel using network communicator with RSHD software
If you are using a parallel version of the solver, be sure to edit both copies of
user nt.udf (the one in the host directory and the one in the node directory), and
specify the appropriate SOURCE, VERSION, and PARALLEL NODE for each.
An excerpt from a sample user nt.udf le is shown below:
# Replace text in " " (and remove quotes)
# | indicates a choice
# note: $(SRC) is defined in the makefile
SOURCES = $(SRC)udfexample.c
VERSION = 2d
PARALLEL_NODE = none

To specify multiple user-de ned functions, enter them for SOURCES, separated by
spaces.
2. In an MS-DOS Command Prompt window, go to your build directory (e.g.,
\libudf\ntx86\2d\), and type nmake.
Note that if there are problems with the build, you can do a complete rebuild by
typing nmake clean.
54

Fluent Inc. September 14, 2000

3.3 Compiled UDFs

3.3.3 Linking Your Shared Library to the FLUENT Executable


Once you have compiled and built your shared library following the UNIX or Windows
NT procedure outlined in Section 3.3.2, you are now ready to link it to a FLUENT process.
The general procedure for linking your shared library to a FLUENT process is as follows:

1. Start FLUENT from your working directory.


2. Read (or set up) your case le. (Make sure that your case le, if previously set up,
is saved in your working directory.)
3. Link your shared library to the FLUENT executable.
De ne ! User-De ned ! Functions ! Compiled...

Figure 3.3.3: The Compiled UDFs Panel


(a) Under Library Name, type the name of your library directory (e.g., libudf) if it
is located in your working directory, or the complete path (e.g., ~myhome/myfiles/
libudf).
Remember to enter the complete path to your library directory, if it is not a
subdirectory of your working directory.
(b) Click Open to link your shared library to the FLUENT executable.
The solver will automatically look for the right architecture and version. Once
you link your shared library to the FLUENT executable and write your case
le, the link will be stored in your case le. Consequently, whenever you
read your case le into FLUENT in a later session, the shared library will be
automatically linked.

Fluent Inc. September 14, 2000

55

Compiling and Linking User-De ned Functions

3.3.4 Common Errors Made While Compiling or Linking Your


Compiled UDF
Specifying the Library Name
You can type just the name of your library directory (e.g., libudf) in the Compiled
UDFs panel only if you launched FLUENT from your working directory and your library
directory is a subdirectory of your working directory. If the shared library you want
to open is located in a di erent location, then you must type the complete path to the
library directory when you link the UDF. If you forget to do this, you'll get the following
error:
Opening library "libudf/ultra/3d/libudf.so"...
Error: open_udf_library: couldn't open library: libudf/ultra/3d/libudf.so

You will also get this error message if you move a shared library to a di erent location,
and then try to read a case le that is linked to that shared library.
Workaround
To work around this error, type the complete path to the shared library under Library
Name in the Compiled UDFs panel, and click Open. You will get the same error message
again, but the new path will be saved in your case le when you write it. Reading the
case le again, after it is written with the new path stored, will result in a successful link.
Using a Di erent Version of FLUENT
If you compile your UDF using one version of FLUENT (e.g., 5.0.1), and try to read
in your case le using a di erent version of the code (e.g., 5.0.2), you will get an error
message:
Error: open_udf_library: library version 5.0.1 incompatible with solver
version 5.0.2

Workaround
You will need to recompile your UDF using the new version of FLUENT before reading
in the case le.

56

Fluent Inc. September 14, 2000

Chapter 4. Using UDFs in Your FLUENT


Model
Once you have compiled (and linked) your UDF as described in Chapter 3, you are ready
to use it in your FLUENT model. Follow the instructions in the sections that follow,
depending on how your UDF is to be used.














Section 4.1: Boundary Conditions


Section 4.2: Source Terms
Section 4.3: Property De nitions
Section 4.4: Discrete Phase Model
Section 4.5: Solution Initialization
Section 4.6: Adjustment of Computed Values
Section 4.7: Wall Heat Fluxes
Section 4.8: Reaction Rates
Section 4.9: Slip Velocity for the Algebraic Slip Mixture Model
Section 4.10: Particle or Droplet Diameter for the Algebraic Slip Mixture Model
Section 4.11: Reading from and Writing to Case and Data Files
Section 4.12: Executing a UDF On Demand
Section 4.13: Accessing Memory for Storage of Variables

Using UDFs in Your FLUENT Model

4.1 Boundary Conditions


Once you have compiled (and linked) your boundary-condition UDF by one of the methods outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable in
FLUENT. If, for example, your UDF de nes a velocity inlet boundary condition, then you
will select the name of your UDF as de ned in your C function (e.g., inlet x velocity)
in the appropriate drop-down list in the Velocity Inlet panel, as shown below.

UDFs for boundary conditions are de ned with the DEFINE PROFILE macro. See Section 2.5.6 for details.

58

Fluent Inc. September 14, 2000

4.2 Source Terms

4.2 Source Terms


Once you have compiled (and linked) your source-term UDF by one of the methods
outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable in
FLUENT. You will select the name of your UDF (e.g., cell x source) in the appropriate
drop-down list in the Fluid panel, as shown below.

UDFs for source terms are de ned with the DEFINE SOURCE macro. See Section 2.5.10
for details.

Fluent Inc. September 14, 2000

59

Using UDFs in Your FLUENT Model

4.3 Property De nitions


Once you have compiled (and linked) your property-de nition UDF by one of the methods outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable
in FLUENT. You will rst select user-de ned in the drop-down list for the appropriate
property in the Materials panel.
De ne !Materials...

60

Fluent Inc. September 14, 2000

4.3 Property De nitions

Then, select the desired UDF (e.g., cell viscosity) in the User-De ned Functions panel.

! If you plan to de ne density using a UDF, note that the solution convergence will become
poor as the density variation becomes large. Specifying a compressible law (density as
a function of pressure) or multiphase behavior (spatially varying density) may lead to
divergence. It is recommended that you restrict the use of UDFs for density to weakly
compressible ows with mild density variations.
UDFs for properties are de ned with the DEFINE PROPERTY macro. See Section 2.5.7 for
details.

Fluent Inc. September 14, 2000

61

Using UDFs in Your FLUENT Model

4.4 Discrete Phase Model


Once you have compiled (and linked) your discrete-phase UDF by one of the methods
outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable in
FLUENT. You will need to select the UDF's name in the appropriate drop-down list
under User-De ned Functions in the Discrete Phase Model panel, as shown below.
De ne ! Models !Discrete Phase...

If you are using a \scalar update" function to calculate scalar values associated with
particles during their trajectories, you can select it from the Scalar Update drop-down list
in the Discrete Phase Model panel. You will also need to specify the Number of Scalars,
as shown in the panel above. See Section 2.6 for more information about DEFINE macros
for the discrete phase model.
62

Fluent Inc. September 14, 2000

4.5 Solution Initialization

4.5 Solution Initialization


Once you have compiled (and linked) your solution-initialization UDF by one of the
methods outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable in FLUENT. You will need to select it in the User-De ned Function Hooks panel
(Figure 4.5.1).
De ne ! User-De ned !Function Hooks...

Figure 4.5.1: The User-De ned Function Hooks Panel


The Initialization Function (DEFINE INIT) is called immediately after you initialize your
ow eld, so it can be used to set the initial values of ow quantities. See Section 2.5.4
for more information about the DEFINE INIT macro.
4.6 Adjustment of Computed Values
Once you have compiled (and linked) your UDF for adjustment of computed values (using
one of the methods outlined in Sections 3.2 and 3.3), it will subsequently become visible
and selectable in FLUENT. You will need to select it in the User-De ned Function Hooks
panel (Figure 4.5.1).
De ne ! User-De ned !Function Hooks...
The Adjust Function (DEFINE ADJUST) is called at the beginning of an iteration before
solution of velocities, pressure, and other quantities begins. It can be used, for example,
to integrate a scalar quantity over the domain and adjust a boundary condition based
on the result. See Section 2.5.1 for more information about the DEFINE ADJUST macro.

c

Fluent Inc. September 14, 2000

63

Using UDFs in Your FLUENT Model

4.7 Wall Heat Fluxes


Once you have compiled (and linked) your UDF for wall heat ux calculation (using one
of the methods outlined in Sections 3.2 and 3.3), it will subsequently become visible and
selectable in FLUENT. You will need to select it in the User-De ned Function Hooks panel
(Figure 4.5.1).
De ne ! User-De ned !Function Hooks...
The Wall Heat Flux Function (DEFINE HEAT FLUX) can be used to modify the way that the
solver computes the heat ux between a wall and the neighboring uid cells. For example,
you can customize the heat transfer coecient or the law-of-the-wall for temperature. See
Section 2.5.3 for more information about the DEFINE HEAT FLUX macro.
4.8 Reaction Rates
Once you have compiled (and linked) your reaction-rate UDF by one of the methods
outlined in Sections 3.2 and 3.3, it will subsequently become visible and selectable in
FLUENT. You will need to select it in the User-De ned Function Hooks panel (Figure 4.5.1).
De ne ! User-De ned !Function Hooks...
The Volume Reaction Rate Function (DEFINE VR RATE) and Surface Reaction Rate Function
(DEFINE SR RATE) are used to provide new reaction rate de nitions (see Section 6.4.1 for
an example). See Sections 2.5.11 and 2.5.14 for more information about DEFINE SR RATE
and DEFINE VR RATE.
4.9 Slip Velocity for the Algebraic Slip Mixture Model
Once you have compiled (and linked) your UDF for the slip velocity in the algebraic
slip mixture model (using one of the methods outlined in Sections 3.2 and 3.3), it will
subsequently become visible and selectable in FLUENT. You will need to select it in the
User-De ned Function Hooks panel (Figure 4.5.1).
De ne ! User-De ned !Function Hooks...
The Slip Velocity Function (DEFINE SLIP VELOCITY) is used to provide a new de nition for
the slip velocity. See Section 2.7.2 for more information about the DEFINE SLIP VELOCITY
macro.

64

Fluent Inc. September 14, 2000

4.10 Particle or Droplet Diameter for the Algebraic Slip Mixture Model

4.10 Particle or Droplet Diameter for the Algebraic Slip


Mixture Model
Once you have compiled (and linked) your UDF for the particle or droplet diameter in
the algebraic slip mixture model (using one of the methods outlined in Sections 3.2 and
3.3), it will subsequently become visible and selectable in FLUENT. You will need to
select the UDF's name in the Droplet Diameter drop-down list in the Multiphase Model
panel, as shown below.
De ne ! Models !Multiphase...

The DEFINE DRIFT DIAM macro is used to provide a new de nition for the particle or
droplet diameter. See Section 2.7.1 for more information about the DEFINE DRIFT DIAM
macro.

Fluent Inc. September 14, 2000

65

Using UDFs in Your FLUENT Model

4.11 Reading from and Writing to Case and Data Files


Once you have compiled (and linked) a UDF for reading or writing a customized section
to or from a case or data le (using one of the methods outlined in Sections 3.2 and 3.3),
it will subsequently become visible and selectable in FLUENT. You will need to select it
in the User-De ned Function Hooks panel (Figure 4.5.1).
De ne ! User-De ned !Function Hooks...
The Read Case Function is called when you read a case le into FLUENT. It will specify
the customized section that is to be read from the case le.
The Write Case Function is called when you write a case le from FLUENT. It will specify
the customized section that is to be written to the case le.
The Read Data Function is called when you read a data le into FLUENT. It will specify
the customized section that is to be read from the data le.
The Write Data Function is called when you write a data le from FLUENT. It will specify
the customized section that is to be written to the data le.
All four functions are de ned with the DEFINE RW FILE macro, described in Section 2.5.8.
See Section 2.9.8 for an example.
4.12 Executing a UDF On Demand
Once you have compiled (and linked) your UDF by one of the methods outlined in
Sections 3.2 and 3.3, you can select it in the Execute UDF On Demand panel (Figure 4.12.1)
to execute it at a particular time, rather than having FLUENT execute it during the
calculation.
De ne ! User-De ned !Execute On Demand...

Figure 4.12.1: The Execute UDF On Demand Panel


Click Execute to have FLUENT execute the UDF immediately.
The function to be executed is de ned with the DEFINE ON DEMAND macro, described in
Section 2.5.5. See Section 5.8 for an example.

66

Fluent Inc. September 14, 2000

4.13 Accessing Memory for Storage of Variables

4.13 Accessing Memory for Storage of Variables


You can store values computed by your UDF in memory so that they can be retrieved
later, either by a UDF or for postprocessing within FLUENT. In order to have access to
this memory, you will need to specify the Number of User-De ned Memory Locations in
the User-De ned Memory panel (Figure 4.13.1).
De ne ! User-De ned !Memory...

Figure 4.13.1: The User-De ned Memory Panel


The macro C UDMI(c,t,i) or F UDMI(f,t,i) can be used in your UDF to access a
particular user-de ned memory location in a cell or face, respectively. In these macros, c
is the index of the cell, f is the index of the face, Thread pointer t points to the thread
of the cell, and i is the index of the user-de ned memory location.
Field values that have been stored in user-de ned memory will be saved to the data le
when you next write one. These elds will also appear in the User De ned Memory...
category in the drop-down lists in FLUENT's postprocessing panels. They will be named
udm-0, udm-1, etc., based on the memory location index. The total number of memory
locations is limited to 500.
See Section 5.8 for an example that makes use of user-de ned memory.

Fluent Inc. September 14, 2000

67

Using UDFs in Your FLUENT Model

68

Fluent Inc. September 14, 2000

Chapter 5. Examples of UDFs


This chapter contains examples of user-de ned functions in FLUENT. More detailed descriptions of UDF applications are presented in Chapter 6.
The UDFs are grouped in the following categories:









Section 5.1: Boundary Conditions


Section 5.2: Source Terms
Section 5.3: User-De ned Scalar Transport Equations
Section 5.4: Discrete Phase Model
Section 5.5: Solution Initialization
Section 5.6: Wall Heat Flux
Section 5.7: Postprocessing Using User-De ned Scalars
Section 5.8: Executing on Demand

UDFs for user-de ned scalar transport equations (Section 5.3), the discrete phase model
(Section 5.4), and wall heat ux (Section 5.6) are examples of compiled UDFs. In all of
the other examples, the UDFs are executed as interpreted UDFs.
For each example given in the following sections, the set of equations that is modeled
by the UDF is presented, as well as the C source code that implements the theory. See
Section 2.4.3 for descriptions of DEFINE functions (e.g., DEFINE SOURCE), and the udf.h
le or Appendix A for precise de nitions. Refer to Section 2.10 for a description of
Fluent-provided solver functions (e.g., C CENTROID), or see the appropriate .h le for
de nitions.

Examples of UDFs

5.1 Boundary Conditions


This section contains examples of UDFs that are used to customize boundary conditions
in FLUENT. Three examples are presented:
 Section 5.1.1: Parabolic Pressure Inlet Pro le for a Turbine Vane
 Section 5.1.2: Fully-Developed Turbulent Inlet Pro les
 Section 5.1.3: Sinusoidal Wall Temperature Pro le

5.1.1 Parabolic Pressure Inlet Pro le for a Turbine Vane


The following UDF named pressure profile, generates a parabolic pressure pro le
according to the equation
p(y ) = 1:1  105

y
0:1  105 0:0745

2

The C source code (profile.c) for this UDF is shown below.


/*************************************************************************/
/* profile.c
*/
/* UDF for specifying a steady-state pressure profile boundary condition */
/*************************************************************************/
#include "udf.h"
DEFINE_PROFILE(pressure_profile, thread, position)
{
real x[ND_ND]; /* this will hold the position vector */
real y;
face_t f;

70

begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y = x[1];
F_PROFILE(f, thread, position) = 1.1e5 - y*y/(.0745*.0745)*0.1e5;
}
end_f_loop(f, thread)

Fluent Inc. September 14, 2000

5.1 Boundary Conditions

The function named pressure profile has two arguments: thread and position.
thread is a pointer to the face's thread, and position is an integer that is a numerical
label for the variable being set within each loop.
Within the function body, variable f is declared as a face. A one-dimensional array x
and variable y are declared as real data types. Following the variable declarations, a
looping macro is used to loop over each face in the zone to create a pro le, or an array
of data. Within each loop, F CENTROID returns the value of the face centroid (array x)
for the face with index f that is on the thread pointed to by thread. The y coordinate
stored in x[1] is assigned to variable y, and is then used to calculate the pressure. This
value is then assigned to F PROFILE, which uses the integer position (passed to it by
the solver based on your selection of the UDF as the boundary condition for pressure in
the Pressure Inlet panel) to set the pressure face value in memory.

Fluent Inc. September 14, 2000

71

Examples of UDFs

5.1.2 Fully-Developed Turbulent Inlet Pro les


This example contains three UDFs that generate pro les for the x velocity, turbulent
kinetic energy, and dissipation rate. The pro les approximate fully-developed conditions.
! Note that you can concatenate more than one UDF in a single C source le.
The 1/7th power law is used to specify the x velocity component:
vx = vx;free

 1=7
y

A fully-developed pro le occurs when is one-half the duct height. In this example,
the mean x-velocity is prescribed and the peak (free-stream) velocity is determined by
averaging across the channel.
The turbulent kinetic energy is assumed to vary linearly from a near wall value of
knw =

u2
C

q

to a free-stream value of
kinf = 0:002u2free

The dissipation rate is given by


 = C3=4 k3=2 `

where the mixing length ` is the minimum of y and 0.085. ( is the von Karman
constant = 0.41.)
The friction velocity and wall shear take the forms
u

w =

w = fu2free=2

The friction factor is estimated from the Blasius equation:


f

= 0:045

ufree


! 1=4

The C source code for this UDF is shown below.


72

Fluent Inc. September 14, 2000

5.1 Boundary Conditions

/************************************************************************/
/* UDF for specifying fully-developed profile boundary conditions
*/
/************************************************************************/
#include "udf.h"
#define
#define
#define
#define
#define
#define
#define
#define
/*

YMIN 0.0 /* constants


YMAX 0.4064
UMEAN 1.0
B 1./7.
DELOVRH 0.5
VISC 1.7894e-05
CMU 0.09
VKC 0.41

profile for x-velocity

*/

*/

DEFINE_PROFILE(x_velocity, thread, position)


{
real y, del, h, x[ND_ND], ufree;
face_t f;

/* variable declarations */

h = YMAX - YMIN;
del = DELOVRH*h;
ufree = UMEAN*(B+1.);
begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y = x[1];
if (y <= del)
F_PROFILE(f,thread,position) = ufree*pow(y/del,B);
else
F_PROFILE(f,thread,position) = ufree*pow((h-y)/del,B);

}
end_f_loop(f, thread)

}
/*

profile for kinetic energy

Fluent Inc. September 14, 2000

*/

73

Examples of UDFs

DEFINE_PROFILE(k_profile, thread, position)


{
real y, del, h, ufree, x[ND_ND];
real ff, utau, knw, kinf;
face_t f;
h = YMAX - YMIN;
del = DELOVRH*h;
ufree = UMEAN*(B+1.);
ff = 0.045/pow(ufree*del/VISC,0.25);
utau=sqrt(ff*pow(ufree,2.)/2.0);
knw=pow(utau,2.)/sqrt(CMU);
kinf=0.002*pow(ufree,2.);
begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y=x[1];
if (y <= del)
F_PROFILE(f,thread,position)=knw+y/del*(kinf-knw);
else
F_PROFILE(f,thread,position)=knw+(h-y)/del*(kinf-knw);

}
end_f_loop(f, thread)

/* profile for dissipation rate

/*

DEFINE_PROFILE(dissip_profile, thread, position)


{
real y, x[ND_ND], del, h, ufree;
real ff, utau, knw, kinf;
real mix, kay;
face_t f;
h = YMAX - YMIN;
del = DELOVRH*h;
ufree = UMEAN*(B+1.);
ff = 0.045/pow(ufree*del/VISC,0.25);
utau=sqrt(ff*pow(ufree,2.)/2.0);

74

Fluent Inc. September 14, 2000

5.1 Boundary Conditions


knw=pow(utau,2.)/sqrt(CMU);
kinf=0.002*pow(ufree,2.);
begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y=x[1];
if (y <= del)
kay=knw+y/del*(kinf-knw);
else
kay=knw+(h-y)/del*(kinf-knw);
if (VKC*y < 0.085*del)
mix = VKC*y;
else
mix = 0.085*del;

F_PROFILE(f,thread,position)=pow(CMU,0.75)*pow(kay,1.5)/mix;
}
end_f_loop(f,thread)

Fluent Inc. September 14, 2000

75

Examples of UDFs

5.1.3 Sinusoidal Wall Temperature Pro le


This UDF applies a sinusoidal temperature variation to a wall boundary according to
the relation


T (x) = 300 + 100 sin 

x 

0:005
The boundary condition is applied to a bottom wall that is 0.005 m long. The wall
temperature starts at 300 K at the left end, reaches a peak of 400 K in the middle, and
falls back to 300 K at the right end.
The C source code for this UDF is shown below.
/**************************************************************************/
/* UDF for specifying a sinusoidal temperature profile boundary condition */
/**************************************************************************/
#include "udf.h"
#define PI 3.141592654
DEFINE_PROFILE(temperature_profile, thread, position)
{
real r[ND_ND]; /* this will hold the position vector */
real x;
face_t f;

76

begin_f_loop(f, thread)
{
F_CENTROID(r,f,thread);
x = r[0];
F_PROFILE(f, thread, position) = 300.+100.*sin(PI*x/0.005);
}
end_f_loop(f, thread)

Fluent Inc. September 14, 2000

5.2 Source Terms

5.2 Source Terms


This section contains two examples of UDFs that are used to add source terms in FLUENT.
 Section 5.2.1: Spatially Dependent Porous Media
 Section 5.2.2: Swirl Generator in a Fluid Zone

5.2.1 Spatially Dependent Porous Media


This function generates an x-momentum source term that varies with y position as

source = 0:5C2yjvxjvx
Suppose
source = S =

Ajvx jvx

where
A = 0:5C2 y

Then
dS
dvx

Ajvx j Avx

d
(jv j)
dvx x

The source term returned is


source =

Ajvx jvx

and the derivative of the source term with respect to vx (true for both positive and
negative values of vx) is
dS
dvx

Fluent Inc. September 14, 2000

= 2Ajvxj

77

Examples of UDFs

/**************************************************************/
/* UDF for specifying an x-momentum source term
*/
/**************************************************************/
#include "udf.h"
#define C2 100.0
DEFINE_SOURCE(xmom_source, cell, thread, dS, eqn)
{
real x[ND_ND];
real con, source;
C_CENTROID(x, cell, thread);
con = C2*0.5*C_R(cell, thread)*x[1];
source = -con*fabs(C_U(cell, thread))*C_U(cell, thread);
dS[eqn] = -2.*con*fabs(C_U(cell, thread));
}

78

return source;

Fluent Inc. September 14, 2000

5.2 Source Terms

5.2.2 Swirl Generator in a Fluid Zone


This function is used to impart a solid-body rotation to the uid in a cell zone that
represents a swirl generator. The implicit and explicit parts of the source term are used
to force the solver to return the desired value of the swirl-velocity component. This
procedure can be used to set any variable to a desired value.
Consider the linearized equation
ap p

ap

@S

@ P

=
=

anb nb + S ()


anb nb + S (old ) +
anb nb + S (old )

@S
(  )
@ P !P;old
@S

@ P;old

(5.2-1)
(5.2-2)
(5.2-3)

If the source is set to


S ()
@S
@

= 1020 (P;desired
= 1020

P )

(5.2-4)
(5.2-5)

the solver will be forced to return the desired value of  as the solution at point P . This
is due to the fact that contributions from neighboring cells are lost to machine round-o .
To set this up, you need to enter both the entire linearized source term expression and the
derivative of the source term with respect to the variable being solved. For this example,
the linearized source term is
source = 1020 (r

vswirl )

where r
is the value you want to \ x", and vswirl is the variable being solved. In FLUENT,
the swirling component of the velocity is C WSWIRL. The derivative of the source term is
then
dS =

Fluent Inc. September 14, 2000

1020

79

Examples of UDFs

The C source code for this UDF is shown below.


/**************************************************************/
/* UDF for specifying a swirl-velocity source term
*/
/**************************************************************/
#include "udf.h"
#define OMEGA 50.
/* rotational speed of swirler */
#define WEIGHT 1.e20 /* weighting coefficients in linearized equation */
DEFINE_SOURCE(user_swirl, cell, thread, dS, eqn)
{
real w_vel, x[ND_ND], y, source;
C_CENTROID(x, cell, thread);
y = x[1];
w_vel = y*OMEGA; /* linear w-velocity at the cell */
source =
WEIGHT*(w_vel - C_WSWIRL(cell,thread));
dS[eqn] = -WEIGHT;
}

return source;

The macro C WSWIRL(cell,thread) is used to get the tangential velocity (in the  direction) for 2D axisymmetric swirl problems.

80

Fluent Inc. September 14, 2000

5.3 User-De ned Scalar Transport Equations

5.3 User-De ned Scalar Transport Equations


This section contains examples of UDFs that are used in conjunction with a user-de ned
scalar transport equation. To illustrate the use of UDFs with user-de ned scalars, an
alternate implementation of FLUENT's P-1 radiation model is presented.
The UDFs presented here de ne boundary conditions, source terms, and properties for
the user-de ned scalar transport equation. All of the UDFs are included in a single C
le, which is executed as a compiled UDF.
The de ning equations for incident radiation and energy that are used in the example
UDFs are shown below.
 Poisson equation for incident radiation, G:


r~  r~ G + S G = 0

(5.3-1)

= 3a + (31 C ) 
s

(5.3-2)

S G = a 4T 4
@S G
@G

(5.3-3)

(5.3-4)

 incident radiation boundary conditions:


qr =

0 0 Ew 
[4Ib(Tiw ) G0 + 0(G)]
A Ew + A


4
Tw4 Ew + A [G0
Gw =
Ew + A
0

Ew =

 energy equation source term:


ST

@S T
@T

c

Fluent Inc. September 14, 2000

2 (2


0 (G)]

w

= 16aT 3

(5.3-6)
(5.3-7)

w )

a 4T 4

(5.3-5)

(5.3-8)
(5.3-9)
81

Examples of UDFs

In addition to compiling and linking the UDFs, as described in Chapter 3, you will need
to enable the solution of a user-de ned scalar transport equation in FLUENT.
De ne ! Models !User-De ned Scalars...
See Section 8.10 of the FLUENT 5 User's Guide for more details.
/**************************************************************/
/* Implementation of the P1 model using user-defined scalars */
/**************************************************************/
#include "udf.h"
#include "sg.h"
#include "prop.h"
/* Define which user-defined scalars to use. */
enum
{
P1,
N_REQUIRED_UDS
};
static
static
static
static

real
real
real
real

abs_coeff = 1.0; /* absorption coefficient */


scat_coeff = 0.0; /* scattering coefficient */
las_coeff = 0.0; /* linear-anisotropic scattering coefficient */
epsilon_w = 1.0; /* wall emissivity */

DEFINE_ADJUST(p1_adjust, domain)
{
/* Make sure there are enough user defined-scalars. */
if (n_uds < N_REQUIRED_UDS)
Internal_Error("not enough user-defined scalars allocated");
}
DEFINE_SOURCE(energy_source, c, t, dS, eqn)
{
dS[eqn] = -16.*abs_coeff*SIGMA_SBC*pow(C_T(c,t),3.);
return -abs_coeff*(4.*SIGMA_SBC*pow(C_T(c,t),4.) - C_UDSI(c,t,P1));
}

82

Fluent Inc. September 14, 2000

5.3 User-De ned Scalar Transport Equations


DEFINE_SOURCE(p1_source, c, t, dS, eqn)
{
dS[eqn] = -abs_coeff;
return abs_coeff*(4.*SIGMA_SBC*pow(C_T(c,t),4.) - C_UDSI(c,t,P1));
}
DEFINE_DIFFUSIVITY(p1_diffusivity, c, t, i)
{
return 1./(3.*abs_coeff + (3. - las_coeff)*scat_coeff);
}
DEFINE_PROFILE(p1_bc, thread, position)
{

face_t f;
real A[ND_ND],At;
real dG[ND_ND],dr0[ND_ND],es[ND_ND],ds,A_by_es;
real aterm,alpha0,beta0,gamma0,Gsource,Ibw;
real Ew = epsilon_w/(2.*(2. - epsilon_w));
Thread *t0=thread->t0;
/* Do nothing if areas aren't computed yet or not next to fluid. */
if (!Data_Valid_P() || !FLUID_THREAD_P(t0)) return;
begin_f_loop (f,thread)
{
cell_t c0 = F_C0(f,thread);
BOUNDARY_FACE_GEOMETRY(f,thread,A,ds,es,A_by_es,dr0);
At = NV_MAG(A);

if (NULLP(T_STORAGE_R_NV(t0,SV_UDSI_G(P1))))
Gsource = 0.; /* if gradient not stored yet */
else
BOUNDARY_SECONDARY_GRADIENT_SOURCE(Gsource,SV_UDSI_G(P1),
dG,es,A_by_es,1.);
gamma0
alpha0
beta0
aterm

=
=
=
=

C_UDSI_DIFF(c0,t0,P1);
A_by_es/ds;
Gsource/alpha0;
alpha0*gamma0/At;

Ibw = SIGMA_SBC*pow(WALL_TEMP_OUTER(f,thread),4.)/M_PI;

Fluent Inc. September 14, 2000

83

Examples of UDFs

/* Specify the radiative heat flux. */


F_PROFILE(f,thread,position) =
aterm*Ew/(Ew + aterm)*(4.*M_PI*Ibw - C_UDSI(c0,t0,P1) + beta0);
}
end_f_loop (f,thread)
}

The DEFINE ADJUST function instructs FLUENT to check that the proper number of
user-de ned scalars has been de ned (in the User-De ned Scalars panel). To pass this
instruction to FLUENT, you will need to hook the p1 adjust UDF to the code using the
User-De ned Function Hooks panel.
De ne ! User-De ned ! Function Hooks...
See Section 4.6 for details.
The p1 diffusivity UDF speci es the incident radiation di usivity ( in Equation 5.3-2).
To use it in your FLUENT model, rst select user-de ned from the UDF Di usivity dropdown list in the Materials panel, and then select p1 di usivity from the User-De ned Functions panel.
The p1 source UDF speci es the source term for the incident radiation equation (S G
in Equation 5.3-3) and its derivative (Equation 5.3-4). The macro SIGMA SB gives the
value of the Stefan-Boltzmann constant,  = 5.672  10 8 W/m2K4 . To use this UDF in
your FLUENT model, select p1 source from the User de ned scalar-0 drop-down list under
Source Terms in the Fluid panel.
The energy source UDF speci es the source term for the energy equation (S T in Equation 5.3-8) and its derivative (Equation 5.3-9). To use this UDF in your model, select
energy source from the Energy drop-down list under Source Terms in the Fluid panel.
The p1 bc UDF speci es the incident radiation boundary condition (Equation 5.3-5). The
macro FLUID THREAD P(t0) is used to determine if a cell thread is a uid (rather than
a solid) thread. BOUNDARY FACE GEOMETRY(f,thread,A,ds,es,A by es,dr0) computes
the face area, cell, and face centroids, as well as the distance between the cell and face
centroids. The macro NULLP(T STORAGE R NV(t0,SV UDSI G(P1))) is used to check if
the gradient of the user-de ned scalar with index P1 has been allocated. To use this
UDF in your model, select p1 bc in the appropriate boundary condition panel.

84

Fluent Inc. September 14, 2000

5.4 Discrete Phase Model

5.4 Discrete Phase Model


This section contains three examples of UDFs that are used to customize the discrete
phase model in FLUENT. All three functions are executed as compiled UDFs, since they
are called at every particle step in FLUENT, and would require a signi cant amount of
CPU time if they were run as interpreted UDFs. They execute much faster when run in
compiled UDF mode.
 Section 5.4.1: Melting Index Along a Particle Trajectory
 Section 5.4.2: Magnetic Force on a Charged Particle
 Section 5.4.3: Particle Drag Coecient

5.4.1 Melting Index Along a Particle Trajectory


This example of a compiled UDF uses DPM SCALAR UPDATE to compute the melting index
along a particle trajectory:

melting index =

Zt
0

1 dt

(5.4-1)

Also included in this UDF is an initialization function DEFINE INIT that is used to
initialize the scalar variables. The DPM OUTPUT function is used to write out the melting
index at sample planes and surfaces. The macro NULL P, which expands to ((p) ==
NULL), checks if its argument is a null pointer.
/***********************************************************************/
/* UDF for computing the melting index along a particle trajectory
*/
/***********************************************************************/
#include "udf.h"
#include "sg.h"
#include "dpm.h"
static real viscosity_0;
DEFINE_INIT(melt_setup, domain)
{
/* if memory for the particle variable titles has not been
* allocated yet, do it now */
if (NULLP(user_particle_vars)) Init_User_Particle_Vars();
/* now set the name and label */

Fluent Inc. September 14, 2000

85

Examples of UDFs

strcpy(user_particle_vars[0].name,"melting-index");
strcpy(user_particle_vars[0].label,"Melting Index");

/* update the user scalar variables */


DEFINE_DPM_SCALAR_UPDATE(melting_index, cell, thread, initialize, p)
{
cphase_state_t *c = &(p->cphase);
if (initialize)
{
/* this is the initialization call, set:
* p->user[0] contains the melting index, initialize to 0
* viscosity_0 contains the viscosity at the start of a time step */

}
else
{

p->user[0] = 0.;
viscosity_0 = c->mu;

/* use a trapezoidal rule to integrate the melting index */


p->user[0] += P_DT(p) * .5 * (1/viscosity_0 + 1/c->mu);
/* save current fluid viscosity for start of next step */
viscosity_0 = c->mu;

/* write melting index when sorting particles at surfaces */


DEFINE_DPM_OUTPUT(melting_output, header, fp, p, thread, plane)
{
char name[100];
if (header)
{
if (NNULLP(thread))
cxprintf(fp,"(%s %d)\n",thread->head->dpm_summary.sort_file_name,11);
else
cxprintf(fp,"(%s %d)\n",plane->sort_file_name,11);
cxprintf(fp,"(%10s %10s %10s %10s %10s %10s %10s"
" %10s %10s %10s %10s %s)\n",
"X","Y","Z","U","V","W","diameter","T","mass-flow",

86

Fluent Inc. September 14, 2000

5.4 Discrete Phase Model

}
else
{

"time","melt-index","name");

sprintf(name,"%s:%d",p->injection->name,p->part_id);
cxprintf(fp,
"((%10.6g %10.6g %10.6g %10.6g %10.6g %10.6g "
"%10.6g %10.6g %10.6g %10.6g %10.6g) %s)\n",
p->state.pos[0], p->state.pos[1], p->state.pos[2],
p->state.V[0], p->state.V[1], p->state.V[2],
p->state.diam, p->state.temp, p->flow_rate, p->state.time,
p->user[0], name);

Fluent Inc. September 14, 2000

87

Examples of UDFs

5.4.2 Magnetic Force on a Charged Particle


The UDF presented below is another example of a compiled UDF. A charged particle is
introduced upstream, into a laminar ow, and travels downstream until t= tstart, when
a magnetic eld is applied. The particle takes on an approximately circular path (not an
exact circular path since the speed and magnetic force vary as the particle is slowed by
the surrounding uid).
The macro P TIME(p) gives the current time for a particle traveling along a trajectory,
which is pointed to by pointer p.
/***********************************************************************/
/* UDF for computing the magnetic force on a charged particle
*/
/***********************************************************************/
#include "udf.h"
#include "dpm.h"
#define Q 1.0
#define BZ 3.0
#define TSTART 18.0

/* particle electric charge


*/
/* z component of magnetic field */
/* field applied at t = tstart
*/

/* Calculate magnetic force on charged particle. Magnetic


/* force is particle charge times cross product of particle
/* velocity with magnetic field: Fx= q*bz*Vy, Fy= -q*bz*Vx

*/
*/
*/

DEFINE_DPM_BODY_FORCE(particle_body_force, p, i)
{
float bforce;
if(P_TIME(p)>=TSTART)
{
if(i==0) bforce=Q*BZ*P_VEL(p)[1];
else if(i==1) bforce=-Q*BZ*P_VEL(p)[0];
}
else
bforce=0.0;
/* an acceleration should be returned */
return (bforce/P_MASS(p));
}

88

Fluent Inc. September 14, 2000

5.4 Discrete Phase Model

5.4.3 Particle Drag Coecient


This UDF computes the drag force on a particle, and is a variation of the body force
UDF presented in Section 5.4.2. The ow is the same, but a di erent curve is used to
describe the particle drag. This UDF is executed as a compiled UDF.
/***********************************************************************/
/* UDF for computing particle drag coefficient (18 Cd Re/24)
*/
/* curve as suggested by R. Clift, J. R. Grace and M.E. Weber
*/
/* "Bubbles, Drops, and Particles" (1978)
*/
/***********************************************************************/
#include "udf.h"
#include "dpm.h"
DEFINE_DPM_DRAG(particle_drag_force, Re, p)
{
float w, drag_force;

if (Re < 0.01)


{
drag_force=18.0;
return (drag_force);
}
else if (Re < 20.0)
{
w = log10(Re);
drag_force = 18.0 + 2.367*pow(Re,0.82-0.05*w) ;
return (drag_force);
}
else
/* Note: suggested valid range 20 < Re < 260 */
{
drag_force = 18.0 + 3.483*pow(Re,0.6305) ;
return (drag_force);
}

Fluent Inc. September 14, 2000

89

Examples of UDFs

5.5 Solution Initialization


The initialization function (DEFINE INIT) is called immediately after you initialize your
ow eld, so it can be used to set the initial values of ow quantities. The following
interpreted UDF demonstrates how you can use a user-de ned function to initialize your
solution.
/***********************************************************************/
/* UDF for initializing flow field variables
*/
/***********************************************************************/
#include "udf.h"
DEFINE_INIT(my_init_function, domain)
{
cell_t c;
Thread *thread;
real xc[ND_ND];

thread_loop_c (thread,domain)
{
begin_c_loop_all (c,thread)
{
C_CENTROID(xc,c,thread);
if (sqrt(ND_SUM(pow(xc[0] - 0.5,2.),
pow(xc[1] - 0.5,2.),
pow(xc[2] - 0.5,2.))) < 0.25)
C_T(c,thread) = 400.;
else
C_T(c,thread) = 300.;
}
end_c_loop_all (c,thread)
}

The macro ND SUM(a, b, c) that is used in the UDF computes the sum of the rst two
arguments (2D) or all three arguments (3D). It is useful for writing functions involving
vector operations so that the same function can be used for 2D and 3D. For a 2D case,
the third argument is ignored.

90

Fluent Inc. September 14, 2000

5.6 Wall Heat Flux

5.6 Wall Heat Flux


The wall heat ux function (DEFINE HEAT FLUX) can be used to modify the way that the
solver computes the heat ux between a wall and the neighboring uid cells. For example,
you can customize the heat transfer coecient or the law-of-the-wall for temperature.
The UDF presented below uses an internal heat transfer coecient to specify the wall
heat ux. It is another example of a UDF that utilizes the ADJUST function to adjust a
computed value, and it is executed as a compiled UDF.
The di usive heat ux coecients (cid) are speci ed in this UDF. The di usive heat
ux (qid) will then be computed by FLUENT using the following equation:
qid = cid[0] + cid[1]*C_T(c0,t0) - cid[2]*F_T(f,t) - cid[3]*pow(F_T(f,t),4)
/***********************************************************************/
/* UDF for specifying the diffusive heat flux between a wall and
*/
/* neighboring cells
*/
/***********************************************************************/
#include "udf.h"
static real h = 0.; /* heat transfer coefficient (W/m^2 C) */
DEFINE_ADJUST(htc_adjust, domain)
{
/* Define the heat transfer coefficient. */
}

h = 120;

DEFINE_HEAT_FLUX(heat_flux, f, t, c0, t0, cid, cir)


{
cid[0] = 0.;
cid[1] = h;
cid[2] = h;
cid[3] = 0.;
}

Fluent Inc. September 14, 2000

91

Examples of UDFs

5.7 Postprocessing Using User-De ned Scalars


The adjust function (DEFINE ADJUST) is called at the beginning of an iteration before
solution of velocities, pressure, and other quantities begins. It can be used, for example,
to integrate a scalar quantity over the domain and adjust a boundary condition based
on the result.
Below is an example of a compiled UDF that computes the gradient of temperature to
the fourth power, and stores its magnitude in a user-de ned scalar. The computed temperature gradient can, for example, be subsequently used to plot contours. Although the
practical application of this UDF is questionable, its purpose here is to show the methodology of computing gradients of arbitrary quantities that can be used for postprocessing.
/***********************************************************************/
/* UDF for computing the magnitude of the gradient of T^4
*/
/***********************************************************************/
#include "udf.h"
/* Define which user-defined scalars to use. */
enum
{
T4,
MAG_GRAD_T4,
N_REQUIRED_UDS
};
DEFINE_ADJUST(adjust_fcn, domain)
{
Thread *t;
cell_t c;
face_t f;
/* Make sure there are enough user-defined scalars. */
if (n_uds < N_REQUIRED_UDS)
Internal_Error("not enough user-defined scalars allocated");
/* Fill first UDS with temperature raised to fourth power. */
thread_loop_c (t,domain)
{
if (NULL != THREAD_STORAGE(t,SV_UDS_I(T4)))

92

Fluent Inc. September 14, 2000

5.7 Postprocessing Using User-De ned Scalars


{

begin_c_loop (c,t)
{
real T = C_T(c,t);
C_UDSI(c,t,T4) = pow(T,4.);
}
end_c_loop (c,t)

thread_loop_f (t,domain)
{
if (NULL != THREAD_STORAGE(t,SV_UDS_I(T4)))
{
begin_f_loop (f,t)
{
real T = 0.;
if (NULL != THREAD_STORAGE(t,SV_T))
T = F_T(f,t);
else if (NULL != THREAD_STORAGE(t->t0,SV_T))
T = C_T(F_C0(f,t),t->t0);
F_UDSI(f,t,T4) = pow(T,4.);
}
end_f_loop (f,t)
}
}
/* Fill second UDS with magnitude of gradient. */
thread_loop_c (t,domain)
{
if (NULL != THREAD_STORAGE(t,SV_UDS_I(T4)) &&
NULL != T_STORAGE_R_NV(t,SV_UDSI_G(T4)))
{
begin_c_loop (c,t)
{
C_UDSI(c,t,MAG_GRAD_T4) = NV_MAG(C_UDSI_G(c,t,T4));
}
end_c_loop (c,t)
}
}
thread_loop_f (t,domain)
{
if (NULL != THREAD_STORAGE(t,SV_UDS_I(T4)) &&

Fluent Inc. September 14, 2000

93

Examples of UDFs
NULL != T_STORAGE_R_NV(t->t0,SV_UDSI_G(T4)))

begin_f_loop (f,t)
{
F_UDSI(f,t,MAG_GRAD_T4) = C_UDSI(F_C0(f,t),t->t0,MAG_GRAD_T4);
}
end_f_loop (f,t)

The conditional statement if (NULL != THREAD STORAGE(t,SV UDS I(T4))) is used to


check if the storage for the user-de ned scalar with index T4 has been allocated, while
NULL != T STORAGE R NV(t,SV UDSI G(T4)) checks whether the storage of the gradient
of the user-de ned scalar with index T4 has been allocated.
In addition to compiling and linking this UDF, as described in Chapter 3, you will need
to enable the solution of a user-de ned scalar transport equation in FLUENT.
De ne ! Models !User-De ned Scalars...
See Section 8.10 of the FLUENT 5 User's Guide for more details.

94

Fluent Inc. September 14, 2000

5.8 Executing On Demand

5.8 Executing On Demand


The following UDF, named demo calc, computes and prints out the minimum, maximum,
and average temperatures for the current data eld, and then computes a temperature
function
f (T ) =

Tmax

Tmin
Tmin

and stores it in user memory location 0 (which is allocated as described in Section 4.13).
Once you execute the UDF (as described in Section 4.12), the eld values for f (T ) will
be available in the drop-down lists in postprocessing panels in FLUENT. You can select
this eld by choosing udm-0 in the User De ned Memory... category. If you write a data
le after executing the UDF, the user-de ned memory eld will be saved to the data le.
The C source code (demand.c) for this UDF is shown below.
/**********************************************************************/
/* demand.c
*/
/* UDF to calculate temperature field function and store in
*/
/* user-defined memory. Also print min, max, avg temperatures.
*/
/**********************************************************************/
#include "udf.h"
extern Domain* domain;
DEFINE_ON_DEMAND(demo_calc)
{
float tavg = 0.;
float tmax = 0.;
float tmin = 0.;
float temp,volume,vol_tot;
Thread *t;
cell_t c;
/* Loop over all cells in the domain */
thread_loop_c(t,domain)
{
/* Compute max, min, volume-averaged temperature */
begin_c_loop(c,t)
{

Fluent Inc. September 14, 2000

95

Examples of UDFs
volume = C_VOLUME(c,t);
temp = C_T(c,t);

/* get cell volume */


/* 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)

*/
*/

begin_c_loop(c,t)
{
temp = C_T(c,t);
C_UDMI(c,t,0) = (temp-tmin)/(tmax-tmin);
}
end_c_loop(c,t)
}

The extern Domain* domain line de nes the domain, since it is not explicitly passed
as an argument of the function. The function, named demo calc, does not take any
explicit arguments. Within the function body, rst the variables to be used are de ned
and initialized. Following the variable declarations, a looping macro is used to loop over
each thread (zone) in the domain. Within that loop another loop is used to loop over
each cell in each thread. Within the inner loop, the total cell volume and the minimum,
maximum, and volume-averaged temperature are computed. These computed values are
printed to the FLUENT console. Then a second loop over each cell in each thread is used
to compute the function f (T ) and store it in user-de ned memory location 0.

96

Fluent Inc. September 14, 2000

Chapter 6. Sample Applications


This chapter contains sample applications of UDFs in FLUENT.





Section 6.1: Boundary Condition Applications


Section 6.2: Source Term Application
Section 6.3: Physical Property Application
Section 6.4: Reaction Rate Application

All of the examples in this chapter are taken directly from Chapter 24 of the FLUENT
5 User's Guide. The volume reaction rate example (Section 6.4) illustrates a problem
setup using a compiled UDF. The remaining applications use UDFs that are executed as
interpreted UDFs.
6.1 Boundary Condition Applications
This section contains two applications of boundary condition UDFs. Both are executed
as interpreted UDFs in FLUENT.
 Section 6.1.1: Parabolic Velocity Inlet Pro le for a Turbine Vane
 Section 6.1.2: Transient Velocity Inlet Pro le for Flow in a Tube

6.1.1 Parabolic Velocity Inlet Pro le in a Turbine Vane


Consider the turbine vane illustrated in Figure 6.1.1. An unstructured grid is used to
model the ow eld surrounding the vane. The domain extends from a periodic boundary
on the bottom to an identical one on the top, a velocity inlet on the left, and a pressure
outlet on the right.
A ow eld in which a constant x velocity is applied at the inlet will be compared with
one where a parabolic x velocity pro le is applied. While the application of a pro le using
a piecewise-linear pro le is available with the boundary pro les option, the speci cation
of a polynomial can only be accomplished by a user-de ned function.
The results of a constant-velocity applied eld (of 20 m/sec) at the inlet are shown in
Figures 6.1.2 and 6.1.3. The initial constant velocity eld is distorted as the ow moves
around the turbine vane.

Sample Applications

Turbine Vane (1551 cells, 2405 faces, 893 nodes)


Grid

Figure 6.1.1: The Grid for the Turbine Vane Example

5.98e+01
5.42e+01
4.86e+01
4.30e+01
3.74e+01
3.19e+01
2.63e+01
2.07e+01
1.51e+01
9.54e+00
3.96e+00

Turbine Vane (1551 cells, 2405 faces, 893 nodes)


Contours of Velocity Magnitude (m/s)

Figure 6.1.2: Velocity Magnitude Contours for a Constant Inlet x Velocity

98

Fluent Inc. September 14, 2000

6.1 Boundary Condition Applications

6.11e+01
5.52e+01
4.93e+01
4.34e+01
3.75e+01
3.16e+01
2.57e+01
1.98e+01
1.39e+01
7.96e+00
2.05e+00

Turbine Vane (1551 cells, 2405 faces, 893 nodes)


Velocity Vectors Colored By Velocity Magnitude (m/s)

Figure 6.1.3: Velocity Vectors for a Constant Inlet x Velocity


The inlet x velocity will now be described by the following pro le:
vx = 20

y 2

20 0:0745
where the variable y is 0.0 at the center of the inlet, and extends to values of  0.0745 m
at the top and bottom. Thus the x velocity will be 20 m/sec at the center of the inlet,
and 0 at the edges.
A user-de ned function is used to introduce this parabolic pro le at the inlet. The C
source code (vprofile.c) for this UDF is shown below. This UDF makes use of Fluentprovided solver functions that are described in Section 2.10.
/*************************************************************************/
/* vprofile.c
*/
/* UDF for specifying a steady-state velocity profile boundary condition */
/*************************************************************************/
#include "udf.h"
DEFINE_PROFILE(inlet_x_velocity, thread, position)
{
real x[ND_ND]; /* this will hold the position vector */
real y;
face_t f;

Fluent Inc. September 14, 2000

99

Sample Applications

begin_f_loop(f, thread)
{
F_CENTROID(x,f,thread);
y = x[1];
F_PROFILE(f, thread, position) = 20. - y*y/(.0745*.0745)*20.;
}
end_f_loop(f, thread)

The function named inlet x velocity has two arguments: thread and position.
Thread is a pointer to the face's thread, and position is an integer that is a numerical
label for the variable being set within each loop.
The function begins by declaring variable f as a face t data type. A one-dimensional
array x and variable y are declared as real data types. A looping macro is then used to
loop over each face in the zone to create a pro le, or an array of data. Within each loop,
F CENTROID outputs the value of the face centroid (array x) for the face with index f
that is on the thread pointed to by thread. The y coordinate stored in x[1] is assigned
to variable y, and is then used to calculate the x velocity. This value is then assigned
to F PROFILE, which uses the integer position (passed to it by the solver based on your
selection of the UDF as the boundary condition for x velocity in the Velocity Inlet panel)
to set the x velocity face value in memory.
To make use of this interpreted UDF in FLUENT, you must rst compile it.
De ne ! User-De ned ! Functions !Interpreted...

In the Interpreted UDFs panel, name your function in the Source File Name eld. If
necessary, enter your C preprocessor type in the CPP Command Name eld and the size
of the stack under Stack Size. Click on Compile and then Close the panel. By default, an
assembly listing will be displayed in your console window as the function compiles.
100

Fluent Inc. September 14, 2000

6.1 Boundary Condition Applications

To select this user-de ned function as the velocity boundary condition for the zone of
choice, open the Velocity Inlet panel.

In the X-Velocity drop-down list, select udf inlet x velocity, the name that was given to the
function above. This function will now be used, rather than the value of (in this example)
20 that appears in the X-Velocity eld. Click on OK to accept the new boundary condition
and close the panel.
After the solution is run to convergence, a revised velocity eld is obtained as shown in
Figures 6.1.4 and 6.1.5. The velocity eld shows a maximum at the center of the inlet,
which drops to zero at the edges.

Fluent Inc. September 14, 2000

101

Sample Applications

4.46e+01
4.05e+01
3.64e+01
3.23e+01
2.83e+01
2.42e+01
2.01e+01
1.60e+01
1.19e+01
7.78e+00
3.68e+00

Turbine Vane (1551 cells, 2405 faces, 893 nodes)


Contours of Velocity Magnitude (m/s)

Figure 6.1.4: Velocity Magnitude Contours for a Parabolic Inlet x Velocity


4.56e+01
4.13e+01
3.70e+01
3.26e+01
2.83e+01
2.40e+01
1.97e+01
1.53e+01
1.10e+01
6.68e+00
2.35e+00

Turbine Vane (1551 cells, 2405 faces, 893 nodes)


Velocity Vectors Colored By Velocity Magnitude (m/s)

Figure 6.1.5: Velocity Vectors for a Parabolic Inlet x Velocity

102

Fluent Inc. September 14, 2000

6.1 Boundary Condition Applications

6.1.2 Transient Velocity Inlet Pro le for Flow in a Tube


In this example, a temporally periodic velocity boundary condition will be applied to the
inlet of a tube using a UDF. The velocity has the form
vx = v0 + A sin(!t)

(6.1-1)
The tube is 1 m long with a radius of 0.2 m. It is assumed to be lled with air with a
density of 1 kg/m3 and a viscosity of 210 5 kg/m-s. The velocity of the air uctuates
about an equilibrium value, v0 , of 20 m/s, with an amplitude of 5 m/s and at a frequency
of 10 rad/s.
The C source code (unsteady.c) for the UDF is shown below.
/***********************************************************************/
/* unsteady.c
*/
/* UDF for specifying a transient velocity profile boundary condition */
/***********************************************************************/
#include "udf.h"
DEFINE_PROFILE(unsteady_velocity, thread, position)
{
face_t f;

begin_f_loop(f, thread)
{
real t = RP_Get_Real("flow-time");
F_PROFILE(f, thread, position) = 20. + 5.0*sin(10.*t);
}
end_f_loop(f, thread)

The function that is de ned in the UDF by the DEFINE macro is named unsteady velocity.
A real variable, flow time, is created for the time. The function RP GET REAL("flow-time")
is used to look up the real ow time from a list that is kept by the Scheme interpreter.
Before you can compile this UDF, you must specify an unsteady ow calculation.
De ne ! Models !Solver...

Fluent Inc. September 14, 2000

103

Sample Applications

Next you can open the Interpreted UDFs panel. Enter the name of the function in the text
entry box under Source File Name and, if necessary, the name of your C preprocessor.
Click on Compile and then Close the panel.
De ne ! User-De ned ! Functions !Interpreted...

The sinusoidal velocity boundary condition de ned by the UDF can now be selected
for the X-Velocity in the inlet zone. In the Velocity Inlet panel, simply select udf unsteady velocity in the drop-down list to the right of the X-Velocity eld, and click on
OK.

104

Fluent Inc. September 14, 2000

6.1 Boundary Condition Applications

The time-stepping parameters are set in the Iterate panel.


Solve !Iterate...

In this example, a Time Step Size of 0.0314 s is used so that 20 time steps will complete
a full period of oscillation in the inlet velocity. The number of iterations to be performed
at each time step is limited to 20. This number of iterations is not enough to obtain
a converged ow eld in the early stages of the solution, but will very likely result in
converged time steps after a few time steps have passed. The UDF Pro le Update Interval
is set to 1 so that the velocity will be updated every iteration. After 60 time steps (or 3
periods) are complete, you can examine the velocity magnitude across the pressure outlet
for its response to the oscillating inlet condition.

Fluent Inc. September 14, 2000

105

Sample Applications

To collect this information during the calculation, open the Surface Monitors panel before
beginning to iterate.
Solve ! Monitors !Surface...

Increase the Surface Monitors index to 1. This will enable you to de ne the parameters
of monitor-1 (which you could rename, if desired, in the text entry box under Name).
Select Plot so that the selected quantity will be plotted as the calculation proceeds. Select
Print to see the changing values of the selected quantity in the console window. Select
Write so that the information will be written to a le, which will be given the name
monitor-1.out. (If you change the name of the monitor, that name will be used as the
pre x for the output le.)
Under Every, you can choose Iteration, Time Step, or Flow Time. To monitor the result
of each time step, you should choose the Time Step option. By clicking on De ne... you
can specify the quantity to be monitored in the De ne Surface Monitor panel.

106

Fluent Inc. September 14, 2000

6.1 Boundary Condition Applications

In this example, Velocity... and Velocity Magnitude are chosen in the drop-down lists
under Report Of. The location of the report is pressure-outlet-5, which is selected in the
Surfaces list. A simple Average is chosen in the Report Type drop-down list, with the Flow
Time chosen in the X Axis drop-down list.
Once the desired number of iterations has been completed, the monitor should appear in
the chosen plot window. Alternatively, you can read the le by opening the File XY Plot
panel.
Plot !File...

You can read the output le by typing its name in the text entry box under Files and
clicking on Add.... By selecting this le and clicking on Plot, you can obtain the plot

c

Fluent Inc. September 14, 2000

107

Sample Applications

shown in Figure 6.1.6.


2.60e+01
2.50e+01
2.40e+01
2.30e+01
2.20e+01
2.10e+01

Average
Velocity
Magnitude

2.00e+01
1.90e+01
1.80e+01
1.70e+01
1.60e+01
1.50e+01
0

0.2

0.4

0.6

0.8

1.2

1.4

1.6

1.8

Flow Time

Average Velocity Magnitude (Time=1.8840e+00)

Figure 6.1.6: Average Velocity Magnitude at the Pressure Outlet


The gure nicely illustrates that the velocity oscillates around the equilibrium value,
20 m/s, with an amplitude of 5 m/s, as expected.

108

Fluent Inc. September 14, 2000

6.2 Source Term Application

6.2 Source Term Application


This section contains an application of a source term UDF. It is executed as an interpreted
UDF in FLUENT.
6.2.1 Adding a Momentum Source to a Duct Flow
When a source term is being modeled with a user-de ned function, it is important to
understand the context in which the UDF is called. When you add a source term,
FLUENT will call your function as it performs a global loop on cells. Your function
should only compute the source term and return it to the main code.
In this example, a momentum source will be added to a 2D Cartesian duct ow. The
duct is 4 m long and 2 m wide, and will be modeled with a symmetry boundary through
the middle. Liquid metal (with properties listed in Table 6.2.1) enters the duct at the left
with a velocity of 1 mm/s at a temperature of 290 K. After the metal has traveled 0.5 m
along the duct, it is exposed to a cooling wall, which is held at a constant temperature
of 280 K. To simulate the freezing of the metal, a momentum source is applied to the
metal as soon as its temperature falls below 288 K. This source is proportional to the x
component of the velocity, vx, and has the opposite sign:
Sx = Cvx

(6.2-1)
where C is a constant. As the liquid cools, its motion will be reduced to zero, simulating
the formation of the solid. (In this simple example, the energy equation will not be
customized to account for the latent heat of freezing. The velocity eld will be used only
as an indicator of the solidi cation region.)
The solver linearizes source terms in order to enhance the stability and convergence of a
solution. To allow the solver to do this, you need to specify the dependent relationship
between the source and solution variables in your UDF, in the form of derivatives. The
source term, Sx, depends only on the solution variable, vx. Its derivative with respect to
vx is
@Sx
@vx

Fluent Inc. September 14, 2000

(6.2-2)

109

Sample Applications

Table 6.2.1: Properties of the Liquid Metal


Property

Density
Viscosity
Speci c Heat
Thermal Conductivity

Value

8000 kg/m3
5.5 10 3 kg/m-s
680 J/kg-K
30 W/m-K

To add the source term and specify its derivative, the following C function is used.
#include "udf.h"
#define CON 20.0
DEFINE_SOURCE(cell_x_source, cell, thread, dS, eqn)
{
real source;
if (C_T(cell,thread) <= 288.)
{
/* source term */
source = -CON*C_U(cell,thread);
/* derivative of source term w.r.t. x-velocity. */
dS[eqn] = -CON;

}
else
source = dS[eqn] = 0.;
}

return source;

The function is called cell x source, and it is de ned on a cell. The constant C in
Equation 6.2-1 is called CON in the function, and it is given a numerical value of 20
kg/m3-s, which will result in the desired units of N/m3 for the source. The temperature
at the cell is C T(cell,thread). The function checks to see if the temperature is below
(or equal to) 288 K. If it is, the source is computed according to Equation 6.2-1 (C U
returns the value of the x velocity of the cell). If it is not, the source is set to 0.0. At
the end of the function, the appropriate value for the source is returned.
This function is executed as an interpreted UDF (see Section 3.2). To include it in the
calculation, you will specify it as a source term in the Fluid panel.
110

Fluent Inc. September 14, 2000

6.2 Source Term Application

To include a source term in the uid, activate the Source Terms button. You can then
add source terms for Mass, Momentum, and Energy (visible by moving the slide bar).
(Note that in other applications, sources for other problem variables would also become
available at this time.) To select the user-de ned source for the X Momentum, select udf
cell x source in the drop-down list and click on OK.
Once the solution has converged, you can view contours of static temperature to see the
cooling e ects of the wall on the liquid metal as it moves through the duct (Figure 6.2.1).

Fluent Inc. September 14, 2000

111

Sample Applications
2.90e+02
2.89e+02
2.87e+02
2.86e+02
2.84e+02
2.83e+02
2.81e+02
2.80e+02
2.78e+02
2.77e+02
2.75e+02
Contours of Static Temperature (k)
Source Term Application

Figure 6.2.1: Temperature Contours Illustrating Liquid Metal Cooling


Contours of velocity magnitude (Figure 6.2.2) show that the liquid in the cool region
near the wall has indeed come to rest to simulate solidi cation taking place.
2.13e-03
1.92e-03
1.70e-03
1.49e-03
1.28e-03
1.06e-03
8.51e-04
6.38e-04
4.26e-04
2.13e-04
0.00e+00
Contours of Velocity Magnitude (m/s)
Source Term Application

Figure 6.2.2: Velocity Magnitude Contours Suggesting Solidi cation

112

Fluent Inc. September 14, 2000

6.2 Source Term Application

The solidi cation is further illustrated by line contours of stream function (Figure 6.2.3).
8.00e+00
7.20e+00
6.40e+00
5.60e+00
4.80e+00
4.00e+00
3.20e+00
2.40e+00
1.60e+00
8.00e-01
0.00e+00
Contours of Stream Function (kg/s)
Source Term Application

Figure 6.2.3: Stream Function Contours Suggesting Solidi cation


To more accurately predict the freezing of a liquid in this manner, an energy source
term would be needed, as would a more accurate value for the constant appearing in
Equation 6.2-1.

Fluent Inc. September 14, 2000

113

Sample Applications

6.3 Physical Property Application


This section contains an application of a physical property UDF. It is executed as an
interpreted UDF in FLUENT.
6.3.1 Solidi cation via a Temperature-Dependent Viscosity
User-de ned functions for properties (as well as sources) are called from within a loop on
cells. For this reason, a UDF that speci es a property is only required to compute the
property for a single cell and return the value.
This sample UDF is applied to the same problem presented in Section 6.2.1, except in this
case the UDF generates a variable viscosity pro le to simulate solidi cation. The viscosity
in the warm (T > 288 K) uid has a molecular value for the liquid (5.5 10 3kg/m-s),
while the viscosity for the cooler region (T < 286 K) has a much larger value (1.0 kg/ms). In the intermediate temperature range (286 K  T  288 K), the viscosity follows a
linear pro le that extends between the two values given above:
 = 143:2135

0:49725T
(6.3-1)
This model is based on the assumption that as the liquid cools and rapidly becomes more
viscous, its velocity will decrease, thereby simulating solidi cation. Here, no correction
is made for the energy eld to include the latent heat of freezing.
The C source code (viscosity.c) for this example is shown below.
/***********************************************************************/
/* viscosity.c
*/
/* UDF for specifying a temperature-dependent viscosity property
*/
/***********************************************************************/
#include "udf.h"
DEFINE_PROPERTY(cell_viscosity, cell, thread)
{
real mu_lam;
real temp = C_T(cell, thread);
if (temp > 288.)
mu_lam = 5.5e-3;
else if (temp > 286.)
mu_lam = 143.2135 - 0.49725 * temp;
else

114

Fluent Inc. September 14, 2000

6.3 Physical Property Application


mu_lam = 1.;
}

return mu_lam;

The function cell viscosity is de ned on a cell and uses the DEFINE PROPERTY macro.
Two real variables are introduced: temp, the value of C T(cell,thread), and mu lam,
the laminar viscosity computed by the function. The value of the temperature is checked,
and based upon the range into which it falls, the appropriate value of mu lam is computed.
At the end of the function, the computed value for mu lam is returned.
To make use of a user-de ned property, you will use the Materials panel. In the drop-down
list for Viscosity, select the user-de ned option.

Once you select this option, the User-De ned Functions panel opens, from which you
can select the appropriate function name. In this example, only one is available, but in
another example, you might have several functions from which to choose. (Recall that if
you need to compile more than one interpreted UDF, the functions can be concatenated
prior to compiling. See Chapter 3 for details.)

c

Fluent Inc. September 14, 2000

115

Sample Applications

The results of this model are similar to those obtained in Section 6.2.1. Figure 6.3.1
shows the viscosity eld resulting from the application of the user-de ned function. The
viscosity varies rapidly over a narrow spatial band from a constant value of 0.0055 to
1.0 kg/m-s.
The velocity eld (Figure 6.3.2) demonstrates that the liquid slows down in response to
the increased viscosity, as expected. In this model, there is a large \mushy" region, in
which the motion of the uid gradually decreases. This is in contrast to the rst model,
in which a momentum source was applied and a more abrupt change in the uid motion
was observed.
1.00e+00
9.01e-01
8.01e-01
7.02e-01
6.02e-01
5.03e-01
4.03e-01
3.04e-01
2.04e-01
1.05e-01
5.50e-03
Contours of Molecular Viscosity (kg/m-s)
Physical Property Application

Figure 6.3.1: Laminar Viscosity Generated by a User-De ned Function

116

Fluent Inc. September 14, 2000

6.3 Physical Property Application

1.73e-03
1.55e-03
1.38e-03
1.21e-03
1.04e-03
8.63e-04
6.91e-04
5.18e-04
3.45e-04
1.73e-04
0.00e+00
Contours of Velocity Magnitude (m/s)
Physical Property Application

Figure 6.3.2: Contours of Velocity Magnitude Resulting from a User-De ned Viscosity

8.00e+00
7.20e+00
6.40e+00
5.60e+00
4.80e+00
4.00e+00
3.20e+00
2.40e+00
1.60e+00
8.00e-01
0.00e+00
Contours of Stream Function (kg/s)
Physical Property Application

Figure 6.3.3: Stream Function Contours Suggesting Solidi cation

Fluent Inc. September 14, 2000

117

Sample Applications

6.4 Reaction Rate Application


This section contains an application of a reaction rate UDF. It is executed as a compiled
UDF in FLUENT.
6.4.1 A Custom Volume Reaction Rate
As an example of a compiled UDF, a custom volume reaction rate for a simple system
of two gaseous species is considered. The species are named species-a and species-b.
The reaction rate is one that converts species-a into species-b at a rate given by the
following expression:
R=

K1 Xa
(1 + K2Xa )2

(6.4-1)

where Xa is the mass fraction of species-a, and K1 and K2 are constants.


The 2D (planar) domain consists of a 90-degree bend. The duct is 16 inches wide and
approximately 114 inches long. A 6-inch-thick porous region covers the bottom and
right-hand wall, and the reaction takes place in the porous region only. The species
in the duct have identical properties. The density is 1.0 kg/m3, and the viscosity is
1.7210 5 kg/m-s.
The outline of the domain is shown in Figure 6.4.1. The porous medium is the region
below and to the right of the line that extends from the inlet on the left to the pressure
outlet at the top of the domain.

Grid

Figure 6.4.1: The Outline of the 2D Duct


Through the inlet on the left, gas that is purely species-a enters with an x velocity of
0.1 m/s. The gas enters both the open region on the top of the porous medium and the
118

Fluent Inc. September 14, 2000

6.4 Reaction Rate Application

porous medium itself, where there is an inertial resistance of 5 m 1 in each of the two
coordinate directions. The laminar ow eld (Figure 6.4.2) shows that most of the gas
is diverted from the porous region into the open region.
1.62e+00
1.46e+00
1.30e+00
1.14e+00
9.73e-01
8.11e-01
6.49e-01
4.87e-01
3.24e-01
1.62e-01
0.00e+00

Contours of Stream Function (kg/s)

Figure 6.4.2: Streamlines for the 2D Duct with a Porous Region


The ow pattern is further substantiated by the vector plot shown in Figure 6.4.3. The
ow in the porous region is considerably slower than that in the open region.
2.34e-01
2.10e-01
1.87e-01
1.64e-01
1.40e-01
1.17e-01
9.38e-02
7.05e-02
4.72e-02
2.39e-02
5.73e-04

Velocity Vectors Colored By Velocity Magnitude (m/s)

Figure 6.4.3: Velocity Vectors for the 2D Duct with a Porous Region
The C le (rate.c) that contains the UDF used to model the reaction taking place in
the porous region is shown below.

c

Fluent Inc. September 14, 2000

119

Sample Applications

/**************************************************************/
/* rate.c
*/
/* UDF for specifying a reaction rate in a porous media
*/
/**************************************************************/
#include "udf.h"
#define K1 2.0e-2
#define K2 5.
DEFINE_VR_RATE(user_rate, cell, thread, r, mole_weight, species_mf, rate, rr_t)
{
real s1 = species_mf[0];
real mw1 = mole_weight[0];

if (FLUID_THREAD_P(thread) && THREAD_VAR(thread).fluid.porous)


*rate = K1*s1/pow((1.+K2*s1),2.0)/mw1;
else
*rate = 0.;

In the C function, a function named user rate is de ned on a cell for a given species
mass fraction. The UDF performs a test to check for the porous region, and only applies
the reaction rate equation to the porous region.
The macro FLUID THREAD P(thread) is used to determine if a cell thread is a uid (rather
than a solid) thread. The variable THREAD VAR(thread).fluid.porous is used to check
if a uid cell thread is a porous region.
To use this UDF, set up a directory named librate to hold the library directory structure. Then build a shared library as described in Chapter 3.
Next, start your FLUENT session, and either read in your case le or set it up. Open the
library that was built during the Makefile process, and link it to the FLUENT executable
by specifying librate as the Library Name in the Compiled UDFs panel and clicking Open.

120

Fluent Inc. September 14, 2000

6.4 Reaction Rate Application


De ne

User-De ned

Functions

! Compiled...

Now you can specify user rate as the reaction rate by selecting it in the Volume Reaction
Rate Function drop-down list in the User-De ned Function Hooks panel.
De ne ! User-De ned ! Function Hooks...

Initialize and run the calculation. The converged solution for the mass fraction of
species-a is shown in Figure 6.4.4. The gas that moves through the porous region
is gradually converted to species-b in the horizontal section of the duct. No reaction
takes place in the uid region, although some di usion of species-b out of the porous
region is suggested by the wide transition layer between the regions of 100% and 0%
species-a.

Fluent Inc. September 14, 2000

121

Sample Applications

1.00e+00
9.00e-01
8.00e-01
7.00e-01
6.00e-01
5.00e-01
4.00e-01
3.00e-01
2.00e-01
1.00e-01
0.00e+00

Contours of Mass fraction of species-a

Figure 6.4.4: Mass Fraction for species-a Governed by a Reaction in a Porous Region

122

Fluent Inc. September 14, 2000

Appendix A. DEFINE Macro De nitions from


udf.h

A.1 General-Use DEFINE Macros


#define DEFINE_DIFFUSIVITY(name, c, t, i)
real name(cell_t c, Thread *t, int i)
#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)
#define DEFINE_UDS_FLUX(name, f, t, i) \
real name(face_t f, Thread *t, int i)
#define DEFINE_UDS_UNSTEADY(name, c, t, i, apu, su) \
void name(cell_t c, Thread *t, int i, real *apu, real *su)
#define DEFINE_HEAT_FLUX(name, f, t, c0, t0, cid, cir) \
void name(face_t f, Thread *t, cell_t c0, \
Thread *t0, real cid[], real cir[])
#define DEFINE_VR_RATE(name, c, t, r, mw, yi, rr, rr_t) \
void name(cell_t c, Thread *t, \
Reaction *r, real *mw, real *yi, \
real *rr, real *rr_t)
#define DEFINE_SR_RATE(name, f, t, r, mw, yi, rr) \
void name(face_t c, Thread *t, \
Reaction *r, real *mw, real *yi, real *rr)
#define DEFINE_SCAT_PHASE_FUNC(name, c, f) \
real name(real c, real *f)
#define DEFINE_RW_FILE(name, fp) \
void name(FILE *fp)
#define DEFINE_ON_DEMAND(name) \
void name(void)

DEFINE

Macro De nitions from udf.h

A.2 Discrete Phase DEFINE Macros


#define DEFINE_DPM_BODY_FORCE(name, p, i) \
real name(Tracked_Particle *p, int i)
#define DEFINE_DPM_DRAG(name, Re) \
real name(real Re)
#define DEFINE_DPM_SOURCE(name, c, t, S, strength, p) \
void name(cell_t c, Thread *t, dpms_t *S, \
real strength, Tracked_Particle *p)
#define DEFINE_DPM_PROPERTY(name, c, t, p) \
real name(cell_t c, Thread *t, Tracked_Particle *p)
#define DEFINE_DPM_OUTPUT(name, header, fp, p, t, plane) \
void name(int header, FILE *fp, \
Tracked_Particle *p, Thread *t, Plane *plane)
#define DEFINE_DPM_EROSION(name, p, t, f, normal, alpha, Vmag, mdot) \
void name(Tracked_Particle *p, Thread *t, \
face_t f, real normal[], real alpha, \
real Vmag, real mdot)
#define DEFINE_DPM_SCALAR_UPDATE(name, c, t, initialize, p) \
void name(cell_t c, Thread *t, int initialize, \
Tracked_Particle *p)
#define DEFINE_DPM_LAW(name, p, ci)
void name(Tracked_Particle *p, int ci)
#define DEFINE_DPM_SWITCH(name, p, ci) \
void name(Tracked_Particle *p, int ci)
#define DEFINE_DPM_INJECTION_INIT(name, I) \
void name(Injection *I)

A.3 Multiphase DEFINE Macros


#define DEFINE_DRIFT_DIAM(name, c,
real name(cell_t
#define DEFINE_SLIP_VELOCITY(name,
void name(Domain

124

t) \
c, Thread *t)
domain) \
*domain)

Fluent Inc. September 14, 2000

Appendix B. C Library Functions


B.1 Trigonometric Functions
The trigonometric functions shown below are computed (with one exception) for the
variable x. Both the function and the argument are double-precision real variables. The
function acos(x) is the arccosine of the argument x, cos 1 (x). The function atan2(x,y)
is the arctangent of x/y, tan 1 (x=y). The function cosh(x) is the hyperbolic cosine
function, and so on.
double
double
double
double
double
double
double
double
double
double

acos (double x);


asin (double x);
atan (double x);
atan2 (double x, double y);
cos (double x);
sin (double x);
tan (double x);
cosh (double x);
sinh (double x);
tanh (double x);

B.2 Miscellaneous Mathematical Functions


The C functions shown on the left below correspond to the mathematical functions shown
on the right.
px
double sqrt (double x);
double
double
double
double
double
double
double
double

pow (double x,
y);
exp (double x);
log (double x);
log10 (double x);
fabs (double x);
ceil (double x);
floor (double x);

xy

ex
ln(x)
log10(x)
jxj
smallest integer not less than x
largest integer not greater than x

C Library Functions

B.3 Standard I/O Functions


A number of standard I/O functions are available. In many cases, these work on a
speci ed le.
FILE *fopen(char *filename, char *type);
int fclose(FILE *fd);
int fprintf(FILE *fd, char *format, ...);
int printf(char *format, ...);
int fscanf(FILE *fd, char *format, ...);

The functions fopen and fclose open and close a le, respectively. The function fprintf
writes to a le in a speci ed format, and the function fscanf reads from a le in the
same manner. The function printf is a general-purpose printing function. The symbol
*fd that appears in many of the functions is simply a pointer that identi es the le. All
of the functions except fopen are declared as integers, since a given integer value will
indicate whether the function (say, to read from a le) was executed successfully or not.
For more information about standard I/O functions in C, you should consult a reference
guide, or, on UNIX machines, view the manual pages.

126

Fluent Inc. September 14, 2000

Potrebbero piacerti anche