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 \*---------------------------------------------------------------------------*/
27 #include "CloudTemplate.H"
28 #include "wedgePolyPatch.H"
29 #include "symmetryPolyPatch.H"
30 #include "cyclicPolyPatch.H"
31 #include "processorPolyPatch.H"
32 #include "wallPolyPatch.H"
33 #include "transform.H"
35 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 template<class ParticleType>
38 void Foam::Particle<ParticleType>::findFaces
40 const vector& position,
41 dynamicLabelList& faceList
44 const polyMesh& mesh = cloud_.polyMesh_;
45 const labelList& faces = mesh.cells()[celli_];
46 const vector& C = mesh.cellCentres()[celli_];
51 label facei = faces[i];
52 scalar lam = lambda(C, position, facei);
54 if ((lam > 0) && (lam < 1.0))
56 faceList.append(facei);
62 template<class ParticleType>
63 void Foam::Particle<ParticleType>::findFaces
65 const vector& position,
67 const scalar stepFraction,
68 dynamicLabelList& faceList
71 const polyMesh& mesh = cloud_.pMesh();
72 const labelList& faces = mesh.cells()[celli];
73 const vector& C = mesh.cellCentres()[celli];
78 label facei = faces[i];
79 scalar lam = lambda(C, position, facei, stepFraction);
81 if ((lam > 0) && (lam < 1.0))
83 faceList.append(facei);
89 template<class ParticleType>
90 template<class TrackData>
91 void Foam::Particle<ParticleType>::prepareForParallelTransfer
97 // Convert the face index to be local to the processor patch
98 facei_ = patchFace(patchi, facei_);
102 template<class ParticleType>
103 template<class TrackData>
104 void Foam::Particle<ParticleType>::correctAfterParallelTransfer
110 const processorPolyPatch& ppp =
111 refCast<const processorPolyPatch>
112 (cloud_.pMesh().boundaryMesh()[patchi]);
114 celli_ = ppp.faceCells()[facei_];
118 if (ppp.forwardT().size() == 1)
120 const tensor& T = ppp.forwardT()[0];
121 transformPosition(T);
122 static_cast<ParticleType&>(*this).transformProperties(T);
126 const tensor& T = ppp.forwardT()[facei_];
127 transformPosition(T);
128 static_cast<ParticleType&>(*this).transformProperties(T);
131 else if (ppp.separated())
133 if (ppp.separation().size() == 1)
135 position_ -= ppp.separation()[0];
136 static_cast<ParticleType&>(*this).transformProperties
143 position_ -= ppp.separation()[facei_];
144 static_cast<ParticleType&>(*this).transformProperties
146 -ppp.separation()[facei_]
151 // Reset the face index for the next tracking operation
152 if (stepFraction_ > (1.0 - SMALL))
159 facei_ += ppp.start();
164 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
166 template<class ParticleType>
167 Foam::Particle<ParticleType>::Particle
169 const Cloud<ParticleType>& cloud,
170 const vector& position,
179 origProc_(Pstream::myProcNo()),
180 origId_(cloud_.getNewParticleID())
184 template<class ParticleType>
185 Foam::Particle<ParticleType>::Particle(const Particle<ParticleType>& p)
187 IDLList<ParticleType>::link(),
189 position_(p.position_),
192 stepFraction_(p.stepFraction_),
193 origProc_(p.origProc_),
198 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
200 template<class ParticleType>
201 template<class TrackData>
202 Foam::label Foam::Particle<ParticleType>::track
204 const vector& endPosition,
210 // Tracks to endPosition or stop on boundary
211 while(!onBoundary() && stepFraction_ < 1.0 - SMALL)
213 stepFraction_ += trackToFace(endPosition, td)*(1.0 - stepFraction_);
221 template<class ParticleType>
222 Foam::label Foam::Particle<ParticleType>::track(const vector& endPosition)
225 return track(endPosition, dummyTd);
228 template<class ParticleType>
229 template<class TrackData>
230 Foam::scalar Foam::Particle<ParticleType>::trackToFace
232 const vector& endPosition,
236 const polyMesh& mesh = cloud_.polyMesh_;
238 dynamicLabelList& faces = cloud_.labels_;
239 findFaces(endPosition, faces);
242 scalar trackFraction = 0.0;
244 if (faces.empty()) // inside cell
247 position_ = endPosition;
251 scalar lambdaMin = GREAT;
253 if (faces.size() == 1)
255 lambdaMin = lambda(position_, endPosition, faces[0], stepFraction_);
260 // If the particle has to cross more than one cell to reach the
261 // endPosition, we check which way to go.
262 // If one of the faces is a boundary face and the particle is
263 // outside, we choose the boundary face.
264 // The particle is outside if one of the lambda's is > 1 or < 0
268 lambda(position_, endPosition, faces[i], stepFraction_);
278 bool internalFace = cloud_.internalFace(facei_);
280 // For warped faces the particle can be 'outside' the cell.
281 // This will yield a lambda larger than 1, or smaller than 0
282 // For values < 0, the particle travels away from the cell
283 // and we don't move the particle, only change cell.
284 // For values larger than 1, we move the particle to endPosition only.
287 if (lambdaMin <= 1.0)
289 trackFraction = lambdaMin;
290 position_ += trackFraction*(endPosition - position_);
295 position_ = endPosition;
298 else if (static_cast<ParticleType&>(*this).softImpact())
300 // Soft-sphere particles can travel outside the domain
301 // but we don't use lambda since this the particle
302 // is going away from face
304 position_ = endPosition;
308 if (internalFace) // Internal face
310 if (celli_ == mesh.faceOwner()[facei_])
312 celli_ = mesh.faceNeighbour()[facei_];
314 else if (celli_ == mesh.faceNeighbour()[facei_])
316 celli_ = mesh.faceOwner()[facei_];
322 "Particle::trackToFace(const vector&, TrackData&)"
323 )<< "addressing failure" << nl
324 << abort(FatalError);
329 ParticleType& p = static_cast<ParticleType&>(*this);
331 // Soft-sphere algorithm ignores the boundary
335 position_ = endPosition;
338 label patchi = patch(facei_);
339 const polyPatch& patch = mesh.boundaryMesh()[patchi];
341 if (!p.hitPatch(patch, td, patchi))
343 if (isA<wedgePolyPatch>(patch))
347 static_cast<const wedgePolyPatch&>(patch), td
350 else if (isA<symmetryPolyPatch>(patch))
354 static_cast<const symmetryPolyPatch&>(patch), td
357 else if (isA<cyclicPolyPatch>(patch))
361 static_cast<const cyclicPolyPatch&>(patch), td
364 else if (isA<processorPolyPatch>(patch))
368 static_cast<const processorPolyPatch&>(patch), td
371 else if (isA<wallPolyPatch>(patch))
375 static_cast<const wallPolyPatch&>(patch), td
380 p.hitPatch(patch, td);
386 // If the trackFraction = 0 something went wrong.
387 // Either the particle is flipping back and forth across a face perhaps
388 // due to velocity interpolation errors or it is in a "hole" in the mesh
389 // caused by face warpage.
390 // In both cases resolve the positional ambiguity by moving the particle
391 // slightly towards the cell-centre.
392 if (trackFraction < SMALL)
394 position_ += 1.0e-3*(mesh.cellCentres()[celli_] - position_);
397 return trackFraction;
400 template<class ParticleType>
401 Foam::scalar Foam::Particle<ParticleType>::trackToFace
403 const vector& endPosition
407 return trackToFace(endPosition, dummyTd);
410 template<class ParticleType>
411 void Foam::Particle<ParticleType>::transformPosition(const tensor& T)
413 position_ = transform(T, position_);
417 template<class ParticleType>
418 void Foam::Particle<ParticleType>::transformProperties(const tensor&)
422 template<class ParticleType>
423 void Foam::Particle<ParticleType>::transformProperties(const vector&)
427 template<class ParticleType>
428 template<class TrackData>
429 bool Foam::Particle<ParticleType>::hitPatch
440 template<class ParticleType>
441 template<class TrackData>
442 void Foam::Particle<ParticleType>::hitWedgePatch
444 const wedgePolyPatch& wpp,
448 vector nf = wpp.faceAreas()[wpp.whichFace(facei_)];
451 static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
455 template<class ParticleType>
456 template<class TrackData>
457 void Foam::Particle<ParticleType>::hitSymmetryPatch
459 const symmetryPolyPatch& spp,
463 vector nf = spp.faceAreas()[spp.whichFace(facei_)];
466 static_cast<ParticleType&>(*this).transformProperties(I - 2.0*nf*nf);
470 template<class ParticleType>
471 template<class TrackData>
472 void Foam::Particle<ParticleType>::hitCyclicPatch
474 const cyclicPolyPatch& cpp,
478 label patchFacei_ = cpp.whichFace(facei_);
480 facei_ = cpp.transformGlobalFace(facei_);
482 celli_ = cloud_.polyMesh_.faceOwner()[facei_];
486 const tensor& T = cpp.transformT(patchFacei_);
488 transformPosition(T);
489 static_cast<ParticleType&>(*this).transformProperties(T);
491 else if (cpp.separated())
493 position_ += cpp.separation(patchFacei_);
494 static_cast<ParticleType&>(*this).transformProperties
496 cpp.separation(patchFacei_)
502 template<class ParticleType>
503 template<class TrackData>
504 void Foam::Particle<ParticleType>::hitProcessorPatch
506 const processorPolyPatch& spp,
512 template<class ParticleType>
513 template<class TrackData>
514 void Foam::Particle<ParticleType>::hitWallPatch
516 const wallPolyPatch& spp,
522 template<class ParticleType>
523 template<class TrackData>
524 void Foam::Particle<ParticleType>::hitPatch
526 const polyPatch& spp,
532 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
534 #include "ParticleIO.C"
536 // ************************************************************************* //