project work: despcription of an adjoint method for object ...hani/kurser/os_cfd_2014/simon... ·...
TRANSCRIPT
CFD with OpenSource software
A course at Chalmers University of TechnologyTaught by Hakan Nilsson
Project work:
Despcription of an adjoint method forobject optimization related to wind noise
Developed for OpenFOAM-2.3.x
Author:Simon Lindberg
Peer reviewed by:Matteo NobileJelena Andric
Disclaimer: This is a student project work, done as part of a course where OpenFOAM and someother 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 detailssimilar 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 thatit works, that it is possible to follow, and to some extent correct the writing. The reviewer has no
responsibility for the contents.
February 2, 2015
Contents
1 Theory 31.1 Aerodynamically induced wind noise . . . . . . . . . . . . . . . . . . . . . . . . . . . 31.2 Adjoint method . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 The adjoint equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41.2.2 Specialization of equations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2 The solvers 72.1 adjointSensitivityFoam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.1.1 adjointShapeOptimizationFoam . . . . . . . . . . . . . . . . . . . . . . . . . 82.1.2 adjointSensitivityFoam.C . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.1.3 adjointOutletPressureFvPatchVectorField.C . . . . . . . . . . . . . . . . 112.1.4 adjointOutletVelocityFvPatchVectorField.C . . . . . . . . . . . . . . . . 122.1.5 createFields.H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.2 sensitivityMoveMesh . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142.2.1 createFields.H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
2.3 lighthillCostFunction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182.3.1 createFields.H . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3 Setting up a case 213.1 constant/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.1 adjointBoxCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.1.2 dynamicMeshDict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 223.1.3 transportProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.1.4 RASProperties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
3.2 0/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233.3 system/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.3.1 controlDict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243.3.2 fvSolution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.4 Running the case . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
4 Results 27
5 Discussion 315.1 adjointSensitivityFoam . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.1.1 laplacian(gamma,U) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315.2 sensitivityMoveMesh problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
5.2.1 alpha value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.3 Frozen turbulence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Bibliography 33
1
CONTENTS CONTENTS
Introduction
The noise level in the car has been an increasing concern for the industry. While they successfullyhave been able to reduce the noise generated from the engine and the road, the aerodynamicallyinduced wind noise has gained attention of the engineers. In the spring of 2014, a master thesis wascarried out at Volvo Cars by Christian Sihvo [1]. The project was searching for a numerical methodusing an adjoint method to optimize the shape of an geometrical object. The method found workedon ”easy” geometrical object as boxes. The goal is to make this method work on more complex ge-ometries, such as back mirror which has a big influence on the aerodynamically induced noise in a car.
This project will describe the code written, and the theory behind the thesis work. The thesisused ANSA, a advanced commercial pre-processing tool for morphing, but this project will in-troduce a way of moving the points in the mesh using OpenFOAM. In this project, the originaladjointShapeOptimizationFoam solver in OpenFOAM will be modified to a new solver calledadjointSensitivityFoam.
2
Chapter 1
Theory
This section will focus on the description of the adjoint method, and the theory regarding the windnoise.
1.1 Aerodynamically induced wind noise
In this project the Lighthill acoustic wave equation will be considered. This equation reads
∂2ρ
∂t2− a2∞∂2ρ
∂x2i
=∂2Tij∂xi∂xj
(1.1)
In the last term, Tij is called the Lighthill stress tensor
Tij = ρvivj + (p− a2∞)δij − τij . (1.2)
The first term of the Tij , the Reynold stress term, is the only term being considered in this project.The second term will be zero for flows without entropy fluctuations and the viscous term τij isconsidered to be zero for high Reynolds number flow. This only leads momentum flux term to besignificant, so that Tij ≈ ρvivj .[2]
The remaining right hand side of Eq. (1.1) can then, named J and be rewritten as
J =∂2
∂xi∂xj(ρvivj) = 2ρ
∆v +
3∑i=1,j=1i 6=j
∂vi∂vj∂xj∂xi
. (1.3)
Moreover J can be written as a sum of the domain part, with subscript Ω, and its boundary part,with subscript Γ, i.e.
J = JΩ + JΓ (1.4)
1.2 Adjoint method
The adjoint method of solving optimization problems in fluid dynamics is an optimization methodthat with only two solver calls, the primal and the adjoint respectively, can determine if a cell inthe mesh is favorable or unfavorable for the specific cost function. The method can be expressed asa minimization problem depending on our flow variables such as velocity v, pressure p, and designvariable α. The constraint in minimization problem is the incompressible, steady state Navier-Stokes
3
1.2. ADJOINT METHOD CHAPTER 1. THEORY
equation. The problem can be written as
minimize J = J(v, p, α)
such that (v · ∇)v +∇p−∇ · (2νD(v)) = 0 (1.5)
∇ · v = 0
Where ν is the kinematic viscosity and the strain-rate tensor D(v) = 12 (∇v + (∇v)T ). A common
way of tackling a constrained optimization problem is introducing a Lagrange multipliers u and qas a Lagrangian relaxation to the optimization problem which then reads
minimize L := J +
∫Ω
(u, q)RdΩ (1.6)
where u is the adjoint velocity and q is the adjoint pressure. R is the constraints from Eq. (1.5), theincompressible RANS and continuity equation. Ω is the flow domain. Thus, in order to distinguishthe favourable cells, the sensitivity field of the design variable α has to be calculated by evaluatingthe total variance of L.
δL = δαL+ δvL+ δpL (1.7)
The Lagrange multipliers for the v and p can be choosen such that
δvL+ δpL = 0 (1.8)
Eqs. (1.7) and (1.8) together gives the expression for the sensitivity of the cell i
∂L
∂αi= ui · viVi (1.9)
where Vi is the volume of the cell i.
1.2.1 The adjoint equations
The adjoint velocity u, and the adjoint pressure q are not velocity and pressure in the physicalmeaning, but have the same dimensions, which suggests that they can be treated similarily. UsingEqs. (1.6) and (1.8) we acquire
δvJ +
∫Ω
(u, q)δvRdΩ + δpJ +
∫Ω
(u, q)δpRdΩ = 0 (1.10)
Here R stands for the incompressible Navier Stokes equations from Eq. (1.5). The change ofeddy viscosity will be neglected due to an approximation called ”frozen turblence”, and this is onlycorrect for laminar flow. This will be an error source for this calculation, but it is a commonly usedapproximation. With some further derivation notm shown here the Eq. (1.10) now reads
δvJ + δpJ +
∫Ω
u · ((δv · ∇)v + (v · ∇)δv −∇ · (2νD(δv)))dΩ−
−∫Ω
q∇ · δvdΩ +
∫Ω
u · ∇δpdΩ = 0 (1.11)
4
1.2. ADJOINT METHOD CHAPTER 1. THEORY
After splitting the cost function J into the boundary Γ and domain Ω part and doing some partialintegration we get the equation
0 =
∫Γ
(u · v +∂JΓ
∂p)δpdΓ +
∫Ω
(−∇ · u +∂JΩ
∂p)δpdΩ+
+
∫Γ
(n(u · v) + u(v · n) + 2νn ·D(n +∂JΓ
∂v)) · δvdΓ−
−∫Γ
2νn ·D(δv) · udΓ+
+
∫Ω
(−∇u · v − (v·)u−∇ · (2νD(u) +∇q +∂JΩ
∂v)) · δvdΩ (1.12)
To fulfill this equation for any δv and δp each integrand has to be 0 individually. The integrandsover the domain gives the adjoint system of equations which are quite similar to the primal one
−2D(u)v = −∇q +∇ · (2νD(u))− ∂JΩ
∂v(1.13)
∇ · u =∂JΩ
∂p(1.14)
Where −2D(u)v = −∇u · v − (v · ∇)u From the eq. 1.12 we can also see the boundary equations∫Γ
(n(u · v) + u(v · n) + 2νn ·D(u− qn +
∂JΓ
∂v
)δvdΓ−
−∫Γ
2νn ·D(δv) · udΓ = 0 (1.15)
∫Γ
(u · v +
∂JΓ
∂p
)δpdΓ = 0 (1.16)
It can be seen in Eqs. (1.13) and (1.14) that if the cost function only has only the contributionfrom the boundaries, the solver will be the same for all different cost functions as the last term ofEq. (1.13) will be zero and the whole RHS of Eq. (1.14) will be zero. If the cost function havecontributions from the domain then the last term of the two equations might not be zero and haveto be implemented in the solver. In this project the cost function do have a contribution from thedomain and the sovler must thus be changed to accoommodate this.
1.2.2 Specialization of equations
This flow is ducted, it is inside a domain with inlet, outlet and walls and the equation has tobe specialized for this flow, as well as for our cost function. This report will not go through thederivation of the boundary conditions, as it is not the main focus of the project. The conditions willonly be valid for a specific primal boundary conditions though, and the ones used in this projectwill be listed in 1.1.
Wall Inlet Outletv No-slip Prescribed value Zero gradientp Zero gradient Zero gradient p = 0
Table 1.1: Boundary conditions for the primals
The adjoint boundary conditions will then be as follows
5
1.2. ADJOINT METHOD CHAPTER 1. THEORY
Wall and inlet boundary conditions
ut = 0 (1.17)
un = −∂JΩ
∂p(1.18)
n · ∇q = 0 (1.19)
Where the subscript t stands for the tangential direction and subscript n stands for the normaldirection.
Outlet boundary conditions
q = u · v + unvn + ν(n · ∇)un +∂JΓ
∂vn(1.20)
0 = vnut + ν(n · ∇)ut +∂JΓ
∂vt(1.21)
The cost function
As it can be seen these equations have plenty of input from the cost function, so different derivationsof the cost function has to be derived. For this cost function, the Lighthill stress tensor
J =∂2
∂xi∂xj(ρvivj) (1.22)
it is easy to see that all derivation with the pressure will be zero, and that the noise level will onlybe important in the domain for this cost function. That leads us with
∂JΩ
∂p= 0 (1.23)
∂JΓ
∂v= 0 (1.24)
∂JΓ
∂p= 0 (1.25)
Then it only remains to calculate the term from the Eq. (1.13)
∂JΩ
∂v=
∫Ω
∂3
∂xi∂xj∂vi(ρvivj)dΩ =
∫Ω
∂2
∂xi∂xj(ρvj)dΩ =
=
∫Ω
ρ∇ · (∇v)dΩ =
∫Ω
ρ∆vdΩ (1.26)
For more information about the method, and how to aquire the equations please see Ulf Nilsson’swork in the course ”CFD with OpenSource software” 2013 [3], and C. Othmers article [4], as wellas Christan Sihvo’s thesis [1] for this specific cost function.
6
Chapter 2
The solvers
This chapter contains the description and the modification of the solvers. In Fig. 2.1 it is possible tofollow how the programs are intended to be run. Both simpleFoam and adjointSensitivityFoam
use the SIMPLE-type algoritm for the pressure-velocity coupling.
Create a blockMesh
run simpleFoam for v and p
run lighthillCostFunction
to see the valueof the wind noise
run adjointSensitivityFoam
for u and q andthe sensitivity field
run sensitivityMoveMesh
to update the geom-etry of the object
next iterationIs this sat-isfactory?
stop
no
yes
Figure 2.1: Flowchart of the way to use the program described in this project
7
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
2.1 adjointSensitivityFoam
As a starting point for the solver we will use adjointShapeOptimizationFoam and do make sub-stansional changes to the program. It is still the best starting point among the OpenFoam solversdue to the fact that it calculates adjoint velocity and adjoint pressure. This part is a description ofwhat was done in the master thesis at Volvo by C. Sihvo. [1]
2.1.1 adjointShapeOptimizationFoam
adjointShapeOptimizationFoam/
adjointContinuityErrs.H
adjointOutletPressure/
adjointOutletPressureFvPatchScalarField.C
adjointOutletPressureFvPatchScalarField.H
adjointOutletVelocity/
adjointOutletVelocityFvPatchVectorField.C
adjointOutletVelocityFvPatchVectorField.H
adjointShapeOptimizationFoam.C
createFields.H
createPhia.H
initAdjointContinuityErrs.H
Make/
options
files
Figure 2.2: Directory structure for adjointShapeOptimizationFoam.
The adjointShapeOptimizationFoam solver applies a ”one-shot” approach to solve the primal andadjoint solvers and the fields are only partially converged. In this project the goal is to solve thefields more carefully and to converge both the primal and adjoint variable before changing the ge-ometry. Thus the primal variables will be solved with simpleFoam before calculating the adjointfields and the sensitivities with adjointSensitivityFoam.
The starting point of the process of creating the adjointSensitivityFoam is to copy the origi-nal solver to the user directory, as follows:
cd $WM PROJECT DIR
cp -r --parents applications/solvers/incompressible/adjointShapeOptimizationFoam \$WM PROJECT USER DIR
Rename the solver to name of choice, e.g. adjointSensitivityFoam
cd $WM PROJECT USER DIR/applications/solvers/incompressible/
mv adjointShapeOptimizationFoam adjointSensitivityFoam
cd adjointSensitivityFoam
mv adjointShapeOptimizationFoam.C adjointSensitivityFoam.C
Rename the executable and change the location in Make/files:
sed -i s/FOAM APPBIN/FOAM USER APPBIN/g Make/files
sed -i s/adjointShapeOptimizationFoam/adjointSensitivityFoam/g Make/files
Clean the previous compilation and recompile with the command wclean and wmake respectively.
8
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
The rest of this section will be a combination of explaination of the code as well as what is neededto add or remove to create the adjointSensitivityFoam solver.
2.1.2 adjointSensitivityFoam.C
83 Info << "\nStarting time loop\n" << endl;848586 while (simple.loop ())87 88 Info << "Time = " << runTime.timeName () << nl << endl;8990 laminarTransport.lookup("lambda") >> lambda;9192 // alpha +=93 // mesh.relaxationFactor ("alpha ")94 // *( lambda*max(Ua & U, zeroSensitivity) - alpha );95 alpha +=96 mesh.fieldRelaxationFactor("alpha")97 *(min(max(alpha + lambda *(Ua & U), zeroAlpha), alphaMax) - alpha );9899 zeroCells(alpha , inletCells );
100 // zeroCells(alpha , outletCells );101102 // Pressure -velocity SIMPLE corrector103 104 // Momentum predictor105106 tmp <fvVectorMatrix > UEqn107 (108 fvm::div(phi , U)109 + turbulence ->divDevReff(U)110 + fvm::Sp(alpha , U)111 );112113 UEqn (). relax ();114115 solve(UEqn() == -fvc::grad(p));116117 p.boundaryField (). updateCoeffs ();118 volScalarField rAU (1.0/ UEqn ().A());119 U = rAU*UEqn ().H();120 UEqn.clear ();121 phi = fvc:: interpolate(U) & mesh.Sf();122 adjustPhi(phi , U, p);123124 // Non -orthogonal pressure corrector loop125 while (simple.correctNonOrthogonal ())126 127 fvScalarMatrix pEqn128 (129 fvm:: laplacian(rAU , p) == fvc::div(phi)130 );131132 pEqn.setReference(pRefCell , pRefValue );133 pEqn.solve ();134135 if (simple.finalNonOrthogonalIter ())136 137 phi -= pEqn.flux ();138 139 140141 #include "continuityErrs.H"142143 // Explicitly relax pressure for momentum corrector144 p.relax ();145
9
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
146 // Momentum corrector147 U -= rAU*fvc::grad(p);148 U.correctBoundaryConditions ();149
Listing 2.1: file adjointShapeOptimizationFoam.C
In listing 2.1 we see that we need to remove lines 90 - 149 to remove the parts regarding the porosityand the primal solver in adjointSensitivityFoam.C. We will also need to remove the line in listing2.2 in the adjointSensitivityFoam.C as we no longer have any continuity error for the primal tocalculate.
76 #include "initContinuityErrs.H"
Listing 2.2: file adjointShapeOptimizationFoam.C
We then must account for the ∂Ω∂v term in the adjoint equation, and add this term, as well as remove
the porosity part of the equation.
169 tmp <fvVectorMatrix > UaEqn170 (171 fvm::div(-phi , Ua)172 - adjointTransposeConvection173 + turbulence ->divDevReff(Ua)174 + fvm::Sp(alpha , Ua)175 );176177 UaEqn (). relax ();178179 solve(UaEqn() == -fvc::grad(pa));
Listing 2.3: file adjointShapeOptimizationFoam.C before change
169 tmp <fvVectorMatrix > UaEqn170 (171 fvm::div(-phi , Ua)172 - adjointTransposeConvection173 + turbulence ->divDevReff(Ua)174 );175176 UaEqn (). relax ();177178 solve(UaEqn() == -fvc::grad(pa) - fvc:: laplacian(gamma ,U));
Listing 2.4: file adjointShapeOptimizationFoam.C after change
As seen on line 178 in listing 2.4 we introduce the laplacian from Eq. (1.26). The interesting hereis that the ρ in the equation has dissapeared and become a gamma. The gamma has the dimensionsof m2/s and is a constant added to make sure that the dimensions are correct. This constant hasbeen renamed in this project from the work done at Volvo, where it was called nu.
As stated in chapter 1.2 the equations for the adjoint variables are solved with ”frozen turbulence”as an approximation, which means that the following line in listing 2.5 can be removed since theνeff is already calculated when simpleFoam was run.
215 turbulence ->correct ();
Listing 2.5: part of file adjointShapeOptimizationFoam.C to delete
The only thing left to do is to add a part that calculates the sensitivity field for the object. The codeis added before the line with the member functions runTime.write() (the line numbering is used tomake it easier to refer to certain parts of the code).
1 word patchName = "innerBox";2 label patchID = mesh.boundaryMesh (). findPatchID(patchName );3 error err("Error!\n");
10
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
4 if(-1 == patchID)5 err.exit ();6 const fvPatch& cPatch = mesh.boundary ()[ patchID ];7 const labelUList& cellsPatch = cPatch.faceCells ();8 forAll(cellsPatch ,cellI)9 sens[cellsPatch[cellI ]] = (Ua[cellsPatch[cellI ]] & U[cellsPatch[cellI ]]) * \
10 mesh.V()[ cellsPatch[cellI ]];11 forAll(cPatch ,faceI)12 13 label faceCellI = cPatch.faceCells ()[ faceI];14 sens.boundaryField ()[ patchID ][faceI] = sens[faceCellI ];15 1617 // scalar maxSens(Foam::sqrt(gMaxMagSqr(sens )));18 scalar maxSens(gMax(sens ));19 scalar minSens(gMin(sens ));20 maxSens = (maxSens*maxSens >= minSens*minSens ? fabs(maxSens) : \21 fabs(minSens ));22 sens = sens/( maxSens+SMALL );
Listing 2.6: file adjointSensitivityFoam.C
As can be seen in listing 2.6 at line 1 we are referring to the boundary called ”innerbox”, which isthe box we want to investigate. After finding the patchID and making sure that the patch exists,some necessary constants are created in lines 6 and 7. The sensitivity is then calculated on the loopon line 9 (which is shown on two lines here for space issues). On the next loop on line 11-15 wemake sure that the the boundary of our object have the same value as the cell have. Since the sen-sitivity is v ·uVi it can’t be calculated on the boundary due to the no slip condition on the boundary.
To make it easier to view the sensitivity later it is then scaled on lines 18-22 with the maximumvalue of the magnitude of either the most positive, or most negative value.
2.1.3 adjointOutletPressureFvPatchVectorField.C
The function for the adjoint outlet pressure will be derived from Eq. (1.20). The first differencefrom the original implementation is that this equation needs of turbulent viscosity, νeff . The line#include "RASModel.H" has to be added in the beginning of the file, so that the viscosity can beacquired from the RASProperies.
107 operator ==(( phiap/patch (). magSf () - 1.0)* phip/patch (). magSf() + (Up & Uap));
Listing 2.7: part of adjointOutletPressureFvPatchScalarField.C to remove
The normal components of the velocities are needed, and are constructed using the fluxes and theface area as
vpatch,n =
(Φp ·AA2
)· n (2.1)
upatch,n =
(Φa ·AA2
)· n (2.2)
The new operator we need to add is derived from Eq. (1.20)
q = u · v + unvn + ν(n · ∇)un, (2.3)
with the approximation that ν(n · ∇)un ≈ νupatch,n−uneigh,n
∆ , where ∆ is the distance between thenodes.
scalarField Up_n = (phip*patch ().Sf()/sqr(patch (). magSf ())) & patch ().nf();// Normal component of the adjoint velocityscalarField Uap_n = (phiap*patch ().Sf()/sqr(patch (). magSf ())) & patch ().nf();
const incompressible :: RASModel& rasModel =
11
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
db(). lookupObject <incompressible ::RASModel >("RASProperties");
scalarField nueff = rasModel.nuEff ()(). boundaryField ()[ patch (). index ()];
// inverse of the distance between nodesconst scalarField& deltainv = patch (). deltaCoeffs ();
// Magnitude of the normal component of the neighboring nodescalarField Uaneigh_n = (Uap.patchInternalField () & patch ().nf());
operator ==(( Uap & Up) + (Up_n*Uap_n) + nueff*(Uap_n -Uaneigh_n )* deltainv );
Listing 2.8: code in adjointOutletPressureFvPatchScalarField.C to add
2.1.4 adjointOutletVelocityFvPatchVectorField.C
Special outlet boundary conditions have to be set, and these will be derived from Eq. (1.21). As inthe outlet pressure conditions is the νeff used. The line #include "RASModel.H" must be added
in the beginning of the fileA·
const fvsPatchField <scalar >& phiap =patch (). lookupPatchField <surfaceScalarField , scalar >("phia");
const fvPatchField <vector >& Up =patch (). lookupPatchField <volVectorField , vector >("U");
scalarField Un(mag(patch ().nf() & Up));vectorField UtHat ((Up - patch ().nf()*Un)/(Un + SMALL ));
vectorField Uan(patch ().nf()*( patch ().nf() & patchInternalField ()));
vectorField :: operator =(phiap*patch ().Sf()/sqr(patch (). magSf ()) + UtHat );// vectorField :: operator =(Uan + UtHat );
Listing 2.9: code in adjointOutletVelocityFvPatchScalarField.C to remove
In the implementation done by C. Sihvo [1] it seems that the following approximation was done
ν(n · ∇)ut ≈ νup,n − uneigh,n
∆, (2.4)
which does not seem intuitive that the tangential part of the velocity will become the normal [1].The following derivation is done with a different approach, in which the Eq. (2.4) should be writtenas follows
ν(n · ∇)ut ≈ νup,t − uneigh,t
∆. (2.5)
Using Eqs. (2.5) and (1.21) ut is calculated. The p,t stands for the tangential part at the patch.Patch is any type of boundary in OpenFoam, and the node at the patch will be the node at theboundary. The neigh,t is the tangential part at the neighbouring node. This approximation from Eq.(2.5) is the same as was used by Ulf Nilssons [3]. In the following derivation ut = up,t.
0 = vnut + ν(n · ∇)ut
0 = vnut + νup,t − uneigh,t
∆
up,t +ν
vn
up,t∆
=ν
vn
uneigh,t∆
up,t =ν
vn
uneigh,t∆
1(1 + ν
∆vn
) =νuneigh,tvn∆ + ν
(2.6)
12
2.1. ADJOINTSENSITIVITYFOAM CHAPTER 2. THE SOLVERS
const fvsPatchField <scalar >& phip =patch (). lookupPatchField <surfaceScalarField , scalar >("phi");
// const fvsPatchField <scalar >& phiap =// patch (). lookupPatchField <surfaceScalarField , scalar >(" phia ");
const fvPatchField <vector >& Uap =patch (). lookupPatchField <volVectorField , vector >("Ua");
const incompressible :: RASModel& rasModel =db(). lookupObject <incompressible ::RASModel >("RASProperties");
scalarField nueff = rasModel.nuEff ()(). boundaryField ()[ patch (). index ()];
const scalarField& deltainv = patch (). deltaCoeffs ();
// Primal magnitude of velocityscalarField Up_ns = phip/patch (). magSf ();
// Neighbouring cell vel.vectorField Uaneigh = Uap.patchInternalField ();vectorField Uaneigh_n = (Uaneigh & patch ().nf())* patch ().nf(); // NormalvectorField Uaneigh_t = Uaneigh - Uaneigh_n;
// vectorField Uan_p = phiap*patch ().Sf()/ sqr(patch (). magSf ()) ;vectorField Uan_p = Uap & patch ().nf() * patch ().nf();vectorField Uap_t = (nueff * Uaneigh_t) / (Up_ns / deltainv + nueff );
operator ==( Uap_t + Uan_p );
Listing 2.10: code in adjointOutletVelocityFvPatchScalarField.C to add
Most of the added code is to create the needed vector fields, and the line vectorField Uap t
corresponds to Eq. (2.6).
2.1.5 createFields.H
The createFields.H for the adjoint solver must read the fields for U ,Ua,p,pa. It must also includethe files for the fluxes #include "createPhi.H" and #include "createPhia.H". The changesdone to the file is to remove all lines regarding to the alpha field as well as adding two new scalars,nu and gamma and the sensitivity field as shown in 2.11.
dimensionedScalar nu(laminarTransport.lookup("nu"));dimensionedScalar gamma(laminarTransport.lookup("gamma"));
const labelList& inletCells = mesh.boundary ()["inlet"]. faceCells ();
volScalarField sens(
IOobject(
"sensitivity",runTime.timeName(),mesh ,IOobject :: READ_IF_PRESENT ,IOobject :: AUTO_WRITE
),(Ua&U)*0.0
);
Listing 2.11: The sensitivity field as well as the laminarTrasport.lookup
13
2.2. SENSITIVITYMOVEMESH CHAPTER 2. THE SOLVERS
2.2 sensitivityMoveMesh
sensitivityMoveMesh/
sensitivityMoveMesh.C
createFields.H
Make/
options
files
Figure 2.3: Directory structure for sensitivityMoveMesh.
As a starting point for this solver, we will use the moveMesh solver in the OpenFoam library andupgrade it as discussed in the ”Moving boundary problem based on calculated data”-discussion onCFD-online forum [5]. Some changes are done to adapt the solver for this case, but the basic func-tionality is the same.
The procedure is the same as for the adjointSensitivityFoam solver, to copy the original solverto the user directory, as follows:
cd $WM PROJECT DIR
cp -r --parents applications/utilities/mesh/manipulation/moveMesh \$WM PROJECT USER DIR
Rename it is not mixed up with the original solver, here to sensitivityMoveMesh
cd $WM PROJECT USER DIR/utilities/mesh/manipulation/
mv moveMesh sensitivityMoveMesh
cd sensitivityMoveMesh
mv moveMesh.C sensitivityMoveMesh.C
Rename the executable and change the location in Make/files:
sed -i s/FOAM APPBIN/FOAM USER APPBIN/g Make/files
sed -i s/moveMesh/sensitivityMoveMesh/g Make/files
Clean the previous compilation and recompile with the command wclean and wmake respecitvely.
The original solver is quite simple and reads the 0/pointDisplacement or 0/pointMotionU files,depending on which solver is chosen in constant/dynamicMeshDict to move the mesh. What willbe done is to add some functionalities to calculate a new pointDisplacement from data acquiredduring the simulations to create the moving part. We must first add a few include files
29 #include "argList.H"30 #include "fvCFD.H"31 #include "simpleControl.H"32 #include "Time.H"33 #include "fvMesh.H"34 #include "motionSolver.H"35 #include "velocityMotionSolver.H"36 #include "primitivePatchInterpolation.H"
Listing 2.12: include section of sensitivityMoveMesh.C
As it can see in listing 2.13 after the int main(int argc, char *argv[]) line the part patch thatha to be moved has to be defined. In this project the patch is called ”innerBox”. Then the basisfiles for the displacement is defined which is pointDisplacement.
autoPtr <motionSolver > motionPtr = motionSolver ::New(mesh);
14
2.2. SENSITIVITYMOVEMESH CHAPTER 2. THE SOLVERS
word patchName = "innerBox";label patchID = mesh.boundaryMesh (). findPatchID(patchName );
pointVectorField& PointDisplacement = const_cast <pointVectorField&>(
mesh.objectRegistry :: lookupObject <pointVectorField >(
"pointDisplacement")
);
Listing 2.13: first section of sensitivityMoveMesh.C after int main..
After the ”pointDisplacement” is acquired the vectorField with the values of the displacement forthe specific patch must be gathered, as done in listing 2.14
//Get the vector field of the patchvectorField &pDisp=refCast <vectorField >( PointDisplacement.boundaryField ()[ patchID ]);
//Find the relevant size of the vector and declare a vectorField.int Psize= pDisp.size ();vectorField dispVals(Psize );
Listing 2.14: creation of the vectorField dispVals in sensitivityMoveMesh.C
In listing 2.15 the code first set up the interpolater using the primitivePatchInterpolation.H classand are then interpolates the selected field to smoothen the motion. The field in this project is thesensitivity field. The last two lines creates a vector field with the old values of the pointdisplacement,and is then creating the normalvector called PointNormalVector.
//- set -up interpolatorprimitivePatchInterpolation patchInterpolator( mesh.boundaryMesh ()[ patchID] );
// displacement based on the external calculation (must provide field data in 0/)scalarField sensitivityPatch = sensitivity.boundaryField ()[ patchID ];
//- perform interpolationscalarField faceValues = \patchInterpolator.faceToPointInterpolate(sensitivityPatch );
vectorField &PointPointer = \refCast <vectorField >( PointDisplacement.boundaryField ()[ patchID ]);
vectorField PointNormalVector = \mesh.boundaryMesh ()[ patchID ]. pointNormals ();
Listing 2.15: interpolation of the sensitivity field in sensitivityMoveMesh.C
After the vectorFields in listing 2.15 the new values to the dispVals can be calculated, as in listing2.16, where the calculation is done for x,y,z direction respectively. The old value of the displacementis the PointPointer[index].x(), and then the new part alpha.value() * faceValues[index]
* PointNormalVector[index].x(); is added. alpha.value() is a dimensionless constant usedto reduce the movement of the boundary. The sensitivity is up the value 1, which is a very largemovement for the mesh. The alpha.value() must reduce the movement with the regards to themesh that is used. It is defined in constant/transportProperties.
// loop over points to move the nodesforAll(dispVals , index)
dispVals[index ].x() = PointPointer[index ].x() - \alpha.value() * faceValues[index] * PointNormalVector[index].x();
dispVals[index ].y() = PointPointer[index ].y() - \alpha.value() * faceValues[index] * PointNormalVector[index].y();
dispVals[index ].z() = PointPointer[index ].z() - \
15
2.2. SENSITIVITYMOVEMESH CHAPTER 2. THE SOLVERS
alpha.value() * faceValues[index] * PointNormalVector[index].z();
Listing 2.16: creating of the new dispVals values in sensitivityMoveMesh.C
The last thing to do before the moveMesh loop is to assign the dispVals to the PointDisplacement.boundaryField()
as done in listning 2.17
//Once the values have been assigned to dispVals ,// assign them to cellDisplacement boundaryFieldPointDisplacement.boundaryField ()[ patchID] == dispVals;
Listing 2.17: defining a new pointDisplacement field in sensitivityMoveMesh.C
The final lines of the sensitivityMoveMesh.C are shown in listing 2.18. This is part of the originalmoveMesh.C code and is not changed for this project.
while (runTime.loop ())
Info << "Time = " << runTime.timeName () << endl;
mesh.movePoints(motionPtr ->newPoints ());
runTime.write ();
Info << "ExecutionTime = " << runTime.elapsedCpuTime () << " s"<< " ClockTime = " << runTime.elapsedClockTime () << " s"<< nl << endl;
Info << "End\n" << endl;
return 0;
Listing 2.18: while loop in sensitivityMoveMesh.C
2.2.1 createFields.H
The fields that the sensitivityMoveMesh needs are the sensitivity and the constant alpha. Thesolver will also need to read the mesh. This can be seen in listing 2.19. This file does not exist inthe original moveMesh utility and need so be created.
1 Info << "Reading field sensitivity\n" << endl;23 volScalarField sensitivity4 (5 IOobject6 (7 "sensitivity",8 runTime.timeName(),9 mesh ,
10 IOobject :: MUST_READ_IF_MODIFIED ,11 IOobject :: NO_WRITE12 ),13 mesh14 );1516 Info << "Reading transportProperties\n" << endl;1718 IOdictionary transportProperties19 (20 IOobject21 (22 "transportProperties",23 runTime.constant(),24 mesh ,25 IOobject :: MUST_READ_IF_MODIFIED ,
16
2.2. SENSITIVITYMOVEMESH CHAPTER 2. THE SOLVERS
26 IOobject :: NO_WRITE27 )28 );293031 Info << "Reading coefficient Alpha\n" << endl;3233 dimensionedScalar alpha34 (35 transportProperties.lookup("alpha")36 );
Listing 2.19: createFields.H
When all files are created and rewritten the program needs to be compiled by typing wmake.
17
2.3. LIGHTHILLCOSTFUNCTION CHAPTER 2. THE SOLVERS
2.3 lighthillCostFunction
lighthillCostFunction/
lighthillCostFunction.C
createFields.H
Make/
options
files
Figure 2.4: Directory structure for lighthillCostFunction.
This is the code that is not based on any original OpenFOAM-code. To create the correct environ-ment write
cd $WM PROJECT USER DIR
mkdir -p applications/utilities/lighthillCostFunction
cd applications/utilities/lighthillCostFunction
foamNewSource App lighthillCostFunction
tree
This will create an empty template of the form of Fig. 2.4 and the rest of the code can be added asfollows. The createFields.H is not created but can be created by typing touch createFields.H.It is important to change the Make/files file and add change the destination as follows.
sed -i s/FOAM APPBIN/FOAM USER APPBIN/g Make/files
In the listings 2.20 - 2.23 the code for the cost function is listed. The line numbering is shownto refer to a specific line of the code.
1 #include "fvCFD.H"2 #include "cellSet.H"34 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //56 int main(int argc , char *argv [])7 8 #include "setRootCase.H"9 #include "createTime.H"
10 #include "createMesh.H"11 #include "createFields.H"1213 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Listing 2.20: The lighthillCostFunction.C
In listing 2.20 the include files and initialization is listed. The only interesting class here is the#include "cellSet.H" line, which enables to select a group of cells based on their geometric locationin the mesh for measuring. To be able to use the cellSet.H the lines-I$(LIB SRC)/meshTools/lnInclude) and -lmeshTools the Make/options.
14 Info << "Compute the tensor: velocity gradient grad(U)!\n" << endl;15 volTensorField gradU(fvc::grad(U));16 Info << "Compute the vector: divergence ofvelocity gradient div(grad(U))!\n" \17 << endl;18 volVectorField divGradU(fvc::div(gradU ));1920 volScalarField Tij(21 IOobject22 (23 "Tij",24 runTime.timeName(),
18
2.3. LIGHTHILLCOSTFUNCTION CHAPTER 2. THE SOLVERS
25 mesh ,26 IOobject ::NO_READ ,27 IOobject :: AUTO_WRITE28 ),29 (mesh.C() & mesh.C())*0.030 );
Listing 2.21: The lighthillCostFunction.C
In the second part of the code shown in listing 2.21 it is shown how initial gradU and divGradU arecalculated, and the volScalarField is created.
31 scalar volume = 0.0;32 cellSet cSet(mesh ,"box");33 const labelList& cells = cSet.toc();34 forAll(cells ,cellI)35 36 Tij[cells[cellI]] =37 2*( divGradU[cells[cellI]] & U[cells[cellI ]]) + \38 sqr(gradU[cells[cellI ]]. component(tensor ::XX)) + \39 sqr(gradU[cells[cellI ]]. component(tensor ::YY)) + \40 sqr(gradU[cells[cellI ]]. component(tensor ::ZZ)) + \41 2*( gradU[cells[cellI ]]. component(tensor ::YX) * \42 gradU[cells[cellI ]]. component(tensor ::XY) + \43 gradU[cells[cellI ]]. component(tensor ::ZY) * \44 gradU[cells[cellI ]]. component(tensor ::YZ) + \45 gradU[cells[cellI ]]. component(tensor ::XZ) *\46 gradU[cells[cellI ]]. component(tensor ::ZX));47 volume += mesh.V()[ cells[cellI ]];48
Listing 2.22: The lighthillCostFunction.C
In the third listing 2.22 the real calculation of the value of the stress tensor in each cell is shownat lines 36-46. The equation evaluated is Eq. (1.3) with the omittance of the ρ constant. At line32 we see the call for the file box, which is in the polyMesh/sets directory. It must be createdbefore running the lighthillCostFunction program. The file used to create it is listed in listing2.24. The line 47 is calculating the accumulated volume of the cells that is used to evaluate the costfunction. At line 31 the volume is initialized.
49 Tij.write ();5051 Info << "Number of cells in box: " << cSet.size() << endl;5253 Info << "Integrate Tij in the whole volume !\n" << endl;54 scalar intTij = gSum(Tij.internalField () * mesh.V());55 reduce(volume ,sumOp <scalar >());5657 Info << "The cost function has the value of: " << intTij /( volume+SMALL) << " \58 [1/s2]\ nDone!\n" << endl;5960 return 0;61
Listing 2.23: The lighthillCostFunction.C
The last part of the lighthillCostFunction.C file is shown in listing 2.23, which is the part wherethe program writes the tensors, and sums it all together before showing the user what the value ofthe cost function is.
cellSet box new boxToCell (-0.15 -0.015 0) (0.035 0.035 0.03)quit
Listing 2.24: The batchSetSet file
The listing 2.24 is showing a file that is used for creating the box file with all the cells used inlighthillCostFunction.C. It creates a box with the coordinates listed. The coordinates are the
19
2.3. LIGHTHILLCOSTFUNCTION CHAPTER 2. THE SOLVERS
opposite vertices of the box and therfore the whole volume can be calculated using only those points.The files is called by typing in the terminal
setSet -batch system/batchSetSet
if the batchSetSet file is in the system directory. The file does not have to be named batchSetSet,it can be called anything.
2.3.1 createFields.H
The only field that the lighthillCostFunction is needing is the velocity field, so the createFields.Hfile will only need to read that field seen in the listing 2.25
1 Info << "Reading field U\n" << endl;2 volVectorField U3 (4 IOobject5 (6 "U",7 runTime.timeName(),8 mesh ,9 IOobject ::MUST_READ ,
10 IOobject :: AUTO_WRITE11 ),12 mesh13 );
Listing 2.25: createFields.H file
When all files are written, complile the code using wmake.
20
Chapter 3
Setting up a case
This chapter will go through the settings needed to run the boxWindCase case that can be downloadedfrom the course homepage. In the Fig. 3.1 all the directories and files that the case contains aredisplayed. The case is a box in a ducted flow, where the geometry of the box will be changed toreduce the aerodynamically induced wind noise. The flow is 1ms over the box.
boxWindCase/
0/
epsilon
k
nut
p
pa
U
Ua
pointDisplacement
constants/
polyMesh/
blockMeshDict
dynamicMeshDict
RASProperties
transportProperties
turbulenceProperties
system/
batchSetSet
controlDict
decomposeParDict
fvSchemes
fvSolution
Figure 3.1: Directory structure for boxWindCase.
3.1 constant/
In this section the files in the constant/ directory will be explained.
21
3.1. CONSTANT/ CHAPTER 3. SETTING UP A CASE
3.1.1 adjointBoxCase
The mesh used for this case is from a blockMeshDict that utilizes a symmetryPlane for reducing thecomputational time. The mesh is rather coarse to reduce computational time. It is thus possiblethat the coarse mesh will reduce the accuracy of the solution. The mesh consits of 30660 hexahedracells, and the patches are
• inlet
• outlet
• slip
• plate
• innerBox
• sym
Here slip is the wall opposite the symmetry wall which is the wall with the box cut in half. InnerBoxis the box that is the subject of the movements and plate is the floor and the roof of the domain.
Figure 3.2: The mesh used without the inlet.
3.1.2 dynamicMeshDict
dynamicFvMesh dynamicMotionSolverFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
/*solver velocityLaplacian;velocityLaplacianCoeffs
diffusivity directional ( 0 100 0 );
22
3.2. 0/ CHAPTER 3. SETTING UP A CASE
// diffusivity uniform;*/
solver displacementLaplacian;displacementLaplacianCoeffs
diffusivity quadratic inversePointDistance (innerBox );
Listing 3.1: dynamicMeshDict
In listing 3.1 it is stated what kind of displacement solver is used for the mesh movement. ThevelocityLaplacian is commented and it is the displacementLaplacian that is used and the diffusivityis specified on the innerBox.
3.1.3 transportProperties
In the listing 3.2 the three important constats used is listed
transportModel Newtonian;
nu nu [0 2 -1 0 0 0 0] 1e-5;gamma gamma [0 2 -1 0 0 0 0] 5e-6;alpha alpha [0 0 0 0 0 0 0] 0.00006;
Listing 3.2: The transportProperties
The value of gamma was set to be 1 · 10−5 in the project at Volvo. In this project both 1 · 10−5 and5 · 10−5 will be tested. This is done to see if the result can be improved by changing this entity, orif it should be interpreted as the viscosity.
The ν value is used for the turbulence, and the α value is a dimensionless constant for scalingthe sensitivity in the sensitivityMoveMesh. The value 0.00006 means that a sensitivity will bemultiplied with the constant to get the movement in meter.
3.1.4 RASProperties
RASModel kEpsilon;
turbulence on;
printCoeffs on;
Listing 3.3: The RASProperties
The file RASProperties is showing only that kEpsilon model is used and that the turbulence is on.
3.2 0/
In the 0/ directory, the initial and boundary conditions for the different fields are located. Theintial values for the k and epsilon files have to be determined. The initial k value was set to 0.375,and the intial epsilon value was set to 14.763. For all the initial condition files, the symmetryPlanecondition can be used for the sym patch, as well as the slip condition for the slip patch.
boundaryField
inlet
type fixedValue;value uniform (0 0 0);
23
3.3. SYSTEM/ CHAPTER 3. SETTING UP A CASE
outlet
type adjointOutletVelocity;value uniform (0 0 0);
innerBox
type fixedValue;value uniform (0 0 0);
Listing 3.4: The 0/Ua file
The listing 3.4 shows some of the initial conditions for the adjoint velocity where the adjointOutletVelocityconditions is very important.
boundaryField
inlet
type zeroGradient;
outlet
type adjointOutletPressure;value uniform 0;
innerBox
type zeroGradient;
Listing 3.5: The 0/pa file
The listing 3.5 shows that the outlet conditions for the adjoint pressure must be described as well.
3.3 system/
In this section, the different files in the system/ directory will be explained.
3.3.1 controlDict
In the controlDict the number of iterations, and how often results has to be written are defined.This must be changed before any solver is run. The first time the simpleFoam is used the endTime
can be set at 3000, and later it is often enough to iterate 2000 steps. The adjoint solver requiresmore time and due to the approximations, and the frozen turbulence, the residuals are not gettingas small as for the primal variables. Instead the Ua velocity is monitored, and the simulation isterminated when stability is achieved.
functions minMaxUa
type fieldMinMax;functionObjectLibs ( "libfieldFunctionObjects.so" );enabled true;// outputControl outputTime;outputControl timeStep;outputInterval 1;
fields(
Ua
24
3.4. RUNNING THE CASE CHAPTER 3. SETTING UP A CASE
);
Listing 3.6: Part of the controlDict file
In the listing 3.6, the user function to see the minMaxUa is shown to give an idea of the stability ofthe adjoint velocity.
3.3.2 fvSolution
The fvSolution file is quite similar to the one in the tutorial of adjointShapeOptimizationFoamwhich is described in Ulf Nilssons work. [3]
The difference with respect to this project is the addition of the solution for the displacementwhich is defined in the following lines in listing 3.7.
cellMotionU
solver PCG;preconditioner DIC;tolerance 1e-8;relTol 0;
cellDisplacement
solver PCG;preconditioner DIC;tolerance 1e-8;relTol 0;
Listing 3.7: Part of the fvSolution file
3.4 Running the case
What follows below is an Allrun script that runs the simulation for one iteration. For more iterationsthe times need to be changed. The script can be found in the course homepage.
#!/bin/sh
cd $0%/* || exit 1 # run from this directory
# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
runApplication blockMesh # run blockmesh
setSet -batch system/batchSetSet > log.setSet #Set up the sets
runApplication decomposePar #Decompose for the run parallel
runParallel simpleFoam 4 #Run simpleFoam on 4 cores
#Copy the pointdisplacement to the latest time
cp processor0/0/pointDisplacement processor0/5000
cp processor1/0/pointDisplacement processor1/5000
cp processor2/0/pointDisplacement processor2/5000
25
3.4. RUNNING THE CASE CHAPTER 3. SETTING UP A CASE
cp processor3/0/pointDisplacement processor3/5000
#Copy the Ua to the latest time
cp processor0/0/Ua processor0/5000
cp processor1/0/Ua processor1/5000
cp processor2/0/Ua processor2/5000
cp processor3/0/Ua processor3/5000
#Copy the pa to the latest time
cp processor0/0/pa processor0/5000
cp processor1/0/pa processor1/5000
cp processor2/0/pa processor2/5000
cp processor3/0/pa processor3/5000
#change endtime
sed -i s/"\(endTime[ \t]*\) 5000;"/"\1 17000;"/g system/controlDict
sed -i s/"0.5"/"0.15"/g system/fvSolution #underRelaxation for the pa
sed -i s/"0.75"/"0.2"/g system/fvSolution #underRelaxation for the Ua
runParallel adjointSensitivityFoam 4 #Run adjoint sensitivityFoam on 4 cores
#Copy the pointdisplacement to the latest time
cp processor0/5000/pointDisplacement processor0/17000
cp processor1/5000/pointDisplacement processor1/17000
cp processor2/5000/pointDisplacement processor2/17000
cp processor3/5000/pointDisplacement processor3/17000
#Change endtime
sed -i s/"\(endTime[ \t]*\) 17000;"/"\1 17010;"/g system/controlDict
#change runintreval
sed -i s/"\(writeInterval[ \t]*\) 1000;"/"\1 10;"/g system/controlDict
runParallel sensitivityMoveMesh 4 #Run sensitivityMovemesh
#change endtime
sed -i s/"\(endTime[ \t]*\) 17010;"/"\1 20000;"/g system/controlDict
sed -i s/"0.15"/"0.5"/g system/fvSolution #underRelaxation for the pa/p
sed -i s/"0.2"/"0.75"/g system/fvSolution #underRelaxation for the Ua/U
runParallel simpleFoam 4 #Run simpleFoam on 4 cores
runApplication reconstructPar #Reconstruct
runApplication lighthillCostFunction
# ----------------------------------------------------------------- end-of-file
26
Chapter 4
Results
In this section the results of the case boxWindCase will be presented. Two different values of gammawere tested for three iterations. Both of the gamma values ended up with cost function valueshigher then the original one, though after the first iteration both cases showed a decrese in theaerodynamically induced wind noise.
start first iteration second iteration third iterationgamma = 1e− 5 -847618 [1/m2] -846094 [1/m2] -848499 [1/m2] -855135 [1/m2]gamma = 5e− 6 -847618 [1/m2] -816134 [1/m2] -851543 [1/m2] -857076 [1/m2]
Table 4.1: The value of the cost function for the different gamma values at different iteration
In the table 4.1, the results of the noise level are shown. The first iteration for both cases shows areduction of the Lighthill stress tensor, and the reduction is greatest for the case with gamma = 5e−6.After the first iteration the cost functon increased greatly.
In the figure 4.1, the displacement is shown for the case with gamma = 5e− 6, colored by the sensi-tivity field. The front of the box is creating an ”edge”, and the back of the box is ”rounded”.
In the figure 4.2, the displacement is shown for the case with gamma = 1e− 5, colored by the sensi-tivity field. The front of the box is creating an ”edge” and the back of the box is ”rounded”. Notethat they look very similar.
The figure 4.3 is showing the back of the box more clearly. The result is shown for the case withgamma = 5e− 6 although the two cases look very similar. Note the small edge that is created.
27
CHAPTER 4. RESULTS
(a) (b)
(c)
Figure 4.1: The box after displacement colored with the sensitivity for the case with gamma = 5e − 6. a)after first displacement b) after second displacement c) after third displacement.
28
CHAPTER 4. RESULTS
(a) (b)
(c)
Figure 4.2: The box after displacement colored with the sensitivity for the case with gamma = 1e − 5. a)after first displacement b) after second displacement c) after third displacement.
29
CHAPTER 4. RESULTS
(a) (b)
(c)
Figure 4.3: The back of the box after displacement colored with the sensitivity for the case with gamma =5e− 6. a) after first displacement b) after second displacement c) after third displacement.
30
Chapter 5
Discussion
It is not surprise that the costfunction eventually after decreasing a bit in the first iteration latergot up. In the work at Volvo, the decrease in the cost function for a square cube was only decreasedwith 0.23%, and that with the cell displacement done in the commercial software ANSA [1].
It is somewhat of a surprise that the small differences in displacement in the two cases gives sobig differences in the costfunction. This would indicate that the costfunction is very sensitive forgeometry change, and maybe that the sensitivityMoveMesh is a too crude instrument to move themesh.
5.1 adjointSensitivityFoam
In the adjointSensitivityFoam solver some problems have been found and corrected, especiallyin the adjointOutletVelocityFvPatchVectorField.C, shown in section 2.1.4. Still no significantimprovement has been shown. It is not out of the question that some of these changes, even thoughmotivated, are wrong, and that the solver is better without them. It is also a possible that thereare still some issues with the solver that are not found yet.
5.1.1 laplacian(gamma,U)
The addition to the adjointSensitivityFoam solver, the laplacian(gamma,U), has been of interestduring the project. The interpretation was first interpreted as the physical quantity ν, but asthe derivation seemed strange some test was preformed to analyse if the quantity could have adifferent, better value. As it can be seen in the results, after the first iteration for the case with thegamma = 5e − 6, roughly half of the physical ν was shown to be better. Therefore it seems that itcan be a different optimal value of gamma then 1e − 5. The dimensions of the constant need to bethe same as ν due to the dimensional check that OpenFOAM preforms before running the code.
5.2 sensitivityMoveMesh problems
The reason for the somehow bad result lies probably with the sensitivityMoveMesh solver. Whileit solves the geometry change acceptably, it always create a small edge at the back of the box thatcan be seen in Fig. 4.3. The effect of the edge on the cost function is not fully determined, but it isnot a big stretch to assume it has an adverse effect on the noise level.
31
5.3. FROZEN TURBULENCE CHAPTER 5. DISCUSSION
5.2.1 alpha value
The alpha value in the change of the geometry is important. In listing 2.16 we can see that thedisplacement function looks like:
displacement = displacement old− alpha value ∗ sensitivity ∗ normal vector (5.1)
As it can see in the Eq. (5.1) the alpha value scales the sensitivity. It was set to 0.00006. It is likelythat this is not the optimal value of alpha, and that the value should even vary during the iterationsand decrease. The sensitivity is rescaled to be a maximum of 1 every iteration so that a decreasinggradient effect, which would normally be seen in an optimization problem, is not present. Thereforeit would be of great interest to investigate further the optimization of the sensitivityMoveMesh
solver.
5.3 Frozen turbulence
The adjoint solvers residuals are not getting very low and the underrelaxation factors are set verylow to make sure the solution is not diverging. This might due to the approximation of frozenturbulenze, meaning that the νeff is not changing when the adjoint field is calculated. Some workcould be done in analyzing if there is a way to update the νeff as the adjoint solver is working, toincrease both the accuracy, and possibly also the stability of the solution.
32
Bibliography
[1] Christian Sihvo. “Numerical method for Shape optimization from wind noise perspective”. MAthesis. Lulea University of Technology, 2014.
[2] Jonas Ask. “Predictions of Aerodynamically Induced Wind Noise Around Ground Vehicles”.PhD thesis. Chalmers University of Technology, 2008.
[3] Ulf Nilsson. Description of adjointShapeOptimizationFoam and how to implement new objec-tive functions. Report for the course CFD with OpenSource software. Chalmers University ofTechnology, 2014.
[4] Othmer C. “A continuous adjoint formulation for the computation of topological and surfacesensitives of ducted flows”. In: Int. J. Numer. Meth. Fluid 58 (2008), pp. 861–877.
[5] Moving boundary problem based on calculated data. Online; accessed 27 October 2014. http://www.cfd-online.com/Forums/openfoam-programming-development/122557-moving-
boundary-problem-based-calculated-data.html: CFD online, 2013.
33