2. Disclaimer
“This offering is not approved or
endorsed by OpenCFD Limited,
the producer of the OpenFOAM
software and owner of the
OPENFOAM® and OpenCFD®
trade marks.”
2
3. Dynamic Mesh in OpenFOAM
In OpenFOAM, the mesh motions and the topology
changes are handled by Dynamic Mesh functionality.
Settings for Dynamic Mesh are described in
dynamicMeshDict file located in the constant directory.
Solvers that can handle these mesh changes have the
letters “DyM”, an abbreviation for Dynamic Mesh, in its
name.
e.g. pimpleDyMFoam, interDyMFoam
3
5. Dynamic Mesh in OpenFOAM
In OpenFOAM, the mesh motions and the topology
changes are handled by Dynamic Mesh functionality.
Settings for Dynamic Mesh are described in
dynamicMeshDict file located in the constant directory.
Solvers that can handle these mesh changes have the
letters “DyM”, an abbreviation for Dynamic Mesh, in its
name.
e.g. pimpleDyMFoam, interDyMFoam
5
6. while (runTime.run())
{
#include "readControls.H"
#include "CourantNo.H"
#include "setDeltaT.H"
runTime++;
Info<< "Time = " << runTime.timeName() << nl << endl;
mesh.update();
// Calculate absolute flux from the mapped surface velocity
phi = mesh.Sf() & Uf;
if (mesh.changing() && correctPhi)
{
#include "correctPhi.H"
}
// Make the flux relative to the mesh motion
fvc::makeRelative(phi, U);
if (mesh.changing() && checkMeshCourantNo)
{
#include "meshCourantNo.H"
}
applications/solvers/incompressible/pimpleFoam/pimpleDyMFoam/pimpleDyMFoam.C
It calls the mesh motion library
to calculate the new position of
points and update the mesh.
Dynamic Mesh in OpenFOAM 6
7. Available types of dynamicFvMesh without topological changes
• staticFvMesh
Disable dynamic mesh
• solidBodyMotionFvMesh
Perform the rigid-body motions such as translational and rotational
movements
• multiSolidBodyMotionFvMesh
Perform the rigid-body motions in multiple regions
• dynamicMotionSolverFvMesh
Solve a Laplace’s equation for the motion displacement or motion
velocity to calculate the updated position of points
• dynamicInkJetFvMesh
Move mesh points sinusoidally in the x direction by explicitly calculating
the new positions
• dynamicRefineFvMesh
Refine the mesh depending on the user specified field values
7
8. Available types of dynamicFvMesh with topological changes
• rawTopoChangerFvMesh
• movingConeTopoFvMesh
• mixerFvMesh
• linearValveFvMesh
• linearValveLayersFvMesh
Under survey
8
9. Inheritance diagram for dynamicFvMesh models
dynamicFvMesh
staticFvMesh
dynamicInkJetFvMeshsolidBodyMotionFvMesh
multiSolidBodyMotionFvMesh
dynamicMotionSolverFvMesh
dynamicRefineFvMesh
Abstract base class for geometry
and/or topology changing fvMesh
9
10. Inheritance diagram for dynamicFvMesh models
dynamicFvMesh
rawTopoChangerFvMesh
movingConeTopoFvMesh
mixerFvMesh
linearValveFvMesh
linearValveLayersFvMesh
topoChangerFvMesh Abstract base class for
a topology changing fvMesh
10
46. Brief description of dynamicMotionSolverFvMesh
Solve a Laplace’s equation for the motion displacement 𝑑 𝑚 [𝑚] or motion
velocity 𝑢 𝑚 [ 𝑚 𝑠]:
𝛻 ∙ 𝛾𝛻𝑑 𝑚 = 0
or
𝛻 ∙ 𝛾𝛻𝑢 𝑚 = 0
Users can select which equations to be solved.
Users need to specify how to calculate the diffusion coefficient 𝛾 of the
equation.
46
47. dynamicMeshDict
dynamicFvMesh dynamicMotionSolverFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
solver velocityComponentLaplacian;
velocityComponentLaplacianCoeffs
{
component x;
diffusivity directional (1 200 0);
}
tutorials/incompressible/pimpleDyMFoam/movingCone/constant/dynamicMeshDict
Users can select which equations to be solved by choosing the solver
from the available options.
Users need to specify how to calculate the diffusion coefficient 𝛾 of
the equation by selecting from the options.
1
2
1
2
47
48. Available types of solver
Solving for cellDisplacement (unit: [𝑚])
• displacementLaplacian
• displacementComponentLaplacian
• displacementInterpolation
• displacementLayeredMotion
• displacementSBRStress
Solving for cellMotionU (unit: [ 𝑚 𝑠])
• velocityLaplacian
• velocityComponentLaplacian
48
49. Available types of solver | displacementLaplacian
void Foam::displacementLaplacianFvMotionSolver::solve()
{
// The points have moved so before interpolation update
// the motionSolver accordingly
movePoints(fvMesh_.points());
diffusivity().correct();
pointDisplacement_.boundaryField().updateCoeffs();
Foam::solve
(
fvm::laplacian
(
diffusivity().operator()(),
cellDisplacement_,
"laplacian(diffusivity,cellDisplacement)"
)
);
}
src/fvMotionSolver/fvMotionSolvers/displacement/laplacian/
displacementLaplacianFvMotionSolver.C
Solving Laplace’s Eqn.
49
50. Available types of solver | velocityLaplacian
void Foam::velocityLaplacianFvMotionSolver::solve()
{
// The points have moved so before interpolation update
// the fvMotionSolver accordingly
movePoints(fvMesh_.points());
diffusivityPtr_->correct();
pointMotionU_.boundaryField().updateCoeffs();
Foam::solve
(
fvm::laplacian
(
diffusivityPtr_->operator()(),
cellMotionU_,
"laplacian(diffusivity,cellMotionU)"
)
);
}
src/fvMotionSolver/fvMotionSolvers/velocity/laplacian/
velocityLaplacianFvMotionSolver.C
Solving Laplace’s Eqn.
50
53. Class diagram of diffusivity models
motionDiffusivity class
//- Return diffusivity field
virtual tmp<surfaceScalarField> operator()() const = 0;
// Protected data
surfaceScalarField faceDiffusivity_;
correct()
//- Correct the motion diffusivity
virtual void correct() = 0;
uniformDiffusivity class
virtual tmp<surfaceScalarField> operator()() const
{
return faceDiffusivity_;
}
directionalDiffusivity class
motionDirectionalDiffusivity class
inverseVolumeDiffusivity class
inverseDistanceDiffusivity class
inverseFaceDistanceDiffusivity class
inversePointDistanceDiffusivity class
override
override
53
54. Class diagram of diffusivity models
motionDiffusivity class
//- Return diffusivity field
virtual tmp<surfaceScalarField> operator()() const = 0;
Foam::tmp<Foam::surfaceScalarField>
Foam::quadraticDiffusivity::operator()() const
{
return sqr(basicDiffusivityPtr_->operator()());
}
//- Correct the motion diffusivity
virtual void correct() = 0;
quadraticDiffusivity class
override
void Foam::quadraticDiffusivity::correct()
{
basicDiffusivityPtr_->correct();
}
54
55. Class diagram of diffusivity models
motionDiffusivity class
//- Return diffusivity field
virtual tmp<surfaceScalarField> operator()() const = 0;
Foam::tmp<Foam::surfaceScalarField>
Foam::exponentialDiffusivity::operator()() const
{
return exp(-alpha_/basicDiffusivityPtr_->operator()());
}
//- Correct the motion diffusivity
virtual void correct() = 0;
exponentialDiffusivity class
override
void Foam::exponentialDiffusivity::correct()
{
basicDiffusivityPtr_->correct();
}
55
56. Calculation of diffusion coefficient
void Foam::inverseVolumeDiffusivity::correct()
{
volScalarField V
(
IOobject
(
"V",
mesh().time().timeName(),
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
mesh(),
dimless,
zeroGradientFvPatchScalarField::typeName
);
V.internalField() = mesh().V();
V.correctBoundaryConditions();
faceDiffusivity_ = 1.0/fvc::interpolate(V);
}
src/fvMotionSolver/motionDiffusivity/inverseVolume/inverseVolumeDiffusivity.C
In the case of inverseVolume type,
faceDiffusivity_ is calculated as the
inverse of the cell volumes as its
name indicates.
correct() function calculates the diffusion coefficient field faceDiffusivity_
56
57. • cmptMultiply(a, b) where 𝑎 = 𝑎0, 𝑎1, 𝑎2 , 𝑏 = 𝑏0, 𝑏1, 𝑏2
𝑐𝑚𝑝𝑡𝑀𝑢𝑙𝑡𝑖𝑝𝑙𝑦 𝑎, 𝑏 = 𝑎0 𝑏0, 𝑎1 𝑏1, 𝑎2 𝑏2
Calculation of diffusion coefficient
void Foam::directionalDiffusivity::correct()
{
const surfaceVectorField n(mesh().Sf()/mesh().magSf());
faceDiffusivity_ == (n & cmptMultiply(diffusivityVector_, n));
}
src/fvMotionSolver/motionDiffusivity/directional/directionalDiffusivity.C
In the case of directional type,
faceDiffusivity_ is calculated using
the user specified diffusivityVector_
and unit normal vectors of each face.
57
58. Mesh update process
bool Foam::dynamicMotionSolverFvMesh::update()
{
fvMesh::movePoints(motionPtr_->newPoints());
if (foundObject<volVectorField>("U"))
{
volVectorField& U =
const_cast<volVectorField&>(lookupObject<volVectorField>("U"));
U.correctBoundaryConditions();
}
return true;
}
src/dynamicFvMesh/dynamicMotionSolverFvMesh/dynamicMotionSolverFvMesh.C
Foam::tmp<Foam::pointField> Foam::motionSolver::newPoints()
{
solve();
return curPoints();
}
src/dynamicMesh/motionSolver/motionSolver/motionSolver.C
mesh.update() calls update() function of dynamicMotionSolverFvMesh class.
58
59. void Foam::velocityComponentLaplacianFvMotionSolver::solve()
{
// The points have moved so before interpolation update
// the fvMotionSolver accordingly
movePoints(fvMesh_.points());
diffusivityPtr_->correct();
pointMotionU_.boundaryField().updateCoeffs();
Foam::solve
(
fvm::laplacian
(
diffusivityPtr_->operator()(),
cellMotionU_,
"laplacian(diffusivity,cellMotionU)"
)
);
}
src/fvMotionSolver/fvMotionSolvers/componentVelocity/componentLaplacian/
velocityComponentLaplacianFvMotionSolver.C
Foam::tmp<Foam::pointField> Foam::motionSolver::newPoints()
{
solve();
return curPoints();
}
src/dynamicMesh/motionSolver/motionSolver/motionSolver.C
Solve Laplace’s Eqn.
Update the diffusion
coefficient field
Mesh update process 59
78. Brief description of dynamicInkJetFvMesh
From the description in the header file
Mesh motion specifically for the "pumping" system of an ink-jet injector.
The set of points in the "pumping" region are compressed and expanded
sinusoidally to impose a sinusoidal variation of the flow at the nozzle exit.
Points can move only in the X direction
78
79. Brief description of dynamicInkJetFvMesh
Points can move only in the X direction
From the description in the header file
Mesh motion specifically for the "pumping" system of an ink-jet injector.
The set of points in the "pumping" region are compressed and expanded
sinusoidally to impose a sinusoidal variation of the flow at the nozzle exit.
79
80. An example usage
FoamFile
{
version 2.0;
format ascii;
class dictionary;
location "constant";
object dynamicMeshDict;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
dynamicFvMesh dynamicInkJetFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
dynamicInkJetFvMeshCoeffs
{
amplitude 0.5;
frequency 1;
refPlaneX 0.0;
}
// ************************************************************************* //
constant/dynamicMeshDict
Three input parameters
control the mesh motions
80
92. Calculation of the new position of points
bool Foam::dynamicInkJetFvMesh::update()
{
scalar scalingFunction =
0.5*
(
::cos(constant::mathematical::twoPi*frequency_*time().value())
- 1.0
);
Info<< "Mesh scaling. Time = " << time().value() << " scaling: "
<< scalingFunction << endl;
pointField newPoints = stationaryPoints_;
newPoints.replace
(
vector::X,
stationaryPoints_.component(vector::X)*
(
1.0
+ pos
(
- (stationaryPoints_.component(vector::X))
- refPlaneX_
)*amplitude_*scalingFunction
)
);
src/dynamicFvMesh/dynamicInkJetFvMesh/dynamicInkJetFvMesh.C
Explicitly calculate
the new position of points
Modify only the x-coordinate
92
93. Calculation of the new position of points
fvMesh::movePoints(newPoints);
volVectorField& U =
const_cast<volVectorField&>(lookupObject<volVectorField>("U"));
U.correctBoundaryConditions();
return true;
}
src/dynamicFvMesh/dynamicInkJetFvMesh/dynamicInkJetFvMesh.C
93
96. Brief description of movingConeTopoFvMesh
From the description in the header file
Sample topoChangerFvMesh that moves an object in x direction
and introduces/removes layers.
It is designed exclusively for use with the movingCone tutorial.
96
97. An example usage
dynamicFvMesh movingConeTopoFvMesh;
motionSolverLibs ( "libfvMotionSolvers.so" );
movingConeTopoFvMeshCoeffs
{
motionVelAmplitude (1.5 0.0 0.0);
motionVelPeriod 0.003;
leftEdge 0.0;
leftObstacleEdge 0.0;
rightObstacleEdge 0.0;
right
{
minThickness 3e-5;
maxThickness 6e-5;
}
left
{
minThickness 3e-5;
maxThickness 5e-5;
}
}
constant/dynamicMeshDict
These parameters are required
but not used.
97
100. curLeft_ = average
(
faceZones()
[
faceZones().findZoneID("leftExtrusionFaces")
]().localPoints()
).x() - SMALL;
curRight_ = average
(
faceZones()
[
faceZones().findZoneID("rightExtrusionFaces")
]().localPoints()
).x() + SMALL;
motionMask_ = vertexMarkup
(
points(),
curLeft_,
curRight_
);
}
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
Constructors (cont’d) 100
The initial x-coordinates of left and
right sides of the moving obstacle
(curLeft_ and curRight_) are calculated
using the faceZones.
101. addZonesAndModifiers
void Foam::movingConeTopoFvMesh::addZonesAndModifiers()
{
// Add zones and modifiers for motion action
if
(
pointZones().size()
|| faceZones().size()
|| cellZones().size()
|| topoChanger_.size()
)
{
Info<< "void movingConeTopoFvMesh::addZonesAndModifiers() : "
<< "Zones and modifiers already present. Skipping."
<< endl;
return;
}
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
101
Create two faceZones and modifiers for motion action
102. addZonesAndModifiers
Info<< "Time = " << time().timeName() << endl
<< "Adding zones and modifiers to the mesh" << endl;
const vectorField& fc = faceCentres();
const vectorField& fa = faceAreas();
labelList zone1(fc.size());
boolList flipZone1(fc.size(), false);
label nZoneFaces1 = 0;
labelList zone2(fc.size());
boolList flipZone2(fc.size(), false);
label nZoneFaces2 = 0;
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
102
103. addZonesAndModifiers
forAll(fc, faceI)
{
if
(
fc[faceI].x() > -0.003501
&& fc[faceI].x() < -0.003499
)
{
if ((fa[faceI] & vector(1, 0, 0)) < 0)
{
flipZone1[nZoneFaces1] = true;
}
zone1[nZoneFaces1] = faceI;
Info<< "face " << faceI << " for zone 1. Flip: "
<< flipZone1[nZoneFaces1] << endl;
nZoneFaces1++;
}
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
103
The faces whose center x-coordinates are
greater than -0.003501 and less than -0.003499
are added to the labelList zone1.
These hard-coded values are designed for movingCone tutorial.
For
movingCone
tutorial
104. addZonesAndModifiers
else if
(
fc[faceI].x() > -0.00701
&& fc[faceI].x() < -0.00699
)
{
if ((fa[faceI] & vector(1, 0, 0)) > 0)
{
flipZone2[nZoneFaces2] = true;
}
zone2[nZoneFaces2] = faceI;
Info<< "face " << faceI << " for zone 2. Flip: "
<< flipZone2[nZoneFaces2] << endl;
nZoneFaces2++;
}
}
zone1.setSize(nZoneFaces1);
flipZone1.setSize(nZoneFaces1);
zone2.setSize(nZoneFaces2);
flipZone2.setSize(nZoneFaces2);
Info<< "zone: " << zone1 << endl;
Info<< "zone: " << zone2 << endl;
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
104
The faces whose center x-coordinates are
greater than -0.00701 and less than -0.00699
are added to the labelList zone2.
Reset the size of four lists.
For
movingCone
tutorial
105. addZonesAndModifiers
List<pointZone*> pz(0);
List<faceZone*> fz(2);
List<cellZone*> cz(0);
label nFz = 0;
fz[nFz] =
new faceZone
(
"rightExtrusionFaces",
zone1,
flipZone1,
nFz,
faceZones()
);
nFz++;
fz[nFz] =
new faceZone
(
"leftExtrusionFaces",
zone2,
flipZone2,
nFz,
faceZones()
);
nFz++;
fz.setSize(nFz);
Info<< "Adding mesh zones." << endl;
addZones(pz, fz, cz);
src/topoChangerFvMesh/movingConeTopoFvMesh/movingConeTopoFvMesh.C
105
Create two faceZones
• rightExtrusionFaces
from zone1 and flipZone1
• leftExtrusionFaces
from zone2 and flipZone2
110. References
[1] Roll Motion of a Box and Interaction with Free-Surface
http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2009/ArashEslamdoost/RollMotionofaBoxandInteracti
onwithFreeSurface.pdf
[2] A tutorial on how to use Dynamic Mesh solver IcoDyMFOAM
http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2007/PiroozMoradnia/OpenFOAM-rapport.pdf
[3] Mesh motion alternatives
http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2009/AndreuOliverGonzalez/PresentationFINAL_Mesh
MotionAlternatives.pdf
[4] OpenFOAM project: A modification of the movingConeTopoFvMesh library
http://www.tfd.chalmers.se/~hani/kurser/OS_CFD_2008/ErikBjerklund/OpenFoamBjerklundE3.pdf
[5] Dynamic mesh in OpenFOAM
https://ilyasivkov.wordpress.com/2015/04/23/dynamic-mesh-in-openfoam/
110
111. This work is licensed under a Creative Commons
Attribution-ShareAlike 4.0 International License.
You should have received a copy of the license
along with this work. If not, see
<http://creativecommons.org/licenses/by-sa/4.0/>.
111