Initial commit for version 2.0.x patch release
[OpenFOAM-2.0.x.git] / src / lagrangian / intermediate / submodels / Kinematic / InjectionModel / PatchInjection / PatchInjection.C
blob43caac386535e9523f40552bc2c2eaaf56fec041
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2009-2011 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
13     the Free Software Foundation, either version 3 of the License, or
14     (at your 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
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "PatchInjection.H"
27 #include "DataEntry.H"
28 #include "distributionModel.H"
30 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
32 template<class CloudType>
33 Foam::PatchInjection<CloudType>::PatchInjection
35     const dictionary& dict,
36     CloudType& owner
39     InjectionModel<CloudType>(dict, owner, typeName),
40     patchName_(this->coeffDict().lookup("patchName")),
41     patchId_(owner.mesh().boundaryMesh().findPatchID(patchName_)),
42     duration_(readScalar(this->coeffDict().lookup("duration"))),
43     parcelsPerSecond_
44     (
45         readScalar(this->coeffDict().lookup("parcelsPerSecond"))
46     ),
47     U0_(this->coeffDict().lookup("U0")),
48     flowRateProfile_
49     (
50         DataEntry<scalar>::New("flowRateProfile", this->coeffDict())
51     ),
52     sizeDistribution_
53     (
54         distributionModels::distributionModel::New
55         (
56             this->coeffDict().subDict("sizeDistribution"),
57             owner.rndGen()
58         )
59     ),
60     cellOwners_(),
61     fraction_(1.0)
63     if (patchId_ < 0)
64     {
65         FatalErrorIn
66         (
67             "PatchInjection<CloudType>::PatchInjection"
68             "("
69                 "const dictionary&, "
70                 "CloudType&"
71             ")"
72         )   << "Requested patch " << patchName_ << " not found" << nl
73             << "Available patches are: " << owner.mesh().boundaryMesh().names()
74             << nl << exit(FatalError);
75     }
77     const polyPatch& patch = owner.mesh().boundaryMesh()[patchId_];
79     cellOwners_ = patch.faceCells();
81     label patchSize = cellOwners_.size();
82     label totalPatchSize = patchSize;
83     reduce(totalPatchSize, sumOp<label>());
84     fraction_ = scalar(patchSize)/totalPatchSize;
86     // Set total volume/mass to inject
87     this->volumeTotal_ = fraction_*flowRateProfile_().integrate(0.0, duration_);
88     this->massTotal_ *= fraction_;
92 template<class CloudType>
93 Foam::PatchInjection<CloudType>::PatchInjection
95     const PatchInjection<CloudType>& im
98     InjectionModel<CloudType>(im),
99     patchName_(im.patchName_),
100     patchId_(im.patchId_),
101     duration_(im.duration_),
102     parcelsPerSecond_(im.parcelsPerSecond_),
103     U0_(im.U0_),
104     flowRateProfile_(im.flowRateProfile_().clone().ptr()),
105     sizeDistribution_(im.sizeDistribution_().clone().ptr()),
106     cellOwners_(im.cellOwners_),
107     fraction_(im.fraction_)
111 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
113 template<class CloudType>
114 Foam::PatchInjection<CloudType>::~PatchInjection()
118 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
120 template<class CloudType>
121 Foam::scalar Foam::PatchInjection<CloudType>::timeEnd() const
123     return this->SOI_ + duration_;
127 template<class CloudType>
128 Foam::label Foam::PatchInjection<CloudType>::parcelsToInject
130     const scalar time0,
131     const scalar time1
134     if ((time0 >= 0.0) && (time0 < duration_))
135     {
136         scalar nParcels =fraction_*(time1 - time0)*parcelsPerSecond_;
138         cachedRandom& rnd = this->owner().rndGen();
140         label nParcelsToInject = floor(nParcels);
142         // Inject an additional parcel with a probability based on the
143         // remainder after the floor function
144         if
145         (
146             nParcelsToInject > 0
147          && (
148                nParcels - scalar(nParcelsToInject)
149              > rnd.position(scalar(0), scalar(1))
150             )
151         )
152         {
153             ++nParcelsToInject;
154         }
156         return nParcelsToInject;
157     }
158     else
159     {
160         return 0;
161     }
165 template<class CloudType>
166 Foam::scalar Foam::PatchInjection<CloudType>::volumeToInject
168     const scalar time0,
169     const scalar time1
172     if ((time0 >= 0.0) && (time0 < duration_))
173     {
174         return fraction_*flowRateProfile_().integrate(time0, time1);
175     }
176     else
177     {
178         return 0.0;
179     }
183 template<class CloudType>
184 void Foam::PatchInjection<CloudType>::setPositionAndCell
186     const label,
187     const label,
188     const scalar,
189     vector& position,
190     label& cellOwner,
191     label& tetFaceI,
192     label& tetPtI
195     if (cellOwners_.size() > 0)
196     {
197         cachedRandom& rnd = this->owner().rndGen();
199         label cellI = rnd.position<label>(0, cellOwners_.size() - 1);
201         cellOwner = cellOwners_[cellI];
203         // The position is between the face and cell centre, which could be
204         // in any tet of the decomposed cell, so arbitrarily choose the first
205         // face of the cell as the tetFace and the first point after the base
206         // point on the face as the tetPt.  The tracking will pick the cell
207         // consistent with the motion in the firsttracking step.
208         tetFaceI = this->owner().mesh().cells()[cellOwner][0];
209         tetPtI = 1;
211         // position perturbed between cell and patch face centres
212         const vector& pc = this->owner().mesh().C()[cellOwner];
213         const vector& pf =
214             this->owner().mesh().Cf().boundaryField()[patchId_][cellI];
216         const scalar a = rnd.sample01<scalar>();
217         const vector d = pf - pc;
218         position = pc + 0.5*a*d;
219     }
220     else
221     {
222         cellOwner = -1;
223         tetFaceI = -1;
224         tetPtI = -1;
225         // dummy position
226         position = pTraits<vector>::max;
227     }
231 template<class CloudType>
232 void Foam::PatchInjection<CloudType>::setProperties
234     const label,
235     const label,
236     const scalar,
237     typename CloudType::parcelType& parcel
240     // set particle velocity
241     parcel.U() = U0_;
243     // set particle diameter
244     parcel.d() = sizeDistribution_->sample();
248 template<class CloudType>
249 bool Foam::PatchInjection<CloudType>::fullyDescribed() const
251     return false;
255 template<class CloudType>
256 bool Foam::PatchInjection<CloudType>::validInjection(const label)
258     return true;
262 // ************************************************************************* //