1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend 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 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
28 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
30 template<class ParticleType>
31 inline Foam::scalar Foam::Particle<ParticleType>::lambda
36 const scalar stepFraction
39 const polyMesh& mesh = cloud_.polyMesh_;
40 bool movingMesh = mesh.moving();
44 vector Sf = mesh.faceAreas()[facei];
46 vector Cf = mesh.faceCentres()[facei];
48 // move reference point for wall
49 if (!cloud_.internalFace(facei))
51 const vector& C = mesh.cellCentres()[celli_];
52 scalar CCf = mag((C - Cf) & Sf);
53 // check if distance between cell centre and face centre
54 // is larger than wallImpactDistance
58 > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
61 Cf -= static_cast<const ParticleType&>(*this)
62 .wallImpactDistance(Sf)*Sf;
66 // for a moving mesh we need to reconstruct the old
67 // Sf and Cf from oldPoints (they aren't stored)
69 const vectorField& oldPoints = mesh.oldPoints();
71 vector Cf00 = mesh.faces()[facei].centre(oldPoints);
72 vector Cf0 = Cf00 + stepFraction*(Cf - Cf00);
74 vector Sf00 = mesh.faces()[facei].normal(oldPoints);
76 // for layer addition Sf00 = vector::zero and we use Sf
77 if (mag(Sf00) > SMALL)
86 scalar magSfDiff = mag(Sf - Sf00);
88 // check if the face is rotating
89 if (magSfDiff > SMALL)
91 vector Sf0 = Sf00 + stepFraction*(Sf - Sf00);
93 // find center of rotation
94 vector omega = Sf0 ^ Sf;
95 scalar magOmega = mag(omega);
96 omega /= magOmega + SMALL;
97 vector n0 = omega ^ Sf0;
98 scalar lam = ((Cf - Cf0) & Sf)/(n0 & Sf);
99 vector r0 = Cf0 + lam*n0;
101 // solve '(p - r0) & Sfp = 0', where
102 // p = from + lambda*(to - from)
103 // Sfp = Sf0 + lambda*(Sf - Sf0)
104 // which results in the quadratic eq.
105 // a*lambda^2 + b*lambda + c = 0
106 vector alpha = from - r0;
107 vector beta = to - from;
108 scalar a = beta & (Sf - Sf0);
109 scalar b = (alpha & (Sf - Sf0)) + (beta & Sf0);
110 scalar c = alpha & Sf0;
114 // solve the second order polynomial
117 scalar cp = ap*ap - 4.0*bp;
121 // imaginary roots only
126 scalar l1 = -0.5*(ap - ::sqrt(cp));
127 scalar l2 = -0.5*(ap + ::sqrt(cp));
129 // one root is around 0-1, while
130 // the other is very large in mag
131 if (mag(l1) < mag(l2))
143 // when a==0, solve the first order polynomial
149 vector alpha = from - Cf0;
150 vector beta = to - from - (Cf - Cf0);
151 scalar lambdaNominator = alpha & Sf;
152 scalar lambdaDenominator = beta & Sf;
154 // check if trajectory is parallel to face
155 if (mag(lambdaDenominator) < SMALL)
157 if (lambdaDenominator < 0.0)
159 lambdaDenominator = -SMALL;
163 lambdaDenominator = SMALL;
167 return (-lambdaNominator/lambdaDenominator);
172 // mesh is static and stepFraction is not needed
173 return lambda(from, to, facei);
178 template<class ParticleType>
179 inline Foam::scalar Foam::Particle<ParticleType>::lambda
186 const polyMesh& mesh = cloud_.polyMesh_;
188 vector Sf = mesh.faceAreas()[facei];
190 vector Cf = mesh.faceCentres()[facei];
192 // move reference point for wall
193 if (!cloud_.internalFace(facei))
195 const vector& C = mesh.cellCentres()[celli_];
196 scalar CCf = mag((C - Cf) & Sf);
197 // check if distance between cell centre and face centre
198 // is larger than wallImpactDistance
202 > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
205 Cf -= static_cast<const ParticleType&>(*this)
206 .wallImpactDistance(Sf)*Sf;
210 scalar lambdaNominator = (Cf - from) & Sf;
211 scalar lambdaDenominator = (to - from) & Sf;
213 // check if trajectory is parallel to face
214 if (mag(lambdaDenominator) < SMALL)
216 if (lambdaDenominator < 0.0)
218 lambdaDenominator = -SMALL;
222 lambdaDenominator = SMALL;
226 return lambdaNominator/lambdaDenominator;
230 template<class ParticleType>
231 inline bool Foam::Particle<ParticleType>::inCell() const
233 dynamicLabelList& faces = cloud_.labels_;
234 findFaces(position_, faces);
236 return (!faces.size());
240 template<class ParticleType>
241 inline bool Foam::Particle<ParticleType>::inCell
243 const vector& position,
245 const scalar stepFraction
248 dynamicLabelList& faces = cloud_.labels_;
249 findFaces(position, celli, stepFraction, faces);
251 return (!faces.size());
255 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
257 template<class ParticleType>
258 inline Foam::Particle<ParticleType>::trackData::trackData
260 Cloud<ParticleType>& cloud
267 template<class ParticleType>
268 inline Foam::Cloud<ParticleType>&
269 Foam::Particle<ParticleType>::trackData::cloud()
275 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
277 template<class ParticleType>
278 inline const Foam::Cloud<ParticleType>&
279 Foam::Particle<ParticleType>::cloud() const
285 template<class ParticleType>
286 inline const Foam::vector& Foam::Particle<ParticleType>::position() const
292 template<class ParticleType>
293 inline Foam::vector& Foam::Particle<ParticleType>::position()
299 template<class ParticleType>
300 inline Foam::label Foam::Particle<ParticleType>::cell() const
306 template<class ParticleType>
307 inline Foam::label& Foam::Particle<ParticleType>::cell()
313 template<class ParticleType>
314 inline Foam::label Foam::Particle<ParticleType>::face() const
320 template<class ParticleType>
321 inline bool Foam::Particle<ParticleType>::onBoundary() const
323 return facei_ != -1 && facei_ >= cloud_.pMesh().nInternalFaces();
327 template<class ParticleType>
328 inline Foam::scalar& Foam::Particle<ParticleType>::stepFraction()
330 return stepFraction_;
334 template<class ParticleType>
335 inline Foam::scalar Foam::Particle<ParticleType>::stepFraction() const
337 return stepFraction_;
341 template<class ParticleType>
342 inline Foam::label Foam::Particle<ParticleType>::origProc() const
348 template<class ParticleType>
349 inline Foam::label Foam::Particle<ParticleType>::origId() const
355 template<class ParticleType>
356 inline bool Foam::Particle<ParticleType>::softImpact() const
362 template<class ParticleType>
363 inline Foam::scalar Foam::Particle<ParticleType>::currentTime() const
366 cloud_.pMesh().time().value()
367 + stepFraction_*cloud_.pMesh().time().deltaT().value();
371 template<class ParticleType>
372 inline Foam::label Foam::Particle<ParticleType>::patch(const label facei) const
374 return cloud_.facePatch(facei);
378 template<class ParticleType>
379 inline Foam::label Foam::Particle<ParticleType>::patchFace
385 return cloud_.patchFace(patchi, facei);
389 template<class ParticleType>
391 Foam::Particle<ParticleType>::wallImpactDistance(const vector&) const
397 template<class ParticleType>
398 inline Foam::label Foam::Particle<ParticleType>::faceInterpolation() const
404 // ************************************************************************* //