Loading...
Searching...
No Matches
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-------------------------------------------------------------------------------
11License
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
27Notes (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
33Hypermesh extension (last verified approx. 2010)
34
35 $HMNAME COMP 1"some-part-name"
36
37ANSA extension (legacy)
38
39 line 1: $ANSA_NAME;<int>;<word>;
40 line 2: $some-part-name
41
42ANSA 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
49ANSA 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
55Random 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
73template<class Face>
74inline Foam::label Foam::fileFormats::NASsurfaceFormat<Face>::writeShell
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
126template<class Face>
128(
129 const fileName& filename
130)
131{
132 read(filename);
133}
134
135
136// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
137
138template<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 {
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 {
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 {
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 (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 {
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
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
574
575 return true;
576}
577
578
579template<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// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
scalar y
Various functions to operate on Lists.
label n
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.
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
void clearStorage()
Clear the list and delete storage.
void push_back(const T &val)
Copy append an element to the end of this list.
DynamicList< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicList.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition HashSet.H:229
bool contains(const Key &key) const
True if hashed key is contained (found) in table.
Definition HashTableI.H:72
const_iterator cfind(const Key &key) const
Find and return an const_iterator set at the hashed entry.
Definition HashTableI.H:113
bool insert(const Key &key, const T &obj)
Copy insert a new entry, not overwriting existing entries.
Definition HashTableI.H:152
bool emplace(const Key &key, Args &&... args)
Emplace insert a new entry, not overwriting existing entries.
Definition HashTableI.H:129
void clear()
Remove all entries from table.
Definition HashTable.C:742
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
virtual const fileName & name() const override
Read/write access to the name of the stream.
Definition ISstream.H:147
A simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
@ ASCII
"ascii" (normal default)
label lineNumber() const noexcept
Const access to the current stream line number.
Definition IOstream.H:409
bool good() const noexcept
True if next operation might succeed.
Definition IOstream.H:281
ISstream & getLine(std::string &str, char delim='\n')
Raw, low-level getline (until delimiter) into a string.
Definition ISstreamI.H:69
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
const labelUList & faceIds() const noexcept
Const access to the faceIds, zero-sized when unused.
const labelUList & faceMap() const noexcept
Const access to the faceMap, zero-sized when unused.
const pointField & points() const noexcept
Return const access to the points.
bool useFaceMap() const noexcept
Can/should use faceMap?
pointField & storedPoints()
Non-const access to global points.
virtual void addZones(const UList< surfZone > &, const bool cullEmpty=false)
Add surface zones.
void sortFacesAndStore(DynamicList< Face > &unsortedFaces, DynamicList< label > &zoneIds, DynamicList< label > &elemIds, bool sorted)
Sort faces by zones and store sorted faces.
bool addZonesToFaces()
Propagate zone information on face regions.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
static bool isTri()
Face-type only handles triangles. Not true in general.
Definition faceTraits.H:51
static void setPrecision(Ostream &os, const fieldFormat format)
Set output stream precision and format flags.
Definition NASCore.C:162
@ FREE
Free format (comma-separated fields).
Definition NASCore.H:71
static std::string nextNasField(const std::string &str, std::string::size_type &pos, const std::string::size_type width, const bool free_format=false)
A std::string::substr() variant to handle fixed-format and free-format NASTRAN.
Definition NASCore.C:129
static int debug
Named/registered debug switch: 'nastran.debug'.
Definition NASCore.H:61
static scalar readNasScalar(const std::string &str)
Extract numbers from things like "-2.358-8" (same as "-2.358e-8").
Definition NASCore.C:82
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.
virtual bool read(const fileName &filename) override
Read from file.
NASsurfaceFormat(const fileName &filename)
Construct from file name.
static List< surfZone > oneZone(const Container &container, const word &name="zone0")
Return a surfZone list with a single entry, the size of which corresponds to that of the container.
A class for handling file names.
Definition fileName.H:75
A line primitive.
Definition line.H:180
bool contains(char c) const noexcept
True if string contains given character (cf. C++23).
Definition string.H:412
bool starts_with(char c) const
True if string starts with given character (cf. C++20).
Definition string.H:436
bool removeEnd(const std::string &text)
Remove the given text from the end of the string.
Definition string.C:222
static word defaultName(const label n=-1)
Default zone name: "zone" or "zoneN".
A surface zone on a MeshedSurface.
Definition surfZone.H:55
A class for handling words, derived from Foam::string.
Definition word.H:66
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
Base class for mesh zones.
Definition zone.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
auto & name
auto & names
surface1 clear()
#define DebugInfo
Report an information message using Foam::Info.
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition ListOps.H:886
const dimensionedScalar c
Speed of light in a vacuum.
Foam::SubStrings split(const std::string &str, const char delim, std::string::size_type pos=0, const bool keepEmpty=false)
Split string into sub-strings at the delimiter character.
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition HashSet.H:80
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition ListOps.C:105
List< surfZone > surfZoneList
List of surfZone.
label readLabel(const char *buf)
Parse entire buffer as a label, skipping leading/trailing whitespace.
Definition label.H:63
messageStream Info
Information stream (stdout output on master, null elsewhere).
Omanip< int > setw(const int i)
Definition IOmanip.H:199
vector point
Point is a vector.
Definition point.H:37
messageStream InfoErr
Information stream (stderr output on master, null elsewhere).
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
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
labelList f(nPoints)
Foam::argList args(argc, argv)
volScalarField & b
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235