Lecture 1: Introduction 15.0 Release
User Defined Functions in ANSYS Fluent
Why use User Defined Functions (UDFs)? The Fluent solver is a general-purpose general-purp ose code. In order to customize the Fluent solver, users can use their own C-codes called user-defined functions (UDFs) to (UDFs) to accomplish: Special boundary conditions Customized or solution dependent material properties New physical models Reaction rates Source terms Customized post-processing post -processing Solving user-supplied partial differential equations More …. •
•
•
•
•
•
•
•
Why use User Defined Functions (UDFs)? The Fluent solver is a general-purpose general-purp ose code. In order to customize the Fluent solver, users can use their own C-codes called user-defined functions (UDFs) to (UDFs) to accomplish: Special boundary conditions Customized or solution dependent material properties New physical models Reaction rates Source terms Customized post-processing post -processing Solving user-supplied partial differential equations More …. •
•
•
•
•
•
•
•
What are User Defined Functions? Programs written in C Similar mechanism used to develop models in Fluent – Powerful and efficient
Extends the functionality of ANSYS Fluent – Initial and boundary conditions – Material properties – Material and energy transfer through source terms – Modify solution variables – Adding extra flow equations – And many more …
Typically compiled to DLLs/shared object libraries – Loaded only when required
Sinusoidal Wall Temperature Variation
Adiabatic wall inlet
outlet
Heated wall T = T(x) T(x) = +
.
What Does It Take to Create a Model? Ability to access and modify – Interact with the user through a GUI/TUI – Field variables – Geometrical and mesh data – Hooks to the solver at appropriate stages of the solution cycle – Convenience macros •
Vector macros
•
Looping macros
•
Parallel programming
Basics of UDFs 15.0 Release
User Defined Functions in ANSYS Fluent
C – The Foundation for UDFs UDFs when compiled create C libraries that Fluent can use Resources to learn C – ANSYS Fluent UDF Manual (Appendix A. C Programming Basics) – E.g. The C-Programming Language, B. Kernighan & D. Ritchie
Programming practices – Simplicity, Clarity and Generality •
Naming conventions
•
Macros and comments
•
Algorithms and data structures
•
Design principles
•
Testing
User Access to the Fluent Solver Segregated
Initialize
Begin Loop
Userdefined ADJUST
Solver?
SOLVERS
Solve U-Momentum Solve V-Momentum
User Defined INITIALIZE
Source terms
Solve W-Momentum
Repeat
PBCS
DBCS
Source terms Solve Mass & Momentum
Solve Mass, Momentum, Energy, Species
Source terms
Solve Mass Continuity; Update Velocity Exit Loop
Check Convergence Solve Energy Update Properties Solve Species
User-Defined Properties User-Defined BCs
Solve Turbulence Equation(s)
Source terms
Data Structures Each type of UDF is passed different values and data structures depending on its function.
Most UDFs will need solver data. This is stored in a hierarchy: •
Domains are collections of threads that make the whole mesh
•
Threads (or zones) are collections of cells or faces
•
Cells and faces are made of Nodes
Geometrical Entities The parts of a mesh are:
Collection of cells and faces are stored in threads.
Data Structures The terms ‘Thread’ and ‘Zone’ are interchangeable. The boundary and cell zones defined in the User Interface are stored internally as threads. – Zones have an associated integer ID seen in the settings
panel – In a UDF, the corresponding thread can be identified using
this ID – Threads are an internal data type which stores information
about the mesh, models, properties, BCs all in one place A cell has information about its bounding faces and a face has access to its neighbouring cells.
Introduction to the C Programming Language 15.0 Release
User Defined Functions in ANSYS Fluent
C Programming – Basic Syntax Rules – Each statement must be terminated with a semicolon ; – Comments can be inserted anywhere between /* and */ – All variables must be explicitly declared (unlike in FORTRAN) – Compound statements can be created by enclosing multiple
statements by braces: { } – Function definitions have the following format:
return-value-type function-name(parameter-list) { function body }
C Programming – Data Types Built-in data types: int, float, double, char, enum int niter, a; /* Declare ‘niter’ and ‘a’ as integers */ float dx[10]; /* dx is an array of numbers indexed from 0 to 9: dx[0],dx[1],…,dx[9]
*/
enum {X, Y, Z} /* X,Y,Z are enumeration constants = 0,1,2 */
Ansys Fluent: real, cxboolean real a;
/* real is a typedef that switches between float for single-precision and double for double-precision arithmetic */ cxboolean flag=TRUE; /* Pre-defined enumeration of FALSE and TRUE*/
C Programming – Pointer •
•
A pointer is a special kind of variable that contains an address in memory, not content, of another variable Pointers are declared using the * notation int *ip; /* declares a pointer named ip that points to an integer variable*/
•
We can make a pointer point to the address of pre-defined variable as follows: int a=1; int *ip; /* (*ip) contains an integer */
Message Macro: Defined in udf.h Similar to printf in C Recommended to use • • •
ip = &a; /* &a returns the address of variable a */ Message(“ip is a pointer with value %p\n”,ip); Message(“The integer a pointed to by ip has value = %d\n”,*ip);
Output:
ip is a pointer with value 0x40b2
C Programming – Pointers and Arrays •
Pointers and arrays are closely related: int ar[10]; /* ar is an array of 10 integers */ int *ip; /* (*ip) contains an integer */
•
The name of an array without an index can be used as a pointer to start the array ip = ar;
•
/* ar is the address of its first integer so this is equivalent to ip = &(ar[0]); */
BUT: An array name cannot be set to a new value. It is fixed to the value set when it is defined as an array. ar = ip;
/* This will cause a compilation error. */
C Programming – Operators •
Arithmetic Operators = +, % ++ --
(assignment) -, *, /, (modulo reduction) (increment) /* i++ is post-increment (i=i+1) (decrement) /* j–- is post-decrement (j=j-1)
*/ */
E.g.: x = 1; y = x++; /* x is now 2, y is 1*/ •
Logical Operators
<, >, >=, <= , ==, != •
Assignments +=, *=, -=, /=
E.g.: x += y; /* is equivalent to x = x + y */
C Programming – Control Statements if-else statement:
for loop:
if ( logical-expression ) { statements } else { statements }
while loop: while ( logical-expression ) {statements}
E.g.: if ( x < 0 ) y = x/50; else { x = -x; y = x/25; }
for (begin ; end ; increment) {statements}
E.g.: for ( k=0; k < 10; k++) {statements} while ( x < 5 ) { executed while the condition is true }
C Programming – Conditional Operator (logical-expression ? result1 : result2)
If the condition/logical-expression is true, result1 is returned else result2 is returned.
E.g.: real y = 2; real x1 = (y < 0 ? 5 : 10); real x2 = (y >= 0 ? 5 : 10); Result: x1 = 10 and x2 = 5
C Programming – User-defined Data Types (1) Structures are collection of data that are of different type. struct { Element 1; …
Element n; };
E.g.: struct { char int real };
car_struct model_name[25]; number_of_wheels; top_speed;
Semicolon (;) at the end of structure declaration is needed! Set and get values struct car_struct alices_car, bobs_car; alices_car.top_speed = 120.0; if (bobs_car.top_speed > alices_car.top_speed)
C Programming – User-defined Data Types (2) To simplify a declaration typedef ;
If the example from previous slide is defined as follows Combined example: typedef struct car_struct { char model_name[25]; int number_of_wheels; real top_speed; } car_model;
Simplified: typedef struct { char model_name[25]; int number_of_wheels; real top_speed; } car_model;
then the variable can be declared as car_model alices_car;
instead of struct car_struct alices_car;
C Programming – Fluent Structures The most common structure in Fluent is Thread. typedef struct thread_struct { …
int id;
E.g.: Thread *ct;
Usually we use pointers to structures.
…
} Thread ;
Pre-defined Marcos can be used to access structure elements. #define THREAD_ID(t) ((t)->id)
Note ->
operator: t->id
is the same as (*t).id
Introduction to UDF Implementation Using C 15.0 Release
User Defined Functions in ANSYS Fluent
Why UDFs are written in the C Language Fluent is written in C because it is a very powerful language. It provides access to high level operations such as graphics and networking and low level capabilities such as mathematical functions and memory operations. It enables the linking of extra functionality using “shared objects” in Unix and Dynamic Linked Libraries (DLLs) in windows systems.
This is a very convenient mechanism for linking in UDFs which allows a seamless connection between the main program and the user functions Users familiar with other “procedural” languages such as FORTRAN will be familiar with most of the ideas and syntax used in C
Mesh Data Types (1) •
There are several Fluent-specific data types that are associated with mesh components.
•
Some of the more commonly used ones are:
•
•
−
Node
– stores data associated with a grid point
−
face_t
– identifies a face within a face thread
−
cell_t
– identifies a cell within a cell thread
−
Thread
– stores data that is common to a collection of cells or faces
−
Domain
– stores data associated with a collection of face and cell threads in a mesh
Each individual cell can be accessed by using a cell index of type cell_t and the cell thread (the zone which contains the cell) Each individual face (boundary or internal) can be accessed by using a face index of type face_t and the face thread (the zone which contains the face)
Mesh Data Types (2) •
•
Some mesh or solver data types have a capital letter. These are actually data structures in the C language and are usually passed between functions as pointers to these structures. Examples of how these data types are defined are shown below: Type
Domain Thread cell_t face_t Node
Example
*d; *t; c; f; *node;
Declaration d is a pointer to a Domain structure t is a pointer to a Thread structure c is cell index, a simple integer f is a face index, a simple integer node is pointer to a Node structure
Mesh Data Types (3) Every Zone is associated to a single ID available in the BC panel or the TUI using:
/grid/modify-zones/list-zones Given the ID, the thread associated with that zone can be retrieved as:
int t_id = 7; Thread *ft; ft = Lookup_Thread(domain, t_id); Once we have the thread we can access its associated data Similarly, a thread’s ID can be retrieved using :
t_id = THREAD_ID(ft);
C macros and UDF Programming •
C has very powerful macro definition capabilities. These are extensively used in Fluent in many ways. Notable example include definitions of: – Data structure looping macro – Geometry macros – Field data macros – Logic and status control macros – Safe arithmetic and trigonometry functions – Complete set of vector arithmetic operations
•
The definition of each UDF also uses a specific DEFINE_ macro.
Looping Macros in a UDF Fluent provides a set of pre-defined macros to accomplish looping tasks: • •
•
thread_loop_c(t,d ){…} thread_loop_f(t,d ){…} begin_c_loop(c,t)
Loop over cell threads in a domain d Loop over face threads in a domain d Loop over the cells in a given thread t
{…}
end_c_loop(c,t) •
begin_f_loop(f,t) {…}
end_f_loop(f,t)
Loop over the faces in a given thread t
Cell Field Variable Macros C_R(c,t);
Density
C_DUDX(c,t);
Velocity derivative
C_P(c,t);
Pressure
C_DUDY(c,t);
Velocity derivative
C_U(c,t); U-velocity
C_DUDZ(c,t);
Velocity derivative
C_V(c,t);
V-velocity
C_DVDX(c,t);
Velocity derivative
C_W(c,t);
W-velocity
C_DVDY(c,t);
Velocity derivative
C_T(c,t);
Temperature
C_DVDZ(c,t);
Velocity derivative
C_H(c,t);
Enthalpy
C_DWDX(c,t);
Velocity derivative
C_K(c,t);
Turbulent kinetic energy (k )
C_DWDY(c,t);
Velocity derivative
C_D(c,t);
Turbulent dissipation rate (ε)
C_DWDZ(c,t);
Velocity derivative
C_YI(c,t,i);
i-th Species mass fraction
C_MU_L(c,t);
Laminar viscosity
C_UDSI(c,t,i);
i-th UDS scalars
C_MU_T(c,t);
Turbulent viscosity
C_UDMI(c,t,i);
i-th UDM scalars
C_MU_EFF(c,t);
Effective viscosity
Geometry Macros
A Hex cell Faces
•
•
•
•
•
•
C_CENTROID(pos,c,t) F_CENTROID(pos,f,t) F_AREA(A,f,t) NV_MAG(A) C_VOLUME(c,t) C_VOLUME_2D(c,t)
x, y, z coords of cell centroid x, y, z coords of face centroid Area vector of a face; Vector magnitude Volume of a cell Volume of a 2D cell
Nodes
Location of cell variables C_NNODES(c,t) = 8 C_NFACES(c,t) = 6 F_NNODES(f,t) = 4 each
pos and A are vectors which are discussed later. Depth is 1m in 2D; 2 radians in axi-symmetric .
Node Coordinates: •
•
•
NODE_X(nn) NODE_Y(nn) NODE_Z(nn)
Node x –coord; (with Node *nn;) Node y –coord; Node z –coord;
Many more macros available, see UDF Manual.
Cell-Face Connectivity (1) •
The cells on either side of a face (f,ft) can be accessed using the macros:
ct0 = THREAD_T0(ft); ct1 = THREAD_T1(ft); c0 = F_C0(f,ft); c1 = F_C1(f,ft);
C0 C1 A face’s area vector points from C0 to C1
•
•
The macros THREAD_T0(ft) and THREAD_T1(ft)only need the face thread, not the face index. Boundary zones such as inlets will connect to a cell zone on one side with THREAD_T0(ft) but THREAD_T1(ft) will return NULL, a special pointer which signifies there is no zone on the other side.
Cell-Face Connectivity (2) •
A face’s area can be obtained by
real A[3], area; F_AREA(A,f,ft); area = NV_MAG(A);
where F_AREA returns the face normal vector A and NV_MAG(A) the magnitude of the vector A. •
The faces that bound a cell can be accessed using this loop : int nf; for(nf = 0; nf < C_NFACES(c,ct); nf++) { f = C_FACE(c,ct,nf); ft= C_FACE_THREAD(c,ct,nf); }
C0 C1
A face’s area vector points from C0 to C1
Macros used for Control •
Data_Valid_P()
if (!Data_Valid_P()) return;
TRUE if data is available, FALSE if not. •
FLUID_THREAD_P(t0) TRUE if threat t0 is a fluid thread, FALSE if not.
•
NULLP(ct)
TRUE if a pointer is NULL, FALSE if not. •
NNULLP(ct)
if(NNULLP(THREAD_T1(ft))) { ... Do things on neighbouring
TRUE if a pointer is NOT NULL, FALSE if not.
cell thread.
}
UDF Defining Macros All UDFs that will be used must be defined using a specific DEFINE_ macro Common examples: •
Profiles
: DEFINE_PROFILE
•
Source Terms
: DEFINE_SOURCE
•
Properties
: DEFINE_PROPERTY
•
User-defined Scalars
: DEFINE_UDS_UNSTEADY , DEFINE_UDS_FLUX DEFINE_DIFFUSIVITY
•
Initialization
: DEFINE_INIT
•
Global Functions
: DEFINE_ADJUST DEFINE_ON_DEMAND
For a complete list, see UDF Manual.
Additional Information •
•
Many additional macros are available to implement different physical models including: –
Combustion models
–
Particle-based models
–
Turbulence models
–
Radiation models
–
etc.
It is also possible to develop additional numerical methods, particularly when using User-Defined Scalars (see Lecture 4). Access to low-level operations is possible, such as –
Flux discretization
–
Variable reconstruction and clipping