@@ -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
0 commit comments