ConeInjection.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2011-2012 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "ConeInjection.H"
27 #include "TimeDataEntry.H"
28 #include "mathematicalConstants.H"
29 #include "unitConversion.H"
30 
31 using namespace Foam::constant::mathematical;
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class CloudType>
37 (
38  const dictionary& dict,
39  CloudType& owner,
40  const word& modelName
41 )
42 :
43  InjectionModel<CloudType>(dict, owner, modelName, typeName),
44  positionAxis_(this->coeffDict().lookup("positionAxis")),
45  injectorCells_(positionAxis_.size()),
46  injectorTetFaces_(positionAxis_.size()),
47  injectorTetPts_(positionAxis_.size()),
48  duration_(readScalar(this->coeffDict().lookup("duration"))),
49  parcelsPerInjector_
50  (
51  readScalar(this->coeffDict().lookup("parcelsPerInjector"))
52  ),
53  flowRateProfile_
54  (
56  (
57  owner.db().time(),
58  "flowRateProfile",
59  this->coeffDict()
60  )
61  ),
62  Umag_
63  (
65  (
66  owner.db().time(),
67  "Umag",
68  this->coeffDict()
69  )
70  ),
71  thetaInner_
72  (
74  (
75  owner.db().time(),
76  "thetaInner",
77  this->coeffDict()
78  )
79  ),
80  thetaOuter_
81  (
83  (
84  owner.db().time(),
85  "thetaOuter",
86  this->coeffDict()
87  )
88  ),
89  sizeDistribution_
90  (
92  (
93  this->coeffDict().subDict("sizeDistribution"), owner.rndGen()
94  )
95  ),
96  nInjected_(this->parcelsAddedTotal()),
97  tanVec1_(positionAxis_.size()),
98  tanVec2_(positionAxis_.size())
99 {
100  duration_ = owner.db().time().userTimeToTime(duration_);
101 
102  // Normalise direction vector and determine direction vectors
103  // tangential to injector axis direction
104  forAll(positionAxis_, i)
105  {
106  vector& axis = positionAxis_[i].second();
107 
108  axis /= mag(axis);
109 
110  vector tangent = vector::zero;
111  scalar magTangent = 0.0;
112 
113  cachedRandom& rnd = this->owner().rndGen();
114  while (magTangent < SMALL)
115  {
116  vector v = rnd.sample01<vector>();
117 
118  tangent = v - (v & axis)*axis;
119  magTangent = mag(tangent);
120  }
121 
122  tanVec1_[i] = tangent/magTangent;
123  tanVec2_[i] = axis^tanVec1_[i];
124  }
125 
126  // Set total volume to inject
127  this->volumeTotal_ = flowRateProfile_.integrate(0.0, duration_);
128 
129  updateMesh();
130 }
131 
132 
133 template<class CloudType>
135 (
136  const ConeInjection<CloudType>& im
137 )
138 :
140  positionAxis_(im.positionAxis_),
141  injectorCells_(im.injectorCells_),
142  injectorTetFaces_(im.injectorTetFaces_),
143  injectorTetPts_(im.injectorTetPts_),
144  duration_(im.duration_),
145  parcelsPerInjector_(im.parcelsPerInjector_),
146  flowRateProfile_(im.flowRateProfile_),
147  Umag_(im.Umag_),
148  thetaInner_(im.thetaInner_),
149  thetaOuter_(im.thetaOuter_),
150  sizeDistribution_(im.sizeDistribution_().clone().ptr()),
151  nInjected_(im.nInjected_),
152  tanVec1_(im.tanVec1_),
153  tanVec2_(im.tanVec2_)
154 {}
155 
156 
157 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
158 
159 template<class CloudType>
161 {}
162 
163 
164 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
165 
166 template<class CloudType>
168 {
169  // Set/cache the injector cells
170  forAll(positionAxis_, i)
171  {
172  this->findCellAtPosition
173  (
174  injectorCells_[i],
175  injectorTetFaces_[i],
176  injectorTetPts_[i],
177  positionAxis_[i].first()
178  );
179  }
180 }
181 
182 
183 template<class CloudType>
185 {
186  return this->SOI_ + duration_;
187 }
188 
189 
190 template<class CloudType>
192 (
193  const scalar time0,
194  const scalar time1
195 )
196 {
197  if ((time0 >= 0.0) && (time0 < duration_))
198  {
199  const scalar targetVolume = flowRateProfile_.integrate(0, time1);
200 
201  const label targetParcels =
202  parcelsPerInjector_*targetVolume/this->volumeTotal_;
203 
204  const label nToInject = targetParcels - nInjected_;
205 
206  nInjected_ += nToInject;
207 
208  return positionAxis_.size()*nToInject;
209  }
210  else
211  {
212  return 0;
213  }
214 }
215 
216 
217 template<class CloudType>
219 (
220  const scalar time0,
221  const scalar time1
222 )
223 {
224  if ((time0 >= 0.0) && (time0 < duration_))
225  {
226  return flowRateProfile_.integrate(time0, time1);
227  }
228  else
229  {
230  return 0.0;
231  }
232 }
233 
234 
235 template<class CloudType>
237 (
238  const label parcelI,
239  const label,
240  const scalar,
241  vector& position,
242  label& cellOwner,
243  label& tetFaceI,
244  label& tetPtI
245 )
246 {
247  const label i = parcelI % positionAxis_.size();
248 
249  position = positionAxis_[i].first();
250  cellOwner = injectorCells_[i];
251  tetFaceI = injectorTetFaces_[i];
252  tetPtI = injectorTetPts_[i];
253 }
254 
255 
256 template<class CloudType>
258 (
259  const label parcelI,
260  const label,
261  const scalar time,
262  typename CloudType::parcelType& parcel
263 )
264 {
265  cachedRandom& rnd = this->owner().rndGen();
266 
267  // set particle velocity
268  const label i = parcelI % positionAxis_.size();
269 
270  scalar t = time - this->SOI_;
271  scalar ti = thetaInner_.value(t);
272  scalar to = thetaOuter_.value(t);
273  scalar coneAngle = degToRad(rnd.position<scalar>(ti, to));
274 
275  scalar alpha = sin(coneAngle);
276  scalar dcorr = cos(coneAngle);
277  scalar beta = twoPi*rnd.sample01<scalar>();
278 
279  vector normal = alpha*(tanVec1_[i]*cos(beta) + tanVec2_[i]*sin(beta));
280  vector dirVec = dcorr*positionAxis_[i].second();
281  dirVec += normal;
282  dirVec /= mag(dirVec);
283 
284  parcel.U() = Umag_.value(t)*dirVec;
285 
286  // set particle diameter
287  parcel.d() = sizeDistribution_().sample();
288 }
289 
290 
291 template<class CloudType>
293 {
294  return false;
295 }
296 
297 
298 template<class CloudType>
300 {
301  return true;
302 }
303 
304 
305 // ************************************************************************* //
virtual bool validInjection(const label parcelI)
Return flag to identify whether or not injection of parcelI is.
virtual void setPositionAndCell(const label parcelI, const label nParcels, const scalar time, vector &position, label &cellOwner, label &tetFaceI, label &tetPtI)
Set the injection position and owner cell, tetFace and tetPt.
dimensioned< scalar > mag(const dimensioned< Type > &)
virtual void updateMesh()
Set injector locations when mesh is updated.
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
virtual bool fullyDescribed() const
Flag to identify whether model fully describes the parcel.
A class for handling words, derived from string.
Definition: word.H:59
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
ParcelType parcelType
Type of parcel the cloud was instantiated for.
Definition: DSMCCloud.H:217
Multi-point cone injection model.
Definition: ConeInjection.H:59
dictionary dict
stressControl lookup("compactNormalStress") >> compactNormalStress
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
#define forAll(list, i)
Definition: UList.H:421
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
Templated injection model class.
dimensionedScalar cos(const dimensionedScalar &ds)
virtual void setProperties(const label parcelI, const label nParcels, const scalar time, typename CloudType::parcelType &parcel)
Set the parcel properties.
Unit conversion functions.
static autoPtr< distributionModel > New(const dictionary &dict, cachedRandom &rndGen)
Selector.
scalar timeEnd() const
Return the end-of-injection time.
ConeInjection(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
Definition: ConeInjection.C:37
Random number generator.
Definition: cachedRandom.H:63
virtual ~ConeInjection()
Destructor.
static const Vector zero
Definition: Vector.H:80
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
virtual label parcelsToInject(const scalar time0, const scalar time1)
Number of parcels to introduce relative to SOI.
A normal distribution model.
Type sample01()
Return a sample whose components lie in the range 0-1.
virtual scalar volumeToInject(const scalar time0, const scalar time1)
Volume of parcels to introduce relative to SOI.
Type position(const Type &start, const Type &end)
Return a sample between start and end.
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:68
mathematical constants.
const scalar twoPi(2 *pi)
dimensionedScalar sin(const dimensionedScalar &ds)