FaceInteraction.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) 2021-2022 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "FaceInteraction.H"
29 #include "faceZoneMesh.H"
30 
31 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
32 
33 template<class CloudType>
36 ({
37  { interactionType::STICK, "stick" },
38  { interactionType::ESCAPE, "escape" },
39  { interactionType::REBOUND, "rebound" },
40 });
41 
42 
43 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
44 
45 template<class CloudType>
47 (
48  const parcelType& p,
49  const label localZonei
50 )
51 {
52  if (!faceZoneBBs_[localZonei].contains(p.position()))
53  {
54  // Quick reject if the particle is not in the face zone bound box
55  return false;
56  }
57 
58  if ((p.d() > dMax_) || (p.d() < dMin_))
59  {
60  return false;
61  }
62 
63  return true;
64 }
65 
66 
67 template<class CloudType>
69 {
70  const fvMesh& mesh = this->owner().mesh();
71  const faceZoneMesh& fzm = mesh.faceZones();
72 
73  Log_<< type() << " output:" << nl;
74 
75  // Retrieve any stored data
76  const label nZones = faceZoneIDs_.size();
77  labelList npe0(nZones, Zero);
78  labelList nps0(nZones, Zero);
79  labelList npr0(nZones, Zero);
80 
81  this->getModelProperty("nEscape", npe0);
82  this->getModelProperty("nStick", nps0);
83  this->getModelProperty("nRebound", npr0);
84 
85  // Accumulate current data
86  labelList npe(returnReduce(nEscapeParticles_, sumOp<labelList>()));
87  labelList nps(returnReduce(nStickParticles_, sumOp<labelList>()));
88  labelList npr(returnReduce(nReboundParticles_, sumOp<labelList>()));
89  forAll(npe, i)
90  {
91  npe[i] = npe[i] + npe0[i];
92  nps[i] = nps[i] + nps0[i];
93  npr[i] = npr[i] + npr0[i];
94  }
95 
96 
97  // Write to log/file
98  forAll(faceZoneIDs_, i)
99  {
100  const label zonei = faceZoneIDs_[i];
101  Log_<< " Zone : " << fzm[zonei].name() << nl
102  << " Escape : " << npe[i] << nl
103  << " Stick : " << nps[i] << nl
104  << " Rebound : " << npr[i] << nl;
105 
106  if (this->writeToFile())
107  {
108  auto& os = filePtrs_[i];
109 
110  writeCurrentTime(os);
111 
112  // Note - writing as scalar for better formatting
113  os << tab << scalar(npe[i])
114  << tab << scalar(nps[i])
115  << tab << scalar(npr[i])
116  << endl;
117  }
118  }
119  Log_<< endl;
120 
121  // Set restart data
122  this->setModelProperty("nEscape", npe);
123  this->setModelProperty("nStick", nps);
124  this->setModelProperty("nRebound", npr);
125 
126  nEscapeParticles_ = Zero;
127  nStickParticles_ = Zero;
128  nReboundParticles_ = Zero;
129 }
130 
131 
132 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
133 
134 template<class CloudType>
136 (
137  const dictionary& dict,
138  CloudType& owner,
139  const word& modelName
140 )
141 :
142  CloudFunctionObject<CloudType>(dict, owner, modelName, typeName),
143  functionObjects::writeFile
144  (
145  owner,
146  this->localPath(),
147  typeName,
148  this->coeffDict()
149  ),
150  faceZoneIDs_(),
151  faceZoneBBs_(),
152  faceZoneInteraction_(),
153  filePtrs_(),
154  nEscapeParticles_(),
155  nStickParticles_(),
156  nReboundParticles_(),
157  dMin_(this->coeffDict().getOrDefault("dMin", -GREAT)),
158  dMax_(this->coeffDict().getOrDefault("dMax", GREAT))
159 {
160  const List<Tuple2<word, word>> nameAndInteraction
161  (
162  this->coeffDict().lookup("faceZones")
163  );
164 
165  filePtrs_.setSize(nameAndInteraction.size());
166 
167  faceZoneBBs_.setSize(nameAndInteraction.size());
168  faceZoneInteraction_.setSize(nameAndInteraction.size());
169 
171  const faceZoneMesh& fzm = owner.mesh().faceZones();
172  const auto& faces = this->owner().mesh().faces();
173  const auto& points = this->owner().mesh().points();
174 
175  label nZone = 0;
176  for (const auto& zoneInfo : nameAndInteraction)
177  {
178  const word& zoneName = zoneInfo.first();
179  const label zonei = fzm.findZoneID(zoneName);
180 
181  if (zonei != -1)
182  {
183  zoneIDs.append(zonei);
184  const faceZone& fz = fzm[zonei];
185 
186  const label nFaces = returnReduce(fz.size(), sumOp<label>());
187  Info<< " " << zoneName << " faces: " << nFaces << nl;
188 
189  // Cache the particle action for this faceZone
190  faceZoneInteraction_[nZone] =
191  interactionTypeNames_[zoneInfo.second()];
192 
193  // Cache faceZone bound box
194  auto& bb = faceZoneBBs_[nZone];
195  for (const label facei : fz)
196  {
197  for (const label fpi : faces[facei])
198  {
199  bb.add(points[fpi]);
200  }
201  }
202  reduce(bb.min(), minOp<point>());
203  reduce(bb.max(), maxOp<point>());
204  bb.inflate(0.05);
205 
206  // Create output file for zone
207  if (this->writeToFile())
208  {
209  filePtrs_.set
210  (
211  nZone,
212  this->newFileAtStartTime(modelName + '_' + zoneName)
213  );
214 
215  writeHeaderValue(filePtrs_[nZone], "Source", type());
216  writeHeaderValue(filePtrs_[nZone], "Face zone", zoneName);
217  writeHeaderValue(filePtrs_[nZone], "Faces", nFaces);
218  writeCommented(filePtrs_[nZone], "Time");
219  writeTabbed(filePtrs_[nZone], "Escape");
220  writeTabbed(filePtrs_[nZone], "Stick");
221  writeTabbed(filePtrs_[nZone], "Rebound");
222  filePtrs_[nZone] << nl;
223  }
224  ++nZone;
225  }
226  else
227  {
229  << "Unable to find faceZone " << zoneName
230  << " - removing" << endl;
231  }
232  }
233  faceZoneIDs_.transfer(zoneIDs);
234 
235  filePtrs_.setSize(nZone);
236  faceZoneBBs_.setSize(nZone);
237  faceZoneInteraction_.setSize(nZone);
238  nEscapeParticles_.setSize(nZone, Zero);
239  nStickParticles_.setSize(nZone, Zero);
240  nReboundParticles_.setSize(nZone, Zero);
241 }
242 
243 
244 template<class CloudType>
246 (
247  const FaceInteraction<CloudType>& pfi
248 )
249 :
251  functionObjects::writeFile(pfi),
252  faceZoneIDs_(pfi.faceZoneIDs_),
253  faceZoneBBs_(pfi.faceZoneBBs_),
254  filePtrs_(),
255  nEscapeParticles_(pfi.nEscapeParticles_),
256  nStickParticles_(pfi.nStickParticles_),
257  nReboundParticles_(pfi.nReboundParticles_),
258  dMin_(pfi.dMin_),
259  dMax_(pfi.dMax_)
260 {}
261 
262 
263 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
264 
265 template<class CloudType>
267 (
268  const parcelType& p,
269  const typename parcelType::trackingData& td
270 )
271 {
272  bool keepParticle = true;
273 
274  const auto& fzm = this->owner().mesh().faceZones();
275 
276  forAll(faceZoneIDs_, i)
277  {
278  if (!processParticle(p, i))
279  {
280  continue;
281  }
282 
283  const label zonei = faceZoneIDs_[i];
284 
285  const label localFacei = fzm[zonei].find(p.face());
286 
287  if (localFacei != -1)
288  {
289  const label facei = fzm[zonei][localFacei];
290 
291  switch (faceZoneInteraction_[i])
292  {
293  case interactionType::ESCAPE:
294  {
295  keepParticle = false;
296  ++nEscapeParticles_[i];
297  break;
298  }
299  case interactionType::STICK:
300  {
301  auto& pRef = const_cast<parcelType&>(p);
302  pRef.active(false);
303  pRef.U() = Zero;
304  ++nStickParticles_[i];
305  break;
306  }
307  case interactionType::REBOUND:
308  {
309  const face& f = this->owner().mesh().faces()[facei];
310  const auto n = f.unitNormal(this->owner().mesh().points());
311 
312  auto& pRef = const_cast<parcelType&>(p);
313  pRef.U() -= 2*n*(pRef.U() & n);
314  ++nReboundParticles_[i];
315  break;
316  }
317  default:
318  {
320  << "Unhandled enumeration "
321  << interactionTypeNames_[faceZoneInteraction_[i]]
322  << abort(FatalError);
323  }
324  }
325  }
326  }
327 
328  return keepParticle;
329 }
330 
331 
332 // ************************************************************************* //
Face zone-based particle interactions.
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
ZoneMesh< faceZone, polyMesh > faceZoneMesh
A ZoneMesh with the type faceZone.
const labelIOList & zoneIDs
Definition: correctPhi.H:59
type
Types of root.
Definition: Roots.H:52
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:326
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
constexpr char tab
The tab &#39;\t&#39; character(0x09)
Definition: Ostream.H:49
Lookup type of boundary radiation properties.
Definition: lookup.H:57
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Perform reduction on a copy, using specified binary operation.
bool processParticle(const parcelType &p, const label localZonei)
Return true if this particle will be assessed.
const CloudType & owner() const
Return const access to the owner cloud.
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
virtual void writeCommented(Ostream &os, const string &str) const
Write a commented string to stream.
Definition: writeFile.C:313
void setSize(const label n)
Alias for resize()
Definition: List.H:316
dynamicFvMesh & mesh
#define Log_
Report write to Foam::Info if the class log switch is true.
const pointField & points
label findZoneID(const word &zoneName) const
Find zone index by name, return -1 if not found.
Definition: ZoneMesh.C:629
A class for handling words, derived from Foam::string.
Definition: word.H:63
virtual bool postFace(const parcelType &p, const typename parcelType::trackingData &td)
Post-face hook.
virtual bool writeToFile() const
Flag to allow writing to file.
Definition: writeFile.C:281
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1103
const dictionary & coeffDict() const
Return const access to the coefficients dictionary.
Definition: subModelBase.C:122
errorManip< error > abort(error &err)
Definition: errorManip.H:139
void writeHeaderValue(Ostream &os, const string &property, const Type &value) const
Write a (commented) header property and value pair.
OBJstream os(runTime.globalPath()/outputName)
const faceZoneMesh & faceZones() const noexcept
Return face zone mesh.
Definition: polyMesh.H:670
virtual autoPtr< OFstream > newFileAtStartTime(const word &name) const
Return autoPtr to a new file using the simulation start time.
Definition: writeFile.C:156
labelList f(nPoints)
const fvMesh & mesh() const
Return reference to the mesh.
Definition: DSMCCloudI.H:37
void write()
Write post-processing info.
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: error.H:64
FaceInteraction(const dictionary &dict, CloudType &owner, const word &modelName)
Construct from dictionary.
void reduce(const List< UPstream::commsStruct > &comms, T &value, const BinaryOp &bop, const int tag, const label comm)
Reduce inplace (cf. MPI Allreduce) using specified communication schedule.
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
A subset of mesh faces organised as a primitive patch.
Definition: faceZone.H:60
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
Templated base class for dsmc cloud.
Definition: DSMCCloud.H:67
Foam::faceZoneMesh.
Templated cloud function object base class.
static const Enum< interactionType > interactionTypeNames_
Names for the interaction types.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
virtual void writeTabbed(Ostream &os, const string &str) const
Write a tabbed string to stream.
Definition: writeFile.C:329