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 \*---------------------------------------------------------------------------*/
27 #include "ExactParticle.H"
29 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
31 template<class ParticleType>
32 template<class TrackingData>
33 Foam::label Foam::ExactParticle<ParticleType>::track
35 const vector& endPosition,
41 // Tracks to endPosition or stop on boundary
42 while (!this->onBoundary() && this->stepFraction_ < 1.0 - SMALL)
44 this->stepFraction_ +=
45 trackToFace(endPosition, td)
46 *(1.0 - this->stepFraction_);
53 template<class ParticleType>
54 Foam::label Foam::ExactParticle<ParticleType>::track
56 const vector& endPosition
60 return track(endPosition, dummyTd);
64 template<class ParticleType>
65 template<class TrackingData>
66 Foam::scalar Foam::ExactParticle<ParticleType>::trackToFace
68 const vector& endPosition,
72 const polyMesh& mesh = this->cloud().pMesh();
73 const labelList& cFaces = mesh.cells()[this->celli_];
75 point intersection(vector::zero);
76 scalar trackFraction = VGREAT;
79 const vector vec = endPosition-this->position_;
83 label facei = cFaces[i];
85 if (facei != this->face())
87 pointHit inter = mesh.faces()[facei].fastIntersection
91 mesh.faceCentres()[facei],
93 intersection::HALF_RAY
96 if (inter.hit() && inter.distance() < trackFraction)
98 trackFraction = inter.distance();
100 intersection = inter.hitPoint();
107 // Did not find any intersection. Fall back to original approximate
109 return Particle<ParticleType>::trackToFace
116 if (trackFraction >= (1.0-SMALL))
118 // Nearest intersection beyond endPosition so we hit endPosition.
120 this->position_ = endPosition;
126 this->position_ = intersection;
127 this->facei_ = hitFacei;
131 // Normal situation (trackFraction 0..1). Straight copy
132 // of Particle::trackToFace.
134 bool internalFace = this->cloud().internalFace(this->facei_);
137 if (internalFace) // Internal face
139 if (this->celli_ == mesh.faceOwner()[this->facei_])
141 this->celli_ = mesh.faceNeighbour()[this->facei_];
143 else if (this->celli_ == mesh.faceNeighbour()[this->facei_])
145 this->celli_ = mesh.faceOwner()[this->facei_];
151 "ExactParticle::trackToFace"
152 "(const vector&, TrackingData&)"
153 )<< "addressing failure" << nl
154 << abort(FatalError);
159 ParticleType& p = static_cast<ParticleType&>(*this);
161 // Soft-sphere algorithm ignores the boundary
165 this->position_ = endPosition;
168 label patchi = patch(this->facei_);
169 const polyPatch& patch = mesh.boundaryMesh()[patchi];
171 if (isA<wedgePolyPatch>(patch))
175 static_cast<const wedgePolyPatch&>(patch), td
178 else if (isA<symmetryPolyPatch>(patch))
182 static_cast<const symmetryPolyPatch&>(patch), td
185 else if (isA<cyclicPolyPatch>(patch))
189 static_cast<const cyclicPolyPatch&>(patch), td
192 else if (isA<processorPolyPatch>(patch))
196 static_cast<const processorPolyPatch&>(patch), td
199 else if (isA<wallPolyPatch>(patch))
203 static_cast<const wallPolyPatch&>(patch), td
206 else if (isA<polyPatch>(patch))
210 static_cast<const polyPatch&>(patch), td
217 "ExactParticle::trackToFace"
218 "(const vector& endPosition, scalar& trackFraction)"
219 )<< "patch type " << patch.type() << " not suported" << nl
220 << abort(FatalError);
224 // If the trackFraction = 0 something went wrong.
225 // Either the particle is flipping back and forth across a face perhaps
226 // due to velocity interpolation errors or it is in a "hole" in the mesh
227 // caused by face warpage.
228 // In both cases resolve the positional ambiguity by moving the particle
229 // slightly towards the cell-centre.
230 if (trackFraction < SMALL)
233 1.0e-6*(mesh.cellCentres()[this->celli_] - this->position_);
236 return trackFraction;
240 template<class ParticleType>
241 Foam::scalar Foam::ExactParticle<ParticleType>::trackToFace
243 const vector& endPosition
247 return trackToFace(endPosition, dummyTd);
251 template<class ParticleType>
252 Foam::Ostream& Foam::operator<<
255 const ExactParticle<ParticleType>& p
258 return operator<<(os, static_cast<const Particle<ParticleType>&>(p));
262 // ************************************************************************* //