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-2025 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  is.getLine(line);
187 
188  if (NASCore::debug > 1) Info<< "Process: " << line << nl;
189 
190  // ANSA extension(s)
191  if (line.starts_with("$ANSA_NAME"))
192  {
193  // Keep empty elements when splitting
194  const auto args = stringOps::split(line, ';', 0, true);
195 
196  if (args.size() > 4 && line.starts_with("$ANSA_NAME_COMMENT"))
197  {
198  // This type of content
199  // $ANSA_NAME_COMMENT;93000;PSHELL;SLIP;;NO;NO;NO;NO;
200 
201  label groupId = 0;
202 
203  if (readLabel(args[1], groupId) && (args[2] == "PSHELL"))
204  {
205  word groupName = word::validate(args[3]);
206 
207  if (!groupName.empty())
208  {
209  DebugInfo
210  << "PSHELL:" << groupId
211  << " = " << groupName << nl;
212 
213  nameLookup.emplace(groupId, std::move(groupName));
214  }
215  }
216 
217  // Handled (or ignored)
218  continue;
219  }
220  else if (args.size() >= 3 && (args[0] == "$ANSA_NAME"))
221  {
222  // This type of content
223 
224  // line 1: $ANSA_NAME;<int>;PSHELL;~
225  // line 2: $some-part-name
226 
227  label groupId = 0;
228 
229  if (readLabel(args[1], groupId) && (args[2] == "PSHELL"))
230  {
231  // Fetch the next line
232  is.getLine(line);
233  line.removeEnd('\r'); // Possible CR-NL
234 
235  word groupName;
236  if (line.starts_with('$'))
237  {
238  groupName = word::validate(line.substr(1));
239  }
240 
241  if (!groupName.empty())
242  {
243  DebugInfo
244  << "PSHELL:" << groupId
245  << " = " << groupName << nl;
246 
247  nameLookup.emplace(groupId, std::move(groupName));
248  }
249  }
250  }
251 
252  // Drop through in case the second line read was not a comment !
253  }
254  else if (line.starts_with("$HMNAME COMP"))
255  {
256  // HYPERMESH extension
257  // This type of content
258  // $HMNAME COMP 1"partName"
259  // [NB: first entry is fixed record length of 32]
260 
261  auto dquote = line.find('"', 12); // Beyond '$HMNAME COMP'
262 
263  label groupId = 0;
264 
265  if
266  (
267  dquote != std::string::npos
268  && readLabel(line.substr(12, (dquote - 12)), groupId)
269  )
270  {
271  // word::validate automatically removes quotes too
272  word groupName = word::validate(line.substr(dquote));
273 
274  if (!groupName.empty())
275  {
276  DebugInfo
277  << "HMNAME group " << groupId
278  << " => " << groupName << nl;
279 
280  nameLookup.emplace(groupId, std::move(groupName));
281  }
282  }
283 
284  continue; // Handled
285  }
286 
287  if (line.empty())
288  {
289  continue; // Ignore empty
290  }
291  else if (line[0] == '$')
292  {
293  // Retain comment (see notes above about weird formats...)
294  lastComment = line;
295  continue;
296  }
297 
298  // Check if character 72 is continuation
299  if (line.size() > 72 && line[72] == '+')
300  {
301  line.resize(72);
302 
303  while (true)
304  {
305  string buf;
306  is.getLine(buf);
307 
308  if (buf.size() > 72 && buf[72] == '+')
309  {
310  line += buf.substr(8, 64);
311  }
312  else
313  {
314  line += buf.substr(8);
315  break;
316  }
317  }
318  }
319 
320 
321  // Parsing position within current line
322  std::string::size_type linei = 0;
323 
324  // Is free format if line contains a comma
325  const bool freeFormat = line.contains(',');
326 
327  // First word (column 0-8)
328  const word cmd(word::validate(nextNasField(line, linei, 8)));
329 
330  if (cmd == "CTRIA3")
331  {
332  // Fixed format:
333  // 8-16 : element id
334  // 16-24 : group id
335  // 24-32 : vertex
336  // 32-40 : vertex
337  // 40-48 : vertex
338 
339  label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
340  label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
341  const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
342  const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
343  const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
344 
345  // Convert groupId into zoneId
346  const auto iterZone = zoneLookup.cfind(groupId);
347  if (iterZone.good())
348  {
349  if (zoneId != iterZone.val())
350  {
351  // PSHELL types are intermixed
352  sorted = false;
353  }
354  zoneId = iterZone.val();
355  }
356  else
357  {
358  zoneId = dynSizes.size();
359  zoneLookup.insert(groupId, zoneId);
360  dynSizes.push_back(0);
361  // Info<< "zone" << zoneId << " => group " << groupId <<nl;
362  }
363 
364  --elemId; // Convert 1-based -> 0-based
365  dynElemId.push_back(elemId);
366  dynFaces.push_back(Face{a, b, c});
367  dynZones.push_back(zoneId);
368  dynSizes[zoneId]++;
369  }
370  else if (cmd == "CQUAD4")
371  {
372  // Fixed format:
373  // 8-16 : element id
374  // 16-24 : group id
375  // 24-32 : vertex
376  // 32-40 : vertex
377  // 40-48 : vertex
378  // 48-56 : vertex
379 
380  label elemId = readLabel(nextNasField(line, linei, 8, freeFormat));
381  label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
382  const auto a = readLabel(nextNasField(line, linei, 8, freeFormat));
383  const auto b = readLabel(nextNasField(line, linei, 8, freeFormat));
384  const auto c = readLabel(nextNasField(line, linei, 8, freeFormat));
385  const auto d = readLabel(nextNasField(line, linei, 8, freeFormat));
386 
387  // Convert groupId into zoneId
388  const auto iterZone = zoneLookup.cfind(groupId);
389  if (iterZone.good())
390  {
391  if (zoneId != iterZone.val())
392  {
393  // PSHELL types are intermixed
394  sorted = false;
395  }
396  zoneId = iterZone.val();
397  }
398  else
399  {
400  zoneId = dynSizes.size();
401  zoneLookup.insert(groupId, zoneId);
402  dynSizes.push_back(0);
403  // Info<< "zone" << zoneId << " => group " << groupId <<nl;
404  }
405 
406  if constexpr (faceTraits<Face>::isTri())
407  {
408  ignoreElemId = true;
409  dynElemId.clear();
410 
411  dynFaces.push_back(Face{a, b, c});
412  dynFaces.push_back(Face{c, d, a});
413  dynZones.push_back(zoneId);
414  dynZones.push_back(zoneId);
415  dynSizes[zoneId] += 2;
416  }
417  else
418  {
419  --elemId; // Convert 1-based -> 0-based
420 
421  dynElemId.push_back(elemId);
422  dynFaces.push_back(Face{a,b,c,d});
423  dynZones.push_back(zoneId);
424  dynSizes[zoneId]++;
425  }
426  }
427  else if (cmd == "GRID")
428  {
429  // Fixed (short) format:
430  // 8-16 : point id
431  // 16-24 : coordinate system (not supported)
432  // 24-32 : point x coordinate
433  // 32-40 : point y coordinate
434  // 40-48 : point z coordinate
435  // 48-56 : displacement coordinate system (optional, unsupported)
436  // 56-64 : single point constraints (optional, unsupported)
437  // 64-70 : super-element id (optional, unsupported)
438 
439  label index = readLabel(nextNasField(line, linei, 8, freeFormat));
440  (void) nextNasField(line, linei, 8, freeFormat);
441  scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
442  scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
443  scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
444 
445  pointId.push_back(index);
446  dynPoints.emplace_back(x, y, z);
447  }
448  else if (cmd == "GRID*")
449  {
450  // Long format is on two lines with '*' continuation symbol
451  // on start of second line.
452  // Typical line (spaces compacted)
453  // GRID* 126 0 -5.55999875E+02 -5.68730474E+02
454  // * 2.14897901E+02
455 
456  // Cannot be long format and free format at the same time!
457 
458  label index = readLabel(nextNasField(line, linei, 16)); // 8-24
459  (void) nextNasField(line, linei, 16); // 24-40
460  scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
461  scalar y = readNasScalar(nextNasField(line, linei, 16)); // 56-72
462 
463  linei = 0; // restart at index 0
464  is.getLine(line);
465  if (line[0] != '*')
466  {
468  << "Expected continuation symbol '*' when reading GRID*"
469  << " (double precision coordinate) format" << nl
470  << "Read:" << line << nl
471  << "File:" << is.name() << " line:" << is.lineNumber()
472  << exit(FatalError);
473  }
474  (void) nextNasField(line, linei, 8); // 0-8
475  scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
476 
477  pointId.push_back(index);
478  dynPoints.emplace_back(x, y, z);
479  }
480  else if (cmd == "PSHELL")
481  {
482  // The last ditch effort to map PSHELL id to a group name.
483  // If ANSA or HMNAME didn't work, it is still possible to
484  // have the 'weird' format where the immediately preceeding
485  // comment contains the information.
486 
487  // Fixed format:
488  // 8-16 : pshell id
489 
490  label groupId = readLabel(nextNasField(line, linei, 8, freeFormat));
491 
492  if (lastComment.size() > 1 && !nameLookup.contains(groupId))
493  {
494  word groupName = word::validate(lastComment.substr(1));
495 
496  if (!groupName.empty())
497  {
498  DebugInfo
499  << "PSHELL:" << groupId
500  << " = " << groupName << nl;
501 
502  nameLookup.emplace(groupId, std::move(groupName));
503  }
504  }
505  }
506  else if (unhandledCmd.insert(cmd))
507  {
508  InfoErr
509  << "Unhandled Nastran command " << line << nl
510  << "File:" << is.name() << " line:" << is.lineNumber()
511  << nl;
512  }
513 
514  // Discard buffered comment (from weird format...)
515  lastComment.clear();
516  }
517 
518 
519  // Info<< "Read faces:" << dynFaces.size()
520  // << " points:" << dynPoints.size()
521  // << endl;
522 
523  if (ignoreElemId)
524  {
525  dynElemId.clear();
526  }
527 
528  // Transfer to normal lists
529  this->storedPoints().transfer(dynPoints);
530 
531  dynFaces.shrink();
532 
533  // Build inverse mapping (NASTRAN pointId -> index)
534  Map<label> mapPointId(invertToMap(pointId));
535  pointId.clearStorage();
536 
537  // Relabel faces
538  // ~~~~~~~~~~~~~
539  for (Face& f : dynFaces)
540  {
541  for (label& vert : f)
542  {
543  vert = mapPointId[vert];
544  }
545  }
546  mapPointId.clear();
547 
548  DebugInfo
549  << "PSHELL names:" << nameLookup << nl;
550 
551  // Create default zone names, or from ANSA/Hypermesh information
552  List<word> names(dynSizes.size());
553  forAllConstIters(zoneLookup, iter)
554  {
555  const label groupId = iter.key();
556  const label zoneId = iter.val();
557 
558  const auto iterName = nameLookup.cfind(groupId);
559  if (iterName.good())
560  {
561  names[zoneId] = iterName.val();
562  }
563  else
564  {
565  names[zoneId] = surfZone::defaultName(zoneId);
566  }
567  }
568 
569  this->sortFacesAndStore(dynFaces, dynZones, dynElemId, sorted);
570 
571  // Add zones (retaining empty ones)
572  this->addZones(dynSizes, names);
573  this->addZonesToFaces(); // for labelledTri
575  return true;
576 }
577 
578 
579 template<class Face>
581 (
582  const fileName& filename,
583  const MeshedSurfaceProxy<Face>& surf,
584  IOstreamOption streamOpt,
585  const dictionary&
586 )
587 {
588  // ASCII only, allow output compression
589  streamOpt.format(IOstreamOption::ASCII);
590 
591  const UList<point>& pointLst = surf.points();
592  const UList<Face>& faceLst = surf.surfFaces();
593  const UList<label>& faceMap = surf.faceMap();
594  const UList<label>& elemIds = surf.faceIds();
595 
596  // for no zones, suppress the group name
597  const surfZoneList zones
598  (
599  surf.surfZones().empty()
600  ? surfaceFormatsCore::oneZone(faceLst, "")
601  : surf.surfZones()
602  );
603 
604  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
605 
606  // Possible to use faceIds?
607  // - cannot if there are negative ids (eg, encoded solid/side)
608  bool useOrigFaceIds =
609  (
610  !useFaceMap
611  && elemIds.size() == faceLst.size()
612  && !ListOps::found(elemIds, lessOp1<label>(0))
613  );
614 
615  // Not possible with on-the-fly face decomposition
616  if (useOrigFaceIds)
617  {
618  for (const auto& f : faceLst)
619  {
620  if (f.size() > 4)
621  {
622  useOrigFaceIds = false;
623  break;
624  }
625  }
626  }
627 
628 
629  OFstream os(filename, streamOpt);
630  if (!os.good())
631  {
633  << "Cannot write file " << filename << nl
634  << exit(FatalError);
635  }
636 
637  // For simplicity, use fieldFormat::FREE throughout
638  fileFormats::NASCore::setPrecision(os, fieldFormat::FREE);
639 
640  os << "CEND" << nl
641  << "TITLE = " << os.name().stem() << nl;
642 
643  // Print zone names as comment
644  forAll(zones, zonei)
645  {
646  // HYPERMESH extension
647  os << "$HMNAME COMP" << setw(20) << (zonei+1)
648  << '"' << zones[zonei].name() << '"' << nl;
649  }
650 
651  // Write vertex coords with 1-based point Id
652  os << "$ GRID POINTS" << nl
653  << "BEGIN BULK" << nl;
654 
655  label pointId = 0;
656  for (const point& pt : pointLst)
657  {
658  os << "GRID" << ','
659  << ++pointId << ','
660  << 0 << ',' // global coordinate system
661  << pt.x() << ',' << pt.y() << ',' << pt.z() << nl;
662  }
663 
664  os << "$ ELEMENTS" << nl;
665 
666  label faceIndex = 0;
667  label zoneIndex = 0;
668  label elemId = 0;
669 
670  for (const surfZone& zone : zones)
671  {
672  for (label nLocal = zone.size(); nLocal--; ++faceIndex)
673  {
674  const label facei =
675  (useFaceMap ? faceMap[faceIndex] : faceIndex);
676 
677  const Face& f = faceLst[facei];
678 
679  if (useOrigFaceIds)
680  {
681  elemId = elemIds[facei];
682  }
683 
684  elemId = writeShell(os, f, elemId, zoneIndex);
685  }
686 
687  ++zoneIndex;
688  }
689 
690  os << "ENDDATA" << nl;
691 }
692 
693 
694 // ************************************************************************* //
reference val() const
Const access to referenced object (value)
Definition: HashTable.H:1201
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:119
A line primitive.
Definition: line.H:52
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.
bool contains(char c) const noexcept
True if string contains given character (cf. C++23)
Definition: string.H:412
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:130
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:652
Output to file stream as an OSstream, normally using std::ofstream for the actual output...
Definition: OFstream.H:71
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:229
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)
StringType validate(const std::string &str, const UnaryPredicate &accept, const bool invert=false)
Return a copy of the input string with validated characters.
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components (by proxy) in NAS format.
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:400
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:147
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:582
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
label size() const noexcept
The number of arguments.
Definition: argListI.H:139
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:71
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.
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats...
Definition: MeshedSurface.H:75
Input from file stream as an ISstream, normally using std::ifstream for the actual input...
Definition: IFstream.H:51
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:451
labelList f(nPoints)
virtual bool read(const fileName &filename) override
Read from file.
auto & name
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:599
label lineNumber() const noexcept
Const access to the current stream line number.
Definition: IOstream.H:409
static bool split(const std::string &line, std::string &key, std::string &val)
Definition: cpuInfo.C:32
bool starts_with(char c) const
True if string starts with given character (cf. C++20)
Definition: string.H:436
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
surface1 clear()
const dimensionedScalar c
Speed of light in a vacuum.
DynamicList< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicList.
Definition: DynamicList.H:565
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:458
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
auto & names
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
Foam::argList args(argc, argv)
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition: ListOps.C:105
bool found
streamFormat format() const noexcept
Get the current stream format.
bool removeEnd(const std::string &text)
Remove the given text from the end of the string.
Definition: string.C:222
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28