Merge /u/wyldckat/foam-extend32/ branch master into master
[foam-extend-3.2.git] / src / lagrangian / basic / Particle / ParticleI.H
blobbeef8cdfe977657be1070005a02499e10b6e6863
1 /*---------------------------------------------------------------------------*\
2   =========                 |
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 -------------------------------------------------------------------------------
8 License
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 \*---------------------------------------------------------------------------*/
26 #include "polyMesh.H"
28 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
30 template<class ParticleType>
31 inline Foam::scalar Foam::Particle<ParticleType>::lambda
33     const vector& from,
34     const vector& to,
35     const label facei,
36     const scalar stepFraction
37 ) const
39     const polyMesh& mesh = cloud_.polyMesh_;
40     bool movingMesh = mesh.moving();
42     if (movingMesh)
43     {
44         vector Sf = mesh.faceAreas()[facei];
45         Sf /= mag(Sf);
46         vector Cf = mesh.faceCentres()[facei];
48         // move reference point for wall
49         if (!cloud_.internalFace(facei))
50         {
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
55             if
56             (
57                 CCf
58               > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
59             )
60             {
61                 Cf -= static_cast<const ParticleType&>(*this)
62                     .wallImpactDistance(Sf)*Sf;
63             }
64         }
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)
78         {
79             Sf00 /= mag(Sf00);
80         }
81         else
82         {
83             Sf00 = Sf;
84         }
86         scalar magSfDiff = mag(Sf - Sf00);
88         // check if the face is rotating
89         if (magSfDiff > SMALL)
90         {
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;
112             if (mag(a) > SMALL)
113             {
114                 // solve the second order polynomial
115                 scalar ap = b/a;
116                 scalar bp = c/a;
117                 scalar cp = ap*ap - 4.0*bp;
119                 if (cp < 0.0)
120                 {
121                     // imaginary roots only
122                     return GREAT;
123                 }
124                 else
125                 {
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))
132                     {
133                         return l1;
134                     }
135                     else
136                     {
137                         return l2;
138                     }
139                 }
140             }
141             else
142             {
143                 // when a==0, solve the first order polynomial
144                 return (-c/b);
145             }
146         }
147         else // no rotation
148         {
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)
156             {
157                 if (lambdaDenominator < 0.0)
158                 {
159                     lambdaDenominator = -SMALL;
160                 }
161                 else
162                 {
163                     lambdaDenominator = SMALL;
164                 }
165             }
167             return (-lambdaNominator/lambdaDenominator);
168         }
169     }
170     else
171     {
172         // mesh is static and stepFraction is not needed
173         return lambda(from, to, facei);
174     }
178 template<class ParticleType>
179 inline Foam::scalar Foam::Particle<ParticleType>::lambda
181     const vector& from,
182     const vector& to,
183     const label facei
184 ) const
186     const polyMesh& mesh = cloud_.polyMesh_;
188     vector Sf = mesh.faceAreas()[facei];
189     Sf /= mag(Sf);
190     vector Cf = mesh.faceCentres()[facei];
192     // move reference point for wall
193     if (!cloud_.internalFace(facei))
194     {
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
199         if
200         (
201             CCf
202           > static_cast<const ParticleType&>(*this).wallImpactDistance(Sf)
203         )
204         {
205             Cf -= static_cast<const ParticleType&>(*this)
206                 .wallImpactDistance(Sf)*Sf;
207         }
208     }
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)
215     {
216         if (lambdaDenominator < 0.0)
217         {
218             lambdaDenominator = -SMALL;
219         }
220         else
221         {
222             lambdaDenominator = SMALL;
223         }
224     }
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,
244     const label celli,
245     const scalar stepFraction
246 ) const
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
263     cloud_(cloud)
267 template<class ParticleType>
268 inline Foam::Cloud<ParticleType>&
269 Foam::Particle<ParticleType>::trackData::cloud()
271     return cloud_;
275 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
277 template<class ParticleType>
278 inline const Foam::Cloud<ParticleType>&
279 Foam::Particle<ParticleType>::cloud() const
281     return cloud_;
285 template<class ParticleType>
286 inline const Foam::vector& Foam::Particle<ParticleType>::position() const
288     return position_;
292 template<class ParticleType>
293 inline Foam::vector& Foam::Particle<ParticleType>::position()
295     return position_;
299 template<class ParticleType>
300 inline Foam::label Foam::Particle<ParticleType>::cell() const
302     return celli_;
306 template<class ParticleType>
307 inline Foam::label& Foam::Particle<ParticleType>::cell()
309     return celli_;
313 template<class ParticleType>
314 inline Foam::label Foam::Particle<ParticleType>::face() const
316     return facei_;
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
344     return origProc_;
348 template<class ParticleType>
349 inline Foam::label Foam::Particle<ParticleType>::origId() const
351     return origId_;
355 template<class ParticleType>
356 inline bool Foam::Particle<ParticleType>::softImpact() const
358     return false;
362 template<class ParticleType>
363 inline Foam::scalar Foam::Particle<ParticleType>::currentTime() const
365     return
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
381     const label patchi,
382     const label facei
383 ) const
385     return cloud_.patchFace(patchi, facei);
389 template<class ParticleType>
390 inline Foam::scalar
391 Foam::Particle<ParticleType>::wallImpactDistance(const vector&) const
393     return 0.0;
397 template<class ParticleType>
398 inline Foam::label Foam::Particle<ParticleType>::faceInterpolation() const
400     return facei_;
404 // ************************************************************************* //