Professional Documents
Culture Documents
LPT For Erosion Modelling in OpenFOAM
LPT For Erosion Modelling in OpenFOAM
LPT For Erosion Modelling in OpenFOAM
modelling in
OpenFOAM
Differences between solidParticle and KinematicParcel
and how to add erosion modelling
Alejandro López
PhD Student
University of Strathclyde
Glasgow, UK
Theoretical background
Lagrangian Particle Tracking
- Eulerian-Eulerian models
-Euler-Lagrange approach
Fp=mp*ap
Erosion
Finnie´s equation
Implementation of LPT in
OpenFOAM
solidParticle Class
cd $WM_PROJECT_DIR/src/lagrangian/solidParticle
cd $WM_PROJECT_DIR/src/lagrangian/intermediate
The intermediate library
particleForces injectionModel
cellZoneInjection
Drag
coneInjection
Lift coneNozzleInjection
Gravity fieldActivatedInjection
Paramagnetic inflationInjection
injectionModel
PressureGradient kinematicLookupTableInjection
VirtualMass manualInjection
NonInertialFrame noInjection
patchInjection
SRF
patchFlowRateInjection
distributionModels
exponential
fixedValue
general
multiNormal
normal
RosinRammler
uniform
The intermediate library
- ClounFunctionObjects
- facePostProcessing: Records particle face quantities on user-specified face
zone
- particleCollector: Collects the parcel-mass and mass flow rate over a set of
polygons, defined as a list of points
- particleTrap: Traps the particles within a given phase fraction for multiphase
cases
- particleErosion: This function creates the particle erosion field on the user-
specified patches
particleErosion
CloudFunctionObject
new volScalarField //Calculate magnitude of the particle
velocity at impingement
( const scalar magU = mag(U);
IOobject //Udir is the velocity unitary
( vector, i.e, the direction of the
this->owner().name() + "Q", particle at impingement.
mesh.time().timeName(), const vector Udir = U/magU;
// determine impact angle, alpha
mesh, const scalar alpha =
IOobject::READ_IF_PRESENT, mathematical::pi/2.0 - acos(nw &
IOobject::NO_WRITE Udir);
), const scalar coeff = p.nParticle()
*p.mass()*sqr(magU)/(p_*psi_*K_);
mesh, const label patchFaceI = pp.whichFace
dimensionedScalar("zero", dimVolume, (p.face());
0.0) scalar& Q = QPtr_->boundaryField()
) [patchI][patchFaceI];
if (tan(alpha) < K_/6.0)
{
Q += coeff*(sin(2.0*alpha) - 6.0/
K_*sqr(sin(alpha)));
}
else
{
Q += coeff*(K_*sqr(cos(alpha))/6.0);
}
Templating in OpenFOAM
Templates are functions or classes that are written for one or more types not yet specied.
template<class T>
class Item
The firrst one defines the template type specification, and the second
The implementation of a template class function must be in the same file as its declaration
Template specialization
This allows the definition of a specific implementation when the argument is of type char.
Coupling of the kinematicCloud
Class and an incompressiblesolver
Uncoupled LPT
cd $WM_PROJECT_USER_DIR
mkdir -p src/lagrangian/
cp -r $FOAM_SRC/lagrangian/intermediate $WM_PROJECT_USER_DIR/
src/lagrangian
- In case a faster compilation is desired modify Make/files & Make/options by deleting the
entries relative to other types of parcels and clouds
- LIB = $(FOAM_USER_LIBBIN)/libkinematiclagrangianIntermediate
- wclean lib
- wmake libso
Coupling of the kinematicCloud
Class and an incompressible solver
pimpleKinematicFoam LIB_USER_SRC = $(WM_PROJECT_USER_DIR)/src
EXE_INC = \
-I$(LIB_SRC)/turbulenceModels/incompressible/turbulenceModel \
-I$(LIB_SRC)/transportModels \
Create the solver directory -I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
-I$(LIB_SRC)/finiteVolume/lnInclude\
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/fvOptions/lnInclude \
cd $WM_PROJECT_USER_DIR/ applications/solvers/ -I$(LIB_SRC)/sampling/lnInclude \
-I$(LIB_SRC)/lagrangian/basic/lnInclude \
-I$(LIB_SRC)/regionModels/surfaceFilmModels/lnInclude \
-I$(LIB_SRC)/regionModels/regionModel/lnInclude \
-I$(LIB_USER_SRC)/lagrangian/intermediate/lnInclude \ # -I$(LIB_SRC)/lagrangian/intermediate/lnInclude \
mkdir pimpleKinematicFoam -I$(LIB_SRC)/lagrangian/distributionModels/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/specie/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/basic/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/properties/liquidProperties/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/properties/liquidMixtureProperties/lnInclude \
Copy pimpleFoam into user´s directory -I$(LIB_SRC)/thermophysicalModels/properties/solidProperties/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/properties/solidMixtureProperties/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/reactionThermo/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/SLGThermo/lnInclude \
-I$(LIB_SRC)/thermophysicalModels/radiationModels/lnInclude \
cd pimpleKinematicFoam -I$(LIB_SRC)/dynamicFvMesh/lnInclude \
-I$(LIB_SRC)/sampling/lnInclude
EXE = $(FOAM_USER_APPBIN)/
pimpleKinematicFoam
Coupling of the kinematicCloud
Class and an incompressible solver
createFields.H: At the beginning of the file add: Add density and dynamic viscosity fields Add the constructor for the
volScalarField rhoInf
kinematicParcel class
(
IOobject
(
Info<< "\nReading transportProperties "rho", word kinematicCloudName
\n" << endl; runTime.timeName(), ("kinematicCloud");
IOdictionary transportProperties mesh, args.optionReadIfPresent
( IOobject::NO_READ,
IOobject::AUTO_WRITE ("cloudName",
IOobject ), kinematicCloudName);
( mesh, Info<< "Constructing
"transportProperties", rhoInfValue kinematicCloud " <<
runTime.constant(), );
kinematicCloudName << endl;
mesh, And just after: basicKinematicCloud
IOobject::MUST_READ_IF_MODIFIED, kinematicCloud
IOobject::NO_WRITE autoPtr<incompressible::turbulenceModel>
turbulence (
) ( incompressible::turbulenceModel::New kinematicCloudName,
); (U, phi, laminarTransport)); add: rhoInf,
dimensionedScalar rhoInfValue U,
( volScalarField mu
( mu,
transportProperties.lookup("rhoInf") IOobject g
); ( );
"mu",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
laminarTransport.nu()*rhoInfValue
);
Coupling of the kinematicCloud
Class and an incompressible solver
pimpleKinematicFoam.C : Then, after #include "createMesh.H”:
Include after int main(int argc, char *argv[]) Info<< "Evolving kinematicCloud.name() <<
the following lines: endl;
argList::addOption kinematicCloud.evolve();
"name", wclean
);
Coupling of the kinematicCloud
Class and an incompressible solver
Coupled Lagrangian Particle Tracking (
TrackData& td,
const scalar dt, // timestep
const label cellI, // owner cell
Term responsible for the coupling is Su() : const scalar Re, // Reynolds number
const scalar mu, // local carrier
viscosity
const scalar mass, // mass
//- Calculate new particle const vector& Su, // explicit particle
velocity momentum source
vector& dUTrans, // momentum transfer
to carrier
template<class TrackData> scalar& Spu // linearised drag
coefficient
const vector calcVelocity ) const;
Coupling of the kinematicCloud
Class and an incompressible
solver
Inside createFields.H the following line is added after the density is read And recompile with:
from the particleProperties dictionary:
wclean
If the solution is properly coupled, the solver will write out two fields:
Then, in order to create the coupled version of the solver is to include this nameoftheCloud:Ucoeff It is of type
momentum transfer into the UEqn.H, so the file will look now like: volscalarField::DimensionedInternalField
// Solve the Momentum equation
tmp<fvVectorMatrix> UEqn It is a nonuniform List<vector>
( nameoftheCloud:Utrans It is of type
fvm::ddt(U)
+ fvm::div(phi, U) volVectorField::DimensionedInternalField
+ turbulence->divDevReff(U)
== It is a nonuniform List<scalar>
fvOptions(U)
+invrhoInf*kinematicCloud.SU(U)
);
UEqn().relax();
fvOptions.constrain(UEqn());
volScalarField rAU(1.0/UEqn().A());
if (pimple.momentumPredictor())
{
solve
(
UEqn()
==
-fvc::grad(p)
);
fvOptions.correct(U);
}
Preprocessing
Geometry
Simple Geometry
created with
blockMesh
9000 hex cells
Cuadrangular pipe
with a 90º bend
kinematicCloudProperties dictionary
run
find tutorials/ -name kinematicCloudProperties
Postprocessing
LPT in Paraview