NASedgeFormat.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-2017 OpenFOAM Foundation
9  Copyright (C) 2017-2024 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 \*---------------------------------------------------------------------------*/
28 
29 #include "NASedgeFormat.H"
30 #include "IFstream.H"
31 #include "StringStream.H"
32 #include "bitSet.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
37 {
38  read(filename);
39 }
40 
41 
42 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
43 
45 (
46  const fileName& filename
47 )
48 {
49  clear();
50 
51  IFstream is(filename);
52  if (!is.good())
53  {
55  << "Cannot read file " << filename
56  << exit(FatalError);
57  }
58 
59  DynamicList<point> dynPoints;
60  DynamicList<edge> dynEdges;
61  DynamicList<label> pointId; // Nastran index of points
62 
63  while (is.good())
64  {
65  string line;
66  is.getLine(line);
67 
68  if (line.empty())
69  {
70  continue; // Ignore empty
71  }
72  else if (line[0] == '$')
73  {
74  // Ignore comment
75  continue;
76  }
77 
78  // Check if character 72 is continuation
79  if (line.size() > 72 && line[72] == '+')
80  {
81  line.resize(72);
82 
83  while (true)
84  {
85  string buf;
86  is.getLine(buf);
87 
88  if (buf.size() > 72 && buf[72] == '+')
89  {
90  line += buf.substr(8, 64);
91  }
92  else
93  {
94  line += buf.substr(8);
95  break;
96  }
97  }
98  }
99 
100 
101  // Parsing position within current line
102  std::string::size_type linei = 0;
103 
104  // Is free format if line contains a comma
105  const bool freeFormat = line.contains(',');
106 
107  // First word (column 0-8)
108  const word cmd(word::validate(nextNasField(line, linei, 8)));
109 
110  if (cmd == "CBEAM" || cmd == "CROD")
111  {
112  // Fixed format:
113  // 8-16 : element id
114  // 16-24 : group id
115  // 24-32 : vertex
116  // 32-40 : vertex
117 
118  // discard elementId
119  (void) nextNasField(line, linei, 8, freeFormat);
120  // discard groupId
121  (void) nextNasField(line, linei, 8, freeFormat);
122 
123  label a = readLabel(nextNasField(line, linei, 8, freeFormat));
124  label b = readLabel(nextNasField(line, linei, 8, freeFormat));
125 
126  dynEdges.emplace_back(a,b);
127  }
128  else if (cmd == "PLOTEL")
129  {
130  // Fixed format:
131  // 8-16 : element id
132  // 16-24 : vertex
133  // 24-32 : vertex
134  // 32-40 : vertex
135 
136  // discard elementId (8-16)
137  (void) nextNasField(line, linei, 8, freeFormat);
138 
139  label a = readLabel(nextNasField(line, linei, 8, freeFormat));
140  label b = readLabel(nextNasField(line, linei, 8, freeFormat));
141 
142  dynEdges.emplace_back(a,b);
143  }
144  else if (cmd == "GRID")
145  {
146  // Fixed (short) format:
147  // 8-16 : point id
148  // 16-24 : coordinate system (unsupported)
149  // 24-32 : point x coordinate
150  // 32-40 : point y coordinate
151  // 40-48 : point z coordinate
152  // 48-56 : displacement coordinate system (optional, unsupported)
153  // 56-64 : single point constraints (optional, unsupported)
154  // 64-70 : super-element id (optional, unsupported)
155 
156  label index = readLabel(nextNasField(line, linei, 8, freeFormat));
157  (void) nextNasField(line, linei, 8, freeFormat);
158  scalar x = readNasScalar(nextNasField(line, linei, 8, freeFormat));
159  scalar y = readNasScalar(nextNasField(line, linei, 8, freeFormat));
160  scalar z = readNasScalar(nextNasField(line, linei, 8, freeFormat));
161 
162  pointId.push_back(index);
163  dynPoints.emplace_back(x, y, z);
164  }
165  else if (cmd == "GRID*")
166  {
167  // Long format is on two lines with '*' continuation symbol
168  // on start of second line.
169  // Typical line (spaces compacted)
170  // GRID* 126 0 -5.55999875E+02 -5.68730474E+02
171  // * 2.14897901E+02
172 
173  // Cannot be long format and free format at the same time!
174 
175  label index = readLabel(nextNasField(line, linei, 16)); // 8-24
176  (void) nextNasField(line, linei, 16); // 24-40
177  scalar x = readNasScalar(nextNasField(line, linei, 16)); // 40-56
178  scalar y = readNasScalar(nextNasField(line, linei, 16)); // 56-72
179 
180  linei = 0; // restart at index 0
181  is.getLine(line);
182  if (line[0] != '*')
183  {
185  << "Expected continuation symbol '*' when reading GRID*"
186  << " (double precision coordinate) format" << nl
187  << "Read:" << line << nl
188  << "File:" << is.name() << " line:" << is.lineNumber()
189  << exit(FatalError);
190  }
191  (void) nextNasField(line, linei, 8); // 0-8
192  scalar z = readNasScalar(nextNasField(line, linei, 16)); // 8-16
193 
194  pointId.push_back(index);
195  dynPoints.emplace_back(x, y, z);
196  }
197  }
198 
199  // transfer to normal lists
200  storedPoints().transfer(dynPoints);
201 
202  // Build inverse mapping (NASTRAN pointId -> index)
203  Map<label> mapPointId(invertToMap(pointId));
204 
205  // note which points were really used and which can be culled
206  bitSet usedPoints(points().size());
207 
208 
209  // Pass1: relabel edges
210  // ~~~~~~~~~~~~~~~~~~~~
211  for (edge& e : dynEdges)
212  {
213  e[0] = mapPointId[e[0]];
214  e[1] = mapPointId[e[1]];
215 
216  usedPoints.set(e[0]);
217  usedPoints.set(e[1]);
218  }
219  pointId.clearStorage();
220  mapPointId.clear();
221 
222  // Not all points were used, subset/cull them accordingly
223  if (!usedPoints.all())
224  {
225  label nUsed = 0;
226 
227  pointField& pts = storedPoints();
228  for (const label pointi : usedPoints)
229  {
230  if (nUsed != pointi)
231  {
232  pts[nUsed] = pts[pointi];
233  }
234 
235  // map prev -> new id
236  mapPointId.set(pointi, nUsed);
237 
238  ++nUsed;
239  }
240  pts.resize(nUsed);
241 
242  // Renumber edge vertices
243  for (edge& e : dynEdges)
244  {
245  e[0] = mapPointId[e[0]];
246  e[1] = mapPointId[e[1]];
247  }
248  }
249 
250  storedEdges().transfer(dynEdges);
251 
252  return true;
253 }
254 
255 
256 // ************************************************************************* //
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:39
A line primitive.
Definition: line.H:52
A class for handling file names.
Definition: fileName.H:72
bool contains(char c) const noexcept
True if string contains given character (cf. C++23)
Definition: string.H:411
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...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
Input/output from string buffers.
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
scalar y
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
virtual bool read(const fileName &filename) override
Read from a file.
Definition: NASedgeFormat.C:38
const pointField & points
const dimensionedScalar b
Wien displacement law constant: default SI units: [m.K].
Definition: createFields.H:27
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
Definition: DynamicListI.H:541
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:67
NASedgeFormat(const fileName &filename)
Construct from file name.
Definition: NASedgeFormat.C:29
Input from file stream as an ISstream, normally using std::ifstream for the actual input...
Definition: IFstream.H:51
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:558
surface1 clear()
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:425
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition: ListOps.C:105
const pointField & pts