Final Report Jan2017
Final Report Jan2017
Project work:
Disclaimer: This is a student project work, done as part of a course where OpenFOAM and some
other OpenSource software are introduced to the students. Any reader should be aware that it
might not be free of errors. Still, it might be useful for someone who would like learn some details
similar to the ones presented in the report and in the accompanying files. The material has gone
through a review process. The role of the reviewer is to go through the tutorial and make sure that
it works, that it is possible to follow, and to some extent correct the writing. The reviewer has no
responsibility for the contents.
How to use it
• how the tutorial case is set up before running the chtMultiRegionFoam solver in FOAM-
extend-4.0 (Section 2.2).
• how to visualize the chtMultiRegionFoam cases in FOAM-extend-4.0 by paraView (Section
5.1).
The theory of it
• the code structure of the chtMultiRegionFoam solver (Section 2.1 and 3.1).
• the theory of the PIMPLE algorithm (Section 3.2).
• the equations of the conjugate heat transfer in fluid and solid regions (Section 3.3-3.4).
• the boundary condition coupling algorithm for multiple regions/physics (Section 3.5).
How it is implemented
• how to implement multiple time steps for multiple regions in chtMultiRegionFoam solver by
two different approaches (Section 4.1).
• how to test the implemented solvers (Section 4.2.2 and Section 4.3.2).
How to modify it
• how to modify the PIMPLE loop and other corresponding files to introduce an extra time step
for the solid regions (Section 4.2-4.3).
• how to modify the current temperature-coupled boundary condition into a new pressure-
coupled boundary condition (Chapter 6).
1
Acknowledgements
I would like to thank Professor Håkan Nilsson for providing the course of CFD with open-source
software OpenFOAM and the continuous support from him during this project. I am greatly ben-
efited from this course. I would like to express my special gratitude to Gregor Cvijetić for his help
and very useful advices for my project. I also appreciate the communication and knowledge sharing
from Turo Välikangas, for we were both working on the conjugate heat transfer solvers.
I am immensely grateful to my supervisor Professor Muk Chen Ong in the University of Stavanger;
without his support, I would not have the chance to go for this course.
Many thanks to all the classmates in this course for we have shared a good time and knowledge
with each other.
2
Contents
1 Introduction 4
3
Chapter 1
Introduction
contains multiple region(s) with the same physical property. For example, in chtMultiRegionFoam, there are only
two domains (fluid and solid), while there are multiple regions (such as the topAir, bottomAir) for each domain.
4
CHAPTER 1. INTRODUCTION 5
For solving the unsteady fluid regions in OpenFOAM, to achieve temporal accuracy and numerical
stability, a Courant number less than 1 is required [2]. The Courant number is defined for one cell
as
δt|U |
Co = (1.1)
δx
where δt is the time step, |U | is the magnitude of the velocity through that cell and δx is the length
scale of the cell in the direction of the velocity. Therefore, the setting of the time step δt should be
small enough to satisfy the Courant number requisition. What is more, for solving the free surface
or turbulent problems, the cell size needs to be small enough to achieve more accurate results. On
the contrary, in solid mechanics, the mesh size and time step can be relatively larger compared to
solving the fluids. Therefore, for some multi-physics problems, it is not efficient to calculate the
multiple regions with the same mesh size and time step.
The chtMultiRegionFoam solver has interface mesh mapping that allows non-conformal meshes
and it has access to interface coupling functionality. However, the fluid and solid regions are solved
with the same time step in a loop, which needs to be modified to our case. To achieve multiple time
steps for each physical domain based on the chtMultiRegionFoam solver, the following modifications
need to be implemented:
• First, a different time step for the solid regions is to be introduced.
• Then the multi-region PIMPLE loop is to be modified to solve different domains in various
time steps.
• Two approaches to implement the multiple time steps are to be demonstrated: one approach
allows the adjustment of the time step while the other does not.
• Info statements for debugging purposes are to be added into the codes.
• Case studies are to be conducted to verify the new solvers.
CHAPTER 1. INTRODUCTION 6
In addition to the implementation of the multiple time steps, a new boundary condition called
solidWallMixedPressureCoupled which applies a pressure mapping between the fluid and solid
regions for WSS interaction is developed. The boundary condition is tested but not verified at this
stage.
To finalize the WSS solver, further work needs to be performed, such as the modification of the
solid solver and fluid solver. Due to the time limitation of this project, these modifications will not
be performed at this stage. Future work is discussed in the last chapter.
Chapter 2
The chtMultiRegionFoam solver is a multi-region (multi-physics) solver that solves transient con-
jugate heat transfer between solid regions and fluid regions.
7
CHAPTER 2. THE CHTMULTIREGIONFOAM SOLVER 8
|----- readPIMPLEControls.H
|----- regionProperties
| |----- regionProperties.C
| |----- regionProperties.H
|----- solid
|----- createSolidFields.H
|----- createSolidMeshes.H
|----- readSolidMultiRegionPIMPLEControls.H
|----- readSolidMultiRegionPISOControls.H
|----- readSolidTimeControls.H
|----- setRegionSolidFields.H
|----- solidRegionDiffNo.C
|----- solidRegionDiffNo.H
|----- solidRegionDiffusionNo.H
|----- solveSolid.H
where
• chtMultiRegionFoam.C, the main source file, calls the needed files and solvers.
• regionProperties/, the subdirectory contains files that read fluid and solid region names set
in the constant/regionProperties of the case files.
• fluid/, the subdirectory contains source files that solve equations for continuity momentum,
enthalpy, pressure for the fluid regions.
• solid/, the subdirectory contains source files for solving heat conduction equation in solid
regions.
• derivedFvPatchFields/, the subdirectory contains files that set new boundary conditions for
the coupling between solid and fluid domains.
• include/, the subdirectory contains files to set/reset the multi-region time step.
• Make/, the subdirectory contains files for compilation purpose.
An insight of the code structure of the chtMultiRegionFoam solver will be presented in Chapter
3.
|--- k
|--- Kappa
|--- p
| --- rho
| --- T
| --- U
|--- 0.001
| --- bottomAir
| |--- cellToRegion
| |--- cp
| |--- epsilon
| |--- k
| |--- Kappa
| |--- p
| |--- rho
| |--- T
| |--- U
| |--- polyMesh
| | --- ...
| --- heater
| |--- cellToRegion
| |--- cp
| |--- epsilon
| |--- k
| |--- Kappa
| |--- p
| |--- rho
| |--- T
| |--- U
| |--- polyMesh
| | ---...
| --- leftSolid
| |--- cellToRegion
| |--- cp
| |--- epsilon
| |--- k
| |--- Kappa
| |--- p
| |--- rho
| |--- T
| |--- U
| |--- polyMesh
| | --- ...
| --- rightSolid
| |--- cellToRegion
| |--- cp
| |--- epsilon
| |--- k
| |--- Kappa
| |--- p
| |--- rho
| |--- T
| |--- U
| |--- polyMesh
CHAPTER 2. THE CHTMULTIREGIONFOAM SOLVER 10
| | --- ...
| --- topAir
|--- cellToRegion
|--- cp
|--- epsilon
|--- k
|--- Kappa
|--- p
|--- rho
|--- T
|--- U
|--- polyMesh
| --- ...
|--- constant
| --- polyMesh
| |--- blockMeshDict
| |--- ...
| --- bottomAir
| |--- g
| |--- RASProperties
| |--- thermophysicalProperties
| |--- turbulenceProperties
| --- topAir
|--- g -> ../bottomAir/g
|--- RASProperties
|--- thermophysicalProperties -> ../bottomAir/thermophysicalProperties
|--- turbulenceProperties -> ../bottomAir/turbulenceProperties
| --- regionProperties
| --- cellToRegion
|--- system
| --- controlDict
| --- fvSchemes
| --- fvSolution
| --- bottomAir
| |--- changeDictionaryDict
| |--- fvSchemes
| |--- fvSolution
| --- heater
| |--- changeDictionaryDict
| |--- fvSchemes
| |--- fvSolution
| --- leftSolid
| |--- changeDictionaryDict
| |--- fvSchemes -> ../heater/fvSchemes
| |--- fvSolution -> ../heater/fvSolution
| --- rightSolid
| |--- changeDictionaryDict
| |--- fvSchemes -> ../heater/fvSchemes
| |--- fvSolution -> ../heater/fvSolution
| --- topAir
|--- changeDictionaryDict
|--- fvSchemes -> ../bottomAir/fvSchemes
|--- fvSolution -> ../bottomAir/fvSolution
|--- Allrun
CHAPTER 2. THE CHTMULTIREGIONFOAM SOLVER 11
In the tree, the symbol -> denotes the file is linked to another file.
• In the 0/ directory, boundary condition files for all desired fields have to be created by the
user. This directory is only needed when setting up the tutorial case which is not needed by
the solver.
• In the 0.001/ directory, the files are created by the Allrun script. Variables and the mesh files
in this directory are actually needed by the solver. The tutorial case is started to be solved
from the time step of 0.001.
• In the constant/ directory, polyMesh/ defines the initial geometry for the full domain, and it
is only needed when setting up the tutorial case. It is important to notice that, in this tutorial,
the region meshes are created by first making a mesh for the entire domain, then splitting it
up into regions using setSet, setsToZones, and splitMeshRegions. After that the mesh in
constant/polyMesh/ is not used anymore.
The file regionProperties specifies region names and assigns the physical phase to each
region: either fluid or solid.
For the fluid regions (bottomAir and topAir), there is a thermophysicalProperties file con-
taining the properties of the fluid, and also RASProperties and turbulenceProperties files,
which provide settings and parameters of the turbulent model.
• In the system directory, the changeDictionaryDict file in each folder contains details about
the necessary fields in the region. The OpenFOAM application changeDictionary will look up
for the dictionary files in the system/regionName folders and then create initial, boundary and
coupling conditions for all fields existing in 0 directory for all regions. The changeDictionaryDict
file is specially needed for setting up this tutorial case and it is not required for running the
solver.
There should be one fvSolution file for each region, for example system/bottomAir/fvSolution,
since each region has its own settings for the solution in that region. However, a dummy file
system/fvSolution is also required (the reason will be explained in the PIMPLE loop in
Section 3.2). The same settings have to be done in both files.
The fvSchemes for each region, for example, system/bottomAir/fvSchemes is required but
the system/fvSchemes file can actually be removed.
• The ./Allrun script for the tutorial case multiRegionHeater calls a series of additional
functions before running the solver. Its main part is shown below:
CHAPTER 2. THE CHTMULTIREGIONFOAM SOLVER 12
#!/bin/bash
# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
f40NR
or by other commands such as fe40, depending on the alias set by the user for initialising
FOAM-extend-4.0. Then,
cd $FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam
vi chtMultiRegionFoam.C
The source file of chtMultiRegionFoam.C, shown in the box below, provides an overview of how
the solver is constructed:
13
CHAPTER 3. A WALK THROUGH THE SOLVER 14
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "basicPsiThermo.H"
#include "turbulenceModel.H"
#include "fixedGradientFvPatchFields.H"
#include "regionProperties.H"
#include "compressibleCourantNo.H"
#include "solidRegionDiffNo.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
regionProperties rp(runTime);
#include "createFluidMeshes.H"
#include "createSolidMeshes.H"
#include "createFluidFields.H"
#include "createSolidFields.H"
#include "initContinuityErrs.H"
#include "readTimeControls.H"
#include "readSolidTimeControls.H"
#include "compressibleMultiRegionCourantNo.H"
#include "solidRegionDiffusionNo.H"
#include "setInitialMultiRegionDeltaT.H"
while (runTime.run())
{
#include "readTimeControls.H"
#include "readSolidTimeControls.H"
#include "readPIMPLEControls.H"
#include "compressibleMultiRegionCourantNo.H"
#include "solidRegionDiffusionNo.H"
#include "setMultiRegionDeltaT.H"
runTime++;
if (nOuterCorr != 1)
{
forAll(fluidRegions, i)
{
#include "setRegionFluidFields.H"
#include "storeOldFluidFields.H"
}
}
CHAPTER 3. A WALK THROUGH THE SOLVER 15
forAll(solidRegions, i)
{
Info<< "\nSolving for solid region "
<< solidRegions[i].name() << endl;
#include "setRegionSolidFields.H"
#include "readSolidMultiRegionPIMPLEControls.H"
#include "solveSolid.H"
}
}
runTime.write();
return 0;
}
// ************************************************************************* //
For example, to look for the path of the turbulenceModel.H included in the main source file,
type the following command:
$FOAM_SRC/turbulenceModels/compressible/turbulenceModel/turbulenceModel.H
The lines containing ‘lnInclude’ are just linking to the other file with a similar path. We can
see from above that in the OpenFOAM library, there are turbulenceModel.H files for both incom-
pressible and compressible models according to their paths. To check which turbulenceModel.H is
included, we can take a look at the Make/options file. Exit the opened text in the terminal by :q!,
and type
vi ./Make/options
It is shown in the last line of EXE_INC in the text that the the following directory is included:
-I$(LIB_SRC)/turbulenceModels/compressible/turbulenceModel
We understand that the turbulenceModel.H file of the compressible model is included. Open the
file by
vi $FOAM_SRC/turbulenceModels/compressible/turbulenceModel/turbulenceModel.H
The description of the file shows that the purpose of the turbulenceModel.H is to declare
‘abstract base class for compressible turbulence models (RAS, LES and laminar)’. It includes the
source files of turbulenceModel.C.
Above is an example of how to look for the information of each included file. The purposes/de-
scriptions of the other included files in the chtMultiRegionFoam.C are provided as follows:
fvCFD.H – A standard file for finite volume method.
turbulenceModel.H – To declare and define abstract base class for compressible turbulence mod-
els (RAS, LES and laminar).
fixedGradientFvPatchFields.H – To make patch type as field type and declare the primitive
field types, such as scalar, tensor, vector, etc.
regionProperties.H – To declare simple class to hold region information for coupled region
simulations.
compressibleCourantNo.H – To calculate and output the mean and maximum Courant Num-
bers for the fluid regions.
solidRegionDiffNo.H –To calculate and output the mean and maximum Diffusion Numbers for
the solid regions.
In the main() function, the following files are included before running the loop. These files are
not proper header files; they only contain pieces of code that are inserted at each location.
setRootCase.H – To check the folder structure of the case.
createTime.H – To check runtime according to the controlDict and initiates time variables.
createFluidFields.H – To create the fields for the fluid region: Reading fluid mesh thermo-
physical properties rho, kappa, U, phi, g, turbulence, DpDtFluid.
CHAPTER 3. A WALK THROUGH THE SOLVER 17
createSolidFields.H – To create the fields for the solid region: Reading solid mesh thermo-
physical properties rho, cp, kappa, T.
Then in the while (runTime.run()) loop, initialising files are executed and some of them are
executed again. Purposes of the files are described as follows:
readTimeControls.H – To read the control parameters used by setDeltaT.
• nOuterCorrectors: it enables looping over the entire system of equations within on time step,
representing the total number of times the system is solved; must be larger than or equal to 1
and is typically set to 1, replicating the PISO algorithm.
• momentumPredictor: the looping algorithms optionally begins each step by solving the mo-
mentum equation: the so-called momentum predictor. This parameter is a switch that controls
solving of the momentum predictor; typically set to off for some flows, including low Reynolds
number and multiphase.
In the chtMultiRegionFoam solver, the PIMPLE looping control parameters are specified in the
files of:
./fluid/readFluidMultiRegionPIMPLEControls.H and ./readPIMPLEcontrols.H.
The readFluidMultiRegionPIMPLEControls.H file declares the following PIMPLE parameters:
int nCorr(readInt(pimple.lookup("nCorrectors")));
int nNonOrthCorr =
pimple.lookupOrDefault<int>("nNonOrthogonalCorrectors", 0);
bool momentumPredictor =
pimple.lookupOrDefault<Switch>("momentumPredictor", true);
fvSolution solutionDict(runTime);
int nOuterCorr(readInt(pimple.lookup("nOuterCorrectors")));
Regarding the case settings, the PIMPLE control parameters are set both in the
system/fvSolution and system/fluidRegionName/fvSolution, where fluidRegionName stands
for the directory named by the fluid region(s). These two files set the same parameters for the
PIMPLE loop, which means that there are (at least) two entries of the PIMPLE settings. The
redundant setting in the file system/fvSolution may due to a lack of tidying up the code of the
solver. A safe and simple way of fixing the setting is to give the same settings in both files.
An example of the PIMPLE loop setting in
chtMultiRegionFoam/multiRegionHeater/system/topAir/fvSolution in the tutorial case of FOAM-
extend-4.0 is presented in the box below:
PIMPLE
{
momentumPredictor off;
nOuterCorrectors 1;
nCorrectors 2;
nNonOrthogonalCorrectors 1;
pRefCell 0;
pRefValue 0;
}
Back to the main source file chtMultiRegionFoam.C, before the PIMPLE loop and after the
runTime++:
CHAPTER 3. A WALK THROUGH THE SOLVER 19
runTime++;
if (nOuterCorr != 1)
{
forAll(fluidRegions, i)
{
#include "setRegionFluidFields.H"
#include "storeOldFluidFields.H"
}
}
The #include "setRegionFluidFields.H" is to set the mesh and the field values that are used
in the calculation for the next time step. If nOuterCorr != 1, the same time step of the fluid
domain will be calculated more than once; therefore, #include "storeOldFluidFields.H" is to
retrieve the pressure and rho from the previous time step.
After that, the PIMPLE loop part is shown in the box below:
forAll(solidRegions, i)
{
Info<< "\nSolving for solid region "
<< solidRegions[i].name() << endl;
#include "setRegionSolidFields.H"
#include "readSolidMultiRegionPIMPLEControls.H"
#include "solveFluid.H"
}
}
It is shown that, within one time step, the fluidRegions are calculated first. Then the soildRegions
are computed based on the field data that are transferred from the fluidRegions. Both fluidRegions
and SolidRegions are looping by the same time step, while they are converged by separate iterations
within one time step.
In the subdirectories of fluid/ and solid/, the fluid solver and solid solver are defined in the
solveFluid.H and solveSolid.H files respectively. Those are described in the following sections.
h = cp · dT (3.1)
where cp is the specific heat capacity at a constant pressure. The conventions differ between solid
mechanics and fluid mechanics.
3.3.2 Equations
The fluid solver solves four equations:
if (oCorr == 0)
{
#include "rhoEqn.H" //Solve the continuity for density.
}
turb.correct();
rho = thermo.rho();
The rhoEqn.H is included from the foam source library, not from the local solver directory. It
can be viewed by:
vi $FOAM_SRC/finiteVolume/lnInclude/rhoEqn.H
The rhoEqn in the C++ format is as below:
\*---------------------------------------------------------------------------*/
{
solve(fvm::ddt(rho) + fvc::div(phi));
}
// ************************************************************************* //
It solves the density of the compressible fluid according to the following equation (rhoEqn):
∂ρ
+ ∇ · (ρu) = 0 (3.2)
∂t
The other three equations UEqn.H, hEqn.H and pEqn.H can be seen in the ./fluid/ directory.
UEqn.H solves the momentum equation. In C++, the code of the momentum equation is shown
below:
CHAPTER 3. A WALK THROUGH THE SOLVER 21
tmp<fvVectorMatrix> UEqn
(
fvm::ddt(rho, U)
+ fvm::div(phi, U)
+ turb.divDevRhoReff()
);
UEqn().relax();
if (momentumPredictor)
{
solve
(
UEqn()
==
fvc::reconstruct
(
fvc::interpolate(rho)*(g & mesh.Sf())
- fvc::snGrad(p)*mesh.magSf()
)
);
}
where u denotes the velocity vector, f denotes the body force per unit mass acting on the fluid
element. The function turb.divDevRhoReff() denotes the full viscous stress tensor in compressible
flow:
2
turb.divDevRhoReff() = ∇ · (µ∇u) + ∇ · µ (∇u)T − tr(∇u)T I (3.4)
3
where tr denotes the trace of the tensor in three dimensions.
hEqn.H solves the thermal energy h:
CHAPTER 3. A WALK THROUGH THE SOLVER 22
\\hEqn.H
{
fvScalarMatrix hEqn
(
fvm::ddt(rho, h)
+ fvm::div(phi, h)
- fvm::laplacian(turb.alphaEff(), h)
==
DpDt
);
if (oCorr == nOuterCorr-1)
{
hEqn.relax();
hEqn.solve(mesh.solutionDict().solver("hFinal"));
}
else
{
hEqn.relax();
hEqn.solve();
}
thermo.correct();
\\pEqn.H part(1)
{
bool closedVolume = p.needReference();
rho = thermo.rho();
U = rUA*UEqn().H();
surfaceScalarField phiU
(
fvc::interpolate(rho)
*(
(fvc::interpolate(U) & mesh.Sf())
+ fvc::ddtPhiCorr(rUA, rho, U, phi)
)
);
The part above interpolates the density (rho) and solves the pEqn.
CHAPTER 3. A WALK THROUGH THE SOLVER 24
\\pEqn.H part(2)
if
(
oCorr == nOuterCorr-1
&& corr == nCorr - 1
&& nonOrth == nNonOrthCorr
)
{
pEqn.solve(mesh.solutionDict().solver(p.name() + "Final"));
}
else
{
pEqn.solve(mesh.solutionDict().solver(p.name()));
}
if (nonOrth == nNonOrthCorr)
{
phi += pEqn.flux();
}
}
// Solve continuity
#include "rhoEqn.H"
The part above mainly updates pressure substantive derivative DpDt and the thermal conductivity
Kappa.
CHAPTER 3. A WALK THROUGH THE SOLVER 25
3.4.2 Equations
The solid solver solves the TEqn for solid regions.
\\solveSolid.H
{
for (int nonOrth=0; nonOrth<=nNonOrthCorr; nonOrth++)
{
tmp<fvScalarMatrix> TEqn
(
fvm::ddt(rho*cp, T)
- fvm::laplacian(Kappa, T)
);
TEqn().relax();
TEqn().solve();
}
Info<< "Min/max T:" << min(T) << ' ' << max(T) << endl;
}
∂T
ρ · cp − ∇(KT ) = 0 (3.7)
∂t
where K denotes Kappa.
Example usage:
myInterfacePatchName
{
type solidWallMixedTemperatureCoupled;
neighbourFieldName T;
Kappa Kappa;
value uniform 300;
}
public:
//- Runtime type information
TypeName("solidWallMixedTemperatureCoupled");
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::solidWallMixedTemperatureCoupledFvPatchScalarField::
solidWallMixedTemperatureCoupledFvPatchScalarField
(
const fvPatch& p,
const DimensionedField<scalar, volMesh>& iF
)
:
mixedFvPatchScalarField(p, iF),
neighbourFieldName_("undefined-neighbourFieldName"),
KappaName_("undefined-Kappa")
{
this->refValue() = 0.0;
this->refGrad() = 0.0;
this->valueFraction() = 1.0;
}
The description denotes that user can choose the boundary condition between Dirichlet type
(pure fixedvalue, agree on refValue), Neumann type (pure fixedgradient, zero gradient) or a mixed
type agree on both temperature and its gradient. This is done by looking up for the keyword
refValue as shown in the box below: Line 100 to line 113 in
solidWallMixedTemperatureCoupledFvPatchScalarField.C.
if (dict.found("refValue"))
{
// Full restart
refValue() = scalarField("refValue", dict, p.size());
refGrad() = scalarField("refGradient", dict, p.size());
valueFraction() = scalarField("valueFraction", dict, p.size());
}
else
{
// Start from user entered data. Assume fixedValue.
refValue() = *this; //set the boundary condition in the time directory
refGrad() = 0.0;
valueFraction() = 1.0;
}
For pressure mapping between the regions, which we have mentioned in Chapter 1, only the
Dirichlet boundary condition needs to be specified because the pressure mapping is an agreement
between the neighbour patches on the pressure value only, which means
p1 = p2 (3.10)
The implementation of the pressure coupled boundary condition will be demonstrated in Chapter 6.
Chapter 4
where n is an integer. In this way, we can specify the time step of the solid regions according to the
solid region property and the fluid region property. The n times of the deltaT indicates that the
solid regions will be solved once after every n times we solve the fluid regions.
However, for such implementation, an important thing needs to be done is that the switch of
‘adjustTimeStep’ for fluid regions must be turned off in the controlDict when setting a case. It
means that we will not allow the system to prolong the time step of the fluid regions according to
the Courant number. Otherwise, the solidRegionDeltaT will not remain the integral multiple of
the fluid region deltaT, which will cause an error to the system. Details upon this point will be
discussed in the next section.
The first approach of implementation enables a stable time step for the solid regions that can be
specified by the user. When doing the case setting, only one extra variable (solidRegionDeltaT)
needs to be specified. One shortcoming of such an implementation is that it might reduce the
efficiency of the fluid region computations, since the ‘adjustTimeStep’ switch is turned off.
28
CHAPTER 4. IMPLEMENTATION OF MULTIPLE TIME STEPS 29
If that happens, also the solidRegionRunTime is updated to prepare for the next check by equation
4.2, as
solidRegionRunTime(j) = runTime(i) (4.3)
For example, set the solidRegionDeltaTRef = 0.01, and the fluid region original deltaT = 0.001.
Then, after running for a little while, let us assume current fluid region time step is at i = 0.0095421,
where i is the time step index for solving the fluid region. Since i is less than 0.01, we haven’t solved
the solid regions yet. Initial solidRegionRunTime is at j = 0, where j is the time step index for
solving the solid region. A detailed illustration from the time step i is presented as follows :
• time step i.
Current time step is i = 0.0095421: it is smaller than solidRegionDeltaTRef 0.01, so the
fluid regions will continually be solved for the next time step.
The solid regions have not been solved yet, j = 0.
• time step i + 1.
Time step adjusted according to Courant number, current time step is i + 1 = 0.014511:
(i+1)−j = 0.014511−0 > 0.01. The time difference is larger than the solidRegionDeltaTRef.
Therefore, the solid regions are solved at j + 1 = 0.014511.
• time step i + 2.
Time step adjusted according to Courant number, current time step is i + 2 = 0.019573: the
difference between current time step and the last time we solve the solid region is (i + 2) −
(j + 1) = 0.005062 < 0.01. The time difference is smaller than the solidRegionDeltaTRef.
Therefore, the solid regions are not solved at this time step.
• time step i + 3.
current time step is i + 3 = 0.0201234, the difference between current time step and the last
time we solve the solid region is (i + 3) − (j + 1) = 0.024634 − 0.014511 = 0.010123 > 0.01.
The time difference is larger than the solidRegionDeltaTRef.
The solid regions should be solved at this time step j + 2 = 0.0201234.
The main benefit of doing in this way is to allow the adjustment of the time step for the fluid
regions. However, it is important to notice that, this approach of implementation is based on the
assumption that: the fluid region deltaT will not be adjusted too much according to the Courant
number, so that after it is subtracted by the last solidRegionRunTime, the time difference will not
be too large for solving the solid regions.
mkdir -p $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cd $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cp -r $FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam .
mv chtMultiRegionFoam chtMultiRegionMultiDeltaTFoam
cd chtMultiRegionMultiDeltaTFoam
mv chtMultiRegionFoam.C chtMultiRegionMultiDeltaTFoam.C
Make sure that the binary file ends up in the user directory, following modifications need to
be implemented in the Make/files,
2. Now we need to create a new variable to control the solid region time step, let us call it
solidRegionDeltaT. The creating of this variable should be implemented in
solid/readSolidTimeControls.H. Add the following commands after the declaration of scalar
maxDi in the readSolidTimeControls.H file:
scalar solidRegionDeltaT =
runTime.controlDict().lookupOrDefault<scalar>("solidRegionDeltaT",
runTime.deltaT().value());
The command above indicates that, if the solidRegionDeltaT is not set in the controlDict
file in the case/system directory, it will be set equal to the original fluid region deltaT.
3. To our case, the solidRegionDeltaT should be set as an integral multiple of the fluid region
deltaT. Therefore, a checking sentence should be written to avoid wrong user setting. The
following commands need to be added after step 2, to see if the solidRegionDeltaT is integral
multiple of the deltaT. If not, the program will stop running instead of generating garbage
results.
See above, an Info line is also added for the convenience of future debugging. It is worthwhile
to mention that fmod() is a C++ function declared in math.h/cmath.h for calculating the
remainder between float or double type of numbers. The % operator in C++ only works for
calculating the remainder between integers.
4. Based on the modification of step 3, before the first command line of the
chtMultiRegionMultiDeltaTFoam.C, Add
CHAPTER 4. IMPLEMENTATION OF MULTIPLE TIME STEPS 31
5. Modify the PIMPLE loop. This is the main step of the modification. The PIMPLE loop in
the chtMultiRegionMultiDeltaTFoam.C needs to be replaced. The following is the original
loop in the chtMultiRegionFoam.C.
The original loop code in the box above needs to be replaced by the modified code below:
CHAPTER 4. IMPLEMENTATION OF MULTIPLE TIME STEPS 32
It is important to be aware of using the fmod() in C++. The float number calculation has
accuracy limitation. For example, it may return a 0.1 when we calculate the remainder between
1.5 and 0.1. The IF statement
cd $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cd chtMultiRegionMultiDeltaTFoam/
wmake
mkdir -p $WM_PROJECT_USER_DIR/run/tutorials/chtMultiRegionFoam
cd $WM_PROJECT_USER_DIR/run/tutorials/chtMultiRegionFoam
cp -r $FOAM_TUTORIALS/heatTransfer/chtMultiRegionFoam/multiRegionHeater .
mv multiRegionHeater multiRegionHeaterMultiDeltaT
cd multiRegionHeaterMultiDeltaT
In the system/controlDict, add the new created variable solidRegionDeltaT and set it to 0.0015;
(deltaT is 0.001, this setting is to check if the errors can be output.) Insert the following line into
the system/controlDict file.
solidRegionDeltaT 0.0015;
Then, type
./Allrun
The program will crash very fast after running and report errors. Then in the
log.chtMultiRegionMultiDeltaTFoam file, an error can be seen:
Error: solid region delta T is not an integral multiple of the original delta T.
The case stopped running at 0.001 second and the same error occurred again. This error is not
what we expected:
Error: solid region delta T is not an integral multiple of the original delta T.
Check the log.chtMultiRegionMultiDeltaTFoam file, we can see that after adjustment of the time
step, the fluid region deltaT becomes 0.1 rather than keeping the original value 0.001. Therefore,
we understand that the solidRegionDeltaT is once again not the multiple of the deltaT.
To solve this error, we need to set the ’adjustTimeStep’ in the controlDict from ’yes’ to ’no’, this
is very important.
Then after a longer while, the case will finish running successfully with a stable time step. It
is shown in the log.chtMultiRegionMultiDeltaTFoam file that the solid regions are not solved until
the runtime is 0.01s. After every 0.01s, the solid regions are to be solved at 0.02s, 0.03s, 0.04s, etc.
Time = 0.01
The box above shows that at 0.01s, the solid regions were run after the remainder was checked
to be zero. Information regarding the calculation outputs were replaced by the ellipsis mark for
a better view of the structure. Note that, in C++ the remainder is calculated by floating point
computation with limited accuracy, the small number 1.734723e-18 is regarded as zero. Till now,
the first approach of loop modification was implemented and verified.
cd $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cp -r $FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam .
mv chtMultiRegionFoam chtMultiRegionMultiDeltaTRefFoam
cd chtMultiRegionMultiDeltaTRefFoam
mv chtMultiRegionFoam.C chtMultiRegionMultiDeltaTRefFoam.C
Make sure that the binary file ends up in the user directory, following modifications need to
be implemented in the make/files,
scalar solidRegionRunTime;
Then, an Info statement was added to provide setting information in the running log file.
<< solidRegionDeltaTRef
<< endl;
Now, we will move to the modification of the main source file chtMultiRegionMultiDeltaTRefFoam.C.
Before the line ’while (runTime.run())’, add
solidRegionRunTime=0.0;
This is to set the initial value of the solid region run time. The value of solidRegionRunTime
will be updated each time when the solid region is run. Then, before ’runTime.write();’, replace
the PIMPLE loop by the following:
CHAPTER 4. IMPLEMENTATION OF MULTIPLE TIME STEPS 36
3. Run wmake in the top-level of the new solver, and then type the new solver name to check if
it is compiled completely.
cd $WM_PROJECT_USER_DIR/run/tutorials/chtMultiRegionFoam
cp -r $FOAM_TUTORIALS/heatTransfer/chtMultiRegionFoam/multiRegionHeater .
mv multiRegionHeater multiRegionHeaterMultiDeltaTRef
cd multiRegionHeaterMultiDeltaTRef
In the system/controlDict, add the new variable solidRegionDeltaTRef and set it to 0.01.
Add the following line in to the controlDict file:
solidRegionDeltaTRef 0.01;
Then, type
./Allrun
The case should be running faster with ’adjustTimeStep’ than without. Check the
log.chtMultiRegionMultiDeltaTRefFoam file. It shows that, the solid regions were run every time
when the difference between the runTime and solidRegionRunTime is larger than 0.01. For example,
at the first time step,
deltaT = 0.1
Time = 0.101
Calculation results were replaced by the symbol of ... for a better view of the structure. It
shows that at the first time step, the deltaT was adjusted to 0.101s, therefore, RunTime minus
solidRegionRunTime was 0.101, which was larger than solidRegionDeltaTRef(0.01), so the solid
regions were computed at this time step.
At the next time step,
CHAPTER 4. IMPLEMENTATION OF MULTIPLE TIME STEPS 38
deltaT = 1.061063e-05
Time = 0.101011
It is shown the difference between current run time and the last time solving the solid regions is
only 1.061063e-05, which is smaller than 0.01, therefore the solid regions will not be solved at this
time step. The fluid regions will be continually solved at the next time step.
Until now, the implementation of the multiple deltaTs for fluid regions and solid regions have
been done. In the next chapter, the graphical results will be compared between the modified solver
and the original solver based on the tutorial case multiRegionHeater in FOAM-extend-4.0.
Chapter 5
5.1 Visualization
To the author’s knowledge, the multiRegionHeater tutorial case solved by chtMultiRegionFoam
does not work very well with paraview visualization in FOAM-extend-4.0. The current solution for
this problem is to use paraview in OpenFOAM-4.0 instead. After running the ./Allrun script, open
a new terminal, and source OpenFOAM-4.0 by:
OF4x
touch multiRegionHeater{bottomAir}.OpenFOAM
touch multiRegionHeater{heater}.OpenFOAM
touch multiRegionHeater{leftSolid}.OpenFOAM
touch multiRegionHeater{rightSolid}.OpenFOAM
touch multiRegionHeater{topAir}.OpenFOAM
Then
paraview
In the paraview window, select File and Open. Then in the window find the option ’Files of
type’, drag the list to the end and select All files(*). Choose:
multiRegionHeater{bottomAir}.OpenFOAM
multiRegionHeater{heater}.OpenFOAM
multiRegionHeater{leftSolid}.OpenFOAM
multiRegionHeater{rightSolid}.OpenFOAM
multiRegionHeater{topAir}.OpenFOAM
Press OK and in the main window, press the green button Apply for each region. Note that for
the solid regions, only temperature T should be selected as a volume field, otherwise, paraview may
crash due to wrong volume fields selection.
In the window of paraview, the mesh of the multiRegionHeater is shown in Figure 5.1.
39
CHAPTER 5. VISUALIZATION AND COMPARISON 40
The blue meshes form the top air region, the red meshes form the bottom air region. In the
middle, the white meshes are the solid regions including left solid, heater and right solid.
Figure 5.2 and 5.3 show the density and temperature distribution of the topAir at 180s for the
original tutorial case.
Figure 5.4 present the results of the modified cases: chtMultiRegionMultiDeltaT and
chtMultiRegionMultiDeltaTRef. The density distributions rho of the topAir at 180s are exactly
the same between the two modified cases and the original case, therefore, only one figure is presented
here. It indicates that the modification of the loop with multiple time steps does not change the
theory and the final results.
5.2 Comparison
Figures 5.5 and 5.6 compare the changes of maximum temperature in the air and solid regions along
time between three cases: the original multiRegionHeater tutorial case, the
multiRegionHeaterMultiDeltaT case calculated by the first approach (approach 1) and the
multiRegionHeaterMultiDeltaTRef case calculated by the second approach (approach 2).
CHAPTER 5. VISUALIZATION AND COMPARISON 41
Figure 5.4: Density distribution of the topAir at 180s from modified cases: MultiRegionHeather-
MultiDeltaT and MultiRegionHeatherMultiDeltaTRef (Results are exactly the same between two
modified cases and the original case).
• Approach 1 provides exact the same result as the original case. It is because that in approach
1, the time step of the solid regions is set as 0.01, which is small enough to achieve a very
accurate result. However, since the adjustment of time step is not allowed in approach 1, the
computation time is longer than the approach 2. The computation time can be reduced by
increasing the time steps of the fluid regions and solid regions.
• Approach 2 provides a relatively accurate result. It has a small variance compared to the
original tutorial case in the initial time steps; after some time, it reaches the same result as
the others.
• Three curves merges at the end. The computational time of approach 2
(chtMultiRegionMultiDeltaTRefFoam) is the shortest among the three.
CHAPTER 5. VISUALIZATION AND COMPARISON 42
380
370
360
topAir Temperature T
350
340
330
320
310
300
0 20 40 60 80 100 120 140 160 180
Time (s)
370
360
350
leftSolid Temperature T
340
330
320
310
300
0 20 40 60 80 100 120 140 160 180
Time (s)
f40NR
cd $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cp -r $FOAM_SOLVERS/heatTransfer/chtMultiRegionFoam .
mv chtMultiRegionFoam multiRegionPressureFoam
cd multiRegionPressureFoam/derivedFvPatchFields
mkdir solidWallPressureCoupled
cp solidWallMixedTemperatureCoupled/* solidWallPressureCoupled
cd solidWallPressureCoupled
mv *Temperature*.C solidWallPressureCoupledFvPatchScalarField.C
mv *Temperature*.H solidWallPressureCoupledFvPatchScalarField.H
Although for pressure coupling only the Dirichlet type boundary condition is needed, the Neu-
mann type and Dirichlet-Neumann partitioning strategy are still kept in case of future extension.
In solidWallPressureCoupledFvPatchScalarField.H and
solidWallPressureCoupledFvPatchScalarField.C files, replace all the ’MixedTemperature’ by
’Pressure’.
43
CHAPTER 6. IMPLEMENTATION OF THE PRESSURE COUPLED BOUNDARY CONDITION44
cd $WM_PROJECT_USER_DIR/applications/solvers/multiphysics/
cd multiRegionPressureFoam
mv chtMultiRegionFoam.C multiRegionPressureFoam.C
sed -i s/chtMultiRegionFoam/multiRegionPressureFoam/g Make/files
sed -i s/FOAM_APPBIN/FOAM_USER_APPBIN/g Make/files
The solver with the newly implemented boundary condition was renamed to multiRegionPressureFoam.
After compiling, it can be tested by a case: a small change was made in the case multiRegionHeater
by changing the pressure boundary condition of the bottomAir in
/system/bottomAir/changeDictionaryDict. Replace the following condition in the field p:
bottomAir_to_rightSolid
{
type buoyantPressure;
value uniform 1e+05;
}
by
bottomAir_to_rightSolid
{
type solidWallPressureCoupled;
neighbourRegionName rightSolid;
neighbourPatchName rightSolid_to_bottomAir;
neighbourFieldName p;
p p;
value uniform 1e+05;
}
This is because a pressure field was not created for the solid regions. A volume field p needs to be
created in order to use the pressure coupled boundary condition.
In solid/createSolidFields.H, add the following line in the first part of initialising the solid
field pointer lists:
PtrList<volScalarField> ps(solidRegions.size());
volScalarField& p = ps[i];
type buoyantPressure;
value uniform 1e+05;
For example, in the leftSolid region, the boundary condition of p as follows should be added:
CHAPTER 6. IMPLEMENTATION OF THE PRESSURE COUPLED BOUNDARY CONDITION46
p
{
boundaryField
{
minX
{
type buoyantPressure;
value uniform 1e+05;
}
maxX
{
type waveTransmissive;
field pd;
U U;
phi phi;
rho rho;
psi psi;
gamma 1.4; // cp/cv
fieldInf 0;
lInf 0.40; // double length of domain
inletOutlet off;
correctSupercritical off;
value uniform 1e+05;
}
minY
{
type buoyantPressure;
value uniform 1e+05;
}
minZ
{
type buoyantPressure;
value uniform 1e+05;
}
maxZ
{
type buoyantPressure;
value uniform 1e+05;
}
leftSolid_to_bottomAir
{
type buoyantPressure;
value uniform 1e+05;
}
leftSolid_to_heater
{
type buoyantPressure;
value uniform 1e+05;
}
leftSolid_to_topAir
{
type buoyantPressure;
value uniform 1e+05;
}
}
}
CHAPTER 6. IMPLEMENTATION OF THE PRESSURE COUPLED BOUNDARY CONDITION47
bottomAir_to_rightSolid
{
type solidWallPressureCoupled;
neighbourRegionName rightSolid;
neighbourPatchName rightSolid_to_bottomAir;
neighbourFieldName p;
p p;
value uniform 1e+05;
}
and in system/rightSolid/changeDict
rightSolid_to_bottomAir
{
type solidWallPressureCoupled;
neighbourRegionName bottomAir;
neighbourPatchName bottomAir_to_rightSolid;
neighbourFieldName p;
p p;
value uniform 1e+05;
}
./Allclean
./Allrun
Now the case is able to run with the use of solidWallPressureCoupled boundary condition.
After running, we can check a time step in the case directory, for example:
ls 150.001/leftSolid/
It is shown that there are five files including: cp, Kappa, rho, T and p, instead of four files cp,
Kappa, rho, T in the original case. A p file is created in the solid region time directories, but without
any calculated values. This is because that current solid solver only solves temperature T.
Now the boundary condition has been successfully created. To verify such boundary condition,
the pressure field need to be computed and output by the solid solver.
However, the verification of such boundary condition has not been done at this stage. The solid
solver needs to be modified in order to solve the pressure/stress to verify the coupled pressure data.
This will leave to the future work.
Chapter 7
7.1 Summary
The chtMultiRegionFoam solver has been studied and modified in this report. The structure of the
chtMultiRegionFoam solver was discussed elaborately. Two approaches of loop modifications were
implemented and verified. A new boundary condition for pressure coupling was implemented.
Here are some basic notes for doing solver modifications:
• Firstly, when modifying a solver, it is important to copy and rename the original solver at the
first step. It is a good habit to do the implementation of the new solver in the user directory
and make sure that the binary file ends up in the user directory.
• Secondly, when doing the modification, it is good to use Info statement to write the newly
defined variable and other relevant information into the log file. When the results turn to be
wrong or the case does not run properly, the information in the log file can be tracked for the
debugging purpose.
• Finally, after modification, case study needs be to performed for verifications.
48
Study questions
1. Why does the author choose to do the modification based on the chtMultiRegionFoam solver
for his/her purpose?
2. In the tutorial case multiRegionHeater, what is the function of the changeDictionaryDict
file? Is it required for running the solver?
3. In the case setup of the tutorial case multiRegionHeater, why there are fvSolution files in
both system directory and system/fluidRegionName/ directory? Are they redundant?
4. In which file has the coupled boundary condition been defined in the chtMultiRegionFoam
solver?
5. What modifications have been done for the new solvers?
6. What is the main difference between two approaches of implementing multiple time steps?
What are the pros and cons for each approach?
7. What is the reason for using multiple time steps in the multi-physics solver?
49
Bibliography
[4] Järvstråt, N. Adding electric conduction and Joule heating to chtMultiRegionFoam, CFD with
open source software, 2009.
[5] Singhal, A. Tutorial to set up a case for chtMultiRegionFoam in OpenFOAM 2.0.0, University
of Luxembourg, 2014
[6] Craven, B.A. and Campbell,R.L. Multi-Region Conjugate Heat/Mass Transfer, MRconjugate-
HeatFoam: A Dirichlet-Neumann partitioned multi-region conjugate heat transfer solver, 6th
OpenFOAM Workshop, 2011.
[7] van der Tempel, M. A chtMultiRegionSimpleFoam tutorial, 6th OpenFOAM Workshop, 2012.
[8] Lide, D.R., ed. CRC Handbook of Chemistry and Physics (90th ed.), Boca Raton, Florida: CRC
Press, 2009.
50