presenter name case studies on using udf’s in fluent … · case studies on using udf’s in...
TRANSCRIPT
1
Presenter NamePresenter Title
Presentation TitleJune XX, 2005
Case studies on usingUDF’s in FLUENT v6.2
Andrey Troshko
June 2005
2
Objective
The objective of this course is to show examples of UDF implementation to solve practical problemsThis is not a course on “how to program UDF”, but rather on “how to apply UDF to real world problem”It is assumed that auditory has at least preliminary knowledge of UDF, however we will cover basics of UDF in several slidesAll cases were developed by Fluent staff Some cases are preceded by short synopsis of UDF macros that are used
3
OutlineBasic concepts of how UDF is built and used
Regulated temperature at inlet (1)Modeling of membrane (2)Staggered injection of particles in silo launch simulation (3)
Basic concepts on variable access in multiphase modelsDrag coefficient for spherical cap bubble (4)Modeling of evaporation from liquid droplets (5)
Basic concepts of parallel UDFWriting of pressure distribution into file for parallel runs (6)
Moving mesh and variable time step for store separation example (7)Appendix
User Defined MemoryFilter blockage modeling for Discrete Particle Model (8)Customized erosion model for Discrete Particle Model (9)
4
User Access to Fluent Solver
Fluent is so designed that the user can access the solver at some strategic instances during the solution process
Flow Diagram
of FLUENT Solvers
Segregated Solver Coupled Solver
Initialize Begin Loop
Exit Loop Repeat
Check Convergence
Update Properties Solve Eddy Dissipation
Solve Turbulence Kinetic Energy
Solve Species
Solve Energy
Solve Mass Continuity;Update Velocity
Solve U-Momentum
Solve V-Momentum
Solve W-Momentum
Solve Mass Momentum &
EnergyFlow
Diagram of
FLUENT Solvers
Segregated Solver Coupled Solver
Initialize Begin Loop
Exit Loop Repeat
Check Convergence
Update Properties Solve Eddy Dissipation
Solve Turbulence Kinetic Energy
Solve Species
Solve Energy
Solve Mass Continuity;Update Velocity
Solve U-Momentum
Solve V-Momentum
Solve W-Momentum
Solve Mass Momentum &
Energy
User-defined ADJUST
Source termsSource terms
Source terms
Source termsSource termsSource termsSource terms
Source termsSource terms
Boxes inblueblue are
some important
user access points
User Defined Initialize
Boxes inblueblue are
some important
user access points
User Defined Initialize
User-Defined PropertiesUser-Defined PropertiesUser-Defined Boundary Conditions
5
User Defined Functions in Fluent
UDF’s in FLUENT are available for:Profiles (Boundary Conditions)
velocity, temperature, pressure etc
Source terms (Fluid and solid zones)mass, momentum, energy, species etc
Propertiesviscosity, conductivity etc (except specific heat)
Initialization
zone and variable specific initializationGlobal FunctionsadjustScalar Functionsunsteady term, flux vector, diffusivityModel Specific Functionsreaction rates, discrete phase model, turbulent viscosity
User Defined Functions are not just any C-functions:User access needs specific “Type” of function callsThese Function types or ‘macro’-s are defined in the header file:
~Fluent.Inc/fluentx.y/src/udf.h
6
Data Structures in FLUENT
Domain
CellCell
Thread
Domain
CellCell
Thread
face
cellcell
face
cellcell
Boundary (face thread or zone) Fluid (cell thread or zone)
Domain
Cell
7
The Domain
“Domain” is the set of connectivity and hierarchy info for the entire data structure in a given problem. It includes:
all fluid zones (‘fluid threads’)all solid zones (‘solid threads’)all boundary zones (‘boundary threads’)
Cell/face - Computational unit, face is one side.Conservation equations are solved over a cellThread - is the collection of cells or faces; defines a
fluid/solid/boundary zone
8
Domain and Threads
Wall
PorousMedium
Fluid-1
Solid-1
Solid-2
Outlet
Wall
Fluid-2Inlet
Domain Domain ofof
AnalysisAnalysis
CorrespondingCorrespondingData setData set
InletFluid-2
Fluid-1
Solid-1
OutletPorousMedium
Solid-2Wall
Domain Domain
Threads Threads
Wall
PorousMedium
Fluid-1
Solid-1
Solid-2
Outlet
Wall
Fluid-2Inlet
Domain Domain ofof
AnalysisAnalysisWall
PorousMedium
Fluid-1
Solid-1
Solid-2
Outlet
Wall
Fluid-2Inlet
Domain Domain ofof
AnalysisAnalysis
CorrespondingCorrespondingData setData set
InletFluid-2
Fluid-1
Solid-1
OutletPorousMedium
Solid-2Wall
Domain Domain
Threads Threads
InletFluid-2
Fluid-1
Solid-1
OutletPorousMedium
Solid-2Wall
InletFluid-2
Fluid-1
Solid-1
OutletPorousMedium
Solid-2Wall
Domain Domain
Threads Threads
9
Cell and Face Datatypes
Control volumes (equivalent of ‘FEM:Elements’) of fluid and solid zones are called ‘cell’ in FLUENT
The data structure for the control volumes is typed as ‘cell_t’The data structure for the control volume faces is typed as ‘face_t’
A fluid or solid zone is comprised of cells The Thread that identifies the cells in a Fluid or Solid Thread, is a ‘Cell-Thread’
A boundary zone is comprised of faces of the adjacent control volumes or cells
The Thread that identifies the faces on a boundary is a ‘Face-Thread’
10
Cell & Face Threads; Cell_t & Face_t Datatypes
TypeType ExampleExample DetailsDetailsDomain *d pointer to the collection of all threadsThread *t pointer to a threadCell_t c cell identifierface_t f face identifierNode *node pointer to a node
Boundary face-threadthe boundary-face ensembleFluid cell-thread
the Control-volume ensemble Internal face-thread
the Internal-face ensembleassociated to cell-threads
Nodes
11
#include "udf.h"
DEFINE_PROFILE(w_profile, thread, position) {
face_t f;real b_val;
begin_f_loop(f, thread){
b_val = …/* your boundary value*/
F_PROFILE(f, thread, position) = b_val;}end_f_loop(f, thread)
}
thread : The thread of the boundary to which the profile is attached
position : A solver internal variable (identifies the stack location of the profile in the data stack)
User can rename the variables at will: DEFINE_PROFILE(my_prof, t, pos)
Boundary Profiles: DEFINE_PROFILE
You can use this UDF to specify
Wall temperatureheat flux, shear stress
Inlets velocitytemperatureturbulencespecies scalars
The macro begin_f_loop loops over all faces on the selected boundary threadThe F_PROFILE macro applies the value to face, f on the thread
User specified
name
Arguments from the solver to this UDF
It’s a must!
12
Inlet temperature is a function of mass averaged exit temperature
ID of exit boundary is taken from BC panel and is used to find exit face thread:exit_face_thread = Lookup_Thread(domain, exit_id);Thread of cells next to exit face is identified:cell_thread = THREAD_T0(exit_face_thread);
( )outin TfT =
∫ ∫=exit exit
out dVTdVT ρρ /
Inlet Temperature vs exit Temperature (1)
13
The following UDFs will be used :DEFINE_PROFILE
Identifies outlet thread from BC panel and identifies cells next to thread to perform mass averagingCalculates mass averaged temperature at outlet and stores itUses calculated mass averaged temperature and uses it as argument to calculate profile of inlet temperature
Inlet Temperature vs exit Temperature (1)
14
Inlet Temperature vs exit Temperature (1)
DEFINE_PROFILE(inlet_temperature, thread,nv){/* Loop through the faces of the exit surface*/
begin_f_loop(f1, exit_face_thread){
/* macro F_C0 is utilized to find neighbor cell*/cell0 = F_C0(f1, exit_face_thread);cell_temp = C_T(cell0, cell_thread);cell_vol = C_VOLUME(cell0, cell_thread);cell_density = C_R(cell0, cell_thread);cell_mass = cell_vol*cell_density;total_mass += cell_mass;total_mass_temp += cell_mass*cell_temp;
}end_f_loop(f1, exit_face_thread);
/* calculation of mass averaged T */exit_temp = total_mass_temp/total_mass;
}
/* Enter the T_inlet vs T_exit here */inlet_temp = exit_temp + 30.;
begin_f_loop(f2, thread){
F_PROFILE(f2, thread, nv) = inlet_temp;}
end_f_loop(f2, thread)}
cell0 = F_C0(f1, f_thread);
15
Inlet Temperature vs exit Temperature (1)
Application to flow in elbow with two inlets
inT
30TT outin +=
outT
16
Molecular membrane – openings are so small that molecules can be separated by sizeSeparation of gas species is possibleVery large pressure difference across membrane “squeezes” molecules throughConvective fluxe across membrane is effectively zeroMass flux across membrane for species i is
Permeance contains info on how “easily” molecules of species i can “squeeze” through membrane openings
Membrane modeling (2)
( )lowi
highiii PPQ −=φ
Membrane permeance of
species i
High partial pressure of
species i
Low partial pressure of
species i
iQ
17
Membrane is modeled as the inner wall which means that it cannot predict pressure drop (it is known). Macros F_C0 and F_SHADOW are used to find cell and thread pointers looking at both sides of membrane, i.e., high and low pressure sidesHaving access to variables at cells sharing membrane cell face allows to calculate mass flux of each species and prescribe volume sources of mass for species i at cells next to membrane
Membrane modeling (2)
Air+ less gasMixture inlet, air+gas, high pressure
Air+more gasMembrane surface (wall)
highPlowP
(f,memb_t)
cell_t c0= F_C0(f,memb_t)memb_t _shadow=
THREAD_SHADOW(memb_t)
pressure
18
Membrane modeling (2)
The following UDFs will be used:DEFINE_ADJUST
Identifies internal surface as a model of membraneAccesses cells on both sides of surface and calculates mass flux of each species and stores equivalent mass sources in User Defined Memory
DEFINE_SOURCEUses mass sources calculated in DEFINE_ADJUST to prescribe mass sources for every species and mixture
19
Membrane modeling (2)
DEFINE_ADJUST(filter_adjust, domain){…………………………./* find membrane thread by ID in BC panel*/memb_thread = Lookup_Thread(domain,memb_id);
/* looping over cells faces of membrane*/begin_f_loop (f, memb_thread){
/* get cell pointer for side of membrane on high pressure*/c0 = F_C0(f,memb_thread);
/* get face thread pointer for shadow membrane surface*/memb_thread_shadow = THREAD_SHADOW(memb_thread);
/* get face pointer for shadow membrane surface*/f_shadow = F_SHADOW(f,memb_thread);
/* get cell pointer from shadow side of membrane*/c1 = F_C0(f_shadow,memb_thread_shadow);
/* get cell thread pointer for side of membrane*/t0 = F_C0_THREAD(f,memb_thread);
/* get cell thread pointer for shadow side of membrane*/t1 =memb_thread_shadow->t0;
………
Membrane shadow face
Membrane face
20
Membrane modeling (2)
/* calculate molar concentration for side of membrane*/x_GAS_outer = molefrac(C_YI(c0, t0, 0), MW_GAS, MW_AIR);x_AIR_outer = 1.- x_N2_outer;/* calculate molar concentration for shadow side of membrane*/x_GAS_inner = molefrac(C_YI(c1, t1, 0), MW_GAS, MW_AIR);x_AIR_inner = 1.- x_N2_inner;/* calculate membrane face area*/
F_AREA(A, f, memb_thread);At = NV_MAG(A);
/* calculate species mass fluxes across the membrane, Pi=P*Xi*/flux_GAS = Q_GAS * ( x_GAS_outer*P_outer - x_GAS_inner*P_inner);flux_AIR = Q_AIR * ( x_AIR_outer*P_outer - x_AIR_inner*P_inner);tot_flux = tot_flux + MW_GAS*flux_GAS*At + MW_AIR*flux_AIR*At;
C_UDMI(c0, t0, 0) = - (MW_GAS*flux_GAS)*At/C_VOLUME(c0,t0);C_UDMI(c1, t1, 0) = (MW_GAS*flux_GAS)*At/C_VOLUME(c1,t1);
C_UDMI(c0, t0, 1) = -(MW_AIR*flux_AIR)*At/C_VOLUME(c0,t0);C_UDMI(c1, t1, 1) = (MW_AIR*flux_AIR)*At/C_VOLUME(c1,t1);
}end_f_loop (f, memb_thread)
High pressure and mole fraction
Low pressure and mole fraction
21
Membrane modeling (2)
66%94%Filter efficiency,mgas,outlet1/mgas,in
101Permeance ratio,Qgas/Qair
66%94%Filter efficiency,mgas,outlet1/mgas,in
101Permeance ratio,Qgas/Qair
Air+ less gas, outlet 1Mixture inlet, air+gas
Air+more gas, outlet 2
Gas mass fraction
22
Membrane modeling (2)
membrane
Species mass source in UDMI
Low species concentration
High species concentration
Velocity vectors
Mass transfer rate variation
23
Unsteady Staggered Particle Injection (3)
Unsteady DPM injection will release the particle packets at the beginning of every timestepA process is needed to inject particles at a certain user specified time interval so as to reduce the number of particles that need to be tracked inside the domainThe process will inject the particles at the beginning of a timestep and then store/accumulate the particles’ mass during the next timesteps when injections are turned offAt the time of the next injection, the accumulated particles’ mass will be injected There will be fewer particles but the particles’s mass will be preserved
24
Once an injection is completed, the starting time of injection can be moved forward in time by a user specified value using a UDF and the particles mass accumulated for the next injectionThe UDF will also move the injection locations as the exhaust location is moving
Unsteady Staggered Particle Injection (3)
25
The following UDFs will be needed to apply this trick to moving mesh example – launch of rocket from silo:
DEFINE_ADJUSTTrack the current exhaust locationAccumulate the particles’ mass when injection is not performed at atimestep
DEFINE_DPM_INJECTION_INITMove the injection locationInject the accumulated mass when injection interval is reached
DEFINE_CG_MOTIONSpecify the DM layering motion
DEFINE_RW_FILEWrite injection information to data file for restart
Other functionsPost processing, etc.
Unsteady Staggered Particle Injection (3)
26
Unsteady Staggered Particle Injection (3)
#include "udf.h"#include "dynamesh_tools.h"/*User specified injection release time interval*/#define RELEASE_STEP 5e-3/*Current exhaust location where injection is performed*/static real current_loc_exh = -3.9624;
#if !RP_NODEstatic int tmsp = 0;static real current_tm = -1.0;static real sum_inj = 0.0; /*Store the accumulated particles’ mass when injections are skipped*/#endif
27
Unsteady Staggered Particle Injection (3)
DEFINE_ADJUST (update, domain){#if !RP_NODE
real tm, tmspsz;real msl_vel, pflow;tm = RP_Get_Real("flow-time");tmspsz = RP_Get_Real("physical-time-step");if ( first_iteration ) /*first iteration of a timestep*/
{msl_vel = get_vel_msl(tm); /*Update missile velocity */current_loc_exh += msl_vel*tmspsz; /*&exhaust location*/pflow = get_mdot_prt(tm);sum_inj += mdot*tmspsz; /* Get the current particle flow rate &
store for later release */current_tm = tm;tmsp += 1;
}#endif}
28
DEFINE_DPM_INJECTION_INIT (init_prt_tm, I){#if !RP_NODEParticle *p;real tm, tmspsz, flowrate, eps=0.015;tm = RP_Get_Real("flow-time");tmspsz = RP_Get_Real("physical-time-step");flowrate = sum_inj/tmspsz; /*Release all the particles that are in store since the
last release*/loop(p,I->p_init) /*beginning of release of particles*/
{p->state.pos[0] = current_loc_exh - eps; /*Update release points due to movement of the exhaust location by MDM*/p->flow_rate = flowrate;
}if ((tm+tmspsz) >= I->unsteady_start) /*now release is delayed by moving injection time*/
I->unsteady_start += RELEASE_STEP; /*Move unsteady_start forward in time for next release*/
sum_inj = 0.0; /*Reset storage for mass of particles*/
#endif}
Unsteady Staggered Particle Injection (3)
This UDF is called only when DPM unsteady start time is smaller than current time
29
Application to missile silo launch. Staggered injections of particles are clearly seen. Contours of Ma number colored by particles with residence time
Non staggered injection
Staggered injection
Unsteady Staggered Particle Injection (3)
30
UDFs for Multiphase Flows
31
In multiphase flows each phase has its set of material properties and may have its own set of variables
For VOF model it is For Euler model it isFor Mixture model it is
Some variables and geometry are shared among phasesIn VOF it is , in Mixture it is , in Euler it is
Therefore, an architecture that stored the phases in separate overlaid Domains was devised.This new Multi-Domain construction can be thought of as multiple versions of Fluent running together, but which communicate between each other at the level of the cells.
The Multi-Domain Architecture
ikk Y,α
ikkkkkk YkTU ,,, , , εα
r
ikkk YU , ,
rα
ε , , , kTUr
ε , , kT ε ,k
32
The Multi-Domain ArchitectureAll the domains are in a hierarchy that has the “superdomain” at the top.The superdomain is where the “mixture” of the phases is stored and so is often called the “mixture domain”.Shared values such as global settings are stored in the superdomain.Each Phase has its own Domain known as a “subdomain” or “phase domain”.
superdomain
P1domainP0domain P2domain
Phase Domain Interaction
Phase Subdomains
33
The Multi-Domain Architecture
Each Thread is also in a hierachy that matches that of the domainsThe “superthreads” are where the “mixture” of the phases is stored and so are often called the “mixture threads”.Shared values such as the grid geometry are stored in the superthread.Each Phase has its own set of threads known as a “subthreads” or “phase threads”.
superthreads
P1threadsP0threads P2threads
Phase Thread Interaction
Phase Subthreads
34
Some data is shared by both types of the thread. The data is not repeated, but each thread points to the same data.
The most common example is the thread geometry.Many UDFs are passed a thread as a parameter. This thread is either a phase thread or a superthread. W
We may want the superthread of a phase thread We may want all the phase threads of a superthread.
There is a new set of macros to get this information about the hierarchy. These are discussed next.
The Multi-Domain Architecture
35
Getting Data for a Specific Phase
DEFINE_SOURCE(x_mom, cell, t, dS, eqn)
{
Thread *tm = THREAD_SUPER_THREAD(t);
/*thread tm will be a superthread, i.e., mixture*/
Thread **pt = THREAD_SUB_THREADS(mixture_thread);
/*pt is an array such that pt[0] is mixture thread, pt[1] first secondary phase thread, pt[2] second secondary phase thread etc.*/
real U_secondary = C_U(cell,pt[1]);
real U_primary = C_U(cell,t); /*or U_primary=C_U(cell,pt[0]); */
real P_mixture = C_P(cell,tm); etc.
Suppose that my momentum source for primary phase is equal (arbitrary): source = constant*(U_secondary-U_primary)*P_mixture. This means that primary phase thread will be passed as argument and I need to get mixture and secondary threads
36
Getting Data for a Specific Phase
Now let’s see how access variables when thread is not passed as an argument
DEFINE_ADJUST(area_density, domain){
Thread *t;Thread **pt;cell_t c;
mp_thread_loop_c (t,domain,pt) /* t is a mixture thread*/if (FLUID_THREAD_P(t ))
{Thread *tp = pt[0]; /* tp is a primary phase thread*/
Thread *ts = pt[1]; /* ts is a secondary thread*/begin_c_loop (c,t)
{C_UDMI(c,t,0) = C_VOF(c,tp)*C_T(c,ts);
}end_c_loop (c,t)
}}
37
Exchange Macros
DEFINE_EXCHANGE_PROPERTY( name, c, mixture_thread, second_column_phase_index,first_column_phase_index)Specifies net heat transfer rates between phases, and drag and lift coefficient functions
Eulerian Model – net heat transfer rate, drag coefficient, lift coefficientMixture Model – drag coeeficient
Phase specific variables can be accessed using first/second_column_phase index which correspond to phase order in Phase Interaction panel
secondcolumnphase
firstcolumnphase
38
Exchange Macros Drag Law for spherical cap bubbles (4)
Schiller-Naumann (default) drag coefficient is valid for spherical particles
Large bubbles have a shape of spherical cap and have constant drag coefficient
DEFINE_EXCHANGE_PROPERTY macro for drag force must return
( )
>≤+
=10004401000150124
f6870
drag Re.ReRe/Re. .
6672fdrag .=
,0)(1
=−∑=
n
ikiik uuK rr
ik
dragkkik
fK
τρα=
k
2ik
ik 18dµ
ρτ =
39
The following UDFs will be needed:DEFINE_ EXCHANGE_PROPERTY
Identify thread for each phaseCalculate drag coefficient
Exchange Macros Drag Law for spherical cap bubbles (4)
40
Exchange Macros Drag Law for spherical cap bubbles (4)
DEFINE_EXCHANGE_PROPERTY(large, c, m_t, s_index, f_index){Thread **pt = THREAD_SUB_THREADS(m_t);real drag_coeff, drag_force;real urel,urelx,urely,urelz,dbub;
dbub = C_PHASE_DIAMETER(c,pt[f_index]);drag_coeff =8/3; /*drag coefficient for large bubbles*/
urelx = C_U(c,pt[f_index]) - C_U(c,pt[s_index]);urely = C_V(c,pt[f_index]) - C_V(c,pt[s_index]);urelz = C_W(c,pt[f_index]) - C_W(c,pt[s_index]);urel = sqrt(urelx*urelx + urely*urely + urelz*urelz);drag_force = 0.75 * drag_coeff*C_R(c,pt[s_index])
* C_VOF(c,pt[s_index])* C_VOF(c,pt[f_index])* urel/dbub;
return drag_force;}
41
Exchange Macros Drag Law for spherical cap bubbles (4)
Free rising air bubbles in water
0
0.2
0.4
0.6
0.8
1
1.2
1.4
1.6
0 1 2 3 4 5 6 7
Bubble diameter, cm
Bub
ble
risin
g ve
loci
ty, m
/sec
experiment
constant drag
Schiller-Naumann drag
pinlet
poutlet
symmetry
gr
Bubble velocity
Comparison for single bubble rise velocity
42
Exchange Macros Drag Law for evaporating droplets (5)
Example – water droplets feely falling in dry air accompanied by evaporation
Water – single species mixture phaseAtmosphere – mixture of two species (air+vapor)Evaporation from droplets into air is modeled as heterogeneous reactionReaction rate is given by
( )drop
dropgasgasOHdropsatOHc dTCTCkrate
α6)()( ,2,2 −=
Molar concentrationArea density
43
Exchange Macros Drag Law for evaporating droplets (5)
The following macro will be usedDEFINE_HET_RXN_RATE
Identifies phases and species Computes reactions rate between species of different phases in kgmole/m3/sec
44
Exchange Macros Drag Law for evaporating droplets (5)
DEFINE_HET_RXN_RATE(vap_con,c,mt,f_in,f_sp,to_in,to_sp){
Thread **pt = THREAD_SUB_THREADS(t);Thread *tp = pt[0];Thread *ts = pt[1];real T_prim = C_T(c,tp); /*gas phase temperature*/real T_sec = C_T(c,ts); /*droplet phase temperature*/real diam = C_PHASE_DIAMETER(c,ts); /*gas phase diameter*/real D_evap_prim = C_DIFF_EFF(c,tp,index_evap_primary); /* laminar
diffusivity of evporating gas species*/C_UDMI(c,t,0) = D_evap_prim ;urelx = C_U(c,tp) - C_U(c,ts);urel = sqrt(urelx*urelx + urely*urely + urelz*urelz); /*slip velocity*/
Re = urel * diam * C_R(c,tp) / C_MU_L(c,tp); /*droplet Re number*/Sc = C_MU_L(c,tp) / C_R(c,tp) / D_evap_prim ; /*gas Sc number*/Nu = 2. + 0.6 * pow(Re, 0.5)* pow(Sc, 0.333); /*Nusselt number*/
45
Exchange Macros Drag Law for evaporating droplets (5)
mass_coeff = Nu * D_evap_prim / diam ; for (i=0; i < MAX_SPE_EQNS_PRIM ; i++) /*looping over gas species*/
{accum = accum + C_YI(c,tp,i)/mw[i][prim_index]; }
mole_frac_evap_prim = C_YI(c,tp,index_evap_primary ) /mw[index_evap_primary][prim_index] / accum; /* mole frac. of evap
species*/concentration_evap_primary = mole_frac_evap_prim * P_OPERUNIVERSAL_GAS_CONSTANT / T_prim ; /* mole conc. of evap species */concentration_sat = psat_h2o(T_sec) / UNIVERSAL_GAS_CONSTANT /
T_sec ; /* saturation conc. of evap species */area_density = 6. * C_VOF(c,ts) / diam ;flux_evap = mass_coeff * (concentration_sat -
concentration_evap_primary ) ;rr* = area_density * flux_evap;
}
46
Exchange Macros Drag Law for evaporating droplets (5)
gr
droplets
dry air
Vapor molefraction
Saturated air
Evaporationrate
47
Parallel Fluent
Print messages
“(%iterate 5)”
mes
sage
s“(
%ite
rate
5)”
Cortex Host
Compute-Node-0
Compute-Node-1
Compute-Node-2
Compute-Node-3
“(%
itera
te5)
”
“(%ite
rate
5)”
“(%iterate 5)”
mes
sage
s
Print messages
Compute nodes labeled consecutively starting at 0Host labeled 999999Host connected to Cortex Each compute node (virtually) connected to every other compute node
“(%
itera
te5)
”“(
%ite
rate
5)”
48
Compiler Directives
“#if” is a compiler directive; Similar to “#define”A “#endif” is used to close a “#if#if RP_NODE /* Compute-Node */#if RP_HOST /* Host */#if PARALLEL /* Equivalent to #if RP_HOST||RP_NODE*/#if !PARALLEL /* Serial, ! means logical negation */#if RP_HOST
Message(“I’m the Host process \n”);#endif#if RP_NODE
Message(“I’m the Node process number:%d \n”, myid);#endif
49
• Although compute nodes can perform computations on data simultaneously when FLUENT is running in parallel, when data is written to a single, common file, the writing operations have to be sequential
• The file has to be opened and written to by processes that have access to the desired file system
• This means that all of the data has to be written from the host process which always runs on a machine with access to a file system, since it reads and writes the case and data files
• file writing in parallel is done in the following stages• The host process opens the file• Compute node-0 sends its data to the host• The other compute nodes send their data to compute node-0• Compute node-0 receives the data from the other compute nodes
and sends it to the host• The host receives the data sent from all the compute nodes and
writes it to the file• The host closes the file
Writing files in parallel (6)
50
Writing files in parallel (6)
• Pressure is written out at the end of the simulation for FEA analysis. The data structure is the coordinates of a face followed by the pressure of the face
• PRF_CRECV_INT(myid - 1, &dummy, 1, myid - 1) - message passing macro which sends sections of data as single arrays fromone process to another process. It is used to make non-zero node wait till node-0 is writing into the file• myid – 1 since myid > 0, than node-myid will wait for data from
node myid-1• &dummy – just a dummy vaiable meaning nothing• 1 – means that just one variable is being sent (dummy)• myid-1 – just a syntax
51
Writing files in parallel (6)
The following UDFs will be needed:DEFINE_ ON_DEMAND
Identifies a node numberIf node number is more than zero, waits till all nodes with lower numbers write their data and than appends to file to write its share of dataIf it is node zero – opens file and writes data first
52
Writing files in parallel (6)
# include "udf.h“# define WALLID 3 /*id of wall for which pressure data will be written*/DEFINE_ON_DEMAND(Write_pressure){real position[ND_ND]; /*vector definition to write coordinates of cell face*/int dummy;Domain *domain;Thread *tf;face_t f;FILE * fp;domain=Get_Domain(1);
/* Node 0 will open a NEW file while node 1, 2, ... will wait. After node 0 finishes,Node 1 will open the SAME file while node 2, 3 ... will wait. This goes on. */#if RP_NODEif (! I_AM_NODE_ZERO_P) PRF_CRECV_INT(myid - 1, &dummy, 1, myid - 1);fp = fopen("pressure.txt", (I_AM_NODE_ZERO_P ? "w" : "a"));
#elsefp = fopen("pressure.txt", "w");
#endif tf=Lookup_Thread(domain, WALLID);
53
Writing files in parallel (6)begin_f_loop(f,tf)
{F_CENTROID(position, f, tf);#if RP_2D
fprintf(fp, "%10.3e %10.3e %10.3e\n",position[0], position[1], F_P(f,tf));
#elsefprintf(fp, "%10.3e %10.3e %10.3e %10.3e\n",
position[0], position[1], position[2], F_P(f,tf));#endif
}end_f_loop(f,tf)
/* After the node finishes, it will close the file and send a signal saying I am done so that the next node can start */#if RP_NODE
fclose(fp);if (! I_AM_NODE_LAST_P) PRF_CSEND_INT(myid + 1, &dummy, 1,
myid);#else
fclose (fp); #endif }
54
Moving and Deforming Mesh + Variable Time Step (7)
You can use the DEFINE_CG_MOTION macro to specify the motion of a particular dynamic zone in FLUENT by providing FLUENT with the linear and angular velocities at every time step. FLUENT uses these velocities to update the node positions on the dynamic zone based on solid-body motion. Note that UDFs that are defined using DEFINE_CG_MOTION can only be executed as compiled UDFs.DEFINE_CG_MOTION ( name, dt, vel, omega, time,dtime)
dt i pointer to the structure that stores the dynamic mesh attributes that you have specifiedvel – velocity vetoromega – angular velocity vectortime - current physical timedtime - time step
This macro overwrites vel and omega vectors which are used to update body position
55
Moving and Deforming Mesh + Variable Time Step (7)
Coupled dynamic mesh problem adjusts the motion of the moving body/surfaces based on the current computed aerodynamic load andapplied external forcesAn optimum ‘mean’ timestep size that will apply generally for the duration of the coupled motion is difficult to obtain since the aerodynamic load is not known a prioriContinual and manual adjustment of the timestep size is required to avoid using an excessively conservative value that will increaserunning time or too large value that will cause the dynamic remeshingto failIt is possible to implement a user defined variable timestep size using UDFThe variable timestep size is computed subject to the following constraints:
User specifies maximum allowable translational distanceUser specifies maximum allowable timestep size value
56
Moving and Deforming Mesh + Variable Time Step (7)
A relation is needed to solve for the timestep size and velocity of the body:The timestep size and the corresponding velocity of the body are such that the body will move by the maximum allowable translational distanceA cap on the timestep size is necessary to prevent an excessively large computed timestep size which can result in divergenceThe maximum allowable translational distance can be varied as function of time, if necessary
The timestep size and body velocity are obtained by solving a quadratic equation derived from the following two relations:
dtVV
MF
dtVh
nn
nmax
−=
×=
+
+
1
1
dt
mF
nV1+nV
maxh = maximum allowable distance traveled
= force_acting_on_body/mass_of_body
= body velocity at previous timestep
= body velocity at next timestep (uknown)
= next timestep size (unknown)
57
Moving and Deforming Mesh + Variable Time Step (7)
The following UDFs will be needed:DEFINE_EXECUTE_AT_END
Compute the forces on the bodyCompute the next timestep size and body velocity subject to the maximum allowable translational distance specified by the user
DEFINE_CG_MOTIONSpecify the MDM motion
DEFINE_RW_FILESave intermediate variables to data file for restart
58
Moving and Deforming Mesh + Variable Time Step (7)
#include "udf.h"#include "sg_mem.h"#include "dynamesh_tools.h“#define PI 3.14159265#define usrloop(n,m) for(n=0;n<m;++n)/*----- User needs to change the section below ----------------*/#define zoneID 28 /* zone ID for the moving boundary */#define b_mass 1.0 /* mass of the body */#define dtm_mx 0.005 /* maximum allowable timestep size *//*----- Layering parameters -------------------------------------------*/#define hc 6.1e-5 /* ideal cell height in meter */#define nc 4.0 /* parameter for advancing layer speed */#define hmove hc/nc /* maximum allowable translation *//*----- Global variables --------------------------------------------------*/real V_body[ND_ND]; /* velocity vector of body */real b_ctr = 0.0; /* gravity center center location */real tmsize = 0.00001; /* current computed timestep size */
59
Moving and Deforming Mesh + Variable Time Step (7)
DEFINE_EXECUTE_AT_END(exec_end){
real tm, dtm, Velx, Vn, Fm;real x_cg[3], f_glob[3], m_glob[3];
Domain *domain = Get_Domain(1);Thread *tf =
Lookup_Thread(domain,zoneID);tm = RP_Get_Real("flow-time");/* Reset arrays to 0 */usrloop(m,ND_ND) x_cg[m] = 0.0;usrloop(m,ND_ND) f_glob[m] = 0.0;usrloop(m,ND_ND) m_glob[m] = 0.0;/* Get the previous c.g. for the
ball zone */x_cg[0] = b_ctr;/* Compute the forces on the body */Compute_Force_And_Moment
(domain,tf,x_cg,f_glob,m_glob,TRUE);
/* Compute velocity and timestepsize from quadratic equation */
Vn = V_body[0];Fm = f_glob[0]/b_mass;dtm = ( -fabs(Vn) + sqrt( Vn*Vn +
4.0*fabs(Fm)*hmove ) )/( 2.0*fabs(Fm) );
if ( dtm > dtm_mx ) dtm = dtm_mx;Velx = Vn + Fm*dtm;if ( (x_cg[0]<=(-Smax))||
(x_cg[0]>=Smax) ) Velx = 0.0;/* Update velocities, timestep size,
and ball c.g. location */V_body[0] = Velx;tmsize = dtm;b_ctr += V_body[0]*tmsize;
RP_Set_Real("physical-time-step",tmsize);}
60
Moving and Deforming Mesh + Variable Time Step (7) DEFINE_RW_FILE(reader,fp)
{int m;
#if !RP_NODEfloat v_read;usrloop(m,ND_ND)
{fscanf(fp,"%e\n",&v_read);V_ball[m] = (real)v_read;
}fscanf(fp,"%e\n",&v_read); b_ctr =
(real)v_read;fscanf(fp,"%e\n",&v_read); tmsize =
(real)v_read;#endif
usrloop(m,ND_ND) host_to_node_real_1(V_ball[m]);
host_to_node_real_1(b_ctr);host_to_node_real_1(tmsize);
}
DEFINE_RW_FILE(writer,fp){#if !RP_NODE
int m;usrloop(m,ND_ND)
fprintf(fp,"%e\n",V_ball[m]);fprintf(fp,"%e\n",b_ctr);fprintf(fp,"%e\n",tmsize);
#endif}
DEFINE_CG_MOTION (body_motion, cg_omega, dt, cg_vel, time, dtime){
/* Reset velocities */NV_S(cg_vel, =, 0.0);NV_S(cg_omega, =, 0.0);/* Assign the linear velocity */cg_vel[0] = V_body[0];
}
61
Moving and Deforming Mesh + Variable Time Step (7)
X_CG comparison
-2
-1
0
1
2
3
4
5
6
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7
time (s)
x_cg
(m)
old-x_cg[0]srl-var-x_cg[0]old-x_cg[1]srl-var-x_cg[1]old-x_cg[2]ser-var-x_cg[2]
Store Separation
Comparison of coordinatesof CG with and without UDF
CPU time spent on single processor:3 days – without UDF1.5 days – with UDF
62
Appendix
63
User Defined Memory (UDM)
User-allocated memory Allow users to allocate memory (up to 500 locations) to store and retrieve the values of field variablesfield variables computed by UDF’s (for postprocessing and use by other UDFs)Same array dimension and size as any flow variableMore efficient storage compared to User Defined Scalars: UDMs are not solved forNumber of User-Defined Memory Locations is specified in the User-Defined Memory panel Accessible via macros
Cell values: C_UDMI(c,t,i)Face values: F_UDMI(f,t,i)
Saved to FLUENT data file
500500
64
User Defined Memory
DEFINE_ON_DEMAND(scaled_temp){
Domain *domain = Get_domain(1);/* Compute scaled temperature store in user-defined memory */thread_loop_c(t,domain){ begin_c_loop(c,t){
temp = C_T(c,t);C_UDMI(c,t,0)=(temp - tmin)/(tmax-tmin);
}end_c_loop(c,t)}
}
65
Filter Blockage (8)
• Trap of particles within a porous filter and analysis of the dust build up influencing the flow
• The trapping of particles is stochastic, which would imply using many runs and finding where particles get stopped
• A simpler approach is possible
• A porous region is defined as the filter in a Cylinder • Particle tracks passing through this region are not stopped but their
flow rate is decreased to represent expected probability of a particle being present
• This approach means that the flow can be run as a series of quasi steady runs with gradual build up of the blockage effect
66
Filter Blockage (8)
The following UDFs will be needed:DEFINE_DPM_LAW
Identifies when Discrete Particle is within area assigned to filterInside the filter, decreases mass flow rate based on particle time to model decreased probability of particle caought by filterStores into USER Defined memory decrease in mass flow rate of particles
DEFINE_DPM_DRAGModifies particle Re number in drag law inside the filter. Re number should be increased because physical velocity of continuous fluid is higher due to porosity
67
• A UDF will also get run if you are just displaying the Particles• The parameter “coupled” is true for flow-coupled DPM iterations, but false
for post-processing with “particle tracks”• DPM_LAW is run once after every drag run• Energy must be enabled for a UDF Law to be runDEFINE_DPM_LAW(dpm_law,p,coupled){ real pos[ND_ND];
real old_flow_rate;cell_t c = P_CELL(p); /*pointer to cell where particle is*/Thread *t = P_CELL_THREAD(p); /*pointer to cell thread where particle is*/C_CENTROID(pos,c,t);if((pos[2]>ZMIN)&&(pos[2]<ZMAX)&&(pos[0]<XMAX)){old_flow_rate= P_FLOW_RATE(p);P_FLOW_RATE(p) = old_flow_rate*pow(TIME_EXP, -(P_TIME(p)-P_TIME0(p))/TIME_CONST);C_UDMI(c,t,0) += old_flow_rate-P_FLOW_RATE(p);}
}
Filter Blockage (8)
( ) CONSTTIMEoldtnewtoldp
newp EXPTIMEmm _/___ −−⋅= &&
68
As a small addition to this model we can modify the drag to take into account the effect of the higher true flow speed in the porous region
DEFINE_DPM_DRAG(drag,Re,p){
real Cd=1.0;real pos[ND_ND];cell_t c;Thread *t;c=P_CELL(p); t=P_CELL_THREAD(p);C_CENTROID(pos,c,t);if((pos[2]>ZMIN) && (pos[2]<ZMAX) && (pos[0]<XMAX)){Re*=2.0 - BLOK*C_UDMI(c,t,0);} /*flow speed higher in porous region*/return 18.0*Cd*Re/24.0;
}
Filter Blockage (8)
69
Filter Blockage (8)
The particle tracks below are colored to show the flow rate of dust (in kg/s) along each path line.
Note how the tracks passing through the filter decrease in flow rate. The particles themselves are the same size and mass, just the rate or “Strength” is decreased
70
Filter Blockage (8)
• The rate of material buildup can be stored in a UDM location• This value can then be used to vary the resistance of the porous region using a momentum source UDF
• Dust build up shown on the computational cells
71
Erosion Model Customization (9)
• Fluent6 already has a erosion model• A tutorial is available• This UDF essentially illustrates how to customize
erosion modeling in Fluent using DPM hooks• Erosion rate is a function of
• Angle of impingement• Impact velocity• Particle diameter• Particle mass• Collision frequency between particles and solid
walls• Material type
72
Erosion Model Customization (9)
m : mass flow rate of the particlesf(α): function of impingement angle aV : impact velocityb : velocity exponentC(Dp): function of particle diameter
Rm C D f V
Aerosionp p
b V
facep
N particles
=
•
=∑ ( ) ( ) ( )α
1
Reflecting Walls
Reflection Coefficient: en=v2,n/v1,n
a1 a2
Reflecting Walls
Reflection Coefficient: en=v2,n/v1,n
a1 a2a1 a2
0
0.2
0.4
0.6
0.8
1
1.2
0 10 20 30 40 50 60 70 80 90Impact Angle (α)
f(a)
Relationship between the impact angle and function f(α)
73
Erosion Model Customization (9)
The following UDFs will be needed:DEFINE_DPM_EROSION
Calculates erosion rate as prescribed by equation
74
Erosion Model Customization (9)
#include "udf.h"#define DEG_TO_RAD(x) ((M_PI*x/180.0))DEFINE_DPM_EROSION(custom_erosion, part, t, f, n, theta, vel, mdot){real er, f_theta, Avec[ND_ND];
real A = 1e-9,a=30,b=-34.79,c = 12.3,n=1.73;/*model constants*/a = DEG_TO_RAD(a);
if (theta <= a)f_theta = b*theta*theta + c*theta;else { /* You may add newer erosion models */ }
/*Removed mass per unit area per unit time (kg/m2s*/er = A*pow(vel, n)*f_theta; F_AREA(Avec, f, t);er *= mdot/NV_MAG(Avec);F_STORAGE_R(f, t, SV_DPMS_EROSION) = er;
}
75
Erosion Model Customization (9)
• Remember also to set up DPM properties on wall
• Reflection coefficients for tangential and normal components
• Also provide the erosion model data • Impact angle • Velocity exponents• Diameter function
76
Closure
In this lecture we have shown several examples of application ofUDF to real world problemEmphasis was given on strategy of UDF implementation, i.e., which macros were used, how macros exchanged information etc.The examples customized boundary conditions (surface and fluid zones), DPM, multiphase momentum exchange, parallel issue, moving and deforming mesh, customized time step and other physical and numerical aspects of modelsSpecial thanks to Fluent staff who contributed to this lecture
Adam Anderson (Fluent Europe)Xiao Hu (Fluent Michigan)Shitalkumar Joshi (Fluent India)Rafi Khan (Fluent New Hampshire)Sutikno Wirogo (Fluent New Hampshire)