19.9.2. Junction Box Example 2: Integrated Residence Time Distribution

This example makes use of the facility in order to print out integrated values of a user-defined Additional Variable that measures the residence time distribution in the flow domain. It uses the facilities to loop over all domains and all boundary condition patches, and it prints out the integrated residence time distribution on each of these locales. For details, see:

It also uses the facilities to look up the fluid name on each domain. Hence, it should work generically for any single phase problem. For details, see:

19.9.2.1. Problem Setup

19.9.2.1.1. Creating the Additional Variables

Before creating the domains, define the Additional Variable representing Residence Time Distribution.

  • Create an Additional Variable called RTD of Type Volumetric.

  • Set Units of time [s].

19.9.2.1.2. Creating the Domains

Create one or more single phase domains. On each domain, include the Additional Variable RTD.

  • Declare RTD of Type Transport Equation.

  • Set its kinematic diffusivity equal to zero.

19.9.2.1.3. Creating the Subdomains and Additional Variable Sources
  • On each domain, create a subdomain that encompass the entire domain.

  • On each such subdomain, for the Additional Variable RTD, set Option to Source, and set the dimensionless source term identically equal to unity.

This ensure that the Additional Variable obeys the transport equation:

(19–5)

Hence, integrated along stream lines RTD, measure the residence time of fluid particles along streamlines.

19.9.2.1.4. Creating the Junction Box Routine

In CFX-Pre, you should create a User Routine with the following settings:

  • Routine Name: User Output

  • Option: Junction Box Routine

  • Calling Name: user_output

  • Library Name: user output

  • Library Path: /home/user/Shared_Libraries

  • Junction Box Location: End of Run

19.9.2.1.5. Enabling the Junction Box Routine

In order to ensure that the solver calls the declared Junction Box routine, you should:

19.9.2.2. User Fortran Junction Box Routine

This routine looks up the number of domains, and loops over them. On each domain, it computes and prints out the arithmetic average and maximum values of the Residence Time Distribution. Additionally, on each domain, it looks up the number of boundary condition patches, and loops over them. On each BCP, it also computes and prints the arithmetic average Residence Time Distribution. Some of the comment lines are omitted. This routine user_output.F is supplied in the <CFXROOT>/examples/UserFortran/ directory of your Ansys CFX installation.

#include "cfx5ext.h"
dllexport(user_output)
      SUBROUTINE USER_OUTPUT (CZ, DZ, IZ, LZ, RZ)
C
C Routine called at end of run
C
C Preprocessor includes
#include "MMS.h"
#include "cfd_constants.h"
C
C Arguments
      CHARACTER*(1) CZ(*)
      DOUBLE PRECISION DZ(*)
      INTEGER IZ(*)
      LOGICAL LZ(*)
      REAL RZ(*)
C
C External routines
      CHARACTER*15 CFROMR
      INTEGER LENACT
      EXTERNAL CFROMR, LENACT
C
C Local parameters
      CHARACTER*(*) ROUTIN
      PARAMETER (ROUTIN = 'USER_OUTPUT')
C Local variables
      CHARACTER*4 CRESLT
      CHARACTER*(MXDNAM) CDIR_GLOB, CDIR_ZONE, CDIR_PHYS, 
     &  CZONE, CBCP, CPHASE
      CHARACTER*120 User_Domain_Name, User_BCP_Name, 
     &  User_Phase_Name, User_Var_Name
      INTEGER NZN,IZN, NBCP,IBCP
      REAL VAR
C
C Executable statements 
      CALL MESAGE( 'WRITE', ' ')
      CALL MESAGE( 'WRITE', '-----------------')
      CALL MESAGE( 'WRITE', 'Start USER_OUTPUT')
      CALL MESAGE( 'WRITE', '-----------------')
      CALL MESAGE( 'WRITE', ' ')
C
C---- Obtain global meshdata
      CDIR_GLOB = ' '
      CALL USER_GET_MESH_INFO (ROUTIN,'GET','STOP','LATEST',
     &  ' ',' ',CDIR_GLOB,CRESLT, CZ,DZ,IZ,LZ,RZ)
C---- Look up number of domains, and loop over domains
      CALL PEEKI ('/USER/'//CDIR_GLOB//'/NZN',IONE,NZN, 
     &  'STOP',CRESLT, IZ)
      IF (CRESLT .NE. 'GOOD') GOTO 999
      DO IZN = 1, NZN
C
C---- CZONE = solver domain name
        CALL PEEKCA ('/USER/'//CDIR_GLOB//'/CZONE',IZN,CZONE, 
     &  'STOP',CRESLT, CZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
C
C---- Convert to user domain name
        CALL CONVERT_NAME_S2U ('Domain',CZONE,' ',User_Domain_Name,
     &  CRESLT, CZ,DZ,IZ,LZ,RZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
        CALL MESAGE( 'WRITE', ' ')
        CALL MESAGE( 'WRITE', '-----------------')
        CALL MESAGE( 'WRITE', 'Domain: '//User_Domain_Name)
        CALL MESAGE( 'WRITE', '-----------------')
        CALL MESAGE( 'WRITE', ' ')
C
C---- Get physics info.
        CDIR_PHYS = ' '
        CALL USER_GET_PHYS_INFO (ROUTIN,'GET','STOP','LATEST',
     &                CZONE,' ',CDIR_PHYS,CRESLT, CZ,DZ,IZ,LZ,RZ)
C
C---- CPHASE = solver phase name (assumes single phase)
        CALL PEEKCA ('/USER/'//CDIR_PHYS//'/CPHASE',IONE,CPHASE, 
     &               'STOP',CRESLT, CZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
C
C---- Convert to user phase name
        CALL CONVERT_NAME_S2U ('Phase',CPHASE,' ',User_Phase_Name,
     &                         CRESLT, CZ,DZ,IZ,LZ,RZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
C
C---- Set User Variable Name = User_Phase_Name.RTD
C---- (RTD = Residence Time Distribution).
        User_Var_Name = User_Phase_Name(1:LENACT(User_Phase_Name))
     &               // '.RTD'
        CALL MESAGE( 'WRITE', ' ')
        CALL MESAGE( 'WRITE', '-----------------')
        CALL MESAGE( 'WRITE', 'Variable: '//User_Var_Name)
        CALL MESAGE( 'WRITE', '-----------------')
        CALL MESAGE( 'WRITE', ' ')
C
C---- Obtain global values on domain
        CALL USER_GET_GVAR (User_Var_Name, User_Domain_Name,
     &                      'ave', CRESLT, VAR, CZ,DZ,IZ,LZ,RZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
        CALL MESAGE( 'WRITE', 'RDT Mean Value = '//CFROMR(VAR))
C
        CALL USER_GET_GVAR (User_Var_Name,User_Domain_Name,
     &                      'maxVal', CRESLT, VAR, CZ,DZ,IZ,LZ,RZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
        CALL MESAGE( 'WRITE', 'RDT Max Value = '//CFROMR(VAR))
C
C---- Obtain zonal meshdata
        CDIR_ZONE = ' '
        CALL USER_GET_MESH_INFO (ROUTIN,'GET','STOP','LATEST',
     &                           CZONE,' ',CDIR_ZONE,CRESLT,
     &                           CZ,DZ,IZ,LZ,RZ)
C
C---- Look up number of Boundary Condition Patches (BCP's), 
C---- and loop over BCP's.
        CALL PEEKI ('/USER/'//CDIR_ZONE//'/NBCP',IONE,NBCP, 
     &              'STOP',CRESLT, IZ)
        IF (CRESLT .NE. 'GOOD') GOTO 999
        DO IBCP = 1, NBCP
C
C---- CBCP = solver BCP name
          CALL PEEKCA ('/USER/'//CDIR_ZONE//'/CBCP',IBCP,CBCP, 
     &               'STOP',CRESLT, CZ)
          IF (CRESLT .NE. 'GOOD') GOTO 999
C
C---- Convert to user BCP name
          CALL CONVERT_NAME_S2U ('Bcp',CBCP,' ',User_BCP_Name,
     &                           CRESLT, CZ,DZ,IZ,LZ,RZ)
          IF (CRESLT .NE. 'GOOD') GOTO 999
          CALL MESAGE( 'WRITE', ' ')
          CALL MESAGE( 'WRITE', '-----------------')
          CALL MESAGE( 'WRITE', 'Boundary: '//User_BCP_Name)
          CALL MESAGE( 'WRITE', '-----------------')
          CALL MESAGE( 'WRITE', ' ')
C
C---- Obtain global values on BCP
          CALL USER_GET_GVAR (User_Var_Name,User_BCP_Name, 
     &                        'ave', CRESLT, VAR, CZ,DZ,IZ,LZ,RZ)
          IF (CRESLT .NE. 'GOOD') GOTO 999
          CALL MESAGE( 'WRITE', 'RDT Mean Value = '//CFROMR(VAR))
C
          CALL USER_GET_GVAR (User_Var_Name,User_BCP_Name,
     &                        'maxVal',CRESLT, VAR, CZ,DZ,IZ,LZ,RZ)
          IF (CRESLT .NE. 'GOOD') GOTO 999
          CALL MESAGE( 'WRITE', 'RDT Max Value = '//CFROMR(VAR))
C
C---- End Loop Over BCP's
        END DO
C
C---- End Loop Over Zones
      END DO
C
C---- Delete Mesh Data
      CALL USER_GET_MESH_INFO (ROUTIN,'DELETE','STOP','LATEST',
     &                         ' ',' ',CDIR_GLOB,CRESLT,
     &                         CZ,DZ,IZ,LZ,RZ)
C
999   CONTINUE
      IF (CRESLT .NE. 'GOOD') THEN
        CALL MESAGE( 'WRITE', 'User abort, CRESLT = '//CRESLT)
        CALL CFXSTP (ROUTIN)
      ENDIF
C
      END