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-2016 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 "TimeFunction1.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 = 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 // ************************************************************************* //
ConeInjection(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
Definition: ConeInjection.C:37
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.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
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
Templated injection model class.
Unit conversion functions.
virtual bool validInjection(const label parcelI)
Return flag to identify whether or not injection of parcelI is.
virtual label parcelsToInject(const scalar time0, const scalar time1)
Number of parcels to introduce relative to SOI.
Random number generator.
Definition: cachedRandom.H:63
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
scalar timeEnd() const
Return the end-of-injection time.
static autoPtr< distributionModel > New(const dictionary &dict, cachedRandom &rndGen)
Selector.
Type sample01()
Return a sample whose components lie in the range 0-1.
stressControl lookup("compactNormalStress") >> compactNormalStress
dimensionedScalar cos(const dimensionedScalar &ds)
mathematical constants.
A class for handling words, derived from string.
Definition: word.H:59
virtual scalar volumeToInject(const scalar time0, const scalar time1)
Volume of parcels to introduce relative to SOI.
static const zero Zero
Definition: zero.H:91
bool readScalar(const char *buf, doubleScalar &s)
Read whole of buf as a scalar. Return true if succesful.
Definition: doubleScalar.H:63
const scalar twoPi(2 *pi)
ParcelType parcelType
Type of parcel the cloud was instantiated for.
Definition: DSMCCloud.H:217
virtual bool fullyDescribed() const
Flag to identify whether model fully describes the parcel.
dimensionedScalar sin(const dimensionedScalar &ds)
virtual ~ConeInjection()
Destructor.
A normal distribution model.
virtual void updateMesh()
Set injector locations when mesh is updated.
dimensionedScalar beta("beta", dimless/dimTemperature, laminarTransport)
dimensioned< scalar > mag(const dimensioned< Type > &)
Type position(const Type &start, const Type &end)
Return a sample between start and end.
const dimensionedScalar alpha
Fine-structure constant: default SI units: [].
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:68
virtual void setProperties(const label parcelI, const label nParcels, const scalar time, typename CloudType::parcelType &parcel)
Set the parcel properties.
Multi-point cone injection model.
Definition: ConeInjection.H:62