NASsurfaceFormat.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) 2011-2015 OpenFOAM Foundation
9  Copyright (C) 2017-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Notes (Reader)
28 
29  Nastran does not directly support any names, but ANSA and Hypermesh
30  have different ways to get around that problem by using/misusing
31  comment lines.
32 
33 Hypermesh extension (last verified approx. 2010)
34 
35  $HMNAME COMP 1"some-part-name"
36 
37 ANSA extension (legacy)
38 
39  line 1: $ANSA_NAME;<int>;<word>;
40  line 2: $some-part-name
41 
42 ANSA extension (19.0.1)
43 
44  line 1: $ANSA_NAME;<int>;PSHELL;~
45  line 2: $some-part-name
46 
47  These seem to appear immediately before the corrsponding PSHELL
48 
49 ANSA extension (23.1.0)
50 
51  $ANSA_NAME_COMMENT;<int>;PSHELL;some-part-name;; ...something trailing...
52 
53  These seem to appear as footer data, but could presumably appear anywhere.
54 
55 Random extension (not sure where this arises)
56 
57  $some-part-name
58  PSHELL 203101 1
59 
60  These seemingly random comments appear immediately before the PSHELL entry.
61 
62 \*---------------------------------------------------------------------------*/
63 
64 #include "NASsurfaceFormat.H"
65 #include "ListOps.H"
66 #include "Fstream.H"
67 #include "IOmanip.H"
68 #include "faceTraits.H"
69 #include "stringOps.H"
70 
71 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
72 
73 template<class Face>
75 (
76  Ostream& os,
77  const Face& f,
78  label elemId,
79  const label groupId
80 )
81 {
82  const label n = f.size();
83 
84  if (n == 3)
85  {
86  os << "CTRIA3" << ','
87  << (++elemId) << ','
88  << (groupId + 1) << ','
89  << (f[0] + 1) << ','
90  << (f[1] + 1) << ','
91  << (f[2] + 1) << nl;
92  }
93  else if (n == 4)
94  {
95  os << "CQUAD4" << ','
96  << (++elemId) << ','
97  << (groupId + 1) << ','
98  << (f[0] + 1) << ','
99  << (f[1] + 1) << ','
100  << (f[2] + 1) << ','
101  << (f[3] + 1) << nl;
102  }
103  else
104  {
105  // simple triangulation about f[0].
106  // better triangulation should have been done before
107  for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
108  {
109  const label fp2 = f.fcIndex(fp1);
110 
111  os << "CTRIA3" << ','
112  << (++elemId) << ','
113  << (groupId + 1) << ','
114  << (f[0] + 1) << ','
115  << (f[fp1] + 1) << ','
116  << (f[fp2] + 1) << nl;
117  }
118  }
119 
120  return elemId;
121 }
122 
123 
124 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
125 
126 template<class Face>
128 (
129  const fileName& filename
130 )
131 {
132  read(filename);
133 }
134 
135 
136 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
137 
138 template<class Face>
140 (
141  const fileName& filename
142 )
143 {
144  // Clear everything
145  this->clear();
146 
147  IFstream is(filename);
148  if (!is.good())
149  {
151  << "Cannot read file " << filename << nl
152  << exit(FatalError);
153  }
154 
155  DynamicList<label> pointId; // Nastran point id (1-based)
156  DynamicList<point> dynPoints;
157 
158  DynamicList<label> dynElemId; // Nastran element id (1-based)
159  DynamicList<Face> dynFaces;
160  DynamicList<label> dynZones;
161  DynamicList<label> dynSizes;
162 
163  Map<label> zoneLookup;
164 
165  // Assume that the groups are not intermixed
166  label zoneId = 0;
167  bool sorted = true;
168 
169  // Element id gets trashed with decompose into a triangle!
170  bool ignoreElemId = false;
171 
172  // Name for face group (limited to PSHELL)
173  Map<word> nameLookup;
174 
175  // A single warning per unrecognized command
176  wordHashSet unhandledCmd;
177 
178  // The line to parse
179  string line;
180 
181  // The last comment line seen (immediately before a 'real' command)
182  string lastComment;
183 
184  while (is.good())
185  {
186  // Parsing position within current line
187  std::string::size_type linei = 0;
188  is.getLine(line);
189 
190  if (NASCore::debug > 1) Info<< "Process: " << line << nl;
191 
192  // ANSA extension(s)
193  if (line.starts_with("$ANSA_NAME"))
194  {
195  // Keep empty elements when splitting
196  const auto args = stringOps::split<std::string>(line, ';', true);
197 
198  if (args.size() > 4 && line.starts_with("$ANSA_NAME_COMMENT"))
199  {
200  // This type of content
201  // $ANSA_NAME_COMMENT;93000;PSHELL;SLIP;;NO;NO;NO;NO;
202 
203  label groupId = 0;
204 
205  if (readLabel(args[1], groupId) && (args[2] == "PSHELL"))
206  {
207  word groupName = word::validate(args[3]);
208 
209  if (!groupName.empty())
210  {
211  DebugInfo
212  << "PSHELL:" << groupId
213  << " = " << groupName << nl;
214 
215  nameLookup.emplace(groupId, std::move(groupName));
216  }
217  }
218 
219  // Handled (or ignored)
220  continue;
221  }
222  else if (args.size() >= 3 && (args[0] == "$ANSA_NAME"))
223  {
224  // This type of content
225 
226  // line 1: $ANSA_NAME;<int>;PSHELL;~
227  // line 2: $some-part-name
228 
229  label groupId = 0;
230 
231  if (readLabel(args[1], groupId) && (args[2] == "PSHELL"))
232  {
233  // Fetch the next line
234  is.getLine(line);
235  line.removeEnd('\r'); // Possible CR-NL
236 
237  word groupName;
238  if (line.starts_with('$'))
239  {
240  groupName = word::validate(line.substr(1));
241  }
242 
243  if (!groupName.empty())
244  {
245  DebugInfo
246  << "PSHELL:" << groupId
247  << " = " << groupName << nl;
248 
249  nameLookup.emplace(groupId, std::move(groupName));
250  }
251  }
252  }
253 
254  // Drop through in case the second line read was not a comment !
255  }
256  else if (line.starts_with("$HMNAME COMP"))
257  {
258  // HYPERMESH extension
259  // This type of content
260  // $HMNAME COMP 1"partName"
261  // [NB: first entry is fixed record length of 32]
262 
263  auto dquote = line.find('"', 12); // Beyond '$HMNAME COMP'
264 
265  label groupId = 0;
266 
267  if
268  (
269  dquote != std::string::npos
270  && readLabel(line.substr(12, (dquote - 12)), groupId)
271  )
272  {
273  // word::validate automatically removes quotes too
274  word groupName = word::validate(line.substr(dquote));
275 
276  if (!groupName.empty())
277  {
278  DebugInfo
279  << "HMNAME group " << groupId
280  << " => " << groupName << nl;
281 
282  nameLookup.emplace(groupId, std::move(groupName));
283  }
284  }
285 
286  continue; // Handled
287  }
288 
289  if (line.empty())
290  {
291  continue; // Ignore empty
292  }
293  else if (line[0] == '$')
294  {
295  // Retain comment (see notes above about weird formats...)
296  lastComment = line;
297  continue;
298  }
299 
300  // Check if character 72 is continuation
301  if (line.size() > 72 && line[72] == '+')
302  {
303  line.resize(72);
304 
305  while (true)
306  {
307  string buf;
308  is.getLine(buf);
309 
310  if (buf.size() > 72 && buf[72] == '+')
311  {
312  line += buf.substr(8, 64);
313  }
314  else
315  {
316  line += buf.substr(8);
317  break;
318  }
319  }
320  }
321 
322  // First word (column 0-8)
323  const word cmd(word::validate(nextNasField(line, linei, 8)));
324 
325  if (cmd == "CTRIA3")
326  {
327  label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
328  label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
329  const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
330  const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
331  const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
332 
333  // Convert groupId into zoneId
334  const auto iterZone = zoneLookup.cfind(groupId);
335  if (iterZone.good())
336  {
337  if (zoneId != iterZone.val())
338  {
339  // PSHELL types are intermixed
340  sorted = false;
341  }
342  zoneId = iterZone.val();
343  }
344  else
345  {
346  zoneId = dynSizes.size();
347  zoneLookup.insert(groupId, zoneId);
348  dynSizes.push_back(0);
349  // Info<< "zone" << zoneId << " => group " << groupId <<nl;
350  }
351 
352  --elemId; // Convert 1-based -> 0-based
353  dynElemId.push_back(elemId);
354  dynFaces.push_back(Face{a, b, c});
355  dynZones.push_back(zoneId);
356  dynSizes[zoneId]++;
357  }
358  else if (cmd == "CQUAD4")
359  {
360  label elemId = readLabel(nextNasField(line, linei, 8)); // 8-16
361  label groupId = readLabel(nextNasField(line, linei, 8)); // 16-24
362  const auto a = readLabel(nextNasField(line, linei, 8)); // 24-32
363  const auto b = readLabel(nextNasField(line, linei, 8)); // 32-40
364  const auto c = readLabel(nextNasField(line, linei, 8)); // 40-48
365  const auto d = readLabel(nextNasField(line, linei, 8)); // 48-56
366 
367  // Convert groupId into zoneId
368  const auto iterZone = zoneLookup.cfind(groupId);
369  if (iterZone.good())
370  {
371  if (zoneId != iterZone.val())
372  {
373  // PSHELL types are intermixed
374  sorted = false;
375  }
376  zoneId = iterZone.val();
377  }
378  else
379  {
380  zoneId = dynSizes.size();
381  zoneLookup.insert(groupId, zoneId);
382  dynSizes.push_back(0);
383  // Info<< "zone" << zoneId << " => group " << groupId <<nl;
384  }
385 
386  if (faceTraits<Face>::isTri())
387  {
388  ignoreElemId = true;
389  dynElemId.clear();
390 
391  dynFaces.push_back(Face{a, b, c});
392  dynFaces.push_back(Face{c, d, a});
393  dynZones.push_back(zoneId);
394  dynZones.push_back(zoneId);
395  dynSizes[zoneId] += 2;
396  }
397  else
398  {
399  --elemId; // Convert 1-based -> 0-based
400 
401  dynElemId.push_back(elemId);
402  dynFaces.push_back(Face{a,b,c,d});
403  dynZones.push_back(zoneId);
404  dynSizes[zoneId]++;
405  }
406  }
407  else if (cmd == "GRID")
408  {
409  label index = readLabel(nextNasField(line, linei, 8)); // 8-16
410  (void) nextNasField(line, linei, 8); // 16-24
411  scalar x = readNasScalar(nextNasField(line, linei, 8)); // 24-32
412  scalar y = readNasScalar(nextNasField(line, linei, 8)); // 32-40
413  scalar z = readNasScalar(nextNasField(line, linei, 8)); // 40-48
414 
415  pointId.push_back(index);
416  dynPoints.emplace_back(x, y, z);
417  }
418  else if (cmd == "GRID*")
419  {
420  // Long format is on two lines with '*' continuation symbol
421  // on start of second line.
422  // Typical line (spaces compacted)
423  // GRID* 126 0 -5.55999875E+02 -5.68730474E+02
424  // * 2.14897901E+02
425 
426  label index = readLabel(nextNasField(line, linei, 16)); // 8-24
427  (void) nextNasField(line, linei, 16); // 24-40
428  scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
429  scalar y = readNasScalar(nextNasField(line, linei, 16)); // 56-72
430 
431  linei = 0; // restart at index 0
432  is.getLine(line);
433  if (line[0] != '*')
434  {
436  << "Expected continuation symbol '*' when reading GRID*"
437  << " (double precision coordinate) format" << nl
438  << "Read:" << line << nl
439  << "File:" << is.name() << " line:" << is.lineNumber()
440  << exit(FatalError);
441  }
442  (void) nextNasField(line, linei, 8); // 0-8
443  scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
444 
445  pointId.push_back(index);
446  dynPoints.emplace_back(x, y, z);
447  }
448  else if (cmd == "PSHELL")
449  {
450  // The last ditch effort to map PSHELL id to a group name.
451  // If ANSA or HMNAME didn't work, it is still possible to
452  // have the 'weird' format where the immediately preceeding
453  // comment contains the information.
454 
455  label groupId = readLabel(nextNasField(line, linei, 8)); // 8-16
456 
457  if (lastComment.size() > 1 && !nameLookup.contains(groupId))
458  {
459  word groupName = word::validate(lastComment.substr(1));
460 
461  if (!groupName.empty())
462  {
463  DebugInfo
464  << "PSHELL:" << groupId
465  << " = " << groupName << nl;
466 
467  nameLookup.emplace(groupId, std::move(groupName));
468  }
469  }
470  }
471  else if (unhandledCmd.insert(cmd))
472  {
473  InfoErr
474  << "Unhandled Nastran command " << line << nl
475  << "File:" << is.name() << " line:" << is.lineNumber()
476  << nl;
477  }
478 
479  // Discard buffered comment (from weird format...)
480  lastComment.clear();
481  }
482 
483 
484  // Info<< "Read faces:" << dynFaces.size()
485  // << " points:" << dynPoints.size()
486  // << endl;
487 
488  if (ignoreElemId)
489  {
490  dynElemId.clear();
491  }
492 
493  // Transfer to normal lists
494  this->storedPoints().transfer(dynPoints);
495 
496  pointId.shrink();
497  dynFaces.shrink();
498 
499  // Build inverse mapping (NASTRAN pointId -> index)
500  Map<label> mapPointId;
501  mapPointId.reserve(pointId.size());
502  for (const label pointi : pointId)
503  {
504  mapPointId.insert(pointi, mapPointId.size());
505  }
506 
507  // Relabel faces
508  // ~~~~~~~~~~~~~
509  for (Face& f : dynFaces)
510  {
511  for (label& vert : f)
512  {
513  vert = mapPointId[vert];
514  }
515  }
516  pointId.clearStorage();
517  mapPointId.clear();
518 
519  DebugInfo
520  << "PSHELL names:" << nameLookup << nl;
521 
522  // Create default zone names, or from ANSA/Hypermesh information
523  List<word> names(dynSizes.size());
524  forAllConstIters(zoneLookup, iter)
525  {
526  const label groupId = iter.key();
527  const label zoneId = iter.val();
528 
529  const auto iterName = nameLookup.cfind(groupId);
530  if (iterName.good())
531  {
532  names[zoneId] = iterName.val();
533  }
534  else
535  {
536  names[zoneId] = surfZone::defaultName(zoneId);
537  }
538  }
539 
540  this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted);
541 
542  // Add zones (retaining empty ones)
543  this->addZones(dynSizes, names);
544  this->addZonesToFaces(); // for labelledTri
546  return true;
547 }
548 
549 
550 template<class Face>
552 (
553  const fileName& filename,
554  const MeshedSurfaceProxy<Face>& surf,
555  IOstreamOption streamOpt,
556  const dictionary&
557 )
558 {
559  // ASCII only, allow output compression
560  streamOpt.format(IOstreamOption::ASCII);
561 
562  const UList<point>& pointLst = surf.points();
563  const UList<Face>& faceLst = surf.surfFaces();
564  const UList<label>& faceMap = surf.faceMap();
565  const UList<label>& elemIds = surf.faceIds();
566 
567  // for no zones, suppress the group name
568  const surfZoneList zones =
569  (
570  surf.surfZones().empty()
571  ? surfaceFormatsCore::oneZone(faceLst, "")
572  : surf.surfZones()
573  );
574 
575  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
576 
577  // Possible to use faceIds?
578  // - cannot if there are negative ids (eg, encoded solid/side)
579  bool useOrigFaceIds =
580  (
581  !useFaceMap
582  && elemIds.size() == faceLst.size()
583  && !ListOps::found(elemIds, lessOp1<label>(0))
584  );
585 
586  // Not possible with on-the-fly face decomposition
587  if (useOrigFaceIds)
588  {
589  for (const auto& f : faceLst)
590  {
591  if (f.size() > 4)
592  {
593  useOrigFaceIds = false;
594  break;
595  }
596  }
597  }
598 
599 
600  OFstream os(filename, streamOpt);
601  if (!os.good())
602  {
604  << "Cannot write file " << filename << nl
605  << exit(FatalError);
606  }
607 
608  // For simplicity, use fieldFormat::FREE throughout
609  fileFormats::NASCore::setPrecision(os, fieldFormat::FREE);
610 
611  os << "CEND" << nl
612  << "TITLE = " << os.name().stem() << nl;
613 
614  // Print zone names as comment
615  forAll(zones, zonei)
616  {
617  // HYPERMESH extension
618  os << "$HMNAME COMP" << setw(20) << (zonei+1)
619  << '"' << zones[zonei].name() << '"' << nl;
620  }
621 
622  // Write vertex coords with 1-based point Id
623  os << "$ GRID POINTS" << nl
624  << "BEGIN BULK" << nl;
625 
626  label pointId = 0;
627  for (const point& pt : pointLst)
628  {
629  os << "GRID" << ','
630  << ++pointId << ','
631  << 0 << ',' // global coordinate system
632  << pt.x() << ',' << pt.y() << ',' << pt.z() << nl;
633  }
634 
635  os << "$ ELEMENTS" << nl;
636 
637  label faceIndex = 0;
638  label zoneIndex = 0;
639  label elemId = 0;
640 
641  for (const surfZone& zone : zones)
642  {
643  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
644  {
645  const label facei =
646  (useFaceMap ? faceMap[faceIndex] : faceIndex);
647 
648  const Face& f = faceLst[facei];
649 
650  if (useOrigFaceIds)
651  {
652  elemId = elemIds[facei];
653  }
654 
655  elemId = writeShell(os, f, elemId, zoneIndex);
656  }
657 
658  ++zoneIndex;
659  }
660 
661  os << "ENDDATA" << nl;
662 }
663 
664 
665 // ************************************************************************* //
reference val() const
Const access to referenced object (value)
Definition: HashTable.H:1185
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
A line primitive.
Definition: line.H:52
List< word > names(const UPtrList< T > &list, const UnaryMatchPredicate &matcher)
List of names generated by calling name() for each list item and filtered for matches.
A class for handling file names.
Definition: fileName.H:72
bool emplace(const label &key, Args &&... args)
Emplace insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:129
Nastran surface reader/writer.
virtual bool read(const fileName &filename)
Read from file.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
messageStream InfoErr
Information stream (stderr output on master, null elsewhere)
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
Output to file stream, using an OSstream.
Definition: OFstream.H:49
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition: label.H:63
A simple container for options an IOstream can normally have.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
const pointField & points() const noexcept
Return const access to the points.
const labelUList & faceMap() const noexcept
Const access to the faceMap, zero-sized when unused.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components by proxy.
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
NASsurfaceFormat(const fileName &filename)
Construct from file name.
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition: HashTableI.H:152
scalar y
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition: ISstream.H:141
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
bool contains(const label &key) const
True if hashed key is contained (found) in table.
Definition: HashTableI.H:72
bool useFaceMap() const noexcept
Can/should use faceMap?
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition: HashTableI.H:113
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
A class for handling words, derived from Foam::string.
Definition: word.H:63
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
Definition: DynamicListI.H:538
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
label size() const noexcept
The number of arguments.
Definition: argListI.H:139
patchWriters clear()
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:68
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
#define DebugInfo
Report an information message using Foam::Info.
Istream and Ostream manipulators taking arguments.
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition: ISstreamI.H:69
void read(Istream &, label &val, const dictionary &)
In-place read with dictionary lookup.
int debug
Static debugging option.
DynamicList< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicList.
Definition: DynamicListI.H:447
OBJstream os(runTime.globalPath()/outputName)
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats...
Definition: MeshedSurface.H:75
Input from file stream, using an ISstream.
Definition: IFstream.H:49
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
labelList f(nPoints)
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:555
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:390
vector point
Point is a vector.
Definition: point.H:37
const labelUList & faceIds() const noexcept
Const access to the faceIds, zero-sized when unused.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:281
const dimensionedScalar c
Speed of light in a vacuum.
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
Foam::argList args(argc, argv)
bool found
streamFormat format() const noexcept
Get the current stream format.
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28