Professional Documents
Culture Documents
0BIntroduction
Table of Contents
1
Introduction .................................................................................................................................... 4
C Programming ................................................................................................................................ 5
7.2
7.3
7.4
10
11
12
13
Macros ....................................................................................................................................... 15
13.1
13.2
14
15
16
17
18
18.1
18.2
18.3
18.4
18.5
19
19.1
19.2
20
0BIntroduction
20.1
Preparation............................................................................................................................ 24
20.2
Mesh ...................................................................................................................................... 24
20.3
20.4
Models ................................................................................................................................... 25
20.5
Materials ............................................................................................................................... 25
20.6
20.6.1
20.6.2
Pressure Outlet.............................................................................................................. 29
20.7
20.7.1
20.8
21
21.1
21.2
21.2.1
21.2.2
0BIntroduction
1 Introduction
What is a User Defined Function?
o A UDF is a routine (programmed by the user) written in C which can be dynamically linked with
the solver.
Standard C functions
e.g., trigonometric, exponential, control blocks, do-loops, file i/o, etc.
Pre-Defined Macros
Allows access to field variable, material property, and cell geometry data.
Why build UDFs?
o Standard interface cannot be programmed to anticipate all needs.
Customization of boundary conditions, source terms, reaction rates, material properties,
etc.
Adjust functions (once per iteration)
Execute on Demand functions
Solution Initialization
2BC Programming
3 C Programming
o Macros are defined in the header files, they can be used just like functions
Built-in data types: int, float, double, enum, Boolean:
int niter, a;
float dx[10];
/* dx is a real array with 10 members, the array index always starts from
dx[0] */
pointer is a special kind of variable that contains the memory address, not content, of
another variable
Pointers are declared using the * notation:
int *ip;
(assignment)
+, -, *, /, % (modulus)
<, >, >=, <=, ==, !=
++ increment; i++ is pors-increment; use the current value of I in the expression, then
increment I by 1 (i=i+)
-- decrement: jpost-decrement, use the current value of j, then decrement j by 1 (j=j-1)
+= addition assignment:
Saeed Sadeghi (saeed@me.iut.ac.ir)
http://www.ssadeghi.ir
2BC Programming
agg += single;
false
real At = (rp_axi ? At*2*M_PI : At );
true
We (as CFD programmers in FLUENT) want to know how FLUENT organizes data so that we
know:
o How to access mesh information for a particular cell zone or a face zone
Cell centroids, cell volumes, the neighbors, etc.
Face centroids, face areas, face normal directions (vectors), etc.
o How to access field data for cells (and faces): pressure, velocity, density, etc.
o How to efficiently loop through these cells or faces in the codes
How to sypply customized source terms, boundary conditions, and fluid properties, etc., to
the solver
How to modify the behaviors or specific model parameters for various physical models as in
turbulence, reactions kinetics, multiphase, and dynamic mesh, etc.
How to implement users own governing equations in the finite-volume framework of
FLUENT solver
5 UDF Basics
UDFs assigns values (e.g., boundary data, source terms)
to individual cells and cell faces in fluid and boundary
zones.
o In a UDF, zones are referred to as threads.
o A looping macro is used to access individual cells
belonging to a thread.
e.g., a face-loop macro visits 563 faces on face zone
3 (velocity-inlet).
Position of each face is available to
calculate and assign spatially
varying properties.
Thread and variable references are
automatically passed to UDF when
assigned to boundary in GUI.
Values returned to the solver by UDFs must
be in SI units.
Domain is the set of connectivity and hierarchy info for the entire data structure in a given
problem for single phase flows. It includes:
o All fluid zones (fluid threads)
o All solid zones (solid threads)
o All boundary zones (boundary threads)
Cell: cell is the computational unit, conservation equations are solved over each cell
Face: direction in the outward normal
Threads: represent the collection of cells or faces; a Thread represents a fluid or solid or
boundary zone
Multiphase simulations (singlephase simulations use single domain only)
o Each phase has its own Domain-structure
o Geometric and common property information are shared among sub-domains
Saeed Sadeghi (saeed@me.iut.ac.ir)
http://www.ssadeghi.ir
Control volumes of fluid and solid zones are also called cells in FLUENT
o The data structure for the cell zones is typed as cell_t (the cell thread index)
o The data structure for the cell faces is typed as face_t (the face thread index)
A fluid or solid zone is called a cell zone, which can be accessed by using cell threads
Boundary or internal faces can be accessed by using face threads
10
The data structure for accessing a cell zone is typed as cell_t (the cell thread index); the
data structure for faces is typed as face_t' (the face thread index)
Type
Example
Declaration
Domain
*d
Thread
*t
t is a pointer to thread
Cell_t
*c
Face_t
Node
*node
Once we have the correct pointer (for a specific zone), we can access the members belonging
to the zone without any problem. Thread pointer provides the leading address of the thread
(zone)
7BGeometry Macros
9 Geometry Macros
C_NNODES(c, t)
C_NFACES(c, t)
F_NNODES(f, t)
C_CENTROID(x, c, t)
F_CENTROID(x, f, t)
centroid
F_AREA(A, f, t)
NV_MAG(A)
C_VOLUME(c, t)
C_VOLUME_2D(c, t)
NODE_X(nn)
Node x-coord; (nn is a node pointer)
NODE_Y(nn)
Node y-coord;
NODE_Z(nn)
Node z-coord;
real flow_time();
returns actual time
int time_step;
returns time step number
RP_GET_Real(physical-time-step);
returns time step size
11
density
pressure
u-velocity
v-velocity
w-velocity
temperature
enthalpy
turbulent KE
tke dissipation
species mass fraction
UDS scalars
UDM scalars
C_DUDX(c,t);
C_DUDY(c,t);
C_DYDZ(c,t);
C_DVDX(c,t);
C_DVDY(c,t);
C_DVDZ(c,t);
C_DWDX(c,t);
C_DWDY(c,t);
C_DWDZ(c,t);
velocity derivative
velocity derivative
velocity derivative
velocity derivative
velocity derivative
velocity derivative
velocity derivative
velocity derivative
velocity derivative
C_MU_L(c,t);
C_MU_T(c,t);
C_MU_EFF(c,t);
C_K_L(c,t);
C_K_T(c,t);
C_K_EFF(c,t);
C_CP(C c,t);
C_RGAS(c,t);
C_DIFF_L(c,t);
C_DIFF_EFF(c,t);
laminar viscosity
turbulent viscosity
effective viscosity
laminar thermal conductivity
turbulent thermal conductivity
effective thermal conductivity
specific heat
gas constant
laminar species diffusivity
effective species diffusivity
12
density
pressure
u-velocity
v-velocity
w-velocity
temperature
enthalpy
turbulent KE
tke dissipation
species mass fraction
UDS scalars
UDM scalars
Mass flux across face f, defined out of domain at boundaries.
13
defines a cell
face_t f;
defines a face
Thread *t;
pointer to a thread
Domain *d;
thread_loop_c(t, d)
{
..........
}
thread_loop_f(t, d)
{
.
}
begin_c_loop(c, t)
{
.
}
end_c_loop
befing_f_loop(c, t)
{
.
}
C_face_loop(f, t, n)
{
.
}
THREAD_ID(tf);
14
11BMacros
13 Macros
Macros are pre-defined (Fluent) functions:
o Allows definition of UDF functionality and function name (DEFINE_ macro)
o Allow access to field variables, cell information, looping capabilities, etc.
Macros are defined in header files.
o The udf.h header file must be included in your source code.
#include udf.h
o The header files must be accessible in your path.
Typically stored in Fluent.Inc/src/directory.
o Other .h header files may need to be included.
Depends upon relevant variables and macros needed in your UDF, e.g.,
dpm.h for DPM variable access
A list of often used macros is provided in the UDF Users Guide.
DEFINE_INIT(name,domain);
DEFINE_ON_DEMAND(name);
DEFINE_RW_FILE(name,face,thread,index);
DEFINE PROFILE(name,thread,index);
DEFINE_SOURCE(name,cell,thread,ds,index);
DEFINE_HEAT_FLUX(name,face,thread,c0,t0,cid,cir);
DEFINE_PROPERTY(name,cell,thread);
DEFINE_DIFFUSIVITY(name,cell,thread,index);
DEFINE_UDS_FLUX(name,face,thread,index);
DEFINE_UDS_UNSTEADY(name,face,thread,index);
DEFINE_SR_RATE(name,face,thread,r,mw,yi,rr);
DEFINE_VR_RATE(name,cell,thread,r,mw,yi,rr,rr_t);
DEFINE_SCAT_PHASE_FUNC(name,cell,face);
DEFINE_DELTAT(name, domain);
15
11BMacros
DEFINE_TURBULENT_VISCOSIT(name, cell, thread);
16
defines turbulent
17
18
+
t
x i
k
k 1,..., N scalars
=
Fi k
S=
k
k
x i
User Specifies:
Define Models User-Defined Scalars
o Number of User-Defined Scalars
o Flux Function F
DEFINE_UDS_FLUX(name, face, thread, index)
DEFINE_UDS_UNSTEADY(name, cell, thread, index)
case statement can be used to associate multiple flux and transient functions with each
UDS.
o Example
Can be used to determine magnetic and/or electric field in a fluid zone.
User must also specify:
o Source terms
o Diffusivity,
case statement needed to
define UDF diffusivities for
each UDS.
o Boundary Conditions for each
UDS.
Specified Flux or Specified
Value.
Define as constant or with UDF.
19
20
y 2
u=
( y ) 20 1
0.0745
y =0
You can change the UDF Profile Update Interval in the Iterate
panel (default value is 1).
o This setting controls how often (either iterations or
time steps if unsteady) the UDF profile is updated.
Run the calculation as usual.
21
22
#include "udf.h"
#define por_gdl
0.4
#define i_permeability 5.68e6
// Inverse Permeability (1/m^2)
#define urf
0.1
// under relaxation factor for stability of momentum source term
real s1=0., s2=0.;
DEFINE_SOURCE(xmom_src,c,t,dS,eqn)
{
real source, mu, u;
mu = C_MU_L(c,t);
u = C_U(c,t);
source = -(mu*u*i_permeability);
dS[eqn] = -(mu*i_permeability);
s1 = s1*(1-urf) + source*urf;
return s1;
}
DEFINE_SOURCE(ymom_src,c,t,dS,eqn)
{
real source, mu, v;
mu = C_MU_L(c,t);
v = C_V(c,t);
source = -(mu*v*i_permeability);
dS[eqn] = -(mu*i_permeability);
s2 = s2*(1-urf) + source*urf;
return s2;
}
23
24
20.2 Mesh
1. Read the mesh file
File Read Mesh
2. Check the mesh
General Check
ANSYS FLUENT will perform various checks on the mesh and report the progress in the ANSYS
FLUENT console window. Ensure that the minimum volume reported is a positive number.
3. Scale the mesh
General Scale
(a) Select mm (millimeter) from the Mesh Was Created In drop-down list in the Scaling group
box.
(b) Click Scale to scale the mesh.
(c) Close the Scale Mesh dialog box.
4. Check the mesh.
General Check
Note: It is a good idea to check the mesh after you manipulate it (i.e., scale, convert to polyhedral,
merge, separate, fuse, add zones, or smooth and swap). This will ensure that the quality of the mesh
has not been compromised.
20.4 Models
Define Models Species Transport & Reaction
(c) FLUENT will notify that Available material properties or method have changed. Please
confirm the property values before continuing. Click OK to close the dialog box.
20.5 Materials
Define Materials
1. Revise the properties for the mixture materials.
Define Material Mixture
25
26
(a) Click the Edit button to the right of the Mixture Species drop-down list to open Species
dialog box.
You can add or remove species from the mixture material as necessary using the Species dialog box.
i.
ii.
Retain the default selections from the Selected Species selection list.
Click OK to close the Species dialog box.
(a) Set Boundary condition for gdl fluid zone, by clicking on the Set button
27
(f) Set Boundary condition for cl fluid zone, by clicking on the Set button
(g) Check the porous zone button to enable the cl porous zone.
(h) Set viscous resistance variables for both directions.
(i) Now you should set porosity for cl porous zone that is equal to 0.1, here.
28
29
(c) Click the Species Tab to set mass fraction of species. Fluent will automatically calculate the
mass fraction of the last specie, that is equal to 1 minus sum of the mass fraction of the other
species.
30
(b) Select pressure outlet on the right side of the boundary conditions dialog box, to specify
pressure at the outlet of the fuel cell.
(c) Click set button to enter Pressure Outlet dialog box.
(d) To prevent solution damage by reverse flows, we should specify outlet conditions near to
real condition.
(e) For this, we have chosen inlet species mass fraction for the outlet condition.
(f) Leave the other parameters by default and click OK.
3.2348e-5
3.89e-5
2.88e-5
#define i_h2o 0
#define i_o2 1
#define i_n2 2
#define mw_h2o
#define mw_o2
18.
32.
// kg/kmol
// kg/kmol
28.
// kg/kmol
enum{ current };
real R_cat(cell_t c, Thread *t)
{
// this routine returns Reraction_Rate_cat as "R_cat"
real eta_cat, C_o2, T, xyz[ND_ND], x ,y, z, Reraction_Rate_cat, i, i0_over_C_ref;
C_o2 = C_YI(c,t,i_o2);
T = C_T(c,t);
//eta_cat = phi_sol-phi_mem-V_oc;
i=C_UDMI(c,t,current);
i0_over_C_ref=0.8*1e4; //[A/m^2] Ref. Khakbaz-Kermani
eta_cat = R*T / (alpha_cat*F) * log(i/C_o2/i0_over_C_ref);
//Butler-Volmer Ref.
Khakbaz-Kermani
C_CENTROID(xyz,c,t);
x=xyz[0];
y=xyz[1];
//z=xyz[2];
// Option 0
// Reraction_Rate_cat = 10000.0;
// Option 1
Reraction_Rate_cat = 100000. *(1.0 - x/L);
// Option 2
from Fluent FC manual
// Reraction_Rate_cat = (zita_cat*j_ref_cat)*pow(C_o2/C_ref_o2,lambda_cat)*(exp(alpha_cat*F*eta_cat/(R*T)));
// Option 3
// Reraction_Rate_cat = (zita_cat*j_ref_cat)*pow(C_o2/C_ref_o2,lambda_cat)*(exp(alpha_cat*F*eta_cat/(R*T)));
return Reraction_Rate_cat;
}
DEFINE_SOURCE(O2_src,c,t,dS,eqn)
{
real source;
source = -mw_o2*R_cat(c,t)/(4.*F) *por_cl;// (kg/kmol)()/(C/kmol)
//Message("%f, %f, %f, %f, %f\n",mw_o2,R_cat(c,t),por_cl, source, F);
C_UDMI(c,t,current)= -4.*F /mw_o2 *source *h_cl; // this is local current density
dS[eqn] = 0.0;
return source;
}
DEFINE_SOURCE(H2O_src,c,t,dS,eqn)
{
real source;
source = +mw_h2o*R_cat(c,t)/(2.*F) *por_cl;
Saeed Sadeghi (saeed@me.iut.ac.ir)
http://www.ssadeghi.ir
31
32
33
Build the UDF and then click on Load to load the Library that is named libudf.
Note that the UDF source files should be in the directory that contains your case and data
files. Click OK to build the library.
Now the fluent creates library libudf.lib, object libudf.exp and other required files.
You can load the library if fluent reveal no error and the message Done have seen at the
end of the commend window.
By loading the library, fluent command window show all defined functions. Here it shows
O2_src, H2O_src, MASS_src, .
Saeed Sadeghi (saeed@me.iut.ac.ir)
http://www.ssadeghi.ir
34
If you have build and load a udf before, be sure to unload it in the Manage dialog box. Else
an error will appear that an libudf is in use.
We have used a UDM in the UDF, so we should specify a UDM for it.
Go to: Define User-Defined Memory then set the number of UDM-s.
Saeed Sadeghi (saeed@me.iut.ac.ir)
http://www.ssadeghi.ir
35
Fluent enables the energy equation by enabling Species Transport equation. In this example,
we dont need the energy equation. To prevent solving this equation go to Solve Solution
Controls and click on Energy in Equations box.
To have a good initial guess for better and time saving convergence, we can specify the
conditions of inlet to the all domain.
So, Solve Initialize Solution Initialize, Compute from inlet and click on Init to specify its
condition to all domains.
You can change Residual criteria and Residual window settings. Solve Monitors
Residual.
To prevent printing on command window, uncheck print. And to show residual on the
residual window, check the plot box.
On iterate window, Solve Iterate, specify the number iterations and start iteration by
clicking on iterate.
36
37
38
The macro DEFINE_ON_DEMAN executes when we want. For example at the beginning,
intermediate and at the end of solution, it can be executed.
The array A is defined in ND_ND dimension to reserve area.
ND_ND is a Fluent macro that is equal to 2 in 2-dimensioanl and 3 in 3-dimensional case.
sum is defined to summarize value of cells in a group cells (Threads)
inlet_ID, outlet_ID and cl_ID are the number of zone that can be found in Boundary
Conditions dialog box.
39
If Fluent complains about not being able to find a compiler, then check to make sure that the
compiler is properly installed. On Windows machines, it is possible to install the Visual C++
compiler without fully setting up the command line compiler (which Fluent needs to be able
to find). During the installation process, you need to select the "register environment
variables" option. Failure to do so will likely lead to complaints about things being "not
recognized as an internal or external command, operable program or batch file" or missing
DLL's. It is theoretically possible to fix this issue by setting the appropriate environment
variables, but keep in mind that even when nmake can be found there still may be DLL
issues. The easy path is probably reinstallation of Visual Studio (taking special care to make
sure that the command line interface is set up properly), but the reinstallation path is always
perilous. If you have long term experience using Windows you should probably know the
risks, and if you don't you should consult an expert.
If you are interpreting, keep in mind that not everything that is supported for compiled UDF's
is supported for interpreted UDF's. This is true both for the UDF interface and the C
language. If you are doing something pretty involved and it fails inexplicably, try compiling to
see if that makes a difference.
There is also the possibility of coding errors. Keep in mind that your source code gets run
through the C preprocessor (to change the Fluent macros into C code), so unintended
interactions are very possible.