1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software; you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation; either version 2 of the License, or (at your
14 option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM; if not, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 template<class ParticleType>
32 inline Foam::scalar Foam::Particle<ParticleType>::lambda
37 const scalar stepFraction
40 const polyMesh& mesh = cloud_.polyMesh_;
41 bool movingMesh = mesh.moving();
45 vector Sf = mesh.faceAreas()[facei];
47 vector Cf = mesh.faceCentres()[facei];
49 // move reference point for wall
50 if (!cloud_.internalFace(facei))
52 const vector& C = mesh.cellCentres()[celli_];
53 scalar CCf = mag((C - Cf) & Sf);
54 // check if distance between cell centre and face centre
55 // is larger than wallImpactDistance
59 > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
62 Cf -= static_cast<const ParticleType&>(*this)
63 .wallImpactDistance(Sf)*Sf;
67 // for a moving mesh we need to reconstruct the old
68 // Sf and Cf from oldPoints (they aren't stored)
70 const vectorField& oldPoints = mesh.oldPoints();
72 vector Cf00 = mesh.faces()[facei].centre(oldPoints);
73 vector Cf0 = Cf00 + stepFraction*(Cf - Cf00);
75 vector Sf00 = mesh.faces()[facei].normal(oldPoints);
77 // for layer addition Sf00 = vector::zero and we use Sf
78 if (mag(Sf00) > SMALL)
87 scalar magSfDiff = mag(Sf - Sf00);
89 // check if the face is rotating
90 if (magSfDiff > SMALL)
92 vector Sf0 = Sf00 + stepFraction*(Sf - Sf00);
94 // find center of rotation
95 vector omega = Sf0 ^ Sf;
96 scalar magOmega = mag(omega);
97 omega /= magOmega + SMALL;
98 vector n0 = omega ^ Sf0;
99 scalar lam = ((Cf - Cf0) & Sf)/(n0 & Sf);
100 vector r0 = Cf0 + lam*n0;
102 // solve '(p - r0) & Sfp = 0', where
103 // p = from + lambda*(to - from)
104 // Sfp = Sf0 + lambda*(Sf - Sf0)
105 // which results in the quadratic eq.
106 // a*lambda^2 + b*lambda + c = 0
107 vector alpha = from - r0;
108 vector beta = to - from;
109 scalar a = beta & (Sf - Sf0);
110 scalar b = (alpha & (Sf - Sf0)) + (beta & Sf0);
111 scalar c = alpha & Sf0;
115 // solve the second order polynomial
118 scalar cp = ap*ap - 4.0*bp;
122 // imaginary roots only
127 scalar l1 = -0.5*(ap - ::sqrt(cp));
128 scalar l2 = -0.5*(ap + ::sqrt(cp));
130 // one root is around 0-1, while
131 // the other is very large in mag
132 if (mag(l1) < mag(l2))
144 // when a==0, solve the first order polynomial
150 vector alpha = from - Cf0;
151 vector beta = to - from - (Cf - Cf0);
152 scalar lambdaNominator = alpha & Sf;
153 scalar lambdaDenominator = beta & Sf;
155 // check if trajectory is parallel to face
156 if (mag(lambdaDenominator) < SMALL)
158 if (lambdaDenominator < 0.0)
160 lambdaDenominator = -SMALL;
164 lambdaDenominator = SMALL;
168 return (-lambdaNominator/lambdaDenominator);
173 // mesh is static and stepFraction is not needed
174 return lambda(from, to, facei);
179 template<class ParticleType>
180 inline Foam::scalar Foam::Particle<ParticleType>::lambda
187 const polyMesh& mesh = cloud_.polyMesh_;
189 vector Sf = mesh.faceAreas()[facei];
191 vector Cf = mesh.faceCentres()[facei];
193 // move reference point for wall
194 if (!cloud_.internalFace(facei))
196 const vector& C = mesh.cellCentres()[celli_];
197 scalar CCf = mag((C - Cf) & Sf);
198 // check if distance between cell centre and face centre
199 // is larger than wallImpactDistance
203 > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
206 Cf -= static_cast<const ParticleType&>(*this)
207 .wallImpactDistance(Sf)*Sf;
211 scalar lambdaNominator = (Cf - from) & Sf;
212 scalar lambdaDenominator = (to - from) & Sf;
214 // check if trajectory is parallel to face
215 if (mag(lambdaDenominator) < SMALL)
217 if (lambdaDenominator < 0.0)
219 lambdaDenominator = -SMALL;
223 lambdaDenominator = SMALL;
227 return lambdaNominator/lambdaDenominator;
231 template<class ParticleType>
232 inline bool Foam::Particle<ParticleType>::inCell() const
234 DynamicList<label>& faces = cloud_.labels_;
235 findFaces(position_, faces);
237 return (!faces.size());
241 template<class ParticleType>
242 inline bool Foam::Particle<ParticleType>::inCell
244 const vector& position,
246 const scalar stepFraction
249 DynamicList<label>& faces = cloud_.labels_;
250 findFaces(position, celli, stepFraction, faces);
252 return (!faces.size());
256 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
258 template<class ParticleType>
259 inline Foam::Particle<ParticleType>::trackData::trackData
261 Cloud<ParticleType>& cloud
268 template<class ParticleType>
269 inline Foam::Cloud<ParticleType>&
270 Foam::Particle<ParticleType>::trackData::cloud()
276 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
278 template<class ParticleType>
279 inline const Foam::Cloud<ParticleType>&
280 Foam::Particle<ParticleType>::cloud() const
286 template<class ParticleType>
287 inline const Foam::vector& Foam::Particle<ParticleType>::position() const
293 template<class ParticleType>
294 inline Foam::vector& Foam::Particle<ParticleType>::position()
300 template<class ParticleType>
301 inline Foam::label Foam::Particle<ParticleType>::cell() const
307 template<class ParticleType>
308 inline Foam::label& Foam::Particle<ParticleType>::cell()
314 template<class ParticleType>
315 inline Foam::label Foam::Particle<ParticleType>::face() const
321 template<class ParticleType>
322 inline bool Foam::Particle<ParticleType>::onBoundary() const
324 return facei_ != -1 && facei_ >= cloud_.pMesh().nInternalFaces();
328 template<class ParticleType>
329 inline Foam::scalar& Foam::Particle<ParticleType>::stepFraction()
331 return stepFraction_;
335 template<class ParticleType>
336 inline Foam::scalar Foam::Particle<ParticleType>::stepFraction() const
338 return stepFraction_;
342 template<class ParticleType>
343 inline Foam::label Foam::Particle<ParticleType>::origProc() const
349 template<class ParticleType>
350 inline Foam::label Foam::Particle<ParticleType>::origId() const
356 template<class ParticleType>
357 inline bool Foam::Particle<ParticleType>::softImpact() const
363 template<class ParticleType>
364 inline Foam::scalar Foam::Particle<ParticleType>::currentTime() const
367 cloud_.pMesh().time().value()
368 + stepFraction_*cloud_.pMesh().time().deltaT().value();
372 template<class ParticleType>
373 inline Foam::label Foam::Particle<ParticleType>::patch(const label facei) const
375 return cloud_.facePatch(facei);
379 template<class ParticleType>
380 inline Foam::label Foam::Particle<ParticleType>::patchFace
386 return cloud_.patchFace(patchi, facei);
390 template<class ParticleType>
392 Foam::Particle<ParticleType>::wallImpactDistance(const vector&) const
398 template<class ParticleType>
399 inline Foam::label Foam::Particle<ParticleType>::faceInterpolation() const
405 // ************************************************************************* //