PDRobstacleLegacyIO.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 "PDRobstacle.H"
29 #include "vector.H"
30 #include "stringOps.H"
31 #include "unitConversion.H"
32 #include <cmath>
33 
34 #define ReportLineInfo(line, file) \
35  if (line >= 0 && !file.empty()) \
36  { \
37  Info<< " Line " << line << " of file '" << file << '\''; \
38  } \
39  Info<< nl;
40 
41 
42 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 
45 (
46  const int groupTypeId,
47  const string& buffer,
48  const label lineNo,
49  const word& inputFile
50 )
51 {
52  // Handling the optional identifier string can be a pain.
53  // Generally can only say that it exists if there are 15 or
54  // more columns.
55  //
56  // Cylinder has 8 normal entries
57  // Cuboid, diagonal beam etc have 14 normal entries
58  // However, reject anything that looks like a slipped numeric
59 
60  double dummy1;
61 
62  string in_ident;
63 
64  const auto columns = stringOps::splitSpace(buffer);
65 
66  for (std::size_t coli = 14; coli < columns.size(); ++coli)
67  {
68  // See if it can parse into a numerical value
69  if (!readDouble(columns[coli].str(), dummy1))
70  {
71  // Not a numeric value. This must be our identifier
72  in_ident = buffer.substr(columns[coli].first - buffer.begin());
73 
74  #ifdef FULLDEBUG
75  Info<< "Identifier: " << in_ident << nl;
76  #endif
77  break;
78  }
79  }
80 
81  // Strip off group number
82  groupId = groupTypeId / 100;
83  typeId = groupTypeId % 100;
84 
85  // This is a safe value
86  orient = vector::X;
87 
88  switch (typeId)
89  {
91  {
92  // 8 Tokens
93  // "%d %lf %lf %lf %lf %lf %d %lf"
94  // USP 13/8/14 Read vbkge in case a negative cyl to punch a circular hole
95 
96  int in_typeId;
97  double in_x, in_y, in_z;
98  double in_len, in_dia;
99  int in_orient;
100  double in_poro;
101 
102  int nread =
103  sscanf
104  (
105  buffer.c_str(),
106  "%d %lf %lf %lf %lf %lf %d %lf",
107  &in_typeId, &in_x, &in_y, &in_z,
108  &in_len, &in_dia, &in_orient,
109  &in_poro
110  );
111 
112  if (nread < 8)
113  {
114  Info<< "Expected 8 items, but read in " << nread;
115  ReportLineInfo(lineNo, inputFile);
116  }
117 
118  identifier = in_ident;
119  pt = point(in_x, in_y, in_z);
120 
121  len() = in_len;
122  dia() = in_dia;
123 
124  orient = vector::X; // Check again later
125 
126  // Read porosity. Convert to blockage.
127  vbkge = 1.0 - in_poro;
128 
129  // Orientation (1,2,3) on input -> (0,1,2)
130  // - sortBias for later position sorting
131  switch (in_orient)
132  {
133  case 1:
134  orient = vector::X;
135  sortBias = len();
136  break;
137  case 2:
138  orient = vector::Y;
139  sortBias = 0.5*dia();
140  break;
141  case 3:
142  orient = vector::Z;
143  sortBias = 0.5*dia();
144  break;
145  default:
146  sortBias = len();
147  Info<< "Unexpected orientation " << in_orient;
148  ReportLineInfo(lineNo, inputFile);
149  break;
150  }
151  }
152  break;
153 
155  {
156  // A diagonal block
157 
158  // 14 columns + identifier
159  // "%d %lf %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %d %lf %s"
160  // vbkge (porosity at this stage) should be 0. Not used (yet)
161 
162  int in_typeId;
163  double in_x, in_y, in_z;
164  double in_len, in_theta;
165  int in_orient;
166  double in_wa, in_wb, in_poro;
167  double col_11, col_12, col_14;
168  int col_13;
169 
170  int nread =
171  sscanf
172  (
173  buffer.c_str(),
174  "%d %lf %lf %lf %lf %lf %d %lf %lf %lf %lf %lf %d %lf",
175  &in_typeId, &in_x, &in_y, &in_z,
176  &in_len, &in_theta, &in_orient,
177  &in_wa, &in_wb, &in_poro,
178  &col_11, &col_12, &col_13, &col_14
179  );
180 
181  if (nread < 14)
182  {
183  Info<< "Expected min 10 items, but read in " << nread;
184  ReportLineInfo(lineNo, inputFile);
185  }
186 
187  identifier = in_ident;
188  pt = point(in_x, in_y, in_z);
189 
190  len() = in_len;
191  dia() = 0;
192  theta() = 0; // Fix later on
193 
194  orient = vector::X; // Check again later
195 
196  wa = in_wa;
197  wb = in_wb;
198 
199  // Degrees on input, limit to range [0, PI]
200  while (in_theta > 180) in_theta -= 180;
201  while (in_theta < 0) in_theta += 180;
202 
203  // Swap axes when theta > PI/2
204  // For 89-90 degrees it becomes -ve, which is picked up
205  // in next section
206  if (in_theta > 89)
207  {
208  in_theta -= 90;
209  // Swap wa <-> wb
210  wa = in_wb;
211  wb = in_wa;
212  }
213 
214  theta() = degToRad(in_theta);
215 
216  // Orientation (1,2,3) on input -> (0,1,2)
217  // - sortBias for later position sorting
218  switch (in_orient)
219  {
220  case 1:
221  orient = vector::X;
222  sortBias = len();
223  break;
224 
225  case 2:
226  orient = vector::Y;
227  sortBias = 0.5*(wa * sin(theta()) + wb * cos(theta()));
228  break;
229 
230  case 3:
231  orient = vector::Z;
232  sortBias = 0.5*(wa * cos(theta()) + wb * sin(theta()));
233  break;
234 
235  default:
236  sortBias = len();
237  Info<< "Unexpected orientation " << in_orient;
238  ReportLineInfo(lineNo, inputFile);
239  break;
240  }
241 
242 
243  // If very nearly aligned with axis, turn it into normal block,
244  // to avoid 1/tan(theta) blowing up
245  if (in_theta < 1)
246  {
247  switch (orient)
248  {
249  case vector::X:
250  span = vector(len(), wa, wb);
251  // Was end center, now lower corner
252  pt.y() = pt.y() - 0.5 * span.y();
253  pt.z() = pt.z() - 0.5 * span.z();
254  break;
255 
256  case vector::Y:
257  span = vector(wb, len(), wa);
258  // Was end center, now lower corner
259  pt.z() = pt.z() - 0.5 * span.z();
260  pt.x() = pt.x() - 0.5 * span.x();
261  break;
262 
263  case vector::Z:
264  span = vector(wa, wb, len());
265  // Was end center, now lower corner
266  pt.x() = pt.x() - 0.5 * span.x();
267  pt.y() = pt.y() - 0.5 * span.y();
268  break;
269  }
270 
272  sortBias = 0;
273  xbkge = ybkge = zbkge = vbkge = 1.0;
274  blowoff_type = 0;
275 
276  Info<< "... changed to type cuboid" << nl;
277  break;
278  }
279  }
280  break;
281 
282  case PDRobstacle::CUBOID_1: // Cuboid "Type 1"
283  case PDRobstacle::LOUVRE_BLOWOFF: // Louvred wall or blow-off panel
284  case PDRobstacle::CUBOID: // Cuboid
285  case PDRobstacle::WALL_BEAM: // Beam against wall (treated here as normal cuboid)
286  case PDRobstacle::GRATING: // Grating
287  case PDRobstacle::RECT_PATCH: // Inlet, outlet, other b.c. (rectangular)
288  {
289  // 14 columns + identifier
290  // "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %d %lf"
291 
292  int in_typeId;
293  double in_x, in_y, in_z;
294  double in_delx, in_dely, in_delz;
295  double in_poro, in_porox, in_poroy, in_poroz;
296  double col_12;
297  int col_13;
298  double in_blowoff_time = 0;
299 
300  int nread =
301  sscanf
302  (
303  buffer.c_str(),
304  "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf %d %lf",
305  &in_typeId, &in_x, &in_y, &in_z,
306  &in_delx, &in_dely, &in_delz,
307  &in_poro, &in_porox, &in_poroy, &in_poroz,
308  &col_12, &col_13, &in_blowoff_time
309  );
310 
311  blowoff_time = scalar(in_blowoff_time);
312 
313  if (nread < 14)
314  {
315  Info<< "Expected 14 items, but read in " << nread;
316  ReportLineInfo(lineNo, inputFile);
317  }
318 
319  identifier = in_ident;
320  pt = point(in_x, in_y, in_z);
321 
322  span = vector(in_delx, in_dely, in_delz);
323 
324  // Read porosity. Convert to blockage.
325  vbkge = 1.0 - in_poro;
326  xbkge = 1.0 - in_porox;
327  ybkge = 1.0 - in_poroy;
328  zbkge = 1.0 - in_poroz;
329 
330  if
331  (
335  )
336  {
337  // Check for invalid input
338 
339  if (vbkge != 1.0 || xbkge != 1.0 || ybkge != 1.0 || zbkge != 1.0)
340  {
341  Info<< "Type " << typeId << " is porous (setting to blockage).";
342  ReportLineInfo(lineNo, inputFile);
343 
344  vbkge = 1;
345  xbkge = 1;
346  ybkge = 1;
347  zbkge = 1;
348  }
350  {
351  // Correct interpretation of column 13
352  inlet_dirn = col_13;
353 
354  if (identifier.empty())
355  {
357  << "RECT_PATCH without a patch name"
358  << exit(FatalError);
359  }
360  }
361  }
362  else if (typeId == PDRobstacle::CUBOID)
363  {
364  }
365  else
366  {
367  if (!equal(cmptProduct(span), 0))
368  {
369  Info<< "Type " << typeId << " has non-zero thickness.";
370  ReportLineInfo(lineNo, inputFile);
371  }
372  }
373 
375  {
376  // Blowoff panel
377  blowoff_press = barToPa(col_12);
378  blowoff_type = col_13;
379 
380  if (blowoff_type == 1)
381  {
382  Info<< "Type " << typeId
383  << ": blowoff-type 1 not yet implemented.";
384  ReportLineInfo(lineNo, inputFile);
385 
386  if (blowoff_time != 0)
387  {
388  Info<< "Type " << typeId << " has blowoff time set,"
389  << " not set to blow off cell-by-cell";
390  ReportLineInfo(lineNo, inputFile);
391  }
392  }
393  else
394  {
395  if
396  (
397  (blowoff_type == 1 || blowoff_type == 2)
398  && (col_12 > 0)
399  )
400  {
401  if (col_12 > maxBlowoffPressure)
402  {
403  Info<< "Blowoff pressure (" << col_12
404  << ") too high for blowoff type "
405  << blowoff_type;
406  ReportLineInfo(lineNo, inputFile);
407  }
408  }
409  else
410  {
411  Info<< "Problem with blowoff parameters";
412  ReportLineInfo(lineNo, inputFile);
413  Info<< "Col12 " << col_12
414  << " Blowoff type " << blowoff_type
415  << ", blowoff pressure " << blowoff_press << nl;
416  }
417  }
418  }
419  else if (typeId == PDRobstacle::WALL_BEAM)
420  {
421  // WALL_BEAM against walls only contribute half to drag
422  // if ((col_12 == 1) || (col_12 == -1)) { against_wall_fac = 0.5; }
423  }
424  else if (typeId == PDRobstacle::GRATING)
425  {
426  if (col_12 > 0)
427  {
428  slat_width = col_12;
429  }
430  else
431  {
432  slat_width = 0;
433  }
434 
435  // Set orientation
436  if (equal(span.x(), 0))
437  {
438  orient = vector::X;
439  }
440  else if (equal(span.y(), 0))
441  {
442  orient = vector::Y;
443  }
444  else
445  {
446  orient = vector::Z;
447  }
448  }
449  }
450  break;
451 
452  case 0: // Group location
453  case PDRobstacle::OLD_INLET: // Ventilation source only
454  return false;
455  break;
456 
457  case PDRobstacle::IGNITION: // Ignition (now ignored. 2019-04)
458  Info<< "Ignition cell type ignored";
459  ReportLineInfo(lineNo, inputFile);
460  return false;
461  break;
462 
463  default:
464  Info<< "Unexpected type " << typeId;
465  ReportLineInfo(lineNo, inputFile);
466  return false;
467  break;
468  }
469 
470  return true;
471 }
472 
473 
474 // ************************************************************************* //
constexpr scalar barToPa(const scalar bar) noexcept
Conversion from bar to Pa.
Cmpt cmptProduct(const VectorSpace< Form, Cmpt, Ncmpts > &vs)
Definition: VectorSpaceI.H:597
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
bool equal(const T &a, const T &b)
Compare two values for equality.
Definition: label.H:164
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
Unit conversion functions.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
scalar sortBias
Bias for position sorting.
Definition: PDRobstacle.H:128
static constexpr int maxBlowoffPressure
The max blowoff pressure [bar].
Definition: PDRobstacle.H:105
dimensionedScalar cos(const dimensionedScalar &ds)
scalar dia() const
Definition: PDRobstacle.H:144
scalar len() const
Definition: PDRobstacle.H:146
label groupId
The group-id.
Definition: PDRobstacle.H:113
Vector< scalar > vector
Definition: vector.H:57
dimensionedScalar sin(const dimensionedScalar &ds)
Foam::SubStrings< StringType > splitSpace(const StringType &str)
Split string into sub-strings at whitespace (TAB, NL, VT, FF, CR, SPC)
vector point
Point is a vector.
Definition: point.H:37
bool setFromLegacy(const int groupTypeId, const string &buffer, const label lineNo=-1, const word &inputFile=word::null)
Set values from single-line, multi-column format.
PtrList< volScalarField > & Y
vector span
The obstacle dimensions (for boxes)
Definition: PDRobstacle.H:140
messageStream Info
Information stream (stdout output on master, null elsewhere)
int typeId
The obstacle type-id.
Definition: PDRobstacle.H:118
direction orient
The x/y/z orientation (0,1,2)
Definition: PDRobstacle.H:123
constexpr scalar degToRad(const scalar deg) noexcept
Conversion from degrees to radians.
point pt
The obstacle location.
Definition: PDRobstacle.H:135
scalar theta() const
Definition: PDRobstacle.H:145