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 | Copyright (C) 2011-2017 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 "LocalInteraction.H"
27 
28 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
29 
30 template<class CloudType>
32 (
33  const dictionary& dict,
34  CloudType& cloud
35 )
36 :
37  PatchInteractionModel<CloudType>(dict, cloud, typeName),
38  patchData_(cloud.mesh(), this->coeffDict()),
39  nEscape_(patchData_.size(), 0),
40  massEscape_(patchData_.size(), 0.0),
41  nStick_(patchData_.size(), 0),
42  massStick_(patchData_.size(), 0.0),
43  writeFields_(this->coeffDict().lookupOrDefault("writeFields", false)),
44  massEscapePtr_(nullptr),
45  massStickPtr_(nullptr)
46 {
47  if (writeFields_)
48  {
49  word massEscapeName(this->owner().name() + ":massEscape");
50  word massStickName(this->owner().name() + ":massStick");
51  Info<< " Interaction fields will be written to " << massEscapeName
52  << " and " << massStickName << endl;
53 
54  (void)massEscape();
55  (void)massStick();
56  }
57  else
58  {
59  Info<< " Interaction fields will not be written" << endl;
60  }
61 
62  // check that interactions are valid/specified
63  forAll(patchData_, patchi)
64  {
65  const word& interactionTypeName =
66  patchData_[patchi].interactionTypeName();
68  this->wordToInteractionType(interactionTypeName);
69 
71  {
72  const word& patchName = patchData_[patchi].patchName();
74  << "Unknown patch interaction type "
75  << interactionTypeName << " for patch " << patchName
76  << ". Valid selections are:"
78  << nl << exit(FatalError);
79  }
80  }
81 }
82 
83 
84 template<class CloudType>
86 (
88 )
89 :
91  patchData_(pim.patchData_),
92  nEscape_(pim.nEscape_),
93  massEscape_(pim.massEscape_),
94  nStick_(pim.nStick_),
95  massStick_(pim.massStick_),
96  writeFields_(pim.writeFields_),
97  massEscapePtr_(nullptr),
98  massStickPtr_(nullptr)
99 {}
100 
101 
102 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
103 
104 template<class CloudType>
106 {}
107 
108 
109 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
110 
111 template<class CloudType>
113 {
114  if (!massEscapePtr_.valid())
115  {
116  const fvMesh& mesh = this->owner().mesh();
117 
118  massEscapePtr_.reset
119  (
120  new volScalarField
121  (
122  IOobject
123  (
124  this->owner().name() + ":massEscape",
125  mesh.time().timeName(),
126  mesh,
127  IOobject::READ_IF_PRESENT,
128  IOobject::AUTO_WRITE
129  ),
130  mesh,
131  dimensionedScalar("zero", dimMass, 0.0)
132  )
133  );
134  }
135 
136  return massEscapePtr_();
137 }
138 
139 
140 template<class CloudType>
142 {
143  if (!massStickPtr_.valid())
144  {
145  const fvMesh& mesh = this->owner().mesh();
146 
147  massStickPtr_.reset
148  (
149  new volScalarField
150  (
151  IOobject
152  (
153  this->owner().name() + ":massStick",
154  mesh.time().timeName(),
155  mesh,
156  IOobject::READ_IF_PRESENT,
157  IOobject::AUTO_WRITE
158  ),
159  mesh,
160  dimensionedScalar("zero", dimMass, 0.0)
161  )
162  );
163  }
164 
165  return massStickPtr_();
166 }
167 
168 
169 template<class CloudType>
171 (
172  typename CloudType::parcelType& p,
173  const polyPatch& pp,
174  bool& keepParticle,
175  const scalar trackFraction,
176  const tetIndices& tetIs
177 )
178 {
179  label patchi = patchData_.applyToPatch(pp.index());
180 
181  if (patchi >= 0)
182  {
183  vector& U = p.U();
184  bool& active = p.active();
185 
187  this->wordToInteractionType
188  (
189  patchData_[patchi].interactionTypeName()
190  );
191 
192  switch (it)
193  {
195  {
196  return false;
197  }
199  {
200  scalar dm = p.mass()*p.nParticle();
201 
202  keepParticle = false;
203  active = false;
204  U = Zero;
205  nEscape_[patchi]++;
206  massEscape_[patchi] += dm;
207  if (writeFields_)
208  {
209  label pI = pp.index();
210  label fI = pp.whichFace(p.face());
211  massEscape().boundaryFieldRef()[pI][fI] += dm;
212  }
213  break;
214  }
216  {
217  scalar dm = p.mass()*p.nParticle();
218 
219  keepParticle = true;
220  active = false;
221  U = Zero;
222  nStick_[patchi]++;
223  massStick_[patchi] += dm;
224  if (writeFields_)
225  {
226  label pI = pp.index();
227  label fI = pp.whichFace(p.face());
228  massStick().boundaryFieldRef()[pI][fI] += dm;
229  }
230  break;
231  }
233  {
234  keepParticle = true;
235  active = true;
236 
237  vector nw;
238  vector Up;
239 
240  this->owner().patchData(p, pp, nw, Up);
241 
242  // Calculate motion relative to patch velocity
243  U -= Up;
244 
245  scalar Un = U & nw;
246  vector Ut = U - Un*nw;
247 
248  if (Un > 0)
249  {
250  U -= (1.0 + patchData_[patchi].e())*Un*nw;
251  }
252 
253  U -= patchData_[patchi].mu()*Ut;
254 
255  // Return velocity to global space
256  U += Up;
257 
258  break;
259  }
260  default:
261  {
263  << "Unknown interaction type "
264  << patchData_[patchi].interactionTypeName()
265  << "(" << it << ") for patch "
266  << patchData_[patchi].patchName()
267  << ". Valid selections are:" << this->interactionTypeNames_
268  << endl << abort(FatalError);
269  }
270  }
271 
272  return true;
273  }
274 
275  return false;
276 }
277 
278 
279 template<class CloudType>
281 {
282  // retrieve any stored data
283  labelList npe0(patchData_.size(), 0);
284  this->getModelProperty("nEscape", npe0);
285 
286  scalarList mpe0(patchData_.size(), 0.0);
287  this->getModelProperty("massEscape", mpe0);
288 
289  labelList nps0(patchData_.size(), 0);
290  this->getModelProperty("nStick", nps0);
291 
292  scalarList mps0(patchData_.size(), 0.0);
293  this->getModelProperty("massStick", mps0);
294 
295  // accumulate current data
296  labelList npe(nEscape_);
297  Pstream::listCombineGather(npe, plusEqOp<label>());
298  npe = npe + npe0;
299 
300  scalarList mpe(massEscape_);
301  Pstream::listCombineGather(mpe, plusEqOp<scalar>());
302  mpe = mpe + mpe0;
303 
304  labelList nps(nStick_);
305  Pstream::listCombineGather(nps, plusEqOp<label>());
306  nps = nps + nps0;
307 
308  scalarList mps(massStick_);
309  Pstream::listCombineGather(mps, plusEqOp<scalar>());
310  mps = mps + mps0;
311 
312 
313  forAll(patchData_, i)
314  {
315  os << " Parcel fate (number, mass) : patch "
316  << patchData_[i].patchName() << nl
317  << " - escape = " << npe[i]
318  << ", " << mpe[i] << nl
319  << " - stick = " << nps[i]
320  << ", " << mps[i] << nl;
321  }
322 
323  if (this->writeTime())
324  {
325  this->setModelProperty("nEscape", npe);
326  nEscape_ = 0;
327 
328  this->setModelProperty("massEscape", mpe);
329  massEscape_ = 0.0;
330 
331  this->setModelProperty("nStick", nps);
332  nStick_ = 0;
333 
334  this->setModelProperty("massStick", mps);
335  massStick_ = 0.0;
336  }
337 }
338 
339 
340 // ************************************************************************* //
Patch interaction specified on a patch-by-patch basis.
volScalarField & massEscape()
Return access to the massEscape field.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
U
Definition: pEqn.H:83
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
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
virtual void info(Ostream &os)
Write patch interaction info to stream.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
virtual ~LocalInteraction()
Destructor.
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:644
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:243
Templated patch interaction model class.
dynamicFvMesh & mesh
A class for handling words, derived from string.
Definition: word.H:59
virtual bool correct(typename CloudType::parcelType &p, const polyPatch &pp, bool &keepParticle, const scalar trackFraction, const tetIndices &tetIs)
Apply velocity correction.
LocalInteraction(const dictionary &dict, CloudType &owner)
Construct from dictionary.
static const zero Zero
Definition: zero.H:91
Storage and named access for the indices of a tet which is part of the decomposition of a cell...
Definition: tetIndices.H:81
errorManip< error > abort(error &err)
Definition: errorManip.H:131
ParcelType parcelType
Type of parcel the cloud was instantiated for.
Definition: DSMCCloud.H:218
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:53
static const char nl
Definition: Ostream.H:262
volScalarField & massStick()
Return access to the massStick field.
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
label patchi
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
label index() const
Return the index of this patch in the boundaryMesh.
messageStream Info
const dimensionSet dimMass(1, 0, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:49
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:66
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:92
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:69
label nw
Definition: createFields.H:25
label whichFace(const label l) const
Return label of face in patch from global face label.
Definition: polyPatch.H:377