cfd for rotating machinery using openfoam
TRANSCRIPT
Keywords: • OpenFOAM • SRF • MRF • cyclicAMI • Sliding Interface
Fumiya Nozaki
Last Updated: 22 May 2014
English
CFD for Rotating Machinery
OpenFOAM v2.3.0
2
Preface
This document covers
how to set up CFD simulation for a rotating machinery using OpenFOAM.
In particular,
• Single Rotating Frame (SRF)
• Multiple Reference Frame (MRF)
• Arbitraly Mesh Interface (AMI) are and will be described in detail.
3
Chapter 1 Introduction
In this chapter we shall describe the classification of the methods for solving a flow around a rotating machinery
using OpenFOAM.
4
What we need to decide
Our simulation begins with deciding the following conditions:
1. Computational Domain
2. Time Dependency
5
What we need to decide
Our simulation begins with deciding the following conditions:
1. Computational Domain
2. Time Dependency
Does our model include some stationary regions or not?
6
What we need to decide
Our simulation begins with deciding the following conditions:
1. Computational Domain
2. Time Dependency
Which do we want to obtain, a steady or transient solution?
7
Classification of methods
Only Rotating Region
Include Stationary Region(s)
Steady SRFSimpleFoam
Chapter 2
SimpleFoam + fvOptions
Transient SRFPimpleFoam
Chapter 2
pimpleDyMFoam
1. Computational Domain 2.Tim
e D
ependency
Chapter 2
Chapter 2
Chapter 3
Chapter 4
8
Chapter 2 Single Rotating Frame
In this chapter we shall describe how to set up the solvers
and
to simulate an incompressible flow field
in a single rotating frame.
SRFSimpleFoam SRFPimpleFoam
9
Overview
The Single Rotating Frame (SRF) model computes fluid flow in a rotating frame of reference that is adhere to a rotating machinery.
• Steady-state solutions are possible • Without any mesh motion
OpenFOAM solvers using Single Rotating Frame (SRF) model
SRFSimpleFoam
SRFPimpleFoam
Steady-state solver
Transient solver
10
Governing equations
Governing Equations of SRFSimpleFoam
𝒖𝑅 ∙ 𝛻 𝒖𝑅 + 2𝜴 × 𝒖𝑅 + 𝜴× 𝜴 × 𝒓 = −𝛻𝑝 + 𝛻 ∙ 𝜈𝑒𝑓𝑓 𝛻𝒖𝑅 + 𝛻𝒖𝑅
𝑇
𝛻 ∙ 𝒖𝑅 = 0
𝒖 = 𝒖𝑅 + 𝜴 × 𝒓
𝜴 :angular velocity
axis of rotation
𝒓
Absolute velocity (the velocity viewed from the stationary frame)
Relative velocity (the velocity viewed from the rotating frame)
:position vector
Coriolis force Centrifugal force
11
Let’s run the tutorials
Tutorials of SRFSimpleFoam and SRFPimpleFoam
• SRFSimpleFoam • SRFPimpleFoam
12
mixer tutorial | Computational domain
tutorials/incompressible/SRFSimpleFoam/mixer
A blade named “innerWall” is rotating counterclockwise at 5000 rpm.
outlet
outerWall
innerWall
cyclic_half1 cyclic_half0
“inlet” patch is hidden for facilitating visualization. inlet
13
mixer tutorial | Boundary conditions
cyclic_half1
cyclic_half0
Cyclic boundary condition
innerWall
𝒖𝑅 = 𝟎
outerWall
𝒖 = 𝟎
inlet
𝒖 = 0 0 − 10
Fixed absolute velocity
Boundary conditions of velocity field
Rotating wall
Stationary wall
14
mixer tutorial | Case structure
transportProperties
polyMesh
RASProperties
system constant 0
controlDict
fvSchemes
fvSolution
boundary
faces
neighbour
owner
points
Urel
p
k
omega
nut
case
SRFProperties
Pay attention to these files!
• “Urel” represents the relative velocity. • Rotating velocity condition is described in “SRFProperties” file.
SRFSimpleFoam
15
SRFProperties
Angular velocity condition is described in “SRFProperties” file.
/*--------------------------------*- C++ -*----------------------------------*¥
| ========= | |
| ¥¥ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| ¥¥ / O peration | Version: 2.3.0 |
| ¥¥ / A nd | Web: www.OpenFOAM.org |
| ¥¥/ M anipulation | |
¥*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object SRFProperties;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
SRFModel rpm;
axis ( 0 0 1 );
rpmCoeffs
{
rpm 5000;
}
// ************************************************************************* //
Angular velocity is specified in terms of revolutions-per-minute [rpm]
Axis of rotation
5000 rpm ⇒ 5000 ∗ 2π 60 = 523.6 [rad/s]
When the axis vector points to you • rpm>0 ⇒ rotation in counterclockwise direction • rpm<0 ⇒ rotation in clockwise direction
Rotational direction
16
Urel
In this tutorial,”SRFVelocity” boundary condition is used on inlet and outerWall boundaries.
inlet
{
type SRFVelocity;
inletValue uniform (0 0 -10);
relative no;
value uniform (0 0 0);
}
This means 𝒖 = 𝟎 (a stationary wall).
This means 𝒖 = 0 0 − 10 .
By setting “relative” up as ”no”
Boundary condition of the relative velocity 𝒖𝑟 (Urel) is able to be specified in terms of the absolute velocity.
outerWall
{
type SRFVelocity;
inletValue uniform (0 0 0);
relative no;
value uniform (0 0 0);
}
17
Closer look at the velocity on outerWall
In the stationary coordinate system
In the rotating coordinate system
Radius of outerWall is 0.1 m
𝒖 = 𝟎
𝒖𝒓 = 𝒖 − 𝛀 × 𝒓
= 523.6 ∙ 0.1 = 52.36 [𝑚/𝑠]
Vectors show 𝒖𝑟
Rotational direction
18
Let’s run the tutorials
Tutorials of SRFSimpleFoam and SRFPimpleFoam
• SRFSimpleFoam • SRFPimpleFoam
19
rotor2D tutorial | Computational domain
tutorials/incompressible/SRFPimpleFoam/rotor2D
A wall named “rotor” is rotating counterclockwise at 60 rpm.
rotor
freestream
0.2m
20
rotor2D tutorial | Boundary conditions
Boundary conditions of velocity field
rotor
freestream
𝒖𝑅 = 𝟎
Rotating wall
21
Implementation | Calculation of additional forces and absolute velocity
𝒖𝑅 ∙ 𝛻 𝒖𝑅 + 2𝜴 × 𝒖𝑅 + 𝜴× 𝜴 × 𝒓 = −𝛻𝑝 + 𝛻 ∙ 𝜈𝑒𝑓𝑓 𝛻𝒖𝑅 + 𝛻𝒖𝑅
𝑇
𝛻 ∙ 𝒖𝑅 = 0
// Relative momentum predictor
tmp<fvVectorMatrix> UrelEqn (
fvm::div(phi, Urel)
+ turbulence->divDevReff(Urel)
+ SRF->Su() ==
fvOptions(Urel) );
UrelEqn.H
Foam::tmp<Foam::DimensionedField<Foam::vector, Foam::volMesh> >
Foam::SRF::SRFModel::Su() const {
return Fcoriolis() + Fcentrifugal(); }
SRFModel.H
2.0*omega_ ^ Urel_ omega_ ^ (omega_ ^ mesh_.C())
l.126 l.147
Calculation of the absolute velocity (Uabs)
Urel + SRF->U()
SRFSimpleFoam.C
omega_ ^ (mesh_.C() - axis_*(axis_ & mesh_.C()))
Calculation of the additional force terms
22
Implementation | SRFVelocity
void Foam::SRFVelocityFvPatchVectorField::updateCoeffs()
{
if (updated())
{
return;
}
// If not relative to the SRF include the effect of the SRF
if (!relative_)
{
// Get reference to the SRF model
const SRF::SRFModel& srf =
db().lookupObject<SRF::SRFModel>("SRFProperties");
// Determine patch velocity due to SRF
const vectorField SRFVelocity(srf.velocity(patch().Cf()));
operator==(-SRFVelocity + inletValue_);
}
// If already relative to the SRF simply supply the inlet value as a fixed
// value
else
{
operator==(inletValue_);
}
fixedValueFvPatchVectorField::updateCoeffs();
}
If ”relative” is ”no”
SRFModel.C l.60 Calculate 𝜴 × 𝒓
𝒖𝑅 = −𝜴 × 𝒓 + 𝒖
If ”relative” is ”yes”
23
Chapter 3 Multiple Reference Frame
In this chapter we shall describe how to set up
the multiple reference frame simulation in OpenFOAM.
This model is activated using
“fvOptions” functionality.
24
Overview
The Multiple Reference Frame (SRF) model computes fluid flow using both the rotating and stationary reference frame.
• Rotating zone is solved in the rotating frame • Stationary zone is solved in the stationary frame
simpleFoam
Steady-state solver
MRFSource +
fvOptions
OpenFOAM solvers using Multiple Reference Frame (MRF) model
Multiple frames
25
Conceptual image
Rotating zone
Stationary zone
26
Governing equations
𝒖𝑅 ∙ 𝛻 𝒖 − 𝛀 × 𝒖 = −𝛻𝑝 + 𝛻 ∙ 𝜈𝑒𝑓𝑓 𝛻𝒖 + 𝛻𝒖 𝑇
𝛻 ∙ 𝒖𝑅 = 0
In a rotating zone • the Coriolis force is added to the governing equations
• the flux is calculated from the relative velocity 𝒖𝑅
Governing equations
Coriolis force
𝒖 ∙ 𝛻 𝒖 − 𝛀 × 𝒖 = −𝛻𝑝 + 𝛻 ∙ 𝜈𝑒𝑓𝑓 𝛻𝒖 + 𝛻𝒖 𝑇
𝛻 ∙ 𝒖 = 0
Rotating zone
Stationary zone
1
2
1
2
27
mixerVessel2D tutorial | Computational domain
tutorials/incompressible/simpleFoam/mixerVessel2D
A wall named “rotor” is rotating counterclockwise at 104.72 rad/s.
rotor
stator
0.1m
0.04m
28
mixerVessel2D tutorial | Rotating zone
Rotating zone
Stationary zone
0.12m
29
mixerVessel2D tutorial | Boundary condition
Rotating wall
rotor
stator
Stationary wall
30
mixerVessel2D tutorial | Case structure
transportProperties
polyMesh
RASProperties
system constant 0
controlDict
fvSchemes
fvSolution
fvOptions boundary
faces
neighbour
owner
points
cellZones
U
p
k
epsilon
nut
case
Pay attention to these files!
• “Urel” represents the relative velocity. • Rotating velocity condition is described in “SRFProperties” file.
31
fvOptions
MRF1
{
type MRFSource;
active ture;
selectionMode cellZone;
cellZone rotor;
MRFSourceCoeffs
{
origin (0 0 0);
axis (0 0 1);
omega 104.72;
}
}
Specifying the rotating zone by cellZone named rotor.
Unit: [rad/s]
axis
Following options are available for “selectionMode” • all • cellSet • cellZone • mapRegion • points
origin
32
What is cellZones?
FoamFile
{
version 2.0;
format ascii;
class regIOobject;
location "constant/polyMesh";
object cellZones;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1
(
rotor
{
type cellZone;
cellLabels List<label>
1536
(
0
1
2
3
(snip)
1533
1534
1535
)
;
}
)
// ************************************************************************* //
The number of cellZones
The name of cellZones
The number of cells that make up cellZones “rotor”
List of their cell labels
constant/polyMesh/cellZones
355 void Foam::MRFZone::addCoriolis(fvVectorMatrix& UEqn, const bool rhs) const
356 {
357 if (cellZoneID_ == -1)
358 {
359 return;
360 }
361
362 const labelList& cells = mesh_.cellZones()[cellZoneID_];
363 const scalarField& V = mesh_.V();
364 vectorField& Usource = UEqn.source();
365 const vectorField& U = UEqn.psi();
366
367 const vector Omega = this->Omega();
368
369 if (rhs)
370 {
371 forAll(cells, i)
372 {
373 label celli = cells[i];
374 Usource[celli] += V[celli]*(Omega ^ U[celli]);
375 }
376 }
377 else
378 {
379 forAll(cells, i)
380 {
381 label celli = cells[i];
382 Usource[celli] -= V[celli]*(Omega ^ U[celli]);
383 }
384 }
385 }
33
Implementation | Calculation of Coriolis force
MRFZone.C
List of cell labels included in cellZones
Adding the Coriolis force as a source term
34
Implementation | Calculation of relative flux
34 template<class RhoFieldType>
35 void Foam::MRFZone::makeRelativeRhoFlux
36 (
37 const RhoFieldType& rho,
38 surfaceScalarField& phi
39 ) const
40 {
41 const surfaceVectorField& Cf = mesh_.Cf();
42 const surfaceVectorField& Sf = mesh_.Sf();
43
44 const vector Omega = omega_->value(mesh_.time().timeOutputValue())*axis_;
45
46 const vectorField& Cfi = Cf.internalField();
47 const vectorField& Sfi = Sf.internalField();
48 scalarField& phii = phi.internalField();
49
50 // Internal faces
51 forAll(internalFaces_, i)
52 {
53 label facei = internalFaces_[i];
54 phii[facei] -= rho[facei]*(Omega ^ (Cfi[facei] - origin_)) & Sfi[facei];
55 }
56
57 makeRelativeRhoFlux(rho.boundaryField(), phi.boundaryField());
58 }
MRFZoneTemplates.C
Making the relative flux by subtracting 𝜴 × 𝒓 ∙ 𝑺𝑓 from the absolute flux
35
Chapter 4 Dynamic Mesh
In this chapter we shall describe how to set up
a transient simulation with mesh motion in OpenFOAM.
36
mixerVesselAMI2D tutorial | Computational domain
First run the tutorial and enjoy post-processing:
incompressible/pimpleDyMFoam/mixerVesselAMI2D
Static Pressure t=5.90 s
37
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.90 s
38
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.905 s
39
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.91 s
40
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.915 s
41
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.92 s
42
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.925 s
43
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.93 s
44
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.935 s
45
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.94 s
46
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.945 s
47
mixerVesselAMI2D tutorial | Results
Velocity Magnitude t=5.95 s
48
mixerVesselAMI2D tutorial | Mesh motion
Mesh is in rotating motion
Mesh is stationary
Settings are in the next page.
49
dynamicMeshDict
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object dynamicMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dynamicFvMesh solidBodyMotionFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
solidBodyMotionFvMeshCoeffs
{
cellZone rotor;
solidBodyMotionFunction rotatingMotion;
rotatingMotionCoeffs
{
origin (0 0 0);
axis (0 0 1);
omega 6.2832; // rad/s
}
}
cellZone: rotor
The cellZone “rotor” is rotating counterclockwise at 6.2832 rad/s about the origin.
50
Sliding interface capability
Patch: AMI1
Patch: AMI2
Coupled through
“cyclicAMI “
stationary
rotating
51
cyclicAMI
nFaces 192;
startFace 6048;
}
AMI1
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 96;
startFace 6240;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch AMI2;
}
AMI2
{
type cyclicAMI;
inGroups 1(cyclicAMI);
nFaces 96;
startFace 6336;
matchTolerance 0.0001;
transform noOrdering;
neighbourPatch AMI1;
}
front
{
type empty;
inGroups 1(empty);
constant/polyMesh/boundary file
Sliding interface capability , e.g. for rotating machinery is available using cyclicAMI boundary patch class.
In “neighbourPatch”, the coupled patch name is specified.
52
Appendix
53
AMI1
{
type cyclicAMI;
inGroups 1 (cyclicAMI);
nFaces 20;
startFace 2440;
neighbourPatch AMI2;
transform noOrdering;
}
AMI2
{
type cyclicAMI;
inGroups 1 (cyclicAMI);
nFaces 40;
startFace 2460;
neighbourPatch AMI1;
transform noOrdering;
}
AMI1 AMI2
Coupled through
“cyclicAMI “
54
AMI: Creating addressing and weights between 20 source faces and 40 target faces AMI: Patch source sum(weights) min/max/average = 1, 1, 1 AMI: Patch target sum(weights) min/max/average = 1, 1, 1
Let’s check the weights!
sum(weights)=1 is the ideal value. This means the patches conform perfectly.
AMI1
{
type cyclicAMI;
inGroups 1 (cyclicAMI);
nFaces 20;
startFace 2440;
neighbourPatch AMI2;
transform noOrdering;
}
AMI2
{
type cyclicAMI;
inGroups 1 (cyclicAMI);
nFaces 40;
startFace 2460;
neighbourPatch AMI1;
transform noOrdering;
}
source patch
target patch
Appearing first in “boundary” file
55
Translate the pink-colored volume upward by 0.02m
56
AMI: Creating addressing and weights between 20 source faces and 40 target faces AMI: Patch source sum(weights) min/max/average = 0.6, 1, 0.98 AMI: Patch target sum(weights) min/max/average = 0.2, 1, 0.98
Let’s recheck the weights!
𝑠𝑢𝑚(𝑤𝑒𝑖𝑔ℎ𝑡𝑠) =0.03
0.05= 0.6
0.05𝑚2 0.03𝑚2
Fraction of the intersecting areas
57
AMI: Creating addressing and weights between 20 source faces and 40 target faces AMI: Patch source sum(weights) min/max/average = 0.6, 1, 0.98 AMI: Patch target sum(weights) min/max/average = 0.2, 1, 0.98
Let’s recheck the weights!
0.025𝑚2
0.005𝑚2
𝑤𝑒𝑖𝑔ℎ𝑡 =0.005
0.025= 0.2
58
User specified threshold for sum(weights)
Release note Version2.3.0
59
Thank You!
Kindly let me know if you have trouble downloading this slide.