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 "DsmcParcel.H"
28 #include "meshTools.H"
30 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
32 template<class ParcelType>
33 template<class TrackData>
34 bool Foam::DsmcParcel<ParcelType>::move
39 ParcelType& p = static_cast<ParcelType&>(*this);
41 td.switchProcessor = false;
42 td.keepParticle = true;
44 const polyMesh& mesh = td.cloud().pMesh();
45 const polyBoundaryMesh& pbMesh = mesh.boundaryMesh();
47 const scalar deltaT = mesh.time().deltaTValue();
48 scalar tEnd = (1.0 - p.stepFraction())*deltaT;
49 const scalar dtMax = tEnd;
51 // For reduced-D cases, the velocity used to track needs to be
52 // constrained, but the actual U_ of the parcel must not be
53 // altered or used, as it is altered by patch interactions an
54 // needs to retain its 3D value for collision purposes.
55 vector Utracking = U_;
57 while (td.keepParticle && !td.switchProcessor && tEnd > ROOTVSMALL)
59 // Apply correction to position for reduced-D cases
60 meshTools::constrainToMeshCentre(mesh, p.position());
64 // Apply correction to velocity to constrain tracking for
66 meshTools::constrainDirection(mesh, mesh.solutionD(), Utracking);
68 // Set the Lagrangian time-step
69 scalar dt = min(dtMax, tEnd);
71 dt *= p.trackToFace(p.position() + dt*Utracking, td);
75 p.stepFraction() = 1.0 - tEnd/deltaT;
77 if (p.onBoundary() && td.keepParticle)
79 if (isA<processorPolyPatch>(pbMesh[p.patch(p.face())]))
81 td.switchProcessor = true;
86 return td.keepParticle;
90 template<class ParcelType>
91 template<class TrackData>
92 bool Foam::DsmcParcel<ParcelType>::hitPatch
103 template<class ParcelType>
104 template<class TrackData>
105 void Foam::DsmcParcel<ParcelType>::hitProcessorPatch
107 const processorPolyPatch&,
111 td.switchProcessor = true;
115 template<class ParcelType>
116 void Foam::DsmcParcel<ParcelType>::hitProcessorPatch
118 const processorPolyPatch&,
124 template<class ParcelType>
125 template<class TrackData>
126 void Foam::DsmcParcel<ParcelType>::hitWallPatch
128 const wallPolyPatch& wpp,
132 label wppIndex = wpp.index();
134 label wppLocalFace = wpp.whichFace(this->face());
136 const scalar fA = mag(wpp.faceAreas()[wppLocalFace]);
138 const scalar deltaT = td.cloud().pMesh().time().deltaTValue();
140 const constantProperties& constProps(td.cloud().constProps(typeId_));
142 scalar m = constProps.mass();
144 vector nw = wpp.faceAreas()[wppLocalFace];
147 scalar U_dot_nw = U_ & nw;
149 vector Ut = U_ - U_dot_nw*nw;
151 scalar invMagUnfA = 1/max(mag(U_dot_nw)*fA, VSMALL);
153 td.cloud().rhoNBF()[wppIndex][wppLocalFace] += invMagUnfA;
155 td.cloud().rhoMBF()[wppIndex][wppLocalFace] += m*invMagUnfA;
157 td.cloud().linearKEBF()[wppIndex][wppLocalFace] +=
158 0.5*m*(U_ & U_)*invMagUnfA;
160 td.cloud().internalEBF()[wppIndex][wppLocalFace] += Ei_*invMagUnfA;
162 td.cloud().iDofBF()[wppIndex][wppLocalFace] +=
163 constProps.internalDegreesOfFreedom()*invMagUnfA;
165 td.cloud().momentumBF()[wppIndex][wppLocalFace] += m*Ut*invMagUnfA;
167 // pre-interaction energy
168 scalar preIE = 0.5*m*(U_ & U_) + Ei_;
170 // pre-interaction momentum
171 vector preIMom = m*U_;
173 td.cloud().wallInteraction().correct
184 Ut = U_ - U_dot_nw*nw;
186 invMagUnfA = 1/max(mag(U_dot_nw)*fA, VSMALL);
188 td.cloud().rhoNBF()[wppIndex][wppLocalFace] += invMagUnfA;
190 td.cloud().rhoMBF()[wppIndex][wppLocalFace] += m*invMagUnfA;
192 td.cloud().linearKEBF()[wppIndex][wppLocalFace] +=
193 0.5*m*(U_ & U_)*invMagUnfA;
195 td.cloud().internalEBF()[wppIndex][wppLocalFace] += Ei_*invMagUnfA;
197 td.cloud().iDofBF()[wppIndex][wppLocalFace] +=
198 constProps.internalDegreesOfFreedom()*invMagUnfA;
200 td.cloud().momentumBF()[wppIndex][wppLocalFace] += m*Ut*invMagUnfA;
202 // post-interaction energy
203 scalar postIE = 0.5*m*(U_ & U_) + Ei_;
205 // post-interaction momentum
206 vector postIMom = m*U_;
208 scalar deltaQ = td.cloud().nParticle()*(preIE - postIE)/(deltaT*fA);
210 vector deltaFD = td.cloud().nParticle()*(preIMom - postIMom)/(deltaT*fA);
212 td.cloud().qBF()[wppIndex][wppLocalFace] += deltaQ;
214 td.cloud().fDBF()[wppIndex][wppLocalFace] += deltaFD;
219 template<class ParcelType>
220 void Foam::DsmcParcel<ParcelType>::hitWallPatch
222 const wallPolyPatch&,
228 template<class ParcelType>
229 template<class TrackData>
230 void Foam::DsmcParcel<ParcelType>::hitPatch
236 td.keepParticle = false;
240 template<class ParcelType>
241 void Foam::DsmcParcel<ParcelType>::hitPatch
249 template<class ParcelType>
250 void Foam::DsmcParcel<ParcelType>::transformProperties
255 Particle<ParcelType>::transformProperties(T);
256 U_ = transform(T, U_);
260 template<class ParcelType>
261 void Foam::DsmcParcel<ParcelType>::transformProperties
263 const vector& separation
266 Particle<ParcelType>::transformProperties(separation);
270 // * * * * * * * * * * * * * * * * IOStream operators * * * * * * * * * * * //
272 #include "DsmcParcelIO.C"
274 // ************************************************************************* //