You are on page 1of 239

THE UNIVERSITY OF QUEENSLAND

Hybrid Rocket Motor – Simulation of Combustion Ballistics for


a Wax Hybrid in Eilmer

Student Name: YU SHEN CHIA


Course Code: MECH4500

Supervisor: Ingo H. Jahn, Dr

Submission date: 24 October 2019

Faculty of Engineering, Architecture and Information Technology


Abstract
In a hybrid rocket motor, the solid fuel and liquid oxidiser are stored separately. Therefore, this
configuration improves safety during the manufacturing and operation phases as the risks of
explosions are reduced. Besides that, this configuration allows motor throttling by providing a
possibility of controlling the oxidiser mass flow rate. [1]. In applications, the solid fuel is
cylindrical and has either a singular port or multiple ports through its cross-section. [1]. In
operations, the oxidiser is injected axially through the ports of the solid fuel. A diffusion flame
front will form at the interface between the oxidiser rich core flow and the fuel-rich layer formed
along the parameter by the ablating fuel surface. [1]. Understanding the mass and heat transfer
processes inside the motor is essential when analysing and optimising motor performance. For
liquefying hybrid rocket fuels, such as paraffin wax, attempts to understand this process is
complicated by the formation of a low viscosity fuel melt layer on the fuel surface.

This project aims to develop a collection of computational fluid dynamics (CFD) sub-models to
simulate the internal combustion ballistics of a Hydroxyl-Terminated Polybutadiene (HTPB) fuel
and pure oxygen inside a two-dimensional (2D) slab hybrid rocket motor (HRM), using the CFD
code Eilmer 4. Eilmer 4 is an open-source compressible transient flow solver developed at the
University of Queensland [2].

The work discussed the implementations of the fuel pyrolysis boundary condition to model the
vaporisation process of non-liquefying solid fuels such as HTPB, the loose coupling mechanism
for the heat transfer process between the fluid domain and solid fuel, the transient solution of the
thermal energy balance in the receding fuel grain by the non-integer system identification (NISI)
method, the selection of appropriate finite rate chemistry models for the combustion, the radiation
model source term, and the implementation of a thin-film model to simulate the melt layer effect.
The results included in the work are the simulated internal combustion ballistics of HTPB solid
fuel that is loaded in a 2D slab HRM and the verifications test cases for the finite-rate chemistry
and thin-film models. The research outcome implies that Eilmer 4 is capable to perform a predictive
CFD analysis in the design process of a hybrid rocket motor. In addition, the research work
provides a strong framework to study the internal combustion ballistics of liquefying solid fuel by
using Eilmer 4 in the future.

3
Contents

Abstract............................................................................................................................................ 3

Introduction ................................................................................................................................... 12

1.1 Aims and Objectives ....................................................................................................... 14

1.2 Thesis Scope ................................................................................................................... 15

Literature Review .......................................................................................................................... 16

2.1 Prior Work ...................................................................................................................... 16

2.1.1 Non-Liquefying Fuel ............................................................................................... 16

2.1.2 Liquefying Fuel ....................................................................................................... 17

2.2 Summary of Modelling Approaches ............................................................................... 18

Background Theory ....................................................................................................................... 21

3.1 Fuel Pyrolysis Modelling ................................................................................................ 21

3.2 Fluid-Solid Coupled Heat Transfer Modelling ............................................................... 23

3.2.1 Convective Heat Flux Modelling ............................................................................ 24

3.2.2 Thermal Radiative Heat Flux Modelling ................................................................. 25

3.2.3 Pyrolysis Heat Flux Modelling ................................................................................ 28

3.2.4 Conductive Heat Flux and Transient Solid Heat Conduction Modelling ................ 29

3.3 Chemistry Kinetics.......................................................................................................... 33

3.3.1 Unit Conversion of the Equilibrium Kinetic Parameters......................................... 34

3.3.2 Finite-rate Formulation of the Two-Step Reduced Chemistry Kinetics .................. 36

3.4 Melt Layer Modelling ..................................................................................................... 37

3.4.1 Mass Continuity Equation and Velocity Profile of the Thin-Film Model............... 40

3.4.2 Momentum Equation of the Thin-Film Model ........................................................ 42

3.4.3 Energy Equation of the Thin-Film Model ............................................................... 43

3.4.4 Boundary Value Problem Formulation.................................................................... 45


4
Implementation Methodology ....................................................................................................... 46

4.1 Implementation Considerations in Eilmer 4 ................................................................... 46

4.2 Fuel Pyrolysis Boundary Condition ................................................................................ 48

4.2.1 Governing Equations of the Fuel Pyrolysis Boundary Condition ........................... 48

4.2.2 Boundary Treatment of the Fuel Pyrolysis Boundary Condition ............................ 49

4.2.3 Formulation of the Fuel Pyrolysis Boundary Condition ......................................... 51

4.2.4 General Implementation of the Fuel Pyrolysis Boundary Condition ...................... 56

4.2.5 MPI Implementation of the Fuel Pyrolysis Boundary Condition ............................ 58

4.3 Fluid-Solid Coupled Heat Transfer Mechanism ............................................................. 64

4.3.1 Algorithm Design of the Loose Coupling Approach .............................................. 64

4.3.2 General Implementation of the Loose Coupling Approach..................................... 65

4.3.3 MPI Implementation of the Loose Coupling Mechanism ....................................... 68

4.4 Melt Layer Boundary Condition ..................................................................................... 69

4.4.1 Isothermal Melt Layer and First Stokes Problem Formulation ............................... 69

4.4.2 Isothermal Melt Layer Boundary Condition Formulation ....................................... 73

4.4.3 General Implementation .......................................................................................... 78

4.5 Chemistry Kinetics Source Term .................................................................................... 80

4.6 Thermal Radiation Source Term..................................................................................... 81

Testing Methodology..................................................................................................................... 83

5.1 Verification Test Case of the Chemistry Kinetics .......................................................... 83

5.1.1 Constant Volume Reactor Test Case ....................................................................... 83

5.1.2 Reacting Pipe Flow Test Case ................................................................................. 87

5.2 Verification Test Case of the Isothermal Melt Layer Boundary Condition.................... 91

5.2.1 Melt Layer Properties .............................................................................................. 91

5.2.2 Geometry ................................................................................................................. 92

5
5.2.3 Boundary and Initial Conditions, Blocking Structure, Meshing and Simulation
Configurations ....................................................................................................................... 92

5.2.4 Methodology of the Verification Calculation.......................................................... 94

5.3 Main Test Case ............................................................................................................... 96

5.3.1 Geometry ................................................................................................................. 97

5.3.2 Blocking Structure and Meshing ............................................................................. 98

5.3.3 Boundary and Initial Conditions ........................................................................... 100

5.3.4 Simulation Configurations..................................................................................... 102

Results and Discussions .............................................................................................................. 104

6.1 Verification Results of the Chemistry Kinetics ............................................................ 104

6.1.1 Verification Results of the Constant Volume Reactor Test Case .......................... 104

6.1.2 Verification Results of the Reacting Pipe Flow Test Case .................................... 106

6.2 Verification Results of the Isothermal Melt Layer Boundary Condition ..................... 108

6.3 Results of the Main Test Case ...................................................................................... 113

6.3.1 Simulation Methodology ....................................................................................... 113

6.3.2 Deriving Low-Speed Flow Solution from High-Speed Flow Solution ................. 113

6.3.3 Non-Dimensional Wall Distance (Y+) Convergence Study .................................. 114

6.3.4 Results of Pure Injection Case with a Truncated Downstream Region ................. 117

6.3.5 Pressure Relaxation Factor .................................................................................... 122

6.3.6 Results of the Pure Injection Simulation with Full Geometry .............................. 124

6.3.7 Results of the Combustion Simulation with Full Geometry ................................. 132

Recommendations and Conclusions ............................................................................................ 136

7.1 Conclusions ................................................................................................................... 136

7.2 Future Recommendations ............................................................................................. 137

References ................................................................................................................................... 138

Appendix ..................................................................................................................................... 142

6
Appendix 1 .............................................................................................................................. 142

List of Figures
Figure 1: Schematic of the heat and mass transfer process during the combustion of liquefying fuel,
adapted from [27]. ......................................................................................................................... 37
Figure 2: Interfacial transport processes of an arbitrary liquid film [28]. ..................................... 39
Figure 3: Schematic of the coordinate system of the fluid domain and thin-film model. ............. 39
Figure 4: Bilinear temperature profile in the melt layer. ............................................................... 43
Figure 5: Control volume of the melt layer. .................................................................................. 44
Figure 6: Grid at the trailing edge of the solid fuel grain. ............................................................. 54
Figure 7: Indexing system of the sub-blocks in a multi-block grid. .............................................. 60
Figure 8: Indexing system of the blockArray table. ...................................................................... 61
Figure 9: Recursive summation approach. .................................................................................... 62
Figure 10: Algorithm of the loose coupling approach, adapted from [36]. ................................... 64
Figure 11: Code architecture of the loose coupling mechanism. .................................................. 65
Figure 12: Operations architecture of the solid heat conduction script. ........................................ 67
Figure 13: Data structure of the input heat flux/fuel surface temperature distribution history file.
....................................................................................................................................................... 67
Figure 14: First stokes problem modelling approach. ................................................................... 71
Figure 15: Truncated fluid domain of the first stokes problem model. ......................................... 71
Figure 16: Modelling approach for a continuously moving wall. ................................................. 72
Figure 17: 1-D finite volume grid. ................................................................................................ 73
Figure 18: State update mechanism of the melt layer. .................................................................. 79
Figure 19: Dimensions of the constant volume reactor. ................................................................ 84
Figure 20: Boundary conditions of the constant volume reactor................................................... 84
Figure 21: Dimensions of the reacting pipe................................................................................... 87
Figure 22: Boundary conditions of the reacting pipe. ................................................................... 87
Figure 23: Control volume used in the linearisation of the conservation equations, adapted from
[38]. ............................................................................................................................................... 89
Figure 24: Dimensions of the fluid domain for the first Stokes problem. ..................................... 92

7
Figure 25: Boundary conditions of the first stokes problem. ........................................................ 92
Figure 26: Geometry of the 2D slab HRM, adapted from [1]. ...................................................... 97
Figure 27: Blocking structure of the fluid domain of the 2D slab HRM. ..................................... 98
Figure 28: Actual mesh of the fluid domain of the 2D slab HRM. ............................................. 100
Figure 29: Comparing Eilmer 4 simulation and calculation results of the transient profile of (a)
Static pressure; (b) Temperature in a constant volume reactor. .................................................. 105
Figure 30: Comparing Eilmer 4 simulation and calculation results of the transient profile of (a)
Mass fraction of C4H6; (b) Mass fraction of CO; (c) Mass fraction of CO2; (d) Mass fraction of
H2O; (e) Mass fraction of O2 in a constant volume reactor. ........................................................ 106
Figure 31: Comparing Eilmer 4 simulation and calculation results of the spatial distribution of (a)
Static pressure; (b) Temperature in a reacting pipe. .................................................................... 106
Figure 32: Comparing Eilmer 4 simulation and calculation results of the spatial distribution of (a)
Mass fraction of C4H6; (b) Mass fraction of CO; (c) Mass fraction of CO2; (d) Mass fraction of
H2O; (e) Mass fraction of O2 in a reacting pipe. ......................................................................... 107
Figure 33: The 𝑥-velocity flow field and vectors of the first Stokes problem test case. ............. 108
Figure 34: Transient wall-normal 𝑥-velocity profile in the fluid domain (with melt layer effect).
..................................................................................................................................................... 109
Figure 35: Wall-normal 𝑥-velocity profile in the fluid domain (with melt layer effect) at 𝑡 = 35.7
ms. ............................................................................................................................................... 111
Figure 36: Boundary conditions and dimensions of the truncated 2D slab HRM (for 𝑦 +
convergence study). ..................................................................................................................... 114
Figure 37: Mesh and initial velocity flow field of the truncated 2D slab HRM (for 𝑦 + convergence
study). .......................................................................................................................................... 115
Figure 38: Skin friction coefficient distribution along the fuel surface at different y+ values. ... 115
Figure 39: Velocity jump condition at the leading edge, when 𝑦 + = 0.20. ............................... 116
Figure 40: Velocity jump condition at the leading edge, when 𝑦 + = 0.03. ............................... 116
Figure 41: Dimensions of the shortened 2D slab HRM. ............................................................. 118
Figure 42: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure
injection case) at t = 20.0 ms. ...................................................................................................... 118
Figure 43: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure
injection case) at t = 40.0 ms. ...................................................................................................... 118

8
Figure 44: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure
injection case) at t = 60.0 ms. ...................................................................................................... 119
Figure 45: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure
injection case) at t = 80.0 ms. ...................................................................................................... 119
Figure 46: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure
injection case) at t = 100.0 ms. .................................................................................................... 119
Figure 47: Temperature field within the shortened 2D slab HRM (pure injection case) at t = 100.0
ms. ............................................................................................................................................... 120
Figure 48: Pressure field within the shortened 2D slab HRM (pure injection case) at t = 100.0 ms.
..................................................................................................................................................... 120
Figure 49: Velocity field within the shortened 2D slab HRM (pure injection case) at t = 100.0 ms.
..................................................................................................................................................... 120
Figure 50: Inlet pressure history of the pure injection case (without pressure relaxation factor at the
inlet). ............................................................................................................................................ 121
Figure 51: Mesh and initial velocity flow field within the shortened 2D slab HRM (for comparative
study of relax_factor). ................................................................................................................. 122
Figure 52: Inlet pressure histories of all relax_factor options. .................................................... 123
Figure 53: Initial conditions within the complete 2D slab HRM. ............................................... 125
Figure 54: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure
injection case) at t = 9.0 ms. ........................................................................................................ 126
Figure 55: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure
injection case) at t = 18.0 ms. ...................................................................................................... 126
Figure 56: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure
injection case) at t = 27.0 ms. ...................................................................................................... 127
Figure 57: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure
injection case) at t = 36.0 ms. ...................................................................................................... 127
Figure 58: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure
injection case) at t = 45.0 ms. ...................................................................................................... 128
Figure 59: Temperature field within the complete 2D slab HRM (pure injection case) at t = 45.0
ms. ............................................................................................................................................... 128
Figure 60: Spatial variation of the wall-normal temperature profile (pure injection case) at t = 45.0
ms. ............................................................................................................................................... 129

9
Figure 61: Spatial variation of the wall-normal profile of 𝑌𝐶4𝐻6 (pure injection case) at t = 45.0
ms. ............................................................................................................................................... 129
Figure 62: Spatial variation of the wall-normal 𝑥-velocity profile (pure injection case) at t = 45.0
ms. ............................................................................................................................................... 130
Figure 63: Inlet pressure history of the pure injection case (without pressure relaxation factor at the
inlet). ............................................................................................................................................ 131
Figure 64: Mass fraction of CO and velocity vectors within the complete 2D slab HRM
(combustion with injection case) at t = 0.90 ms. ......................................................................... 132
Figure 65: Mass fraction of CO and velocity vectors within the complete 2D slab HRM
(combustion with injection case) at t = 1.80 ms. ......................................................................... 132
Figure 66: Mass fraction of CO and velocity vectors within the complete 2D slab HRM
(combustion with injection case) at t = 2.70 ms. ......................................................................... 133
Figure 67: Mass fraction of CO and velocity vectors within the complete 2D slab HRM
(combustion with injection case) at t = 3.60 ms. ......................................................................... 133
Figure 68: Temperature field within the complete 2D slab HRM (combustion with injection case)
at t = 4.90 ms. .............................................................................................................................. 134
Figure 69: Dimensions of the fluid-cell with the unphysical temperature. ................................. 134
Figure 70: Wall-normal temperature profile at 𝑥 = 50.0 mm and at t = 3.60 ms. ....................... 135
Figure 71: Wall-normal species profile at 𝑥 = 50.0 mm and at t = 3.60 ms................................ 135

List of Tables
Table 1: Inclusions and exclusions of the thesis. .......................................................................... 15
Table 2: Relevant theoretical topics and contexts to identify the background theories to implement
the CFD sub-models. ..................................................................................................................... 20
Table 3: Regression rate parameters of HTPB fuel [6]. ................................................................ 22
Table 4: Fitting coefficients of H20, CO2 and CO [13]. ............................................................... 27
Table 5: Thermochemical properties of HTPB fuel [19]. ............................................................. 29
Table 6: Equilibrium kinetic parameters of the two-step reduced finite rate chemistry kinetics of
HTPB-oxygen mixture [26]. .......................................................................................................... 33

10
Table 7: Differences between the unit system of the two-step reduced chemistry kinetics and Eilmer
4. .................................................................................................................................................... 34
Table 8: Pre-exponential factor of the two-step reduced chemistry kinetics in the unit system of
Eilmer 4. ........................................................................................................................................ 35
Table 9: User-defined function (UDF) group classifications of the CFD sub-models.................. 47
Table 10: Algorithm of the fuel pyrolysis boundary condition. .................................................... 57
Table 11: Algorithm of the recursive summation approach. ......................................................... 63
Table 12: Data structure of the userPad array. .............................................................................. 78
Table 13: Mesh settings of the constant volume reactor test case. ................................................ 84
Table 14: Initial conditions of the constant volume reactor test case. ........................................... 85
Table 15: Simulation configurations of the constant volume reactor test case. ............................ 85
Table 16: Ignition settings of the constant volume reactor test case. ............................................ 85
Table 17: Mesh settings of the reacting pipe flow test case. ......................................................... 88
Table 18: Block marching settings of the reacting pipe flow test case. ........................................ 88
Table 19: Supersonic inflow conditions of the reacting pipe flow test case. ................................ 88
Table 20: Simulation configurations of the reacting pipe flow test case....................................... 88
Table 21: Properties of paraffin wax [39]. .................................................................................... 91
Table 22: Mesh settings of the first Stokes problem test case. ...................................................... 93
Table 23: Parallelisation settings of the fluid domain of the first Stokes problem test case. ........ 93
Table 24: Initial conditions of the isothermal melt layer and the fluid domain. ........................... 93
Table 25: Simulation configurations of the first Stokes problem test case. .................................. 94
Table 26: Coordinates of all the points that define the 2D slab HRM geometry. ......................... 97
Table 27: Coordinates of all the internal grid points of the fluid domain of the 2D slab HRM.... 98
Table 28: Mesh settings of the main block of the fluid domain of the 2D slab HRM. ................. 99
Table 29: Fluid domain boundary conditions of the fluid domain of the 2D slab HRM. ........... 100
Table 30: Initial conditions of the fluid domain of the 2D slab HRM. ....................................... 101
Table 31: Simulation configurations of the fluid domain of the 2D slab HRM. ......................... 102
Table 32: Parallelisation settings of the fluid domain of the 2D slab HRM. .............................. 103
Table 33: Ignition settings of the combustion with injection case of the 2D slab HRM............. 103
Table 34: Isothermal Melt Layer Properties at the time where the simulation stopped. ............. 110

11
Chapter 1

Introduction

A hybrid rocket motor (HRM) is designed to store the solid fuel and liquid oxidiser separately.
This configuration improves safety and lowers the launching cost because it is less susceptible to
explosions. [1]. In practice, the solid fuel grain geometry in the combustion chamber of HRM can
be a cylinder that is hollowed out axially by at least one port or a slab. In a slab HRM, the
combustion chamber has a rectangular cross-section with outer side windows and a fuel slab
located on the inner bottom side of the chamber. The windows allow for combustion flame
visualisation in lab-scale testing. [3].

In operation, the liquid oxidiser will vaporise and then enter the combustion chamber of HRM.
This configuration enables motor throttling because the mass flow rate of the gaseous oxidiser
stream is controllable at the inlet of the chamber. [1]. When the gaseous oxidiser stream is flowing
through the chamber, it will transfer heat to the surface of the solid fuel grain through convection
and radiation. As a result of heat absorption by the solid fuel grain through conduction, the fuel
surface temperature will increase and eventually lead to the onset of the fuel pyrolysis process.

There are two types of HRM fuel: non-liquefying and liquefying fuels. For a non-liquefying fuel
like the Hydroxyl-Terminated Polybutadiene (HTPB), the fuel pyrolysis process leads to the
injection of vaporised fuel along the perimeter of the solid fuel grain and the simultaneous recession
of the fuel surface. The vaporised fuel then mixes with the gaseous oxidiser stream. When this fuel-
oxidiser mixture is ignited, a diffusion flame is formed at the interface between the oxidiser-rich
core flow and fuel-rich layer on the fuel surface. [1]. For a liquefying fuel like the paraffin wax,
the fuel pyrolysis process is complicated by the formation of a melt layer on the fuel surface. Under
the action of interfacial shear force on the top surface of the melt layer, this surface can become

12
unstable and eventually evolve into roll waves. The wave crest of the roll waves can break-up into
fuel droplets that will entrain into the oxidiser stream. As a result, there are two mass transfer
mechanisms on the melt layer surface: vaporisation of fuel and the mechanical removal of fuel by
droplets entrainment.

This work will focus on the development of a collection of computational fluid dynamics (CFD)
sub-models to simulating the internal combustion ballistics of an HTPB fuel (non-liquefying fuel)
and pure oxygen in a two-dimensional slab HRM. The HTPB-oxygen combination is chosen in
this work because its numerical investigations are well-documented in the literature. Besides that,
slab HRM is chosen due the simplicity of its geometry. All CFD sub-models will be developed
within the framework of user-defined boundary conditions and source terms in Eilmer 4. Eilmer 4
is an open-source compressible transient flow solver developed at the University of Queensland
[3]. Each CFD sub-model represents a physical process or a flow feature that governs the internal
combustion ballistics of the two-dimensional slab HRM. In reference to the descriptions of the
internal combustion ballistics of a typical HRM from the preceding paragraphs, the physical
processes that will be transformed into CFD sub-models are the solid fuel pyrolysis and regression
processes, heat conduction process in the solid fuel, combustion kinetics of the HTPB-oxygen
mixture, thermal radiation effect and the fluid-solid coupled heat transfer process at the solid fuel
surface. To establish a framework to simulate the internal combustion ballistics of liquefying fuels
like paraffin wax in the two-dimensional slab HRM, this work entails the implementation of a thin-
film model to model the melt layer effect. Inline to the development of CFD sub-models, this work
will explain the underlying physics that govern the behaviour of the physical process or flow
feature considered. To fully utilise the high-performance computing (HPC) resources, this work
will also explain the algorithm design methodologies for the CFD sub-models to achieve
compatibility with parallel processing via the standard message passing library (MPI).

Aside from the implementation of CFD sub-models, this work also involves the construction of a
flow domain, mesh generation and boundary treatment to set up the two-dimensional slab HRM
simulation. The boundary treatment will integrate the CFD sub-models developed and assign the
relevant default boundary conditions to the flow domain constructed. The results of this work will
include the transient and steady-state flow solutions of the following test cases, including; pure
injection of HTPB fuel, and the injection and combustion of HTPB fuel under a low-speed oxidiser

13
flow (6 ms-1) in the two-dimensional slab HRM. The results of this work will also extend to the
validation test cases for the CFD sub-models of the combustion kinetics of HTPB-oxygen mixture,
fluid-solid coupled heat transfer process and the thin-film model.

This work is important because it provides a platform for Eilmer 4 to showcase its capability to
simulate the internal combustion ballistics of an HRM. It is expected that the complexity of the
HRM simulation will push Eilmer 4 to its limit, thus providing an opportunity for further
improvements of Eilmer 4 and the CFD sub-models developed. The improvements made would
potentially extend the capability of Eilmer 4 to allow for a more robust and predictive HRM
simulation in the future. As a result, Eilmer 4 would eventually become a powerful CFD tool to
study and characterise the performance of an HRM design. The application of Eilmer 4 in the
design process of HRM will reduce the development cost because it is free and can minimise
experimental trials and errors through predictive analysis.

1.1 Aims and Objectives


As per the Introduction section, this work aims to simulate the internal combustion ballistics of an
HTPB fuel (non-liquefying fuel) and pure oxygen in a two-dimensional slab HRM in Eilmer 4.
Besides that, this work also aims to develop some of the capabilities required to simulating the
internal combustion ballistics of liquefying fuels like paraffin wax. To achieve these aims, the
objectives that will command the direction of this work are:
1. Implement predictive CFD sub-models of the following physical processes:
a. Solid fuel pyrolysis and regression processes.
b. Heat conduction process in the solid fuel.
c. Combustion kinetics of the HTPB-oxygen mixture.
d. Thermal radiation effect.
e. Fluid-solid coupled heat transfer process at the solid fuel surface.
f. Melt layer effect.
2. Utilise the HPC resources by designing the algorithm of the CFD sub-models for parallel
processing in MPI.

14
1.2 Thesis Scope
To establish the context for this work, the inclusions and exclusions of this work are presented in
Table 1.
Table 1: Inclusions and exclusions of the thesis.
Inclusions Exclusions
• Implement predictive CFD sub-models of the • Implement predictive CFD sub-models to
physical processes outlined in Section 1.1 simulate the formation and disintegration of
within the framework of user-defined melt layer roll waves and the entrainment,
boundary conditions or source terms in Eilmer evaporation and spray combustion of fuel
4. droplets.

• Simulate the internal combustion ballistics of • Axisymmetric or three-dimensional


an HTPB fuel and pure oxygen in a two- simulations of the internal combustion
dimensional slab HRM by using the CFD sub- ballistics of an HTPB fuel and pure oxygen in
models developed. different types of HRM configuration, such as
cylindrical fuel grain and outlet nozzle.

• Algorithm design for parallel processing in • Code development of Eilmer 4.


MPI to fully utilise the HPC resources.

• Mesh generation and boundary treatment for • Adaptive and moving mesh treatments for the
the constructed flow domain. receding fuel surface.

• Viscous flow simulation. • Turbulence modelling.

• Validate the simulation results by using • Validate the simulation results through the
analytical methods and matching the parallel experimental testing of an actual slab HRM.
experimental data in the literature.

15
Chapter 2

Literature Review

This chapter entails a literature review of several prior numerical investigations of the internal
combustion ballistics of a hybrid rocket motor (HRM). The objective of this review is to identify
the design parameters and modelling approaches that were previously used to simulate the internal
combustion ballistics of liquefying and non-liquefying fuels in HRMs. Understanding all this
information will provide a direction to identify the required background theories to construct the
computational fluid dynamics (CFD) sub-models of the physical processes outlined in Section 1.1.

2.1 Prior Work


Inline to the aims and scopes of this work, several numerical investigations were reviewed to
identify the design parameters and simulation features of an HRM simulation. This review
considers two cases: liquefying and non-liquefying fuels.

2.1.1 Non-Liquefying Fuel


For the non-liquefying fuel case, one of the prior works reviewed was the numerical simulation of
the internal combustion ballistics of a Hydroxyl-Terminated Polybutadiene (HTPB) fuel and pure
oxygen in a two-dimensional slab HRM from Gariani et al. In their work, they have developed a
CFD code that solves the Navier-Stokes equations with the Reynolds-Averaged Navier–Stokes
(RANS) approach. The CFD code from Gariani et al. is capable of simulating chemistry kinetics
and radiation effects. To achieve model closure for the governing equations of their CFD code,
they employed a well-stirred reactor and a 𝑘 − 𝜖 turbulence model. [1].

16
Gariani et al. used a four-step reduced chemistry kinetics to model the combustion of HTPB-
oxygen mixture. Aside from this, they have developed a gas-surface interface (GSI) boundary
condition, which is the highlight of their numerical investigation. This boundary condition solves
the quasi-steady heat flux balance equation iteratively for the fuel surface temperature until the
continuity condition on the fuel surface is satisfied. Their interfacial heat flux balance equation is
one-dimensional and considers heat transfers due to convection, incident radiation from the fluid
domain, radiation emission from the fuel surface, pyrolysis and heat conduction in the solid fuel
grain. The incident radiative heat transfer is modelled using the P1-radiation model. Besides that,
the pyrolysis heat transfer is modelled using the semi-empirical regression rate law of the HTPB
fuel. Furthermore, the conductive heat transfer process in the solid fuel grain is modelled using the
transient heat conduction equation. This equation is solved simultaneously with the governing
equations of the fluid domain by the fluid-solid heat transfer coupling mechanism that is inherent
to the energy balance equation. [1].

Another similar work was performed by Coronetti and Sirignano, using a single port cylindrical
fuel grain. In their work, they used the same fuel-oxidiser combination, modelling approaches for
the heat flux terms in the interfacial heat flux balance equation and radiation model as Gariani et
al. Contrary to Gariani et al. 's work, Coronetti and Sirignano used a six-step reduced chemical
kinetics to model the combustion of HTPB-oxygen mixture. Besides that, they model the regression
rate by modifying the semi-empirical regression rate law from Risha et al. [2] to deal with the
presence of oxygen at the fuel surface. Furthermore, they modelled the moving interface effect,
which corresponds to the recession of the fuel surface according to the regression rate of the fuel.
Moreover, the governing equations of their CFD code are Favre-averaged Navier-Stokes equations,
which are closed by a 𝑘 − 𝜖 turbulence model and a partially stirred reactor. [3].

2.1.2 Liquefying Fuel


For the liquefying fuel case, Bianchi et al. attempted to extend their GSI boundary condition that
was validated against the HTPB-oxygen combustion case to model the pyrolysis process of a
paraffin wax fuel. In their work, they neglected the radiation effect and modelled their steady-state
energy balance equation at the melt-layer-solid interface as [4]:

𝑠𝑠
𝜕𝑇
𝑞̇ 𝑐𝑜𝑛𝑑 ≡𝑘 = 𝑚̇𝑒𝑛𝑡 𝑐𝑙 (𝑇𝑤 − 𝑇𝑚 ) + 𝑚̇𝑒𝑛𝑡 Δℎ𝑚𝑒𝑙𝑡 + 𝑚̇𝑒𝑛𝑡 𝑐𝑠 (𝑇𝑚 − 𝑇𝑖 ) (1)
𝜕𝜂

17
𝑠𝑠
where 𝑞̇ 𝑐𝑜𝑛𝑑 , 𝑘, 𝜕𝑇⁄𝜕𝜂, 𝑚̇𝑒𝑛𝑡 , 𝑐𝑙 , 𝑐𝑠 , 𝑇𝑤 , 𝑇𝑚 , 𝑇𝑖 and Δℎ𝑚𝑒𝑙𝑡 are defined as the steady-state heat
conduction, conductivity, wall-normal temperature gradient, entrainment mass flux, specific heat
capacity of the melt layer, specific heat capacity of the solid fuel grain, melt layer temperature at
the gas-melt-layer interface, melting temperature, initial temperature of the solid fuel grain and
melting enthalpy of the solid fuel grain, respectively. Further information about the underlying
assumptions of equation (1) can be found in [4].

Bianchi et al. mentioned that the focus of their work is on the relationship between 𝑇𝑤 and 𝑚̇𝑒𝑛𝑡 .
For this reason, they calculate 𝑚̇𝑒𝑛𝑡 by solving equation (1) instead of using semi-empirical
entrainment models. Knowing the value of 𝑚̇𝑒𝑛𝑡 enables the CFD modelling of fuel injection into
the combustion chamber of an HRM. Before modelling the fuel injection process, prior knowledge
of the types of fuel species to be injected is essential. According to Bianchi et al., the paraffin wax
fuel (𝐶32 𝐻66 ) is assumed to decompose into hydrogen (𝐻2 ) and ethylene (𝐶2 𝐻4 ) directly at the gas-
melt-layer interface through the following reaction scheme [4]:
𝐶32 𝐻66 → 𝐻2 + 16𝐶2 𝐻4 (2)
As their study is restricted to a single-phase system only, the entrainment and vaporisation of liquid
fuel droplets are not modelled. Instead, the gas-melt-layer interface is modelled to inject the
gaseous 𝐶2 𝐻4 and 𝐻2 directly to the gaseous oxygen stream at an injection rate of 𝑚̇𝑒𝑛𝑡 . To simulate
the gas-phase reactions of 𝐶2 𝐻4 with oxygen in the combustion chamber of HRM, they used a two-
step reduced finite-rate chemistry kinetics scheme for 𝐶2 𝐻4 . Further details about this chemistry
kinetics scheme can be found in [4].

2.2 Summary of Modelling Approaches


From the literature review in Section 2.1, several commonly used modelling approaches were
identified:
1. The pyrolysis process of a solid fuel grain is characterised by the semi-empirical regression
rate correlations.
2. The heat flux balance equation at the fluid-solid interface is subject to the quasi-steady state
and one-dimensional heat transfer assumptions. It considers the interfacial heat flux terms
due to conduction, radiation, pyrolysis and convection.

18
3. The heat conduction term in the heat flux balance equation at the fluid-solid interface is
governed by the transient heat conduction equation and is solved simultaneously with the
governing equations of the fluid domain.
4. The quasi-steady state heat flux balance equation at the fluid-solid interface is equivalent
to a fluid-solid coupled heat transfer mechanism.
5. The quasi-steady state heat flux balance equation at the fluid-solid interface is solved to
calculate the fuel surface temperature, and thus the corresponding regression rate.
6. Gas-phase reactions of the fuel-oxidiser mixture are modelled using reduced chemistry
kinetics.
7. Turbulence modelling is an integrative part of the numerical simulation of the internal
combustion ballistics of an HRM.
On top of the commonly used modelling approaches, the thermal radiation effect in the flow field
and the incident radiation on the fuel surface can be modelled using the P1 radiation model.
However, this does not exclude the possibility of considering other types of radiation model or
even neglecting the thermal radiation effect for simplicity. Besides that, moving interface treatment
is required to model the recession of the fuel surface due to pyrolysis. However, this treatment
requires an adaptive or moving mesh to account for the changes in the local position of the flow
domain boundaries. As this work is a preliminary attempt to perform an HRM simulation in Eilmer
4, it is necessary to simplify the HRM simulation by excluding the moving interface treatment for
the fuel surface recession effect.

For the liquefying fuel case, the modelling approach from Bianchi et al. is relevant to the
thermochemical aspect of the melt layer during the fuel pyrolysis and combustion processes.
However, their approach is lacking in terms of kinematics modelling to include effects like the wall
shear stress at the gas-melt-layer interface and changes in the local melt layer height. Hence, there
is a need to find a melt layer model that can complement the kinematics aspect of Bianchi et al. ‘s
approach. Besides that, despite Bianchi et al. were able to calculate the entrainment mass flux of
the paraffin wax fuel by solving the energy balance equation (1), their approach is not legitimate
because it does not have a direct experimental basis. The capacity of this approach to retain the
essential physics of the entrainment process remains questionable, especially when the calculated
entrainment mass flux is the solution to an already simplified mathematical model. For this reason,
it is inevitable to use the semi-empirical representation of the entrainment mass flux in future work.

19
To integrate the identified modelling approaches into the implementation of CFD sub-models, the
next stage review will be on establishing the background theories required for this purpose. The
theoretical topics and contexts that will command the direction of the next stage review are
presented in Table 2. This review is detailed in the Chapter 3.

Table 2: Relevant theoretical topics and contexts to identify the background theories to implement the
CFD sub-models.
Topic Context
• Conduct theoretical reviews on the relevant semi-empirical regression rate
Fuel pyrolysis
laws.
modelling

• Conduct theoretical reviews on the relevant mathematical models to model


the heat flux terms in the fluid-solid interface energy balance equation:
1. Thermal radiative heat flux.
Fluid-solid 2. Conductive heat flux.
coupled heat 3. Pyrolysis heat flux.
transfer modelling 4. Convective heat flux term.
• Conduct theoretical reviews on the methodology to solve the fluid-solid
interface energy balance equation for the fluid surface temperature.

• Conduct theoretical reviews on the reduced chemistry kinetics scheme of the


Combustion
HTPB-oxygen mixture.
modelling

Melt layer • Conduct theoretical reviews on the relevant melt layer model that considers
modelling both thermochemical and kinematics aspects of the melt layer.

20
Chapter 3

Background Theory

This chapter will provide comprehensive reviews on the background theories required to
implement the computational fluid dynamics (CFD) sub-models of all the physical processes
outlined in Section 1.1 while considering the modelling approaches identified in Section 2.2. The
structure of this chapter is as per the theoretical topics listed in Table 2.

3.1 Fuel Pyrolysis Modelling


The fuel pyrolysis process can be modelled as a CFD sub-model that injects vaporised fuel at the
regression rate of the solid fuel considered. As mentioned in Section 2.2, the regression rate of
solid fuel must be a semi-empirical parameter. In the literature, the regression rate is correlated to
the internal operating conditions of a hybrid rocket motor, such as the chamber pressure and
oxidiser mass flow rate. There are several types of model of the regression rate of solid fuel. Among
them is the regression rate law developed by Marxman and Gilbert in the early 1960s. Their
regression rate law is defined by the following equation [5]:
𝑛
𝑚̇0
𝑟̇ = 𝛼 ( ) = 𝛼𝐺0𝑛 (3)
𝐴𝑝𝑜𝑟𝑡

where 𝑟̇ , 𝑚̇0 , 𝐴𝑝𝑜𝑟𝑡 and 𝐺0 are the regression rate, oxidiser mass flow rate, cross-sectional area of
the fuel port and oxidiser mass flux, respectively. In equation (3), parameters 𝛼 and 𝑛 are propellant
specific empirical constants. The value of 𝛼 is inversely proportional to the 0.2th power of the axial
length of the solid fuel grain, whereas the value of 𝑛 is typically between 0.5 and 0.8. In addition,
the chamber pressure does not influence the value of 𝑟̇ unless the fluxes are very low where
radiation effects become dominant or very high where the chemical kinetics effects become
dominant. [5].

21
Another type of regression rate law is based on the Arrhenius equation, which was developed by
Chiaverini et al. for the Hydroxyl-Terminated Polybutadiene (HTPB) fuel. Their regression rate
law is defined as [6]:
𝐸𝑎
𝑟̇𝐴𝑟𝑟 = 𝐴𝑒𝑥𝑝 (− ) (4)
𝑅𝑢 𝑇𝑠

where 𝑟̇𝐴𝑟𝑟 , 𝐴, 𝐸𝑎 , 𝑅𝑢 and 𝑇𝑠 are the Arrhenius-type regression rate, pre-exponential factor,
activation energy of the fuel pyrolysis process, universal gas constant and fuel surface temperature,
respectively. The empirical values of 𝐴 and 𝐸𝑎 are tabulated in Table 3.
Table 3: Regression rate parameters of HTPB fuel [6].
𝑻𝒔 (K) 𝑨 (mm∙s-1) 𝑬𝒂 (J∙mol-1)
𝑻𝒔 < 722 3965 5.589 × 104
𝑻𝒔 > 722 11.04 2.056 × 104

According to Chiaverini et al., the regression rate of HTPB fuel is dominated by the thermal
decomposition process on the fuel surface. Besides that, 𝐸𝑎 is a strong function of 𝑇𝑠 instead of
pressure. This is consistent with the findings from Marxman and Gilbert, where they discovered
that the value of 𝑟̇ is insensitive to the chamber pressure. Further, Chiaverini et al. also found that
𝐸𝑎 is higher at lower 𝑇𝑠 because the chemical processes of cross-linking, cyclisation and
depolymerisation dominate the fuel pyrolysis process. [6].

The preceding regression rate models are only valid for non-liquefying hybrid rocket fuels. For
liquefying hybrid rocket fuels, the fuel pyrolysis process is complicated by the formation of a melt
layer, together with the mechanical removal of liquid fuel droplet from the melt layer through an
entrainment process. As a result, the total regression rate of a liquefying fuel is the sum of fuel
vaporisation rate and entrainment rate. According to Karabeyoglu et al., the mass entrainment rate
(𝑚̇𝑒𝑛𝑡 ) of a liquefying fuel is defined in terms of the internal operating conditions of a hybrid rocket
motor by the following empirical equation [7]:
𝑃𝑑𝛼 𝛿 𝛽
𝑚̇𝑒𝑛𝑡 = 𝜌𝑙 𝑟̇𝑒𝑛𝑡 ∝ 𝛾 (5)
𝜇𝑙 𝜎 𝜋

where 𝑟̇𝑒𝑛𝑡 , 𝑃𝑑 , 𝜌𝑙 , 𝛿, 𝜇𝑙 and 𝜎 are the entrainment rate, dynamic pressure in the port, and the
density, thickness, viscosity and surface tension of the melt layer, respectively. Parameters 𝛼, 𝛽, 𝛾
and 𝜋 are propellant specific empirical constants. [7].

22
The total regression rate of a liquefying fuel can be calculated by using the extended hybrid theory
from Karabeyoglu et al. As modelling the droplet entrainment process on the melt layer surface is
beyond the scope of this thesis, the governing equations and assumptions of the extended hybrid
theory will not be presented in this section and can be found in [7].

3.2 Fluid-Solid Coupled Heat Transfer Modelling


When a hybrid rocket motor is in operation phase, there is fluid-solid coupled heat transfer at the
interface between the core fuel-oxidiser mixture flow and the solid fuel grain. Due to this heat
transfer process, the transient temperature distribution on the fuel surface will change at each
instant. To reflect the effect of the changes in fuel surface temperature (𝑇𝑠 ) distribution on the
pyrolysis behaviour of the fuel, the selected regression rate law must have a dependency on 𝑇𝑠 .
Besides that, the fuel in this work is Hydroxyl-Terminated Polybutadiene (HTPB). For these
reasons, the pyrolysis process of the fuel has to be modelled by using the Arrhenius-type regression
rate (𝑟̇𝐴𝑟𝑟 ) law (refer to equation (4)). As the value of 𝑟̇𝐴𝑟𝑟 governs the amount of fuel injected to
the oxidiser stream and the internal combustion ballistics of the motor, the accuracy of the 𝑇𝑠
distribution is crucial. To determine the transient 𝑇𝑠 distribution at each instant accurately, the
approach to model and implement the fluid-solid coupled heat transfer process must be correct.
The energy balance equation at the fuel surface governs the interfacial fluid-solid coupled heat
transfer process. According to the modelling approaches from Section 2.2, the heat transfer process
at the fluid-solid interface can be assumed as quasi-steady, one-dimensional and dominant in the
direction normal to the fuel surface. Under these assumptions, the mathematical form of the
interfacial energy balance equation is [4]:
𝑞̇ 𝑐𝑜𝑛𝑣 + 𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 − 𝑞̇ 𝑝𝑦𝑟 − 𝑞̇ 𝑐𝑜𝑛𝑑 = 0 (6)
where 𝑞̇ 𝑐𝑜𝑛𝑣 , 𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 , 𝑞̇ 𝑝𝑦𝑟 and 𝑞̇ 𝑐𝑜𝑛𝑑 are the convective, net thermal radiative, pyrolysis and
conductive heat fluxes, respectively. This interfacial energy balance equation is only suitable for
non-liquefying solid fuel, which is the central focus of this thesis. To solve this equation for the 𝑇𝑠
distribution, and therefore the 𝑟̇𝐴𝑟𝑟 distribution, a thorough understanding of the formulation of
each heat flux term is required. For this reason, the remaining subsections of this section are
dedicated to explaining the underlying theories and modelling approach of each heat flux term. To
complete the model description of the fluid-solid coupled heat transfer process, the solution method
to determine the 𝑇𝑠 distribution will also be provided.

23
3.2.1 Convective Heat Flux Modelling
The convective heat transfer from the near-wall fuel-oxidiser mixture flow to the solid fuel grain
is conductive due to the no-slip condition at the fuel surface. Hence, Fourier's law of heat
conduction is used to model the convective heat flux (𝑞̇ 𝑐𝑜𝑛𝑣 ) adjacent to the fuel surface. With this
modelling approach and considering the underlying assumptions of the interfacial energy balance
equation, the mathematical form of this heat flux term is [5]:
𝜕𝑇
𝑞̇ 𝑐𝑜𝑛𝑣 = 𝑘𝑔 |𝑦=0+ | (7)
𝜕𝑦 𝑦=0

where 𝑦, 𝑘𝑔 |𝑦=0+ and 𝜕𝑇⁄𝜕𝑦|𝑦=0 are defined as the wall-normal coordinate, conductivity of the

multi-component fluid mixture and wall-normal temperature gradient, respectively. A wall-normal


coordinate of 𝑦 = 0+ refers to the centre height of the fluid-cell adjacent to the fuel surface, whereas
a wall-normal coordinate of 𝑦 = 0 refers to the fuel surface. Equation (7) is suitable to modelling
the 𝑞̇ 𝑐𝑜𝑛𝑣 term in the present work because it is capable of integration within the framework of
user-defined boundary conditions of the CFD solver, Eilmer 4.

To provide an integrative framework for equation (7), a one-sided finite difference scheme is used
to approximate the 𝜕𝑇⁄𝜕𝑦|𝑦=0 term in this equation. In the literature, this approach was used by
Kan Qin et al. in their CFD model for the fluid-structure-thermal simulation of thrust bearings [8].
With the one-sided finite difference scheme, the numerical approximation of 𝜕𝑇⁄𝜕𝑦|𝑦=0 is:
𝜕𝑇 𝑇𝑦=0+ − 𝑇𝑦=0
| = (8)
𝜕𝑦 𝑦=0 ∆𝑦

where 𝑇𝑦=0+ , 𝑇𝑦=0 and ∆𝑦 are the fluid temperature at the centre of the fluid-cell adjacent to the
fuel surface, fuel surface temperature and the first-cell height, respectively. The presence of 𝑇𝑦=0+
term in equation (8) leads to the fluid-solid coupling at the fuel surface. As this numerical
approximation scheme has a first-order truncation error, the magnitude of ∆𝑦 must be sufficiently
small to ensure the truncation error of 𝜕𝑇⁄𝜕𝑦|𝑦=0 is negligible. To correctly select the magnitude
of ∆𝑦, the near-wall modelling approach is required. This approach involves converting ∆𝑦 to the
equivalent non-dimensional wall distance (𝑦 + ). The decision on the magnitude of ∆𝑦 should be
based on the near-wall boundary layer region that the 𝑦 + value represents under the law of the wall
and the compatibility of the 𝑦 + value to the turbulence model of the CFD solver.

24
Another modelling approach for the 𝑞̇ 𝑐𝑜𝑛𝑣 term is by using the quasi-steady flame model from
Karabeyoglu and Altman, which is based on Marxman’s turbulent boundary layer combustion
model. Under this model, the mathematical form of 𝑞̇ 𝑐𝑜𝑛𝑣 is [9]:
0.03 ∙ 𝑞 1⁄(1−𝑘) 𝐵𝑡 ∙ ℎ𝑣 0.8⁄(1−𝑘) −𝑘⁄(1−𝑘)
𝑞̇ 𝑐𝑜𝑛𝑣 = ( −0.2 ) ( 𝑘⁄(𝑘−1) ) 𝑧 −0.2⁄(1−𝑘) 𝐺0 𝑟̇ (9)
𝜇 𝜌𝑠
where 𝜇, 𝐵𝑡 , ℎ𝑣 , 𝜌𝑠 , 𝑧, 𝐺0 and 𝑟̇ are defined as the viscosity, thermochemical blowing parameter,
total heat of gasification, solid fuel density, axial coordinate, oxidiser mass flux and dimensional
regression rate, respectively. Parameters 𝑞 and 𝑘 are correlated by the Marxman’s blocking factor
(𝐶𝑓 ⁄𝐶𝑓0 ), which is defined as [9]:
𝐶𝑓
= 𝑞𝐵𝑎 −𝑘 (10)
𝐶𝑓0
where 𝐵𝑎 is defined as the aerodynamic blowing parameter. In literature, Funami and Shimada
used equation (9) in their hybrid rocket motor CFD model to modelling the 𝑞̇ 𝑐𝑜𝑛𝑣 term in their gas-
solid interface energy balance equation [10]. Nevertheless, it is not recommended to use equation
(9) to modelling the 𝑞̇ 𝑐𝑜𝑛𝑣 term in the present work because the applicability of this equation is
restrictive by its underlying assumptions on the boundary layer characteristics. In contrary,
equation (7) remains a better modelling option because it has demonstrated integrability to the CFD
solver as a numerically-discretised boundary condition, without compromising the generality of
the heat transfer problem.

3.2.2 Thermal Radiative Heat Flux Modelling


The net thermal radiative heat flux (𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 ) at the fuel surface can be defined as:
𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 = 𝑞̇ 𝑖𝑛𝑐 − 𝑞̇ 𝑤𝑎𝑙𝑙,𝑒𝑚𝑖 (11)
where 𝑞̇ 𝑖𝑛𝑐 and 𝑞̇ 𝑤𝑎𝑙𝑙,𝑒𝑚𝑖 are defined as the heat fluxes due to the incident thermal radiation and
emission of thermal radiation at the fuel surface, respectively. The 𝑞̇ 𝑖𝑛𝑐 term arises due to the
thermal radiation effect in the flow field. To establish the theoretical frameworks for both 𝑞̇ 𝑖𝑛𝑐 and
𝑞̇ 𝑤𝑎𝑙𝑙,𝑒𝑚𝑖 terms and the thermal radiation effect in the flow field, the remaining subsections of this
section will explain the relevant theories and approaches to model them.

25
Flow Field and Incident Thermal Radiation Heat Transfer Modelling
As mentioned in Section 2.2, the thermal radiation effect in the flow field and thus 𝑞̇ 𝑖𝑛𝑐 can be
modelled using the P1-radiation model. This radiation model is suitable to model optically thick
flow fields, which usually correspond to a spectral optical thickness of greater than one [11].
Besides that, it accounts for the scattering effect without additional computational costs.
Furthermore, it is also compatible with flow geometries with body-fitted coordinates. [12].
The P1-radiation model is defined by the following second-order elliptical partial differential
equation (PDE) [11]:
∇ ∙ (Γ𝜆 ∙ ∇𝐺𝜆 ) − 𝑎𝜆 𝐺𝜆 + 4𝜎𝑎𝜆 𝑇 4 = 0 (12)
where G𝜆 , 𝑎𝜆 , 𝜎 and 𝑇 are defined as the incident radiation, spectral absorption coefficient, Stefan-
Boltzmann constant and temperature, respectively. In equation (12), parameter Γ𝜆 is defined as
[11]:
1 1
Γ𝜆 = ≡ (13)
3𝐾𝜆 3(𝑎𝜆 + 𝜎𝑠𝜆 )
where 𝐾𝜆 and 𝜎𝑠𝜆 are defined as the spectral extinction and scattering coefficients, respectively.
The 𝑎𝜆 term which appears in both equation (12) and (13) can be modelled using the Planck Mean
Absorption Coefficients (PMAC) for common combustion products, such as H2O, CO2 and CO.
With the PMAC approach, the 𝑎𝜆 term becomes the mixture weighted absorption coefficient
(𝑘𝑚𝑖𝑥 ). Mathematically, 𝑘𝑚𝑖𝑥 is defined as [13]:
𝑁

𝑘𝑚𝑖𝑥 ≡ 𝑎𝜆 = 𝑝𝑡𝑜𝑡 ∑ 𝑥𝑖 𝑘𝑖 (𝑇) (14)


𝑖=1

where 𝑝𝑡𝑜𝑡 , 𝑥𝑖 and 𝑘𝑖 (𝑇) are defined as the total pressure of the gas mixture and the molar fraction
and PMAC value of the 𝑖𝑡ℎ species in the gas mixture, respectively. The 𝑘𝑖 (𝑇) term is a temper-
ature-dependent function that is fitted to the HITEMP experimental data of the 𝑖𝑡ℎ species.
Mathematically, the 𝑘𝑖 (𝑇) term can be described by the Gaussian nth degree function [13]:
𝑛
𝑇−𝛽 2
−( 𝛾 𝑖 )
𝑘𝑖 (𝑇) = ∑ 𝑎𝑖 𝑒 𝑖 (15)
𝑖=0

where 𝑎𝑖 , 𝛽𝑖 and 𝛾𝑖 are defined as the fitting coefficients of the 𝑖𝑡ℎ species. The fitting coefficients
of each species are tabulated in Table 2.

26
Table 4: Fitting coefficients of H20, CO2 and CO [13].
Species H2O CO2 CO

𝑎1 63.87 34.57 0.9245

𝛽1 149.5 45.32 503.1

𝛾1 174.3 838.4 106.3

𝑎2 2.629 1.22 1.51

𝛽2 493.6 930.2 630.9

𝛾2 111.1 184.9 200.3

𝑎3 222.9 -22.32 0.4082

𝛽3 -2110 323.9 418

𝛾3 1592 217.9 441.8

𝑎4 0.991 17.14 1.571

𝛽4 1700 92.98 845.4

𝛾4 619.2 1657 371.8

The fit function (refer to equation (15)) is only valid for a temperature range of 300 – 2500 K [13].
Assuming the flow field is a grey medium with constant 𝐾𝜆 and 𝜎𝑠𝜆 values, the value of G𝜆 is
calculated at each node in the fluid domain by solving equation (12) in conjunction with the
Marshak boundary condition at the wall (e.g. slip wall, isothermal wall and fuel surface) [11]. This
boundary condition is defined as ( [11], [14])
∂G 𝜀𝑤
−Γ | = (4𝜎𝑇𝑤4 − 𝐺𝑤 ) (16)
∂n 𝑤 2(2 − 𝜀𝑤 )
where 𝑤 and 𝜀𝑤 are defined as the indicated variable at the wall and wall emissivity, respectively.
To solve equation (12) in conjunction with equation (16), the finite volume method (FVM)
approach is required. To implement this approach, the work from Krishnamoorthy et al. is most
relevant for this purpose. Full details of their FVM approach to implementing the P1-radiation
model is in [15]. Once the value of G𝜆 at the centre node of a fluid-cell is known, the divergence
of the radiation source term (∇ ∙ ⃗q 𝑟𝑎𝑑 ) local to that fluid-cell will be calculated. The equation of
this source term is [11]:
∇ ∙ ⃗q 𝑟𝑎𝑑 = 𝑎𝜆 𝐺𝜆 − 4𝜎𝑎𝜆 𝑇 4 (17)

27
Equation (17) implies that the difference between the thermal radiation absorbed and emitted in a
volume contributes to the net thermal radiative heat flux out of that volume [11]. When the value
of G𝜆 near the fuel surface (G𝜆𝑠 ) is known, then the 𝑞̇ 𝑖𝑛𝑐 value at the fuel surface is simply:
𝑞̇ 𝑖𝑛𝑐 = G𝜆𝑠 ≡ 𝐺𝑤 (18)
Aside from the P-1 radiation model, there are several types of radiation model in the literature. This
may include:
1. Discrete transfer radiation model (DTRM) [16].
2. Rosseland model [17].
3. Surface-to-surface model [17].
4. Discrete ordinates model [18].

Fuel Surface Thermal Radiation Emission Modelling


Assuming the solid fuel grain is a grey body, the 𝑞̇ 𝑤𝑎𝑙𝑙,𝑒𝑚𝑖 term at the fuel surface can be modelled
using the following equation [5]:
𝑞̇ 𝑤𝑎𝑙𝑙,𝑒𝑚𝑖 = 𝜀𝑠 𝜎𝑇𝑠4 (19)
where 𝜀𝑠 is defined as the emissivity of fuel surface.

3.2.3 Pyrolysis Heat Flux Modelling


The fuel pyrolysis heat flux (𝑞̇ 𝑝𝑦𝑟 ) term in the interfacial energy balance equation is a result of the
phase change process at the surface of the solid fuel grain. For a non-liquefying hybrid rocket fuel,
the solid fuel grain undergoes a phase change from solid to gas directly through sublimation. The
energy change in the sublimation process of solid fuel grain is the pyrolysis enthalpy (ℎ𝑝𝑦𝑟 ). As
the sublimation process is endothermic, the value of ℎ𝑝𝑦𝑟 is positive. For a Hydroxyl-Terminated
Polybutadiene (HTPB) fuel, the corresponding value of ℎ𝑝𝑦𝑟 is 1.82 × 106 J∙kg-1 [19].
The 𝑞̇ 𝑝𝑦𝑟 term is simply the multiplicative product of the pyrolysis mass flow flux (𝑚̇𝑝𝑦𝑟 ) and
ℎ𝑝𝑦𝑟 . Hence, the equation of 𝑞̇ 𝑝𝑦𝑟 is [1]:
𝑞̇ 𝑝𝑦𝑟 = 𝑚̇𝑝𝑦𝑟 ℎ𝑝𝑦𝑟 (20)
As the pyrolysis process at the surface of the solid fuel grain is modelled by using the Arrhenius-
type regression rate (𝑟̇𝐴𝑟𝑟 ) law (refer to equation (4)), the mathematical form of 𝑚̇𝑝𝑦𝑟 is [1]:
𝑚̇𝑝𝑦𝑟 = 𝜌𝑠 𝑟̇𝐴𝑟𝑟 (21)
where 𝜌𝑠 is defined as the density of the solid fuel grain.
28
3.2.4 Conductive Heat Flux and Transient Solid Heat Conduction Modelling
The conductive heat flux (𝑞̇ 𝑐𝑜𝑛𝑑 ) term in the interfacial energy balance equation is a result of the
heat transfer process in the solid fuel grain. As the 𝑞̇ 𝑐𝑜𝑛𝑑 term can be extracted by rearranging the
interfacial energy balance equation, explicit computation of this heat flux term is not required. With
this approach, the 𝑞̇ 𝑐𝑜𝑛𝑑 term becomes the following form:
𝑞̇ 𝑐𝑜𝑛𝑑 = 𝑞̇ 𝑐𝑜𝑛𝑣 + 𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 − 𝑞̇ 𝑝𝑦𝑟 (22)
By treating this form of 𝑞̇ 𝑐𝑜𝑛𝑑 as the heat flux boundary condition of the transient heat conduction
problem in the solid fuel grain, the heat transfer between the fluid and solid fuel grain becomes
coupled. To define the transient heat conduction problem, consider the following equation [1]:
∂𝑇𝑠
− 𝛼∇2 𝑇𝑠 = 0 (23)
∂t
where
𝑘𝑠
𝛼= (24)
𝜌𝑠 𝑐𝑠
where 𝛼, 𝑘𝑠 , 𝜌𝑠 , 𝑐𝑠 and 𝑇𝑠 are defined as the thermal diffusivity, conductivity, density, specific heat
and surface temperature of the solid fuel grain, respectively. Equation (23) does not consider the
energy loss term due to fuel pyrolysis (𝑟̇𝐴𝑟𝑟 (∂𝑇𝑠 ⁄∂𝑦)) because it has small influence on the solution
when the value of 𝑟̇𝐴𝑟𝑟 is significantly smaller than the fuel-oxygen mixture velocity [3]. Besides
that, if the physical properties of the solid fuel grain are homogeneous, then 𝑘𝑠 , 𝜌𝑠 and 𝑐𝑠 are
uniform throughout the solid fuel grain. As the fuel is Hydroxyl-Terminated Polybutadiene
(HTPB), the thermochemical properties of the fuel are tabulated in Table 5.
Table 5: Thermochemical properties of HTPB fuel [19].
𝒌𝒔 (W∙m-1∙K-1) 𝝆𝒔 (kg∙m-3) 𝒄𝒔 (J∙kg-1∙K-1)
0.1572 803.5 1957.0

Furthermore, if the transient heat conduction in the solid fuel grain is one-dimensional and
dominant in the direction normal to the fuel surface, then equation (23) simplifies into:
∂𝑇𝑠 𝜕 2 𝑇𝑠
−𝛼 =0 (25)
∂t 𝜕𝑦 2
where 𝑦 is defined as the wall-normal coordinate. Solving equation (25) along the vertical cross-
section of the solid fuel grain at any axial coordinate along the fuel surface leads to the solution for
the local 𝑇𝑠 value. Before solving equation (25), the boundary treatment of this equation is required.
In boundary treatment, the fuel surface is subject to the heat flux boundary condition as defined by
29
equation (22), whereas the outer wall of the solid fuel grain is subject to an adiabatic wall boundary
condition. The adiabatic wall boundary condition reflects the presence of thermal insulation to
protect the structural integrity of the motor case under high internal pressure and temperatures. To
solve equation (25), the required approach for this purpose is the numerical time integration
method. The way the numerical time integration is carried out depends on the type of the fluid-
solid heat transfer coupling approach. There are two types of coupling approach: tight and loose
coupling approaches.

Tight coupling approach is desirable for time-accurate transient simulations [20]. This approach
assumes that the time scales of the transient fluid flow and the transient heat conduction in the solid
fuel grain are equal [20]. As a result, equation (25) must be solved for the 𝑇𝑠 distribution at each
fluid domain time step. The solid block model in Eilmer 4 adopts the tight coupling approach. In
practice, this solid block requires meshing and boundary treatment, which may add up to a large
CFD model when combined with the fluid domain blocks. Besides that, the time scale of the
transient fluid flow tends to be very small, requiring a very small simulation time step for the fluid
domain. As a result, the wall-clock time of the simulation may be unacceptably long to allow for
practical applications.

On the other hand, the loose coupling approach utilises the very distinct time scales of the transient
fluid flow and the transient heat conduction in the solid fuel grain by taking the later time scale as
the overall simulation time step. The transient heat conduction time scale (𝜏ℎ𝑒𝑎𝑡 ) is defined as [21]:
𝐿2𝑠
𝜏ℎ𝑒𝑎𝑡 = (26)
𝛼
where 𝐿𝑠 is defined as the characteristic length of the solid fuel grain. In the loose coupling
approach, the governing equations of the transient fluid flow and heat conduction in the solid fuel
grain are solved separately at their respective time scale [22]. When the simulation time of the fluid
domain has reached a multiple of 𝜏ℎ𝑒𝑎𝑡 , both fluid and solid domains will exchange information
by the boundary condition that couples them [22]. This information exchange provides a
precondition to solving equation (25) for the new 𝑇𝑠 distribution. Concurrently, the fluid flow
would have already reached a quasi-steady state as 𝜏ℎ𝑒𝑎𝑡 tends to be much longer than the fluid
flow time scale. As a result, the transient simulation is essentially a time series of quasi-steady flow
states that are separated by a regular interval of 𝜏ℎ𝑒𝑎𝑡 [8]. As this coupling approach excludes the

30
necessity to solve the fluid-solid coupled heat transfer problem at each fluid domain time step, it is
less computationally expensive than the tight coupling approach. Therefore, the loose coupling
approach is the most viable option for a robust simulation.

One way to implement the loose coupling approach is by using the Non-Integer System
Identification (NISI) Method, which is first presented by Battaglia et al. [23]. This method provides
a framework to analyse the one-dimensional transient heat conduction problem outlined earlier as
a non-integer system. At a given location, this system takes a time-dependent heat flux as input and
returns a time-dependent temperature as output [24]. The relationship between the input heat flux
and output temperature of the non-integer system is expressed by a non-integer model [23]. There
are three equivalent forms of non-integer model: the rational transfer function, the developed modal
form and the factorised modal form [23]. Further details of all types of non-integer model and their
corresponding identification methods are in [23]. Once the non-integer model is identified, it is
used to compute the impulse response of the system [23].

According to Battaglia et al., a one-dimensional transient heat conduction problem can be modelled
as the discrete convolution between the input heat flux and the impulse response of the system [23].
By the convolution theorem, the temperature at an arbitrary wall-normal coordinate (𝑦) and time
(𝑡 = 𝑘ℎ) is [23]:
𝑘

𝑇(𝑦, 𝑘ℎ) = ∑ 𝐼((𝑘 − 𝑛 + 1)ℎ)𝑄(𝑘ℎ) + 𝑇0 (𝑦) (27)


𝑛=0

where 𝑘, ℎ, 𝐼, 𝑄 and 𝑇0 are defined as the time index, time step, impulse response, input heat flux
and initial temperature, respectively. Mallard and Jahn adapted equation (27) to solve the one-
dimensional transient heat conduction problem outlined earlier. In their work, their adapted form
of equation (27) is [25]:
𝑘

𝑇(𝑦, 𝑘ℎ) = {𝐼 ∙ 𝑄}(𝑘ℎ) = ∑ 𝐼((𝑘 − 𝑛)ℎ)𝑄(𝑘ℎ) , 0≤𝑘≤𝑁 (28)


𝑛=0

They expressed equation (28) as the following matrix product [25]:


𝑇0 𝐼0 0 ⋯ 0 𝑄0
𝑇1 𝐼 𝐼0 ⋯ ⋮ 𝑄
𝑇 = {𝐼 ∙ 𝑄} ↔ [ ] = [ 1 ∙ 1
⋱ 0] [ ⋮ ] (29)
⋮ ⋮ ⋮
𝑇𝑁 𝐼𝑁 𝐼𝑁−1 ⋯ 𝐼0 𝑄𝑁

31
where [𝑇0 𝑇1 ⋯ 𝑇𝑁 ]𝑇 , [𝐼0 𝐼1 ⋯ 𝐼𝑁 ]𝑇 and [𝑄0 𝑄1 ⋯ 𝑄𝑁 ]𝑇 are defined as the
discretised temperature, discretised impulse response and the discretised input heat flux in the time
axis at a wall-normal coordinate (𝑦), respectively. Inline to the loose coupling approach, the time
step to discretise 𝑇, 𝐼 and 𝑄 in the time axis is 𝜏ℎ𝑒𝑎𝑡 (refer to equation (26)).

At an axial coordinate on the fuel surface, the vertical cross-section of the solid fuel grain is
discretised in the wall-normal coordinate (𝑦) system. By applying equation (29) at each wall-
normal coordinate (𝑦) along the discretised vertical cross-section, the vertical temperature distribu-
tion in the solid fuel grain can be calculated from the time history of 𝑄 at the fuel surface at each
𝜏ℎ𝑒𝑎𝑡 . From the known time history of the vertical temperature distribution in the solid fuel grain,
the corresponding transient profile of 𝑇𝑠 at the same axial coordinate can be determined.

32
3.3 Chemistry Kinetics
As mentioned in Section 2.2, the reduced chemistry kinetics of the Hydroxyl-Terminated
Polybutadiene (HTPB)-oxygen mixture is required for combustion modelling. In the literature,
Morinigo and Quesada investigated three reduced chemistry kinetics of two, four and six steps to
simulate the combustion of solid HTPB fuel and gaseous oxygen. Full details of all their reduced
chemistry kinetics are in [26].

The two-step reduced chemistry kinetics of the HTPB-oxygen mixture from Morinigo and Quesada
is chosen for this work because of its simplicity and reasonable predictive capabilities. This
chemistry kinetics only involves five species, including 1,3 butadiene (C4H6), O2, CO, CO2 and
H2O. The reaction mechanisms of these species are based on the following two global reactions
[26]:
𝐶4 𝐻6 + 3.5𝑂2 → 4𝐶𝑂 + 3𝐻2 𝑂 (R1)
𝐶𝑂 + 0.5𝑂2 ↔ 𝐶𝑂2 (R2)
The forward and backward reaction rates of these two global reactions are defined by the
Arrhenius-type rate:
𝑟̇ = 𝐴𝑇 𝑛 𝑒𝑥𝑝{− 𝐸𝑎 ⁄𝑅𝑢 𝑇}[𝑋𝐹𝑢𝑒𝑙 ]𝑎 [𝑋𝑜𝑥𝑖𝑑𝑖𝑠𝑒𝑟 ]𝑏 (30)
where [𝑋𝐹𝑢𝑒𝑙 ] and [𝑋𝑜𝑥𝑖𝑑𝑖𝑠𝑒𝑟 ] are defined as the molar concentrations of the fuel and oxidiser,
respectively. The equilibrium kinetic parameters for the forward and backward Arrhenius-type
reaction rates of each global reaction are tabulated in Table 6.
Table 6: Equilibrium kinetic parameters of the two-step reduced finite rate chemistry kinetics of HTPB-
oxygen mixture [26].
Reaction 𝑨𝒇 𝑬𝒂,𝒇 (cal∙mol-1) 𝑨𝒌 𝑬𝒂,𝒌 (cal∙mol-1) 𝒏 𝒂 𝒃
R1 1.35 × 1010 3 × 104 0 0 0 1 1
6 6 7 7
R2 2.0 × 10 1.2 × 10 8.1 × 10 7.72 × 10 0 1 0.5

The unit system of 𝐴 is based on [m, kmol and s], whereas subscripts 𝑓 and 𝑘 indicate the forward
and backward reactions, respectively. Besides that, the universal gas constant (𝑅𝑢 ) under the [cal,
mol] unit system is 1.987 cal∙mol-1∙K-1.

33
The remaining subsections of this section will explain the unit conversion of the equilibrium kinetic
parameters (refer to Table 6), and the finite-rate formulation of the two-step reduced chemistry
kinetics of the HTPB-oxygen mixture.

3.3.1 Unit Conversion of the Equilibrium Kinetic Parameters


As the two-step reduced chemistry kinetics is to be implemented in Eilmer 4, the units of the
equilibrium kinetic parameters must be equal to that of Eilmer 4. However, as indicated in Table
7, this is not the case at the present stage.
Table 7: Differences between the unit system of the two-step reduced chemistry kinetics and Eilmer 4.
Units
Two-Step Reduced Conversion Factor
Parameter Eilmer 4
Chemistry Kinetics to Eilmer 4
Molar concentration, [𝑋] kmol∙m-3 mol∙m-3 10-3
Molar fraction, 𝑋 kmol mol 10-3
Temperature, T K K 1
Species production rate, 𝑤̇ kg∙m ∙s
-3 -1
kg∙m ∙s
-3 -1
1
Molar weight, 𝑀𝑊 kg∙kmol-1 kg∙mol-1 103

In Table 7, the species production rate (𝑤̇ ) is defined as:


𝑤̇ = 𝑀𝑊 ∙ 𝐴𝑇𝑛 𝑒𝑥𝑝{− 𝐸𝑎 ⁄𝑅𝑢 𝑇}[𝑋𝐹𝑢𝑒𝑙 ]𝑎 [𝑋𝑜𝑥𝑖𝑑𝑖𝑠𝑒𝑟 ]𝑏 (31)
As the unit of 𝑤̇ under the two-step reduced chemistry kinetics and Eilmer 4 are equal (refer to
Table 7), there is a need to convert the unit of 𝐴 under this chemistry kinetics to the unit system of
Eilmer 4 to maintain this equality. For this purpose, equation (31) is used to derive the unit
conversion factor for 𝐴.

Under the unit system of the two-step reduced chemistry kinetics ([𝐴(𝐶ℎ𝑒𝑚. ) ]), equation (31)
becomes:
[𝑘𝑔 ∙ 𝑚−3 ∙ 𝑠 −1 ] = [𝑘𝑔 ∙ 𝑘𝑚𝑜𝑙 −1 ] ∙ [𝐴(𝐶ℎ𝑒𝑚. ) ] ∙ [𝐾 ]𝑛 ∙ [1] ∙ [𝑘𝑚𝑜𝑙 ∙ 𝑚−3 ]𝑎+𝑏 (32)
By rearranging equation (32) in terms of [𝐴(𝐶ℎ𝑒𝑚. ) ], it follows that:
{𝑘𝑚𝑜𝑙 [1−(𝑎+𝑏)] 𝑚[−3+3(𝑎+𝑏)] 𝐾 −𝑛 ∙ 𝑠 −1 }
[𝐴(𝐶ℎ𝑒𝑚. ) ] = ⏟
(33)
𝑈𝑛𝑖𝑡 𝑠𝑦𝑠𝑡𝑒𝑚 𝑜𝑓 𝑡ℎ𝑒 𝑐ℎ𝑒𝑚𝑖𝑠𝑡𝑟𝑦 𝑘𝑖𝑛𝑒𝑡𝑖𝑐𝑠

Equation (33) gives the unit of the values of 𝐴 in Table 6.

34
By applying the conversion factors from Table 7 to the relevant parameters in equation (33), it
follows that:
[𝐴 (𝐶ℎ𝑒𝑚. )] = 103[1−(𝑎+𝑏)] ∙ {𝑚𝑜𝑙 [1−(𝑎+𝑏)] [−3+3(𝑎+𝑏)] −𝑛
⏟ 𝑚 𝐾 ∙ 𝑠 −1 } (34)
𝐸𝑖𝑙𝑚𝑒𝑟 4 𝑢𝑛𝑖𝑡 𝑠𝑦𝑠𝑡𝑒𝑚

From equation (34), the unit conversion factor for 𝐴 (𝑈𝐶𝐴 ) is:
𝑈𝐶𝐴 = 103[1−(𝑎+𝑏)] (35)
This is the conversion factor to be applied on the values of 𝐴 in Table 6 when all other parameters
in equation (31) is based on the unit system of Eilmer 4. After unit conversion, the unit of 𝐴 under
the unit system of Eilmer 4 ([𝐴(𝐸𝑖𝑙𝑚𝑒𝑟 4) ]) is:
[𝐴(𝐸𝑖𝑙𝑚𝑒𝑟 4) ] = 𝑚𝑜𝑙 [1−(𝑎+𝑏)] 𝑚[−3+3(𝑎+𝑏)] 𝐾 −𝑛 ∙ 𝑠 −1 (36)
By applying equation (35) and (36) on the values of 𝐴 for both forward and backward reactions in
Table 6, the updated values of 𝐴 were calculated and are tabulated in Table 8.
Table 8: Pre-exponential factor of the two-step reduced chemistry kinetics in the unit system of Eilmer 4.
Reaction 𝑨𝒇 𝑨𝒌
R1 1.35 × 107 mol-1∙m3∙s-1 0
R2 2.0 × 10 4.5
mol ∙m ∙s
-0.5 1.5 -1
8.1 × 10 5.5
mol-0.5∙m1.5∙s-1

35
3.3.2 Finite-rate Formulation of the Two-Step Reduced Chemistry Kinetics
To simulate the combustion of the HTPB-oxygen mixture, the finite-rate formulation of the two-
step reduced chemistry kinetics is required to compute the net production rate of each species
(C4H6, O2, CO, CO2 and H2O).
By using equation (30) in conjunction with Table 6, the forward and backward reaction rates of the
two global reactions (refer to R1 and R2) are:
1 1
𝑅𝑓1 = 𝐴𝑓1 𝑒𝑥𝑝{− 𝐸𝑎𝑓1 ⁄𝑅𝑢 𝑇}[𝑋𝐶4 𝐻6 ] [𝑋𝑂2 ] (37)
0.5
𝑅𝑓2 = 𝐴𝑓2 𝑒𝑥𝑝{− 𝐸𝑎𝑓2 ⁄𝑅𝑢 𝑇}[𝑋𝐶𝑂 ]1 [𝑋𝑂2 ] (38)
1
𝑅𝑘2 = 𝐴𝑘2 𝑒𝑥𝑝{− 𝐸𝑎𝑘2 ⁄𝑅𝑢 𝑇}[𝑋𝑐𝑂2 ] (39)
Repeat for convenience, the values of 𝐴 in equation (37), (38) and (39) are based on Table 8.
Lastly, the finite-rate formulation of the two-step reduced chemistry kinetics is:
𝑤̇𝐶4 𝐻6 = −𝑀𝑊𝐶4 𝐻6 ∙ 𝑅𝑓1 (40)

𝑤̇𝑜2 = 𝑀𝑊𝑜2 ∙ (−3.5 ∙ 𝑅𝑓1 − 0.5 ∙ 𝑅𝑓2 + 0.5 ∙ 𝑅𝑘2 ) (41)

𝑤̇𝑐𝑜 = 𝑀𝑊𝑐𝑜 ∙ (4 ∙ 𝑅𝑓1 − 𝑅𝑓2 + 𝑅𝑘2 ) (42)


𝑤̇𝐻2 𝑂 = 3 ∙ 𝑀𝑊𝐻2 𝑂 ∙ 𝑅𝑓1 (43)
𝑤̇𝑐𝑜2 = 𝑀𝑊𝑐𝑜2 ∙ (𝑅𝑓2 − 𝑅𝑘2 ) (44)
where 𝑤̇ is defined as the species production rate. The finite-rate formulation is based on the unit
system of Eilmer 4.

36
3.4 Melt Layer Modelling
The melt layer modelling aims to model the kinematic effects and mass transfer mechanisms at the
gas-melt-layer interface. Inline to this approach, this interface will be modelled as the gas-liquid
boundary condition of the fluid domain, thus avoiding the need to simulate two-phase flow. Under
this modelling framework, the global cartesian coordinate system of the fluid domain is placed on
the gas-melt-layer interface. As a result, the wall-normal coordinate (𝑦) of this interface is equal to
zero.

This work entails the melt layer modelling of the liquefying paraffin wax fuel by combining the
liquefying fuel combustion modelling approach by Weinstein and Gany (refer to [27]) and the thin-
film model by Meredith et al. (refer to [28]). Figure 1 illustrates the heat and mass transfer model
of liquefying fuel.

Figure 1: Schematic of the heat and mass transfer process during the combustion of liquefying fuel,
adapted from [27].

According to Weinstein and Gany, the heat transfer at the gas-melt-layer interface is assumed to
be one-dimensional, wall-normal and steady. Besides that, the effect of heat transfer due to thermal
radiation is neglected. Hence, the heat flux balance equation at this interface is [27]:
𝑞̇ 𝑐𝑜𝑛𝑣 − 𝑞̇ 𝑣 − 𝑞̇ 𝑚 = 0 (45)
where 𝑞̇ 𝑐𝑜𝑛𝑣 , 𝑞̇ 𝑣 and 𝑞̇ 𝑚 are defined as the heat flux due to convection, vaporisation and melting,
respectively. As this interface is subject to no-slip and translating wall conditions, it follows that
𝑞̇ 𝑐𝑜𝑛𝑣 is equivalent to a conductive heat flux. Hence, 𝑞̇ 𝑐𝑜𝑛𝑣 is defined as (see Section 3.2.1):
(𝑇𝑦=0+ − 𝑇𝑦=0 )
𝑞̇ 𝑐𝑜𝑛𝑣 = 𝑘𝑔 |𝑦=0+
∆𝑦 (46)
where 𝑇𝑦=0+ , 𝑇𝑦=0 and ∆𝑦 are the fluid temperature at the centre of the fluid-cell adjacent to the
gas-melt-layer interface, gas-melt-layer interface temperature and the first-cell height, respectively.
37
Furthermore, the gas-melt-layer and melt-layer-solid interfaces are isothermal, but different
temperatures. The gas-melt-layer interface is at the vaporisation temperature (𝑇𝑣 ), whereas the
melt-layer-solid interface is at the melting temperature (𝑇𝑚 ).
Hence, the equations of 𝑞̇ 𝑐𝑜𝑛𝑣 , 𝑞̇ 𝑣 and 𝑞̇ 𝑚 are [27]:
(𝑇𝑦=0+ − 𝑇𝑣 )
𝑞̇ 𝑐𝑜𝑛𝑣 = 𝑘𝑔 |𝑦=0+ (47)
∆𝑦
𝑞̇ 𝑣 = 𝜌𝑙 𝑟̇𝑣 [𝐻𝑣 + 𝐶𝑝,𝑙 (𝑇𝑣 − 𝑇𝑚 )] (48)
𝑞̇ 𝑚 = 𝜌𝑠 𝑟̇𝑚 [𝐻𝑚 + 𝐶𝑝,𝑠 (𝑇𝑚 − 𝑇𝑎 )] (49)
where 𝜌, 𝐻, 𝑟̇ and 𝐶𝑝 are defined as density, latent enthalpy, rate and specific heat capacity,
respectively. The subscripts 𝑙, 𝑠, 𝑣, 𝑚 and 𝑎 indicate liquid, solid, vaporisation, melting and
ambient, respectively.
Assuming the melt layer is thin enough such that its temperature profile is approximately linear in
the wall-normal direction and knowing that the melt-layer-solid interface is subject to a no-slip
condition, 𝑞̇ 𝑚 can be modelled using the Fourier’s law of heat conduction [27]:
(𝑇𝑣 − 𝑇𝑚 )
𝑞̇ 𝑚 = 𝑞̇ 𝑐𝑜𝑛𝑑,𝑙 ≡ 𝑘𝑙 (50)
𝛿
where 𝑘𝑙 and 𝛿 are defined as the conductivity and thickness of the melt layer, respectively. By
substituting equation (50) into equation (49) and then rearrange the resultant equation in terms of
the melting rate (𝑟̇𝑚 ), it follows that:
𝑘𝑙 𝑇𝑣 − 𝑇𝑚
𝑟̇𝑚 = [ ] (51)
𝛿𝜌𝑠 𝐻𝑚 + 𝐶𝑝,𝑠 (𝑇𝑚 − 𝑇𝑎 )
By substituting equation (47), (48) and (50) into equation (45) and then rearrange the resultant
equation in terms of the vaporisation rate (𝑟̇𝑣 ), it follows that:
1 (𝑇𝑦=0+ − 𝑇𝑣 ) (𝑇𝑣 − 𝑇𝑚 )
𝑟̇𝑣 = ∙ [𝑘𝑔 |𝑦=0+ − 𝑘𝑙 ] (52)
𝜌𝑙 [𝐻𝑣 + 𝐶𝑝,𝑙 (𝑇𝑣 − 𝑇𝑚 )] ∆𝑦 𝛿

As mentioned in Section 3.1, the entrainment rate (𝑟̇𝑒𝑛𝑡 ) of the paraffin wax fuel droplets can be
calculated using the entrainment rate model from Karabeyoglu et al [7]. The equation of
entrainment rate by this model is [27]:
2𝛼
𝐺𝑡𝑜𝑡
𝑟̇𝑒𝑛𝑡 = 𝑎 𝛽 (53)
𝑟̇𝑚
where 𝐺𝑡𝑜𝑡 is defined as the oxidiser mass flux. The values of 𝑎, 𝛼 and 𝛽 are 6.88 × 10-14 m9∙kg-3,
1.5 and 2, respectively [27]. The equation of 𝐺𝑡𝑜𝑡 is:
38
𝐺𝑡𝑜𝑡 = (𝜌𝑔 𝑣𝑡𝑜𝑡 )𝑖𝑛𝑙𝑒𝑡 (54)

where 𝜌𝑔 |𝑖𝑛𝑙𝑒𝑡 and 𝑣𝑡𝑜𝑡 |𝑖𝑛𝑙𝑒𝑡 are defined as the density and resultant velocity of the gas-phase flow

at the inlet of the fuel port, respectively.

On the other hand, the thin-film model by Meredith et al. is capable to account for the interfacial
transport processes in Figure 2. Full details of their thin-film model are in [28].

Figure 2: Interfacial transport processes of an arbitrary liquid film [28].

The thin-film model is governed by the mass continuity, momentum and energy conservation
equations. Contrary to the fluid domain, the reference coordinate system of this model is on the
melt-layer-solid interface (refer to Figure 3). The wall-normal coordinate of this coordinate system
is 𝑦𝑙 .

Figure 3: Schematic of the coordinate system of the fluid domain and thin-film model.

To provide an integrative framework for the thin-film model by Meredith et al. and the liquefying
fuel combustion modelling approach by Weinstein and Gany, several assumptions are imposed on
the thin-film model:
1. One-dimensional melt layer in the wall-tangential direction.
2. The melt layer flow is laminar and wavy [28].
3. The melt layer is thin enough to apply the flat surface approximation.
39
4. The velocity profile of the melt layer is quadratic [28].
5. The top and bottom surfaces of the melt layer are isothermal, but different temperatures.
The top surface is at the vaporisation temperature (𝑇𝑣 ), whereas the bottom surface is at the
melting temperature (𝑇𝑚 ).
6. The melting mass flux (𝑚̇𝑚 ), vaporisation mass flux (𝑚̇𝑣 ) and entrainment mass flux
(𝑚̇𝑒𝑛𝑡 ) of the paraffin wax fuel are modelled using the liquefying combustion modelling
approach by Weinstein and Gany.
7. The thickness of the melt layer (𝛿) is greater than zero and already established at the start
of the simulation.
8. No thermal radiation.
9. The melt layer is characterised by its mean properties [28].
10. The melt layer’s density (𝜌𝑙 ) and dynamic viscosity (𝜇𝑙 ) are constant.
11. No droplet impingement, splashing and film separation.
12. Entrained droplets are vaporised immediately so that the fluid domain only has gas-phase
reactions.
The remaining subsections of this section will present and explain the conservation equations of
the simplified thin-film model. Besides that, Section 3.4.3 will provide explanations on how the
liquefying combustion modelling approach by Weinstein and Gany will be modified to integrate
with the thin-film model.

3.4.1 Mass Continuity Equation and Velocity Profile of the Thin-Film Model
As the melt layer is assumed to be one-dimensional in the wall-tangential direction, the mass
continuity equation of the thin-film model (refer to [28]) simplifies to:
𝜕𝛿 𝜕(𝑈̅𝛿) 𝑆𝛿
+ = (55)
𝜕𝑡 𝜕𝑥 𝜌𝑙
̅ are defined as time, axial coordinate along the fuel surface, mass source term,
where 𝑡, 𝑥, 𝑆𝛿 and 𝑈
and mean velocity of the melt layer, respectively. As the net mass accumulation rate of the melt
layer is the difference between the rate of mass gain due to the melting of solid fuel and the rate of
mass loss due to the vaporisation and entrainment of melt layer, the 𝑆𝛿 term is:
𝑆𝛿 = 𝑚̇𝑚 − (𝑚̇𝑣 + 𝑚̇𝑒𝑛𝑡 ) ≡ 𝜌𝑠 𝑟̇𝑚 − 𝜌𝑙 (𝑟̇𝑣 + 𝑟̇𝑒𝑛𝑡 ) (56)

40
Using the modified liquefying fuel combustion modelling approach by Weinstein and Gany (refer
to Section 3.4.3), the 𝑟̇𝑚 , 𝑟̇𝑣 and 𝑟̇𝑒𝑛𝑡 terms in equation (56) are modelled using equation (74), (76)
̅ is [28]:
and (53), respectively. Besides that, the equation of 𝑈
1 𝛿
̅=
𝑈 ∫ 𝑢 (𝑦)𝑑𝑦𝑙 (57)
𝛿 0 𝑥
where 𝑢𝑥 (𝑦𝑙 ) is defined as the quadratic velocity profile (𝑥-velocity) of the melt layer. The equation
of 𝑢𝑥 (𝑦𝑙 ) is [28]:
𝑢𝑥 (𝑦𝑙 ) = 𝑎𝑦𝑙2 + 𝑏𝑦𝑙 + 𝑐 (58)
To determine the coefficients 𝑎, 𝑏 and 𝑐, the equation of 𝑢𝑥 (𝑦𝑙 ) is subject to two boundary
conditions: wall-tangential shear stress (𝜏𝑥𝑦 ) condition at the top of the melt layer (refer to equation
(59)) [32] and no-slip condition at the bottom of the melt layer (refer to equation (60)). As
mentioned earlier, the reference coordinate system of the thin-film model is on the melt-layer-solid
interface. Hence, the boundary conditions of 𝑢𝑥 (𝑦𝑙 ) are based on this coordinate system.
𝜏𝑥𝑦 𝜕𝑢𝑥
= | (59)
𝜇𝑙 𝜕𝑦𝑙 𝑦 =𝛿
𝑙

𝑢𝑥 |𝑦𝑙=0 = 0 (60)
where 𝜇𝑙 is defined as the dynamic viscosity of the melt layer.
At 𝑦𝑙 = 0, substitution of equation (60) into equation (58) gives:
𝑢𝑥 (0) = 0 = 𝑎(0)2 + 𝑏(0) + 𝑐 → 𝑐 = 0 (61)
At 𝑦𝑙 = 𝛿, substitution of equation (59) into the first derivative of equation (58) gives:
𝜕𝑢𝑥 𝜏𝑥𝑦 𝜏𝑥𝑦
| = = 2𝑎(𝛿) + 𝑏 → = 2𝑎𝛿 + 𝑏 (62)
𝜕𝑦𝑙 𝑦 =𝛿 𝜇𝑙 𝜇𝑙
𝑙

By substituting equation (61) and (58) into equation (57) and then perform direct integration, it
follows that:
𝑎𝛿 2 𝑏𝛿
̅=
𝑈 + (63)
3 2

By rearranging equation (63) in terms of 𝑏 and substitute into equation (62), it follows that:
𝜏𝑥𝑦 2𝑈̅ 4𝑎𝛿 (64)
= +
𝜇𝑙 𝛿 3

41
By rearranging equation (64) in terms of 𝑎, it follows that:
3 𝜏𝑥𝑦 2𝑈̅
𝑎= ( − ) (65)
4𝛿 𝜇𝑙 𝛿
By substituting equation (65) into equation (62) and rearrange the resultant equation in terms of 𝑏,
it follows that:
3𝑈̅ 𝜏𝑥𝑦
𝑏= − (66)
𝛿 2𝜇𝑙
By substituting equation (65) and (66) into equation (58), the complete equation of 𝑢𝑥 (𝑦𝑙 ) is:
3 𝜏𝑥𝑦 2𝑈̅ 3𝑈̅ 𝜏𝑥𝑦
𝑢𝑥 (𝑦𝑙 ) = ( − ) 𝑦𝑙2 + ( − )𝑦 (67)
4𝛿 𝜇𝑙 𝛿 𝛿 2𝜇𝑙 𝑙

3.4.2 Momentum Equation of the Thin-Film Model


Using the same simplifying assumptions as Section 3.4.1, the momentum equation of the thin-film
model (refer to [28]) simplifies to:
𝜕(𝛿𝑈̅) 𝜕(𝑈
̅ 2 𝛿) 𝛿 𝜕𝑝𝑔 𝑆𝛿𝑈̅
+ =− + (68)
𝜕𝑡 𝜕𝑥 𝜌𝑙 𝜕𝑥 𝜌𝑙
where 𝑝𝑔 and 𝑆𝛿𝑈̅ are defined as the gas-phase pressure adjacent to the gas-melt-layer interface
and momentum source term, respectively. To account for the wall-tangential shear stresses at the
gas-melt-layer and melt-layer-solid interfaces, the 𝑆𝛿𝑈̅ term becomes:
𝑆𝛿𝑈̅ = 𝜏𝑥𝑦 − 𝜏𝑤,𝑚 (69)
where 𝜏𝑤,𝑚 is defined as the wall-tangential shear stress at the melt-layer-solid interface (or 𝑦𝑙 =
0).
The equation of 𝜏𝑤,𝑚 is derived by differentiating 𝑢(𝑦𝑙 ) (refer to equation (67)) and is:
3𝑈̅ 𝜏𝑥𝑦
𝜏𝑤,𝑚 = 𝜇𝑙 − (70)
𝛿 2

The value of 𝜏𝑥𝑦 is calculated using the gas-phase properties adjacent to the gas-melt-layer
interface.

42
3.4.3 Energy Equation of the Thin-Film Model
Using the same simplifying assumptions as Section 3.4.1, the energy equation of the thin-film
model (refer to [28]) simplifies to:
̅𝛿ℎ) 𝑆𝛿ℎ
𝜕(𝛿ℎ) 𝜕(𝑈
+ = (71)
𝜕𝑡 𝜕𝑥 𝜌𝑙
where ℎ and 𝑆𝛿ℎ are defined as the mean enthalpy at the mean film temperature (𝑇𝑓 ) and energy
source term, respectively. Solving equation (71) for ℎ and then evaluate for 𝑇𝑓 will contradict the
linear melt layer temperature profile assumption made earlier because the temperature profile will
become bilinear (refer to Figure 4).

Figure 4: Bilinear temperature profile in the melt layer [33].

Besides that, there will be entrainment heat transfer at the gas-melt-layer interface (𝑞̇ 𝑒𝑛𝑡 ) and
conductive heat transfer in the solid at the melt-layer-solid interface (𝑞̇ 𝑐𝑜𝑛𝑑,𝑠 ). To account for the
bilinear temperature profile in the melt layer and the entrainment and solid conductive heat
transfers at both interfaces, the liquefying combustion modelling approach by Weinstein and Gany
requires modifications. After modifications, the updated heat flux balance equation at the melt-
layer-solid interface is:
𝑞̇ 𝑚 + 𝑞̇ 𝑐𝑜𝑛𝑑,𝑠 = 𝑞̇ 𝑐𝑜𝑛𝑑,𝑙 (72)
Equation (72) is then expanded into this form:
𝜕𝑇 (𝑇𝑓 − 𝑇𝑚 )
𝜌𝑠 𝑟̇𝑚 [𝐻𝑚 + 𝐶𝑝,𝑠 (𝑇𝑚 − 𝑇𝑎 )] + 𝑘𝑠 | = 𝑘𝑙 (73)
𝜕𝑦𝑠 𝑦 =0− 𝛿 ⁄2
𝑙

where 𝑘𝑠 , 𝑦𝑠 and 𝜕𝑇⁄𝜕𝑦𝑠 |𝑦𝑙=0− are defined as thermal conductivity of the solid, wall-normal
coordinate in the coordinate system of the solid fuel and the wall-normal temperature gradient in

43
the solid just beneath the gas-melt-layer interface, respectively. Rearranging equation (73) in terms
of 𝑟̇𝑚 gives:
1 (𝑇𝑓 − 𝑇𝑚 ) 𝜕𝑇
𝑟̇𝑚 = ∙ [𝑘𝑙 − 𝑘𝑠 | ]
𝜌𝑠 [𝐻𝑚 + 𝐶𝑝,𝑠 (𝑇𝑚 − 𝑇𝑎 )] 𝛿 ⁄2 𝜕𝑦𝑠 𝑦 =0 (74)
𝑙

On the other hand, the updated heat flux balance equation at the gas-melt-layer interface is:
(𝑇𝑣 − 𝑇𝑓 )
𝑞̇ 𝑐𝑜𝑛𝑣 − 𝑞̇ 𝑣 = 𝑘𝑙 (75)
𝛿 ⁄2
In equation (75), the heat transfer contribution due to entrainment is absent because only the
evaporative mass transfer contributes to the heat flux balance equation at this interface [7]. By
substituting equation (47) and (48) into equation (75) and then rearrange the resultant equation in
terms of 𝑟̇𝑣 , it follows that:
1 (𝑇𝑦=0+ − 𝑇𝑣 ) (𝑇𝑣 − 𝑇𝑓 )
𝑟̇𝑣 = ∙ [𝑘𝑔 |𝑦=0+ − 𝑘𝑙 ] (76)
𝜌𝑙 [𝐻𝑣 + 𝐶𝑝,𝑙 (𝑇𝑣 − 𝑇𝑚 )] ∆𝑦 𝛿 ⁄2

Equation (74) and (76) are used to calculate the 𝑟̇𝑚 and 𝑟̇𝑣 terms in equation (56), respectively.
To determine the equation of 𝑆𝛿ℎ , control volume analysis is performed to analyse the heat and
mass transfer processes in the melt layer.

Figure 5: Control volume of the melt layer.

From the control volume analysis of melt layer in Figure 5, the melt layer gains energy by the
convective heat transfer from the gas-phase flow at the gas-melt-layer interface and melting heat
transfer from the melt-layer-solid interface. Besides that, the melt layer loss energy by heat
conduction into the solid at the melt-layer-solid interface, and by entrainment and vaporisation at
the gas-melt-layer interface. The net effect of these heat transfers is described by 𝑆𝛿ℎ :
𝑆𝛿ℎ = 𝑞̇ 𝑐𝑜𝑛𝑣 − 𝑞̇ 𝑣 + 𝑞̇ 𝑚 − 𝑞̇ 𝑐𝑜𝑛𝑑,𝑙 − 𝑞̇ 𝑒𝑛𝑡 (77)

44
By considering the heat flux balance equation at the gas-melt-layer interface (refer to equation
(75)) and at the melt-layer-solid interface (refer to equation (73)), equation (77) is expanded into
the following form:
(𝑇𝑣 − 𝑇𝑓 ) 𝜕𝑇
𝑆𝛿ℎ = 𝑘𝑙 − 𝑘𝑠 | − 𝜌𝑙 𝑟̇𝑒𝑛𝑡 ℎ𝑒 (78)
𝛿 ⁄2 𝜕𝑦𝑠 𝑦 =0−
𝑙

where ℎ𝑒 is defined as the total heat of entrainment.

3.4.4 Boundary Value Problem Formulation


The conservation equations of the thin-film model from the preceding sections can be represented
in the following form:
̅𝜙) 𝑆
𝜕𝜙 𝜕(𝑈
+ = (79)
𝜕𝑡 𝜕𝑥 𝜌𝑙
where 𝜙 and 𝑆 are defined as the general transport variable and source term, respectively. The
equation of 𝜙 and 𝑆 are:
𝜙 = [𝛿 ̅
𝛿𝑈 𝛿ℎ]𝑇 (80)
𝑆 = [𝑆𝛿 𝑆𝛿𝑈̅ 𝑆𝛿ℎ ]𝑇 (81)
̅ and ℎ. To solve equation (79) for 𝜙
The primitive variables that characterise the thin-film are 𝛿, 𝑈
and then determine the value of each primitive variable at each instant, a boundary value problem
(BVP) must be established. The BVP for equation (79) requires one boundary condition and one
initial condition for each primitive variable. The decision on the boundary conditions will depend
on the type of flow to be modelled.

45
Chapter 4

Implementation Methodology

This chapter will provide the methodologies to apply the background theories from Chapter 3 to
implement the computational fluid dynamics (CFD) sub-models of all the physical processes
outlined in Section 1.1.

4.1 Implementation Considerations in Eilmer 4


Within the framework of user-defined function (UDF) in Eilmer 4, the CFD sub-model of each
physical process considered is implementable as a user-defined boundary condition or source term.
Full details of the UDF functionality of Eilmer 4 is in [29]. To implement a user-defined boundary
condition in Eilmer 4, there are two approaches [29]:
1. Specifying the ghost-cell and interface properties.
2. Specifying the combined convective and viscous interface fluxes directly.
Approach 2 is chosen for this work because it allows the direct specification of fluxes at a domain
boundary. As a result, this will make the implementation simpler as it provides a possibility to
retain the original mathematical form of the fluxes, thus excluding the necessity to use ghost cells
and discretise the fluxes numerically. Under this approach, the combined convective and viscous
interface fluxes at a boundary are in terms of mass, momentum, energy and species. On the other
hand, a user-defined source term defines the rate of addition of a quantity in terms of per unit
volume. It applies to any conservation equation by being added to the internally computed source
terms. [29].

Besides that, the CFD sub-model of each physical process has its group. If a physical process is a
boundary phenomenon, then the CFD sub-model belongs to the user-defined boundary condition
group. If a physical process is a flow field phenomenon, then the CFD sub-model belongs to the
46
user-defined source term group. Knowing the UDF group classification of a CFD sub-model allows
the establishment of implementation contexts. Table 9 summarises the UDF group classifications
of the CFD sub-models according to the nature of the physical processes they represent.
Table 9: User-defined function (UDF) group classifications of the CFD sub-models.
Topic (CFD sub-model) UDF group
Fuel pyrolysis modelling User-defined boundary condition
User-defined boundary condition
Fluid-solid coupled heat transfer modelling

User-defined boundary condition


Melt layer modelling

Combustion modelling User-defined source term


Thermal radiation modelling in the flow field User-defined source term

Furthermore, parallel processing with high-performance computing (HPC) resources is a desirable


approach to accelerate the simulation speed. The mesh structure of a fluid domain can consist of
multiple main blocks. If one face of the main block has a boundary condition, then the block-
division along that face will divide that boundary condition into coplanar segments that are each
local to a sub-block. In parallel simulations, all sub-blocks along that boundary condition are being
run independently by a copy of Eilmer 4 on separate processors [30]. The communications between
sub-blocks are handled by the standard message passing library (MPI) [30]. In MPI, if the sub-
segments of that boundary condition are unable to exchange information at the block-boundaries
that divided them, it can lead to simulation errors. For this reason, the algorithm to implement a
CFD sub-model as a user-defined boundary condition must also be compatible with parallel
processing.

Inline to the implementation considerations mentioned earlier, the subsequent sections of this
chapter will explain the mathematical formulations and algorithmic implementations of the CFD
sub-models within the framework of their UDF group classification and parallel processing with
high-performance computing (HPC).

47
4.2 Fuel Pyrolysis Boundary Condition
This section entails the formulation and implementation of the fuel pyrolysis boundary condition.

4.2.1 Governing Equations of the Fuel Pyrolysis Boundary Condition


As per the aims and objectives from Section 1.1, the internal combustion ballistics modelling will
be based on a two-dimensional slab hybrid rocket motor (HRM). For this reason, the dimensionality
of the conservation equations of Eilmer 4 in the cartesian coordinate system (𝑥, 𝑦, 𝑧) is reduced
from three-dimensional to two-dimensional by omitting the 𝑧-component of the conservation
equations. The origin of the two-dimensional cartesian coordinate system is then fixed at the
leading edge and surface level of the fuel slab, with the fuel being the Hydroxyl-Terminated
Polybutadiene (HTPB). Full details of the three-dimensional conservation equations of Eilmer 4
are in [30].
According to Section 4.1, the fuel pyrolysis boundary condition will be implemented as a flux
boundary condition by directly specifying the fluxes at the domain boundary. The net flux (𝐹̅𝑛𝑒𝑡 )
of this boundary condition is defined as [30]:
𝐹̅𝑛𝑒𝑡 = 𝐹̅𝑖 − 𝐹̅𝑣 (82)
where 𝐹̅𝑖 and 𝐹̅𝑣 are defined as the inviscid and viscous flux vectors, respectively. The complete
mathematical descriptions of 𝐹̅𝑖 and 𝐹̅𝑣 are in [30].
As the surface of the fuel slab is planar and assuming that the fuel injection during the pyrolysis
process is dominant in the wall-normal direction, only the 𝑗̂ unit-vector components of 𝐹̅𝑖 and 𝐹̅𝑣
are relevant to model the fluxes at the boundary. Hence, the equation of 𝐹̅𝑛𝑒𝑡 in the two-dimensional
cartesian coordinate system (𝑥, 𝑦) and at the fuel surface (corresponds to 𝑦 = 0) becomes:
𝐹𝑚𝑎𝑠𝑠 𝜌𝑢𝑦
𝐹𝑥−𝑚𝑜𝑚 𝜌𝑢 𝑥 𝑦 − 𝜏𝑥𝑦
𝑢
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝜌𝑢𝑦2 + 𝑝 − 𝜏𝑦𝑦
(83)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝜌𝐸𝑢𝑦 + 𝑝𝑢𝑦 − (𝜏𝑥𝑦 𝑢𝑥 + 𝜏𝑦𝑦 𝑢𝑦 + 𝑞𝑦 )
[𝐹𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝜌𝑓𝑠 𝑢𝑦 − 𝐽𝑦,𝑠 ]𝑥=𝑥 ,𝑦=0
𝑖

where 𝜌, 𝑢𝑥 , 𝑢𝑦 , 𝑝, 𝜏, 𝐸, 𝑞𝑦 , 𝑓𝑠 and 𝐽𝑦,𝑠 are defined as the fluid density, fluid velocity component
in the 𝑥-direction, fluid velocity component in the 𝑦-direction, static pressure, viscous shear stress,
total energy per unit mass, wall-normal viscous heat flux, species mass fraction and species
diffusion flux, respectively. Equation (83) applies to any 𝑥-coordinate (𝑥𝑖 ) along the fuel surface,

48
spanning from the leading edge (corresponds to 𝑥 = 0) to the trailing edge of the solid fuel grain
(corresponds 𝑥 = 𝐿𝑓 ; where 𝐿𝑓 = length of the fuel grain).

4.2.2 Boundary Treatment of the Fuel Pyrolysis Boundary Condition


The objective of the boundary treatment is to model the fuel pyrolysis boundary condition as a
porous and viscous wall, which injects HTPB fuel under the influence of the regression rate law.
Inline to this objective, this section will explain the boundary treatment techniques of the governing
equations of the fuel pyrolysis boundary condition (refer to equation (83)).
First, the fuel surface is subject to the no-slip condition due to the viscous effect. As a result, the
following velocity condition arises:
𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0 = 0 (84)
As the fuel surface is injecting vaporised fuel into the combustion chamber in the wall-normal
direction, the fuel surface is also subject to another velocity condition:
𝑢𝑦 |𝑥=𝑥 ,𝑦=0 = 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 (85)
𝑖 𝑖

where 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 is defined as the wall-normal fuel injection velocity at the fuel surface. The
𝑖

value of 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 can be calculated by the mass continuity condition. This condition is applied
𝑖

across the sublimation process of the fuel grain from the solid to the gas state, which takes place at
the fuel surface. By the mass continuity condition, the equation of 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 is:
𝑖

𝑚̇𝑝𝑦𝑟 |𝑥=𝑥 ,𝑦=0


𝑖
𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 = (86)
𝑖 𝜌𝑓𝑔 |𝑥=𝑥 ,𝑦=0
𝑖

where 𝑚̇𝑝𝑦𝑟 |𝑥=𝑥 ,𝑦=0 and 𝜌𝑓𝑔 |𝑥=𝑥 ,𝑦=0 are defined as the pyrolysis mass flux and density of the
𝑖 𝑖

vaporised fuel at the fuel surface, respectively. According to Section 3.2.3, the equation of
𝑚̇𝑝𝑦𝑟 |𝑥=𝑥 ,𝑦=0 is:
𝑖

𝑚̇𝑝𝑦𝑟 |𝑥=𝑥 ,𝑦=0 = (𝜌𝑓 𝑟̇𝐴𝑟𝑟 )|𝑥=𝑥 ,𝑦=0 (87)


𝑖 𝑖

where 𝜌𝑓 |𝑥=𝑥 ,𝑦=0 and 𝑟̇𝐴𝑟𝑟 |𝑥=𝑥𝑖 ,𝑦=0 are defined as the density of the solid fuel grain and Arrhenius-
𝑖

type regression rate at the fuel surface, respectively. The equation of 𝑟̇𝐴𝑟𝑟 |𝑥=𝑥𝑖 ,𝑦=0 is:
𝐸𝑎
𝑟̇𝐴𝑟𝑟 |𝑥=𝑥𝑖 ,𝑦=0 = 𝐴𝑒𝑥𝑝 (− ) (88)
𝑅𝑢 𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0

49
where 𝐴, 𝐸𝑎 , 𝑅𝑢 and 𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0 are defined as the pre-exponential factor, activation energy of the
fuel pyrolysis process, universal gas constant and fuel surface temperature, respectively. To
calculate 𝑟̇𝐴𝑟𝑟 |𝑥=𝑥𝑖 ,𝑦=0 , the distribution of 𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0 is initialised at the start of simulation as:
𝑇𝑠0 |𝑥=𝑥𝑖 ,𝑦=0 , 𝑡 ≥ 0 (𝐶𝑜𝑛𝑠𝑡𝑎𝑛𝑡 𝑡𝑒𝑚𝑝𝑒𝑟𝑎𝑡𝑢𝑟𝑒)
𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0 = { (89)
𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 , 𝑡 ≥ 0 (𝐹𝑙𝑢𝑖𝑑 − 𝑠𝑜𝑙𝑖𝑑 𝑐𝑜𝑢𝑝𝑙𝑒𝑑 ℎ𝑒𝑎𝑡 𝑡𝑟𝑎𝑛𝑠𝑓𝑒𝑟)
where 𝑡 is defined as a simulation time. Besides that, the wall-normal pressure gradient boundary
condition at the fuel surface is defined as:
𝜕𝑝
| =0 (90)
𝜕𝑦 𝑥=𝑥 ,𝑦=0
𝑖

This pressure gradient boundary condition was used by Gariani et al. to model the surface pressure
condition of the fuel slab in their slab HRM study [1]. To provide an integrative framework for
equation (90), a one-sided finite difference scheme is used to approximate 𝜕𝑝⁄𝜕𝑦|𝑥=𝑥𝑖 ,𝑦=0 . Thus,
this numerical approximation corresponds to:
𝜕𝑝 𝑝𝑥=𝑥𝑖 ,𝑦=0+ − 𝑝𝑥=𝑥𝑖 ,𝑦=0
| = = 0 → 𝑝𝑥=𝑥𝑖 ,𝑦=0+ = 𝑝𝑥=𝑥𝑖 ,𝑦=0
𝜕𝑦 𝑥=𝑥 ,𝑦=0 ∆𝑦 (91)
𝑖

where 𝑝𝑥=𝑥𝑖 ,𝑦=0+ , 𝑝𝑥=𝑥𝑖 ,𝑦=0 and ∆𝑦 are defined as the fluid static pressure at the centre of the fluid-
cell adjacent to the fuel surface, fluid static pressure at the fuel surface and first-cell height,
respectively. Furthermore, the species mass fraction (𝑓𝑠 |𝑥=𝑥𝑖 ,𝑦=0 ) condition at the fuel surface is
defined as:
1, 𝑠 = 𝑓𝑢𝑒𝑙
𝑓𝑠 |𝑥=𝑥𝑖 ,𝑦=0 = { (92)
0, 𝑠 ≠ 𝑓𝑢𝑒𝑙
This condition reflects that the fuel surface is purely the fuel species.
Lastly, as the objective of the boundary treatment is to treat the pyrolysing fuel surface as a porous
and viscous wall, the pyrolysing fuel surface is equivalent to a continuous array of mechanical fuel
injectors. Within this modelling framework, the fuel injection process at each fuel injector behaves
like the mechanical equivalent of the Arrhenius-type regression rate law, rather than the permeation
of species due to thermochemical diffusion. For this reason, the 𝐽𝑦,𝑠 term in equation (83) is omitted
for this work.

50
4.2.3 Formulation of the Fuel Pyrolysis Boundary Condition
In this section, the fuel pyrolysis boundary condition will be formulated by applying the boundary
treatment techniques from Section 4.2.2 on its governing equations (refer to equation (83)).
By substituting the pyrolysis mass flux (𝑚̇𝑝𝑦𝑟 |𝑥=𝑥 ,𝑦=0 ) equation (refer to equation (87)) into all
𝑖

terms of equation (83), it follows that:


𝐹𝑚𝑎𝑠𝑠 𝑚̇𝑝𝑦𝑟
𝐹𝑥−𝑚𝑜𝑚 𝑚̇𝑝𝑦𝑟 𝑢𝑥 − 𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝑚̇𝑝𝑦𝑟 𝑢𝑦 + 𝑝 − 𝜏𝑦𝑦 (93)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝑚̇𝑝𝑦𝑟 𝐸 + 𝑝𝑢𝑦 − (𝜏𝑥𝑦 𝑢𝑥 + 𝜏𝑦𝑦 𝑢𝑦 + 𝑞𝑦 )
𝐹
[ 𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝑚̇𝑝𝑦𝑟 𝑓𝑠 − 𝐽𝑦,𝑠 ]𝑥=𝑥 ,𝑦=0
𝑖

By applying the no-slip condition (refer to equation (84)) to the relevant terms of equation (93), it
follows that:
𝐹𝑚𝑎𝑠𝑠 𝑚̇𝑝𝑦𝑟
𝐹𝑥−𝑚𝑜𝑚 −𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝑚̇𝑝𝑦𝑟 𝑢𝑦 + 𝑝 − 𝜏𝑦𝑦 (94)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝑚̇𝑝𝑦𝑟 𝐸 + 𝑝𝑢𝑦 − (𝜏𝑦𝑦 𝑢𝑦 + 𝑞𝑦 )
[𝐹𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝑚̇𝑝𝑦𝑟 𝑓𝑠 − 𝐽𝑦,𝑠 ] 𝑥=𝑥𝑖 ,𝑦=0

By applying the fuel injection velocity (𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 ) condition (refer to equation (85)) and the
𝑖

zero wall-normal pressure gradient condition (refer to equation (91)) to the relevant terms of
equation (94), it follows that:
𝐹𝑚𝑎𝑠𝑠 𝑚̇𝑝𝑦𝑟
𝐹𝑥−𝑚𝑜𝑚 −𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝑚̇𝑝𝑦𝑟 𝑣𝑖𝑛𝑗 + 𝑝|𝑦=0+ − 𝜏𝑦𝑦 (95)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝑚̇𝑝𝑦𝑟 𝐸 + 𝑝|𝑦=0+ 𝑣𝑖𝑛𝑗 − (𝜏𝑦𝑦 𝑣𝑖𝑛𝑗 + 𝑞𝑦 )
𝐹
[ 𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝑚̇𝑝𝑦𝑟 𝑓𝑠 − 𝐽𝑦,𝑠 ]𝑥=𝑥 ,𝑦=0
𝑖

where the 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 term is defined by equation (86). As per the concluding remarks of the
𝑖

species diffusion flux (𝐽𝑦,𝑠 ) term in equation (95) from Section 4.2.2, the 𝐽𝑦,𝑠 term is omitted. As a
result, the governing equations of the fuel pyrolysis boundary condition becomes:
𝐹𝑚𝑎𝑠𝑠 𝑚̇𝑝𝑦𝑟
𝐹𝑥−𝑚𝑜𝑚 −𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝑚̇𝑝𝑦𝑟 𝑣𝑖𝑛𝑗 + 𝑝|𝑦=0+ − 𝜏𝑦𝑦 (96)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝑚̇𝑝𝑦𝑟 𝐸 + 𝑝|𝑦=0+ 𝑣𝑖𝑛𝑗 − (𝜏𝑦𝑦 𝑣𝑖𝑛𝑗 + 𝑞𝑦 )
[𝐹𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝑚̇𝑝𝑦𝑟 𝑓𝑠 ]𝑥=𝑥𝑖 ,𝑦=0

51
The remaining terms in equation (96) that require modelling are the wall viscous shear stresses
(𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 and 𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 ), wall-normal viscous heat flux (𝑞𝑦 |𝑥=𝑥 ,𝑦=0 ) and the total energy
𝑖 𝑖 𝑖

per unit mass (𝐸|𝑥=𝑥𝑖 ,𝑦=0 ) at the fuel surface.

Viscous Shear Stresses Formulation


According to Jacobs et al., the equations of the wall viscous shear stresses (𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 and
𝑖

𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 ) are [30]:


𝑖

𝜕𝑢𝑥 𝜕𝑢𝑦
𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ( | + | ) (97)
𝑖 𝜕𝑦 𝑥=𝑥 ,𝑦=0 𝜕𝑥 𝑥=𝑥𝑖 ,𝑦=0
𝑖

𝜕𝑢𝑦 2 𝜕𝑢𝑥 𝜕𝑢𝑦


𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ [2 | − ( | + | )] (98)
𝑖 𝜕𝑦 𝑥=𝑥 ,𝑦=0 3 𝜕𝑥 𝑥=𝑥𝑖 ,𝑦=0 𝜕𝑦 𝑥=𝑥 ,𝑦=0
𝑖 𝑖

where 𝜇𝑥=𝑥𝑖 ,𝑦=0+ is defined as the dynamic viscosity of the fluid at the centre of the fluid-cell
adjacent to the fuel surface. It considers the dynamic viscosity contribution of each species within
the multi-component mixture flow near the fuel surface.

To provide an integrative framework for the 𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 and 𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 terms in the context of
𝑖 𝑖

a two-dimensional finite-volume grid, the spatial derivatives of velocity inherent to these terms are
approximated by using the one-sided finite difference scheme. With this numerical approximation,
the equations of 𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 and 𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 becomes:
𝑖 𝑖

(𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0 )


1 ∆𝑦
𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ (99)
𝑖 1 (𝑢𝑦 | − 𝑢𝑦 |𝑥=𝑥 ,𝑦=0 )
𝑥=𝑥 𝑖+1 ,𝑦=0 𝑖
[ 𝑥𝑖+1 − 𝑥𝑖 ]

4 (𝑢𝑦 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑢𝑦 |𝑥=𝑥𝑖 ,𝑦=0 )


1
𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ 3 ∆𝑦 (100)
𝑖 −1 2 (𝑢 |
𝑥 𝑥=𝑥𝑖+1 ,𝑦=0 − 𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0 )
[3 𝑥𝑖+1 − 𝑥𝑖 ]

52
By applying the no-slip condition (refer to equation (84)) to the relevant terms of equation (99) and
(100), it follows that:
𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0+
1 ∆𝑦
𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ (101)
𝑖 1 (𝑢𝑦 |𝑥=𝑥 − 𝑢𝑦 |𝑥=𝑥 ,𝑦=0 )
𝑖+1 ,𝑦=0 𝑖
+
[ 𝑥𝑖+1 − 𝑥𝑖 ]

4 (𝑢𝑦 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑢𝑦 |𝑥=𝑥𝑖 ,𝑦=0 )


1
𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ 3 ∆𝑦 (102)
𝑖 −1 2 𝑢𝑥 |𝑥=𝑥𝑖+1 ,𝑦=0
[ 3 𝑥𝑖+1 − 𝑥𝑖 ]

By applying the fuel injection velocity condition (refer to equation (85)) to the relevant terms of
equation (101) and (102), it follows that:
𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0+
1 ∆𝑦
𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ (103)
𝑖 1 (𝑣𝑖𝑛𝑗 | − 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 )
𝑥=𝑥 𝑖+1 ,𝑦=0 𝑖
[ 𝑥𝑖+1 − 𝑥𝑖 ]

4 (𝑢𝑦 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑣𝑖𝑛𝑗 |𝑥=𝑥𝑖 ,𝑦=0 )


1
𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥𝑖 ,𝑦=0+ ∙ [ ] ∙ 3 ∆𝑦 (104)
𝑖 −1 2 𝑢𝑥 |𝑥=𝑥𝑖+1,𝑦=0
[ 3 𝑥𝑖+1 − 𝑥𝑖 ]
where 𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0+ and 𝑢𝑦 |𝑥=𝑥 ,𝑦=0+ are defined as the fluid velocity components in the 𝑥 and 𝑦
𝑖

directions at the centre of the fluid-cell adjacent to the fuel surface, respectively.
At the trailing edge of the solid fuel grain, equation (103) and (104) will try to access the
information of the adjacent fluid-cell on the right-hand side of the current fluid-cell due to the
𝑣𝑖𝑛𝑗 |𝑥=𝑥 and 𝑢𝑥 |𝑥=𝑥𝑖+1 ,𝑦=0 terms. This condition is illustrated in Figure 6.
𝑖+1 ,𝑦=0

53
Figure 6: Grid at the trailing edge of the solid fuel grain.

To account for this condition in the formulation of the pyrolysis boundary condition, the
𝑣𝑖𝑛𝑗 |𝑥=𝑥 and 𝑢𝑥 |𝑥=𝑥𝑖+1 ,𝑦=0 terms are adjusted for the slip, no-slip and no penetration
𝑖+1 ,𝑦=0

conditions at the downstream of the trailing edge.

𝑚̇𝑝𝑦𝑟 |𝑥=𝑥
𝑖+1 ,𝑦=0 (105)
, 𝑓𝑜𝑟 𝑥𝑖+1 ≤ 𝐿𝑓
𝑣𝑖𝑛𝑗 |𝑥=𝑥 = 𝜌𝑓𝑔 |𝑥=𝑥
𝑖+1 ,𝑦=0 𝑖+1 ,𝑦=0
{ 0, 𝑓𝑜𝑟 𝑥𝑖+1 > 𝐿𝑓 (𝑁𝑜 𝑝𝑒𝑛𝑒𝑡𝑟𝑎𝑡𝑖𝑜𝑛)

0, 𝑓𝑜𝑟 𝑥𝑖+1 ≤ 𝐿𝑓 (𝑁𝑜 𝑠𝑙𝑖𝑝)


(106)
𝑢𝑥 |𝑥=𝑥𝑖+1 ,𝑦=0 = {𝑢𝑥 |𝑥=𝑥𝑖+1 ,𝑦=0+ , 𝑓𝑜𝑟 𝑥𝑖+1 > 𝐿𝑓 (𝑆𝑙𝑖𝑝)
0, 𝑓𝑜𝑟 𝑥𝑖+1 > 𝐿𝑓 (𝑁𝑜 𝑠𝑙𝑖𝑝)
According to Section 3.2.1, near-wall modelling approach is required to determine the magnitude
of ∆𝑦. There are two-types of near-wall modelling approach: Low-Reynolds number and wall
function modelling approaches.
To ensure the one-sided finite difference approximations of the spatial derivatives of velocity has
negligible truncation errors, the magnitude of ∆𝑦 must be sufficiently small. For this reason, the
Low-Reynolds number near-wall modelling approach is the most relevant. Under this approach,
∆𝑦 should correspond to a non-dimensional wall distance (𝑦 + ) of less than one. The advantage of
this approach is not only because it leads to a much smaller ∆𝑦 value than that of the wall function
near-wall modelling approach, but the 𝑦 + range that corresponds to this approach is also sufficient
to resolve the viscous sublayer of the near-wall boundary layer [31] and makes it compatible with
the 𝑘 − 𝜔 turbulence model of Eilmer 4 [29]. This class of turbulence model is valid up to the near-
wall region without using wall functions [32].
54
In the viscous sublayer, the unsteady velocity fluctuations have little influences on the total wall
shear stress because of the significant effects of viscosity. Due to the negligible velocity
fluctuations, the velocity profile in this sublayer will become linear. [33]. As a result, the one-sided
finite difference approximations of the spatial derivatives of velocity will become constant because
they resemble the gradient of the linear velocity profile.

Viscous Heat Flux Formulation


Due to the fluid motion near the fuel surface, the wall-normal viscous heat flux (𝑞𝑦 |𝑥=𝑥 ,𝑦=0 ) is
𝑖

equivalent to the convective heat flux at the fuel surface (𝑞̇ 𝑐𝑜𝑛𝑣 |𝑥=𝑥𝑖 ,𝑦=0 ). Repeat for convenience
from Section 3.2.1, the 𝑞̇ 𝑐𝑜𝑛𝑣 |𝑥=𝑥𝑖 ,𝑦=0 term is defined as:
(𝑇|𝑥=𝑥𝑖 ,𝑦=0+ − 𝑇|𝑥=𝑥𝑖 ,𝑦=0 )
𝑞𝑦 |𝑥=𝑥 ,𝑦=0 ≡ 𝑞̇ 𝑐𝑜𝑛𝑣 |𝑥=𝑥𝑖 ,𝑦=0 = 𝑘𝑔 |𝑥=𝑥 ,𝑦=0+
𝑖 𝑖 ∆𝑦 (107)

By applying the temperature condition at the fuel surface (refer to equation (89)) to the 𝑇|𝑥=𝑥𝑖 ,𝑦=0
term in equation (107), it follows that:
(𝑇|𝑥=𝑥𝑖 ,𝑦=0+ − 𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0 )
𝑞𝑦 |𝑥=𝑥 ,𝑦=0 ≡ 𝑞̇ 𝑐𝑜𝑛𝑣 |𝑥=𝑥𝑖 ,𝑦=0 = 𝑘𝑔 |𝑥=𝑥 ,𝑦=0+
𝑖 𝑖 ∆𝑦 (108)

where 𝑘𝑔 |𝑥=𝑥 ,𝑦=0+ , 𝑇|𝑥=𝑥𝑖 ,𝑦=0+ and 𝑇𝑠 |𝑥=𝑥𝑖 ,𝑦=0 are defined as the conductivity of the multi-
𝑖

component fluid mixture and fluid temperature at the centre of the fluid-cell adjacent to the fuel
surface, and the fuel surface temperature, respectively. Again, the magnitude of ∆𝑦 is determined
using the Low-Reynolds number near-wall modelling approach as described in Section 4.2.3.1.

Total Energy Per Unit Mass Formulation


According to Jacobs et al., the equation of the total energy per unit mass (𝐸|𝑥=𝑥𝑖 ,𝑦=0 ) is [30]:
1 2
𝐸|𝑥=𝑥𝑖 ,𝑦=0 = 𝑒𝑓𝑔 |𝑥=𝑥 ,𝑦=0 + 𝑣𝑖𝑛𝑗 | (109)
𝑖 2 𝑥=𝑥𝑖 ,𝑦=0

where 𝑒𝑓𝑔 |𝑥=𝑥 ,𝑦=0 is defined as the internal energy per unit mass of the vaporised fuel at the fuel
𝑖

surface. In addition, the 𝑣𝑖𝑛𝑗 |𝑥=𝑥 ,𝑦=0 term is defined by equation (86).
𝑖

55
4.2.4 General Implementation of the Fuel Pyrolysis Boundary Condition
The general implementation of the fuel pyrolysis boundary condition aims to establish the base
algorithm of this boundary condition and does not consider parallel processing. There are two
considerations to implement this boundary condition: data storage for the fuel surface temperature
(𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 ) distribution and the vaporised fuel state calculations.

To store the 𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 distribution, the userPad array (refer to userPad in [29]) is used. The
size of this array is set equal to the total number of fluid-cells along the fuel pyrolysis boundary
condition. The element indexing of this array is synchronised with the index position of the adjacent
fluid cells by subtracting the 𝑖-index of the fluid cells by one. This subtraction is to account for the
fact that the 𝑖-index of the main block starts from two because of the two-cell deep buffer region
[30], whereas the index of the userPad array starts from one because it is a Lua table. This array
stores the 𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 distribution in the global namespace, thus providing a possibility to update
the 𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 distribution in the user-defined supervisor script (refer to config.udf_super-
visor_file in [29]) by invoking the fluid-solid coupled heat transfer mechanism (refer to Section
4.3).

On the other hand, the vaporised fuel state properties that must be calculated are the vaporised fuel
density (𝜌𝑓𝑔 |𝑥=𝑥 ,𝑦=0 ) and internal energy per unit mass (𝑒𝑓𝑔 |𝑥=𝑥 ,𝑦=0 ). To calculate these fluid
𝑖 𝑖

properties, a function that is based on the gas model package of Eilmer 4 [34] is implemented. This
function is FuelState. Due to the imposition of the zero wall-normal pressure gradient condition
(refer to equation (91)), wall temperature condition (refer to equation (89)) and species mass
fraction condition (refer to equation (92)) at the fuel surface, the static pressure, temperature and
mass fraction of the fuel species at the fuel surface are known values at each instant. These fluid
properties define the surface fuel state at each instant, thus providing a precondition to solve for
𝜌𝑓𝑔 |𝑥=𝑥 ,𝑦=0 and 𝑒𝑓𝑔 |𝑥=𝑥 ,𝑦=0 by invoking the following GasModel methods: updateThermoFro-
𝑖 𝑖

mPT and updateTransCoeffs methods [34].

As the selected implementation approach involves the direct specification of fluxes at the domain
boundary (refer to Section 4.1), the convectiveFlux function is used to define the fuel pyrolysis
boundary condition. The algorithm description of this boundary condition is presented in Table 10.
56
Table 10: Algorithm of the fuel pyrolysis boundary condition.
Algorithm: Fuel Pyrolysis Boundary Condition
Function convectiveFlux (args):

Input: args (a table that contains instantaneous state information of the fluid-cell adjacent to the
boundary condition [29]).

Output: Flux (a table that contains all entries of the flux vector (refer to equation (96)) that defines the
boundary condition.

Pseudocode:
1 Use the sampleFluidCell function (with args table as input) to extract the flow state from the fluid-
cells that are located at the current and right-hand side 𝑖-indexes, and adjacent to the boundary
condition.
2 At the current 𝑖-index, invoke the FuelState function to compute the vaporised fuel state at the
fuel surface.
3 At the current 𝑖-index, extract the fuel surface temperature from the userPad (subtract the 𝑖-
index by one for synchronisation) and compute the local regression rate of the solid fuel grain.
4 Using the calculation results from step 2 and 3, calculate the pyrolysis mass flux (refer to
equation (87)), fuel injection velocity (refer to equation (86)) and total energy per unit mass
(refer to equation (109)) at the fuel surface and current cell index.
5 Initialise the Flux table.
6 Apply corrections to the wall velocities at the right-hand side 𝑖-index (refer to equation (105) and
(106)).
7 Using the corrected wall velocities from step 6, compute the wall viscous shear stresses (refer
to equation (103) and (104)).
8 Compute the temperature gradient term of the wall-normal viscous heat flux (refer to equation
(108)).
9 Assign the Flux table with the following entries: mass, x-momentum, y-momentum, total energy
and species entries. Compute each entry of the Flux table by using equation (96) in conjunction
with the computed sub-terms from the previous steps.

Return Flux

Further details of the MPI implementation of this algorithm are in Section 4.2.5.

57
4.2.5 MPI Implementation of the Fuel Pyrolysis Boundary Condition
The fuel pyrolysis boundary condition must be compatible for parallel processing with high-
performance computing (HPC) to avoid the information exchange issues mentioned in Section 4.1.
For this reason, there is a need for the MPI implementation of this boundary condition. To establish
a framework for the MPI implementation, the governing equations and the base algorithm of this
boundary condition must be understood.

Compatibility of the Governing Equations of the Fuel Pyrolysis Boundary Condition to


Parallel Processing
The governing equations of the fuel pyrolysis boundary condition are defined by equation (96),
which constitutes of sub-terms that are defined by equation (103), (104), (105), (106), (108) and
(109). Among these equations, equation (105) and (106) could lead to information exchange issues
during parallel processing because they will try to access the data of the adjacent fluid-cell, which
is located at the right-hand side of the current 𝑖-index and could be in the adjacent sub-block.
According to Jacobs et al., each sub-block has a buffer region with two layers of ghost cell. This
region surrounds the active cells of the grid of the sub-block. At the common boundary between
two connected sub-blocks, the ghost cells in the buffer region of one sub-block will directly copy
the cell-average data from the active cells of the adjacent sub-block. In parallel simulations, the
standard message passing library (MPI) retains and handles this mode of block-to-block communi-
cations between processors. [30]. As a result, this prevents equation (105) and (106) from causing
information exchange issues at the common boundary between two connected sub-blocks during
parallel simulations in MPI.

Compatibility of the Base Algorithm of the Fuel Pyrolysis Boundary Condition to Parallel
Processing
As mentioned in Section 4.2.4, the userPad array is used to store the fuel surface temperature
(𝑇𝑠 (𝑡)|𝑥=𝑥𝑖 ,𝑦=0 ) distribution in the global namespace. A technique was proposed to synchronise the
index of this array with the 𝑖-index of the fluid-cells adjacent to the fuel pyrolysis boundary
condition. However, the proposed index synchronisation technique will lead to issues in accessing
the element of this array when there are block division and parallel simulations.

58
Before the block division, the grid of the main block only has one local parametric coordinate
system. After the block division, the local parametric coordinate system of this block will change
because it is being replaced by an array of independent parametric sub-coordinate systems that are
local to each sub-block. As a result, there will be a change in local parametric sub-coordinate
system at the common boundary between two connected sub-blocks. When this occurs, the 𝑖-index
of the fluid-cells is no longer sequential because it will reset from the maximum 𝑖-index of the
previous sub-block to the minimum 𝑖-index of the current sub-block. If the index synchronisation
technique for the userPad array does not consider this behaviour, the synchronisation issues
mentioned earlier will occur because this technique assumes that the 𝑖-index of the fluid-cells is
always sequential from the first fluid-cell at the leading edge of the fuel slab.

When there is block division and no parallel simulations, the convectiveFlux function that defines
the fuel pyrolysis boundary condition will be invoked sequentially in the 𝑖-direction. If the index
synchronisation technique for the userPad array considers the change in local parametric sub-
coordinate system at the block-boundary, there are no synchronisation issues. However, when there
are both block division and parallel simulations, the invocation of the convectiveFlux function will
no longer be sequential because the sub-blocks that are assigned with this boundary condition are
being run independently on separate processors. As the invocation sequence of the sub-blocks is
unpredictable in MPI, it is impossible to synchronise the userPad array unless there is an MPI-
invariant way to calculate the sequential 𝑖-index.

MPI Implementation Approach for the Fuel Pyrolysis Boundary Condition


As mentioned in Section 4.2.5.2, the userPad array will experience synchronisation issues
associated with the block division and parallel simulations. To address this issue, the recursion
technique can be used in conjunction with the fluidBlockArrays text file of Eilmer 4 to calculate
the sequential 𝑖-index of the fluid-cells along the fuel pyrolysis boundary condition. This techniq-
ue utilises the divisibility of the index of the sub-block (𝑖𝑏 ) along the fuel pyrolysis boundary
condition by the total number of sub-blocks in the 𝑗-direction (𝑛𝑗𝑏 ). To illustrate this divisibility,
consider the general case of the indexing system of the sub-blocks in Figure 7.

59
Figure 7: Indexing system of the sub-blocks in a multi-block grid.

In Figure 7, the thick black lines represent the boundaries of the main block, whereas the thin black
lines represent the common boundaries of the sub-blocks. The index sequence of the sub-blocks
proceeds as per the direction of the red arrows. From the figure, it is noticeable that the 𝑖𝑏 values
of the sub-blocks at the bottom row are a multiple of 𝑛𝑗𝑏 . This multiplicity implies the divisibility
of 𝑖𝑏 by 𝑛𝑗𝑏 . This property is applicable to the calculation of the sequential 𝑖-index along the fuel
pyrolysis boundary condition if and only if this boundary condition is assigned to the lower wall
of the domain.

On the other hand, the fluidBlockArrays text file contains a collection of mapping tables for the
𝑖𝑏 values of all the sub-blocks. To generate this array, the face of the main block that is assigned
with the fuel pyrolysis boundary condition must be labelled with a string. By discretion, this string
label is called “Injection”. This string label behaves like the pointer of each sub-block along this
boundary condition. In the fluidBlockArrays text file, the mapping tables that are relevant to the
recursion technique are:
1. fluidBlockArraysDict table
2. blockArray table of the fluidBlockArrays table.
The fluidBlockArraysDict table maps the “Injection” string label to the index of the main block
(blkId) that has the fuel pyrolysis boundary condition, whereas the blockArray table of the
fluidBlockArrays table maps blkId to the 𝑖𝑏 value of a sub-block by the equivalent blockArray

60
indices of that sub-block. Based on the blocking structure from Figure 7, the blockArray indexing
system is in Figure 8.

Figure 8: Indexing system of the blockArray table.

By utilising the divisibility of 𝑖𝑏 by 𝑛𝑗𝑏 through modular arithmetic, the sequential 𝑖-index along
the fuel pyrolysis boundary condition is mathematically defined as:
𝑛𝑖𝑏 |𝑝𝑟𝑒𝑣,𝐵.𝐶

𝑖 = 𝑖 𝑖𝑏 + ∑ 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 (110)


𝐾=1

where 𝑖𝑖𝑏 , 𝑛𝑖𝑏 |𝑝𝑟𝑒𝑣,𝐵.𝐶 , 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 and 𝐾 are defined as the 𝑖-index of a fluid-cell in the current

sub-block (at 𝑖𝑏 ), total number of sub-blocks that precedes the current sub-block in the 𝑖-direction
along the boundary condition, number of cells of each sub-block that precedes the current sub-
block and the number of blocks before the current sub-block, respectively. In application, 𝑖𝑖𝑏 is
determined from args.𝑖. With block division and parallel processing, 𝑛𝑖𝑏 |𝑝𝑟𝑒𝑣,𝐵.𝐶 is not a parameter
that is known in advance. As a result, it is impossible to use the summation of series approach as
outlined in equation (110) to compute the total number of cells of all sub-blocks that precede the
current sub-block. For this reason, the summation of series approach must be replaced by the
recursive summation approach because knowledge about 𝑛𝑖𝑏 |𝑝𝑟𝑒𝑣,𝐵.𝐶 is not required. The recursive
summation approach is illustrated in Figure 9.

61
Figure 9: Recursive summation approach.
In Figure 9, the red arrow represents a recursive call. At each recursive call, the sub-block index
(which is 𝑖𝑏 − 𝑛𝑗𝑏 𝐾) will be subtracted by 𝑛𝑗𝑏 to move to the adjacent sub-block on the left-hand
side. At the new sub-block (which is 𝑖𝑏 − 𝑛𝑗𝑏 (𝐾 + 1)), the infoFluidBlock(𝑖𝑏 − 𝑛𝑗𝑏 (𝐾 +
1)).nicell method is called to determine 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏(𝐾+1) . The value of 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏(𝐾+1) will then

be added to the cumulative number of fluid-cells in the 𝑖-direction calculated from the previous
recursive calls.

The recursion will continue in the fashion as illustrated in Figure 9 until the index of the sub-block
corresponds to the first sub-block of the fuel pyrolysis boundary condition. By this stage, the value
𝑛 |
𝑖𝑏 𝑝𝑟𝑒𝑣,𝐵.𝐶 𝑛 |
𝑖𝑏 𝑝𝑟𝑒𝑣,𝐵.𝐶
of ∑𝐾=1 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 is known. Then, the values of ∑𝐾=1 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 and args.𝑖 are

added together to determine the sequential 𝑖-index that counts from the leading edge of the fuel
grain and along this boundary condition.

The recursive approach is implemented as a function called getNcellsRecursion by using the


mentioned mapping tables from the fluidBlockArrays text file. Within the framework of Eilmer 4,
𝑖𝑏 is equivalent to blkId, which is a globally defined variable. The initial input of this function is
blkId subtracted by 𝑛𝑗𝑏 so that the recursive call starts from the adjacent sub-block that precedes
𝑛 |
𝑖𝑏 𝑝𝑟𝑒𝑣,𝐵.𝐶
the current sub-block. The output being the value of ∑𝐾=1 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 . The algorithm

description of this function is in Table 11.

62
Table 11: Algorithm of the recursive summation approach.
Algorithm: Recursive Summation Approach
Function getNcellsRecursion (𝑖𝑏′ ):

Input: 𝑖𝑏′ (Sub-block index that will be updated in each recursive call).

Initial Input: 𝑖𝑏′ = blkId - fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb

𝑛 |
𝑖𝑏 𝑝𝑟𝑒𝑣,𝐵.𝐶
Output: Total number of cells that precede the current sub-block (∑𝐾=1 𝑛𝑖𝑐𝑒𝑙𝑙 |𝑖𝑏−𝑛𝑗𝑏𝐾 ).

Pseudocode:

if 𝑖𝑏′ == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then


1. The condition where the sub-block index in the current recursive call corresponds to a sub-
block on the fuel pyrolysis boundary condition.
Return infoFluidBlock(𝑖𝑏′ ).nicell

elseif 𝑖𝑏′ < fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then


2. The condition where the recursive call goes before the first fluid-cell of the fuel pyrolysis
boundary condition.
Return 0

else
3. Invoke the recursive calls.
Return (infoFluidBlock(𝑖𝑏′ ).nicell +
getNcellsRecursion(𝑖𝑏′ - fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb))

63
4.3 Fluid-Solid Coupled Heat Transfer Mechanism
This section presents the algorithm design and implementation of the fluid-solid coupled heat
transfer mechanism, which is based on the loose coupling approach and Non-Integer System
Identification (NISI) method. The code for the NISI method was implemented by Jahn as part of
the heat engine and turbomachinery design tools (HTDT) [35]. This code will be an integral part
of the algorithm design of the fluid-solid coupled heat transfer mechanism.

4.3.1 Algorithm Design of the Loose Coupling Approach


According to Section 3.2.4, the loose coupling approach utilises the very distinct time scales of the
fluid flow and solid heat conduction processes by approximating the transient simulation as a time
series of quasi-steady flow states that are separated by a regular interval of the thermal time scale
in the solid (𝜏ℎ𝑒𝑎𝑡 ; refer to equation (26)). Figure 10 illustrates the algorithm of this coupling
approach.

Figure 10: Algorithm of the loose coupling approach, adapted from [36].

As indicated in Figure 10, time-integrations are performed along the fluid time-axis (𝑡) and solid
time-axis (𝑡𝑠 ). In step 1 of the algorithm, the surface temperature (𝑇𝑠𝑛−1 ) distribution of the solid
fuel grain, which is also the temperature boundary condition of the fluid domain will stay constant
from time-level 𝑛 − 1 (an equivalent for 𝑡 = (𝑛 − 1)𝑡𝑠𝑡𝑒𝑎𝑑𝑦 ) to 𝑛 (an equivalent for 𝑡 = 𝑛𝑡𝑠𝑡𝑒𝑎𝑑𝑦 ).
The duration of the fluid domain simulation between these two time-levels is 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 , which is the
required simulation time for the fluid domain to reach a quasi-steady state. The value of 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 is
set as constant and is pre-determined by running a representative test case to a quasi-steady state.
𝑛
In step 2 of the algorithm, the input heat flux (𝑞̇ 𝑖𝑛 ) distribution on the fuel surface at time-level 𝑛
𝑛
is calculated. As per Section 3.2.4, the 𝑞̇ 𝑖𝑛 distribution corresponds to the heat flux boundary
64
condition of the transient solid heat conduction problem at time-level 𝑛 − 1 in the solid time-axis
𝑛
(an equivalent for 𝑡𝑠 = (𝑛 − 1)𝜏ℎ𝑒𝑎𝑡 ). The equation of 𝑞̇ 𝑖𝑛 is derived by modifying equation (22)
to account for the possibility of heat flux contributions due to wall translations and fuel injections.

𝑛
(𝑇 𝑛 |𝑦=0+ − 𝑇𝑠𝑛−1 |𝑦=0 ) 𝑛 𝑛 𝑛
𝑞̇ 𝑖𝑛 = 𝑘𝑔𝑛 |𝑦=0+ + 𝑞̇ 𝑛𝑒𝑡,𝑟𝑎𝑑 𝑛
− 𝑞̇ 𝑝𝑦𝑟 𝑛 𝑛
+ 𝜏𝑥𝑦 𝑢𝑥 + 𝜏𝑦𝑦 𝑣𝑖𝑛𝑗 (111)
∆𝑦
In step 3 of the algorithm, the solid heat conduction simulation is performed using the NISI method
to predict the 𝑇𝑠𝑛 distribution at time-level 𝑛 in the solid time-axis (an equivalent for 𝑡𝑠 = 𝑛𝜏ℎ𝑒𝑎𝑡 ).
In step 4 of the algorithm, the 𝑇𝑠𝑛 distribution from step 3 becomes the new temperature boundary
condition of the fluid-domain at time-level 𝑛 by replacing the 𝑇𝑠𝑛−1 distribution at this time-level.

4.3.2 General Implementation of the Loose Coupling Approach


This section presents the general implementation methodology of the algorithm of the loose
coupling approach in Section 4.3.1.

Implementation of the Loose Coupling Mechanism


The loose coupling approach is implemented as a mechanism with the code architecture in Figure
11.

Figure 11: Code architecture of the loose coupling mechanism.

This mechanism will be an integral part of the fuel pyrolysis boundary condition (refer to Section
4.2) to update the surface temperature distribution and thus the regression rate distribution of the
solid fuel grain. In Figure 11, step 1 of this mechanism entails the saving operations of the input

65
𝑛
heat flux (𝑞̇ 𝑖𝑛 ) distribution on the fuel surface at time-level 𝑛 (refer to equation (111)) and the fuel
surface temperature (𝑇𝑠𝑛−1 ) distribution at time-level 𝑛 − 1 into two separate output text files. As
per the algorithm in Figure 10, the saving operations will occur when the simulation time in the
fluid domain (𝑡) is a multiple of 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 and at least equal to 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 . To reflect the time-level
differences, superscript 𝑛 is added to 𝑡 and the solid time (𝑡𝑠 ) from now on.

As mentioned in Section 4.2.4, the 𝑇𝑠𝑛−1 distribution is stored in the userPad array (refer to
userPad in [29]). According to Section 4.3.1, time-integration is also performed in the solid-time
axis. To store the value of 𝑡𝑠𝑛 for future updates, the same userPad array that stores the 𝑇𝑠𝑛−1
distribution is extended by one memory slot for this purpose during the initialisation phase. To
update the 𝑇𝑠𝑛−1 distribution and 𝑡𝑠𝑛 in the userPad array, a user-defined supervisor script (refer to
config.udf_supervisor_file in [29]) is required. That is because the userPad array only allows one-
way data synchronisation [29].

In step 2, the supervisor script will invoke the solid heat conduction script (refer to Section 4.3.2.2)
when 𝑡 𝑛 is a multiple of 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 and at least equal to 𝑡𝑠𝑡𝑒𝑎𝑑𝑦 . The solid heat conduction script will
take the output text files from step 1 as inputs to predict the 𝑇𝑠𝑛 distribution at time-level 𝑛 in the
solid time-axis. Then, this script will save the predicted 𝑇𝑠𝑛 distribution as an output text file.
In step 3, the supervisor script will load the output text file from step 2 to replace the 𝑇𝑠𝑛−1
distribution in the userPad array with the 𝑇𝑠𝑛 distribution at time-level 𝑛. Besides that, the script
will also update the 𝑡𝑠𝑛 value in the userPad array by adding the thermal time scale in the solid
(𝜏ℎ𝑒𝑎𝑡 ) to it.

In step 4, the 𝑇𝑠𝑛 distribution in the userPad array will be broadcasted to the fuel pyrolysis
boundary condition script and becomes the new temperature boundary condition of the fluid-
domain from time-level 𝑛 to 𝑛 + 1.

66
Implementation of the Solid Heat Conduction Script
The operations architecture of the solid heat conduction script is as shown in Figure 12.

Figure 12: Operations architecture of the solid heat conduction script.

𝑛
In Figure 12, the solid heat conduction script will load the 𝑞̇ 𝑖𝑛 distribution and 𝑇𝑠𝑛−1 distribution as
𝑛
inputs in step 1. In step 2, this script will save the 𝑞̇ 𝑖𝑛 distribution into the history file. The data
structure of this history file is in Figure 13.

Figure 13: Data structure of the input heat flux/fuel surface temperature distribution history file.

67
In Figure 13, the first column is the simulation time history in the solid-time axis, whereas the
second to the last column correspond to the 𝑞̇ 𝑖𝑛 |𝑖 history at each 𝑖-index on the fuel surface. Besides
𝑛
that, the second to the last row correspond to the 𝑞̇ 𝑖𝑛 distribution at each time-level 𝑛.

In step 3 and starting from 𝑖 = 1, the solid heat conduction script will extract the 𝑞̇ 𝑖𝑛 |1 history and
the time history (up to a time-level 𝑛) from the history file. In step 4, the solid heat conduction
script will write these data into the relevant fields in the input template of the HTDT code. In step
5, this script will invoke the filled input template to call the HTDT code. The HTDT code will then
return the value of 𝑇𝑠 |1 at 𝑖 = 1. In step 6, the solid heat conduction script will append the value of
𝑇𝑠 |1 into an array, which is the data structure to store the 𝑇𝑠𝑛 distribution at time-level 𝑛. Step 3 to
6 will then be repeated from 𝑖 = 2 to 𝑁.

In step 7, the solid heat conduction script will save the 𝑇𝑠𝑛 distribution at time-level 𝑛 into a history
file, where the data structure is as indicated in Figure 13. Besides that, this script will also save the
𝑇𝑠𝑛 distribution into an output text file. This file will then be loaded by the supervisor script, which
is an integral part of the loose coupling mechanism (refer to Section 4.3.2.1). The purpose is to
replace the 𝑇𝑠𝑛−1 distribution in the userPad array with the 𝑇𝑠𝑛 distribution at time-level 𝑛.

4.3.3 MPI Implementation of the Loose Coupling Mechanism


In the software implementation of the loose coupling mechanism, the supervisor script will execute
the solid heat conduction script by using the os.execute command. However, prior testing showed
that this command is ignored in the MPI simulations. As a result, there was an issue to update the
fuel surface temperature distribution. The solution to this issue is to force the os.execute command
to run in the master MPI task, which has a rank of zero. Besides that, all sub-blocks assigned with
the user-defined boundary condition are grouped into the master task so that they are in the same
memory space during MPI simulations. This is accomplished using the mpiDistributeBlocks
function [29]. With this approach, all other sub-blocks can run on separate processors in MPI
simulations, whereas the sub-blocks assigned with the user-defined boundary condition will not
have data communication issues.

68
4.4 Melt Layer Boundary Condition
This section entails the general and MPI implementation methodology of the melt layer boundary
condition.

4.4.1 Isothermal Melt Layer and First Stokes Problem Formulation


The thin-film model to be implemented will subject to the isothermal film assumption. This
assumption implies that the rate of heat gain and heat loss of the melt layer are equal so that the
internal energy and thus the melt layer temperature are both constant. With this assumption, the
𝑆𝛿𝑈̅ term (refer to equation (78)) in the energy conservation equation of the thin-film model will
become zero. As a result, the energy conservation equation simplifies to:
̅𝛿ℎ)
𝜕(𝛿ℎ) 𝜕(𝑈
+ =0 (112)
𝜕𝑡 𝜕𝑥
However, equation (112) is insufficient to allow for the isothermal assumption to hold due to the
̅𝛿ℎ)⁄𝜕𝑥 term. For this reason, a boundary value problem (BVP) must be formulated in such a
𝜕(𝑈
̅𝛿ℎ)⁄𝜕𝑥 term vanishes, equation (112) further
way to make this term vanish. When the 𝜕(𝑈
simplifies to:
𝜕(𝛿ℎ)
=0 (113)
𝜕𝑡
Equation (113) implies that the energy of the melt layer is in steady-state and remains unchanged.
As a result, the temperature of the melt layer is constant and satisfies the isothermal film assumpti-
on. One positive implication of the isothermal film assumption is the reduction in the complexity
of the implementation of the thin-film model because there is no need to solve the energy conser-
vation equation of this model. On the other hand, it is also assumed that there are no mass transfers
in and out the melt layer. With this assumption, the 𝑆𝛿 term (refer to equation (56)) in the mass
continuity conservation equation of the melt layer model becomes zero.

̅𝛿ℎ)⁄𝜕𝑥 term vanish is


One type of flow problem that corresponds to a BVP that can make the 𝜕(𝑈
the first Stokes problem for a finite-depth liquid. This problem entails the creation of flow in the
fluid domain by the translation of a wall under the liquid. One pertinent analytical study for this
type of flow is from Chi-Min. In their work, they impose the following boundary conditions to the
finite-depth liquid on a solid surface [37]:
𝑢𝑥 |𝑦=0,𝑡>0 = 𝑢𝑠𝑢𝑟𝑓 (114)

69
𝜕𝑢𝑥
| =0 (115)
𝜕𝑦 𝑦=𝛿,𝑡>0

𝑢𝑥 |𝑦>0,𝑡=0 = 0 (116)
where 𝑢𝑥 is the defined as the 𝑥-velocity profile of the finite-depth liquid in the wall-normal
direction and 𝑢𝑠𝑢𝑟𝑓 is defined as the bottom wall 𝑥-velocity of the liquid. Equation (114)
corresponds to a translating wall condition, whereas equation (116) corresponds to a zero initial
velocity condition within the finite-depth liquid.

To account for the translating wall and zero initial velocity conditions in the present melt layer
model, the quadratic velocity profile of this model (refer to equation (67)) is modified into the
following form using the derivation steps from Section 3.4.1:
𝑢𝑥 (𝑦𝑙 )
𝑢𝑠𝑢𝑟𝑓 , 𝑦𝑙 = 0, 𝑡 > 0
0, 𝑦𝑙 > 0, 𝑡 = 0 (117)
=
3 𝜏𝑥𝑦 2 3 𝜏
[ − (𝑈 ̅ − 𝑢𝑠𝑢𝑟𝑓 ) − 𝑥𝑦 ] 𝑦𝑙 + 𝑢𝑠𝑢𝑟𝑓 ,
̅ − 𝑢𝑠𝑢𝑟𝑓 )] 𝑦𝑙2 + [ (𝑈 0 < 𝑦𝑙 ≤ 𝛿, 𝑡 > 0
{4𝛿 𝜇𝑙 𝛿 𝛿 2𝜇𝑙
With the modified quadratic velocity profile, the wall-tangential shear stress at the melt-layer-solid
interface (𝜏𝑤,𝑚 ; equation (70)) becomes:
̅ − 𝑢𝑠𝑢𝑟𝑓 ) 𝜏𝑥𝑦
3(𝑈
𝜏𝑤,𝑚 = 𝜇𝑙 − (118)
𝛿 2
Besides that, equation (115) corresponds to a zero-stress condition at the free-surface of the liquid.
This condition is unrealistic because it neglects the tangential stress at the free-surface due to the
balance of forces on the gas-liquid interface. For this reason and to maintain consistency with the
boundary condition imposed on the melt layer velocity profile, equation (115) is replaced with the
wall-tangential shear stress condition (refer to equation (59)).

The boundary conditions for the first Stokes problem (refer to equation (114) – (116)) only affects
the formulation of the melt layer velocity profile and cannot be used as the boundary conditions to
solve the thin-film model. That is because these boundary conditions are defined with respect to
(w.r.t) the wall-normal coordinate (𝑦𝑙 ), whereas the spatial derivative of the thin-film model is w.r.t
the wall-tangential coordinate (𝑥).

70
The decision on the boundary conditions for the thin-film model should depend on how the first
Stokes problem is modelled in CFD. The first Stokes problem can be modelled as two parallel
walls moving in the opposite direction with the same translation velocity, where the internal flow
field between the parallel walls being static initially. Figure 14 illustrates this modelling approach.

Figure 14: First stokes problem modelling approach.

To reduce the computational cost, the fluid domain in Figure 14 is truncated by the symmetry axis.
Figure 15 illustrates the truncated fluid domain for the first Stokes flow simulation.

Figure 15: Truncated fluid domain of the first stokes problem model.

Due to the no-slip condition at the surface of the melt layer and note that the top and bottom walls
move in the opposite direction by the same translation velocity, the wall-normal velocity profile in
the fluid domain will be spanwise asymmetric about the vertical axis. As a result of this asymmetry,
the horizontal velocity at the symmetry axis of the original fluid domain (refer to Figure 14) or the
top wall of the truncated fluid domain (refer to Figure 15) will become zero, which corresponds to
a mirror-image condition.

To simulate the continuous movement of the bottom wall, the flow information at the inlet ghost
cells will be copied to the outlet ghost cells. With this approach, the internal flow field becomes
71
infinite in the 𝑥-direction because the bottom wall behaves like a conveyor belt that drives the flow
in one direction. Figure 16 illustrates the modelling approach for this wall.

Figure 16: Modelling approach for a continuously moving wall.

To ensure the thin-film model is consistent with the modelling approach of the continuously
moving wall (refer to Figure 16), a zero Neumann boundary condition is required for each transport
̅ or 𝛿ℎ) of this model at the inlet boundary. Mathematically, this boundary
variable (as in 𝛿, 𝛿𝑈
condition is in the following form:
𝜕𝛿 ̅
𝜕𝛿𝑈 𝜕𝛿ℎ
| = 0, | = 0, | =0 (119)
𝜕𝑥 𝑥=0 𝜕𝑥 𝑥=0 𝜕𝑥 𝑥=0

If the initial temperature of the melt layer is already isothermal and all transport variables are
homogeneous initially, then the zero Neumann boundary condition (refer to equation (119)) will
maintain the isothermal condition of the melt layer during the simulation. As a result, the
̅𝛿ℎ)⁄𝜕𝑥 term in equation (112) will vanish and there is no need to solve the energy conser-
𝜕(𝑈
vation equation.

When the simulation has reached a steady-state, the velocity profile in the fluid domain will become
linear and is equivalent to a Couette flow. Besides that, the shear stress of the top and bottom
surface of the melt layer will balance each other. Furthermore, the velocity at the top of the melt
layer will be different from the translation velocity of the wall due to the velocity profile in the
melt layer.

72
4.4.2 Isothermal Melt Layer Boundary Condition Formulation
This section presents the one-dimensional finite volume discretisation of the thin-film model,
boundary treatment of the discretised equations, numerical time-integration scheme of the thin-
film model and the governing equation of the isothermal melt layer boundary condition.

One-Dimensional Finite Volume Discretisation of the Thin-Film Model


To solve the mass continuity and momentum conservation equations of the thin-film model for 𝛿
̅, one-dimensional finite volume method (FVM) is required. The discrete approximation of
and 𝑈
the transport variable (𝜙) of the thin-film model in a one-dimensional grid is as shown in Figure
17.

Figure 17: 1-D finite volume grid [41].

In reference to Figure 17, the mathematical form of 𝜙 in FVM is:


𝜙(𝑥, 𝑡) = 𝜙𝑖 (𝑥𝑖 , 𝑡), 𝑥𝑖−1 ≤ 𝑥𝑖 ≤ 𝑥𝑖+1 (120)
2 2

where the equation of 𝜙𝑖 is:


𝑥 1
1 𝑖+
𝜙𝑖 (𝑥𝑖 , 𝑡) = ∫ 2 𝜙(𝑥, 𝑡)𝑑𝑥 (121)
𝑥𝑖+1 − 𝑥𝑖−1 𝑥 1
2 2 𝑖−
2

By integrating the general conservation equation of the thin-film model (refer to equation (79))
from 𝑥𝑖−1 to 𝑥𝑖+1 and then divide by the width of the fluid-cell, it follows that:
2 2

1 𝜕 𝑥𝑖+12 1 𝑥 1 ̅𝜙)
𝑖+ 𝜕(𝑈 1 𝑥 1
𝑖+ 𝑆
2
∫ 𝜙𝑑𝑥 + ∫ 𝑑𝑥 = ∫ 2 𝑑𝑥
𝑥𝑖+1 − 𝑥𝑖−1 𝜕𝑡 𝑥 1 𝑥𝑖+1 − 𝑥𝑖−1 𝑥 1 𝜕𝑥 𝑥𝑖+1 − 𝑥𝑖−1 𝑥 1 𝜌𝑙 (122)
2 2 𝑖− 2 2 𝑖− 2 2 𝑖−
2 2 2

73
As a result of this integration, equation (122) becomes:
𝜕𝜙𝑖 1 𝑆
+ [(𝑈 ̅𝜙) 1 ] = 𝑖
̅𝜙) 1 − (𝑈 (123)
𝜕𝑡 𝑥𝑖+1 − 𝑥𝑖−1 𝑖+2 𝑖−2 𝜌𝑙
2 2

By rearranging equation (123) in terms of 𝜕𝜙𝑖 ⁄𝜕𝑡, it follows that:


𝜕𝜙𝑖 𝑆𝑖 1
= − ̅𝜙) 1 − (𝑈
[(𝑈 ̅𝜙) 1 ] (124)
𝜕𝑡 𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1 𝑖+2 𝑖−2
2 2
̅𝜙) 1 and (𝑈
On the other hand, the first-order upwind scheme for (𝑈 ̅𝜙) 1 are below [41]:
𝑖+ 𝑖−
2 2

̅𝜙)𝑖 ,
(𝑈 ̅𝑖 > 0
𝑈
̅𝜙)
(𝑈 1 ={ (125)
𝑖+2 ̅𝜙)𝑖+1 ,
(𝑈 ̅𝑖 < 0
𝑈
̅𝜙)𝑖−1 ,
(𝑈 ̅𝑖 > 0
𝑈
̅𝜙)
(𝑈 1 ={ (126)
𝑖−
2 ̅𝜙)𝑖 ,
(𝑈 ̅𝑖 < 0
𝑈

By applying the first-order upwind scheme on equation (124), it follows that:


𝑆𝑖 1
− ̅𝜙)𝑖 − (𝑈
[(𝑈 ̅𝜙)𝑖−1 ], ̅𝑖 > 0
𝑈
𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1
𝜕𝜙𝑖 2 2
= (127)
𝜕𝑡 𝑆𝑖 1
− ̅𝜙)𝑖+1 − (𝑈
[(𝑈 ̅𝜙)𝑖 ], ̅𝑖 < 0
𝑈
𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1
{ 2 2

Since the interface node is at the midpoint between the centres of two-connecting cells, it follows
that the equation of fluid-cell width is:
𝑥𝑖+1 + 𝑥𝑖 𝑥𝑖 + 𝑥𝑖−1 𝑥𝑖+1 − 𝑥𝑖−1
𝑥𝑖+1 − 𝑥𝑖−1 = − = (128)
2 2 2 2 2

By substituting equation (128) into equation (127), it follows that:


𝑆𝑖𝑛 2
𝑛 − ̅𝜙)𝑛𝑖 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖−1 ], ̅𝑖𝑛 > 0
𝑈
𝜕𝜙𝑖 𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1
= (129)
𝜕𝑡 𝑆𝑖𝑛 2
− ̅𝜙)𝑛𝑖+1 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖 ], ̅𝑖𝑛
𝑈 <0
𝜌
{ 𝑙 𝑥𝑖+1 − 𝑥𝑖−1

where 𝑛 is defined as time level. In reference to Figure 17, the range of 𝑖 is 1 ≤ 𝑖 ≤ 𝑁. Based on
this indexing system, equation (129) can be represented in the following vector forms:

74
2
̅𝜙)1𝑛 − (𝑈
[(𝑈 ̅𝜙)𝑛0 ]
𝑥2 − 𝑥0
2
𝜕𝜙1𝑛 ⁄𝜕𝑡 𝑆1𝑛 ̅𝜙)𝑛2 − (𝑈
[(𝑈 ̅𝜙)1𝑛 ]
𝑥 − 𝑥
𝜕𝜙2𝑛 ⁄𝜕𝑡 𝑆2𝑛 3 1
𝑛 2
𝜕𝜙3𝑛 ⁄𝜕𝑡 1 𝑆3 ̅𝜙)𝑛3 − (𝑈
[(𝑈 ̅𝜙)𝑛2 ]
⋮ = ⋮ − 𝑥4 − 𝑥2 , ̅𝑖𝑛 > 0
𝑈 (130)
𝑛 𝜌𝑙 𝑛 ⋮
𝜕𝜙𝑖 ⁄𝜕𝑡 𝑆𝑖
2
⋮ ⋮ ̅𝜙)𝑛𝑖 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖−1 ]
𝑛⁄
[𝜕𝜙𝑁 𝜕𝑡] 𝑛
[𝑆𝑁 ] 𝑥𝑖+1 − 𝑥𝑖−1

2
̅𝜙)𝑛𝑁 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑁−1 ]
[𝑥𝑁+1 − 𝑥𝑁−1 ]
2
̅𝜙)1𝑛 − (𝑈
[(𝑈 ̅𝜙)𝑛0 ]
𝑥2 − 𝑥0
2
𝜕𝜙1𝑛 ⁄𝜕𝑡 𝑆1𝑛 ̅𝜙)𝑛2 − (𝑈
[(𝑈 ̅𝜙)1𝑛 ]
𝑥 − 𝑥
𝜕𝜙2𝑛 ⁄𝜕𝑡 𝑆2𝑛 3 1
𝑛⁄ 𝑛 2
𝜕𝜙3 𝜕𝑡 1 𝑆3 ̅𝜙)𝑛3 − (𝑈
[(𝑈 ̅𝜙)𝑛2 ]
⋮ = ⋮ − 𝑥4 − 𝑥2 , ̅𝑖𝑛 < 0
𝑈 (131)
𝑛 𝜌𝑙 𝑛 ⋮
𝜕𝜙𝑖 ⁄𝜕𝑡 𝑆𝑖
2
⋮ ⋮ ̅𝜙)𝑛𝑖+1 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖 ]
𝑛⁄
[𝜕𝜙𝑁 𝜕𝑡] 𝑛
[𝑆𝑁 ] 𝑥𝑖+1 − 𝑥𝑖−1

2
̅𝜙)𝑛𝑁 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑁−1 ]
[𝑥𝑁+1 − 𝑥𝑁−1 ]
The first row of equation (130) and (131) requires boundary treatment. According to Section 4.4.1,
a zero Neumann boundary condition is imposed on each transport variable at the inlet boundary.
As the first row of these equation is adjacent to the inlet boundary, the zero Neumann boundary
condition applies.

To provide an integrative framework for the zero Neumann boundary condition, a first-order
central difference scheme is used. With this scheme, it follows that:
𝜕𝜙 𝜙1𝑛 − 𝜙0𝑛
| =0 → = 0 → 𝜙1𝑛 = 𝜙0𝑛 (132)
𝜕𝑥 𝑥=0 𝑥1 − 𝑥0
By expanding equation (132), it follows that:
𝛿1𝑛 = 𝛿0𝑛 , ̅1𝑛 = 𝛿0𝑛 𝑈
𝛿1𝑛 𝑈 ̅0𝑛 → 𝑈
̅1𝑛 = 𝑈
̅0𝑛 (133)
With equation (133), the first row of (130) and (131) becomes:
𝜕𝜙1𝑛 𝑆1𝑛 2 𝑆𝑛 2𝜙1𝑛 𝑆𝑛
= − [𝑈 ̅0𝑛 𝜙0𝑛 ] → 1 −
̅1𝑛 𝜙1𝑛 − 𝑈 [𝑈 ̅0𝑛 ] → 1
̅1𝑛 − 𝑈 (134)
𝜕𝑡 𝜌𝑙 𝑥2 − 𝑥0 𝜌𝑙 𝑥2 − 𝑥0 𝜌𝑙

75
Numerical Time-Integration Scheme for the Thin-Film Model
To solve the thin-film model for the spatial distribution of each transport variable at every instant
of the simulation, equation (130) or (131) requires numerical time-integration. The chosen
numerical time-integration scheme is the explicit Euler method because it is compatible with the
convectiveFlux function, which will be called sequentially. The compatibility arises because this
method allows local time-integration at each node. The locality of the time-integration makes the
implementation simpler because it excludes the necessity to solve for each transport variable at all
nodes simultaneously. With this scheme, it follows that:
𝑆𝑖𝑛 2
𝑛+1 𝑛 − ̅𝜙)𝑛𝑖 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖−1 ], ̅𝑖𝑛 > 0
𝑈
𝜙𝑖 − 𝜙𝑖 𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1
= (135)
∆𝑡 𝑆𝑖𝑛 2
− ̅𝜙)𝑛𝑖+1 − (𝑈
[(𝑈 ̅𝜙)𝑛𝑖 ], ̅𝑖𝑛
𝑈 <0
{ 𝜌𝑙 𝑥𝑖+1 − 𝑥𝑖−1

Governing Equation of the Isothermal Melt Layer Boundary Condition


̅𝑖𝑛 . To determine
At each instant, the state of the melt layer is characterised by variables 𝛿𝑖𝑛 and 𝛿𝑖𝑛 𝑈
̅𝑖𝑛 , variable 𝛿𝑖𝑛 𝑈
the value of 𝑈 ̅𝑖𝑛 will be divided by 𝛿𝑖𝑛 . The value of 𝑈
̅𝑖𝑛 will then be used in
conjunction with equation (117) to calculate the current top surface velocity of the melt layer
(𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 ):
𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0
𝑛 𝑛
3 𝜏𝑥𝑦 2 3 𝜏𝑥𝑦
= [ − ̅
(𝑈 𝑛
− 𝑢 𝑠𝑢𝑟𝑓 )] 𝑦 2
+ ̅
(𝑈
[ 𝑛 𝑖 𝑛
− 𝑢 𝑠𝑢𝑟𝑓 ) − ]𝑦 (136)
4𝛿𝑖𝑛 𝜇𝑙 𝛿𝑖𝑛 𝑖 𝑙
𝛿𝑖 2𝜇𝑙 𝑙
+ 𝑢𝑠𝑢𝑟𝑓
The simplification of equation (136) gives:
𝑛 𝑛
𝜏𝑥𝑦 𝛿𝑖
̅𝑖𝑛 − 𝑢𝑠𝑢𝑟𝑓 ) +
𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 = 1.5(𝑈 + 𝑢𝑠𝑢𝑟𝑓 (137)
4𝜇𝑙
𝑛
According to Section 4.2.3.1, the wall viscous shear stress (𝜏𝑥𝑦 ) term in equation (137) is:

𝑛 𝑛 𝑛
(𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦=0 ) 𝜕𝑢𝑦𝑛
𝜏𝑥𝑦 = 𝜏𝑥𝑦 |𝑥=𝑥 ,𝑦=0 = 𝜇𝑥=𝑥 𝑖 ,𝑦=0
+ [ + | ] (138)
𝑖 ∆𝑦 𝜕𝑥 𝑥=𝑥 ,𝑦=0
𝑖

As 𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 is the velocity boundary condition of the fluid domain, it follows that:
𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦=0 = 𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 (139)

76
By substituting equation (138) and (139) into equation (137), it follows that:
𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0
̅𝑖𝑛 − 𝑢𝑠𝑢𝑟𝑓 )
= 1.5(𝑈

𝛿𝑖𝑛 (𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦=0+ − 𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 ) 𝜕𝑢𝑦𝑛 (140)


+ 𝜇𝑥=𝑥𝑖 ,𝑦=0+ [ + | ]
4𝜇𝑙 ∆𝑦 𝜕𝑥 𝑥=𝑥 ,𝑦=0
𝑖

+ 𝑢𝑠𝑢𝑟𝑓
By rearranging equation (140) in terms of 𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 , it follows that:
𝑢𝑥𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0
𝑛 𝑛
𝛿 𝑛 𝜇𝑥=𝑥𝑖 ,𝑦=0+ 𝑢𝑥 |𝑥=𝑥𝑖 ,𝑦=0+ 𝜕𝑢𝑦𝑛
̅𝑖𝑛
1.5(𝑈 − 𝑢𝑠𝑢𝑟𝑓 ) + 𝑖 [ ] ∙[ + | ] + 𝑢𝑠𝑢𝑟𝑓
4 𝜇𝑙 ∆𝑦 𝜕𝑥 𝑥=𝑥 ,𝑦=0 (141)
𝑖
= 𝑛
𝛿𝑖𝑛 𝜇𝑥=𝑥 𝑖 ,𝑦=0
+
1+
4∆𝑦 [ ]
𝜇𝑙
The isothermal melt layer boundary condition can be formulated in the same way as the fuel
pyrolysis boundary condition. Repeat for convenience, the governing equation of the fuel pyrolysis
boundary condition is:
𝜌𝑢𝑦 𝑛
𝐹𝑚𝑎𝑠𝑠
𝐹𝑥−𝑚𝑜𝑚 𝜌𝑢𝑥 𝑢𝑦 − 𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 = 𝐹𝑦−𝑚𝑜𝑚 = 𝜌𝑢𝑦2 + 𝑝 − 𝜏𝑦𝑦 (142)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 𝜌𝐸𝑢𝑦 + 𝑝𝑢𝑦 − (𝜏𝑥𝑦 𝑢𝑥 + 𝜏𝑦𝑦 𝑢𝑦 + 𝑞𝑦 )
[𝐹𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 𝜌𝑓𝑠 𝑢𝑦 − 𝐽𝑦,𝑠 ]𝑥=𝑥 ,𝑦=0
𝑖

By applying the boundary treatment technique from Section 4.2.2 and the assumption that there is
no mass injection at the top surface of the melt layer, equation (142) simplifies to:
𝑛
𝐹𝑚𝑎𝑠𝑠 0
𝐹𝑥−𝑚𝑜𝑚 −𝜏𝑥𝑦
(𝐹̅𝑛𝑒𝑡 ∙ 𝑛̂)|𝑥=𝑥𝑖 ,𝑦=0 𝐹
= 𝑦−𝑚𝑜𝑚 = 𝑝|𝑦=0+ − 𝜏𝑦𝑦 (143)
𝐹𝑒𝑛𝑒𝑟𝑔𝑦 −(𝜏𝑥𝑦 𝑢𝑛 |𝑥=𝑥𝑖 ,𝑦𝑙=𝛿,𝑡>0 + 𝑞𝑦 )
[𝐹𝑠𝑝𝑒𝑐𝑖𝑒𝑠−𝑠 ] [ 0 ] 𝑥=𝑥𝑖 ,𝑦=0
𝑛
The formulation of the 𝜏𝑦𝑦 |𝑥=𝑥 ,𝑦=0 and 𝑞𝑦𝑛 |𝑥=𝑥 ,𝑦=0 terms in equation (143) are as per Section
𝑖 𝑖

4.2.3.1 and 4.2.3.2, respectively. The temperature boundary condition at the gas-melt-layer inter-
face is set as constant to reflect the isothermal nature of the melt layer.

77
4.4.3 General Implementation
The general implementation of the isothermal melt layer boundary condition aims to establish the
base algorithm of this boundary condition. There are two considerations to implement this
boundary condition: data storage for the spatial distribution of the isothermal gas-melt-layer
̅,
interface temperature (𝑇𝑚𝑠 |𝑥=𝑥𝑖 ,𝑦=0 ) and the spatial distributions of the current and future 𝛿 and 𝑈
and a state update mechanism for the melt layer.

According to Section 4.2.4, the userPad array (refer to userPad in [29]) is the recommended data
structure to store the spatial distribution of 𝑇𝑚𝑠 |𝑥=𝑥𝑖 ,𝑦=0 and the spatial distributions of the current
̅. In terms of implementation, one would think of defining five userPad arrays
and future 𝛿 and 𝑈
of the same size, where the size of each array is set equal to the total number of fluid-cells (𝑁)
along the isothermal melt layer boundary condition. Among the five arrays, one array is for
̅.
𝑇𝑚𝑠 |𝑥=𝑥𝑖 ,𝑦=0 , whereas the remaining two pairs of arrays are for 𝛿 and 𝑈

As Eilmer 4 only allows defining one userPad array, the data storage approach mentioned earlier
requires modifications. Instead of defining five userPad arrays where each array size is 𝑁, one can
combine the five userPad arrays into a single userPad array with a size of 5𝑁. In this array, every
interval of size 𝑁 corresponds to the spatial distribution of a primitive variable (as in 𝑇𝑚𝑠 |𝑥=𝑥𝑖 ,𝑦=0 ,
̅) along the isothermal melt layer boundary condition. Once this array is defined, its element
𝛿 or 𝑈
index must be synchronised with the index position of the fluid-cell adjacent to the boundary
condition by using the synchronisation technique from Section 4.2.4.

Given the synchronised 𝑖-index position of a fluid cell, each primitive variable at that position can
be extracted from the userPad array by using Table 12 as a reference. To reflect the time level of
the primitive variables, a superscript 𝑛 will be added to these variables from now on.
Table 12: Data structure of the userPad array.
Primitive Variable Offset Factor Offset 𝒊-index (𝒊′ ) Index Range within the
userPad Array
𝛿𝑖𝑛 0 𝑖 1 ≤ 𝑖′ ≤ 𝑁
̅𝑖𝑛
𝑈 𝑁 𝑖+𝑁 𝑁 + 1 ≤ 𝑖 ′ ≤ 2𝑁
𝛿𝑖𝑛+1 2𝑁 𝑖 + 2𝑁 2𝑁 + 1 ≤ 𝑖 ′ ≤ 3𝑁
̅𝑖𝑛+1
𝑈 3𝑁 𝑖 + 3𝑁 3𝑁 + 1 ≤ 𝑖 ′ ≤ 4𝑁

78
Primitive Variable Offset Factor Offset 𝒊-index (𝒊′ ) Index Range within the
userPad Array
𝑇𝑚𝑠 |𝑥=𝑥𝑖 ,𝑦=0 4𝑁 𝑖 + 4𝑁 4𝑁 + 1 ≤ 𝑖 ′ ≤ 5𝑁

To update the state of the melt layer, the intervals in the userPad array that contain the spatial
̅ 𝑛 must be updated in the user-defined supervisor script (refer to config.-
distributions of 𝛿 𝑛 and 𝑈
udf_supervisor_file in [29]) by a state update mechanism. That is because the userPad array only
allows one-way data synchronisation [29]. The state update mechanism is as shown in Figure 18.

Figure 18: State update mechanism of the melt layer.

From Figure 18, the script of the isothermal melt layer boundary condition will export the spatial
̅ 𝑛+1 at the new time level as two separate output files. The supervisor
distributions of 𝛿 𝑛+1 and 𝑈
script will then load the output files to update the userPad entries that contain the spatial distribu-
̅ 𝑛 with the spatial distributions of 𝛿 𝑛+1 and 𝑈
tions of 𝛿 𝑛 and 𝑈 ̅ 𝑛+1 . The updated userPad will then
be used for the intermediate calculations within the isothermal melt layer boundary condition.

79
4.5 Chemistry Kinetics Source Term
The implementation of the chemistry kinetics source term is rather straightforward. Within the
framework of Eilmer 4, no MPI implementation is required for this source term because the
conservation equations of the fluid domain are already compatible for parallel processing with
high-performance computing. To implement this source term, it is recommended to use the
sourceTerms function of Eilmer 4. This function accepts two inputs and returns one output. The
two inputs are the current simulation time (𝑡) and cell data table (denote as cell), whereas the output
is a table that may include the following entries [34]:
1. mass.
2. momentum_x.
3. momentum_y.
4. momentum_z.
5. total_energy.
6. species.
7. renergies.
8. romega.
9. rtke.
By discretion, the name of the output table is src. The src table only requires the species entry
because chemistry kinetics modelling is all about species production. The species entry of the src
table is a table with the key and value being the name and rate of production of each species,
respectively. According to Section 3.3.2, the species involved in the combustion of Hydroxyl-
Terminated Polybutadiene (HTPB) fuel and pure oxygen are C4H6, O2, CO, CO2 and H2O. The rate
of productions of these species is given by equation (40) – (44). To calculate the production rate of
each species, information about the local temperature and the molar mass and concentration of the
species are required.

In terms of implementation, the local temperature is extracted from the cell table to compute the
forward and backward reaction rates of the global reactions (refer to equation (37) – (39)).
Providing the gas model of all species has been defined, the molar mass and concentration of each
species can be determined using the following GasModel methods: massf2conc and molMasses
methods [34].

80
4.6 Thermal Radiation Source Term
According to Section 3.2.2, the P1-radiation model is chosen to model the thermal radiation effect
in the flow field. This radiation model is governed by the transport equation of the incident radiation
(𝐺𝜆 ), which is a second-order elliptical partial differential equation (PDE; refer to equation (12)).
This transport equation is to be solved in conjunction with the Marshak boundary condition (refer
to equation (16)) for the local incident radiation throughout the fluid domain. The solution approach
to this equation is the finite volume method (FVM).
By discretising equation (12) using the FVM approach by Krishnamoorthy et al., it follows that the
cell-centred incident radiation is [15]:
𝜕𝐺𝜆 𝜕𝐺𝜆 𝜕𝐺𝜆 𝜕𝐺𝜆
[(Γ𝜆 ) − (Γ𝜆 ) ] 𝑑𝑦𝑑𝑧 + [(Γ𝜆 ) − (Γ𝜆 ) ] 𝑑𝑥𝑑𝑧
𝜕𝑥 𝑒 𝜕𝑥 𝑤 𝜕𝑦 𝑛 𝜕𝑦 𝑠
𝜕𝐺𝜆 𝜕𝐺𝜆 (144)
+ [(Γ𝜆 ) − (Γ𝜆 ) ] 𝑑𝑥𝑑𝑦 − (𝑎𝜆 |𝑝 𝐺𝜆𝑝 )𝑑𝑥𝑑𝑦𝑑𝑧
𝜕𝑧 𝑡 𝜕𝑧 𝑏
+ (4𝑎𝜆 |𝑝 𝜎𝑇𝑝4 )𝑑𝑥𝑑𝑦𝑑𝑧 = 0
where subscripts 𝑒, 𝑤, 𝑛, 𝑠, 𝑡 and 𝑏 indicate the east, west, north, south, top and bottom surfaces
of a fluid-cell, respectively. Besides that, subscript 𝑝 is defined as the node at which equation (12)
is approximated. Furthermore, Γ𝜆 and 𝑎𝜆 |𝑝 are given by equation (13) and (14), respectively. To
approximate the spatial derivatives of 𝐺𝜆 at the common interfaces between fluid-cells, a central
difference scheme is required [15]. If the considered control volume is adjacent to a boundary
cell(s), then the corresponding spatial derivatives of 𝐺𝜆 in equation (144) must be replaced by equa-
tion (16).

Mathematically, equation (144) can be transformed into the following form [15]:

𝐴𝑝 𝐺𝜆𝑝 + ∑ 𝐴𝑅 𝐺𝜆𝑅 = 𝐵𝑝 (145)


𝑅

where 𝐴𝑅 and 𝐵𝑝 are defined as the product of the geometric and medium properties, and a group
of all known terms, respectively. Besides that, subscript 𝑅 corresponds to the index of the neigh-
bouring surface nodes. Equation (145) is then assembled into the following matrix form [15]:
𝐴∙𝐺 =𝐵 (146)
where 𝐴 is defined as the sparse and symmetric square coefficient matrix. This matrix is to be
solved for 𝐺𝜆𝑝 throughout the fluid domain iteratively.

81
In terms of implementation, it difficult to implement the P1-radiation model within the framework
of user-defined source term due to the following challenges:
1. Must create a segregated solver that solves the P1-radiation model for 𝐺𝜆𝑝 by using the
FVM approach mentioned earlier because it is a boundary value problem.
2. Must create a data structure that can store the value of 𝐺𝜆𝑝 and temperature at each node of
the fluid domain.
3. The sourceTerms function can only access the local cell data at each call. However,
solving for 𝐺𝜆𝑝 throughout the fluid domain simultaneously requires the geometric and
medium properties of all the cells at each instant to populate the FVM matrix of the P1-
radiation model (refer to equation (146)).
4. The segregated solver approach allows the FVM matrix to be solved in the shared memory
fashion. If the fluid domain is running in MPI, it would be difficult for the segregated solver
to access the data of the relevant sub-blocks at each instant because all sub-blocks are
running independently on separate processors.
5. Solving a large FVM matrix by using a segregated solver would be computationally
expensive.
As it is inevitable to solve the P1-radiation model throughout the fluid domain as a boundary value
problem, it is recommended to implement this radiation model within the framework of Eilmer 4
directly via code development. With this approach, it would reduce the complexity of implement-
ation as it excludes the necessity to create a segregated solver, which requires an additional data
transfer and storing mechanism to extract the fluid domain data. Due to time constraints to
implementing the P1-radiation model, this model is not modelled in this work.
As the P1-radiation model is not implemented, the divergence of radiation source term local to a
fluid-cell becomes:
∇ ∙ ⃗q 𝑟𝑎𝑑 = −4𝜎𝑎𝜆 𝑇 4 (147)
Implementing this radiation source term is simple. Coming off from Section 4.5, equation (147) is
assigned to the total_energy entry of the src table. As equation (147) is simply an energy sink
term, the energy of the flow field in the fluid domain will not be conserved during the simulation
when this source term is active. Hence, one would expect the temperature of the flow field will
keep dropping due to energy loss, which is unrealistic. Therefore, the thermal radiation effect will
be neglected in the simulation.

82
Chapter 5

Testing Methodology

This chapter presents the testing methodologies for the computational fluid dynamics (CFD) sub-
models from Chapter 4. The testing methodologies will cover the details of the verification, valida-
tion and the main test cases for all the CFD sub-models, except for the thermal radiation source
term and the fluid-solid coupled heat transfer mechanism.

5.1 Verification Test Case of the Chemistry Kinetics


There are two test cases to verify the implementation correctness of the chemistry kinetics: constant
volume reactor and reacting pipe flow test cases. As part of the verification, the transient simulation
results of Eilmer 4 will be compared with the calculation results.

5.1.1 Constant Volume Reactor Test Case


This section presents the geometry, blocking structure, mesh, boundary and initial conditions,
simulation configurations and the verification calculation methodology of the constant volume
reactor test case.

Geometry
The constant volume reactor is a two-dimensional square domain. The geometrical dimensions of
this reactor are in Figure 19.

83
Figure 19: Dimensions of the constant volume reactor.

Boundary and Initial Conditions, Blocking Structure, Meshing and Simulation


Configurations
The boundary conditions and blocking structure of the constant volume reactor are in Figure 20.

Figure 20: Boundary conditions of the constant volume reactor.

In Figure 20, the slip-wall condition is implemented using Eilmer 4’s default WallBC_WithSlip
boundary condition. This boundary condition enforces the flow tangency and no-penetration
conditions at the wall. Besides that, the zero wall-normal temperature gradient condition is inherent
to this boundary condition. As a result, the reactor is adiabatic and has a fixed total mass.
The fluid domain of the constant volume reactor is discretised using a single block structured grid,
which has a uniform mesh. The mesh settings of the grid are in Table 13.
Table 13: Mesh settings of the constant volume reactor test case.
Block ID No. Cells in the 𝒊-direction (𝑵) No. Cells in the 𝒋-direction

0 3 3

84
Besides that, the initial conditions of this test case are in Table 14.
Table 14: Initial conditions of the constant volume reactor test case.
Parameter Initial Condition
Static pressure, p (atm) 1.33
Temperature, T (K) 300.0
Flow velocity (ms-1) 0.0
Mass fraction of C4H6, 𝑌𝐶4𝐻6 27/83
Mass fraction of O2, 𝑌𝑂2 56/83

In Table 14, the mass fractions of C4H6 and O2 are based on stoichiometric ratio. Furthermore, the
simulation configurations of this test case are in Table 15.
Table 15: Simulation configurations of the constant volume reactor test case.
Configuration Parameter Setting

config.dimensions 2

config.viscous false

config.turbulence_model none

config.udf_source_terms true

config.max_time 5.0 × 10-3 s

config.dt_init 1.0 × 10-7 s

config.fixed_time_step true

In Table 15, the viscous effect is turned off. Neglecting the viscous effect will simplify the
calculations to verify the simulation results of Eilmer 4. Lastly, there is a need to ignite the HTPB-
oxygen mixture to initiate a combustion. The ignition settings of this test case are in Table 16.
Table 16: Ignition settings of the constant volume reactor test case.
Ignition Parameter Setting
Ignition temperature, 𝑇𝑖𝑔𝑛 (K) 1500
Ignition start time, 𝑡𝑖𝑔𝑛,𝑠𝑡𝑎𝑟𝑡 (s) 0.10 × config.max_time
Ignition end time, 𝑡𝑖𝑔𝑛,𝑒𝑛𝑑 (s) 0.105 × config.max_time

For verification purpose, a history point is assigned to record the transient profiles of the
temperature, static pressure and species mass fractions in the reactor throughout the simulation.

85
Methodology of the Verification Calculation
The verification calculation will involve the numerical time-integration of the chemistry kinetics
to determine the transient profiles of the temperature, static pressure and species mass fractions in
the reactor. To account for the adiabatic and fixed total mass conditions of the reactor, constraints
are applied to ensure the internal energy and gas-mixture density of the reactor are constant
throughout the numerical time-integration.

At each time step, the explicit Euler method is used to integrate the species production rate of the
chemistry kinetics (refer to Section 3.3.2) to determine the species concentrations and thus the
equivalent species mass fractions at the new time-level. The new species mass fractions are then
assigned to the flow state object from the previous time-level. To implement the constraints
mentioned earlier, the initial internal energy and gas-mixture density of the reactor are also
assigned to the flow state object. By invoking the updateThermoFromRHOU method from the
GasModel object [34], the flow state object will be updated from the internal energy and gas-
mixture density to determine the flow state at the new time-level.

Once the maximum simulation time is reached, the calculated transient profiles of the temperature,
static pressure and species mass fractions in the reactor are used to verify the simulation results of
Eilmer 4.

86
5.1.2 Reacting Pipe Flow Test Case
This section presents the geometry, blocking structure, mesh, boundary and initial conditions,
simulation configurations and the verification calculation methodology of the reacting pipe flow
test case.

Geometry
The reacting pipe is a two-dimensional rectangular domain, which is axisymmetric. The geometri-
cal dimensions of this pipe are in Figure 21.

Figure 21: Dimensions of the reacting pipe.

Boundary and Initial Conditions, Blocking Structure, Meshing and Simulation


Configurations
The boundary conditions and blocking structure of the reacting pipe are in Figure 22.

Figure 22: Boundary conditions of the reacting pipe.

The fluid domain of the reacting pipe is discretised using a single block structured grid, which is
evenly-spaced in the direction of discretisation. The mesh settings of the grid are in Table 17.

87
Table 17: Mesh settings of the reacting pipe flow test case.
Block ID No. Cells in the 𝒊-direction (𝑵) No. Cells in the 𝒋-direction

0 2000 2

To reduce the computational expense of the reacting pipe flow simulation, block marching (refer
to block_marching in [29]) is used. With block marching, only two blocks are integrated in time
in the dominant flow direction at each instant [29]. In the reacting pipe flow simulation, the
dominant flow direction is the 𝑖-direction because of the supersonic inflow. The settings for block
marching are in Table 18.
Table 18: Block marching settings of the reacting pipe flow test case.
Configuration Parameter Setting

config.block_marching true

config.nib 200

config.njb 1

Besides that, the initial conditions of the reacting pipe flow are set equal to the supersonic inflow
conditions, which are in Table 19.
Table 19: Supersonic inflow conditions of the reacting pipe flow test case.
Parameter Inflow Condition
Static pressure, p (kPa) 96.87
Temperature, T (K) 1559
Flow velocity in the 𝑥-direction, 𝑢𝑥 (ms-1) 4551.73
Mass fraction of C4H6, 𝑌𝐶4𝐻6 27/83
Mass fraction of O2, 𝑌𝑂2 56/83

In Table 19, the mass fractions of C4H6 and O2 are based on stoichiometric ratio. Furthermore, the
simulation configurations of this test case are in Table 20.
Table 20: Simulation configurations of the reacting pipe flow test case.
Configuration Parameter Setting

config.dimensions 2

config.axisymmetric true

config.stringent_cfl true

config.viscous false

config.turbulence_model none

config.udf_source_terms true

88
Configuration Parameter Setting

config.propagate_inflow_data true

config.flux_calculator adaptive

config.gasdynamic_update_scheme classic-rk3

config.max_time 5.0 × 10-5 s

config.dt_init 1.0 × 10-10 s

config.cfl_value 0.5

Lastly, there is a need to ignite the HTPB-oxygen mixture to initiate a combustion. The ignition
settings of this test case are in Table 16. For verification purpose, the steady-state spatial distribu-
tions of the temperature, static pressure and species mass fractions are plotted in the 𝑖-direction.

Methodology of the Verification Calculation


The verification calculation will involve the numerical spatial-integration of the linearised
conservation equations of mass, momentum and energy and the equation of state in the 𝑖-direction,
starting from the inlet of the reacting pipe. To linearise the conservation equations, the control
volume in Figure 23 is considered.

Figure 23: Control volume used in the linearisation of the conservation equations, adapted from [38].

The linearised conservation equations are only valid to describe a one-dimensional steady, reacting
and compressible flow. The equations can be written in the following matrix form [38]:
𝑣 𝜌 0 0
𝛿𝜌 0
0 𝜌𝑣 1 0
𝛿𝑣 −𝛿𝑝
𝑣𝐸 𝜌𝐸 + 𝑝 0 𝜌𝑣 ∙ 𝑐ℎ𝑒𝑚
𝛿𝑝𝑔𝑑𝑎 = [−𝜌𝑣𝛿𝑢𝑐ℎ𝑒𝑚 ] (148)
𝜕𝑓 𝜕𝑓
0 −1 [𝛿𝑢𝑔𝑑𝑎 ] 0
[ 𝜕𝜌 𝜕𝑢]
During the numerical spatial-integration, the axial coordinate will change from 𝑥 to 𝑥 + 𝛿𝑥. This
is equivalent to a flow travelling from 𝑥 to 𝑥 + 𝛿𝑥. The travelling time of the flow between 𝑥 to 𝑥

89
+ 𝛿𝑥 is equivalent to the chemistry time step (𝑑𝑡𝑐ℎ𝑒𝑚 ) to perform the numerical time-integration
of the species production rate of the chemistry kinetics. The equation of 𝑑𝑡𝑐ℎ𝑒𝑚 is:
𝑡𝑓𝑙𝑜𝑤
𝑑𝑡𝑐ℎ𝑒𝑚 = (149)
𝑁𝑠𝑝𝑎𝑐𝑒
where 𝑡𝑓𝑙𝑜𝑤 is defined as the travelling time of the supersonic inflow from the inlet to the outlet of
the reacting pipe and 𝑁𝑠𝑝𝑎𝑐𝑒 is defined as the number of discrete spaces between the inlet and outlet
of the reacting pipe. A discrete space is the region between 𝑥 and 𝑥 + 𝛿𝑥. The equation of 𝑡𝑓𝑙𝑜𝑤 is:
𝐿
𝑡𝑓𝑙𝑜𝑤 = (150)
(𝑣𝑖𝑛𝑓𝑙𝑜𝑤 + 𝑣𝑜𝑢𝑡𝑙𝑒𝑡 )⁄2
where 𝐿 is defined as the horizontal length of the reacting pipe (refer to Figure 21), 𝑣𝑖𝑛𝑓𝑙𝑜𝑤 is the
velocity of the supersonic inflow (refer to Table 19) and 𝑣𝑜𝑢𝑡𝑙𝑒𝑡 is the outlet velocity of the reacting
pipe flow. The value of 𝑣𝑜𝑢𝑡𝑙𝑒𝑡 can only be determined after the simulation in Eilmer 4 is
completed.

By integrating the species production rate of the chemistry kinetics (refer to Section 3.3.2) in time
by a time step of 𝑑𝑡𝑐ℎ𝑒𝑚 , the species concentrations and thus the equivalent species mass fractions
at 𝑥 + 𝛿𝑥 are determined. The new species mass fractions are then assigned to the flow state object
at 𝑥. By invoking the updateThermoFromRHOU method from the GasModel object [34], the flow
state object will be updated from the internal energy and gas-mixture density to determine the flow
state at 𝑥 + 𝛿𝑥.

Using the flow states at 𝑥 and 𝑥 + 𝛿𝑥, the values of 𝛿𝑝𝑐ℎ𝑒𝑚 and 𝛿𝑢𝑐ℎ𝑒𝑚 are calculated using the
following equations [38]:
𝛿𝑝𝑐ℎ𝑒𝑚 = 𝑝𝑥+𝛿𝑥 − 𝑝𝑥 (151)
𝛿𝑢𝑐ℎ𝑒𝑚 = 𝑢𝑥+𝛿𝑥 − 𝑢𝑥 (152)
Using the flow state at 𝑥, the derivatives 𝜕𝑓⁄𝜕𝜌 and 𝜕𝑓 ⁄𝜕𝑢 at 𝑥 are calculated using the finite-
difference scheme. With the values of 𝜕𝑓⁄𝜕𝜌, 𝜕𝑓 ⁄𝜕𝑢, 𝛿𝑝𝑐ℎ𝑒𝑚 and 𝛿𝑢𝑐ℎ𝑒𝑚 at 𝑥 known, the linear
matrix system in equation (148) is solved for the accommodation increment vector at 𝑥.
[𝛿𝜌 𝛿𝑣 𝛿𝑝𝑔𝑑𝑎 𝛿𝑢𝑔𝑑𝑎 ]𝑇 (153)
Equation (153) is then added to the flow state at 𝑥, which is [𝜌 𝑣 𝑝 𝑢]𝑇 . This addition leads
to the flow state at 𝑥 + 𝛿𝑥. Using the flow state at this position, the updateThermoFromRHOU
method from the GasModel object [34] is invoked again to determine the determine the temperature
90
at 𝑥 + 𝛿𝑥. Due to the linearity from 𝑥 to 𝑥 + 𝛿𝑥, the acceleration at this interval is constant. As a
result, the equation of 𝛿𝑥 is [38]:
𝑣𝑥+𝛿𝑥 + 𝑣𝑥
𝛿𝑥 = 𝑑𝑡𝑐ℎ𝑒𝑚 ( ) (154)
2
Once the simulation time reaches 𝑡𝑓𝑙𝑜𝑤 , the calculated spatial-distributions of the temperature,
static pressure and species mass fractions in the reacting pipe are used to verify the simulation
results of Eilmer 4.

5.2 Verification Test Case of the Isothermal Melt Layer Boundary


Condition
According to Section 4.4.1, the isothermal melt layer boundary condition was formulated based on
the first Stokes problem, which entails the creation of flow in the fluid domain by the translation
of a wall under the melt layer. Hence, the test case to verify this boundary condition should be the
first Stokes problem. To implement this test case in Eilmer 4, this section presents the required
geometry, blocking structure, mesh, boundary and initial conditions, simulation configurations and
the verification calculation methodology.

5.2.1 Melt Layer Properties


The isothermal melt layer boundary condition will be tested using the properties of paraffin wax
because it is a liquefying fuel. The properties of this fuel are tabulated in Table 21.
Table 21: Properties of paraffin wax [39].
Parameter Value
Species C24H50
-3
Density, 𝜌𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 (kg∙m ) 890.0
Dynamic viscosity at 343 K, 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 (Pa∙s) 0.090
Melting temperature, 𝑇𝑚 |𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 (K) 324.0

With the melt-layer modelling assumptions from Section 3.4 and 4.4.1, the properties of the
paraffin-wax-based melt layer will remain constant throughout the simulation.

91
5.2.2 Geometry
The geometry of the fluid domain to implement the first Stokes problem is a two-dimensional
rectangular domain. The dimensions of this domain are in Figure 24.

Figure 24: Dimensions of the fluid domain for the first Stokes problem.

5.2.3 Boundary and Initial Conditions, Blocking Structure, Meshing and


Simulation Configurations
The boundary conditions and blocking structure of the first Stokes problem are in Figure 25.

Figure 25: Boundary conditions of the first stokes problem.

The fluid domain of the first Stokes problem is discretised using a single block structured grid. The
mesh settings of the grid are in Table 22.

92
Table 22: Mesh settings of the first Stokes problem test case.
Block ID No. Cells in the 𝒊-direction (𝑵) No. Cells in the 𝒋-direction

0 20 20

The mesh is clustered to the south wall of the fluid domain such that the first-cell height (∆𝑦) is
7.55 × 10-6 m (or first-layer height of 1.51 × 10-5 m). To speed up the simulation, parallel processing
is required to break the grid of the main block into sub-blocks. The settings of the parallelisation
are in Table 23.
Table 23: Parallelisation settings of the fluid domain of the first Stokes problem test case.
Block ID No. sub-blocks in the 𝒊-direction (𝒏𝒊𝒃 ) No. sub-blocks in the 𝒋-direction (𝒏𝒋𝒃 )

0 6 9

The indexing system of the blocking structure is as per Figure 7. To achieve compatibility of the
isothermal melt layer boundary condition to parallel processing, all sub-blocks along this boundary
condition are grouped into the master MPI task, which has a rank of zero. The index of each sub-
block (𝑖𝑏 ) along this boundary condition is divisible by 𝑛𝑗𝑏 , which corresponds to 𝑖𝑏 = 0, 9, 18, 27,
36 and 45. According to Section 4.3.3, the grouping of the sub-blocks within this 𝑖𝑏 list into the
master MPI task is achievable using the mpiDistributeBlocks function [29].

Besides that, the initial conditions of the isothermal melt layer and fluid domain are in Table 24.
Table 24: Initial conditions of the isothermal melt layer and the fluid domain.
Domain
Parameter Initial Condition
Type
Fluid Temperature, T (K) 343 (corresp. temp. of 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 ; refer to Table 21)
Static pressure, p (atm) 1.0
Flow velocity (ms-1) 0.0
Mass fraction of O2, 𝑌𝑂2 1.0

Isothermal Gas-melt-layer interface 343 (corresp. temp. of 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 ; refer to Table 21)
melt layer temperature, 𝑇𝑚𝑠 (K)
Melt layer thickness, 𝛿 (m) 50 × 10-6
Mean velocity of the melt 0.0
̅ (ms-1)
layer, 𝑈
Melt-layer-solid interface 𝑥- -10.0
-1
velocity, 𝑢𝑠𝑢𝑟𝑓 (ms )

93
In Table 24, the melt layer surface temperature (𝑇𝑚𝑠 ) is set equal to the corresponding temperature
of the dynamic viscosity of the paraffin wax (𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 ) because 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 is one of the parameters
to compute the melt layer’s velocity profile (refer to equation (117)), top surface velocity (refer to
equation (141)) and wall shear stress (refer to equation (118)). Due to the isothermal condition, the
value of 𝑇𝑚𝑠 is uniform along the perimeter of the gas-melt-layer interface and constant throughout
the simulation.

Besides that, the thickness of the melt layer is set as 50 µm because the melt layer thickness range
of the paraffin wax fuel is around 50 - 100 µm [5]. Furthermore, the initial velocity of the fluid
̅) are set as zero so that the zero initial velocity
domain and the mean velocity of the melt layer (𝑈
condition of the first Stokes problem (refer to equation (116)) is satisfied. The velocity field of the
fluid domain and the mean velocity of the melt layer will change in the simulation due to the
movement of the melt-layer-solid interface.

The simulation configurations of this test case are in Table 25.


Table 25: Simulation configurations of the first Stokes problem test case.
Configuration Parameter Setting
config.dimensions 2
config.viscous true
config.turbulence_model none
config.flux_calculator ausm_plus_up
config.max_time 0.10 s
config.dt_init 1.0 × 10-9 s
config.fixed_time_step true
config.user_pad_length 10𝑁 (refer to Table 22 for 𝑁)

5.2.4 Methodology of the Verification Calculation


During the simulation of the first Stokes problem, the horizontal translation of the melt-layer-solid
interface will create flows within the melt layer and fluid domain. The flow in the melt layer is
driven by the wall shear stress difference between the gas-melt-layer and melt-layer-solid
interfaces. The 𝑥-velocity profile within the melt layer is quadratic in the wall-normal direction
(refer to equation (117)), where the reference coordinate system is on the melt-layer-solid interface
(refer to Section 3.4. This velocity profile determines the 𝑥-velocity of the gas-melt-layer interface

94
(refer to equation (141)). The 𝑥-velocity of this interface is different from that of the translating
melt-layer-solid interface.

There is a need to verify if the velocity difference between the gas-melt-layer and melt-layer-solid
interfaces (∆𝑢𝑥 ) is correct because it is an indication of the correctness of the implementation of
the quadratic velocity profile of the melt-layer and the numerical time-integration method. This
verification can be performed when the wall viscous shear stresses at the gas-melt-layer (𝜏𝑥𝑦 ; refer
to equation (97)) and melt-layer-solid (𝜏𝑤,𝑚 ; refer to equation (118)) interfaces are equal. The
mathematical form of this condition is:
𝜏𝑥𝑦 = 𝜏𝑤,𝑚 (155)
The expanded form of equation (155) is:
̅ − 𝑢𝑠𝑢𝑟𝑓 ) 𝜏𝑥𝑦
3(𝑈
𝜏𝑥𝑦 = 𝜏𝑤,𝑚 → 𝜏𝑥𝑦 = 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 − (156)
𝛿 2
Rearranging equation (156) in terms of 𝜏𝑥𝑦 gives:
̅ − 𝑢𝑠𝑢𝑟𝑓 )
(𝑈 ∆𝑢𝑥
𝜏𝑥𝑦 = 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 → 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 (157)
𝛿 ⁄2 𝛿
Equation (157) indicates that the 𝑥-velocity profile in the melt layer is linear. Further expansion of
equation (157) leads to:
∆𝑢𝑥 𝜕𝑢𝑥 𝜕𝑢𝑦 ∆𝑢𝑥
𝜏𝑥𝑦 = 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 → 𝜇𝑦=0+ ( | + | ) = 𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 (158)
𝛿 𝜕𝑦 𝑦=0 𝜕𝑥 𝑦=0 𝛿

As the verification objective is to check the correctness of ∆𝑢𝑥 , equation (158) is rearranged in
terms of ∆𝑢𝑥 , giving [44]:
𝜇𝑦=0+ 𝜕𝑢𝑥 𝜕𝑢𝑦
∆𝑢𝑥 = 𝛿 ∙ ( )∙( | + | ) (159)
𝜇𝑝𝑎𝑟𝑎𝑓𝑓𝑖𝑛 𝜕𝑦 𝑦=0 𝜕𝑥 𝑦=0

In the simulation, the isothermal melt layer boundary condition will save the spatial distributions
of 𝛿 and the 𝑥-velocity of the gas-melt-layer interface as two separate output text files at each
instant. In the verification process, the LHS of equation (159) is computed by subtracting the output
𝑥-velocity of the gas-melt-layer interface with the 𝑥-velocity of the translating melt-layer-solid
interface, whereas the RHS of equation (159) is computed using the flow field data of the fluid
domain. Both LHS and RHS of this equation should be equal if the implementation of the
isothermal melt layer boundary condition is correct.

95
5.3 Main Test Case
According to Section 1.1, this work entails the numerical simulation of the internal combustion
ballistics of an HTPB fuel (non-liquefying fuel) and pure oxygen in a two-dimensional slab hybrid
rocket motor (HRM) in Eilmer 4. Inline to this aim, the work from Gariani et al. will be the main
test case for this work. More information about their work is in [1]. This test case will be
implemented in Eilmer 4 to simulate the following cases:
• Pure fuel injection.
• Combustion with injection cases.
As this work is a preliminary attempt to simulate the internal combustion ballistics of HRM in
Eilmer 4, simplifications are required. In this work, the following simplifications are made:
• Neglect the thermal radiation effect.
• Exclude turbulence modelling.
The simulations will neglect the thermal radiation effect in the fluid domain because the local
divergence of radiation source term (refer to equation (147)) is essentially an energy sink term due
to the absence of the incident radiation term to counterbalance the energy loss.
On the other hand, the exclusion of turbulence modelling is not always a valid simplification
because the internal flow field of the slab HRM can be turbulent. However, this simplification is
important because it can improve the simulation speed and reduce the number of factors that can
influence the behaviour of the simulated flow, thus making the development of the HRM
simulation capability easier.

To implement this test case in Eilmer 4, the remaining subsections of this section will present the
required geometry, block structure, meshing, boundary and initial conditions and the simulation
configurations.

96
5.3.1 Geometry
The geometry of the slab HRM is a two-dimensional (2D) rectangular domain. The main dimen-
sions of this domain are in Figure 26.

Figure 26: Geometry of the 2D slab HRM, adapted from [1].

The coordinates of each point in Figure 26 are in Table 25.


Table 26: Coordinates of all the points that define the 2D slab HRM geometry.
Coordinates
Point 𝒙 (mm) 𝒚 (mm)
A 0.0 0.0
B -0.076 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.0
C -𝐿𝑖𝑛𝑙𝑒𝑡 0.0
D -𝐿𝑖𝑛𝑙𝑒𝑡 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
E -0.076 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
F 0.0 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
G 𝐿𝑓𝑢𝑒𝑙 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
H 0.924 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
I 0.924 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.0
J 𝐿𝑓𝑢𝑒𝑙 0.0

97
5.3.2 Blocking Structure and Meshing
The fluid domain of the 2D slab HRM is discretised using a multi-block structured grid, where the
blocking structure is as illustrated in Figure 27.

Figure 27: Blocking structure of the fluid domain of the 2D slab HRM.

The coordinate of each internal grid point of the fluid domain is in Table 27.
Table 27: Coordinates of all the internal grid points of the fluid domain of the 2D slab HRM.
Coordinates
Point 𝒙 (mm) 𝒚 (mm)
M1 0.0 0.0774
M2 -0.076 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.0774
M3 -𝐿𝑖𝑛𝑙𝑒𝑡 0.0774
M4 -𝐿𝑖𝑛𝑙𝑒𝑡 0.5 × 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
M5 -0.076 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.5 × 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
M6 0.0 0.5 × 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
M7 𝐿𝑓𝑢𝑒𝑙 0.5 × 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
M8 0.924 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.5 × 𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟
M9 0.924 × 𝐿𝑐ℎ𝑎𝑚𝑏𝑒𝑟 0.0774
M10 𝐿𝑓𝑢𝑒𝑙 0.0774

According to Figure 27, the blocking structure of the fluid domain has three rows of main blocks.
The advantage of this structure is that the top and bottom walls of the fluid domain can have
different clustering options. Besides that, this blocking structure also separates block 𝑖𝑏 = 6 from
the rest of the main blocks. In parallel processing, this blocking characteristic allows all sub-blocks
in this block to be assigned to the master MPI task, while the sub-blocks in other main blocks are
running on separate processors. These operations are performed only when the boundary condition
at block 𝑖𝑏 = 6 – AJ (South) requires special treatment to achieve compatibility with the MPI-

98
parallel simulations, such as the isothermal melt layer boundary condition or the loosely coupled
fluid-solid heat transfer mechanism. On the other hand, the mesh settings of each main block of
the fluid domain are in Table 28.
Table 28: Mesh settings of the main block of the fluid domain of the 2D slab HRM.
Block ID No. Cells in the 𝒊-direction (𝑵) No. Cells in the 𝒋-direction
0 7 6
1 7 20
2 7 21
3 30 6
4 30 20
5 30 21
6 133 6
7 133 20
8 133 21
9 181 6
10 181 20
11 181 21

The fuel surface, leading and trailing edges of the fuel surface and the top and bottom walls of the
2D slab HRM are high-gradient regions. To resolve these regions accurately and to achieve mesh
smoothness, mesh clustering is required. The mesh is clustered to the north wall (edge DH) of the
fluid domain such that the first-cell height (∆𝑦) from this wall is equal to 1.425 × 10-5 m (or first-
layer height of 2.85 × 10-5 m), which corresponds to a non-dimensional wall distance (𝑦 + ) of
approximately 0.10. By the law of the wall, this 𝑦 + value corresponds to the viscous sublayer.
Besides that, the mesh is clustered to the fuel surface’s leading edge (edge AF) and trailing edge
(edge JG) such that the aspect ratios of the first cell adjacent to these edges and the grid smoothness
ratio are approximately equal to 1.0.

Furthermore, the mesh of each main block along the south wall (edge CI) of the fluid domain (e.g.
𝑖𝑏 = 0, 3, 6 and 9) is not clustered to this wall because these blocks are essentially an inflation layer
which has a thickness of 6 fluid-cells with identical heights. The ∆𝑦 value of these blocks is 6.45
× 10-6 m (or first-layer height of 1.29 × 10-5 m), which corresponds to a 𝑦 + value of approximately
0.05 (refer to Section 6.3.3 for the justification). By the law of the wall, this 𝑦 + value corresponds
to the viscous sublayer.

99
Figure 28 illustrates the mesh of the fluid domain of the 2D slab HRM.

Figure 28: Actual mesh of the fluid domain of the 2D slab HRM.

5.3.3 Boundary and Initial Conditions


The boundary conditions are assigned to the fluid domain of the 2D slab HRM as per the annotated
block edges in Figure 27. All boundary conditions are listed in Table 29.
Table 29: Fluid domain boundary conditions of the fluid domain of the 2D slab HRM.
Block Boundary Condition
Block Edge Condition
ID (Eilmer 4)
0 CB (South) WallBC_WithSlip • No penetration.
• Flow tangency.
CM3 (West) InFlowBC_FromStagnation • Inlet static pressure, 𝑝𝑖𝑛𝑙𝑒𝑡 = 1.0 atm.
• Inlet temperature, 𝑇𝑖𝑛𝑙𝑒𝑡 = 900.0 K.
• Inlet velocity, 𝑢𝑥 |𝑖𝑛𝑙𝑒𝑡 = 6.0 ms-1.
• Fixed inlet mass flux.
• Relaxation factor, relax_factor = 0.001
(refer to Section 6.3.5).
• Mass fraction of oxygen, 𝑌𝑜2 = 1.0
(Pure oxygen inflow).
1 M3M4 (West) InFlowBC_FromStagnation • Same as block 𝑖𝑏 = 0 – CM3 (West).

2 M4D (West) InFlowBC_FromStagnation • Same as block 𝑖𝑏 = 0 – CM3 (West).


DE (North) WallBC_WithSlip • Same as block 𝑖𝑏 = 0 – CB (South).

3 BA (South) WallBC_WithSlip • Same as block 𝑖𝑏 = 0 – CB (South).

100
Block Boundary Condition
Block Edge Condition
ID (Eilmer 4)
5 EF (North) WallBC_NoSlip_FixedT • No-slip.
• No penetration.
• Wall temperature, 𝑇𝑤𝑎𝑙𝑙 = 900 K.
6 AJ (South) UserDefinedFluxBC • Wall temperature, 𝑇𝑤𝑎𝑙𝑙 = 675 K
• Fuel pyrolysis boundary condition
(Filename = ‘../udf/udf-GSI-FluxBC.lua’).
8 FG (North) WallBC_NoSlip_FixedT • Same as block 𝑖𝑏 = 5 – EF (North).

9 IM9 (East) OutFlowBC_FixedP • Zero Neumann condition for all flow


variables, except pressure.
• Outlet pressure, 𝑝𝑜𝑢𝑡𝑙𝑒𝑡 = 1.0 atm.
JI (South) WallBC_WithSlip • Same as block 𝑖𝑏 = 0 – CB (South).

10 M9M8 (East) OutFlowBC_FixedP • Same as block 𝑖𝑏 = 9 – IM9 (East).

11 M8H (East) OutFlowBC_FixedP • Same as block 𝑖𝑏 = 9 – IM9 (East).

GH (North) WallBC_NoSlip_FixedT • Same as block 𝑖𝑏 = 5 – EF (North).

Besides that, the initial conditions of the fluid domain of the 2D slab HRM are in Table 30.
Table 30: Initial conditions of the fluid domain of the 2D slab HRM.

Domain Type Parameter Initial Condition

Fluid Temperature, T (K) 300


Static pressure, p (atm) 1.0
-1
Flow velocity in the 𝑥-direction, 𝑢𝑥 (ms ) 6.0
Mass fraction of O2, 𝑌𝑂2 1.0

In Table 29, stagnation inlet and fixed pressure outlet boundary conditions are chosen because they
are suitable to simulate subsonic flow, which is relevant to the current test case because the
prescribed inlet velocity of the fluid domain is only 6 ms-1. Besides that, fixed inlet mass flux
condition is applied to activate the feedback mechanism inherent to the InFlowBC_FromStag-
nation boundary condition in Eilmer 4. This feedback mechanism is required to dampen the
pressure wave oscillations between the inlet and outlet of the fluid domain. The rate of convergence
of this feedback mechanism is governed by the relaxation factor (relax_factor) [29], which is

101
prescribed to be 0.001 because prior testing showed that this value gives a smooth oscillatory
dampening effect within reasonable flow time (approximately 50 ms).

When setting up the stagnation inlet boundary condition (or InFlowBC_FromStagnation), the
required stagnation conditions at the inlet should be calculated using the corresponding entropy
and enthalpy of the desired inflow conditions [44]. This approach eliminates the possibility of
entropy jump condition at the inlet, which can cause pressure fluctuations. The first step to
implement this approach involves creating an inlet state object. This state object is assigned with
the desired inflow conditions (refer to Table 29). Following this, invoke the pertinent GasModel
methods to update the inlet state object to determine the inflow enthalpy (ℎ𝑖𝑛𝑙𝑒𝑡 ) and entropy
(𝑠𝑖𝑛𝑙𝑒𝑡 ). The stagnation enthalpy (ℎ𝑠𝑡𝑎𝑔 ) is then calculated using the following equation:
𝑢𝑥 |2𝑖𝑛𝑙𝑒𝑡
ℎ𝑠𝑡𝑎𝑔 = ℎ𝑖𝑛𝑙𝑒𝑡 + (160)
2
On the other hand, a stagnation state object is created. This state object is assigned with the desired
initial conditions of the fluid domain (refer to Table 30) as an initial guess of the stagnation
conditions. By updating the stagnation state object using the updateThermoFromHS method [34]
in conjunction with the values of ℎ𝑠𝑡𝑎𝑔 and 𝑠𝑖𝑛𝑙𝑒𝑡 , the stagnation conditions at the inlet are
calculated.

5.3.4 Simulation Configurations


The simulation configurations of this test case are in Table 25.
Table 31: Simulation configurations of the fluid domain of the 2D slab HRM.
Configuration Parameter Setting
config.dimensions 2
config.viscous true
config.turbulence_model none
config.flux_calculator ausm_plus_up
config.max_time 4.5 × 10-3 s
config.dt_init 1.0 × 10-12 s
config.cfl_value 0.2
config.udf_source_terms False (Set as true when there is combustion)
config.udf_source_terms_file ‘../udf/udf-HTPB-Oxygen-Reaction-Radiation.lua’

102
For parallel simulations with high-performance computing, the required parallelisation settings are
in Table 32. As a result of these settings, there are 72 sub-blocks in total in the fluid domain.
Table 32: Parallelisation settings of the fluid domain of the 2D slab HRM.
Block ID No. sub-blocks in the 𝒊-direction (𝒏𝒊𝒃 ) No. sub-blocks in the 𝒋-direction (𝒏𝒋𝒃 )

0 2 1

1 2 2

2 2 3

3 1 1

4 1 2

5 1 3

6 3 1

7 3 2

8 3 3

9 6 1

10 6 2

11 6 3

For the combustion with injection case, the HTPB fuel injected by the fuel pyrolysis boundary
condition and the pure oxygen inflow must be ignited. The ignition settings for this case are in
Table 33.
Table 33: Ignition settings of the combustion with injection case of the 2D slab HRM.
Ignition Parameter Setting
Ignition temperature, 𝑇𝑖𝑔𝑛 (K) 1500
Ignition start time, 𝑡𝑖𝑔𝑛,𝑠𝑡𝑎𝑟𝑡 (s) 0.0
Ignition end time, 𝑡𝑖𝑔𝑛,𝑒𝑛𝑑 (s) 0.001 × config.max_time
Start of ignition region, 𝑥𝑖𝑔𝑛,𝑠𝑡𝑎𝑟𝑡 (m) 0.0
End of ignition region, 𝑥𝑖𝑔𝑛,𝑒𝑛𝑑 (m) 0.05 × 𝐿𝑓𝑢𝑒𝑙

The ignition settings in Table 33 are only applicable when the fuel-rich layer is already established.
Besides that, the ignition region is confined to a small region around the leading edge of the fuel
surface only. Prior testing showed that if the ignition region is too big, it will lead to a fuel explosion
event in the fluid domain. In this event, the flame will propagate at high speed in both upstream
and downstream directions. As a result, it will destroy the low-speed flow field (𝑢𝑥 |𝑖𝑛𝑙𝑒𝑡 = 6 ms-1)
in the fluid domain.

103
Chapter 6

Results and Discussions

This section will present and discuss the results of the verification test cases of the chemistry
kinetics and melt-layer boundary condition and the simulation results of the internal combustion
ballistics of a two-dimensional (2D) slab hybrid rocket motor (HRM).

6.1 Verification Results of the Chemistry Kinetics


This section presents the verification results of the constant volume reactor and reacting pipe flow
test cases. The simulation results of both test cases agree well with the verification calculation
results, implying that the chemistry kinetics of HTPB-oxygen combustion was implemented
correctly.

6.1.1 Verification Results of the Constant Volume Reactor Test Case


Figure 29 and Figure 30 compare the transient simulation and calculation results of the constant
volume reactor test case. Details about the setup and verification methodology of this test case are
in Section 5.1.1.

104
(a) (b)
Figure 29: Comparing Eilmer 4 simulation and calculation results of the transient profile of (a) Static
pressure; (b) Temperature in a constant volume reactor.

(a) (b)

(c) (d)

105
(e)
Figure 30: Comparing Eilmer 4 simulation and calculation results of the transient profile of (a) Mass
fraction of C4H6; (b) Mass fraction of CO; (c) Mass fraction of CO2; (d) Mass fraction of H2O; (e) Mass
fraction of O2 in a constant volume reactor.

From both Figure 29 and Figure 30, the simulation results of Eilmer 4 and the verification
calculation results have excellent agreement.

6.1.2 Verification Results of the Reacting Pipe Flow Test Case


Figure 31 and Figure 32 compare the transient simulation and calculation results of the reacting
pipe flow test case. Details about the setup and verification methodology of this test case are in
Section 5.1.2.

(a) (b)
Figure 31: Comparing Eilmer 4 simulation and calculation results of the spatial distribution of (a) Static
pressure; (b) Temperature in a reacting pipe.

106
(a) (b)

(c) (d)

(e)
Figure 32: Comparing Eilmer 4 simulation and calculation results of the spatial distribution of (a) Mass
fraction of C4H6; (b) Mass fraction of CO; (c) Mass fraction of CO2; (d) Mass fraction of H2O; (e) Mass
fraction of O2 in a reacting pipe.

From both Figure 31 and Figure 32, the simulation results of Eilmer 4 and the verification
calculation results have excellent agreement.
107
6.2 Verification Results of the Isothermal Melt Layer Boundary
Condition
As per the simulation configurations from Table 25, the verification test of the isothermal melt
layer boundary condition is expected to run for a simulation time (𝑡) of 100.0 ms. However, the
simulation was stopped at 𝑡 = 35.7 ms because the maximum wall-clock time of the simulation was
reached. Nevertheless, the simulation time at which the simulation was stopped is still long enough
to capture the transient behaviours of the fluid domain and melt layer. Hence, this work will analyse
the intermediate simulation results from 𝑡 = 0.0 ms to 35.7 ms.
The isothermal melt layer boundary condition was tested using the first Stokes problem. Hence,
the flows within the melt layer and fluid domain were created by the horizontal translation of the
melt-layer-solid interface. Figure 33 shows the simulation results of the first Stokes problem at 𝑡 =
35.7 ms.

Figure 33: The 𝑥-velocity flow field and vectors of the first Stokes problem test case.

108
Figure 34 illustrates the transient behaviour of the wall-normal 𝑥-velocity profile in the fluid
domain from the start to end of the simulation under the presence of melt layer effect. The axial
location of this velocity profile is at the midpoint of the horizontal domain length, which
corresponds to the origin of the global cartesian coordinate system (refer to Figure 24).

Figure 34: Transient wall-normal 𝑥-velocity profile in the fluid domain (with melt layer effect).

In Figure 34, the gas-melt-layer interface is at 𝑦⁄𝐻 = 0.0, whereas the symmetry plane with the
mirror image condition is at 𝑦⁄𝐻 = 1.0. When 𝑡 = 0.0 ms, the wall-normal 𝑥-velocity profile is a
flat line spanning from 𝑦⁄𝐻 = 0.0 to 1.0 at 𝑢𝑥 ⁄|𝑢𝑠𝑢𝑟𝑓 | = 0.0. This implies that the flow field in the
fluid domain is stationary. When 𝑡 > 0.0 ms, the horizontal translation of the melt-layer-solid
interface creates a velocity gradient within the melt layer. Due to the velocity gradient, viscous
wall shear stress arises at the bottom of the melt layer. The presence of wall shear stress will create
a flow within the melt layer because the momentum source term (refer to equation (69)) of the
momentum conservation equation of the thin-film model is non-zero.

Eventually, a velocity profile is established in the melt layer (refer to equation (117)). This velocity
profile determines the horizontal translation velocity of the gas-melt-layer interface (refer to
equation (141)). As the flow field in the fluid domain is subject to the no-slip condition at the gas-
melt-layer interface, the translation of this interface will accelerate the fluid near it. This explains

109
why the flow field in the fluid domain has a wall-normal 𝑥-velocity profile with a steep velocity
gradient when 𝑦⁄𝐻 < 0.10 and at 𝑡 = 1.25 ms.

As the value of 𝑡 continues to increase, shear stress between the adjacent fluid layers leads to the
acceleration of the top fluid layer. Eventually, the wall-normal velocity profile of the flow field in
the fluid domain will converge to the steady-state solution of a Couette flow, which is a linear
velocity profile. Although the wall-normal 𝑥-velocity profiles in Figure 34 are not completely
linear, the trend of the time evolution of these velocity profiles suggests that the wall-normal 𝑥-
velocity profile in the fluid domain will eventually become linear if the simulation time is
sufficiently long.

At every instant of the simulation, the isothermal melt layer boundary condition will output the
properties of the melt layer. When the simulation stopped at 𝑡 = 35.7 ms, the corresponding melt
layer properties are tabulated in Table 34.
Table 34: Isothermal Melt Layer Properties at the time where the simulation stopped.
Parameter Value
Time, 𝑡 (ms) 35.7
Film height, 𝛿 (µm) 50.0
Melt-layer-solid interface velocity, 𝑢𝑠𝑢𝑟𝑓 (m/s) -10.0
̅ (m/s)
Average film velocity, 𝑈 -9.999952700
Gas-melt-layer interface velocity, 𝑢𝑥 | 𝑦𝑙=𝛿 (m/s) -9.999904343
Velocity difference between the gas-melt-layer and melt-
9.56570 × 10-5
layer-solid interfaces, ∆𝑢𝑥 (ms-1)
Wall-tangential shear stress at the gas-melt-layer
0.172168849
interface, 𝜏𝑥𝑦 (Pa)
Wall-tangential shear stress at the melt-layer-solid
0.172197820
interface, 𝜏𝑤,𝑚 (Pa)
Absolute percentage difference between the surface and
0.0168
bottom shear, %∆𝜏 (%)

In Table 34, the value of %∆𝜏 is very small such that it can be assumed as negligible. Hence, this
implies that both 𝜏𝑥𝑦 and 𝜏𝑤,𝑚 are approximately equal. With this condition, the verification
methodology from Section 5.2.4 is applicable because it is formulated using this condition. This
methodology entails checking if the value of ∆𝑢𝑥 in Table 34 matches the RHS of equation (159).
110
To begin with the validation, the spatial derivatives of velocity in the RHS of equation (159) (which
are the 𝜕𝑢𝑥 ⁄𝜕𝑦|𝑦=0 and 𝜕𝑢𝑦 ⁄𝜕𝑥|𝑦=0 terms) must be calculated. The 𝜕𝑢𝑥 ⁄𝜕𝑦|𝑦=0 term is

calculated using the linear portion of the wall-normal 𝑥-velocity profile in the fluid domain.

Figure 35 illustrates the selected data point on the linear portion of the wall-normal 𝑥-velocity
profile to calculate the 𝜕𝑢𝑥 ⁄𝜕𝑦|𝑦=0 term.

Figure 35: Wall-normal 𝑥-velocity profile in the fluid domain (with melt layer effect) at 𝑡 = 35.7 ms.

Using the first-order one-sided finite difference scheme in conjunction with the selected data point
in Figure 35, the values of 𝑢𝑠𝑢𝑟𝑓 and 𝑢𝑥 | 𝑦𝑙=𝛿 in Table 34 and the domain dimensions in Figure 24
to calculate the 𝜕𝑢𝑥 ⁄𝜕𝑦|𝑦=0 term, it follows that:

𝜕𝑢𝑥 (𝑢𝑥 ⁄|𝑢𝑠𝑢𝑟𝑓 |) ∙ 𝑢𝑠𝑢𝑟𝑓 − 𝑢𝑥 | 𝑦𝑙=𝛿


| = (161)
𝜕𝑦 𝑦=0 (𝑦⁄𝐻 ) ∙ 𝐻

𝜕𝑢𝑥 −0.772680 ∙ |10| − (−9.999904343)


∴ | = = 7403.04 (162)
𝜕𝑦 𝑦=0 0.061410 ∙ 5 ∙ 10−3

Besides that, as the isothermal melt layer boundary condition is subject to no-slip condition, the 𝑦-
velocity on the gas-melt-layer interface is always zero. Hence, it follows that the value of
𝜕𝑢𝑦 ⁄𝜕𝑥|𝑦=0 will also be zero. Furthermore, the dynamic viscosity of the fluid at the centre of the

fluid-cell adjacent to the gas-melt-layer interface (𝜇𝑦=0+ ) was determined to equal to 2.304 × 10-5
Pa∙s from the simulated flow field in Eilmer 4.

111
Using the paraffin wax fuel properties from Table 21 in conjunction with the preceding calculation
results, it follows that the RHS of equation (159) is:
2.304 ∙ 10−5
𝑅𝐻𝑆 = 50 ∙ 10−6 ∙ ( ) ∙ (7403.04 + 0.0) = 9.47589 × 10−5 (163)
0.090
The percentage difference between the value of ∆𝑢𝑥 in Table 34 and the value of 𝑅𝐻𝑆
(%∆𝐿𝐻𝑆−𝑅𝐻𝑆 ) is calculated below as:
∆𝑢𝑥 − 𝑅𝐻𝑆 (9.56570 − 9.47589) ∙ 10−5
%∆𝐿𝐻𝑆−𝑅𝐻𝑆 = ∙ 100 = [ ] ∙ 100 = 0.9478% (164)
𝑅𝐻𝑆 9.47589 ∙ 10−5
As the value of %∆𝐿𝐻𝑆−𝑅𝐻𝑆 is small, it implies that the isothermal melt layer boundary condition
was implemented correctly.

112
6.3 Results of the Main Test Case
This section presents the results of the numerical simulations of the internal combustion ballistics
of a two-dimensional (2D) slab hybrid rocket motor (HRM) in Eilmer 4. Two cases were simulated,
including pure injection and combustion with injection cases.

6.3.1 Simulation Methodology


A practical simulation methodology was developed in the process of simulating the internal
combustion ballistics of a 2D slab HRM in Eilmer 4. The steps of this methodology are in the
following order:
1. Run a high-speed flow simulation in the fluid domain of the 2D slab HRM until reaching
steady-state, without the presence of injection and combustion.
2. Load the high-speed flow field solution from step 1 as the initial condition of the 2D slab
HRM. Then, reduce the inlet stagnation pressure to reduce the pressure difference between
the inlet and outlet. As a result, the velocity of the flow field will decrease and eventually
reaches the desired low-speed (subsonic) conditions.
3. Load the low-speed (subsonic) flow field from step 2 as the initial condition of the pure
fuel injection case, which corresponds to the fuel pyrolysis process.
4. Load the flow field of the injection case as the initial condition of the combustion with the
injection case.
The notion of steps 1 and 2 is to bypass the unphysical flow issues of running low speed (subsonic)
flows directly in Eilmer 4 by deriving the low-speed flow solution from the high-speed flow
solution.

6.3.2 Deriving Low-Speed Flow Solution from High-Speed Flow Solution


The high-speed flow solution is derived by running a high-speed simulation without injection and
combustion. To set up a simulation without injection, the fuel pyrolysis boundary condition of the
fluid domain of the complete 2D slab HRM is replaced with Eilmer 4’s fixed temperature and no-
slip boundary conditions. All other boundary and initial conditions are as per Table 29, except that
the inlet and initial pressures are set as 1.3 atm. With this setup, there is a pressure difference of
0.3 atm between the inlet pressure and the atmospheric pressure condition at the outlet. This
pressure difference is large enough to create a high-speed flow within the fluid domain.

113
Using the high-speed flow field, set the inlet pressure and inlet velocity of the complete 2D slab
HRM to 1.0 atm and 6 ms-1, respectively. Then, use the entropy matching method (refer to Section
5.3.3) to calculate the corres-ponding stagnation properties. Following this, simulate at least a 100.0
ms of simulation time until the speed of the flow field has reduced to the desired condition.

6.3.3 Non-Dimensional Wall Distance (Y+) Convergence Study


The convergence study of the non-dimensional wall distance (𝑦 + ) aims to determine the first-cell
height (∆𝑦) of the mesh. The objective of this study is to check the degree of agreement between
the computed skin friction coefficient (𝑐𝑓 ) distribution at the given 𝑦 + value with that of the Blasius
solution. The 𝑦 + convergence study is based on a wall that is subject to isothermal and no-slip
boundary conditions. From the chosen 𝑦 + value in this study, the value of ∆𝑦 determined will be
the first-cell height of the fuel pyrolysis boundary condition.
The original geometry of the 2D slab HRM (refer to Figure 26) is truncated by only considering
the main blocks below the mid-height symmetry plane and by removing the pre-entrance (block
CDEB) and downstream blocks (block JGHI). The purpose is to reduce the computational expense
and thus improve the speed of the 𝑦 + convergence study. The boundary conditions and dimensions
of the truncated geometry are in Figure 23.

Figure 36: Boundary conditions and dimensions of the truncated 2D slab HRM (for 𝑦 + convergence
study).

The set-up method of the inlet and outlet boundary conditions is as per Section 5.3.3. Besides that,
the initial condition in the fluid domain of the truncated 2D slab HRM is the low-speed flow field
solution determined earlier. Figure 37 shows the mesh and initial velocity flow field of the fluid
domain in this convergence study.

114
Figure 37: Mesh and initial velocity flow field of the truncated 2D slab HRM (for 𝑦 + convergence study).

To compare the spatial distribution of 𝑐𝑓 for different 𝑦 + values, the steps that were followed are:
1. Select at least three 𝑦 + values.
2. At the given 𝑦 + value, simulate 25.0 ms of simulation time.
3. Repeat step 1 to 2 for all the remaining 𝑦 + values.
4. Plot the corresponding spatial distribution of 𝑐𝑓 for each 𝑦 + value and the Blasius solution
for the spatial distribution of 𝑐𝑓 in the same graph (refer to Figure 38).
Figure 38 compares the spatial distribution of 𝑐𝑓 for each 𝑦 + value with that of the Blasius solution.

Figure 38: Skin friction coefficient distribution along the fuel surface at different y+ values.

115
In Figure 38, it is clear that the spatial distribution of 𝑐𝑓 at 𝑦 + value of 0.03 agrees well with the
Blasius solution, although it is subject to noise. Besides that, the spatial distribution of 𝑐𝑓 at other
𝑦 + values generally agree closely with each other and to the Blasius solution when the axial
distance from the leading edge of the fuel surface (𝑥) is more than 6 mm.
When 𝑥 is less than 6 mm, it is noticeable the corresponding spatial distribution of 𝑐𝑓 of all 𝑦 +
values above 0.03 has a region where the values of 𝑐𝑓 drop suddenly and deviates from the Blasius
solution significantly. By observation, the width of the sudden-drop region of 𝑐𝑓 increases with the
𝑦 + value (from 𝑦 + = 0.05 to 0.20). The cause of the sudden-drop in 𝑐𝑓 is the velocity jump condition
when the flow experience a transition from the slip wall to the isothermal no-slip wall boundary
condition at the vicinity of the leading edge of the fuel surface (refer to Figure 36).

Figure 39: Velocity jump condition at the leading edge, when 𝑦 + = 0.20.

Figure 40: Velocity jump condition at the leading edge, when 𝑦 + = 0.03.

116
For the 𝑦 + = 0.20 case in Figure 39, it is noticeable that the 𝑥-velocity of the flow increases
suddenly from approximately 5.5 ms-1 to 12.0 ms-1 in front of the leading edge. Then, the 𝑥-velocity
of the flow drops steeply and overshoots to a negative value before climbing back again to satisfy
the no-slip condition. As the value of 𝑐𝑓 is proportional 𝑥-velocity of the flow (assuming the wall-
normal gradient of the 𝑥-velocity is computed using the one-sided finite difference scheme), the
spatial distribution of 𝑐𝑓 will follow the trend of the 𝑥-velocity of the flow. As a result, this gives
rise to the sudden-drop region of 𝑐𝑓 in Figure 38.

By the same principle, the spatial distribution of 𝑐𝑓 at 𝑦 + value of 0.03 does not have a sudden drop
region because Figure 40 shows that the 𝑥-velocity of the flow at this 𝑦 + value drops smoothly to
zero and does not overshoot to satisfy the no-slip condition at the fuel surface, after flowing across
the leading edge.

In conclusion, the final verdict is to use a 𝑦 + value of 0.05 because Figure 38 indicates that the
width of its sudden-drop region of 𝑐𝑓 is very small and does not affect the majority of the near-wall
flow downstream the leading edge. Besides that, its spatial distribution of 𝑐𝑓 has excellent
agreement with that of a 𝑦 + value of 0.03. Moreover, it will lead to a faster simulation speed than
using a 𝑦 + value of 0.03.

6.3.4 Results of Pure Injection Case with a Truncated Downstream Region


In the preliminary attempt to simulate the injection of fuel into the oxidiser stream, the downstream
region of the 2D slab HRM geometry was shortened to reduce the computational expense and to
increase the simulation speed. Besides that, the initial condition in the fluid domain of the 2D slab
HRM is the low-speed flow field solution determined earlier. The set-up method of the boundary
conditions of the shortened 2D slab HRM geometry is also as per Section 5.3.3, except that the
inlet mass flux and the pressure relaxation factor (or relax_factor) were not specified due to the
lack of knowledge about their significance. Furthermore, the selected 𝑦 + values of the top and
bottom wall of the 2D slab HRM were equal to 0.05 (refer to Section 6.3.3 for the justification).

117
Figure 41: Dimensions of the shortened 2D slab HRM.

The pure injection case was run for a simulation time of 100.0 ms. The following figures the time
evolution of the fuel injection process:

Figure 42: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure injection
case) at t = 20.0 ms.

Figure 43: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure injection
case) at t = 40.0 ms.

118
Figure 44: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure injection
case) at t = 60.0 ms.

Figure 45: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure injection
case) at t = 80.0 ms.

Figure 46: Mass fraction of C4H6 and velocity vectors within the shortened 2D slab HRM (pure injection
case) at t = 100.0 ms.

119
When the simulation time is at 100.0 ms, the temperature, pressure and velocity field of the fluid
domain of the shortened 2D slab HRM are as follows:

Figure 47: Temperature field within the shortened 2D slab HRM (pure injection case) at t = 100.0 ms.

Figure 48: Pressure field within the shortened 2D slab HRM (pure injection case) at t = 100.0 ms.

Figure 49: Velocity field within the shortened 2D slab HRM (pure injection case) at t = 100.0 ms.

120
From Figure 42 to Figure 46, the velocity vectors of the flow field are pointing to the right. This is
the correct flow direction because the gaseous oxygen is expected to flow from the inlet to outlet.
Besides that, it is noticeable that the velocity vectors along the perimeter of the fuel surface are
pointing upwards and to the right. This is the correct flow direction because the HTPB-fuel injected
by the fuel pyrolysis boundary condition (refer to Section 4.2) will be blown to the right by the
freestream gaseous oxygen flow. Furthermore, Figure 47 indicates that the temperature of the fuel-
rich layer near the fuel surface is in the range of 675 – 720 K. This is the correct temperature range
because the fuel surface is subject to an isothermal condition at 675 K (refer to Table 29). Hence,
the injected fuel will be at this temperature. The injected fuel will then be heat up by the hotter
gaseous oxygen flow, which has a temperature of 900 K (refer to Table 29).

From Figure 42 to Figure 46, it is also noticeable that the interface between the gaseous oxygen
and fuel-rich layer exhibits wavy characteristics during the time-evolution of the fuel-rich layer.
Further analysis indicated that the wavy characteristics were instabilities induced by the pressure
fluctuations of the gaseous oxygen flow. Figure 50 shows the inlet pressure history of the shortened
2D slab HRM.

Figure 50: Inlet pressure history of the pure injection case (without pressure relaxation factor at the inlet).

121
In Figure 50, the inlet pressure eventually reached a steady-state with fluctuations about a mean
value, starting from approximately 40 ms. These pressure fluctuations are a result of the pressure
wave oscillations between the inlet and outlet of the shortened 2D slab HRM and is an unphysical
effect. Hence, there is a need to damp out these pressure fluctuations to eliminate flow disturbances
that can destabilise the fuel-rich layer.

6.3.5 Pressure Relaxation Factor


The pressure waves oscillations in the fluid domain lead to flow disturbances, which destabilise
the fuel-rich layer. To damp out the pressure wave oscillations, fixed inlet mass flux condition is
applied to activate the feedback mechanism inherent to the InFlowBC_FromStagnation boundary
condition. The rate of convergence of this mechanism is governed by the (relax_factor) [29]. The
pressure damping effect of different options of relax_factor was studied to pick the best option.
When performing this study, the existing boundary conditions at the top and bottom walls of the
truncated 2D slab HRM geometry from Section 6.3.4 are replaced with the WallBC_WithSlip
boundary condition. The set-up method of the inlet and outlet boundary conditions is as per Section
5.3.3. Besides that, the initial condition in the fluid domain of the 2D slab HRM is the low-speed
flow field solution determined earlier. As the top and bottom walls are slip-walls, near-wall
modelling is not required. Hence, all mesh clustering settings are turned off to improve the
simulation speed. As a result of turning off mesh clustering, the mesh of each main block of the
fluid domain becomes uniform. Figure 51 shows the mesh and initial velocity flow field of the fluid
domain in this study.

Figure 51: Mesh and initial velocity flow field within the shortened 2D slab HRM (for comparative study of
relax_factor).

122
To compare the pressure damping effect of different options of relax_factor, the steps that were
followed are:
1. Select at least three options of relax_factor.
2. Set a history point at the inlet of the fluid domain.
3. At the given relax_factor, simulate 50.0 ms of simulation time.
4. Repeat step 1 to 3 for all the remaining options of relax_factor.
5. Plot the corresponding inlet pressure histories of each relax_factor against time in the same
graph (refer to Figure 52).
Figure 52 compares the inlet pressure histories of all relax_factor options.

Figure 52: Inlet pressure histories of all relax_factor options.

According to Figure 52, increasing the magnitude of relax_factor will increase the amplitude and
frequency of pressure fluctuations at the inlet; and vice versa when the magnitude of relax_factor
is reduced. From Figure 52, it is clear that a relax_factor of 0.1 and 0.5 are not good options
because their corresponding inlet pressure histories have a very high frequency of oscillations, high
peak-to-peak amplitudes (the maximum value is at least 200) and does not damp out even after 50
ms of simulation time.

123
A relax_factor of 0.0001 and 0.001 are now the remaining candidates. Both relax_factor options
deem suitable for applications because their corresponding inlet pressure histories have a much
lower frequency of oscillations and peak-to-peak amplitudes than the other relax_factor options,
which were discussed earlier. The final verdict is to use a relax_factor of 0.001 in the simulation
because it has the most effective pressure damping effect among all options. This verdict is
supported by the trend of its corresponding inlet pressure histories, which indicate that the inlet
pressure is converging to a steady-state starting from 45 ms of simulation time.

6.3.6 Results of the Pure Injection Simulation with Full Geometry


The pure injection simulation was run again using the full geometry of the 2D slab HRM (refer to
Figure 26). Full geometry is used because, in the preliminary attempt (refer to Section 6.3.4), the
outlet boundary condition was too close to the wake region that is downstream the trailing edge of
the fuel surface. As the outlet boundary condition was entails fixed pressure and zero Neumann
boundary conditions for all other variables, the flow variables in the wake region are highly likely
not yet stabilised to satisfy the zero Neumann boundary conditions of the outlet. With the use of
full geometry, the flow variables in the wake region have enough travelling distance to be fully
stabilised, such that they satisfy the zero Neumann boundary conditions and Dirichlet boundary
condition for the pressure at the outlet.

In this simulation, the boundary conditions, blocking structure, meshing and simulation
configurations of the fluid domain are as per Section 5.3. Contrary to the previous attempt
discussed in Section 6.3.6, the stagnation inlet boundary condition is also assigned with the fixed
inlet mass flux condition and a pressure relaxation factor (or relax_factor) 0.001 (refer to Section
6.3.5 for justification). Besides that, the fluid domain is initialised with two different initial
conditions. The initial conditions of the pre-entrance, entrance and slab HRM regions are set equal
to the pure injection flow field solution mentioned in Section 6.3.4, whereas the initial conditions
of the downstream region are set equal to the low-speed flow field solution determined earlier.

124
Figure 53 shows the initial conditions of the pure injection simulation.

Figure 53: Initial conditions within the complete 2D slab HRM

125
In Figure 53, the regions with discontinuity in flow properties indicate the partition of the two different initial conditions.
The pure injection simulation was run for a simulation time of 45.0 ms because it is the required flow duration for the prescribed pressure
relaxation factor (relax_factor = 0.001) to damp out the pressure oscillations in the flow field (refer to Section Figure 52). The time evolution
of the fuel injection process over the 45.0 ms flow time are in the following figures:

Figure 54: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure injection case) at t = 9.0 ms.

Figure 55: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure injection case) at t = 18.0 ms.
126
Figure 56: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure injection case) at t = 27.0 ms.

Figure 57: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure injection case) at t = 36.0 ms.

127
Figure 58: Mass fraction of C4H6 and velocity vectors within the complete 2D slab HRM (pure injection case) at t = 45.0 ms.

From Figure 54 to Figure 58, it is observable that the fuel injected by the fuel pyrolysis boundary condition is consistently being blown
downstream by the gaseous oxygen flow. As a result, the fuel eventually wet the lower wall of the downstream region of the complete 2D slab
HRM. When the simulation time is at 45.0 ms, the temperature field of the fluid domain of the complete 2D slab HRM is in Figure 59.

Figure 59: Temperature field within the complete 2D slab HRM (pure injection case) at t = 45.0 ms.

128
Figure 60, Figure 61 and Figure 62 compare the corresponding wall-normal profiles of the
temperature, mass fraction of C4H6 and 𝑥-velocity for a set of distinct 𝑥-coordinates at 𝑡 = 45.0 ms.

Figure 60: Spatial variation of the wall-normal temperature profile (pure injection case) at t = 45.0 ms.

Figure 61: Spatial variation of the wall-normal profile of 𝑌𝐶4𝐻6 (pure injection case) at t = 45.0 ms.

In Figure 60, it is observable when 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0, the temperature at 𝑥-coordinates = 12.5, 25.0,
37.5 and 50.0 mm are the same and equal to 675 K. That is because these 𝑥-coordinates are along
the perimeter of the fuel surface, which is subject to an isothermal condition at this temperature.
When the 𝑥-coordinate is above 50.0 mm, the temperature at 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0 is no longer at 675
K and free to vary because of the zero wall-normal temperature gradient condition, which is
inherent to the slip-wall condition assigned to this range of 𝑥-coordinate.
129
Besides that, the temperature in this range of 𝑥-coordinate at 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0 is greater than 675
K because of the heat up effect from the gaseous oxygen stream to the fuel-rich layer on the wall,
which is 675 K initially before being blown downstream from the trailing edge of the fuel surface.
The presence of fuel-rich melt layer at this range of 𝑥-coordinate is evident in Figure 61, which
indicates that the mass fraction of the HTPB-fuel (𝑌𝐶4 𝐻6 ) at 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0 is in the range of 0.6
– 0.9.
When 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 > 0, it is noticeable in Figure 61 that the value of 𝑌𝐶4 𝐻6 at each 𝑥-coordinate
becomes zero at a certain value of 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 . The value of 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 at which 𝑌𝐶4 𝐻6 is equal
to zero corresponds to the thickness of the fuel-rich layer. When 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 1, the temperature
at all 𝑥-coordinates is equal to 900 K because the top wall of the 2D slab HRM is subject to an
isothermal condition at this temperature.

Figure 62: Spatial variation of the wall-normal 𝑥-velocity profile (pure injection case) at t = 45.0 ms.

In Figure 62, it is observable when 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0, the 𝑥-velocity at 𝑥-coordinate = 12.5, 25.0,
37.5 and 50.0 mm are equal to zero. This is an indication that the no-slip condition at the fuel
surface was implemented correctly in the fuel pyrolysis boundary condition. When the 𝑥-coordi-
nate is above 50.0 mm, it is noticeable that the 𝑥-velocity at 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0 is greater than zero
and free to vary because of the slip-wall condition.

130
When 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 > 0, it is noticeable that the 𝑥-velocity at all 𝑥-coordinates exhibit oscillatory
behaviour in the wall-normal direction. The possible reason for this behaviour would be the
blowing effect of the fuel injection process and the formation of vorticial structures [26]. The
amplitude of oscillation decreases when the value of 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 increases. When 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 >
0.8, the 𝑥-velocity is in parabolic form and does not exhibit oscillatory behaviour. The possible
reason for the non-oscillatory behaviour is that the flow is predominantly the undisturbed gaseous
oxygen at this range of 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 (refer to Figure 61). When 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 1, the 𝑥-velocity at
all 𝑥-coordinates is equal to zero because the top wall of the 2D slab HRM is subject to a no-slip
condition.
Figure 63 shows the static pressure history at the inlet of the complete 2D slab HRM.

Figure 63: Inlet pressure history of the pure injection case (without pressure relaxation factor at the inlet).

In Figure 63, it is evident that specifying a fixed inlet mass flux in conjunction with a relax_factor
of 0.001 does have significant pressure damping effect. However, the same figure also indicates
that the inlet pressure still exhibits oscillatory behaviour at 45.0 ms. This implies that the simulation
time for the pure injection case was not long enough to allow the fluctuations of the inlet pressure
fully damped out.

131
6.3.7 Results of the Combustion Simulation with Full Geometry
The combustion with injection simulation was performed using the full geometry of the 2D slab HRM (refer to Figure 26). This simulation
used the same boundary and initial conditions, blocking structure, mesh and simulation configurations in Section 6.3.6. Besides that, the
ignition parameters from Table 33 were used in the simulation. The simulation was set to run for a simulation time of 45.0 ms. The following
figures show the time-evolution of the diffusion flame in the 2D slab HRM.

Figure 64: Mass fraction of CO and velocity vectors within the complete 2D slab HRM (combustion with injection case) at t = 0.90 ms.

Figure 65: Mass fraction of CO and velocity vectors within the complete 2D slab HRM (combustion with injection case) at t = 1.80 ms.

132
Figure 66: Mass fraction of CO and velocity vectors within the complete 2D slab HRM (combustion with injection case) at t = 2.70 ms.

Figure 67: Mass fraction of CO and velocity vectors within the complete 2D slab HRM (combustion with injection case) at t = 3.60 ms.

From Figure 64 to Figure 67, it is observable that the flame was ignited at the leading edge of the fuel. The flame was self-sustainable upon
ignition and propagates downstream to form a diffusion flame at the interface between the gaseous oxygen and the fuel-rich layer.
Unfortunately, the simulation failed when the simulation time is 4.5 ms because the temperature at a region downstream the trailing edge of
the fuel surface went unphysical.
133
Figure 68: Temperature field within the complete 2D slab HRM (combustion with injection case) at t = 4.90 ms.

Poor mesh quality is very likely to be the cause of the simulation failure because the fluid-cells with unphysical cell-centre temperature have
an aspect ratio of approximately 135 (refer to Figure 69), which is large.

Figure 69: Dimensions of the fluid-cell with the unphysical temperature.

134
Figure 70 and Figure 71 compare the corresponding wall-normal profiles of the temperature and
mass fractions of all species at 𝑡 = 3.60 ms.

Figure 70: Wall-normal temperature profile at 𝑥 = 50.0 mm and at t = 3.60 ms.

Figure 71: Wall-normal species profile at 𝑥 = 50.0 mm and at t = 3.60 ms.

In Figure 70, the high temperature region spans from 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0.1 to 0.7. This occupies a
significant proportion of the combustion chamber height, implying a thick flame. However, Figure
71 indicates that the actual combustion is located at between 𝑦⁄𝐻𝑐ℎ𝑎𝑚𝑏𝑒𝑟 = 0.04 and 0.10 because
this is the position where the mass fractions of the fuel and oxygen drop to zero and the mass
fractions of the products are at maximum.

135
Chapter 7

Recommendations and Conclusions

This section presents the conclusions and future recommendations of this research project.

7.1 Conclusions
As a conclusion, the aim of this work is to simulate the internal combustion ballistics of an HTPB
fuel and pure oxygen in a 2D slab HRM in Eilmer 4. Besides that, this work also aims to develop
some of the capabilities required to simulating the internal combustion ballistics of liquefying fuels
like paraffin wax. To achieve these aims, the objectives of this work are:
1. Implement predictive CFD sub-models of the following physical processes:
a. Solid fuel pyrolysis and regression processes.
b. Heat conduction process in the solid fuel.
c. Combustion kinetics of the HTPB-oxygen mixture.
d. Thermal radiation effect.
e. Fluid-solid coupled heat transfer process at the solid fuel surface.
f. Melt layer effect.
2. Utilise the HPC resources by designing the algorithm of the CFD sub-models for parallel
processing in MPI.
By the end of this thesis, the aims and all objectives of this have been achieved. In the process of
achieving these aims and objectives, there were several key milestones:
1. Successfully identified the required background theories of all the CFD sub-models
mentioned earlier.
2. Successfully developed the implementation methodologies of each CFD sub-model from
the background theories and knowledge about Eilmer 4’s user-defined functionalities.
3. Successfully implemented all the CFD sub-models mentioned earlier.

136
4. Successfully verified the implementation of the chemistry kinetics source term of the
HTPB-oxygen mixture and the isothermal melt layer boundary condition.
5. Successfully developed a methodology to simulate the internal combustion ballistics of a
hybrid rocket motor in Eilmer 4 at a very low speed condition.
6. Successfully simulated the internal combustion ballistics of an HTPB fuel and pure oxygen
inside a 2D slab HRM by using the fuel pyrolysis boundary condition and the verified
chemistry kinetics.

These milestones showed that Eilmer 4 has the capability to simulate the internal combustion
ballistics of a hybrid rocket motor, making it a potential design tool for a hybrid rocket motor.

7.2 Future Recommendations


Although all aims and objectives of this project were met, more work has to be done to improve
and refine the developed CFD sub-models to establish the confidence of their validity. Inline to
this cause, several future recommendations are proposed including:
1. Test the implemented fluid-coupled heat transfer mechanism with a test case that is
analytically solvable.
2. Develop a solver that can solve the P1-radiation model for the incident radiation term in the
local divergence of the radiative heat flux.
3. Perform mesh convergence analysis to determine the optimal mesh quality.
4. Perform more thorough verification and validation of the implemented CFD sub-models,
especially the fuel pyrolysis and isothermal melt layer boundary conditions.
5. Model spray evaporation and combustion of fuel droplets.
6. Make the implemented CFD sub-models compatible with circular fuel grains.
7. Develop a more robust MPI implementation of the boundary conditions to maximise the
utilisation of the high-performance computing resources.

137
References

[1] Gariani G., Maggi F. and Galfetti L., “Numerical Simulation of HTPB Combustion in a 2D
Hybrid Slab Combustor,” Acta Astronautica, no. 69, pp. 289-296, 2011.
[2] Risha, Grant, et al. , “Pyrolysis and combustion of solid fuels in various oxidizing
environments,” in 34th AIAA/ASME/SAE/ASEE Joint Propulsion Conference and Exhibit,
1998.
[3] Andrea Coronetti and William A. Sirigano, “Numerical Analysis of Hybrid Rocket
Combustion,” Journal of Propulsion and Power, vol. 29, no. 2, 2013.
[4] D. Bianchi, F. Nasuti, D. Delfini, “Modeling of gas-surface interface for paraffin-based
hybrid rocket fuels in computational fluid dynamics simulations,” Progress in propulsion
physics, pp. 3-24, 2019.
[5] Karabeyoglu M. A., Cantwel B.J. and Altman D., “Recent Advances in Hybrid Propulsion,”
International Journal of Energetic Materials and Chemical Propulsion 9(4), pp. 305-326,
2010.
[6] Martin J. Chiaverini, George C. Harting, Yeu-Cherng Lu, Kenneth K. Kuo and Arie Peretz,
“Pyrolysis Behavior of Hybrid-Rocket Solid Fuels Under Rapid Heating Conditions,”
Journal of Propulsion and Power, vol. 15, no. 6, 1999.
[7] M. A. Karabeyoglu, D. Altman and B. J. Cantwell, “Combustion of Liquefying Hybrid
Propellants: Part 1, General Theory,” Journal of Propulsion and Power, vol. 18, no. 3, 2002.
[8] Kan Qin, Peter A. Jacobs, Joshua Keep, Ingo H. Jahn, “A three dimensional fluid structure
thermal simulation of bump-type foil thrust bearings,” in Proceedings of the 1st Global
Power and Propulsion Forum, Zurich, Switzerland, 2017.
[9] M. Arif Karabeyoglu and D. Altman, “Dynamic Modeling of Hybrid Rocket Combustion,”
Journal of Propulsion and Power, vol. 15, no. 4, 1999.
[10] Funami Y. and Shimada T., “Numerical Evaluation of Hybrid Rocket Internal Ballistics with
Thermal Radiation Effect.,” Japan Society for Aeronautical and Space Sciences and ISTS,
vol. 12, no. 29, pp. 21-30, 2014.

138
[11] Crnjac, Peter, et al., “Implementation of the Rosseland and the P1 radiation models in the
system of Navier-stokes equations with the boundary element method.,” International
Journal of Computational Methods and Experimental Measurements , vol. 5, no. 3, pp. 348-
358, 2017.
[12] Sazhin, S. S., et al., “The P-1 model for thermal radiation transfer: advantages and
limitations.,” Fuel, vol. 75, no. 3, pp. 289-294, 1996.
[13] Chmielewski, Maciej, and Marian Gieras, “Planck Mean Absorption Coefficients of H2O,
CO2, CO and NO for radiation numerical modeling in combusting flows.,” Journal of Power
Technologies, vol. 95, no. 2, pp. 97-104, 2015.
[14] CFX-Solver, A. N. S. Y. S., “Theory Guide, 1996-2006 ANSYS Europe,” Ltd., ANSYS CFX
Release 11, 2006.
[15] Krishnamoorthy, Gautham, Rajesh Rawat, and Philip J. Smith, “Parallelization of the p-1
radiation model.,” Numerical Heat Transfer, Part B: Fundamentals, vol. 49, no. 1, pp. 1-17,
2006.
[16] Carvalho, MdG, Tiago Farias, and Paulo Fontes, “Predicting radiative heat transfer in
absorbing, emitting, and scattering media using the discrete transfer method.,” Fundamentals
of radiation heat transfer , vol. 160, no. 1, pp. 17-26, 1991.
[17] Howell, John R., M. Pinar Menguc, and Robert Siegel, Thermal radiation heat transfer, CRC
press, 2015.
[18] Raithby, G. D., and E. H. Chui, “A finite-volume method for predicting a radiant heat transfer
in enclosures with participating media.,” Journal of heat transfer, vol. 112, no. 2, pp. 415-
423, 1990.
[19] Fanli Shan, Lingyun Hou, Ying Piao, “Combustion performance and scale effect from
N2O/HTPB,” Acta Astronautica, vol. 85 , pp. 1-11, 2013.
[20] Pietro Ferrero and Domenic D’Ambrosio, “A Numerical Method For Conjugate Heat
Transfer Problems in Hypersonic Flows,” in 40th Thermodynamics Conference, Seattle,
Washington, 2008.
[21] Bautista, Oscar & Mendez, Federico & Campos, I., “Transient heat conduction in a solid slab
using multiple-scale analysis,” Heat and Mass Transfer, 2005.

139
[22] Fanchao Meng, Sujun Dong, Jun Wang, Dechun Guo, “A new algorithm of global tightly-
coupled transient heat transfer based on quasi-steady flow to the conjugate heat transfer
problem,” Theoretical & Applied Mechanics Letters, no. 6, pp. 233-235, 2016.
[23] J.-L. Battaglia, O. Cois, L. Puigsegur, A. Oustaloup, “Solving an inverse heat conduction
problem using a non-integer identified model,” International Journal of Heat and Mass
Transfer, vol. 44, no. 14, pp. 2671-2680, 2001.
[24] S. Löhle, “Derivation of the non-integer system identification method for the adiabatic
boundary condition using Laplace transform,” International Journal of Heat and Mass
Transfer, vol. 115, pp. 1144-1149, 2017.
[25] Lucien Mallard, Ingo Jahn, “Measure of fuel grain thickness in rocket motors through inverse
heat conduction problem,” School of Mechanical and Mining Engineering, The University
of Queensland, 2018.
[26] José Antonio Moríñigo, José Hermida-Quesada, “Evaluation of reduced-order kinetic models
for HTPB-oxygen,” Aerospace Science and Technology, vol. 58, pp. 358-368, 2016.
[27] Weinstein, Alexandra, and Alon Gany, “Testing and modeling liquefying fuel combustion in
hybrid propulsion.,” Progress in Propulsion Physics, vol. 4, pp. 99-112, 2013.
[28] Meredith, K. A. R. L., Y. I. B. I. N. G. Xin, and J. A. A. P. de Vries, “A numerical model for
simulation of thin-film water transport over solid fuel surfaces.,” Fire Safety Science, vol. 10,
pp. 415-428, 2011.
[29] Jacobs P.A. and Gollan R.J., “The Eilmer 4.0 flow simulation program: Guide to the transient
flow solver,” 2019. [Online]. Available: http://cfcfd.mechmining.uq.edu.au/eilmer/.
[30] P. A. Jacobs, R. J. Gollan, A. J. Denman, B. T. O’Flaherty, D. F. Potter, P. J. Petrie-Repar, I.
A. Johnston., “Eilmer’s Theory Book: Basic Models for Gas Dynamics and
Thermochemistry,” Queensland Geothermal Energy Centre of Excellence, The University of
Queensland, Brisbane, 2012.
[31] CFD-Online, “CFD Online - Turbulence near-wall modelling,” 22 March 2007. [Online].
Available: https://www.cfd-online.com/Wiki/Turbulence_near-wall_modeling. [Accessed
21 September 2019].

140
[32] Salim .M. Salim, and S.C. Cheah, “Wall y+ Strategy for Dealing with Wall-bounded
Turbulent Flows,” in Proceedings of the International MultiConference of Engineers and
Computer Scientists , Hong Kong , 2009.
[33] H. Tennekes, A first course in turbulence, Cambridge: Mass. :MIT Press, 1972.
[34] Rowan J. Gollan and Peter A. Jacobs, “The Eilmer 4.0 flow simulation program: Guide to
the basic gas models package,” School of Mechanical & Mining Engineering, The University
of Queensland, 2018.
[35] I. H. Jahn, HTDT - Heat engine & Turbomachinery Design Tools, bitbucket.org, 2018.
[36] V. Marguet, “Ablation-radiation coupling modelling for hayabusa re-entry vehicle.,” No.
STUDENT., 2013.
[37] C.-M. Liu, “Complete solutions to extended Stokes' problems.,” Mathematical Problems in
Engineering, 2008.
[38] P. Jacobs, Eilmer 4.0 A toolkit for doing gas-dynamic calculations, Brisbane: The University
of Queensland, 2018.
[39] Merotto, Laura, et al., “Characterization of a family of paraffin-based solid fuels.,” in
Proceedings of the 4th European Conference for Aerospace Sciences (EUCASS), St.
Petersburg, Russia., 2011.
[40] B. Florczak, “Viscosity testing of HTPB rubber based pre-binders.,” Central European
Journal of Energetic Materials, vol. 11, no. 4, pp. 625-637, 2014.

141
Appendix
Appendix 1: Directory Structure of the Simulation Set Up
The directory structure of the simulation set up are as follows:
1. common
a. Store the initial conditions and the parameters that contains all the constants.
2. main
a. Store the main input script.
3. udf
a. Store all the user-defined boundary conditions and source terms.

142
Appendix 2: 2D Slab HRM Simulation Code Directory
Appendix 2.1: common directory
Appendix 2.1.1: HybridSlab_SimContd.lua
- Simulation conditions for 2D hybrid slab.
--
-- Filename: HybridSlab_SimContd.lua.
-- Author: Yu Shen Chia.
-- Date: 01/04/2019.
--
-- Last update: 12/07/2019.
--
-- Reference(s): [1] Daniele Bianchi, Barbara Betti and Francesco Nasuti (2015). Simulation of
Gaseous
-- Oxygen/Hydroxyl-Terminated Polybutadiene Hybrid Rocket Flowfields and
Comparison
-- with Experiments.
--
-- [2] Shan F., Lingyun H. and Ying P. (2013). Combustion Performance and Scale
Effect from N2O/HTPB
-- Hybrid Rocket Simulations, Acta Astronautica 85(2013) 1-11.
--
-- [3] Kuo, Kenneth and Chiaverini, Martin (2007). Fundamentals of Hybrid Rocket
Combustion and Propulsion,
-- American Institute of Aeronautics and Astronautics. AIAA Books.

143
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species parameter(s):
-- - gasFrac = A table of gas species mass fractions.
--
-- Geometry parameter(s):
-- - geomType = Geometry type of the fuel grain. Options: 'FLAT', 'CYLINDRICAL' and
'SPHERICAL'.
--
-- Fuel parameter(s):
-- - rhofs = Density of the solid fuel grain (Unit: kg/m^3).
-- - hfs = Pyrolysis enthalpy of the solid fuel grain (J/kg).
-- - kfs = Thermal conductivity of the solid fuel grain (Unit: W/m-K).
-- - Cpfs = Specific heat of the solid fuel (Unit: J/kg-K)
-- - Ea = Activation energy of the regression (Unit: J/mol).
-- - Ru = Universal gas constant (Unit: J/mol-K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
-- - fueFrac = A table of fuel species mass fractions.
--
-- Simulation configuration parameter(s):
-- - ts_Curr = Current simulation time in the solid domain (Unit: s).
--
-- Interface parameter(s):
-- - Twall = Wall temperature (Unit: K).
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species fractions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
gasFrac = {C4H6 = 0.0, O2 = 1.0, CO = 0.0, H2O = 0.0, CO2 = 0.0, H2 = 0.0}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Geometry and dimensions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Dimensions, from Ref([1]).
Hchb = 0.02 -- [m].
Lchb = 0.25 -- [m].
Hf = 5e-3 -- [m].
Lf = 0.05 -- [m].
Linlet = 0.03 -- [m].
geomType = 'FLAT'

144
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Cells.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Cell size.
AR = 0.25
dx = 6e-4 -- [m].
dy = AR*dx -- [m].

-- Scale factors.
Scale = 2^1.0
S = 0.4*Scale
w0 = 1.5*0.25
w1 = 4.05*0.6
w2 = 4.0
w3 = 1.5--*0.5
w4 = 0.5

-- Number of cells.
nx0 = math.floor(S*w0*Linlet/dx)
nx1 = math.floor(S*w1*0.076*Lchb/dx)
nx2 = math.floor(S*w2*Lf/dx) -- For the injection block.
nx3 = math.floor(S*w3*(0.924*Lchb - Lf)/dx)
ny0 = 2
ny1 = math.floor(S*w4*Hchb/dy) - ny0
ny2 = math.floor(0.8*S*w4*Hchb/dy)

-- First cell height.


FirstCellHeight = 3.39e-6 -- [m].

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- HTPB fuel properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Fuel properties, from Ref([1, 2]).
rhofs = 8.035e2 -- [kg/m^3].
hpyr = 1.82e6 -- [J/kg].
kfs = 1.572e-1 -- [W/m-K].
Cpfs = 1.957e3 -- [J/kg-K].
Ea = 5.589e4 -- [J/mol].
Ru = 8.314 -- [J/mol-K].
Af = 3.965e3 -- [mm/s].

145
fuelFrac = {C4H6 = 1.0, O2 = 0.0, CO = 0.0, H2O = 0.0, CO2 = 0.0, H2 = 0.0}

-- Thermal time scale.


Scale_Lchar = 6e-3
Lchar = Scale_Lchar*Hf -- [m].
alpha = kfs/(rhofs*Cpfs) -- [m^2/s].
tchar = (Lchar^2)/alpha -- [s].

-- Solid heat conduction.


solidCondFlag = false
solidHeatFile = 'python3 HybridSlab_Solid.py'

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Source terms and udf configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Ignition setting.
ignFlag = true
nthermal = 5
t_final = nthermal*tchar -- [s].
T_ign = 1500 -- [K].
t_ignStart = 0.0*t_final -- [s].
t_ignEnd = 0.0*0.001*t_final --[s].
x_ignStart = 0.0*Lf -- [m].
x_ignEnd = 0.0*0.05*Lf -- [m].

-- Radiation setting.
radFlag = false

-- Injection setting.
injectFlag = true

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Gas surface interface (GSI) properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
os.execute("mkdir ../userData")
inputFile1 = '../userData/WallTempHist.txt'
inputFile2 = '../userData/qInputHist.txt'
outputFile1 = '../userData/Twall_Prev.txt'
outputFile2 = '../userData/qInput_Curr.txt'
outputFile3 = '../userData/Twall_Curr.txt'
Twall_GSI_ini = 675.0 -- [K].

146
Twall_GSI = {}
ts_Curr = 0.0 -- [s].

-- Print the current simulation time.


print(string.format("Current simulation time in the solid fuel grain: %f s", ts_Curr))

-- Set the initial wall temperature distribution at GSI.


for i=1,nx2 do Twall_GSI[i] = Twall_GSI_ini end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Melt layer properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
thinFilmFlag = false
Tmelt = 241 + 273.15 -- [K], from Ref([3]).
FilmHeight_ini = 1e-6 -- [m] (**Must be greater than zero).
FilmVelx_ini = 0.0 -- [m/s].
BC_List = {"Dirichlet", "Neumann"}
LE_BC = BC_List[1]
TE_BC = BC_List[2]

-- Surface velocity of the solid fuel surface.


u_surf = 0.0 -- [m/s] (At y = 0 m).

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- End of input file.
--++++++++++++++++++++++++++++++++++++++

Appendix 2.2: main directory


Appendix 2.2.1 – HybridSlab.lua
--- Title: Numerical Simulation of HTPB Combustion in a 2D Hybrid Slab Combustor.
--
-- Filename: HybridSlab.lua.
-- Author: Yu Shen Chia.
-- Date: 22/03/2019.
--
-- Last update: 12/07/2019.
--
-- Description: Truncated combustion chamber.
--
-- Reference: [1] Gariani G., Maggi F. and Luciano G. (2011). Numerical Simulation of HTPB
Combustion
-- in a 2D Hybrid Slab Combustor, Acta Astronautica 69(2011) 289-296
--

147
-- **Input file = HybridSlab_SimContd.lua
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Flow Conditions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Load the simulation parameters.
dofile('../common/HybridSlab_SimContd.lua')

-- Initial conditions, from Ref([1]).


P_atm = 101.325e3 -- [Pa].
T_ini = 300.0 -- [K].
velx_ini = 6.0 -- [m/s].
gasFrac_ini = gasFrac -- (from input file).

-- Freestream conditions, from Ref([1]).


p_inf = P_atm -- [Pa].
T_inf = 900.0 -- [K].
velx_inf = 6.0 -- [m/s].
gasFrac_inf = gasFrac -- (from input file).

-- Set up the initial state at the inlet.


gmodel = GasModel:new{'FuelMixture-gas-model.lua'}
InitialState = GasState:new{gmodel}
InitialState.massf = gasFrac -- (from input file).
StagnationState = GasState:new{gmodel}
StagnationState.massf = gasFrac -- (from input file).

-- Compute the initial state of the oxidizer at the inlet.


InitialState.p = p_inf -- [Pa].
InitialState.T = T_inf -- [K].
gmodel:updateThermoFromPT(InitialState)
SInitial = gmodel:entropy(InitialState)
hInitial = gmodel:enthalpy(InitialState)
rhoInitial = InitialState.rho -- [kg/m^3].

-- The initial guess for the stagnation conditions are atmospheric pressure and room temperature.
StagnationState.p = p_inf -- [Pa].
StagnationState.T = 298.15 -- [K].
h_stag = hInitial + 0.5*math.pow(velx_ini, 2) -- [J/kg].

-- Calculate the stagnation conditions at the inlet.


print("---------- Calculation ----------")
gmodel:updateThermoFromHS(StagnationState, h_stag, SInitial)
rhoStagnation = StagnationState.rho
PStagnation = StagnationState.p -- [Pa].
TStagnation = StagnationState.T -- [K].

148
SStagnation = gmodel:entropy(InitialState)
hStagnation = gmodel:enthalpy(InitialState) -- [J/kg].

-- Print the inlet stagnation conditions.


print("---------- Stagnation State ----------")
print(PStagnation, TStagnation, hStagnation, SStagnation, rhoStagnation)

-- Outlet conditions, from Ref([1]).


p_outlet = P_atm -- [Pa].

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Flow States and Turbulence Modelling.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
nsp, nmodes, gmodel = setGasModel('FuelMixture-gas-model.lua')
initial = FlowState:new{p = p_ini, T = T_ini, velx = velx_ini, massf = gasFrac_ini}
inflow = FlowState:new{p = p_inf, T = T_inf, velx = velx_inf, massf = gasFrac_inf}

-- Estimate k and omega values for turbulence modelling.


Dh = 2*Hchb
lturb = 0.07*Dh
tke_inf = 1.0e-4
Cmu = 0.09
omega_inf = math.pow(Cmu, -0.25)*math.pow(tke_inf, 0.5)/lturb
stagnation = FlowState:new{p = PStagnation, T = TStagnation, massf = gasFrac_inf,
tke = tke_inf, omega = omega_inf}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
config.title = "2D Hybrid Slab Combustor"
print(config.title)

config.dimensions = 2
config.max_time = t_final -- [s].
config.max_step = 250000000
config.dt_init = 1.0e-12 -- [s].
config.turbulence_model = "none"
config.viscous = true
config.flux_calculator = "ausm_plus_up"
config.cfl_value = 0.2
config.dt_plot = config.max_time/200 -- [s].

149
config.dt_history = config.max_time/1000 -- [s].
config.M_inf = velx_inf/inflow.a

if ignFlag or radFlag then


config.udf_source_terms = true
config.udf_source_terms_file = "../udf/udf-HTPB-Oxygen-Reaction-Radiation.lua"
if ignFlag then print("Finite Rate Chemistry is Activated") end
if radFlag then print("Radiation Effect is Activated") end
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Flow domain.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Combustor geometry, from Ref([1]).
--
-- |<--Linlet-->|
-- T1-----------T2------T3------------T4------T5
-- | 2 | 5 | 8 | 11 |
-- | | | | |
-- ___ A------------B-------C-------------D-------E
-- | | | | | |
-- | | 1 | 4 | 7 | 10 |
-- Inlet => 0.5*Hchb M1-----------M2------M3------------M4------M5 => Outlet
-- | | | | | |
-- _|_ | 0 | 3 | 6 | 9 |
-- J------------I-------H-------------G-------F
--
-- |<----Lf----->|
--
-- Geometry parameter(s):
-- - Hchb = Combustor chamber height (Unit: m).
-- - Lchb = Combustor chamber length (Unit: m).
-- - Lf = Solid fuel grain length (Unit: m).
-- - Linlet = Inlet buffer length (Unit: m).
--
-- **All dimensions are provided in the input file.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Top grid points.
T1 = Vector3:new{x = -Linlet, y = Hchb}
T2 = Vector3:new{x = -0.076*Lchb, y = Hchb}
T3 = Vector3:new{x = 0.0, y = Hchb}
T4 = Vector3:new{x = Lf, y = Hchb}
T5 = Vector3:new{x = 0.924*Lchb, y = Hchb}

150
-- Middle grid points.
A = Vector3:new{x = -Linlet, y = 0.5*Hchb}
B = Vector3:new{x = -0.076*Lchb, y = 0.5*Hchb}
C = Vector3:new{x = 0.0, y = 0.5*Hchb}
D = Vector3:new{x = Lf, y = 0.5*Hchb}
E = Vector3:new{x = 0.924*Lchb, y = 0.5*Hchb}

-- Bottom grid points.


F = Vector3:new{x = 0.924*Lchb, y = 0.0}
G = Vector3:new{x = Lf, y = 0.0}
H = Vector3:new{x = 0.0, y = 0.0}
I = Vector3:new{x = -0.076*Lchb, y = 0.0}
J = Vector3:new{x = -Linlet, y = 0.0}

-- Top of inflation layer grid points.


M1 = Vector3:new{x = -Linlet, y = ny0*FirstCellHeight}
M2 = Vector3:new{x = -0.076*Lchb, y = ny0*FirstCellHeight}
M3 = Vector3:new{x = 0.0, y = ny0*FirstCellHeight}
M4 = Vector3:new{x = Lf, y = ny0*FirstCellHeight}
M5 = Vector3:new{x = 0.924*Lchb, y = ny0*FirstCellHeight}

-- Patches.
S0 = CoonsPatch:new{p00 = J, p10 = I, p11 = M2, p01 = M1}
S1 = CoonsPatch:new{p00 = M1, p10 = M2, p11 = B, p01 = A}
S2 = CoonsPatch:new{p00 = A, p10 = B, p11 = T2, p01 = T1}
S3 = CoonsPatch:new{p00 = I, p10 = H, p11 = M3, p01 = M2}
S4 = CoonsPatch:new{p00 = M2, p10 = M3, p11 = C, p01 = B}
S5 = CoonsPatch:new{p00 = B, p10 = C, p11 = T3, p01 = T2}
S6 = CoonsPatch:new{p00 = H, p10 = G, p11 = M4, p01 = M3}
S7 = CoonsPatch:new{p00 = M3, p10 = M4, p11 = D, p01 = C}
S8 = CoonsPatch:new{p00 = C, p10 = D, p11 = T4, p01 = T3}
S9 = CoonsPatch:new{p00 = G, p10 = F, p11 = M5, p01 = M4}
S10 = CoonsPatch:new{p00 = M4, p10 = M5, p11 = E, p01 = D}
S11 = CoonsPatch:new{p00 = D, p10 = E, p11 = T5, p01 = T4}

-- Clustering.
rcfLy = RobertsFunction:new{end0 = false, end1 = true, beta=1.01}
rcfRy = RobertsFunction:new{end0 = true, end1 = false, beta=1.003} -- (y+ = 0.07).
rcfRx0 = RobertsFunction:new{end0 = false, end1 = true, beta=1.0045}
rcfLx1 = RobertsFunction:new{end0 = true, end1 = true, beta=1.0075}
rcfLx2 = RobertsFunction:new{end0 = true, end1 = false, beta=1.0025}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Grids.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

151
+++
-- Grids (Number of cells of each block are provided in the input file).
grid = {}
grid[0] = StructuredGrid:new{psurface = S0, niv = nx0+1, njv = ny0+1}
grid[1] = StructuredGrid:new{psurface = S1, niv = nx0+1, njv = ny1+1,
cfList = {east = rcfRy, west = rcfRy}}
grid[2] = StructuredGrid:new{psurface = S2, niv = nx0+1, njv = ny2+1,
cfList = {east = rcfLy, west = rcfLy}}
grid[3] = StructuredGrid:new{psurface = S3, niv = nx1+1, njv = ny0+1,
cfList = {north = rcfRx0, south = rcfRx0}}
grid[4] = StructuredGrid:new{psurface = S4, niv = nx1+1, njv = ny1+1,
cfList = {east = rcfRy, west = rcfRy, north = rcfRx0, south = rcfRx0
}}
grid[5] = StructuredGrid:new{psurface = S5, niv = nx1+1, njv = ny2+1,
cfList = {north = rcfRx0, south = rcfRx0, east = rcfLy, west = rcfLy
}}
grid[6] = StructuredGrid:new{psurface = S6, niv = nx2+1, njv = ny0+1,
cfList = {north = rcfLx1, south = rcfLx1}}
grid[7] = StructuredGrid:new{psurface = S7, niv = nx2+1, njv = ny1+1,
cfList = {east = rcfRy, west = rcfRy, north = rcfLx1, south = rcfLx1
}}
grid[8] = StructuredGrid:new{psurface = S8, niv = nx2+1, njv = ny2+1,
cfList = {north = rcfLx1, south = rcfLx1, east = rcfLy, west = rcfLy
}}
grid[9] = StructuredGrid:new{psurface = S9, niv = nx3+1, njv = ny0+1,
cfList = {north = rcfLx2, south = rcfLx2}}
grid[10] = StructuredGrid:new{psurface = S10, niv = nx3+1, njv = ny1+1,
cfList = {east = rcfRy, west = rcfRy, north = rcfLx2, south = rcfLx2
}}
grid[11] = StructuredGrid:new{psurface = S11, niv = nx3+1, njv = ny2+1,
cfList = {north = rcfLx2, south = rcfLx2, east = rcfLy, west = rcfLy
}}
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Fluid blocks and boundary conditions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Lower wall boundary conditions option(s):
-- 1 - UserDefinedFluxBC:new{fileName = 'udf-GSI-FluxBC.lua'}
-- 2 - WallBC_NoSlip_FixedT:new{Twall = 675}
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Top wall temperature.
Twall_Top = 900.0 -- [K].

-- Lower wall temperature.

152
Twall_Lower = Twall_GSI_ini -- [K].

-- Load the initial condition from the previous simulation.


fsol_ini =FlowSolution:new{jobName="HybridSlab",dir="../common/iniContd",tindx=150,nBlocks=24}
fsol_iniFront = FlowSolution:new{jobName="HybridSlab",dir="../common/iniContd2",tindx=110,nBlocks
=120}
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- MPI blocking.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- jth-direction.
njb0 = 1
njb1 = 2--4--2
njb2 = 2--2--5--2

-- ith-direction.
nib0 = 3--6--3
nib1 = 3--6--2--4
nib2 = 6--7--4--2--4
nib3 = 13--3--4

-- Fluid blocks.
blK0 = FluidBlockArray{grid=grid[0], initialState=fsol_iniFront, nib=nib0, njb=njb0, label='blk0'
,
bcList={west = InFlowBC_FromStagnation:new{stagnationState=stagnation, ma
ss_flux=inflow.rho*velx_inf, relax_factor=1e-1},
south = WallBC_WithSlip:new{}}}

blK1 = FluidBlockArray{grid=grid[1], initialState=fsol_iniFront, nib=nib0, njb=njb1, label='blk1'


,
bcList={west = InFlowBC_FromStagnation:new{stagnationState=stagnation, ma
ss_flux=inflow.rho*velx_inf, relax_factor=1e-1}}}

blK2 = FluidBlockArray{grid=grid[2], initialState=fsol_iniFront, nib=nib0, njb=njb2, label='blk2'


,
bcList={west = InFlowBC_FromStagnation:new{stagnationState=stagnation, ma
ss_flux=inflow.rho*velx_inf, relax_factor=1e-1},
north = WallBC_WithSlip:new{}}}

blK3 = FluidBlockArray{grid=grid[3], initialState=fsol_iniFront, nib=nib1, njb=njb0, label='blk3'


,
bcList={south = WallBC_WithSlip:new{}}}

blK4 = FluidBlockArray{grid=grid[4], initialState=fsol_iniFront, nib=nib1, njb=njb1, label='blk4'


}

153
blK5 = FluidBlockArray{grid=grid[5], initialState=fsol_iniFront, nib=nib1, njb=njb2, label='blk5'
,
bcList={north = WallBC_NoSlip_FixedT:new{Twall = Twall_Top}}}

if injectFlag then
print("Fuel Pyrolysis Boundary Condition is Activated")
config.udf_supervisor_file = "../udf/udf-HybridSlabProcess.lua"
if thinFilmFlag then
-- With melt layer on top of the GSI.
config.user_pad_length = math.floor(9*nx2)
user_pad_data = {}

for i=1,nx2 do
user_pad_data[i] = FilmHeight_ini -- [m] (Current film height
distribution).
user_pad_data[i+nx2] = FilmVelx_ini + u_surf -- [m/s] (Current average
film velocity distribution).
user_pad_data[i+math.floor(2*nx2)] = FilmHeight_ini -- [m] (Future film height
distribution).
user_pad_data[i+math.floor(3*nx2)] = FilmVelx_ini + u_surf -- [m/s] (Future average film
velocity distribution).
user_pad_data[i+math.floor(4*nx2)] = Twall_GSI[i] -- [K] (Current film surface
temperature distribution).
user_pad_data[i+math.floor(5*nx2)] = 0.0 -- [K] (Current solid block input
heat flux distribution).
user_pad_data[i+math.floor(6*nx2)] = 0.0 -- [m/s] (Current film surface
velocity distribution).
user_pad_data[i+math.floor(7*nx2)] = 0.0 -- [Pa] (Current film surface shear
stress distribution).
user_pad_data[i+math.floor(8*nx2)] = 0.0 -- [Pa] (Current film-wall surface
shear stress distribution).
end
print("Thin Film Model is Activated")
else
-- There is no melt layer.
config.user_pad_length = math.floor(2*nx2)
user_pad_data = {}
for i=1,nx2 do
user_pad_data[i] = Twall_GSI[i] -- [K] (Current temperature distribution at GSI).
user_pad_data[i+nx2] = Twall_GSI[i] -- [K] (Current solid block input heat flux
distribution at GSI).
end
if solidCondFlag then print("Solid heat conduction is Activated") end
end
blk6 = FluidBlockArray{grid=grid[6], initialState=fsol_iniFront, nib=nib2, njb=njb0, label='In
jection',
bcList={south = UserDefinedFluxBC:new{fileName = '../udf/udf-GSI-
FluxBC.lua'}}}
else

154
blk6 = FluidBlockArray{grid=grid[6], initialState=fsol_iniFront, nib=nib2, njb=njb0, label='In
jection',
bcList={south = WallBC_NoSlip_FixedT:new{Twall = Twall_GSI_ini}}}
end

blK7 = FluidBlockArray{grid=grid[7], initialState=fsol_iniFront, nib=nib2, njb=njb1, label='blk7'


}

blK8 = FluidBlockArray{grid=grid[8], initialState=fsol_iniFront, nib=nib2, njb=njb2, label='blk8'


,
bcList={north = WallBC_NoSlip_FixedT:new{Twall = Twall_Top}}}

blk9 = FluidBlockArray{grid=grid[9], initialState=fsol_ini, nib=nib3, njb=njb0, label='blk9',


bcList={east = OutFlowBC_FixedP:new{p_outside=p_outlet},
south = WallBC_WithSlip:new{}}}

blk10 = FluidBlockArray{grid=grid[10], initialState=fsol_ini, nib=nib3, njb=njb1, label='blk10',


bcList={east = OutFlowBC_FixedP:new{p_outside=p_outlet}}}

blk11 = FluidBlockArray{grid=grid[11], initialState=fsol_ini, nib=nib3, njb=njb2, label='blk11',


bcList={east = OutFlowBC_FixedP:new{p_outside=p_outlet},
north = WallBC_NoSlip_FixedT:new{Twall = Twall_Top}}}

identifyBlockConnections()

-- Ensure that the user defined boundary conditions are in the same MPI task in the master task.
local preassign_List = {}
task_No = 0

for ib=(nib0 + nib1)*(njb0 + njb1 + njb2),(nib0 + nib1)*(njb0 + njb1 + njb2) + (nib2 - 1)*njb0,nj
b0 do
preassign_List[ib] = task_No
end

mpiTasks = mpiDistributeBlocks{ntasks=(nib0 + nib1 + nib2 + nib3)*(njb0 + njb1 + njb2) - nib2*njb


0 + 1,
dist="load-balance",preassign=preassign_List}

-- Turbulence zone.
TurbulentZone:new{p0=I,p1=M5}

-- History points.
setHistoryPoint{x = 0.0, y = 0.0, z = 0.0}
setHistoryPoint{x = 0.5*Lf, y=0.5*Hchb, z=0.0}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

155
+++
-- Domain visualisation by vtk.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
if false then
for ib = 0,2 do
fileName = string.format("HybridSlab-blk-%d.vtk", ib)
grid[ib]:write_to_vtk_file(fileName)
end
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- End of Input Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

156
Appendix 2.3: udf directory
Appendix 2.3.1: udf-GSI-FluxBC.lua
-- Simplified Gas-surface interface boundary condition for the hybrid slab.
-- Author: Yu Shen Chia.
-- Date: 31/03/2019.
--
-- Last update : 23/08/2019.
--
-- Reference(s): [1] Gariani G., Maggi F. and Galfetti L. (2011). Numerical simulation of HTPB
combustion
-- in a 2D Hybrid Slab Combustor, Acta Astronautical 69(2011) 289-296.
--
-- [2] P. A. Jacobs∗, R. J. Gollan†, A. J. Denman, B. T. O’Flaherty,
-- D. F. Potter, P. J. Petrie-Repar and I. A. Johnston. (2012). Eilmer’s Theory
Book:
-- Basic Models for GasDynamics and Thermochemistry, School of Mechanical and
Mining
-- Engineering.
--
-- [3] Bogdan FLORCZAK (2014). Viscosity Testing of HTPB Rubber Based Pre-binders,
-- Central European Journal of Energetic Materials, 2014, 11(4), 625-637
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- GSI Boundary Condition Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- General variables.
local blkId_L, blkId_R, ib
local tsCurr = nil
local Af = Af
local Ea = Ea
local Ru = Ru
local fuelFrac = fuelFrac
local gm = GasModel:new{'../main/FuelMixture-gas-model.lua'}
local fuelFrac = fuelFrac
local rhofs = rhofs
local dudy = 0.0
local dvdx = 0.0
local dvdy = 0.0
local sigma_yy = 0.0
local sigma_yx = 0.0

157
local dTdy = 0.0
local Adjcell = {}
local Adjcell_L = {}
local Adjcell_R = {}
local icell = 0.0
local icell_L, icell_R
local GSI_State = {}
local mdotf = 0.0
local v_inject = 0.0
local v_nxt = 0.0
local Flux = {}
local State= GasState:new{gm}
local GSI_State_nxt = {}
local SpeciesName, SpeciesFrac
local hfg, hfs, qInput_i

-- Additional variables for the thin-film model.


local grad_transVar_i, transVar_i, transVar_i_nxt, Si, dxi, dt
local Tfmean_i, Tfilm_min, Tfilm_max, Tfilm, muFilm, mdotSurf, mdotMelt, v_pyr, u_FilmSurf, sigma
_MeltSurf, Smass, Smom
local spatialDeriv_FilmHeight, spatialDeriv_FilmVelx
local dPgdx, dPvapdx, Pvap_R, Pvap
local Adjcell_sub, Adjcell_subR, Adjcell_subL, icell_sub, ibsub
local ibmax = #fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray
local file

-- Total number of cells along the thin film.


local nicells_tot = nx2

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- General Functions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

function RegressionRate(Twall)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the regression rate at the gas-surface interface (GSI), from
Ref([1]).
--
-- Intermediate parameter(s):
-- - Ea = Activation energy of the regression (Unit: kJ/mol).
-- - Ru = Universal gas constant (Unit: J/mol.K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
--

158
-- Input(s):
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - Regression rate of the fuel (Unit: m/s).
--
-- RegressionRate(float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

return Af*math.exp(-Ea/(Ru*Twall))*1e-3
end

function getNcellsRecursion(ib)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to calculate the number of cells in the ith-direction from the first to the
current
-- block at the gas-surface interface (GSI). Recursive method and modularity of blocks are
imposed.
--
-- Input(s):
-- - ib = Block Id.
--
-- Output(s):
-- - Number of cells in the ith-direction from the first to the current block.
--
-- getNcellsRecursion(int) -> int.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

if ib == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then
-- First sub-block at GSI.
return infoFluidBlock(ib).nicell

elseif ib < fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then


-- Before the first sub-block at GSI.
return 0

else
-- Sub-blocks at GSI.
return (infoFluidBlock(ib).nicell
+ getNcellsRecursion(ib-fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb))
end

end

159
function FuelState(Pwall, Twall)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the fuel state at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - fueFrac = A table of fuel species mass fractions.
--
-- Input(s):
-- - Pwall = Wall pressure at GSI (Unit: Pa).
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - OutputState = A table of fuel state properties at GSI.
--
-- FuelState(float, float) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Define local parameters.


OutputState = {}

-- Compute the fuel state.


State.p = Pwall
State.T = Twall
State.massf = fuelFrac
gm:updateThermoFromPT(State)
gm:updateTransCoeffs(State)
OutputState.rho = State.rho
OutputState.e = gm:intEnergy(State)
OutputState.mu = State.mu

return OutputState
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Moving Wall Functions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function HTPB_Viscosity(Tfilm)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

160
-- A function to compute the viscosity of the R45M HTPB propellant slurry based on the film
temperature.
--
-- Input(s):
-- - Tfilm = Film temperature (Unit: K).
--
-- Output(s):
-- - muHTPB = Viscosity of the R45M HTPB propellant slurry (Unit: Pa.s).
--
-- HTPB_Viscosity(float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
Tfilm_min = 318 -- [K].
Tfilm_max = 338 -- [K].

if Tfilm <= Tfilm_min then


Tfilm = Tfilm_min
elseif Tfilm >= Tfilm_max then
Tfilm = Tfilm_max
end

muHTPB = (0.5657*math.pow(Tfilm, 2) - 386.21*Tfilm + 66124)*1e-3 -- [Pa.s] (Ref. 3).


return muHTPB
end

function ThinFilm_ODE(spatialDeriv_i, Si)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the gradient of the transport variables of the thin-film.
--
-- The gradient of the transport variables is devised from the governing equations of the thin
film by
-- using the method of lines and the finite volume method (FVM) discretisation. The FVM
discretisation
-- scheme is upwind.
--
-- Input(s):
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell
index.
-- - Si = Source term that pertains to the transport variable at the current
cell index.
--
-- Output(s):
-- - grad_transVar_i = Time derivative of the transport variable at the current cell index.
--
-- ThinFilm_ODE(float, float) -> float.
--

161
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
grad_transVar_i = Si - spatialDeriv_i

return grad_transVar_i
end

function Integration_Euler(transVar_i, spatialDeriv_i, Si, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to numerically integrate the governing equations of the thin film by using the
euler method.
--
-- Input(s):
-- - transVar_i = Transport variable at the current time level and current cell index.
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell
index.
-- - Si = Source term that pertains to the transport variable at the current
cell index.
-- - dt = Current time step (Unit: s).
--
-- Output(s):
-- - transVar_i_Nxt = Transport variable at the next time level and current cell index.
--
-- Integration_Euler(float, float, float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
transVar_i_Nxt = transVar_i + dt*ThinFilm_ODE(spatialDeriv_i, Si)

return transVar_i_Nxt
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Main Function.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function convectiveFlux(args)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to model the fuel injection at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - Adjcell = A table of state properties of the interior cell adjacent to GSI.

162
-- - icell = Current cell index originating from the leading edge of GSI. Range:
icell >= 0.
-- - njb = Number of blocks in the jth-direction.
-- - Twall_GSI = Wall temperature distribution at GSI (Unit: K).
-- - GSI_State = A table of fuel state properties at GSI.
-- - rhofs = Solid fuel density (Unit: kg/m^3).
-- - mdotf = Mass flux of the injected fuel (Unit: kg/s*m^2).
-- - v_inject = Fuel injection velocity (Unit: m/s).
-- - dudy = Gradient of the x-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - dvdx = Gradient of the y-velocity w.r.t x-coordinate at GSI (Unit: 1/s).
-- - dvdy = Gradient of the y-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - sigma = Viscous shear stress (Unit: Pa).
-- - dTdy = Gradient of the temperature w.r.t y-coordinate at GSI (Unit: K/m).
--
-- Input(s):
-- - args = A table of state properties.
--
-- Output(s):
-- - Flux = A table of inviscid flux properties at GSI.
--
-- convectiveFlux(table<var, float>) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Extract the flow properties of the interior cell adjacent to GSI.


Adjcell = sampleFluidCell(blkId, args.i, args.j, args.k) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI. Range: icell >=
1.
icell = getNcellsRecursion(blkId - fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb) +
args.i - 1

-- Determine the adjacent cell properties on the right.


icell_R = args.i + 1
Adjcell_R = sampleFluidCell(blkId, icell_R, args.j, args.k) -- (At y = 0+ m).

-- Determine the adjacent cell properties on the left.


icell_L = args.i - 1
Adjcell_L = sampleFluidCell(blkId, icell_L, args.j, args.k) -- (At y = 0+ m).

-- Initialise the flux table.


Flux = {}

if thinFilmFlag then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 1: With Film Flow.

163
--
-- Note(s):
-- [1] Only valid for a film that is isothermal and has constant density.
-- [2] Only valid for 1D film flow.
-- [3] Only valid when the initial film height is greater than zero.
-- [4] Only consider the continuity and momentum transport equations of the film.
-- [5] The continuity and momentum transport equations are tightly coupled to the
solver, whereas
-- the energy transport equation is loosely coupled to the solver.
-- [6] For the mass source term of the film, the vaporosation flux on the film surface
and melting
-- flux on the solid fuel are both governed by the same pyrolysis law (Applies to
HTPB fuel).
-- [7] For the momentum soruce term of the film, only the gas-film shear stress and
solid-film
-- shear stress are considered.
-- [8] Zero pressure gradient in the normal and tangential directions of the film.
-- [9] Quadratic velocity profile.
--
-- userPad entries:
-- [1] userPad[1:nicells_tot] = Spatial distribution of film height at the current time
level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of average film
velocity at
-- the current time level.
-- [3] userPad[(2*nicells_tot+1):3*nicells_tot] = Spatial distribution of film height at
the next
-- time level.
-- [4] userPad[(3*nicells_tot+1):4*nicells_tot] = Spatial distribution of average film
velocity at
-- the next time level.
-- [5] userPad[(4*nicells_tot+1):5*nicells_tot] = Spatial distribution of the film
surface temperature
-- at the current time level.
-- [6] userPad[(5*nicells_tot+1):6*nicells_tot] = Spatial distribution of the solid
block input heat
-- flux at the current time level.
-- [7] userPad[(6*nicells_tot+1):7*nicells_tot] = Spatial distribution of the film
surface velocity
-- at the current time level.
-- [8] userPad[(7*nicells_tot+1):8*nicells_tot] = Spatial distribution of the film
surface shear stress
-- at the current time level.
-- [9] userPad[(8*nicells_tot+1):9*nicells_tot] = Spatial distribution of the film-wall
surface shear stress
-- at the current time level.
--
-- **Warning:
-- [1] Do not parallelize along this boundary condition, because the governing equations

164
of this
-- boundary condition (thin film model) is not parallellized.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

-- Calculate the mean film temperature (Assuming linear temperature profile in the film).
Tfmean_i = 0.5*(userPad[icell + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the properties on the film surface based on the film surface temperature.
-- (Assuming the film is already established).
GSI_State = FuelState(Adjcell.p, userPad[icell + 4*nicells_tot]) -- (At y = 0 m).

-- Calculate the injection velocity on the film surface based on the film surface
temperature.
-- (Assuming the film is already established and the film density is approximately equal to
the solid fuel density).
mdotSurf = rhofs*RegressionRate(userPad[icell + 4*nicells_tot]) -- [kg/s] (At y = 0 m).
v_inject = mdotSurf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the injection/normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density
and film
-- state of that cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell + 4*nicells_tot + 1]) -- (At y = 0
m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = rhofs*RegressionRate(userPad[icell + 4*nicells_tot + 1])/GSI_State_nxt.rho --
[m/s] (At y = 0 m).
end

-- Dynamic viscosity of the film.


muFilm = HTPB_Viscosity(Tfmean_i) -- [Pa.s].

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Surface velocity of the film (Based on the quadratic velocity profile assumption).
u_FilmSurf = (1.5*(userPad[icell + nicells_tot] - u_surf) + u_surf +
0.25*userPad[icell]*(Adjcell.mu/muFilm)*(dvdx + Adjcell.velx/Adjcell.y))/(1 +

165
0.25*userPad[icell]*(Adjcell.mu/muFilm)*(1/Adjcell.y))-- [m/s] (At y = 0 m).

-- (Assuming the film is already established).


dudy = (Adjcell.velx - u_FilmSurf)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
-- (Assuming the film is already established).
dTdy = (Adjcell.T - userPad[icell + 4*nicells_tot])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotSurf -- (At y = 0 m).
Flux.momentum_x = GSI_State.rho*u_FilmSurf*v_inject - sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotSurf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0
Flux.total_energy = mdotSurf*(GSI_State.e + 0.5*math.pow(v_inject, 2) + Adjcell.p/GSI_State
.rho)
- (sigma_yx*u_FilmSurf + sigma_yy*v_inject + Adjcell.k*dTdy)
-- (At y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] = mdotSurf*Spe


ciesFrac end

if blkId == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][1] and


args.i == infoFluidBlock(blkId).imax then
-- Update the film state.
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1]
for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI.
Range: icell >= 1.
icell_sub = getNcellsRecursion(ibsub - fluidBlockArrays[fluidBlockArraysDict["Inje
ction"]].njb) + i - 1

-- Extract the cell properties on the left of the current cell.


Adjcell_subL = sampleFluidCell(ibsub, i - 1, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the injection mass flux and velocity.


GSI_State = FuelState(Adjcell.p, userPad[icell_sub + 4*nicells_tot]) -- (At y = 0

166
m).
mdotf = rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the mean film temperature (Assuming linear temperature profile in the
film).
Tfmean_i = 0.5*(userPad[icell_sub + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the injection velocity on the melt surface based on the melting
temperature.
v_pyr = RegressionRate(Tmelt) -- [m/s] (At y = 0- m).

-- Calculate the injection/normal velocity at the south boundary of the next right
cell.
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature
array, then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel
density and film
-- state of that cell.
GSI_State_nxt = FuelState(Adjcell_subR.p, userPad[icell_sub + 4*nicells_tot + 1
]) -- (At y = 0 m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using
mass balance.
v_nxt = rhofs*RegressionRate(userPad[icell_sub + 4*nicells_tot + 1])/GSI_State_
nxt.rho -- [m/s] (At y = 0 m).
end

-- Dynamic viscosity of the film.


muFilm = HTPB_Viscosity(Tfmean_i) -- [Pa.s].

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Surface velocity of the film (Based on the quadratic velocity profile


assumption).
u_FilmSurf = (1.5*(userPad[icell_sub + nicells_tot] - u_surf) + u_surf +
0.25*userPad[icell_sub]*(Adjcell.mu/muFilm)*(dvdx + Adjcell.velx/Adj
cell.y))/(1 + 0.25*userPad[icell_sub]*(Adjcell.mu/muFilm)*(1/Adjcell.y))-- [m/s] (At y = 0 m).

-- Store the surface velocity of the film at the current time level.
userPad[icell_sub + 6*nicells_tot] = u_FilmSurf

-- (Assuming the film is already established).

167
dudy = (Adjcell.velx - u_FilmSurf)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell
index.
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y = 0
m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell
index.
-- (Assuming the film is already established).
dTdy = (Adjcell_sub.T - userPad[icell_sub + 4*nicells_tot])/Adjcell_sub.y -- [K/m]
(At y = 0 m).

-- Calculate the gas-phase streamwise pressure gradient that adjacent to the thin
film.
-- (Assuming zero normal pressure gradient, dPgdy = 0).
dPgdx = (Adjcell_subR.p - Adjcell_sub.p)/(Adjcell_subR.x - Adjcell_sub.x)

-- Calculate the tangential film-wall viscous shear stress on the melt surface at
the current cell index.
-- (Assuming the film is already established).
sigma_MeltSurf = 3*muFilm*(userPad[icell_sub + nicells_tot] - u_surf)/userPad[icel
l_sub] - 0.5*sigma_yx-- [Pa] (At y = 0- m).

-- Store the film surface and bottom shear stresses at the current time level.
userPad[icell_sub + 7*nicells_tot] = sigma_yx
userPad[icell_sub + 8*nicells_tot] = sigma_MeltSurf

-- Calculate the mass source term.


-- (Assuming the film is already established).
Smass = -RegressionRate(userPad[icell_sub + 4*nicells_tot]) + v_pyr -- [m/s].

-- Compute the momentum source term.


-- (Assuming the film is already established).
Smom = (sigma_yx - sigma_MeltSurf - userPad[icell_sub]*dPgdx)/rhofs

-- Compute the cell spacing.


dxi = Adjcell_subR.x - Adjcell_subL.x -- [m].

-- Upwind scheme.
if userPad[icell_sub + nicells_tot] >= 0 then
-- When the average film velocity at the current cell index is not negative.
if icell_sub > 1 then
-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub + nicells_tot]*userPad[
icell_sub] -
userPad[icell_sub + nicells_tot - 1]*user
Pad[icell_sub - 1])

168
spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub + nicells_tot]*userPad[
icell_sub + nicells_tot]*userPad[icell_sub] -
userPad[icell_sub + nicells_tot - 1]*user
Pad[icell_sub + nicells_tot - 1]*userPad[icell_sub - 1])
else
if LE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
leading edge of the thin film.
spatialDeriv_FilmHeight = (2/dxi)*userPad[icell_sub + nicells_tot]*userPa
d[icell_sub]
spatialDeriv_FilmVelx = (2/dxi)*userPad[icell_sub + nicells_tot]*userPa
d[icell_sub + nicells_tot]*userPad[icell_sub]

elseif LE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed
at the leading edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.
end -- Close the conditional comparison of the cell index along GSI.
else
if icell_sub < nicells_tot then
-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub + nicells_tot + 1]*user
Pad[icell_sub + 1] -
userPad[icell_sub + nicells_tot]*userPad[
icell_sub])

spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub + nicells_tot + 1]*user


Pad[icell_sub + nicells_tot + 1]*userPad[icell_sub + 1] -
userPad[icell_sub + nicells_tot]*userPad[
icell_sub + nicells_tot]*userPad[icell_sub])
else
if TE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
trailing edge of the thin film.
spatialDeriv_FilmHeight = -
(2/dxi)*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

spatialDeriv_FilmVelx = -
(2/dxi)*userPad[icell_sub + nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

elseif TE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed
at the trailing edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.

169
end -- Close the conditional comparison of the cell index along GSI.
end -- Close the conditional comparison of the directionality of the film velocity
at the current cell index.
-- Calculate the new time level film height at the current cell index.
userPad[icell_sub + 2*nicells_tot] = Integration_Euler(userPad[icell_sub], spatialDer
iv_FilmHeight, Smass, args.dt)

-- Calculate the new time level average film velocity at the current cell index.
userPad[icell_sub + 3*nicells_tot] = Integration_Euler(userPad[icell_sub]*userPad[ice
ll_sub + nicells_tot],
spatialDeriv_FilmVelx, Smom, a
rgs.dt)/userPad[icell_sub + 2*nicells_tot]
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the film state at the new time level.


file = io.open("../userData/FilmHeight_Nxt.txt","w")
file:write(table.concat(userPad, " ",2*nicells_tot+1, 3*nicells_tot))
file:close()
file = io.open("../userData/FilmVelx_Nxt.txt","w")
file:write(table.concat(userPad, " ",3*nicells_tot+1, 4*nicells_tot))
file:close()

-- Save the film state at the current time level.


file = io.open("../userData/FilmSurfVelx_Curr.txt","w")
file:write(table.concat(userPad, " ",6*nicells_tot+1, 7*nicells_tot))
file:close()
file = io.open("../userData/FilmSurfShear_Curr.txt","w")
file:write(table.concat(userPad, " ",7*nicells_tot+1, 8*nicells_tot))
file:close()
file = io.open("../userData/FilmWallShear_Curr.txt","w")
file:write(table.concat(userPad, " ",8*nicells_tot+1, 9*nicells_tot))
file:close()
end -- Close the conditional comparison of the minimum i-index of the current MPI block.
else
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 2: Without Film Flow.
--
-- userPad entries:
-- [1] userPad[(1:nicells_tot] = Spatial distribution of the GSI temperature at the
current time
-- level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of the solid block
input heat
-- flux at the current time level.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

170
++++
-- Calculate the vaporised fuel properties on GSI at the current cell
index.
GSI_State = FuelState(Adjcell.p, userPad[icell]) -- (At y = 0 m).

-- Calculate the fuel injection velocity on GSI at the current cell index by using mass
balance.
mdotf = rhofs*RegressionRate(userPad[icell]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density
state of that
-- cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell+1]) -- (At y = 0
m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho -- [m/s] (At y = 0 m).
end

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dudy = (Adjcell.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
dTdy = (Adjcell.T - userPad[icell])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the enthalpy of the gaseous injected fuel (After phase change).
hfg = GSI_State.e + 0.5*math.pow(v_inject, 2) + Adjcell.p/GSI_State.rho -- [J/kg].

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotf -- (At y = 0 m).
Flux.momentum_x = -sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0 -- (At y = 0 m).
Flux.total_energy = mdotf*hfg - (sigma_yx*u_surf + sigma_yy*v_inject + Adjcell.k*dTdy) --

171
(At y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] = mdotf*Specie


sFrac end

if solidCondFlag then
if (args.t%tchar) <= args.dt and args.t >= tchar then
-- Predict the future temperature distribution at GSI.
if blkId == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][
1] and args.i == infoFluidBlock(blkId).imax then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
-- Energy balance:
-- qInput_i == qCond_i = qConv_i - mdotf*(hfg - hfs)
--
-- where:
-- hfs = Enthalpy of the fuel surface at solid state during phase change.
--
-- As hfs is an unknown and note that hpyr (Pyrolysis enthalpy) = hfg - hfs, it
follows that:
-- qInput_i == qCond_i = qConv_i - mdotf*hpyr
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1
]

for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of
GSI. Range: icell >= 1.
icell_sub = getNcellsRecursion(ibsub - fluidBlockArrays[fluidBlockArraysDict
["Injection"]].njb) + i - 1

-- Calculate the injection mass flux and velocity.


GSI_State = FuelState(Adjcell.p, userPad[icell])
mdotf = rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right
cell.

172
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI
temperature array, then
-- the next right cell is after the trailing edge of GSI, which is a slip
wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip
wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised
fuel density state of that cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[i+1]) -- (At y = 0
m).

-- Calculate the fuel injection velocity of the next right cell at GSI by
using mass balance.
v_nxt = rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho -- [m/s]
(At y = 0 m).
end

-- Compute the shear stress and temperature gradient at GSI.


dudy = (Adjcell_sub.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_subR.x - Adjcell_sub.x) -- [1/s] (At y =
0 m).
dvdy = (Adjcell_sub.vely - v_inject)/Adjcell_sub.y -- [1/s] (At y = 0 m).
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y
= 0 m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).
dTdy = (Adjcell_sub.T - userPad[icell_sub])/Adjcell_sub.y -- [K/m] (At y = 0
m).

-- Store the input heat flux of the solid fuel in userPad.


userPad[icell_sub + nicells_tot] = Adjcell_sub.k*dTdy + sigma_yx*u_surf + si
gma_yy*v_inject - mdotf*hpyr -- [J/kg] (At y = 0- m).
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the wall temperature distribution at GSI at the previous (current) time
level.
file = io.open(outputFile1,"w")
file:write(tostring(args.t - tchar) .. " " .. table.concat(userPad, "
",1, nicells_tot))
file:close()

-- Save the input heat flux of the solid block at the current time level.
file = io.open(outputFile2,"w")
file:write(tostring(args.t) .. " " .. table.concat(userPad, "
",nicells_tot+1, 2*nicells_tot))
file:close()
end -- Close the conditional comparison of the minimum i-index of the current MPI

173
block.
end -- Close the conditional comparison of the instant to update the surface temperature
distribution on GSI.
end -- Close the conditional statement for the solidCondFlag.
end -- Close the conditional statement for the thinFilmFlag.
return Flux
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

Appendix 2.3.2: udf-HTPB-Oxygen-Reaction-Radiation.lua


-- HTPB-Oxygen 2-step finite rate reaction mechanisms.
-- Filename: "udf-HTPB-Oxygen-Reaction-Radiation.lua".
-- Author: Yu Shen Chia.
-- Date: 17/08/2019.
--
-- Version 1.0
--

174
-- Reference(s): [1] Rowan Gollan, Peter Jacobs and Ingo Jahn (2018). User-defined Run-time
Customisation for Eilmer Simulations.
--
-- [2] Brittany Chamber (2017). Simulating Micro Combustion with a Compressible
Flow Solver.
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Finite-rate reaction parameter(s):
-- - Jf = Forward reaction rate.
-- - Jb = Backward reaction rate.
-- - A = Pre-exponential factor for the rate constant in jth reaction.
-- - Ea = Activation energy for jth reaction (Unit: cal∕mol).
-- - R = Universal gas constant (Unit: cal/mol-K).
-- - n = Order of reaction (Unit: None).
-- - c = Ea/R (Unit: Kelvin).
-- - T = Temperature (Unit: Kelvin).
-- - M = Molecular weight of the species (Unit: kg∕mol).
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Finite-rate reaction rate data for the HTPB-Oxygen reaction, from Ref([2]).
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Load the simulation parameters.
dofile('../common/HybridSlab_SimContd.lua')

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Combustion parameters.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Constants for the reaction rate of each reaction.
local Af1 = 1.35e10*1e-3 -- [m^3/mol-s].
local Af2 = 2.0e6*(1e-3)^0.5 -- [(m^3/mol)^0.5*(1/s)].
local Ab2 = 8.1e7 -- [1/s].
local nf1 = 0.0
local nf2 = 0.0
local nb2 = 0.0
local cf1 = 3e4/1.987 -- [K].
local cf2 = 1.2e6/1.987 -- [K].
local cb2 = 7.72e7/1.987 -- [K].

-- Other parameters.

175
local k
local A
local T, Tcurr
local n
local c
local T
local t
local cell
local Conc
local MW
local kf1
local kf2
local kb2
local src

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Radiation parameters.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
local alpha = {}
local beta = {}
local gamma = {}
local molef = {}
local i, Ki, Kmix
local sigma_SB = 5.670374419e-8 -- [W/(m^2-K^4)].

-- Fitting function coefficients for CO2.


alpha['CO2'] = {34.57, 1.22, -22.32, 17.14}
beta['CO2'] = {45.32, 930.2, 323.9, 92.98}
gamma['CO2'] = {838.4, 184.9, 217.9, 1657}

-- Fitting function coefficients for H2O.


alpha['H2O'] = {63.87, 2.629, 222.9, 0.991}
beta['H2O'] = {149.5, 493.6, -2110, 1700}
gamma['H2O'] = {174.3, 111.1, 1592, 619.2}

-- Fitting function coefficients for CO.


alpha['CO'] = {0.9245, 1.51, 0.4082, 1.571, 0.94}
beta['CO'] = {503.1, 630.9, 418, 845.4, 1139}
gamma['CO'] = {106.3, 200.3, 44.18, 371.8, 959.2}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Combustion model.
--

176
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++

function ReactionRate(A, n, c, T)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++
-- A function to compute the Arrhenius reaction rate of the current reaction.
--
-- Input(s):
-- - A = Pre-exponential factor for the rate constant in jth reaction (Unit: kg∕m^2-s).
-- - n = Order of reaction (Unit: None).
-- - c = Ea/R (Unit: Kelvin).
-- - T = Temperature (Unit: Kelvin).
--
-- Output(s):
-- - k = Reaction rate.
--
-- ReactionRate(float, float, float, float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++
k = A*math.pow(T, n)*math.exp(-c/T)
return k
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- Radiation model.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
function PMAC_Species(T, Species)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++
-- A function to compute the Planck Mean Absorption Coefficient (PMAC) for a particular species
in the combusting gas.
--
-- Input(s):
-- - T = Static temperature of the current cell (Unit: K).
-- - Species = Name of the species.
--
-- Output(s):
-- - Ki = The PMAC value for a particular species in the combusting gas (Unit: 1/(m-Pa)).
--
-- PMAC_Species(float, str) -> float.
--

177
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++

Ki = 0.0 -- [1/(m-Pa)].
if T > 2500 then T = 2500 end
for i=1,#alpha[Species] do Ki = Ki + alpha[Species][i]*math.exp(-
math.pow((T - beta[Species][i])/gamma[Species][i], 2)) end
return Ki
end

function sourceTerms(t, cell)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++
-- A function to compute the species source terms of the HTPB-Oxygen 2-step reaction
mechanisms.
--
-- Input(s):
-- - t = Current time (Unit: s).
-- - cell = A table of current cell properties.
--
-- Output(s):
-- - src = A table of species source terms.
--
-- sourceTerms(float, table<var, float>) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++

-- Initialise the species source terms table.


src = {}
src.mass = 0
src.momentum_x = 0
src.momentum_y = 0
src.momentum_z = 0
src.total_energy = 0

if ignFlag then
-- Initialise relevant functions from the gas package.
Conc = gmodel:massf2conc(cell) -- [mol/m^3]
MW = gmodel:molMasses() -- [kg/mol].

-- Set the current temperature to the local flow temperature.


Tcurr = cell.T

-- Ignition zone, adapted from Ref([3]).


if cell.x >= x_ignStart and cell.x <= x_ignEnd then
if t >= t_ignStart and t <= t_ignEnd then Tcurr = T_ign end
end

178
-- Set Arrhenius reaction rate to the correct value in the ignition zone, from Ref([2]).
Jf1 = ReactionRate(Af1, nf1, cf1, Tcurr)*Conc['C4H6']*Conc['O2']
Jf2 = ReactionRate(Af2, nf2, cf2, Tcurr)*Conc['CO']*(Conc['O2']^0.5)
Jb2 = ReactionRate(Ab2, nb2, cb2, Tcurr)*Conc['CO2']

-- Species = [0:C4H6, 1:O2, 2:CO, 3:H2O, 4:CO2, 5:H2], from Ref([2]).


src.species = {}
src.species['C4H6'] = -MW['C4H6']*Jf1 -- [kg/m^3-s].
src.species['O2'] = MW['O2']*(-3.5*Jf1 - 0.5*Jf2 + 0.5*Jb2) -- [kg/m^3-s].
src.species['CO'] = MW['CO']*(4.0*Jf1 - Jf2 + Jb2) -- [kg/m^3-s].
src.species['H2O'] = 3*MW['H2O']*Jf1 -- [kg/m^3-s].
src.species['CO2'] = MW['CO2']*(Jf2 - Jb2) -- [kg/m^3-s].

-- There is only radiation during combustion.


if radFlag then
-- Determine the mole fractions of the all the species in the current cell.
molef = gmodel:massf2molef(cell)

-- Determine the PMAC value for the combusting gas mixture.


Kmix = cell.p*(molef['CO2']*PMAC_Species(Tcurr, 'CO2') +
molef['CO']*PMAC_Species(Tcurr, 'CO') +
molef['H2O']*PMAC_Species(Tcurr, 'H2O')) -- [1/m].

-- Compute the divergence of the local radiative flux.


src.total_energy = -4*Kmix*sigma_SB*math.pow(Tcurr, 4)
end
end
return src
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++
-- End of script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++

179
Appendix 2.3.3: udf-HybridSlabProcess.lua
-- A supervisor file to update the state of the thin film.
-- Author: Yu Shen Chia.
-- Date: 24/08/2019.
--
-- Last update : 24/08/2019.
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- HybridSlab process script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- Total number of cells along the thin film.


local nicells_tot = nxcells

-- Interval to record the film properties history.


local dt_writeFilmHist = 2.5e-4 -- [s].

-- Tables for file saving.


local FilmHeight_Nxt, FilmVelx_Nxt

function atTimestepEnd(t,steps, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- A function to update the state of the thin film at the end of each time step.
--
-- atTimestepEnd(float, float, float) -> nil.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

if in_mpi_context and not is_master_task then return end

if thinFilmFlag then

180
-- Update the film state if there is a melt layer.
if (steps % 1) == 0 then
-- Initialise the tables for saving.
FilmHeight_Nxt = {}
FilmVelx_Nxt = {}

for elem in io.lines("../userData/FilmHeight_Nxt.txt")():gmatch("%S+") do table.insert(F


ilmHeight_Nxt, tonumber(elem)) end
for elem in io.lines("../userData/FilmVelx_Nxt.txt")():gmatch("%S+") do table.insert(Fil
mVelx_Nxt, tonumber(elem)) end

for i=1,nicells_tot do
-- Update the spatial distribution of the film height.
userPad[i] = FilmHeight_Nxt[i]

-- Update the spatial distribution of the average film velocity.


userPad[i+nicells_tot] = FilmVelx_Nxt[i]
end
-- Write the film flow solution into the history file.
atWriteToFilmHist(t, dt)
end
else
-- Without melt layer.
if solidCondFlag then
-- If there is conduction.
if (t%tchar) <= dt and t >= tchar then
-- Execute the python script for solid block conduction simulation.
os.execute(solidHeatFile)

-- Update the temperature distribution at GSI at the current time level.


Twall_GSI_Curr = {}
for elem in io.lines(outputFile3)():gmatch("%S+") do table.insert(Twall_GSI_Curr, ton
umber(elem)) end

for i=1,nicells_tot do
userPad[i] = Twall_GSI_Curr[i]
end
end
end
end

return
end

function atWriteToFilmHist(t, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- A function to record the state of the thin film at the end of each time step.

181
--
-- atWriteToFilmHist(float, float) -> nil.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
if thinFilmFlag then
if (t%dt_writeFilmHist) <= dt and t >= dt_writeFilmHist then
print("Write Film Flow Solution at :", t)
-- Save the film height distribution at the current time level.
file = io.open("../userData/FilmHeight_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, " ",1, nicells_tot) .. "\n")
file:close()

-- Save the average film velocity distribution at the current time level.
file = io.open("../userData/FilmVelx_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, "
",nicells_tot+1, 2*nicells_tot) .. "\n")
file:close()

-- Save the film surface velocity at the current time level.


Temp = {}
for elem in io.lines("../userData/FilmSurfVelx_Curr.txt")():gmatch("%S+") do table.inser
t(Temp, tonumber(elem)) end
file = io.open("../userData/FilmSurfVelx_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(Temp " ",1, #Temp) .. "\n")
file:close()

-- Save the film surface shear stress at the current time level.
Temp = {}
for elem in io.lines("../userData/FilmSurfShear_Curr.txt")():gmatch("%S+") do table.inse
rt(Temp, tonumber(elem)) end
file = io.open("../userData/FilmSurfShear_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, "
",7*nicells_tot+1, 8*nicells_tot) .. "\n")
file:close()

-- Save the film-wall interface shear stress at the current time level.
Temp = {}
for elem in io.lines("../userData/FilmWallShear_Curr.txt")():gmatch("%S+") do table.inse
rt(Temp, tonumber(elem)) end
file = io.open("../userData/FilmWallShear_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, "
",8*nicells_tot+1, 9*nicells_tot) .. "\n")
file:close()
else
return
end
end
end

182
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

Appendix 3: Thin-Film Model Test Case


Appendix 3.1: common directory
Appendix 3.1.1: HybridSlab_SimContd.lua
-- Simulation conditions for 2D hybrid slab.
--
-- Filename: HybridSlab_SimContd.lua.
-- Author: Yu Shen Chia.
183
-- Date: 01/04/2019.
--
-- Last update: 12/07/2019.
--
-- Reference(s): [1] Daniele Bianchi, Barbara Betti and Francesco Nasuti (2015). Simulation of
Gaseous
-- Oxygen/Hydroxyl-Terminated Polybutadiene Hybrid Rocket Flowfields and
Comparison
-- with Experiments.
--
-- [2] Shan F., Lingyun H. and Ying P. (2013). Combustion Performance and Scale
Effect from N2O/HTPB
-- Hybrid Rocket Simulations, Acta Astronautica 85(2013) 1-11.
--
-- [3] Kuo, Kenneth and Chiaverini, Martin (2007). Fundamentals of Hybrid Rocket
Combustion and Propulsion,
-- American Institute of Aeronautics and Astronautics. AIAA Books.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species parameter(s):
-- - gasFrac = A table of gas species mass fractions.
--
-- Geometry parameter(s):
-- - geomType = Geometry type of the fuel grain. Options: 'FLAT', 'CYLINDRICAL' and
'SPHERICAL'.
--
-- Fuel parameter(s):
-- - rhofs = Density of the solid fuel grain (Unit: kg/m^3).
-- - hfs = Pyrolysis enthalpy of the solid fuel grain (J/kg).
-- - kfs = Thermal conductivity of the solid fuel grain (Unit: W/m-K).
-- - Cpfs = Specific heat of the solid fuel (Unit: J/kg-K)
-- - Ea = Activation energy of the regression (Unit: J/mol).
-- - Ru = Universal gas constant (Unit: J/mol-K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
-- - fueFrac = A table of fuel species mass fractions.
--
-- Simulation configuration parameter(s):
-- - ts_Curr = Current simulation time in the solid domain (Unit: s).
--
-- Interface parameter(s):
-- - Twall = Wall temperature (Unit: K).
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species fractions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

184
++++++
gasFrac = {C4H6 = 0.0, O2 = 1.0, CO = 0.0, H2O = 0.0, CO2 = 0.0}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Geometry and dimensions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Dimensions, from Ref([1]).
Hchb = 0.02 -- [m].
Lchb = 0.25 -- [m].
Hf = 5e-3 -- [m].
Lf = 0.05 -- [m].
Linlet = 0.03 -- [m].
geomType = 'FLAT'

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Cells.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
N_refine = 1
nxcells = 20*N_refine
nycells = 20*N_refine

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- HTPB fuel properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Fuel properties, from Ref([1, 2]).
--rhofs = 8.035e2 -- [kg/m^3].
hpyr = 1.82e6 -- [J/kg].
kfs = 1.572e-1 -- [W/m-K].
Cpfs = 1.957e3 -- [J/kg-K].
Ea = 5.589e4 -- [J/mol].
Ru = 8.314 -- [J/mol-K].
Af = 3.965e3 -- [mm/s].
fuelFrac = {C4H6 = 1.0, O2 = 0.0, CO = 0.0, H2O = 0.0, CO2 = 0.0}

-- Paraffin fuel properties (Moretto et al. (2011). Characterization of a family of paraffin-


based solid fuels)
rhofParaffin = 890.0 -- [kg/m^3].

185
muFilmParaffin = 0.090 -- [Pa.s] (At T = 343 K)
rhofWater = 971.8 -- [kg/m^3].
muFilmWater = 0.354e-3 -- [Pa.s] (At T = 80 degree celcius or 353 K).
rhofs = rhofParaffin--rhofWater
--muFilm = muFilmwater

-- Thermal time scale.


Scale_Lchar = 1e-2
Lchar = Scale_Lchar*Hf -- [m].
alpha = kfs/(rhofs*Cpfs) -- [m^2/s].
tchar = math.pow(Lchar, 2)/alpha -- [s].

-- Solid heat conduction.


solidHeatFile = 'python3 HybridSlab_Solid.py'

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Source terms and udf configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Ignition setting.
ignFlag = false
nthermal = 5
t_final = 100e-3 --nthermal*tchar -- [s].
T_ign = 1500 -- [K].
t_ignStart = 0.0*t_final -- [s].
t_ignEnd = 0.025*t_final --[s].
x_ignStart = 0.0*Lf -- [m].
x_ignEnd = 0.05*Lf -- [m].

-- Radiation setting.
radFlag = false

-- Injection setting.
injectFlag = true

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Gas surface interface (GSI) temperature.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
os.execute("mkdir ../userData")
inputFile1 = '../userData/WallTempHist.txt'
inputFile2 = '../userData/qInputHist.txt'

186
outputFile1 = '../userData/Twall_Prev.txt'
outputFile2 = '../userData/qInput_Curr.txt'
outputFile3 = '../userData/Twall_Curr.txt'
Twall_GSI_ini = 343.0 -- [K].
Twall_GSI = {}
ts_Curr = 0.0 -- [s].

-- Print the current simulation time.


print(string.format("Current simulation time in the solid fuel grain: %f s", ts_Curr))

-- Set the initial wall temperature distribution at GSI.


for i=1,nxcells do Twall_GSI[i] = Twall_GSI_ini end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Melt layer properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
thinFilmFlag = true
--Tmelt = 241 + 273.15 -- [K], from Ref([3]).
Tmelt = 324 -- [K] (Paraffin fuel).
FilmHeight_ini = 50e-6 -- [m] (**Must be greater than zero).
FilmVelx_ini = 0.0 -- [m/s].
BC_List = {"Dirichlet", "Neumann"}
LE_BC = BC_List[2]
TE_BC = BC_List[2]
u_surf = -10.0 -- [m/s].

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- End of input file.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

Appendix 3.2: main directory


Appendix 3.2.1 – HybridSlab.lua
- Author: Ingo HJ Jahn
-- Date: 2018-10-10

187
--
-- This Lua script is used to prepare an Eilmer4
-- simulation to simulate Stokes Second Flow
-- See:
-- Schlichting, H (1979), Boudary-Layer Theory, McGraw-Hill, New York
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Load the simulation parameters.
dofile('../common/HybridSlab_SimContd.lua')

-- Freestream conditions.
P_atm = 101.325e3 -- [Pa].
T_inf = Twall_GSI_ini -- [K].
gasFrac_inf = gasFrac -- (from input file).

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
config.title = "Paraffin Thin Film"
print(config.title)

config.interpolation_order = 2
config.dimensions = 2
config.max_time = t_final -- [s].
config.max_step = 250000000
config.dt_init = 1.0e-9 -- [s].
config.turbulence_model = "none"
config.viscous = true
config.flux_calculator = "ausm_plus_up"
config.cfl_value = 0.1
config.dt_plot = 0.25e-3 -- [s].
config.dt_history = config.max_time/1000 -- [s].
config.fixed_time_step = true

-- Gas model and flow state setup


nsp, nmodes, gmodel = setGasModel('FuelMixture-gas-model.lua')
initial = FlowState:new{p = P_atm, T = T_inf, massf = gasFrac_inf}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Flow domain.
--

188
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- d----N----c
-- | |
-- | |
-- W E
-- | |
-- | |
-- a----S----b
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++

a = Vector3:new{x=-Hchb/2., y=0.0}
b = Vector3:new{x= Hchb/2., y=0.0}
c = Vector3:new{x= Hchb/2., y=0.25*Hchb}
d = Vector3:new{x=-Hchb/2., y=0.25*Hchb}

cf = RobertsFunction:new{end0=true,end1=false,beta=1.01}

grid = StructuredGrid:new{psurface=CoonsPatch:new{p00=a, p10=b, p01=d, p11=c},


niv=nxcells+1, njv=nycells+1,
cfList={east=cf, west=cf} }

-- Boundary conditions:
--blk.bcList[south] = WallBC_NoSlip_FixedT:new{Twall=startT}
-- blk.bcList[south] = WallBC_NoSlip_Adiabatic:new{}
if injectFlag then
print("Fuel Pyrolysis Boundary Condition is Activated")
config.udf_supervisor_file = "../udf/udf-HybridSlabProcess.lua"
if thinFilmFlag then
-- With melt layer on top of the GSI.
config.user_pad_length = math.floor(10*nxcells)
user_pad_data = {}
for i=1,nxcells do
user_pad_data[i] = FilmHeight_ini -- [m] (Current film height
distribution).
user_pad_data[i+nxcells] = FilmVelx_ini --+ u_surf -- [m/s] (Current
average film velocity distribution).
user_pad_data[i+math.floor(2*nxcells)] = FilmHeight_ini -- [m] (Future film height
distribution).
user_pad_data[i+math.floor(3*nxcells)] = FilmVelx_ini --+ u_surf -- [m/s] (Future
average film velocity distribution).
user_pad_data[i+math.floor(4*nxcells)] = Twall_GSI[i] -- [K] (Current film surface
temperature distribution).
user_pad_data[i+math.floor(5*nxcells)] = 0.0 -- [K] (Current solid block
input heat flux distribution).

189
user_pad_data[i+math.floor(6*nxcells)] = 0.0 -- [m/s] (Current film surface
velocity distribution).
user_pad_data[i+math.floor(7*nxcells)] = 0.0 -- [Pa] (Current film surface
shear stress distribution).
user_pad_data[i+math.floor(8*nxcells)] = 0.0 -- [Pa] (Current film-wall
surface shear stress distribution).
user_pad_data[i+math.floor(9*nxcells)] = 0.0 -- [m/s] (Current adjacent
surface velocity distribution).
end
print("Thin Film Model is Activated")
else
-- There is no melt layer.
config.user_pad_length = math.floor(2*nxcells)
user_pad_data = {}
for i=1,nxcells do
user_pad_data[i] = Twall_GSI[i] -- [K] (Current temperature distribution at GSI).
user_pad_data[i+nxcells] = Twall_GSI[i] -- [K] (Current solid block input heat flux
distribution at GSI).
end
end
blk = FluidBlockArray{grid=grid, initialState=initial , nib=6, njb=9, label='Injection',
bcList={south = UserDefinedFluxBC:new{fileName = '../udf/udf-GSI-
FluxBC.lua'},
north = UserDefinedBC:new{fileName='midplane-bc.lua'},
east = OutFlowBC_SimpleExtrapolate:new{xOrder=0},
west = OutFlowBC_SimpleExtrapolate:new{xOrder=0}}}
else
blk = FluidBlockArray{grid=grid, initialState=initial , nib=1, njb=5, label='Injection',
bcList={south = WallBC_NoSlip_FixedT0:new{Twall = Twall_GSI_ini},
north = UserDefinedBC:new{fileName='midplane-bc.lua'},
east = OutFlowBC_SimpleExtrapolate:new{xOrder=0},
west = OutFlowBC_SimpleExtrapolate:new{xOrder=0}}}
end

-- Ensure that the user defined boundary conditions are in the same MPI tasks.
local preassign_List = {}
task_No = 0

for ib=0,5*9,9 do
preassign_List[ib] = task_No
end

mpiTasks = mpiDistributeBlocks{ntasks=6*9 - 6,
dist="load-balance",preassign=preassign_List}

setHistoryPoint{x = 0.0, y = 0.0, z = 0.0}

Appendix 3.2.2: midplane-bc.lua

190
Author: Ingo H. Jahn
Updated by: Yu Shen Chia.
-- Initialize the global simulation parameters.
dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

local cell1 = {}
local cell2 = {}

function ghostCells(args)
cell = sampleFluidCell(blkId, args.i, args.j, args.k)

-- First ghost cell.


cell1.p = cell.p
cell1.T = cell.T
cell1.massf = cell.massf
cell1.velx = -cell.velx -- Image of the velocity at the symmetry plane.
cell1.vely = cell.vely -- Zero normal velocity gradient.

-- Second ghost cell.


cell2.p = cell.p
cell2.T = cell.T
cell2.massf = cell.massf
cell2.velx = -cell.velx -- Image of the velocity at the symmetry plane.
cell2.vely = cell.vely -- Zero normal velocity gradient.

return cell1, cell2


end

function interface(args)Auth
cell = sampleFluidCell(blkId, args.i, args.j, args.k)
inter = {}
inter.p = cell.p
inter.T = cell.T
return inter
end

191
Appendix 3.3: udf directory
Appendix 3.3.1: udf-GSI-FluxBC.lua
-- Simplified Gas-surface interface boundary condition for the hybrid slab.
-- Author: Yu Shen Chia.
-- Date: 31/03/2019.
--
-- Last update : 23/08/2019.
--
-- Reference(s): [1] Gariani G., Maggi F. and Galfetti L. (2011). Numerical simulation of HTPB
combustion
-- in a 2D Hybrid Slab Combustor, Acta Astronautical 69(2011) 289-296.
--
-- [2] P. A. Jacobs∗, R. J. Gollan†, A. J. Denman, B. T. O’Flaherty,
-- D. F. Potter, P. J. Petrie-Repar and I. A. Johnston. (2012). Eilmer’s Theory
Book:
-- Basic Models for GasDynamics and Thermochemistry, School of Mechanical and
Mining
-- Engineering.
--
-- [3] Bogdan FLORCZAK (2014). Viscosity Testing of HTPB Rubber Based Pre-binders,
-- Central European Journal of Energetic Materials, 2014, 11(4), 625-637
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- GSI Boundary Condition Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- General variables.
local blkId_L, blkId_R, ib
local tsCurr = nil
local Af = Af
local Ea = Ea
local Ru = Ru
local fuelFrac = fuelFrac
local gm = GasModel:new{'../main/FuelMixture-gas-model.lua'}
local fuelFrac = fuelFrac
local rhofs = rhofs
local dudy = 0.0
local dvdx = 0.0
local dvdy = 0.0
local sigma_yy = 0.0
local sigma_yx = 0.0

192
local dTdy = 0.0
local Adjcell = {}
local Adjcell_L = {}
local Adjcell_R = {}
local icell = 0.0
local icell_L, icell_R
local GSI_State = {}
local mdotf = 0.0
local v_inject = 0.0
local v_nxt = 0.0
local Flux = {}
local State= GasState:new{gm}
local GSI_State_nxt = {}
local SpeciesName, SpeciesFrac
local hfg, hfs, qInput_i

-- Additional variables for the thin-film model.


local grad_transVar_i, transVar_i, transVar_i_nxt, Si, dxi, dt
local Tfmean_i, Tfilm_min, Tfilm_max, Tfilm, dotSurf, mdotMelt, v_pyr, u_FilmSurf, sigma_MeltSurf
, Smass, Smom
local spatialDeriv_FilmHeight, spatialDeriv_FilmVelx
local dPgdx, dPvapdx, Pvap_R, Pvap
local Adjcell_sub, Adjcell_subR, Adjcell_subL, icell_sub, ibsub
local ibmax = #fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray
local file

-- Total number of cells along the thin film.


local nicells_tot = nxcells

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- General Functions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

function RegressionRate(Twall)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the regression rate at the gas-surface interface (GSI), from
Ref([1]).
--
-- Intermediate parameter(s):
-- - Ea = Activation energy of the regression (Unit: kJ/mol).
-- - Ru = Universal gas constant (Unit: J/mol.K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
--

193
-- Input(s):
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - Regression rate of the fuel (Unit: m/s).
--
-- RegressionRate(float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

return Af*math.exp(-Ea/(Ru*Twall))*1e-3
end

function getNcellsRecursion(ib)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to calculate the number of cells in the ith-direction from the first to the
current
-- block at the gas-surface interface (GSI). Recursive method and modularity of blocks are
imposed.
--
-- Input(s):
-- - ib = Block Id.
--
-- Output(s):
-- - Number of cells in the ith-direction from the first to the current block.
--
-- getNcellsRecursion(int) -> int.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

if ib == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then
-- First sub-block at GSI.
return infoFluidBlock(ib).nicell

elseif ib < fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then


-- Before the first sub-block at GSI.
return 0

else
-- Sub-blocks at GSI.
return (infoFluidBlock(ib).nicell
+ getNcellsRecursion(ib-fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb))
end

end

194
function FuelState(Pwall, Twall)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the fuel state at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - fueFrac = A table of fuel species mass fractions.
--
-- Input(s):
-- - Pwall = Wall pressure at GSI (Unit: Pa).
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - OutputState = A table of fuel state properties at GSI.
--
-- FuelState(float, float) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Define local parameters.


OutputState = {}

-- Compute the fuel state.


State.p = Pwall
State.T = Twall
State.massf = fuelFrac
gm:updateThermoFromPT(State)
gm:updateTransCoeffs(State)
OutputState.rho = State.rho
OutputState.e = gm:intEnergy(State)
OutputState.mu = State.mu

return OutputState
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Moving Wall Functions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function HTPB_Viscosity(Tfilm)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

195
-- A function to compute the viscosity of the R45M HTPB propellant slurry based on the film
temperature.
--
-- Input(s):
-- - Tfilm = Film temperature (Unit: K).
--
-- Output(s):
-- - muHTPB = Viscosity of the R45M HTPB propellant slurry (Unit: Pa.s).
--
-- HTPB_Viscosity(float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
Tfilm_min = 318 -- [K].
Tfilm_max = 338 -- [K].

if Tfilm <= Tfilm_min then


Tfilm = Tfilm_min
elseif Tfilm >= Tfilm_max then
Tfilm = Tfilm_max
end

muHTPB = (0.5657*math.pow(Tfilm, 2) - 386.21*Tfilm + 66124)*1e-3 -- [Pa.s] (Ref. 3).


return muHTPB
end

function ThinFilm_ODE(spatialDeriv_i, Si)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the gradient of the transport variables of the thin-film.
--
-- The gradient of the transport variables is devised from the governing equations of the thin
film by
-- using the method of lines and the finite volume method (FVM) discretisation. The FVM
discretisation
-- scheme is upwind.
--
-- Input(s):
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell
index.
-- - Si = Source term that pertains to the transport variable at the current
cell index.
--
-- Output(s):
-- - grad_transVar_i = Time derivative of the transport variable at the current cell index.
--
-- ThinFilm_ODE(float, float) -> float.
--

196
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
grad_transVar_i = Si - spatialDeriv_i

return grad_transVar_i
end

function Integration_Euler(transVar_i, spatialDeriv_i, Si, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to numerically integrate the governing equations of the thin film by using the
euler method.
--
-- Input(s):
-- - transVar_i = Transport variable at the current time level and current cell index.
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell
index.
-- - Si = Source term that pertains to the transport variable at the current
cell index.
-- - dt = Current time step (Unit: s).
--
-- Output(s):
-- - transVar_i_Nxt = Transport variable at the next time level and current cell index.
--
-- Integration_Euler(float, float, float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
transVar_i_Nxt = transVar_i + dt*ThinFilm_ODE(spatialDeriv_i, Si)

return transVar_i_Nxt
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Main Function.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function convectiveFlux(args)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to model the fuel injection at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - Adjcell = A table of state properties of the interior cell adjacent to GSI.

197
-- - icell = Current cell index originating from the leading edge of GSI. Range:
icell >= 0.
-- - njb = Number of blocks in the jth-direction.
-- - Twall_GSI = Wall temperature distribution at GSI (Unit: K).
-- - GSI_State = A table of fuel state properties at GSI.
-- - rhofs = Solid fuel density (Unit: kg/m^3).
-- - mdotf = Mass flux of the injected fuel (Unit: kg/s*m^2).
-- - v_inject = Fuel injection velocity (Unit: m/s).
-- - dudy = Gradient of the x-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - dvdx = Gradient of the y-velocity w.r.t x-coordinate at GSI (Unit: 1/s).
-- - dvdy = Gradient of the y-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - sigma = Viscous shear stress (Unit: Pa).
-- - dTdy = Gradient of the temperature w.r.t y-coordinate at GSI (Unit: K/m).
--
-- Input(s):
-- - args = A table of state properties.
--
-- Output(s):
-- - Flux = A table of inviscid flux properties at GSI.
--
-- convectiveFlux(table<var, float>) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Extract the flow properties of the interior cell adjacent to GSI.


Adjcell = sampleFluidCell(blkId, args.i, args.j, args.k) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI. Range: icell >=
1.
icell = getNcellsRecursion(blkId - fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb) +
args.i - 1

-- Determine the adjacent cell properties on the right.


icell_R = args.i + 1
Adjcell_R = sampleFluidCell(blkId, icell_R, args.j, args.k) -- (At y = 0+ m).

-- Determine the adjacent cell properties on the left.


icell_L = args.i - 1
Adjcell_L = sampleFluidCell(blkId, icell_L, args.j, args.k) -- (At y = 0+ m).

-- Initialise the flux table.


Flux = {}

if thinFilmFlag then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 1: With Film Flow.

198
--
-- Note(s):
-- [1] Only valid for a film that is isothermal and has constant density.
-- [2] Only valid for 1D film flow.
-- [3] Only valid when the initial film height is greater than zero.
-- [4] Only consider the continuity and momentum transport equations of the film.
-- [5] The continuity and momentum transport equations are tightly coupled to the
solver, whereas
-- the energy transport equation is loosely coupled to the solver.
-- [6] For the mass source term of the film, the vaporosation flux on the film surface
and melting
-- flux on the solid fuel are both governed by the same pyrolysis law (Applies to
HTPB fuel).
-- [7] For the momentum soruce term of the film, only the gas-film shear stress and
solid-film
-- shear stress are considered.
-- [8] Zero pressure gradient in the normal and tangential directions of the film.
-- [9] Quadratic velocity profile.
--
-- userPad entries:
-- [1] userPad[1:nicells_tot] = Spatial distribution of film height at the current time
level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of average film
velocity at
-- the current time level.
-- [3] userPad[(2*nicells_tot+1):3*nicells_tot] = Spatial distribution of film height at
the next
-- time level.
-- [4] userPad[(3*nicells_tot+1):4*nicells_tot] = Spatial distribution of average film
velocity at
-- the next time level.
-- [5] userPad[(4*nicells_tot+1):5*nicells_tot] = Spatial distribution of the film
surface temperature
-- at the current time level.
-- [6] userPad[(5*nicells_tot+1):6*nicells_tot] = Spatial distribution of the solid
block input heat
-- flux at the current time level.
-- [7] userPad[(6*nicells_tot+1):7*nicells_tot] = Spatial distribution of the film
surface velocity
-- at the current time level.
-- [8] userPad[(7*nicells_tot+1):8*nicells_tot] = Spatial distribution of the film
surface shear stress
-- at the current time level.
-- [9] userPad[(8*nicells_tot+1):9*nicells_tot] = Spatial distribution of the film-wall
surface shear stress
-- at the current time level.
--
-- **Warning:
-- [1] Do not parallelize along this boundary condition, because the governing equations

199
of this
-- boundary condition (thin film model) is not parallellized.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

-- Calculate the mean film temperature (Assuming linear temperature profile in the film).
Tfmean_i = 0.5*(userPad[icell + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the properties on the film surface based on the film surface temperature.
-- (Assuming the film is already established).
GSI_State = FuelState(Adjcell.p, userPad[icell + 4*nicells_tot]) -- (At y = 0 m).

-- Calculate the injection velocity on the film surface based on the film surface
temperature.
-- (Assuming the film is already established and the film density is approximately equal to
the solid fuel density).
mdotSurf = 0.0--rhofs*RegressionRate(userPad[icell + 4*nicells_tot]) -- [kg/s] (At y = 0
m).
v_inject = 0.0--mdotSurf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the injection/normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density
and film
-- state of that cell.
--GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell + 4*nicells_tot + 1]) -- (At y =
0 m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = 0.0--rhofs*RegressionRate(userPad[icell + 4*nicells_tot + 1])/GSI_State_nxt.rho
-- [m/s] (At y = 0 m).
end

-- Dynamic viscosity of the film.


muFilm = muFilmParaffin--muFilmWater -- [Pa.s].

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Surface velocity of the film (Based on the quadratic velocity profile assumption).
if args.t > 1e-7 then

200
u_FilmSurf = (1.5*(userPad[icell + nicells_tot] - u_surf) + u_surf +
0.25*userPad[icell]*(Adjcell.mu/muFilm)*(dvdx + Adjcell.velx/Adjcell.y))/(
1 + 0.25*userPad[icell]*(Adjcell.mu/muFilm)*(1/Adjcell.y))-- [m/s] (At y = 0 m).
else
u_FilmSurf = (1.5*(userPad[icell + nicells_tot]) +
0.25*userPad[icell]*(Adjcell.mu/muFilm)*(dvdx + Adjcell.velx/Adjcell.y))/(
1 + 0.25*userPad[icell]*(Adjcell.mu/muFilm)*(1/Adjcell.y))-- [m/s] (At y = 0 m).
end

-- (Assuming the film is already established).


dudy = (Adjcell.velx - u_FilmSurf)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
-- (Assuming the film is already established).
dTdy = (Adjcell.T - userPad[icell + 4*nicells_tot])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotSurf -- (At y = 0 m).
Flux.momentum_x = GSI_State.rho*u_FilmSurf*v_inject - sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotSurf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0
Flux.total_energy = mdotSurf*(GSI_State.e + 0.5*math.pow(v_inject, 2) + Adjcell.p/GSI_State
.rho)
- (sigma_yx*u_FilmSurf + sigma_yy*v_inject + Adjcell.k*dTdy)
-- (At y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] = mdotSurf*Spe


ciesFrac end

if blkId == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][1] and


args.i == infoFluidBlock(blkId).imax then
-- Update the film state.
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1]
for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI.
Range: icell >= 1.
icell_sub = getNcellsRecursion(ibsub - fluidBlockArrays[fluidBlockArraysDict["Inje
ction"]].njb) + i - 1

-- Extract the cell properties on the left of the current cell.

201
Adjcell_subL = sampleFluidCell(ibsub, i - 1, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the injection mass flux and velocity.


--GSI_State = FuelState(Adjcell.p, userPad[icell_sub + 4*nicells_tot]) -- (At y =
0 m).
mdotf = 0.0--rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0 m).
v_inject = 0.0--mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the mean film temperature (Assuming linear temperature profile in the
film).
Tfmean_i = 0.5*(userPad[icell_sub + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the injection velocity on the melt surface based on the melting
temperature.
v_pyr = 0.0--RegressionRate(Tmelt) -- [m/s] (At y = 0- m).

-- Calculate the injection/normal velocity at the south boundary of the next right
cell.
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature
array, then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel
density and film
-- state of that cell.
--GSI_State_nxt = FuelState(Adjcell_subR.p, userPad[icell_sub + 4*nicells_tot +
1]) -- (At y = 0 m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using
mass balance.
v_nxt = 0.0--rhofs*RegressionRate(userPad[icell_sub + 4*nicells_tot +
1])/GSI_State_nxt.rho -- [m/s] (At y = 0 m).
end

-- Dynamic viscosity of the film.


muFilm = muFilmParaffin--muFilmWater -- [Pa.s].

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dvdx = (v_nxt - v_inject)/(Adjcell_subR.x - Adjcell_sub.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell_sub.vely - v_inject)/Adjcell_sub.y -- [1/s] (At y = 0 m).

-- Surface velocity of the film (Based on the quadratic velocity profile


assumption).
if args.t > 1e-7 then

202
u_FilmSurf = (1.5*(userPad[icell + nicells_tot] - u_surf) + u_surf +
0.25*userPad[icell]*(Adjcell_sub.mu/muFilm)*(dvdx + Adjcell_sub.v
elx/Adjcell_sub.y))/(1 + 0.25*userPad[icell]*(Adjcell_sub.mu/muFilm)*(1/Adjcell_sub.y))-- [m/s]
(At y = 0 m).
else
u_FilmSurf = (1.5*(userPad[icell + nicells_tot]) +
0.25*userPad[icell]*(Adjcell_sub.mu/muFilm)*(dvdx + Adjcell_sub.v
elx/Adjcell_sub.y))/(1 + 0.25*userPad[icell]*(Adjcell_sub.mu/muFilm)*(1/Adjcell_sub.y))-- [m/s]
(At y = 0 m).
end

-- Store the surface velocity of the film at the current time level.
userPad[icell_sub + 6*nicells_tot] = u_FilmSurf

-- (Assuming the film is already established).


dudy = (Adjcell_sub.velx - u_FilmSurf)/Adjcell_sub.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell
index.
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y = 0
m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell
index.
-- (Assuming the film is already established).
dTdy = (Adjcell_sub.T - userPad[icell_sub + 4*nicells_tot])/Adjcell_sub.y -- [K/m]
(At y = 0 m).

-- Calculate the gas-phase streamwise pressure gradient that adjacent to the thin
film.
-- (Assuming zero normal pressure gradient, dPgdy = 0).
dPgdx = (Adjcell_subR.p - Adjcell_sub.p)/(Adjcell_subR.x - Adjcell_sub.x)

-- Calculate the tangential film-wall viscous shear stress on the melt surface at
the current cell index.
-- (Assuming the film is already established).
if args.t > 1e-6 then
sigma_MeltSurf = 3*muFilm*(userPad[icell_sub + nicells_tot] - u_surf)/userPad[i
cell_sub] - 0.5*sigma_yx-- [Pa] (At y = 0- m).
else
sigma_MeltSurf = 3*muFilm*(userPad[icell_sub + nicells_tot])/userPad[icell_sub]
- 0.5*sigma_yx-- [Pa] (At y = 0- m).
end

-- Store the film surface and bottom shear stresses at the current time level.
userPad[icell_sub + 7*nicells_tot] = sigma_yx
userPad[icell_sub + 8*nicells_tot] = sigma_MeltSurf
userPad[icell_sub + 9*nicells_tot] = Adjcell_sub.velx

203
-- Calculate the mass source term.
-- (Assuming the film is already established).
Smass = 0.0---RegressionRate(userPad[icell_sub + 4*nicells_tot]) + v_pyr -- [m/s].

-- Compute the momentum source term.


-- (Assuming the film is already established).
Smom = (sigma_yx - sigma_MeltSurf - userPad[icell_sub]*dPgdx)/rhofs

-- Compute the cell spacing.


dxi = Adjcell_subR.x - Adjcell_subL.x -- [m].

-- Upwind scheme.
if userPad[icell_sub + nicells_tot] >= 0 then
-- When the average film velocity at the current cell index is not negative.
if icell_sub > 1 then
-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub + nicells_tot]*userPad[
icell_sub] -
userPad[icell_sub + nicells_tot - 1]*user
Pad[icell_sub - 1])

spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub + nicells_tot]*userPad[


icell_sub + nicells_tot]*userPad[icell_sub] -
userPad[icell_sub + nicells_tot - 1]*user
Pad[icell_sub + nicells_tot - 1]*userPad[icell_sub - 1])
else
if LE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
leading edge of the thin film.
spatialDeriv_FilmHeight = (2/dxi)*userPad[icell_sub + nicells_tot]*userPa
d[icell_sub]
spatialDeriv_FilmVelx = (2/dxi)*userPad[icell_sub + nicells_tot]*userPa
d[icell_sub + nicells_tot]*userPad[icell_sub]

elseif LE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed
at the leading edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.
end -- Close the conditional comparison of the cell index along GSI.
else
if icell_sub < nicells_tot then
-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub + nicells_tot + 1]*user
Pad[icell_sub + 1] -
userPad[icell_sub + nicells_tot]*userPad[
icell_sub])

204
spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub + nicells_tot + 1]*user
Pad[icell_sub + nicells_tot + 1]*userPad[icell_sub + 1] -
userPad[icell_sub + nicells_tot]*userPad[
icell_sub + nicells_tot]*userPad[icell_sub])
else
if TE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
trailing edge of the thin film.
spatialDeriv_FilmHeight = -
(2/dxi)*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

spatialDeriv_FilmVelx = -
(2/dxi)*userPad[icell_sub + nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

elseif TE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed
at the trailing edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.
end -- Close the conditional comparison of the cell index along GSI.
end -- Close the conditional comparison of the directionality of the film velocity
at the current cell index.
-- Calculate the new time level film height at the current cell index.
userPad[icell_sub + 2*nicells_tot] = Integration_Euler(userPad[icell_sub], spatialDer
iv_FilmHeight, Smass, args.dt)

-- Calculate the new time level average film velocity at the current cell index.
userPad[icell_sub + 3*nicells_tot] = Integration_Euler(userPad[icell_sub]*userPad[ice
ll_sub + nicells_tot],
spatialDeriv_FilmVelx, Smom, a
rgs.dt)/userPad[icell_sub + 2*nicells_tot]

--print(args.t, userPad[icell_sub + 7*nicells_tot], userPad[icell_sub +


8*nicells_tot], userPad[icell_sub + 3*nicells_tot],Adjcell_sub.velx, userPad[icell_sub +
6*nicells_tot])
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the film state at the new time level.


file = io.open("../userData/FilmHeight_Nxt.txt","w")
file:write(table.concat(userPad, " ",2*nicells_tot+1, 3*nicells_tot))
file:close()
file = io.open("../userData/FilmVelx_Nxt.txt","w")
file:write(table.concat(userPad, " ",3*nicells_tot+1, 4*nicells_tot))
file:close()

-- Save the film state at the current time level.

205
file = io.open("../userData/FilmSurfVelx_Curr.txt","w")
file:write(table.concat(userPad, " ",6*nicells_tot+1, 7*nicells_tot))
file:close()
file = io.open("../userData/FilmSurfShear_Curr.txt","w")
file:write(table.concat(userPad, " ",7*nicells_tot+1, 8*nicells_tot))
file:close()
file = io.open("../userData/FilmWallShear_Curr.txt","w")
file:write(table.concat(userPad, " ",8*nicells_tot+1, 9*nicells_tot))
file:close()
file = io.open("../userData/AdjVelx_Curr.txt","w")
file:write(table.concat(userPad, " ",9*nicells_tot+1, 10*nicells_tot))
file:close()
end -- Close the conditional comparison of the minimum i-index of the current MPI block.
else
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 2: Without Film Flow.
--
-- userPad entries:
-- [1] userPad[(1:nicells_tot] = Spatial distribution of the GSI temperature at the
current time
-- level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of the solid block
input heat
-- flux at the current time level.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Calculate the vaporised fuel properties on GSI at the current cell
index.
GSI_State = FuelState(Adjcell.p, userPad[icell]) -- (At y = 0 m).

-- Calculate the fuel injection velocity on GSI at the current cell index by using mass
balance.
mdotf = rhofs*RegressionRate(userPad[icell]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density
state of that
-- cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell+1]) -- (At y = 0

206
m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho -- [m/s] (At y = 0 m).
end

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dudy = (Adjcell.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
dTdy = (Adjcell.T - userPad[icell])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the enthalpy of the gaseous injected fuel (After phase change).
hfg = GSI_State.e + 0.5*math.pow(v_inject, 2) + Adjcell.p/GSI_State.rho -- [J/kg].

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotf -- (At y = 0 m).
Flux.momentum_x = -sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0 -- (At y = 0 m).
Flux.total_energy = mdotf*hfg - (sigma_yx*u_surf + sigma_yy*v_inject + Adjcell.k*dTdy) --
(At y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] = mdotf*Specie


sFrac end

if solidCondFlag then
if (args.t%tchar) <= args.dt and args.t >= tchar then
-- Predict the future temperature distribution at GSI.
if blkId == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][
1] and args.i == infoFluidBlock(blkId).imax then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
-- Energy balance:
-- qInput_i == qCond_i = qConv_i - mdotf*(hfg - hfs)
--
-- where:
-- hfs = Enthalpy of the fuel surface at solid state during phase change.
--
-- As hfs is an unknown and note that hpyr (Pyrolysis enthalpy) = hfg - hfs, it

207
follows that:
-- qInput_i == qCond_i = qConv_i - mdotf*hpyr
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1
]

for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of
GSI. Range: icell >= 1.
icell_sub = getNcellsRecursion(ibsub - fluidBlockArrays[fluidBlockArraysDict
["Injection"]].njb) + i - 1

-- Calculate the injection mass flux and velocity.


GSI_State = FuelState(Adjcell.p, userPad[icell])
mdotf = rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right
cell.
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI
temperature array, then
-- the next right cell is after the trailing edge of GSI, which is a slip
wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip
wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised
fuel density state of that cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[i+1]) -- (At y = 0
m).

-- Calculate the fuel injection velocity of the next right cell at GSI by
using mass balance.
v_nxt = rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho -- [m/s]
(At y = 0 m).
end

-- Compute the shear stress and temperature gradient at GSI.


dudy = (Adjcell_sub.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).

208
dvdx = (v_nxt - v_inject)/(Adjcell_subR.x - Adjcell_sub.x) -- [1/s] (At y =
0 m).
dvdy = (Adjcell_sub.vely - v_inject)/Adjcell_sub.y -- [1/s] (At y = 0 m).
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y
= 0 m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).
dTdy = (Adjcell_sub.T - userPad[icell_sub])/Adjcell_sub.y -- [K/m] (At y = 0
m).

-- Store the input heat flux of the solid fuel in userPad.


userPad[icell_sub + nicells_tot] = Adjcell_sub.k*dTdy + sigma_yx*u_surf + si
gma_yy*v_inject - mdotf*hpyr -- [J/kg] (At y = 0- m).
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the wall temperature distribution at GSI at the previous (current) time
level.
file = io.open(outputFile1,"w")
file:write(tostring(args.t - tchar) .. " " .. table.concat(userPad, "
",1, nicells_tot))
file:close()

-- Save the input heat flux of the solid block at the current time level.
file = io.open(outputFile2,"w")
file:write(tostring(args.t) .. " " .. table.concat(userPad, "
",nicells_tot+1, 2*nicells_tot))
file:close()
end -- Close the conditional comparison of the minimum i-index of the current MPI
block.
end -- Close the conditional comparison of the instant to update the surface temperature
distribution on GSI.
end -- Close the conditional statement for the solidCondFlag.
end -- Close the conditional statement for the thinFilmFlag.
return Flux
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

209
Appendix 3.3.1 – udf-HybridSlabProcess.lua
-- A supervisor file to update the state of the thin film.
-- Author: Yu Shen Chia.
-- Date: 24/08/2019.
--
-- Last update : 24/08/2019.
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- HybridSlab process script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- Total number of cells along the thin film.


local nicells_tot = nxcells

-- Interval to record the film properties history.


local dt_writeFilmHist = 2.5e-4 -- [s].

-- Tables for file saving.


local FilmHeight_Nxt, FilmVelx_Nxt

function atTimestepEnd(t,steps, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- A function to update the state of the thin film at the end of each time step.
--
-- atTimestepEnd(float, float, float) -> nil.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

if in_mpi_context and not is_master_task then return end

if thinFilmFlag then
-- Update the film state if there is a melt layer.
if (steps % 1) == 0 then
-- Initialise the tables for saving.
FilmHeight_Nxt = {}
FilmVelx_Nxt = {}

210
for elem in io.lines("../userData/FilmHeight_Nxt.txt")():gmatch("%S+") do table.insert(F
ilmHeight_Nxt, tonumber(elem)) end
for elem in io.lines("../userData/FilmVelx_Nxt.txt")():gmatch("%S+") do table.insert(Fil
mVelx_Nxt, tonumber(elem)) end

for i=1,nicells_tot do
-- Update the spatial distribution of the film height.
userPad[i] = FilmHeight_Nxt[i]

-- Update the spatial distribution of the average film velocity.


userPad[i+nicells_tot] = FilmVelx_Nxt[i]
end
-- Write the film flow solution into the history file.
atWriteToFilmHist(t, dt)
end
else
-- Without melt layer.
if solidCondFlag then
-- If there is conduction.
if (t%tchar) <= dt and t >= tchar then
-- Execute the python script for solid block conduction simulation.
os.execute(solidHeatFile)

-- Update the temperature distribution at GSI at the current time level.


Twall_GSI_Curr = {}
for elem in io.lines(outputFile3)():gmatch("%S+") do table.insert(Twall_GSI_Curr, ton
umber(elem)) end

for i=1,nicells_tot do
userPad[i] = Twall_GSI_Curr[i]
end
end
end
end

return
end

function atWriteToFilmHist(t, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- A function to record the state of the thin film at the end of each time step.
--
-- atWriteToFilmHist(float, float) -> nil.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
if thinFilmFlag then

211
if (t%dt_writeFilmHist) <= dt and t >= dt_writeFilmHist then
print("Write Film Flow Solution at :", t)
-- Save the film height distribution at the current time level.
file = io.open("../userData/FilmHeight_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, " ",1, nicells_tot) .. "\n")
file:close()

-- Save the average film velocity distribution at the current time level.
file = io.open("../userData/FilmVelx_Hist.txt","a")
file:write(tostring(t) .. " " .. table.concat(userPad, "
",nicells_tot+1, 2*nicells_tot) .. "\n")
file:close()

else
return
end
end
end

Appendix 4: Heat Conduction Problem


Appendix 4.1: common directory
Appendix 4.1.1: HybridSlab_SimContd.lua
-- Simulation conditions for 2D hybrid slab.
--
-- Filename: HybridSlab_SimContd.lua.
-- Author: Yu Shen Chia.
-- Date: 01/04/2019.
--
-- Last update: 12/07/2019.
--
-- Reference(s): [1] Daniele Bianchi, Barbara Betti and Francesco Nasuti (2015). Simulation of
Gaseous
-- Oxygen/Hydroxyl-Terminated Polybutadiene Hybrid Rocket Flowfields and
Comparison
-- with Experiments.
--
-- [2] Shan F., Lingyun H. and Ying P. (2013). Combustion Performance and Scale
Effect from N2O/HTPB
-- Hybrid Rocket Simulations, Acta Astronautica 85(2013) 1-11.
--
-- [3] Kuo, Kenneth and Chiaverini, Martin (2007). Fundamentals of Hybrid Rocket
Combustion and Propulsion,
-- American Institute of Aeronautics and Astronautics. AIAA Books.
212
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species parameter(s):
-- - gasFrac = A table of gas species mass fractions.
--
-- Geometry parameter(s):
-- - geomType = Geometry type of the fuel grain. Options: 'FLAT', 'CYLINDRICAL' and
'SPHERICAL'.
--
-- Fuel parameter(s):
-- - rhofs = Density of the solid fuel grain (Unit: kg/m^3).
-- - hfs = Pyrolysis enthalpy of the solid fuel grain (J/kg).
-- - kfs = Thermal conductivity of the solid fuel grain (Unit: W/m-K).
-- - Cpfs = Specific heat of the solid fuel (Unit: J/kg-K)
-- - Ea = Activation energy of the regression (Unit: J/mol).
-- - Ru = Universal gas constant (Unit: J/mol-K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
-- - fueFrac = A table of fuel species mass fractions.
--
-- Simulation configuration parameter(s):
-- - ts_Curr = Current simulation time in the solid domain (Unit: s).
--
-- Interface parameter(s):
-- - Twall = Wall temperature (Unit: K).
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Species fractions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
gasFrac = {C4H6 = 0.0, O2 = 1.0, CO = 0.0, H2O = 0.0, CO2 = 0.0}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Geometry and dimensions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Dimensions, from Ref([1]).
Hchb = 0.02 -- [m].
Lchb = 0.25 -- [m].
Hf = 5e-3 -- [m].
Lf = 0.05 -- [m].
Linlet = 0.03 -- [m].
geomType = 'FLAT'

213
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Cells.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Cell size.
AR = 0.25
dx = 6e-4 -- [m].
dy = AR*dx -- [m].

-- Scale factors.
Scale = 2^0.5
S = 0.4*Scale
w0 = 1.5*0.25
w1 = 4.05*0.6
w2 = 4.0
w3 = 0.8025*0.3
w4 = 0.5

-- Number of cells.
nx0 = math.floor(S*w0*Linlet/dx)
nx1 = math.floor(S*w1*0.076*Lchb/dx)
nx2 = 20--math.floor(S*w2*Lf/dx) -- For the injection block.
nx3 = math.floor(S*0.5*w3*(0.924*Lchb - Lf)/dx)
ny = 20--math.floor(S*w4*Hchb/dy)

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- HTPB fuel properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Fuel properties, from Ref([1, 2]).
rhofs = 8.035e2 -- [kg/m^3].
hpyr = 1.82e6 -- [J/kg].
kfs = 1.572e-1 -- [W/m-K].
Cpfs = 1.957e3 -- [J/kg-K].
Ea = 5.589e4 -- [J/mol].
Ru = 8.314 -- [J/mol-K].
Af = 3.965e3 -- [mm/s].
fuelFrac = {C4H6 = 1.0, O2 = 0.0, CO = 0.0, H2O = 0.0, CO2 = 0.0}

-- Thermal time scale.


Scale_Lchar = 1
Lchar = Scale_Lchar*Hf -- [m].

214
alpha = kfs/(rhofs*Cpfs) -- [m^2/s].
tchar = (Lchar^2)/alpha -- [s].
tsteady = 50e-3

-- Solid heat conduction.


solidCondFlag = true
solidHeatFile = 'python3 HybridSlab_Solid.py'

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Source terms and udf configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Ignition setting.
ignFlag = false
nthermal = 10
t_final = nthermal*tsteady -- [s].
T_ign = 1500 -- [K].
t_ignStart = 0.0*t_final -- [s].
t_ignEnd = 0.001*t_final --[s].
x_ignStart = 0.0*Lf -- [m].
x_ignEnd = 0.05*Lf -- [m].

print("Steady time:", tsteady)


print("Final time:", t_final)
print("Thermal time step:", tchar)
-- Radiation setting.
radFlag = false

-- Injection setting.
injectFlag = true

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Gas surface interface (GSI) properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
os.execute("mkdir ../userData")
inputFile1 = '../userData/WallTempHist.txt'
inputFile2 = '../userData/qInputHist.txt'
outputFile1 = '../userData/Twall_Prev.txt'
outputFile2 = '../userData/qInput_Curr.txt'
outputFile3 = '../userData/Twall_Curr.txt'
Twall_GSI_ini = 675.0 -- [K].
Twall_GSI = {}

215
ts_Curr = 0.0 -- [s].

-- Surface velocity of GSI.


u_surf = -10.0 -- [m/s] (At y = 0 m).

-- Print the current simulation time.


print(string.format("Current simulation time in the solid fuel grain: %f s", ts_Curr))

-- Set the initial wall temperature distribution at GSI.


for i=1,nx2 do Twall_GSI[i] = Twall_GSI_ini end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- Melt layer properties.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
thinFilmFlag = false
Tmelt = 241 + 273.15 -- [K], from Ref([3]).
FilmHeight_ini = 1e-6 -- [m] (**Must be greater than zero).
FilmVelx_ini = 0.0 -- [m/s].
BC_List = {"Dirichlet", "Neumann"}
LE_BC = BC_List[1]
TE_BC = BC_List[2]

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- End of input file.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

216
Appendix 4.2: main directory
Appendix 4.2.1: HybridSlab.lua
-- Author: Ingo HJ Jahn
-- Date: 2018-10-10
--
-- This Lua script is used to prepare an Eilmer4
-- simulation to simulate Stokes Second Flow
-- See:
-- Schlichting, H (1979), Boudary-Layer Theory, McGraw-Hill, New York
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Load the simulation parameters.
dofile('../common/HybridSlab_SimContd.lua')

-- Freestream conditions.
P_atm = 101.325e3 -- [Pa].
T_inf = 900.0 -- [K].
gasFrac_inf = gasFrac -- (from input file).

217
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Configurations.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
config.title = "Stokes Second Flow"
print(config.title)

config.interpolation_order = 2
config.dimensions = 2
config.max_time = t_final -- [s].
config.max_step = 250000000
config.dt_init = 1.0e-12 -- [s].
config.turbulence_model = "none"
config.viscous = true
config.flux_calculator = "ausm_plus_up"
config.cfl_value = 0.1
config.dt_plot = t_final/200 -- [s].
config.dt_history = config.max_time/1000 -- [s].

-- Gas model and flow state setup


nsp, nmodes, gmodel = setGasModel('FuelMixture-gas-model.lua')
initial = FlowState:new{p = P_atm, T = T_inf, massf = gasFrac_inf}

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- Flow domain.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++
-- d----N----c
-- | |
-- | |
-- W E
-- | |
-- | |
-- a----S----b
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++

a = Vector3:new{x=-Hchb/2., y=0.0}
b = Vector3:new{x= Hchb/2., y=0.0}

218
c = Vector3:new{x= Hchb/2., y=0.5*Hchb}
d = Vector3:new{x=-Hchb/2., y=0.5*Hchb}

cf = RobertsFunction:new{end0=true,end1=false,beta=1.005}

grid = StructuredGrid:new{psurface=CoonsPatch:new{p00=a, p10=b, p01=d, p11=c},


niv=nx2+1, njv=ny+1,
cfList={east=cf, west=cf} }

-- Boundary conditions:
if injectFlag then
print("Fuel Pyrolysis Boundary Condition is Activated")
config.udf_supervisor_file = "../udf/udf-HybridSlabProcess.lua"
if thinFilmFlag then
-- With melt layer on top of the GSI.
config.user_pad_length = math.floor(6*nx2)
user_pad_data = {}
for i=1,nx2 do
user_pad_data[i] = FilmHeight_ini -- [m] (Current film height
distribution).
user_pad_data[i+nx2] = FilmVelx_ini -- [m/s] (Current average film
velocity distribution).
user_pad_data[i+math.floor(2*nx2)] = FilmHeight_ini -- [m] (Future film height
distribution).
user_pad_data[i+math.floor(3*nx2)] = FilmVelx_ini -- [m/s] (Future average film
velocity distribution).
user_pad_data[i+math.floor(4*nx2)] = Twall_GSI[i] -- [K] (Current film surface
temperature distribution).
user_pad_data[i+math.floor(5*nx2)] = 0.0 -- [K] (Current solid block input
heat flux distribution).
end
print("Thin Film Model is Activated")
else
-- There is no melt layer.
config.user_pad_length = math.floor(2*nx2)
user_pad_data = {}
for i=1,nx2 do
user_pad_data[i] = Twall_GSI[i] -- [K] (Current temperature distribution at GSI).
user_pad_data[i+nx2] = Twall_GSI[i] -- [K] (Current solid block input heat flux
distribution at GSI).
end
user_pad_data[2*nx2 + 1] = 0.0 -- [s] Thermal time scale.
end
blk = FluidBlockArray{grid=grid, initialState=initial, nib=4, njb=6, label='Injection',
bcList={south = UserDefinedFluxBC:new{fileName = '../udf/udf-GSI-
FluxBC.lua'},
north = UserDefinedBC:new{fileName='midplane-bc.lua'},
east = OutFlowBC_SimpleExtrapolate:new{xOrder=0},
west = OutFlowBC_SimpleExtrapolate:new{xOrder=0}}}

219
else
blk = FluidBlockArray{grid=grid, initialState=initial, nib=1, njb=6, label='Injection',
bcList={south = WallBC_NoSlip_FixedT0:new{Twall = Twall_GSI_ini},
north = UserDefinedBC:new{fileName='midplane-bc.lua'},
east = OutFlowBC_SimpleExtrapolate:new{xOrder=0},
west = OutFlowBC_SimpleExtrapolate:new{xOrder=0}}}
end

-- Ensure that the user defined boundary conditions are in the same MPI tasks.
local preassign_List = {}
task_No = 0
for ib=0,18,6 do
preassign_List[ib] = task_No
end

mpiTasks = mpiDistributeBlocks{ntasks=24 - 4, dist="load-balance",preassign=preassign_List}


setHistoryPoint{x = 0.0, y = 0.0, z = 0.0}

Appendix 4.2.2: HybridSlab_Solid.py


import os
import pandas as pd
import numpy as np
from lupa import LuaRuntime

# Global parameters.
lua = LuaRuntime()
inputFile = "../common/HybridSlab_SimContd.lua"
src = open(inputFile).read()
lua.execute(src)
inputParam = lua.globals()

def createJobFile(ts_Curr, HistTime, qInputHist_i, templateName, jobFileName):


"""
A function to create the job file to run the heat conduction problem.

Input(s):
- ts_Curr = Next simulation time in the solid domain (Unit: s).
- HistTime = Time history (Unit: s).
- q_InputHist_i = Input flux history up to the current time level at the current i-position
along GSI (W/m^2).
- templateName = Name of the job file template.
- jobFileName = Name of the output job file.

Output(s):
- None.

createJobFile(float, list<float>, np.array<float>, str, str) -> None.


"""
# Initialise the jobfile template.
fin = open(templateName, 'r')
templateText = fin.read()
fin.close()

220
# Update the fields in the jobfile template.
templateText = templateText.replace('<insert-ts_Curr-here>', str(ts_Curr))
templateText = templateText.replace('<insert-HistTime-here>', str(HistTime))
fieldText = templateText.replace('<insert-qInputHist_i-here>', str(qInputHist_i))

# Output file.
fout = open(jobFileName, 'w')
fout.write(fieldText)
fout.close()
return None

def SolidConduction(ts_Prev, ts_Curr, TwallDistrb_Prev, qInputDistrb_Curr):


"""
A function to predict the current temperature distribution at the fuel surface.

Input(s):
- ts_Prev = Previous simulation time level in the solid domain (Unit: s).
- ts_Curr = Current simulation time level in the solid domain (Unit: s).
- TwallDistrb_Prev = Wall temperature distribution at the previous time level (Constant
up to the current time level) (Unit: K).
- qInputDistrb_Curr = Wall heat flux distribution at the current time level (Unit: J/kg).

Output(s):
- TwallDistrb_Curr = Predicted wall temperature distribution at the current time level
(Unit: K).

SolidConduction(float, float, str, str, str, str) -> None.


"""
# Open the input files.
TwallHist_File = open(inputParam.inputFile1,'a+')
qInputHist_File = open(inputParam.inputFile2,'a+')

# Check if the input file of the wall temperature distribution at GSI is empty.
if os.path.getsize(inputParam.inputFile1) > 0:
# The input file of the wall temperature distribution at GSI is not empty.
None

else:
# The input file of the wall temperature distribution at GSI is empty.
# Write the headers and initial wall temperature distribution at GSI.
TwallHist_File.write(str('#') + ' ' + ' '.join('$' + str(i) for i in
range(0,inputParam.nx2)) + '\n')
TwallHist_File.write(str(ts_Prev) + ' ' + ' '.join(str(Twall_i) for Twall_i in
TwallDistrb_Prev) + '\n')
TwallHist_File.close()
TwallHist_File = open(inputParam.inputFile1,'a+')

# Check if the input file of the input heat fluxes is empty.


if os.path.getsize(inputParam.inputFile2) > 0:
# The input file of the input heat fluxes is not empty.
# Initialise the wall heat flux temperature history at GSI.
qInputHistData = pd.DataFrame(data = np.loadtxt(inputParam.inputFile2))

# Extract time history.


HistTime = qInputHistData.values[1:,0].tolist()
221
else:
# The input file of the input heat fluxes is empty.
# Write the headers only. The initial input heat fluxes are to be determined.
qInputHist_File.write(str('#') + ' ' + ' '.join('$' + str(i) for i in
range(0,inputParam.nx2)) + '\n')
qInputHist_File.write(str(0.0) + ' ' + ' '.join(str(0.0) for i in range(0,inputParam.nx2)) +
'\n')
qInputHist_File.close()
qInputHist_File = open(inputParam.inputFile2,'a+')

# Write the current input heat flux distribution at GSI into its input file.
qInputHist_File.write(str(ts_Curr) + ' ' + ' '.join(str(qInput_i) for qInput_i in
qInputDistrb_Curr) + '\n')
qInputHist_File.close()

# Initialise the updated input file of the input fluxes at GSI using data frame.
qInputHistData = pd.DataFrame(data = np.loadtxt(inputParam.inputFile2))

# Extract time history.


HistTime = qInputHistData.values[1:,0].tolist()

# Initialise the parameters to compute the current wall temperature distribution at GSI.
Twall_CurrArr = list()

# Compute the current wall temperature distribution at GSI based on the heat flux history up
to the current time level.
for i in range(1, inputParam.nx2+1):
# Extract the input heat flux history at the current i-position at GSI.
print("i-position at GSI: {0}/{1}".format(i, inputParam.nx2))
qInputHist_i = qInputHistData.values[1:,i].tolist()

# Create the job file.


createJobFile(ts_Curr, HistTime, qInputHist_i, 'WallTempJob_Template.py',
'WallTempJob_Curr.py')

# Run the jobfile.


os.system('SurfTemp.py --job=WallTempJob_Curr --out-file=WallTemp_Curr.txt')

# Process the output.


outputFile_i = open("WallTemp_Curr.txt", "r")
output_i = outputFile_i.readlines()[-1].split(" ")
output_i.pop(-1)
Twall_Curr_i = float(output_i[-2])
Twall_CurrArr.append(Twall_Curr_i)

# Write the current wall temperature distribution at GSI in the input file.
TwallHist_File.write(str(ts_Curr) + ' ' + ' '.join(str(Twall_i) for Twall_i in Twall_CurrArr)
+ '\n')
TwallHist_File.close()

# Write the current wall temperature distribution at GSI in the input file for the userPad in
Eilmer.
TwallCurr_File = open(inputParam.outputFile3,'a+')
TwallCurr_File.write(' '.join(str(Twall_i) for Twall_i in Twall_CurrArr))
222
TwallCurr_File.close()
return None

if __name__ == '__main__':
"""
Main
"""
TwallData_Prev = pd.DataFrame(data = np.loadtxt(inputParam.outputFile1))
qInputData_Curr = pd.DataFrame(data = np.loadtxt(inputParam.outputFile2))
TwallData_Prev = [i[0] for i in TwallData_Prev.values]
qInputData_Curr = [j[0] for j in qInputData_Curr.values]
ts_Prev = TwallData_Prev[0]
ts_Curr = qInputData_Curr[0]
TwallDistrb_Prev = TwallData_Prev[1:]
qInputDistrb_Curr = qInputData_Curr[1:]
SolidConduction(ts_Prev, ts_Curr, TwallDistrb_Prev, qInputDistrb_Curr)

Appendix 4.2.3: WallTempJob_Template.py


"""
Solving the heat conduction problem for the surface temperature at the gas-Surface Interface.

Author : Ingo H. Jahn.


Adapted by : Yu Shen Chia.
Created : 05/05/2019.

Version: 1.0.

"""
# Global parameters.
from HybridSlab_Solid import *

ts_Curr = '<insert-ts_Curr-here>'
HistTime ='<insert-HistTime-here>'
qInputHist_i = '<insert-qInputHist_i-here>'

# settings for run


gdata.qUpdatedMode = 'firstOrderHold' # approach taken to update
gdata.scheme = 'IMPLICIT' # Set scheme used foor solutuion. Options: 'IMPLICIT', 'EXPLICIT'
gdata.method = 'UNITSTEP' # set method for how response is calculated. Options 'IMPULSE',
'UNITSTEP'
gdata.subcycle = None # Set number of subcycles. Set to None or 1 to switch off.
gdata.geometry = inputParam.geomType # set of equations used Options: 'flat', 'cylindrical',
'spherical'
gdata.N_coeff = 20 # Number of coefficients used
gdata.tStart = 0. # [s] set starting time
gdata.tEnd = eval(ts_Curr) # [s] set end time
gdata.timeSteps = 20 # [-] number of steps used for temporal solution
gdata.spaceSteps = 10 # [-] number of steps used for spatial solution
gdata.dtplot = 0.1 # [s] time interval between plots
gdata.graph = 'SINGLE' # Set if output plotted in single or multiple figures. Options: 'SINGLE',
'MULTIPLE'

223
# set how heat transfer is set at end0 and end1
if True:
end0_HTC.type = 'set_Q'
end0_HTC.time = eval(HistTime) # Time history up to the end (current) time.
end0_HTC.value= eval(qInputHist_i) # Wall input heat flux history up to the end (current)
time.
end0_HTC.radiationFlag = False # True/False switch if radiation modelling is includes
end0_HTC.radiationEmissivity = 0.8 # [-] emissivity
else:
end0_HTC.type = 'adiabatic'

if False:
end1_HTC.type = 'set_Q'
end1_HTC.time = eval(HistTime)
end1_HTC.value= eval(qInputHist_i) # Will be updated every time.
end1_HTC.radiationFlag = False # True/False switch if radiation modelling is includes
end1_HTC.radiationEmissivity = 0.8 # [-] emissivity
else:
end1_HTC.type = 'adiabatic'

# Define the wall that will be modelled


wall.x0 = 0.0 # [m] thickness of wall to be analysed
wall.x1 = inputParam.Lchar # [m] thickness of fuel to be analysed
wall.density = inputParam.rhofs # [kg / m3] density of wall material
wall.thermalConductivity = inputParam.kfs # [W/m-K] thermal conductivity
wall.specificHeat = inputParam.Cpfs # [J /kg-K)]
wall.temperatureStart = inputParam.Twall_GSI_ini # [K] Solid fuel temperature at start
# wall.end0_BC = BC1 # boundary condition for end0
# wall.end1_BC = BC2 # boundary condition for end0

# define what and how data will be post-processed


# post.start = 1

Appendix 4.3: udf directory


Appendix 4.3.1: udf-GSI-FluxBC.lua
-- Simplified Gas-surface interface boundary condition for the hybrid slab.
-- Author: Yu Shen Chia.
-- Date: 31/03/2019.
--
-- Last update : 23/08/2019.
--
-- Reference(s): [1] Gariani G., Maggi F. and Galfetti L. (2011). Numerical simulation of HTPB
combustion
-- in a 2D Hybrid Slab Combustor, Acta Astronautical 69(2011) 289-296.
--
-- [2] P. A. Jacobs∗, R. J. Gollan†, A. J. Denman, B. T. O’Flaherty,
-- D. F. Potter, P. J. Petrie-Repar and I. A. Johnston. (2012). Eilmer’s Theory
Book:
-- Basic Models for GasDynamics and Thermochemistry, School of Mechanical and
Mining
-- Engineering.

224
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- GSI Boundary Condition Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- General variables.
local blkId_L, blkId_R, ib
local tsCurr = nil
local Af = Af
local Ea = Ea
local Ru = Ru
local fuelFrac = fuelFrac
local gm = GasModel:new{'../main/FuelMixture-gas-model.lua'}
local fuelFrac = fuelFrac
local rhofs = rhofs
local dudy = 0.0
local dvdx = 0.0
local dvdy = 0.0
local sigma_yy = 0.0
local sigma_yx = 0.0
local dTdy = 0.0
local Adjcell = {}
local Adjcell_L = {}
local Adjcell_R = {}
local icell = 0.0
local icell_L, icell_R
local GSI_State = {}
local mdotf = 0.0
local v_inject = 0.0
local v_nxt = 0.0
local Flux = {}
local State= GasState:new{gm}
local GSI_State_nxt = {}
local SpeciesName, SpeciesFrac
local hfg, hfs, qInput_i

-- Additional variables for the thin-film model.


local grad_transVar_i, transVar_i, transVar_i_nxt, Si, dxi, dt
local Tfmean_i, Film_State, Film_State_nxt, mdotSurf, mdotMelt, v_pyr, u_FilmSurf, sigma_MeltSurf,
Smass, Smom
local spatialDeriv_FilmHeight, spatialDeriv_FilmVelx
local dPgdx, dPvapdx, Pvap_R, Pvap
local Adjcell_sub, Adjcell_subR, Adjcell_subL, icell_sub, ibsub
local ibmax = #fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray
local file

-- Total number of cells along the thin film.


local nicells_tot = nx2
225
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- General Functions.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

function RegressionRate(Twall)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the regression rate at the gas-surface interface (GSI), from Ref([1]).
--
-- Intermediate parameter(s):
-- - Ea = Activation energy of the regression (Unit: kJ/mol).
-- - Ru = Universal gas constant (Unit: J/mol.K).
-- - Af = Pre-exponential factor for the fuel regression rate equation (Unit: mm/s).
--
-- Input(s):
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - Regression rate of the fuel (Unit: m/s).
--
-- RegressionRate(float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

return Af*math.exp(-Ea/(Ru*Twall))*1e-3
end

function getNcellsRecursion(ib)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to calculate the number of cells in the ith-direction from the first to the current
-- block at the gas-surface interface (GSI). Recursive method and modularity of blocks are
imposed.
--
-- Input(s):
-- - ib = Block Id.
--
-- Output(s):
-- - Number of cells in the ith-direction from the first to the current block.
--
-- getNcellsRecursion(int) -> int.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

if ib == fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then
-- First sub-block at GSI.
226
return infoFluidBlock(ib).nicell

elseif ib < fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[1][1][1] then


-- Before the first sub-block at GSI.
return 0

else
-- Sub-blocks at GSI.
return (infoFluidBlock(ib).nicell
+ getNcellsRecursion(ib-fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb))
end

end

function FuelState(Pwall, Twall)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the fuel state at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - fueFrac = A table of fuel species mass fractions.
--
-- Input(s):
-- - Pwall = Wall pressure at GSI (Unit: Pa).
-- - Twall = Wall temperature at GSI (Unit: K).
--
-- Output(s):
-- - OutputState = A table of fuel state properties at GSI.
--
-- FuelState(float, float) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Define local parameters.


OutputState = {}

-- Compute the fuel state.


State.p = Pwall
State.T = Twall
State.massf = fuelFrac
gm:updateThermoFromPT(State)
gm:updateTransCoeffs(State)
OutputState.rho = State.rho
OutputState.e = gm:intEnergy(State)
OutputState.mu = State.mu

return OutputState
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Moving Wall Functions.
227
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function ThinFilm_ODE(spatialDeriv_i, Si)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to compute the gradient of the transport variables of the thin-film.
--
-- The gradient of the transport variables is devised from the governing equations of the thin
film by
-- using the method of lines and the finite volume method (FVM) discretisation. The FVM
discretisation
-- scheme is upwind.
--
-- Input(s):
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell index.
-- - Si = Source term that pertains to the transport variable at the current cell
index.
--
-- Output(s):
-- - grad_transVar_i = Time derivative of the transport variable at the current cell index.
--
-- ThinFilm_ODE(float, float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
grad_transVar_i = Si - spatialDeriv_i

return grad_transVar_i
end

function Integration_Euler(transVar_i, spatialDeriv_i, Si, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to numerically integrate the governing equations of the thin film by using the
euler method.
--
-- Input(s):
-- - transVar_i = Transport variable at the current time level and current cell index.
-- - spatialDeriv_i = Spatial derivative of the transport variable at the current cell index.
-- - Si = Source term that pertains to the transport variable at the current cell
index.
-- - dt = Current time step (Unit: s).
--
-- Output(s):
-- - transVar_i_Nxt = Transport variable at the next time level and current cell index.
--
-- Integration_Euler(float, float, float) -> float.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
transVar_i_Nxt = transVar_i + dt*ThinFilm_ODE(spatialDeriv_i, Si)

228
return transVar_i_Nxt
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- Main Function.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
function convectiveFlux(args)
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++
-- A function to model the fuel injection at the gas-surface interface (GSI).
--
-- Intermediate parameter(s):
-- - Adjcell = A table of state properties of the interior cell adjacent to GSI.
-- - icell = Current cell index originating from the leading edge of GSI. Range: icell
>= 0.
-- - njb = Number of blocks in the jth-direction.
-- - Twall_GSI = Wall temperature distribution at GSI (Unit: K).
-- - GSI_State = A table of fuel state properties at GSI.
-- - rhofs = Solid fuel density (Unit: kg/m^3).
-- - mdotf = Mass flux of the injected fuel (Unit: kg/s*m^2).
-- - v_inject = Fuel injection velocity (Unit: m/s).
-- - dudy = Gradient of the x-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - dvdx = Gradient of the y-velocity w.r.t x-coordinate at GSI (Unit: 1/s).
-- - dvdy = Gradient of the y-velocity w.r.t y-coordinate at GSI (Unit: 1/s).
-- - sigma = Viscous shear stress (Unit: Pa).
-- - dTdy = Gradient of the temperature w.r.t y-coordinate at GSI (Unit: K/m).
--
-- Input(s):
-- - args = A table of state properties.
--
-- Output(s):
-- - Flux = A table of inviscid flux properties at GSI.
--
-- convectiveFlux(table<var, float>) -> table<var, float>.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++

-- Extract the flow properties of the interior cell adjacent to GSI.


Adjcell = sampleFluidCell(blkId, args.i, args.j, args.k) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI. Range: icell >=
1.
icell = getNcellsRecursion(blkId - fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb) +
args.i - 1

-- Determine the adjacent cell properties on the right.


icell_R = args.i + 1
Adjcell_R = sampleFluidCell(blkId, icell_R, args.j, args.k) -- (At y = 0+ m).

229
-- Determine the adjacent cell properties on the left.
icell_L = args.i - 1
Adjcell_L = sampleFluidCell(blkId, icell_L, args.j, args.k) -- (At y = 0+ m).

-- Initialise the flux table.


Flux = {}

if thinFilmFlag then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 1: With Film Flow.
--
-- Note(s):
-- [1] Only valid for a film that is isothermal and has constant density.
-- [2] Only valid for 1D film flow.
-- [3] Only valid when the initial film height is greater than zero.
-- [4] Only consider the continuity and momentum transport equations of the film.
-- [5] The continuity and momentum transport equations are tightly coupled to the solver,
whereas
-- the energy transport equation is loosely coupled to the solver.
-- [6] For the mass source term of the film, the vaporosation flux on the film surface and
melting
-- flux on the solid fuel are both governed by the same pyrolysis law (Applies to HTPB
fuel).
-- [7] For the momentum soruce term of the film, only the gas-film shear stress and solid-
film
-- shear stress are considered.
-- [8] Zero pressure gradient in the normal and tangential directions of the film.
-- [9] Quadratic velocity profile.
--
-- userPad entries:
-- [1] userPad[1:nicells_tot] = Spatial distribution of film height at the current time
level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of average film
velocity at
-- the current time level.
-- [3] userPad[(2*nicells_tot+1):3*nicells_tot] = Spatial distribution of film height at
the next
-- time level.
-- [4] userPad[(3*nicells_tot+1):4*nicells_tot] = Spatial distribution of average film
velocity at
-- the next time level.
-- [5] userPad[(4*nicells_tot+1):5*nicells_tot] = Spatial distribution of the film surface
temperature
-- at the current time level.
-- [6] userPad[(5*nicells_tot+1):6*nicells_tot] = Spatial distribution of the solid block
input heat
-- flux at the current time level.
--
-- **Warning:
-- [1] Do not parallelize along this boundary condition, because the governing equations
of this
-- boundary condition (thin film model) is not parallellized.

230
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

-- Calculate the mean film temperature (Assuming linear temperature profile in the film).
Tfmean_i = 0.5*(userPad[icell + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the properties on the film surface based on the film surface temperature.
-- (Assuming the film is already established).
GSI_State = FuelState(Adjcell.p, userPad[icell + 4*nicells_tot]) -- (At y = 0 m).

-- Calculate the mean properties of the film based on the mean film temperature.
-- (Assuming the film is already established).
Film_State = FuelState(Adjcell.p, Tfmean_i) -- (At y = 0- m).

-- Calculate the injection velocity on the film surface based on the film surface temperature.
-- (Assuming the film is already established).
mdotSurf = Film_State.rho*RegressionRate(userPad[icell + 4*nicells_tot]) -- [kg/s] (At y =
0 m).
v_inject = mdotSurf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the injection/normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density and
film
-- state of that cell.
GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell + 4*nicells_tot + 1]) -- (At y = 0
m).
Film_State_nxt = FuelState(Adjcell_R.p, 0.5*(userPad[icell + 4*nicells_tot + 1] + Tmelt))
-- (At y = 0- m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = Film_State_nxt.rho*RegressionRate(userPad[icell + 4*nicells_tot +
1])/GSI_State_nxt.rho -- [m/s] (At y = 0 m).
end

-- Surface velocity of the film (Based on the quadratic velocity profile assumption).
u_FilmSurf = 1.5*userPad[icell + nicells_tot] + u_surf -- [m/s] (At y = 0 m).

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


-- (Assuming the film is already established).
dudy = (Adjcell.velx - u_FilmSurf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

231
-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
-- (Assuming the film is already established).
dTdy = (Adjcell.T - userPad[icell + 4*nicells_tot])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotSurf -- (At y = 0 m).
Flux.momentum_x = GSI_State.rho*u_FilmSurf*v_inject - sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotSurf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0
Flux.total_energy = mdotSurf*(GSI_State.e + 0.5*math.pow(v_inject, 2) +
Adjcell.p/GSI_State.rho)
- (sigma_yx*u_FilmSurf + sigma_yy*v_inject + Adjcell.k*dTdy) -
- (At y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] =


mdotSurf*SpeciesFrac end

if args.i == infoFluidBlock(blkId).imax and blkId


==fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][1] then
-- Update the film state.
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1]
for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI. Range:
icell >= 1.
icell_sub = getNcellsRecursion(ibsub -
fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb) + i - 1

-- Extract the cell properties on the left of the current cell.


Adjcell_subL = sampleFluidCell(ibsub, i - 1, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the injection mass flux and velocity.


GSI_State = FuelState(Adjcell.p, userPad[icell_sub + 4*nicells_tot]) -- (At y = 0
m).
mdotf = rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0 m).
v_inject = mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the mean film temperature (Assuming linear temperature profile in the
film).
Tfmean_i = 0.5*(userPad[icell_sub + 4*nicells_tot] + Tmelt) -- (At y = 0- m).

-- Calculate the mean properties of the film based on the mean film temperature.
-- (Assuming the film is already established).
Film_State = FuelState(Adjcell_sub.p, Tfmean_i) -- (At y = 0- m).

-- Calculate the injection velocity on the melt surface based on the melting
temperature.
mdotMelt = rhofs*RegressionRate(Tmelt) -- [kg/s] (At y = 0- m).
232
v_pyr = mdotMelt/Film_State.rho -- [m/s] (At y = 0- m).

-- Calculate the injection/normal velocity at the south boundary of the next right
cell.
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature
array, then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel
density and film
-- state of that cell.
GSI_State_nxt = FuelState(Adjcell_subR.p, userPad[icell_sub + 4*nicells_tot + 1])
-- (At y = 0 m).
Film_State_nxt = FuelState(Adjcell_subR.p, 0.5*(userPad[icell_sub + 4*nicells_tot
+ 1] + Tmelt)) -- (At y = 0- m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using
mass balance.
v_nxt = Film_State_nxt.rho*RegressionRate(userPad[icell_sub + 4*nicells_tot +
1])/GSI_State_nxt.rho -- [m/s] (At y = 0 m).
end

-- Surface velocity of the film (Based on the quadratic velocity profile assumption).
u_FilmSurf = 1.5*userPad[icell_sub + nicells_tot] + u_surf -- [m/s] (At y = 0 m).

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


-- (Assuming the film is already established).
dudy = (Adjcell_sub.velx - u_FilmSurf)/Adjcell_sub.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_subR.x - Adjcell_sub.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell_sub.vely - v_inject)/Adjcell_sub.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell
index.
-- (Assuming the film is already established).
dTdy = (Adjcell_sub.T - userPad[icell_sub + 4*nicells_tot])/Adjcell_sub.y -- [K/m]
(At y = 0 m).

-- Calculate the gas-phase streamwise pressure gradient that adjacent to the thin
film.
-- (Assuming zero normal pressure gradient, dPgdy = 0).
dPgdx = (Adjcell_subR.p - Adjcell_sub.p)/(Adjcell_subR.x - Adjcell_sub.x)

-- Calculate the tangential film-wall viscous shear stress on the melt surface at
the current cell index.
-- (Assuming the film is already established).
sigma_MeltSurf = 3*Film_State.mu*userPad[icell_sub +
nicells_tot]/userPad[icell_sub] -- [Pa] (At y = 0- m).

-- Calculate the mass source term.


233
-- (Assuming the film is already established).
Smass = -RegressionRate(userPad[icell_sub + 4*nicells_tot]) + v_pyr -- [m/s].

-- Compute the momentum source term.


-- (Assuming the film is already established).
Smom = (sigma_yx - sigma_MeltSurf - userPad[icell_sub]*dPgdx)/Film_State.rho

-- Compute the cell spacing.


dxi = Adjcell_subR.x - Adjcell_subL.x -- [m].

-- Upwind scheme.
if userPad[icell_sub + nicells_tot] >= 0 then
-- When the average film velocity at the current cell index is not negative.
if icell_sub > 1 then
-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub +
nicells_tot]*userPad[icell_sub] -
userPad[icell_sub + nicells_tot -
1]*userPad[icell_sub - 1])

spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub +
nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub] -
userPad[icell_sub + nicells_tot -
1]*userPad[icell_sub + nicells_tot - 1]*userPad[icell_sub - 1])
else
if LE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
leading edge of the thin film.
spatialDeriv_FilmHeight = (2/dxi)*userPad[icell_sub +
nicells_tot]*userPad[icell_sub]
spatialDeriv_FilmVelx = (2/dxi)*userPad[icell_sub +
nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

elseif LE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed at
the leading edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.
end -- Close the conditional comparison of the cell index along GSI.
else
-- When the average film velocity at the current cell index is negative.
Mass_transVar_i = userPad[icell_sub + 1]
Mom_transVar_i = userPad[icell_sub + nicells_tot + 1]*userPad[icell_sub + 1]

if icell_sub < nicells_tot then


-- Calculate the spatial derivatives for the transport variables.
spatialDeriv_FilmHeight = (2/dxi)*(userPad[icell_sub + nicells_tot +
1]*userPad[icell_sub + 1] -
userPad[icell_sub +
nicells_tot]*userPad[icell_sub])

spatialDeriv_FilmVelx = (2/dxi)*(userPad[icell_sub + nicells_tot +


1]*userPad[icell_sub + nicells_tot + 1]*userPad[icell_sub + 1] -

234
userPad[icell_sub +
nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub])
else
if TE_BC == "Dirichlet" then
-- Zero film height and velocity boundary condition is imposed at the
trailing edge of the thin film.
spatialDeriv_FilmHeight = -(2/dxi)*userPad[icell_sub +
nicells_tot]*userPad[icell_sub]

spatialDeriv_FilmVelx = -(2/dxi)*userPad[icell_sub +
nicells_tot]*userPad[icell_sub + nicells_tot]*userPad[icell_sub]

elseif TE_BC == "Neumann" then


-- Zero film height and velocity gradient boundary condition is imposed at
the trailing edge of the thin film.
spatialDeriv_FilmHeight = 0.0
spatialDeriv_FilmVelx = 0.0
end -- Close the conidtional comparison of the film boundary condition.
end -- Close the conditional comparison of the cell index along GSI.
end -- Close the conditional comparison of the directionality of the film velocity
at the current cell index.
-- Calculate the new time level film height at the current cell index.
userPad[icell_sub + 2*nicells_tot] = Integration_Euler(userPad[icell_sub],
spatialDeriv_FilmHeight, Smass, args.dt)

-- Calculate the new time level average film velocity at the current cell index.
userPad[icell_sub + 3*nicells_tot] =
Integration_Euler(userPad[icell_sub]*userPad[icell_sub + nicells_tot],
spatialDeriv_FilmVelx, Smom,
args.dt)/userPad[icell_sub + 2*nicells_tot]
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the film state at the new time level.


file = io.open("../userData/FilmHeight_Nxt.txt","w")
file:write(table.concat(userPad, " ",2*nicells_tot+1, 3*nicells_tot))
file:close()
file = io.open("../userData/FilmVelx_Nxt.txt","w")
file:write(table.concat(userPad, " ",3*nicells_tot+1, 4*nicells_tot))
file:close()
end -- Close the conditional comparison of the minimum i-index of the current MPI block.
else
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Case 2: Without Film Flow.
--
-- userPad entries:
-- [1] userPad[(1:nicells_tot] = Spatial distribution of the GSI temperature at the current
time
-- level.
-- [2] userPad[(nicells_tot+1):2*nicells_tot] = Spatial distribution of the solid block
input heat
-- flux at the current time level.

235
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- Calculate the vaporised fuel properties on GSI at the current cell index.
--GSI_State = FuelState(Adjcell.p, userPad[icell]) -- (At y = 0 m).

-- Calculate the fuel injection velocity on GSI at the current cell index by using mass
balance.
mdotf = 0.0--rhofs*RegressionRate(userPad[icell]) -- [kg/s] (At y = 0 m).
v_inject = 0.0--mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right cell.
if icell + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI temperature array,
then
-- the next right cell is after the trailing edge of GSI, which is a slip wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised fuel density state
of that
-- cell.
--GSI_State_nxt = FuelState(Adjcell_R.p, userPad[icell+1]) -- (At y = 0 m).

-- Calculate the fuel injection velocity of the next right cell at GSI by using mass
balance.
v_nxt = 0.0--rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho -- [m/s] (At y = 0
m).
end

-- Calculate gas-phase velocity gradients on GSI at the current cell index.


dudy = (Adjcell.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_R.x - Adjcell.x) -- [1/s] (At y = 0 m).
dvdy = (Adjcell.vely - v_inject)/Adjcell.y -- [1/s] (At y = 0 m).

-- Calculate the gas-phase viscous shear stresses on GSI at the current cell index.
sigma_yy = 2*Adjcell.mu*dvdy + (-2/3)*Adjcell.mu*dvdy -- [Pa] (At y = 0 m).
sigma_yx = Adjcell.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).

-- Calculate the gas-phase normal temperature gradient on GSI at the current cell index.
dTdy = (Adjcell.T - userPad[icell])/Adjcell.y -- [K/m] (At y = 0 m).

-- Calculate the enthalpy of the gaseous injected fuel (After phase change).
hfg = 0.0 --GSI_State.e + 0.5*math.pow(v_inject, 2) + Adjcell.p/GSI_State.rho -- [J/kg].

-- Calculate the inviscid and viscous fluxes at GSI.


Flux.mass = mdotf -- (At y = 0 m).
Flux.momentum_x = -sigma_yx -- (At y = 0 m).
Flux.momentum_y = Adjcell.p + mdotf*v_inject - sigma_yy -- (At y = 0 m).
Flux.momentum_z = 0.0 -- (At y = 0 m).
Flux.total_energy = mdotf*hfg - (sigma_yx*u_surf + sigma_yy*v_inject + Adjcell.k*dTdy) -- (At
y = 0 m).
Flux.species = {} -- (At y = 0 m).

for SpeciesName, SpeciesFrac in pairs(fuelFrac) do Flux.species[SpeciesName] =


mdotf*SpeciesFrac end
236
if solidCondFlag then
if (args.t%tsteady) <= args.dt and args.t >= tsteady then
-- Predict the future temperature distribution at GSI.i
if args.i == infoFluidBlock(blkId).imax and blkId
==fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ibmax][1][1] then
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
-- Energy balance:
-- qInput_i == qCond_i = qConv_i - mdotf*(hfg - hfs)
--
-- where:
-- hfs = Enthalpy of the fuel surface at solid state during phase change.
--
-- As hfs is an unknown and note that hpyr (Pyrolysis enthalpy) = hfg - hfs, it
follows that:
-- qInput_i == qCond_i = qConv_i - mdotf*hpyr
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
for ib=1,ibmax do
ibsub = fluidBlockArrays[fluidBlockArraysDict["Injection"]].blockArray[ib][1][1]

for i=infoFluidBlock(ibsub).imin,infoFluidBlock(ibsub).imax do
-- Extract the cell properties of the current cell.
Adjcell_sub = sampleFluidCell(ibsub,i, 2, 0.0) -- (At y = 0+ m).

-- Extract the cell properties on the right of the current cell.


Adjcell_subR = sampleFluidCell(ibsub, i + 1, 2, 0.0) -- (At y = 0+ m).

-- Calculate the current cell index originating from the leading edge of GSI.
Range: icell >= 1.
icell_sub = getNcellsRecursion(ibsub -
fluidBlockArrays[fluidBlockArraysDict["Injection"]].njb) + i - 1

-- Calculate the injection mass flux and velocity.


--GSI_State = FuelState(Adjcell.p, userPad[icell])
mdotf = 0.0--rhofs*RegressionRate(userPad[icell_sub]) -- [kg/s] (At y = 0
m).
v_inject = 0.0--mdotf/GSI_State.rho -- [m/s] (At y = 0 m).

-- Calculate the normal velocity at the south boundary of the next right cell.
if icell_sub + 1 > nicells_tot then
-- If the next right cell index is greater than the size of the GSI
temperature array, then
-- the next right cell is after the trailing edge of GSI, which is a slip
wall.
v_nxt = 0.0 -- [m/s] (At y = 0 m; No penetration condition at the slip
wall).
else
-- If the next right cell index is still at GSI, calculate the vaporised
fuel density state of that cell.
--GSI_State_nxt = FuelState(Adjcell_R.p, userPad[i+1]) -- (At y = 0 m).

237
-- Calculate the fuel injection velocity of the next right cell at GSI by
using mass balance.
v_nxt = 0.0--rhofs*RegressionRate(userPad[icell+1])/GSI_State_nxt.rho --
[m/s] (At y = 0 m).
end

-- Compute the shear stress and temperature gradient at GSI.


dudy = (Adjcell_sub.velx - u_surf)/Adjcell.y -- [1/s] (At y = 0 m).
dvdx = (v_nxt - v_inject)/(Adjcell_subR.x - Adjcell_sub.x) -- [1/s] (At y = 0
m).
dvdy = (Adjcell_sub.vely - v_inject)/Adjcell_sub.y -- [1/s] (At y = 0 m).
sigma_yy = 2*Adjcell_sub.mu*dvdy + (-2/3)*Adjcell_sub.mu*dvdy -- [Pa] (At y =
0 m).
sigma_yx = Adjcell_sub.mu*(dudy + dvdx) -- [Pa] (At y = 0 m).
dTdy = (Adjcell_sub.T - userPad[icell_sub])/Adjcell_sub.y -- [K/m] (At y = 0
m).

-- Store the input heat flux of the solid fuel in userPad.


userPad[icell_sub + nicells_tot] = Adjcell_sub.k*dTdy + sigma_yx*u_surf +
sigma_yy*v_inject - mdotf*hpyr -- [J/kg] (At y = 0- m).
end -- Close the for loop iteration of the cell index of the current MPI block.
end -- Close the for loop iteration of the MPI block index.

-- Save the wall temperature distribution at GSI at the previous (current) time
level.
file = io.open(outputFile1,"w")
file:write(tostring(math.floor(args.t/tsteady)*tchar - tchar) .. " " ..
table.concat(userPad, " ",1, nicells_tot))
file:close()

-- Save the input heat flux of the solid block at the current time level.
file = io.open(outputFile2,"w")
file:write(tostring(math.floor(args.t/tsteady)*tchar) .. " " ..
table.concat(userPad, " ",nicells_tot+1, 2*nicells_tot))
file:close()
--os.execute(solidHeatFile)
end -- Close the conditional comparison of the minimum i-index of the current MPI block.
end -- Close the conditional comparison of the instant to update the surface temperature
distribution on GSI.
end -- Close the conditional statement for the solidCondFlag.
end -- Close the conditional statement for the thinFilmFlag.
return Flux
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

API • Code • Made by Alexander Kojevnikov • Powered by Flask and Pygmen

238
Appendix 4.3.2: udf-HybridSlabProcess.lua
- A supervisor file to update the state of the thin film.
-- Author: Yu Shen Chia.
-- Date: 24/08/2019.
--
-- Last update : 24/08/2019.
--
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- HybridSlab process script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

-- Initialize the global simulation parameters.


dofile('../common/HybridSlab_SimContd.lua')
dofile('../main/config/HybridSlab.fluidBlockArrays')

-- Total number of cells along the thin film.


local nicells_tot = nx2

-- Tables for file saving.


local FilmHeight_Nxt, FilmVelx_Nxt

function atTimestepEnd(t,steps, dt)


--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++
-- A function to update the state of the thin film at the end of each time step.
--
-- atTimestepEnd(float, float, float) -> nil.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++

if in_mpi_context and not is_master_task then return end

if thinFilmFlag then
-- Update the film state if there is a melt layer.
if (steps % 1) == 0 then
-- Initialise the tables for saving.
FilmHeight_Nxt = {}
FilmVelx_Nxt = {}

for elem in io.lines("../userData/FilmHeight_Nxt.txt")():gmatch("%S+") do


table.insert(FilmHeight_Nxt, tonumber(elem)) end
for elem in io.lines("../userData/FilmVelx_Nxt.txt")():gmatch("%S+") do
table.insert(FilmVelx_Nxt, tonumber(elem)) end

for i=1,nicells_tot do
-- Update the spatial distribution of the film height.
userPad[i] = FilmHeight_Nxt[i]

239
-- Update the spatial distribution of the average film velocity.
userPad[i+nicells_tot] = FilmVelx_Nxt[i]
end
end
else
-- Without melt layer.
if solidCondFlag then
-- If there is conduction.
if (t%tsteady) <= dt and t >= tsteady then
-- Execute the python script for solid block conduction simulation.
os.execute(solidHeatFile)

-- Update the temperature distribution at GSI at the current time level.


Twall_GSI_Curr = {}
for elem in io.lines(outputFile3)():gmatch("%S+") do table.insert(Twall_GSI_Curr,
tonumber(elem)) end

for i=1,nicells_tot do
userPad[i] = Twall_GSI_Curr[i]
end
userPad[2*nicells_tot + 1] = math.floor(t/tsteady)*tchar
end
end
end

return
end

--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++
-- End of Script.
--
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++

240

You might also like