meshingSurfaceList.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "meshingSurfaceList.H"
27 
28 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29 
30 void Foam::meshingSurfaceList::mergeBoundingBoxes
31 (
32  boundBox& bb1,
33  const boundBox& bb2
34 )
35 {
36  if (bb1.volume() == 0)
37  {
38  bb1 = bb2;
39  return;
40  }
41 
42  point& min1 = bb1.min();
43  point& max1 = bb1.max();
44  const point& min2 = bb2.min();
45  const point& max2 = bb2.max();
46 
47  forAll(min1, i)
48  {
49  min1[i] = Foam::min(min1[i], min2[i]);
50  max1[i] = Foam::max(max1[i], max2[i]);
51  }
52 }
53 
54 
55 void Foam::meshingSurfaceList::swapExternalIndexZero(const label index)
56 {
57  if (index == 0)
58  {
59  return;
60  }
61 
62  autoPtr<meshingSurface> s0Ptr(set(0, nullptr));
63  autoPtr<meshingSurface> sIndexPtr(set(index, nullptr));
64 
65  set(index, s0Ptr.ptr());
66  set(0, sIndexPtr.ptr());
67 }
68 
69 
70 bool Foam::meshingSurfaceList::regionsValid
71 (
72  const wordList& specifiedRegions,
73  const wordList& regions,
74  const word& opt
75 )
76 {
77  if (specifiedRegions.empty())
78  {
79  return false;
80  }
81 
82  forAll(specifiedRegions, s)
83  {
84  bool match(false);
85 
86  forAll(regions, r)
87  {
88  match = (specifiedRegions[s] == regions[r]) || match;
89  if (match)
90  {
91  break;
92  }
93  }
94 
95  if (!match)
96  {
98  << "Region '"<< specifiedRegions[s]
99  << "' specified with the '" << opt
100  << "' option" << nl
101  << "does not match any regions in the external surface"
102  << exit(FatalError);
103  }
104  }
105 
106  return true;
107 }
108 
109 
110 void Foam::meshingSurfaceList::setSurfaceTypes
111 (
112  const List<word>& surfaces,
113  const surfaceType& type
114 )
115 {
116  forAll(surfaces, i)
117  {
118  const word surface = fileName(surfaces[i]).lessExt();
119  const word surfaceType = meshingSurface::surfaceTypeNames[type];
120  bool match = false;
121 
122  // Check if the surface name matches a surface name
123  forAll(*this, surfi)
124  {
125  if (surface == operator[](surfi).name())
126  {
127  // For cellZone and rotatingZone, ensure surface is closed
128  if
129  (
130  !operator[](surfi).closed()
131  && (
132  type == surfaceType::rotatingZone
133  || type == surfaceType::cellZone
134  )
135  )
136  {
138  << "Argument to '-" << surfaceType
139  << "' contains the " << surfaceType << " '"
140  << surface << "'" << nl
141  << "which is not a closed surface."
142  << exit(FatalError);
143  }
144 
145  operator[](surfi).type() = type;
146  match = true;
147  break;
148  }
149  }
150 
151  if (!match)
152  {
154  << "Argument to '-" << surfaceType
155  << "' contains the " << surfaceType << " '"
156  << surface << "'" << nl
157  << "which does not correspond to any surfaces."
158  << exit(FatalError);
159  }
160  }
161 }
162 
163 
164 void Foam::meshingSurfaceList::setRotatingZoneBounds()
165 {
166  forAll(*this, surfi)
167  {
168  if (operator[](surfi).type() == surfaceType::rotatingZone)
169  {
170  mergeBoundingBoxes(rzbb_, operator[](surfi).bb());
171  }
172  }
173 }
174 
175 
176 void Foam::meshingSurfaceList::identifyCellZones()
177 {
178  forAll(*this, i)
179  {
180  if
181  (
182  operator[](i).type() == surfaceType::external
183  || operator[](i).type() == surfaceType::rotatingZone
184  || operator[](i).nParts() != 1
185  || !operator[](i).closed()
186  )
187  {
188  continue;
189  }
190 
191  forAll(*this, j)
192  {
193  if (i == j)
194  {
195  continue;
196  }
197 
198  if (operator[](i).bb().contains(operator[](j).bb()))
199  {
200  operator[](i).type() = surfaceType::cellZone;
201  continue;
202  }
203  }
204  }
205 }
206 
207 
208 void Foam::meshingSurfaceList::reportWordList(const wordList& wl)
209 {
210  forAll(wl, i)
211  {
212  Info<< wl[i];
213  if (i != wl.size() - 1)
214  {
215  Info<< ", ";
216  }
217  }
218 
219  Info<< endl;
220 }
221 
222 
223 void Foam::meshingSurfaceList::reportSurfaces()
224 {
225  Info<< "Case contains the following surface geometry files:"
226  << endl;
227 
228  forAll(*this, i)
229  {
230  Info<< "+ " << operator[](i).name() << nl
231  << " + File: " << operator[](i).file() << nl
232  << " + Bounding box: " << operator[](i).bb() << nl
233  << " + " << (operator[](i).closed() ? "Closed" : "Open")
234  << " surface" << endl;
235 
236  switch (operator[](i).type())
237  {
238  case surfaceType::external:
239  {
240  Info << " + External boundary surface" << endl;
241 
242  if (!operator[](i).inletRegions().empty())
243  {
244  Info<< " + Inlet regions: ";
245  reportWordList(operator[](i).inletRegions());
246  }
247 
248  if (!operator[](i).outletRegions().empty())
249  {
250  Info << " + Outlet regions: ";
251  reportWordList(operator[](i).outletRegions());
252  }
253 
254  break;
255  }
256 
257  case surfaceType::wall:
258  {
259  Info << " + Wall boundary surface" << endl;
260  break;
261  }
262 
263  case surfaceType::cellZone:
264  {
265  Info << " + Cell zone surface" << endl;
266  break;
267  }
268 
269  case surfaceType::rotatingZone:
270  {
271  Info << " + Rotating zone surface" << endl;
272  break;
273  }
274 
275  case surfaceType::baffle:
276  {
277  Info << " + Baffle wall surface" << endl;
278  break;
279  }
280  }
281  }
282 
283  Info<< endl;
284 }
285 
286 
287 void Foam::meshingSurfaceList::setBounds(const boundBox& bb)
288 {
289  if (bb.contains(bb_))
290  {
291  Info<< "Specifed bounding box contains the overall bounding box"
292  << endl;
293  }
294  else
295  {
297  << "Specified bounding box does not contain the overall "
298  << "bounding box"
299  << endl;
300  }
301 
302  if (bb.mag() > 1.5*bb_.mag())
303  {
304  Info<< "Specified bounding box is > (1.5 * overall "
305  << "bounding box)" << nl
306  << "**Assuming this is an external flow**"
307  << endl;
308 
309  operator[](0).type() = surfaceType::wall;
310  }
311 
312  Info<< endl;
313 
314  bb_ = bb;
315 }
316 
317 
318 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
319 
321 (
322  const Time& time,
323  const fileNameList& surfaces,
324  const wordList& cellZones,
325  const wordList& rotatingZones,
326  const wordList& baffles,
327  const boundBox& bb,
328  const wordList& specifiedInletRegions,
329  const wordList& specifiedOutletRegions
330 )
331 :
332  PtrList<meshingSurface>(),
333  bb_(),
334  rzbb_()
335 {
336  // Load all the surfaces and construct the bounding box
337  forAll(surfaces, i)
338  {
339  append(new meshingSurface(surfaces[i], time));
340 
341  mergeBoundingBoxes(bb_, last().bb());
342  }
343 
344  label externalID = 0;
345  forAll(surfaces, i)
346  {
347  // Test for external surface inflates the bounding box by a small factor
348  // to account for imprecise surface geometry files
349  boundBox bbInflate = operator[](i).bb();
350  bbInflate.inflate(1e-4);
351 
352  if
353  (
354  operator[](i).closed()
355  && operator[](i).nParts() == 1
356  && bbInflate.contains(bb_)
357  )
358  {
359  externalID = i;
360  operator[](i).type() = surfaceType::external;
361 
362  // Override any inlet and outlet regions on external boundary
363  // specified by the '-inletRegions' and '-outletRegions' options
364  const wordList& regions = operator[](i).regions();
365 
366  wordList& inletRegions = operator[](i).inletRegions();
367  if (regionsValid(specifiedInletRegions, regions, "-inletRegions"))
368  {
369  inletRegions = specifiedInletRegions;
370  }
371 
372  wordList& outletRegions = operator[](i).outletRegions();
373  if (regionsValid(specifiedOutletRegions, regions, "-outletRegions"))
374  {
375  outletRegions = specifiedOutletRegions;
376  }
377 
378  // If inletRegions and outletRegions are both empty, set "template"
379  // names
380  if (inletRegions.empty() && outletRegions.empty())
381  {
382  inletRegions.append("<inletRegion>");
383  outletRegions.append("<outletRegion>");
384  }
385  }
386  }
387 
388  swapExternalIndexZero(externalID);
389 
390  if (!rotatingZones.empty())
391  {
392  setSurfaceTypes(rotatingZones, surfaceType::rotatingZone);
393  }
394 
395  if (!baffles.empty())
396  {
397  setSurfaceTypes(baffles, surfaceType::baffle);
398  }
399 
400  setRotatingZoneBounds();
401 
402  if (cellZones.empty())
403  {
404  identifyCellZones();
405  }
406  else
407  {
408  setSurfaceTypes(cellZones, surfaceType::cellZone);
409  }
410 
411  reportSurfaces();
412 
413  if (bb.volume() != 0)
414  {
415  setBounds(bb);
416  }
417 }
418 
419 
420 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
421 
423 {}
424 
425 
426 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
static const Form max
Definition: VectorSpace.H:115
static const Form min
Definition: VectorSpace.H:116
~meshingSurfaceList()
Destructor.
meshingSurfaceList(const Time &time, const fileNameList &surfaces, const wordList &cellZones, const wordList &rotatingZones, const wordList &baffles, const boundBox &bb, const wordList &inletRegions, const wordList &outletRegions)
Construct from components.
static const NamedEnum< surfaceType, 5 > surfaceTypeNames
Enumeration names for surfaceTypes.
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
#define WarningInFunction
Report a warning using Foam::Warning.
const dimensionedScalar e
Elementary charge.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< word > wordList
A List of words.
Definition: fileName.H:54
List< fileName > fileNameList
A List of fileNames.
Definition: fileNameList.H:50
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
word name(const bool)
Return a word representation of a bool.
Definition: boolIO.C:39
messageStream Info
vector point
Point is a vector.
Definition: point.H:41
layerAndWeight min(const layerAndWeight &a, const layerAndWeight &b)
layerAndWeight max(const layerAndWeight &a, const layerAndWeight &b)
error FatalError
static const char nl
Definition: Ostream.H:260
fileType type(const fileName &, const bool checkVariants=true, const bool followLink=true)
Return the file type: directory or file.
Definition: POSIX.C:488