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