LocalInteraction.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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2020 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "LocalInteraction.H"
30 
31 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
32 
33 template<class CloudType>
35 {
37 
38  forAll(nEscape_, patchi)
39  {
40  const word& patchName = patchData_[patchi].patchName();
41 
42  forAll(nEscape_[patchi], injectori)
43  {
44  const word suffix = Foam::name(injectori);
45  this->writeTabbed(os, patchName + "_nEscape_" + suffix);
46  this->writeTabbed(os, patchName + "_massEscape_" + suffix);
47  this->writeTabbed(os, patchName + "_nStick_" + suffix);
48  this->writeTabbed(os, patchName + "_massStick_" + suffix);
49  }
50  }
51 }
52 
53 
54 template<class CloudType>
56 (
57  const dictionary& dict,
59 )
60 :
62  patchData_(cloud.mesh(), this->coeffDict()),
63  nEscape_(patchData_.size()),
64  massEscape_(nEscape_.size()),
65  nStick_(nEscape_.size()),
66  massStick_(nEscape_.size()),
67  writeFields_(this->coeffDict().getOrDefault("writeFields", false)),
68  injIdToIndex_(),
69  massEscapePtr_(nullptr),
70  massStickPtr_(nullptr)
71 {
72  const bool outputByInjectorId
73  = this->coeffDict().getOrDefault("outputByInjectorId", false);
74 
75  if (writeFields_)
76  {
77  Info<< " Interaction fields will be written to "
78  << this->owner().name() << ":massEscape"
79  << " and "
80  << this->owner().name() << ":massStick" << endl;
81 
82  (void)massEscape();
83  (void)massStick();
84  }
85  else
86  {
87  Info<< " Interaction fields will not be written" << endl;
88  }
89 
90  // Determine the number of injectors and the injector mapping
91  label nInjectors = 0;
92  if (outputByInjectorId)
93  {
94  for (const auto& inj : cloud.injectors())
95  {
96  injIdToIndex_.insert(inj.injectorID(), nInjectors++);
97  }
98  }
99 
100  // The normal case, and safety if injector mapping was somehow null.
101  if (!nInjectors)
102  {
103  nInjectors = 1;
104  }
105 
106  // Check that interactions are valid/specified
107  forAll(patchData_, patchi)
108  {
109  const word& interactionTypeName =
110  patchData_[patchi].interactionTypeName();
112  this->wordToInteractionType(interactionTypeName);
113 
115  {
116  const word& patchName = patchData_[patchi].patchName();
118  << "Unknown patch interaction type "
119  << interactionTypeName << " for patch " << patchName
120  << ". Valid selections are:"
122  << nl << exit(FatalError);
123  }
124 
125  nEscape_[patchi].setSize(nInjectors, Zero);
126  massEscape_[patchi].setSize(nInjectors, Zero);
127  nStick_[patchi].setSize(nInjectors, Zero);
128  massStick_[patchi].setSize(nInjectors, Zero);
129  }
130 }
131 
132 
133 template<class CloudType>
135 (
136  const LocalInteraction<CloudType>& pim
137 )
138 :
140  patchData_(pim.patchData_),
141  nEscape_(pim.nEscape_),
142  massEscape_(pim.massEscape_),
143  nStick_(pim.nStick_),
144  massStick_(pim.massStick_),
145  writeFields_(pim.writeFields_),
146  injIdToIndex_(pim.injIdToIndex_),
147  massEscapePtr_(nullptr),
148  massStickPtr_(nullptr)
149 {}
150 
151 
152 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
153 
154 template<class CloudType>
156 {
157  if (!massEscapePtr_)
158  {
159  const fvMesh& mesh = this->owner().mesh();
160 
161  massEscapePtr_.reset
162  (
163  new volScalarField
164  (
165  IOobject
166  (
167  this->owner().name() + ":massEscape",
168  mesh.time().timeName(),
169  mesh,
170  IOobject::READ_IF_PRESENT,
171  IOobject::AUTO_WRITE
172  ),
173  mesh,
175  )
176  );
177  }
178 
179  return *massEscapePtr_;
180 }
181 
182 
183 template<class CloudType>
185 {
186  if (!massStickPtr_)
187  {
188  const fvMesh& mesh = this->owner().mesh();
189 
190  massStickPtr_.reset
191  (
192  new volScalarField
193  (
194  IOobject
195  (
196  this->owner().name() + ":massStick",
197  mesh.time().timeName(),
198  mesh,
199  IOobject::READ_IF_PRESENT,
200  IOobject::AUTO_WRITE
201  ),
202  mesh,
204  )
205  );
206  }
207 
208  return *massStickPtr_;
209 }
210 
211 
212 template<class CloudType>
214 (
215  typename CloudType::parcelType& p,
216  const polyPatch& pp,
217  bool& keepParticle
218 )
219 {
220  const label patchi = patchData_.applyToPatch(pp.index());
221 
222  if (patchi >= 0)
223  {
224  vector& U = p.U();
225 
226  // Location for storing the stats.
227  const label idx =
228  (
229  injIdToIndex_.size()
230  ? injIdToIndex_.lookup(p.typeId(), 0)
231  : 0
232  );
233 
235  this->wordToInteractionType
236  (
237  patchData_[patchi].interactionTypeName()
238  );
239 
240  switch (it)
241  {
243  {
244  return false;
245  }
247  {
248  keepParticle = false;
249  p.active(false);
250  U = Zero;
251 
252  const scalar dm = p.mass()*p.nParticle();
253 
254  nEscape_[patchi][idx]++;
255  massEscape_[patchi][idx] += dm;
256 
257  if (writeFields_)
258  {
259  const label pI = pp.index();
260  const label fI = pp.whichFace(p.face());
261  massEscape().boundaryFieldRef()[pI][fI] += dm;
262  }
263  break;
264  }
266  {
267  keepParticle = true;
268  p.active(false);
269  U = Zero;
270 
271  const scalar dm = p.mass()*p.nParticle();
272 
273  nStick_[patchi][idx]++;
274  massStick_[patchi][idx] += dm;
275 
276  if (writeFields_)
277  {
278  const label pI = pp.index();
279  const label fI = pp.whichFace(p.face());
280  massStick().boundaryFieldRef()[pI][fI] += dm;
281  }
282  break;
283  }
285  {
286  keepParticle = true;
287  p.active(true);
288 
289  vector nw;
290  vector Up;
291 
292  this->owner().patchData(p, pp, nw, Up);
293 
294  // Calculate motion relative to patch velocity
295  U -= Up;
296 
297  if (mag(Up) > 0 && mag(U) < this->Urmax())
298  {
300  << "Particle U the same as patch "
301  << " The particle has been removed" << nl << endl;
302 
303  keepParticle = false;
304  p.active(false);
305  U = Zero;
306  break;
307  }
308 
309  scalar Un = U & nw;
310  vector Ut = U - Un*nw;
311 
312  if (Un > 0)
313  {
314  U -= (1.0 + patchData_[patchi].e())*Un*nw;
315  }
316 
317  U -= patchData_[patchi].mu()*Ut;
318 
319  // Return velocity to global space
320  U += Up;
321 
322  break;
323  }
324  default:
325  {
327  << "Unknown interaction type "
328  << patchData_[patchi].interactionTypeName()
329  << "(" << it << ") for patch "
330  << patchData_[patchi].patchName()
331  << ". Valid selections are:" << this->interactionTypeNames_
332  << endl << abort(FatalError);
333  }
334  }
335 
336  return true;
337  }
338 
339  return false;
340 }
341 
342 
343 template<class CloudType>
345 {
347 
348  // retrieve any stored data
349  labelListList npe0(patchData_.size());
350  scalarListList mpe0(patchData_.size());
351  labelListList nps0(patchData_.size());
352  scalarListList mps0(patchData_.size());
353 
354  forAll(patchData_, patchi)
355  {
356  label lsd = nEscape_[patchi].size();
357  npe0[patchi].setSize(lsd, Zero);
358  mpe0[patchi].setSize(lsd, Zero);
359  nps0[patchi].setSize(lsd, Zero);
360  mps0[patchi].setSize(lsd, Zero);
361  }
362 
363 
364  this->getModelProperty("nEscape", npe0);
365  this->getModelProperty("massEscape", mpe0);
366  this->getModelProperty("nStick", nps0);
367  this->getModelProperty("massStick", mps0);
368 
369  // accumulate current data
370  labelListList npe(nEscape_);
371  forAll(npe, i)
372  {
373  Pstream::listCombineGather(npe[i], plusEqOp<label>());
374  npe[i] = npe[i] + npe0[i];
375  }
376 
377  scalarListList mpe(massEscape_);
378  forAll(mpe, i)
379  {
380  Pstream::listCombineGather(mpe[i], plusEqOp<scalar>());
381  mpe[i] = mpe[i] + mpe0[i];
382  }
383 
384  labelListList nps(nStick_);
385  forAll(nps, i)
386  {
387  Pstream::listCombineGather(nps[i], plusEqOp<label>());
388  nps[i] = nps[i] + nps0[i];
389  }
390 
391  scalarListList mps(massStick_);
392  forAll(nps, i)
393  {
394  Pstream::listCombineGather(mps[i], plusEqOp<scalar>());
395  mps[i] = mps[i] + mps0[i];
396  }
397 
398  if (injIdToIndex_.size())
399  {
400  // Since injIdToIndex_ is a one-to-one mapping (starting at zero),
401  // can simply invert it.
402  labelList indexToInjector(injIdToIndex_.size());
403  forAllConstIters(injIdToIndex_, iter)
404  {
405  indexToInjector[iter.val()] = iter.key();
406  }
407 
408  forAll(patchData_, patchi)
409  {
410  forAll(mpe[patchi], indexi)
411  {
412  const word& patchName = patchData_[patchi].patchName();
413 
414  os << " Parcel fate: patch " << patchName
415  << " (number, mass)" << nl
416  << " - escape (injector " << indexToInjector[indexi]
417  << " ) = " << npe[patchi][indexi]
418  << ", " << mpe[patchi][indexi] << nl
419  << " - stick (injector " << indexToInjector[indexi]
420  << " ) = " << nps[patchi][indexi]
421  << ", " << mps[patchi][indexi] << nl;
422  }
423  }
424  }
425  else
426  {
427  forAll(patchData_, patchi)
428  {
429  const word& patchName = patchData_[patchi].patchName();
430 
431  os << " Parcel fate: patch " << patchName
432  << " (number, mass)" << nl
433  << " - escape = "
434  << npe[patchi][0] << ", " << mpe[patchi][0] << nl
435  << " - stick = "
436  << nps[patchi][0] << ", " << mps[patchi][0] << nl;
437  }
438  }
439 
440  forAll(npe, patchi)
441  {
442  forAll(npe[patchi], injectori)
443  {
444  this->file()
445  << tab << npe[patchi][injectori]
446  << tab << mpe[patchi][injectori]
447  << tab << nps[patchi][injectori]
448  << tab << mps[patchi][injectori];
449  }
450  }
451 
452  this->file() << endl;
453 
454  if (this->writeTime())
455  {
456  this->setModelProperty("nEscape", npe);
457  this->setModelProperty("massEscape", mpe);
458  this->setModelProperty("nStick", nps);
459  this->setModelProperty("massStick", mps);
460 
461  nEscape_ = Zero;
462  massEscape_ = Zero;
463  nStick_ = Zero;
464  massStick_ = Zero;
465  }
466 }
467 
468 
469 // ************************************************************************* //
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::LocalInteraction::writeFileHeader
virtual void writeFileHeader(Ostream &os)
Output file header information.
Definition: LocalInteraction.C:34
Foam::LocalInteraction::LocalInteraction
LocalInteraction(const dictionary &dict, CloudType &owner)
Construct from dictionary.
Definition: LocalInteraction.C:56
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::PatchInteractionModel
Templated patch interaction model class.
Definition: KinematicCloud.H:89
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
LocalInteraction.H
Foam::polyPatch
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:68
Foam::dimensionedScalar
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Definition: dimensionedScalarFwd.H:42
Foam::DSMCCloud
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:71
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::LocalInteraction::info
virtual void info(Ostream &os)
Write patch interaction info to stream.
Definition: LocalInteraction.C:344
os
OBJstream os(runTime.globalPath()/outputName)
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::fvMesh
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:85
Foam::dimMass
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:51
Foam::patchIdentifier::index
label index() const noexcept
The index of this patch in the boundaryMesh.
Definition: patchIdentifier.H:147
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::LocalInteraction
Patch interaction specified on a patch-by-patch basis.
Definition: LocalInteraction.H:54
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::cloud
A cloud is a registry collection of lagrangian particles.
Definition: cloud.H:57
U
U
Definition: pEqn.H:72
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
Foam::polyPatch::whichFace
label whichFace(const label l) const
Return label of face in patch from global face label.
Definition: polyPatch.H:448
Foam::tab
constexpr char tab
Definition: Ostream.H:403
Foam::nl
constexpr char nl
Definition: Ostream.H:404
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::Vector< scalar >
Foam::List< labelList >
Foam::mag
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
Foam::LocalInteraction::correct
virtual bool correct(typename CloudType::parcelType &p, const polyPatch &pp, bool &keepParticle)
Apply velocity correction.
Definition: LocalInteraction.C:214
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::DSMCCloud::parcelType
ParcelType parcelType
Type of parcel the cloud was instantiated for.
Definition: DSMCCloud.H:220
Foam::PatchInteractionModel::interactionType
interactionType
Definition: PatchInteractionModel.H:73
Foam::plusEqOp
Definition: ops.H:72
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::GeometricField< scalar, fvPatchField, volMesh >
Foam::LocalInteraction::massEscape
volScalarField & massEscape()
Return access to the massEscape field.
Definition: LocalInteraction.C:155
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::LocalInteraction::massStick
volScalarField & massStick()
Return access to the massStick field.
Definition: LocalInteraction.C:184