Loading...
Searching...
No Matches
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
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 {
282 obs.slat_width = pars.def_grating_slat_w;
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
347Foam::Istream& Foam::operator>>(Istream& is, PDRobstacle& obs)
348{
349 obs.read(is);
350
351 return is;
352}
353
354
355// ************************************************************************* //
Preparation of fields for PDRFoam.
#define floatSMALL
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
void append(const T &val)
Copy append an element to the end of this list.
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
An Istream is an abstract base class for all input systems (streams, files, token lists etc)....
Definition Istream.H:60
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
void resize(const label len)
Adjust allocated size of list.
Definition ListI.H:153
Obstacle definitions for PDR.
Definition PDRobstacle.H:71
static bool isCylinder(const label id)
Is obstacle type id cylinder-like?
scalar volume() const
Volume of the obstacle.
scalar sortBias
Bias for position sorting.
point pt
The obstacle location.
direction orient
The x/y/z orientation (0,1,2).
volumeType trim(const boundBox &bb)
Trim obstacle to ensure it is within the specified bounding box and return the intersection type.
scalar len() const
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.
void clear()
Reset to a zero obstacle.
scalar dia() const
vector span
The obstacle dimensions (for boxes).
bool read(Istream &is)
Read name / dictionary.
int typeId
The obstacle type-id.
void scale(const scalar factor)
Scale obstacle dimensions by specified scaling factor.
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static Form uniform(const Cmpt &s)
Return a VectorSpace with all elements = s.
A bounding box defined in terms of min/max extrema points.
Definition boundBox.H:71
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.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,...
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...
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...
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
A class for handling file names.
Definition fileName.H:75
An enumeration wrapper for classification of a location as being inside/outside of a volume.
Definition volumeType.H:56
@ OUTSIDE
A location outside the volume.
Definition volumeType.H:66
@ MIXED
A location that is partly inside and outside.
Definition volumeType.H:67
A class for handling words, derived from Foam::string.
Definition word.H:66
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:637
Different types of constants.
Namespace for OpenFOAM.
List< word > wordList
List of word.
Definition fileName.H:60
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
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
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
vector point
Point is a vector.
Definition point.H:37
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
vectorField pointField
pointField is a vectorField.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict
List< treeBoundBox > meshBb(1, treeBoundBox(coarseMesh.points()).extend(rndGen, 1e-3))
const pointField & pts