3.3. Looping Macros

Many UDF tasks require repeated operations to be performed on nodes, cells, and threads in a computational domain. For your convenience, Ansys Fluent has provided you with a set of predefined macros to accomplish looping tasks. For example, to define a custom boundary profile function you will need to loop over all the faces in a face thread using begin..end_f_loop looping macros. For operations where you want to loop over all the faces or cells in a domain, you will need to nest a begin..end_f_loop or begin..end_c_loop inside a thread_loop_f or thread_loop_c, respectively.

The following general looping macros can be used for UDFs in single-phase or multiphase models in Ansys Fluent. Definitions for these macros are contained in the mem.h header file.


Important:  You should not access a Scheme variable using any of the RP_GET_... functions from inside a cell or face looping macro (c_loop or f_loop). This type of communication between the solver and cortex is very time consuming and therefore should be done outside of loops.


3.3.1. Looping Over Cell Threads in a Domain (thread_loop_c)

You can use thread_loop_c when you want to loop over all cell threads in a given domain. It consists of a single statement, followed by the operation(s) to be performed on all cell threads in the domain enclosed within braces   as shown below. Note that thread_loop_c is similar in implementation to the thread_loop_f macro described below.

 Domain *domain;
 Thread *c_thread;
 thread_loop_c(c_thread, domain) /*loops over all cell threads in domain*/
  {
  } 

3.3.2. Looping Over Face Threads in a Domain (thread_loop_f)

You can use thread_loop_f when you want to loop over all face threads in a given domain. It consists of a single statement, followed by the operation(s) to be performed on all face threads in the domain enclosed within braces   as shown below. Note that thread_loop_f is similar in implementation to the thread_loop_c macro described above.

 Thread *f_thread;
 Domain *domain;
 thread_loop_f(f_thread, domain)/* loops over all face threads in a domain*/
  {
  } 

3.3.3. Looping Over Cells in a Cell Thread (begin...end_c_loop)

You can use begin_c_loop and end_c_loop when you want to loop over all cells in a given cell thread. It contains a begin and end loop statement, and performs operation(s) on each cell in the cell thread as defined between the braces  . This loop is usually nested within thread_loop_c when you want to loop over all cells in all cell threads in a domain.

 cell_t c;
 Thread *c_thread;
 begin_c_loop(c, c_thread) /* loops over cells in a cell thread */
  {
  }
 end_c_loop(c, c_thread) 

Example

 /* Loop over cells in a thread to get information stored in cells. */
  begin_c_loop(c, c_thread)
  {
  /* C_T gets cell temperature. The += will cause all of the cell
   temperatures to be added together. */
   temp += C_T(c, c_thread);
  }
  end_c_loop(c, c_thread)
 } 

3.3.4. Looping Over Faces in a Face Thread (begin...end_f_loop)

You can use begin_f_loop and end_f_loop when you want to loop over all faces in a given face thread. It contains a begin and end loop statement, and performs operation(s) on each face in the face thread as defined between the braces  . This loop is usually nested within thread_loop_f when you want to loop over all faces in all face threads in a domain.

 face_t f;
 Thread *f_thread;
 begin_f_loop(f, f_thread) /* loops over faces in a face thread */
  {
  }
 end_f_loop(f, f_thread) 

Example

 /* Loop over faces in a face thread to get the information stored on faces. */
  begin_f_loop(f, f_thread)
  {
   /* F_T gets face temperature. The += will cause all of the face
    temperatures to be added together. */
   temp += F_T(f, f_thread);
  }
  end_f_loop(f, f_thread) 

3.3.5. Looping Over Faces of a Cell (c_face_loop)

The following looping function loops over all faces of a given cell. It consists of a single loop statement, followed by the action to be taken in braces.

 cell_t c;
 Thread *t;
 face_t f;
 Thread *tf;
 int n;
 c_face_loop(c, t, n)   /* loops over all faces of a cell */
  {
  .
  .
  .
  f = C_FACE(c,t,n);
  tf = C_FACE_THREAD(c,t,n);
  .
  .
  .
  } 

The argument n is the local face index number. The local face index number is used in the C_FACE macro to obtain the global face number (for example, f = C_FACE(c,t,n)).

Another useful macro that is often used in c_face_loop is C_FACE_THREAD. This macro is used to reference the associated face thread (for example, tf = C_FACE_THREAD(c,t,n)).

Refer to Miscellaneous Macros for other macros that are associated with c_face_loop.

3.3.6. Looping Over Nodes of a Cell (c_node_loop)

c_node_loop(c,t,n) is a function that loops over all nodes of a given cell. It consists of a single loop statement, followed by the action to be taken in braces {}.

Example:

 cell_t c;
 Thread *t;
 int n;
 Node *node;
 c_node_loop(c,t,n)
  {
  .
  .
  node = C_NODE(c,t,n);
  .
  .
  } 

Here, n is the local node index number. The index number can be used with the C_NODE macro to obtain the global cell node number (for example, node = C_NODE(c,t,n)).

3.3.7. Looping Over Nodes of a Face (f_node_loop)

f_node_loop(f,t,n) is a function that loops over all nodes of a given face. It consists of a single loop statement, followed by the action to be taken in braces {}.

Example

 face_t f;
 Thread *t;
 int n;
 Node *node;
 f_node_loop(f,t,n)
  {
  .
  .
  .
  node = F_NODE(f,t,n);
  .
  .
  .
  }

Here, n is the local node index number. The index number can be used with the F_NODE macro to obtain the global face node number (for example, node = F_NODE(f,t,n)).

See DEFINE_GRID_MOTION for an example of a UDF that uses f_node_loop.

3.3.8. Overset Mesh Looping Macros

This section contains descriptions of looping macros that can be used for cases that have overset meshes. For further information about overset meshes, see Overset Meshes in the User's Guide.

3.3.8.1. Looping Over Overset Interface Cell Threads (thread_loop_overset_c)

You can use thread_loop_overset_c when you want to loop over only the cell threads participating in the overset interfaces for a given domain (as opposed to the thread_loop_c function, which is for operations that need to be performed across all cell threads in the domain). It consists of a single statement, followed by the operations (enclosed within parentheses, as shown in the example that follows) to be performed on all the cell threads related to the overset interfaces in the domain.

 Domain *domain;
 Thread *c_thread;
 thread_loop_overset_c(c_thread, domain) /*loops over all cell threads participating in overset */
                                         /*interfaces in the domain                             */
  {
  } 

3.3.8.2. Looping Over Active Overset Cells in a Cell Thread (begin...end_c_loop_active, begin…end_c_loop_solve)

The cells in a domain with overset meshes may be classified into two broad categories: active cells and dead (inactive) cells. This classification is important with regards to the solver discretization (gradient evaluations, sources, AMG system, and so on) and the solution variables. Active cells may further be divided into solve cells and receptor (interpolation) cells (see Overset Field Functions in the User's Guide).

Therefore, a generalization of begin_c_loop and end_c_loop for overset meshes is available. The two loops are:

  • begin_c_loop_active

  • begin_c_loop_solve

The active function loops over all cells except dead (inactive) cells. The solve loop is restricted to active cells where no interpolation is performed (that is, receptor cells are excluded). It is recommended that you use overset specific loops when global operations are performed, such as the evaluation of minimum or maximum values in the cell thread, or the summation over cell threads. The choice to include receptor cells in these evaluations will determine the choice of loops, and is left to your discretion.


Note:  Global summations over all active or solve cells in all cell threads may still introduce an error due to mesh overlap in an overset mesh. For details, see Overset Postprocessing Limitations.


You can use begin_c_loop_active and end_c_loop_active or begin_c_loop_solve and end_c_loop_solve when you want to loop over all active or solve cells, respectively, in a given cell thread. These functions contain a begin and end loop statement, and perform operations (enclosed within parentheses, as shown in the example that follows) on each cell in the cell thread. Such loops are usually nested within thread_loop_overset_c, so that they loop over cells in only the cell threads participating in the overset interface in a domain; you may also nest them under thread_loop_c.

 cell_t c;
 Thread *c_thread;
 begin_c_loop_active(c, c_thread) /* loops over solve + receptor cells in a cell thread, no dead cells */
  {
  }
 end_c_loop_active(c, c_thread) 

cell_t c;
 Thread *c_thread;
 begin_c_loop_solve(c, c_thread) /* loops over solve cells in a cell thread, no receptor or dead cells */
  {
  }
 end_c_loop_solve(c, c_thread) 
3.3.8.2.1. Example 1
/* Loop over solve cells in a thread and perform arithmetic averaging of Temperature. */
  real no_solve_cells;
  real avg_temp_solve=0.0;
  begin_c_loop_solve(c, c_thread)
  {
  /* C_T gets cell temperature. The += causes all cell temperatures to be added together. */
   avg_temp_solve += C_T(c, c_thread); 
   no_solve_cells=no_solve_cells+1.0;	
  }
  end_c_loop_solve(c, c_thread)
 } 
 avg_temp_solve = avg_temp_solve/no_solve_cells; 
3.3.8.2.2. Example 2
/* Loop over active cells (solve + receptor) in a thread and perform arithmetic averaging of Temperature. */
  real no_active_cells;
  real avg_temp_active=0.0;
  begin_c_loop_active(c, c_thread)
  {
  /* C_T gets cell temperature. The += causes all cell temperatures to be added together. */
   avg_temp_active += C_T(c, c_thread); 
   no_cells_active = no_cells_active+1.0;	
  }
  end_c_loop_active(c, c_thread)
 } 

avg_temp_active = avg_temp_active/no_active_cells; 

3.3.8.3. Looping Over Faces in a Face Thread with Overset Mesh (begin...end_f_loop_active)

Similar to the cell loops, you can use begin_f_loop_active and end_f_loop_active when you want to loop over all of the faces in a given face thread, excluding the overset interface and dead faces. The overset dead faces are defined as faces that lie adjacent to a dead cell for a boundary thread and between two dead cells when they are part of an interior face thread. The overset interface face is defined as a face that

  • lies on an overset boundary thread adjacent to a receptor cell

  • separates active cells from dead cells (that is, between receptor and dead cells)

Figure 3.3: Overset Interface Example

Overset Interface Example

Figure 3.3: Overset Interface Example shows the overset interface before and after intersection (on the left and right side, respectively), so that the location of dead cells are apparent. The bottom row shows the overset cell type field contour plot for one of the component meshes (cyan = receptor, red = donor, yellow = solve). This figure illustrates that an overset interface face can lie either on the overset boundary thread or between receptor and dead cells.

This loop allows face-based operations from being adversely affected by dead or inactive cells. It contains a begin and end loop statement, and performs operations (enclosed within parentheses, as shown in the example that follows) on each face in the face thread. This loop is usually nested within thread_loop_f, so that it loops over all of the faces in all face threads in a domain.

 face_t f;
 Thread *f_thread;
 begin_f_loop_active(f, f_thread) /* loops over all active faces in a face thread */
  {
  }
 end_f_loop_active(f, f_thread) 
3.3.8.3.1. Example
/* Loop over active faces in a face thread to get the information stored on faces. */ 
  real no_active_faces;
  real avg_temp_active=0.0;
  begin_f_loop_active(f, f_thread)
  {
   /* F_T gets face temperature. The += causes all face temperatures to be added together. */
   avg_temp_active += F_T(f, f_thread);
   no_active_faces = no_active_faces + 1.0; 
  }
  end_f_loop_active(f, f_thread) 

  avg_temp_active /= no_of_active_faces;

3.3.9. Multiphase Looping Macros

This section contains a description of looping macros that are to be used for multiphase UDFs only. They enable your function to loop over all cells and faces for given threads or domains. Refer to Multiphase-specific Data Types and, in particular, Figure 1.5: Domain and Thread Structure Hierarchy for a discussion on hierarchy of structures within Ansys Fluent.

3.3.9.1. Looping Over Phase Domains in Mixture (sub_domain_loop)

The sub_domain_loop macro loops over all phase domains (subdomains) within the mixture domain. The macro steps through and provides each phase domain pointer defined in the mixture domain as well as the corresponding phase_domain_index. As discussed in Multiphase-specific Data Types, the domain pointer is needed, in part, to gain access to data within each phase. Note that sub_domain_loop is similar in implementation to the sub_thread_loop macro described below.

 int phase_domain_index; /* index of subdomain pointers */
 Domain *mixture_domain;
 Domain *subdomain;
 sub_domain_loop(subdomain, mixture_domain, phase_domain_index) 

The variable arguments to sub_domain_loop are subdomain, mixture_domain, and phase_domain_index. subdomain is a pointer to the phase-level domain, and mixture_domain is a pointer to the mixture-level domain. The mixture_domain is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a domain variable argument (for example, DEFINE_ADJUST) and your UDF is hooked to the mixture. If mixture_domain is not explicitly passed to your UDF, you will need to use another utility macro to retrieve it (for example, Get_Domain(1)) before calling sub_domain_loop (see Domain Pointer (Get_Domain)). phase_domain_index is an index of subdomain pointers. phase_domain_index is 0 for the primary phase, and is incremented by one for each secondary phase in the mixture. Note that subdomain and phase_domain_index are set within the sub_domain_loop macro.

Example

The following interpreted UDF patches an initial volume fraction for a particular phase in a solution. It is executed once at the beginning of the solution process. The function sets up a spherical volume centered at 0.5, 0.5, 0.5 with a radius of 0.25. A secondary-phase volume fraction of 1 is then patched to the cells within the spherical volume, while the volume fraction for the secondary phase in all other cells is set to 0.

 /*****************************************************************
   UDF for initializing phase volume fraction
 ******************************************************************/
 
 #include "udf.h"
 
 /* domain pointer that is passed by INIT function is mixture domain */
 DEFINE_INIT(my_init_function, mixture_domain)
 {
    int phase_domain_index;
    cell_t cell;
    Thread *cell_thread;
    Domain *subdomain;
    real xc[ND_ND];
    /* loop over all subdomains (phases) in the superdomain (mixture) */
    sub_domain_loop(subdomain, mixture_domain, phase_domain_index)
    {
    /* loop if secondary phase */
    if (DOMAIN_ID(subdomain) == 3)
    /* loop over all cell threads in the secondary phase domain */
    thread_loop_c (cell_thread,subdomain)
    {
     /* loop over all cells in secondary phase cell threads */
     begin_c_loop (cell,cell_thread)
     {
      C_CENTROID(xc,cell,cell_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)
      /* set volume fraction to 1 for centroid */
      C_VOF(cell,cell_thread) = 1.;    else
      /* otherwise initialize to zero */
      C_VOF(cell,cell_thread) = 0.;
     }
     end_c_loop (cell,cell_thread)
    }
   }
 } 

3.3.9.2. Looping Over Phase Threads in Mixture (sub_thread_loop)

The sub_thread_loop macro loops over all phase-level threads (subthreads) associated with a mixture-level thread. The macro steps through and returns the pointer to each subthread as well as the corresponding phase_domain_index. As discussed in Multiphase-specific Data Types, if the subthread pointer is associated with an inlet zone, then the macro will provide the pointers to the face threads associated with the inlet for each of the phases.

 int phase_domain_index;
 Thread *subthread;
 Thread *mixture_thread;
 sub_thread_loop(subthread, mixture_thread, phase_domain_index) 

The variable arguments to sub_thread_loop are subthread, mixture_thread, and phase_domain_index. subthread is a pointer to the phase thread, and mixture_thread is a pointer to the mixture-level thread. The mixture_thread is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a thread variable argument (for example, DEFINE_PROFILE) and your UDF is hooked to the mixture. If the mixture_thread is not explicitly passed to your UDF, you will need to use a utility macro to retrieve it before calling sub_thread_loop. phase_domain_index is an index of subdomain pointers that can be retrieved using the PHASE_DOMAIN_INDEX macro. (See Phase Domain Index (PHASE_DOMAIN_INDEX) 0 for the primary phase, and is incremented by one for each secondary phase in the mixture. Note that subthread and phase_domain_index are initialized within the sub_thread_loop macro definition.

3.3.9.3. Looping Over Phase Cell Threads in Mixture (mp_thread_loop_c)

The mp_thread_loop_c macro loops through all cell threads (at the mixture level) within the mixture domain and provides the pointers of the phase-level (cell) threads associated with each mixture-level thread. This is nearly identical to the thread_loop_c macro (Looping Over Cell Threads in a Domain (thread_loop_c)) when applied to the mixture domain. The difference is that, in addition to stepping through each cell thread, the macro also returns a pointer array (pt) that identifies the corresponding phase-level threads. The pointer to the cell thread for the ith phase is pt[i], where i is the phase_domain_index. pt[i] can be used as an argument to macros requiring the phase-level thread pointer. phase_domain_index can be retrieved using the PHASE_DOMAIN_INDEX macro. (See Phase Domain Index (PHASE_DOMAIN_INDEX)

 Thread **pt;
 Thread *cell_threads;
 Domain *mixture_domain;
 mp_thread_loop_c(cell_threads, mixture_domain, pt) 

The variable arguments to mp_thread_loop_c are cell_threads, mixture_domain, and pt. cell_threads is a pointer to the cell threads, and mixture_domain is a pointer to the mixture-level domain. pt is an array pointer whose elements contain pointers to phase-level threads.

mixture_domain is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a domain variable argument (for example, DEFINE_ADJUST) and your UDF is hooked to the mixture. If mixture_domain is not explicitly passed to your UDF, you will need to use another utility macro to retrieve it (for example, Get_Domain(1), described in Domain Pointer (Get_Domain)). Note that the values for pt and cell_threads are set within the looping function.

mp_thread_loop_c is typically used along with begin_c_loop. begin_c_loop loops over cells in a cell thread. When begin_c_loop is nested within mp_thread_loop_c, you can loop over all cells in all phase cell threads within a mixture.

3.3.9.4. Looping Over Phase Face Threads in Mixture (mp_thread_loop_f)

The mp_thread_loop_f macro loops through all face threads (at the mixture level) within the mixture domain and provides the pointers of the phase-level (face) threads associated with each mixture-level thread. This is nearly identical to the thread_loop_f macro when applied to the mixture domain. The difference is that, in addition to stepping through each face thread, the macro also returns a pointer array (pt) that identifies the corresponding phase-level threads. The pointer to the face thread for the i th phase is pt[i], where i is the phase_domain_index. pt[i] can be used as an argument to macros requiring the phase-level thread pointer. The phase_domain_index can be retrieved using the PHASE_DOMAIN_INDEX macro. (See Phase Domain Index (PHASE_DOMAIN_INDEX) for details.)

 Thread **pt;
 Thread *face_threads;
 Domain *mixture_domain;
 mp_thread_loop_f(face_threads, mixture_domain, pt) 

The variable arguments to mp_thread_loop_f are face_threads, mixture_domain, and pt. face_threads is a pointer to the face threads, and mixture_domain is a pointer to the mixture-level domain. pt is an array pointer whose elements contain pointers to phase-level threads.

mixture_domain is automatically passed to your UDF by the Ansys Fluent solver if you are using a DEFINE macro that contains a domain variable argument (for example, DEFINE_ADJUST) and your UDF is hooked to the mixture. If mixture_domain is not explicitly passed to your UDF, you may use another utility macro to retrieve it (for example, Get_Domain(1), described in Domain Pointer (Get_Domain)). Note that the values for pt and face_threads are set within the looping function.

mp_thread_loop_f is typically used along with begin_f_loop. begin_f_loop loops over faces in a face thread. When begin_f_loop is nested within mp_thread_loop_f, you can loop over all faces in all phase face threads within a mixture.

3.3.10. Advanced Multiphase Macros

For most standard UDFs written for multiphase models (for example, source term, material property, profile functions), variables that your function needs (domain pointers, thread pointers, and so on) are passed directly to your UDF as arguments by the solver in the solution process. All you need to do is hook the UDF to your model and everything is taken care of. For example, if your multiphase UDF defines a custom profile for a particular boundary zone (using DEFINE_PROFILE) and is hooked to the appropriate phase or mixture in Ansys Fluent in the relevant boundary condition dialog box, then appropriate phase or mixture variables will be passed to your function by the solver at run time.

There may, however, be more complex functions you want to write that require a variable that is not directly passed through its arguments. DEFINE_ADJUST and DEFINE_INIT functions, for example, are passed mixture domain variables only. If a UDF requires a phase domain pointer, instead, then it will need to use macros presented in this section to retrieve it. ON_DEMAND UDFS are not directly passed any variables through their arguments. Consequently, any on demand function that requires access to phase or domain variables will also need to use macros presented in this section to retrieve them.

Recall that when you are writing UDFs for multiphase models, you will need to keep in mind the hierarchy of structures within Ansys Fluent (see Multiphase-specific Data Types for details). The particular domain or thread structure that gets passed into your UDF from the solver depends on the DEFINE macro you are using, as well as the domain the function is hooked to (either through the graphical user interface, or hardwired in the code). As mentioned above, it also may depend on the multiphase model that you are using. Refer to Multiphase-specific Data Types and, in particular, Figure 1.5: Domain and Thread Structure Hierarchy for a discussion on hierarchy of structures within Ansys Fluent.

3.3.10.1. Phase Domain Pointer (DOMAIN_SUB_DOMAIN)

There are two ways you can get access to a specific phase (or subdomain) pointer within the mixture domain. You can use either the DOMAIN_SUB_DOMAIN macro (described below) or Get_Domain, which is described below.

DOMAIN_SUB_DOMAIN has two arguments: mixture_domain and phase_domain_index. The function returns the phase pointer subdomain for the given phase_domain_index. Note that DOMAIN_SUB_DOMAIN is similar in implementation to the THREAD_SUB_THREAD macro described in Phase-Level Thread Pointer (THREAD_SUB_THREAD).

 int phase_domain_index = 0;    /* primary phase index is 0 */
 Domain *mixture_domain;
 Domain *subdomain = DOMAIN_SUB_DOMAIN(mixture_domain,phase_domain_index); 

mixture_domain is a pointer to the mixture-level domain. It is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a domain variable argument (for example, DEFINE_ADJUST) and your UDF is hooked to the mixture. Otherwise, if the mixture_domain is not explicitly passed to your UDF, you will need to use another utility macro to retrieve it (for example, Get_Domain(1)) before calling sub_domain_loop.

phase_domain_index is an index of subdomain pointers. It is an integer that starts with 0 for the primary phase and is incremented by one for each secondary phase. phase_domain_index is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a phase domain index argument (DEFINE_EXCHANGE_PROPERTY, DEFINE_VECTOR_EXCHANGE_PROPERTY) and your UDF is hooked to a specific interaction phase. Otherwise, you will need to hard code the integer value of phase_domain_index to the DOMAIN_SUB_DOMAIN macro. If your multiphase model has only two phases defined, then phase_domain_index is 0 for the primary phase, and 1 for the secondary phase. However, if you have more than one secondary phase defined for your multiphase model, you will need to use the PHASE_DOMAIN_INDEX utility to retrieve the corresponding phase_domain_index for the given domain. See Phase Domain Index (PHASE_DOMAIN_INDEX) for details.

3.3.10.2. Phase-Level Thread Pointer (THREAD_SUB_THREAD)

The THREAD_SUB_THREAD macro can be used to retrieve the phase-level thread (subthread) pointer, given the phase domain index. THREAD_SUB_THREAD has two arguments: mixture_thread and phase_domain_index.

The function returns the phase-level thread pointer for the given phase_domain_index. Note that THREAD_SUB_THREAD is similar in implementation to the DOMAIN_SUB_DOMAIN macro described in Phase Domain Pointer (DOMAIN_SUB_DOMAIN).

 int phase_domain_index = 0;           /* primary phase index is 0     */
 Thread *mixture_thread;               /* mixture-level thread pointer */
 Thread *subthread = THREAD_SUB_THREAD(mixture_thread,phase_domain_index); 

mixture_thread is a pointer to a mixture-level thread. It is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a variable thread argument (for example, DEFINE_PROFILE), and the function is hooked to the mixture. Otherwise, if the mixture thread pointer is not explicitly passed to your UDF, then you will need to use the Lookup_Thread utility macro to retrieve it (see Thread Pointer for Zone ID (Lookup_Thread)).

phase_domain_index is an index of subdomain pointers. It is an integer that starts with 0 for the primary phase and is incremented by one for each secondary phase. phase_domain_index is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a phase domain index argument (DEFINE_EXCHANGE_PROPERTY, DEFINE_VECTOR_EXCHANGE_PROPERTY) and your UDF is hooked to a specific interaction phase. (See DEFINE_EXCHANGE_PROPERTY phase_domain_index to the THREAD_SUB_THREAD macro.) If your multiphase model has only two phases defined, then phase_domain_index is 0 for the primary phase, and 1 for the secondary phase. However, if you have more than one secondary phase defined for your multiphase model, you will need to use the PHASE_DOMAIN_INDEX utility to retrieve the corresponding phase_domain_index for the given domain. See Phase Domain Index (PHASE_DOMAIN_INDEX) for details.

3.3.10.3. Phase Thread Pointer Array (THREAD_SUB_THREADS)

The THREAD_SUB_THREADS macro can be used to retrieve the pointer array, pt, whose elements contain pointers to phase-level threads (subthreads). THREAD_SUB_THREADS has one argument, mixture_thread.

 Thread *mixture_thread;
 Thread **pt;  /* initialize pt  */
 pt = THREAD_SUB_THREADS(mixture_thread); 

mixture_thread is a pointer to a mixture-level thread which can represent a cell thread or a face thread. It is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a variable thread argument (for example, DEFINE_PROFILE), and the function is hooked to the mixture. Otherwise, if the mixture thread pointer is not explicitly passed to your UDF, then you will need to use another method to retrieve it. For example you can use the Lookup_Thread utility macro (see Thread Pointer for Zone ID (Lookup_Thread)).

pt[i], an element in the array, is a pointer to the corresponding phase-level thread for the ith phase, where i is the phase_domain_index. You can use pt[i] as an argument to some cell variable macros when you want to retrieve specific phase information at a cell. For example, C_R(c,pt[i]) can be used to return the density of the i th phase fluid at cell c. The pointer pt[i] can also be retrieved using THREAD_SUB_THREAD, discussed in Phase-Level Thread Pointer (THREAD_SUB_THREAD), using i as an argument. The phase_domain_index can be retrieved using the PHASE_DOMAIN_INDEX macro. See Phase Domain Index (PHASE_DOMAIN_INDEX) for details.

3.3.10.4. Mixture Domain Pointer (DOMAIN_SUPER_DOMAIN)

You can use DOMAIN_SUPER_DOMAIN when your UDF has access to a particular phase-level domain (subdomain) pointer, and you want to retrieve the mixture-level domain pointer. DOMAIN_SUPER_DOMAIN has one argument, subdomain. Note that DOMAIN_SUPER_DOMAIN is similar in implementation to the THREAD_SUPER_THREAD macro described in Mixture Thread Pointer (THREAD_SUPER_THREAD).

 Domain *subdomain;
 Domain *mixture_domain = DOMAIN_SUPER_DOMAIN(subdomain); 

subdomain is a pointer to a phase-level domain within the multiphase mixture. It is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a domain variable argument (for example, DEFINE_ADJUST), and the function is hooked to a primary or secondary phase in the mixture. Note that in the current version of Ansys Fluent, DOMAIN_SUPER_DOMAIN will return the same pointer as Get_Domain(1). Therefore, if a subdomain pointer is available in your UDF, it is recommended that the DOMAIN_SUPER_DOMAIN macro be used instead of the Get_Domain macro to avoid potential incompatibility issues with future releases of Ansys Fluent.

3.3.10.5. Mixture Thread Pointer (THREAD_SUPER_THREAD)

You can use the THREAD_SUPER_THREAD macro when your UDF has access to a particular phase-level thread (subthread) pointer, and you want to retrieve the mixture-level thread pointer. THREAD_SUPER_THREAD has one argument, subthread.

 Thread *subthread;
 Thread *mixture_thread = THREAD_SUPER_THREAD(subthread); 

subthread is a pointer to a particular phase-level thread within the multiphase mixture. It is automatically passed to your UDF by the Ansys Fluent solver when you use a DEFINE macro that contains a thread variable argument (for example, DEFINE_PROFILE, and the function is hooked to a primary or secondary phase in the mixture. Note that THREAD_SUPER_THREAD is similar in implementation to the DOMAIN_SUPER_DOMAIN macro described in Mixture Domain Pointer (DOMAIN_SUPER_DOMAIN).

3.3.10.6. Domain ID (DOMAIN_ID)

You can use DOMAIN_ID when you want to access the domain_id that corresponds to a given phase-level domain pointer. DOMAIN_ID has one argument, subdomain, which is the pointer to a phase-level domain. The default domain_id value for the top-level domain (mixture) is 1. That is, if the domain pointer that is passed to DOMAIN_ID is the mixture-level domain pointer, then the function will return a value of 1. Note that the domain_id that is returned by the macro is the same integer ID that is displayed in the graphical user interface when you select the desired phase in the Phases dialog box in Ansys Fluent.

 Domain *subdomain;
 int domain_id = DOMAIN_ID(subdomain); 

3.3.10.7. Phase Domain Index (PHASE_DOMAIN_INDEX)

The PHASE_DOMAIN_INDEX macro retrieves the phase_domain_index for a given phase-level domain (subdomain) pointer. PHASE_DOMAIN_INDEX has one argument, subdomain, which is the pointer to a phase-level domain. phase_domain_index is an index of subdomain pointers. It is an integer that starts with 0 for the primary phase and is incremented by one for each secondary phase.

 Domain *subdomain;
 int phase_domain_index = PHASE_DOMAIN_INDEX(subdomain);