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-------------------------------------------------------------------------------
10License
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
32using namespace Foam;
33using 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
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 {
211 ++nOutside;
212 continue; // Can ignore the rest
213 break;
214
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
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 {
300 ++nOutside;
301 continue; // Can ignore the rest
302 break;
303
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// ************************************************************************* //
Preparation of fields for PDRFoam.
#define floatSMALL
Definition: PDRsetFields.H:54
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:391
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
void reserve(const label len)
Definition: DynamicListI.H:333
Input from file stream, using an ISstream.
Definition: IFstream.H:57
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition: Istream.H:64
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
Obstacle definitions for PDR.
Definition: PDRobstacle.H:75
static bool isCylinder(const label id)
Is obstacle type id cylinder-like?
Definition: PDRobstacleI.H:30
scalar volume() const
Volume of the obstacle.
scalar sortBias
Bias for position sorting.
Definition: PDRobstacle.H:119
point pt
The obstacle location.
Definition: PDRobstacle.H:123
direction orient
The x/y/z orientation (0,1,2)
Definition: PDRobstacle.H:116
volumeType trim(const boundBox &bb)
scalar len() const
Definition: PDRobstacle.H:132
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.
label groupId
The group-id.
Definition: PDRobstacle.H:110
void clear()
Reset to a zero obstacle.
scalar dia() const
Definition: PDRobstacle.H:130
vector span
The obstacle dimensions (for boxes)
Definition: PDRobstacle.H:126
bool read(Istream &is)
Read name / dictionary.
int typeId
The obstacle type-id.
Definition: PDRobstacle.H:113
void scale(const scalar factor)
Scale obstacle dimensions by specified scaling factor.
scalar def_grating_slat_w
Default slat thickness grating.
Definition: PDRparams.H:124
scalar obs_expand
Definition: PDRparams.H:121
scalar min_width
Ignore obstacles with second dimension (or diameter) less than this.
Definition: PDRparams.H:113
virtual bool read()
Re-read model coefficients if they have changed.
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A bounding box defined in terms of min/max extrema points.
Definition: boundBox.H:64
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Particle-size distribution model wherein random samples are drawn from the doubly-truncated uniform p...
Definition: uniform.H:164
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
A class for handling file names.
Definition: fileName.H:76
An enumeration wrapper for classification of a location as being inside/outside of a volume.
Definition: volumeType.H:61
@ OUTSIDE
A location outside the volume.
Definition: volumeType.H:69
@ MIXED
A location that is partly inside and outside.
Definition: volumeType.H:70
A class for handling words, derived from Foam::string.
Definition: word.H:68
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
#define FatalIOErrorInLookup(ios, lookupTag, lookupName, lookupTable)
Report an error message using Foam::FatalIOError.
Definition: error.H:478
Different types of constants.
Namespace for OpenFOAM.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
messageStream Info
Information stream (stdout output on master, null elsewhere)
Istream & operator>>(Istream &, directionInfo &)
Foam::PDRparams pars
Globals for program parameters (ugly hack)
IOerror FatalIOError
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
List< treeBoundBox > meshBb(1, treeBoundBox(boundBox(coarseMesh.points(), false)).extend(rndGen, 1e-3))
dictionary dict