Skip to content

Commit 546cb75

Browse files
author
Will Bainbridge
committed
Lagrangian::turbulentDispersion: Prevent excessive iteration
This change comprises two fixes. Firstly, the turbulence has been constrained to zero for particles that are in contact with walls. This prevents a turbulent velocity fluctuation from being generated that points into the wall. This in turn prevents a drag force into the wall that causes the particle to vibrate in conjunction with a rebound velocity boundary condition. Secondly, when the turbulent time scale becomes small the model now stops treating eddies individually and instead applies a statistical estimate of their combined effect. This prevents excessive iteration near walls when the eddies become very small and the number of eddies increases significantly. The number of eddies at which this happens can be controlled with a new 'maxDiscreteEddies' switch, which is set to 32 by default.
1 parent f3c3b3e commit 546cb75

File tree

2 files changed

+81
-19
lines changed

2 files changed

+81
-19
lines changed

src/Lagrangian/cloud/LagrangianModels/turbulentDispersion/turbulentDispersion.C

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ License
2828
#include "coupledToIncompressibleFluid.H"
2929
#include "coupledToFluid.H"
3030
#include "standardNormal.H"
31+
#include "wallPolyPatch.H"
3132
#include "maxLagrangianFieldSources.H"
3233
#include "NaNLagrangianFieldSources.H"
3334
#include "internalLagrangianFieldSources.H"
@@ -121,6 +122,11 @@ Foam::Lagrangian::turbulentDispersion::turbulentDispersion
121122
cloudLagrangianModel(static_cast<const LagrangianModel&>(*this)),
122123
dragPtr_(nullptr),
123124
momentumTransportModel_(mesh.mesh().lookupType<momentumTransportModel>()),
125+
Cmu75_(pow(dimensionedScalar("Cmu", dimless, modelDict, 0.09), 0.75)),
126+
maxDiscreteEddies_
127+
(
128+
modelDict.lookupOrDefault<label>("maxDiscreteEddies", 32)
129+
),
124130
kc_
125131
(
126132
cloud<clouds::coupled>().carrierField<scalar>
@@ -217,7 +223,6 @@ void Foam::Lagrangian::turbulentDispersion::calculate
217223
const LagrangianSubVectorField& Uturb0 = Uturb.oldTime();
218224

219225
// Update the eddy time-scale
220-
const dimensionedScalar cps(dimless, 0.16432); // (model constant ?)
221226
const LagrangianSubScalarField magUrel
222227
(
223228
mag(cloud().U(subMesh) - cloud<clouds::coupled>().Uc(subMesh))
@@ -236,12 +241,37 @@ void Foam::Lagrangian::turbulentDispersion::calculate
236241
max
237242
(
238243
kc_(subMesh)/max(epsilonc_(subMesh), rootVSmallEpsilon),
239-
cps*kc_(subMesh)*sqrt(kc_(subMesh))
244+
Cmu75_*kc_(subMesh)*sqrt(kc_(subMesh))
240245
/max(epsilonc_(subMesh)*magUrel, rootVSmallEpsilonU)
241246
);
242247

243248
// Velocity fluctuation magnitude
244-
const LagrangianSubScalarField magUturb(sqrt(2.0/3.0*kc_(subMesh)));
249+
LagrangianSubScalarField magUturb(sqrt(2.0/3.0*kc_(subMesh)));
250+
251+
// Modify particles on the walls to account for the turbulent kinetic
252+
// energy being constrained to zero. This prevents a turbulent velocity
253+
// fluctuation from pointing through a wall and causing a particle to
254+
// vibrate as the drag model and the rebound model fight each other.
255+
const PackedBoolList patchIsWall
256+
(
257+
mesh().mesh().boundaryMesh().findIndices<wallPolyPatch>().toc()
258+
);
259+
forAll(subMesh, subi)
260+
{
261+
const label i = subi + subMesh.start();
262+
263+
if (mesh().state(i) < LagrangianState::onPatchZero) continue;
264+
265+
const label patchi =
266+
static_cast<label>(mesh().state(i))
267+
- static_cast<label>(LagrangianState::onPatchZero);
268+
269+
if (!patchIsWall[patchi]) continue;
270+
271+
tTurb[subi] = rootVSmall;
272+
273+
magUturb[subi] = 0;
274+
}
245275

246276
// Initialise the average turbulent velocities
247277
avgUturbPtr_.reset
@@ -271,6 +301,16 @@ void Foam::Lagrangian::turbulentDispersion::calculate
271301
false
272302
);
273303

304+
// Generate a random direction with a normally distributed magnitude
305+
auto rndDir = [&rndGen, &stdNormal]()
306+
{
307+
const scalar theta =
308+
rndGen.scalar01()*constant::mathematical::twoPi;
309+
const scalar z = 2*rndGen.scalar01() - 1;
310+
const scalar r = sqrt(1 - sqr(z));
311+
return stdNormal.sample()*vector(r*cos(theta), r*sin(theta), z);
312+
};
313+
274314
// Set up sub-stepping
275315
const scalar Dt = max(deltaT[subi], rootVSmall);
276316
scalar dt = 0;
@@ -284,27 +324,40 @@ void Foam::Lagrangian::turbulentDispersion::calculate
284324
}
285325

286326
// Add new eddies across the time-step
287-
while (dt < Dt)
327+
const scalar nEddies = Dt/tTurb[subi];
328+
if (nEddies < maxDiscreteEddies_)
288329
{
289-
const scalar dtPrev = dt;
290-
dt += tTurb[subi];
330+
while (dt < Dt)
331+
{
332+
// Create a turbulent velocity fluctuation for the new eddy
333+
Uturb[subi] = rndDir()*magUturb[subi];
291334

292-
// Create a random direction with normally distributed magnitude
293-
const scalar theta =
294-
rndGen.scalar01()*constant::mathematical::twoPi;
295-
const scalar u = 2*rndGen.scalar01() - 1;
296-
const scalar a = sqrt(1 - sqr(u));
297-
const vector dir(a*cos(theta), a*sin(theta), u);
335+
// Add this eddy to the average
336+
avgUturbPtr_()[subi] +=
337+
(min(dt + tTurb[subi], Dt) - dt)/Dt*Uturb[subi];
298338

299-
// Set the new turbulent fluctuation velocity
300-
Uturb[subi] = dir*stdNormal.sample()*magUturb[subi];
339+
// Increment the time
340+
dt += tTurb[subi];
341+
}
301342

302-
// Add it to the average
303-
avgUturbPtr_()[subi] += (min(dt, Dt) - dtPrev)/Dt*Uturb[subi];
343+
// Set the fraction to where we got to in the current eddy
344+
fractionTurb[subi] = 1 - (dt - Dt)/tTurb[subi];
345+
}
346+
else
347+
{
348+
// Create a turbulent velocity fluctuation for the new eddy
349+
Uturb[subi] = rndDir()*magUturb[subi];
350+
351+
// Add the combined effect of all the eddies to the average
352+
avgUturbPtr_()[subi] +=
353+
(Dt - dt)/Dt
354+
*sqrt(nEddies/3)
355+
*stdNormal.sample<vector>()
356+
*magUturb[subi];
357+
358+
// Set the fraction to indicate that the eddies are finished
359+
fractionTurb[subi] = 1;
304360
}
305-
306-
// Set the fraction to where we got to in the current eddy
307-
fractionTurb[subi] = 1 - (dt - Dt)/tTurb[subi];
308361
}
309362

310363
// If this is not the final iteration then rewind the generator so that the

src/Lagrangian/cloud/LagrangianModels/turbulentDispersion/turbulentDispersion.H

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Usage
3636
<LagrangianModelName>
3737
{
3838
type turbulentDispersion;
39+
Cmu 0.09;
3940
}
4041
\endverbatim
4142
@@ -79,6 +80,14 @@ private:
7980
//- Reference to the momentum transport model
8081
const momentumTransportModel& momentumTransportModel_;
8182

83+
//- Model coefficient, equal to 0.09^0.75 by default
84+
const dimensionedScalar Cmu75_;
85+
86+
//- Maximum number of individual eddies considered per step, equal to
87+
// 32 by default. If there are more than this then the combined effect
88+
// of the eddies is represented approximately.
89+
const label maxDiscreteEddies_;
90+
8291
//- Carrier turbulent kinetic energy
8392
const CarrierField<scalar>& kc_;
8493

0 commit comments

Comments
 (0)