PDRobstacleIO.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) 2019-2021 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 "PDRsetFields.H"
29 #include "PDRobstacle.H"
30 #include "volumeType.H"
31 
32 using namespace Foam;
33 using namespace Foam::constant;
34 
35 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
36 
38 {
39  this->clear();
40 
41  const word obsType(is);
42  const dictionary dict(is);
43 
44  auto* mfuncPtr = readdictionaryMemberFunctionTable(obsType);
45 
46  if (!mfuncPtr)
47  {
49  (
50  is,
51  "obstacle",
52  obsType,
53  *readdictionaryMemberFunctionTablePtr_
54  ) << exit(FatalIOError);
55  }
56 
57  mfuncPtr(*this, dict);
58 
59  return true;
60 }
61 
62 
64 (
65  const fileName& obsFileDir,
66  const wordList& obsFileNames,
67  const boundBox& meshBb,
68 
70  DynamicList<PDRobstacle>& cylinders
71 )
72 {
73  blocks.clear();
74  cylinders.clear();
75 
76  scalar totVolume = 0;
77  label nOutside = 0;
78  label nProtruding = 0;
79 
80  scalar shift = pars.obs_expand;
81 
82  if (!obsFileNames.empty())
83  {
84  Info<< "Reading obstacle files" << nl;
85  }
86 
87  label maxGroup = -1;
88 
89  for (const word& inputFile : obsFileNames)
90  {
91  Info<< " file: " << inputFile << nl;
92 
93  fileName path = (obsFileDir / inputFile);
94 
95  IFstream is(path);
96  dictionary inputDict(is);
97 
98  const scalar scaleFactor = inputDict.getOrDefault<scalar>("scale", 0);
99 
100  const label verbose = inputDict.getOrDefault<label>("verbose", 0);
101 
102  for (const entry& dEntry : inputDict)
103  {
104  if (!dEntry.isDict())
105  {
106  // ignore non-dictionary entry
107  continue;
108  }
109 
110  const dictionary& dict = dEntry.dict();
111 
112  if (!dict.getOrDefault("enabled", true))
113  {
114  continue;
115  }
116 
117  label obsGroupId = 0;
118  if (dict.readIfPresent("groupId", obsGroupId))
119  {
120  maxGroup = max(maxGroup, obsGroupId);
121  }
122  else
123  {
124  obsGroupId = ++maxGroup;
125  }
126 
127 
128  pointField pts;
129  dict.readIfPresent("locations", pts);
130  if (pts.empty())
131  {
132  pts.resize(1, Zero);
133  }
134 
135  List<PDRobstacle> obsInput;
136  dict.readEntry("obstacles", obsInput);
137 
138  label nCyl = 0; // The number of cylinders vs blocks
139 
140  for (PDRobstacle& obs : obsInput)
141  {
142  obs.groupId = obsGroupId;
143  obs.scale(scaleFactor);
144 
145  if (obs.isCylinder())
146  {
147  ++nCyl;
148  }
149  }
150 
151  const label nBlock = (obsInput.size() - nCyl);
152 
153  blocks.reserve(blocks.size() + nBlock*pts.size());
154  cylinders.reserve(cylinders.size() + nCyl*pts.size());
155 
156  if (verbose)
157  {
158  Info<< "Read " << obsInput.size() << " obstacles ("
159  << nCyl << " cylinders) with "
160  << pts.size() << " locations" << nl;
161 
162  if (verbose > 1)
163  {
164  Info<< "locations " << pts << nl
165  << "obstacles " << obsInput << nl;
166  }
167  }
168 
169  for (const PDRobstacle& scanObs : obsInput)
170  {
171  // Reject anything below minimum width
172  if (scanObs.tooSmall(pars.min_width))
173  {
174  continue;
175  }
176 
177  for (const point& origin : pts)
178  {
179  // A different (very small) shift for each obstacle
180  // so that faces cannot be coincident
181 
182  shift += floatSMALL;
183  const scalar shift2 = shift * 2.0;
184 
185 
186  switch (scanObs.typeId)
187  {
189  {
190  // Make a copy
191  PDRobstacle obs(scanObs);
192 
193  // Offset for the group position
194  obs.pt += origin;
195 
196  // Shift the end outwards so, if exactly on
197  // cell boundary, now overlap cell.
198  // So included in Aw.
199  obs.pt -= point::uniform(shift);
200  obs.len() += shift2;
201  obs.dia() -= floatSMALL;
202 
203 
204  // Trim against the mesh bounds.
205  // Ignore if it doesn't overlap, or bounds are invalid
206  const volumeType vt = obs.trim(meshBb);
207 
208  switch (vt)
209  {
210  case volumeType::OUTSIDE:
211  ++nOutside;
212  continue; // Can ignore the rest
213  break;
214 
215  case volumeType::MIXED:
216  ++nProtruding;
217  break;
218 
219  default:
220  break;
221  }
222 
223  // Later for position sorting
224  switch (obs.orient)
225  {
226  case vector::X:
227  obs.sortBias = obs.len();
228  break;
229  case vector::Y:
230  obs.sortBias = 0.5*obs.dia();
231  break;
232  case vector::Z:
233  obs.sortBias = 0.5*obs.dia();
234  break;
235  }
236 
237  totVolume += obs.volume();
238  cylinders.append(obs);
239 
240  break;
241  }
242 
244  {
245  // Make a copy
246  PDRobstacle obs(scanObs);
247 
248  // Offset for the group position
249  obs.pt += origin;
250 
251  // Shift the end outwards so, if exactly on
252  // cell boundary, now overlap cell.
253  // So included in Aw.
254  obs.pt -= point::uniform(shift);
255  obs.len() += shift2;
256  obs.wa += shift2;
257  obs.wb += shift2;
258 
259  totVolume += obs.volume();
260  cylinders.append(obs);
261 
262  break;
263  }
264 
267  case PDRobstacle::CUBOID:
271  {
272  // Make a copy
273  PDRobstacle obs(scanObs);
274 
275  // Offset for the position of the group
276  obs.pt += origin;
277 
278  if (obs.typeId == PDRobstacle::GRATING)
279  {
280  if (obs.slat_width <= 0)
281  {
283  }
284  }
285 
286  // Shift the end outwards so, if exactly on
287  // cell boundary, now overlap cell.
288  // So included in Aw.
289  obs.pt -= point::uniform(shift);
290  obs.span += point::uniform(shift2);
291 
292 
293  // Trim against the mesh bounds.
294  // Ignore if it doesn't overlap, or bounds are invalid
295  const volumeType vt = obs.trim(meshBb);
296 
297  switch (vt)
298  {
299  case volumeType::OUTSIDE:
300  ++nOutside;
301  continue; // Can ignore the rest
302  break;
303 
304  case volumeType::MIXED:
305  ++nProtruding;
306  break;
307 
308  default:
309  break;
310  }
311 
312  totVolume += obs.volume();
313 
314  blocks.append(obs);
315 
316  break;
317  }
318  }
319  }
320  }
321 
322  // Info<< "Cylinders: " << cylinders << nl;
323  }
324 
325  if (nOutside || nProtruding)
326  {
327  Info<< "Warning: " << nOutside << " obstacles outside domain, "
328  << nProtruding << " obstacles partly outside domain" << nl;
329  }
330  }
331 
332  // #ifdef FULLDEBUG
333  // Info<< blocks << nl << cylinders << nl;
334  // #endif
335 
336 
337  Info<< "Number of obstacles: "
338  << (blocks.size() + cylinders.size()) << " ("
339  << cylinders.size() << " cylinders)" << nl;
340 
341  return totVolume;
342 }
343 
344 
345 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
346 
348 {
349  obs.read(is);
350 
351  return is;
352 }
353 
354 
355 // ************************************************************************* //
Different types of constants.
static bool isCylinder(const label id)
Is obstacle type id cylinder-like?
Definition: PDRobstacleI.H:23
dictionary dict
scalar volume() const
Volume of the obstacle.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
A class for handling file names.
Definition: fileName.H:71
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:420
scalar sortBias
Bias for position sorting.
Definition: PDRobstacle.H:128
scalar def_grating_slat_w
Default slat thickness grating.
Definition: PDRparams.H:138
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:63
An enumeration wrapper for classification of a location as being inside/outside of a volume...
Definition: volumeType.H:55
scalar obs_expand
Definition: PDRparams.H:133
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, IOobjectOption::readOption readOpt=IOobjectOption::MUST_READ) const
Find entry and assign to T val. FatalIOError if it is found and the number of tokens is incorrect...
scalar min_width
Ignore obstacles with second dimension (or diameter) less than this.
Definition: PDRparams.H:121
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
A class for handling words, derived from Foam::string.
Definition: word.H:63
scalar dia() const
Definition: PDRobstacle.H:144
Istream & operator>>(Istream &, directionInfo &)
scalar len() const
Definition: PDRobstacle.H:146
label groupId
The group-id.
Definition: PDRobstacle.H:113
Preparation of fields for PDRFoam.
patchWriters clear()
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicList.H:558
A location outside the volume.
Definition: volumeType.H:66
volumeType trim(const boundBox &bb)
Trim obstacle to ensure it is within the specified bounding box and return the intersection type...
#define floatSMALL
Definition: PDRsetFields.H:48
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Definition: DynamicListI.H:326
A location that is partly inside and outside.
Definition: volumeType.H:67
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
Input from file stream, using an ISstream.
Definition: IFstream.H:49
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:384
PtrList< volScalarField > & Y
vector span
The obstacle dimensions (for boxes)
Definition: PDRobstacle.H:140
Foam::PDRparams pars
Globals for program parameters (ugly hack)
messageStream Info
Information stream (stdout output on master, null elsewhere)
int typeId
The obstacle type-id.
Definition: PDRobstacle.H:118
static scalar readFiles(const fileName &obsFileDir, const wordList &obsFileNames, const boundBox &meshBb, DynamicList< PDRobstacle > &blocks, DynamicList< PDRobstacle > &cylinders)
Read obstacle files and set the lists.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
direction orient
The x/y/z orientation (0,1,2)
Definition: PDRobstacle.H:123
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:615
void scale(const scalar factor)
Scale obstacle dimensions by specified scaling factor.
point pt
The obstacle location.
Definition: PDRobstacle.H:135
Obstacle definitions for PDR.
Definition: PDRobstacle.H:70
List< treeBoundBox > meshBb(1, treeBoundBox(coarseMesh.points()).extend(rndGen, 1e-3))
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
bool read(Istream &is)
Read name / dictionary.
const pointField & pts
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157