NASCore.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) 2017-2024 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 "NASCore.H"
29 #include "IOmanip.H"
30 #include "Ostream.H"
31 #include "parsing.H"
32 #include "defineDebugSwitch.H"
33 
34 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
35 
36 namespace Foam
37 {
38 namespace fileFormats
39 {
40  defineDebugSwitchWithName(NASCore, "nastran.debug", 0);
42  (
43  NASCore, Nastran, "nastran.debug"
44  );
45 }
46 }
47 
48 
49 const Foam::Enum
50 <
52 >
54 ({
55  { fieldFormat::SHORT, "short" },
56  { fieldFormat::LONG, "long" },
57  { fieldFormat::FREE, "free" },
58 });
59 
60 
61 const Foam::Enum
62 <
64 >
66 ({
67  { loadFormat::PLOAD2, "PLOAD2" },
68  { loadFormat::PLOAD4, "PLOAD4" },
69 });
70 
71 
72 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
73 
74 namespace Foam
75 {
76 
77 template<class Type>
78 static inline void putValue(Ostream& os, const Type& value, const int width)
79 {
80  if (width) os << setw(width);
81  os << value;
82 }
83 
84 } // End namespace Foam
85 
86 
87 // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
88 
89 Foam::scalar Foam::fileFormats::NASCore::readNasScalar(const std::string& str)
90 {
91  const auto signPos = str.find_last_of("+-");
92 
93  if
94  (
95  signPos == std::string::npos
96  || signPos == 0
97  || str[signPos-1] == 'E' || str[signPos-1] == 'e'
98  || isspace(str[signPos-1])
99  )
100  {
101  // A normal number format
102  return readScalar(str);
103  }
104 
105 
106  // Nastran compact number format.
107  // Eg, "1234-2" instead of "1234E-2"
108 
109  scalar value = 0;
110  int exponent = 0; // Any integer
111 
112  if
113  (
114  readScalar(str.substr(0, signPos), value) // Mantissa
115  && readInt(str.substr(signPos), exponent) // Exponent (with sign)
116  )
117  {
118  // Note: this does not catch underflow/overflow
119  // (especially when scalar is a float)
120  value *= ::pow(10, exponent);
121  }
122  else
123  {
124  FatalIOErrorInFunction("unknown")
126  << exit(FatalIOError);
127 
128  value = 0;
129  }
130 
131  return value;
132 }
133 
134 
136 (
137  const std::string& str,
139  const std::string::size_type width,
140  const bool free_format
141 )
142 {
143  const auto beg = pos;
144  const auto end = str.find(',', pos);
145 
146  if (end == std::string::npos)
147  {
148  if (free_format)
149  {
150  // Nothing left
151  pos = str.size();
152  return str.substr(beg);
153  }
154 
155  // Fixed format - continue after field width
156  pos = beg + width;
157  return str.substr(beg, width);
158  }
159  else
160  {
161  // Free format - continue after comma
162  pos = end + 1;
163  return str.substr(beg, (end - beg));
164  }
165 }
166 
167 
169 (
170  Ostream& os,
171  const fieldFormat format
172 )
173 {
175 
176  // Capitalise the E marker
177  os.setf(std::ios_base::uppercase);
178 
179  const label offset = 7;
180 
181  label prec = 16 - offset;
182  switch (format)
183  {
184  case fieldFormat::SHORT :
185  {
186  prec = 8 - offset;
187  break;
188  }
189 
190  case fieldFormat::LONG :
191  case fieldFormat::FREE :
192  {
193  prec = 16 - offset;
194  break;
195  }
196  }
197 
198  os.precision(prec);
199 }
200 
201 
203 (
204  Ostream& os,
205  const word& keyword,
206  const fieldFormat format
207 )
208 {
209  os.setf(std::ios_base::left);
210 
211  switch (format)
212  {
213  case fieldFormat::SHORT :
214  {
215  os << setw(8) << keyword;
216  break;
217  }
218  case fieldFormat::LONG :
219  {
220  os << setw(8) << word(keyword + '*');
221  break;
222  }
223  case fieldFormat::FREE :
224  {
225  os << keyword;
226  break;
227  }
228  }
229 
230  os.unsetf(std::ios_base::left);
231 
232  return os;
233 }
234 
235 
237 (
238  Ostream& os,
239  const point& p,
240  const label pointId, // zero-based
241  const fieldFormat format
242 )
243 {
244  // Field width (SHORT, LONG formats)
245  const int width =
246  (
247  format == fieldFormat::SHORT ? 8
248  : format == fieldFormat::LONG ? 16
249  : 0
250  );
251 
252  // Separator char (FREE format)
253  const char sep = (format == fieldFormat::FREE ? ',' : '\0');
254 
255 
256  // Fixed short/long formats:
257  // 1 GRID
258  // 2 ID : point ID - requires starting index of 1
259  // 3 CP : coordinate system ID (blank)
260  // 4 X1 : point x coordinate
261  // 5 X2 : point y coordinate
262  // 6 X3 : point z coordinate
263  // 7 CD : coordinate system for displacements (blank)
264  // 8 PS : single point constraints (blank)
265  // 9 SEID : super-element ID
266 
267  writeKeyword(os, "GRID", format);
268  if (sep) os << sep;
269 
270  os.setf(std::ios_base::right);
271 
272  // Point ID (from 0-based to 1-based)
273  putValue(os, (pointId+1), width);
274  if (sep) os << sep;
275 
276  // Coordinate system ID (blank)
277  putValue(os, "", width);
278  if (sep) os << sep;
279 
280  putValue(os, p.x(), width);
281  if (sep) os << sep;
282 
283  putValue(os, p.y(), width);
284  if (sep) os << sep;
285 
286  if (format == fieldFormat::LONG)
287  {
288  // Continuation
289  os.unsetf(std::ios_base::right);
290  os << nl;
291  writeKeyword(os, "", format);
292  os.setf(std::ios_base::right);
293  }
294 
295  putValue(os, p.z(), width);
296  os << nl;
297 
298  os.unsetf(std::ios_base::right);
299 }
300 
301 
303 (
304  const UList<point>& points,
305  const UList<face>& faces,
306  labelList& decompOffsets,
307  DynamicList<face>& decompFaces
308 )
309 {
310  // On-demand face decomposition (triangulation)
311 
312  decompOffsets.resize(faces.size()+1);
313  decompFaces.clear();
314 
315  auto offsetIter = decompOffsets.begin();
316  *offsetIter = 0; // The first offset is always zero
317 
318  for (const face& f : faces)
319  {
320  const label n = f.size();
321 
322  if (n != 3 && n != 4)
323  {
324  // Decompose non-tri/quad into tris
325  f.triangles(points, decompFaces);
326  }
327 
328  // The end offset, which is the next begin offset
329  *(++offsetIter) = decompFaces.size();
330  }
331 
332  return decompFaces.size();
333 }
334 
335 
336 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
static const Enum< fieldFormat > fieldFormatNames
Selection names for the NASTRAN file field formats.
Definition: NASCore.H:77
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
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
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:68
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:153
loadFormat
Output load format.
Definition: NASCore.H:82
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
static const Enum< loadFormat > loadFormatNames
Selection names for the NASTRAN load formats.
Definition: NASCore.H:91
int readInt(Istream &is)
Read int from stream.
Definition: intIO.C:73
defineDebugSwitchWithName(NASCore, "nastran.debug", 0)
fieldFormat
File field formats.
Definition: NASCore.H:67
static void putValue(Ostream &os, const Type &value, const int width)
Definition: NASCore.C:71
dimensionedScalar pos(const dimensionedScalar &ds)
static void setPrecision(Ostream &os, const fieldFormat format)
Set output stream precision and format flags.
Definition: NASCore.C:162
const pointField & points
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
registerDebugSwitchWithName(NASCore, Nastran, "nastran.debug")
A class for handling words, derived from Foam::string.
Definition: word.H:63
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:67
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:392
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
static void writeCoord(Ostream &os, const point &p, const label pointId, const fieldFormat format)
Write a GRID point.
Definition: NASCore.C:230
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
Istream and Ostream manipulators taking arguments.
General parsing error.
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
OBJstream os(runTime.globalPath()/outputName)
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
labelList f(nPoints)
static scalar readNasScalar(const std::string &str)
Extract numbers from things like "-2.358-8" (same as "-2.358e-8")
Definition: NASCore.C:82
word format(conversionProperties.get< word >("format"))
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: error.H:64
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:637
Macro definitions for debug switches.
const char * end
Definition: SVGTools.H:223
bool isspace(char c) noexcept
Test for whitespace (C-locale)
Definition: char.H:69
static label faceDecomposition(const UList< point > &points, const UList< face > &faces, labelList &decompOffsets, DynamicList< face > &decompFaces)
Calculate face decomposition for non tri/quad faces.
Definition: NASCore.C:296
label n
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
volScalarField & p
static Ostream & writeKeyword(Ostream &os, const word &keyword, const fieldFormat format)
Write initial keyword (eg, &#39;GRID&#39; or &#39;GRID*&#39;) followed by the requisite number of spaces for the fiel...
Definition: NASCore.C:196
IOstream & scientific(IOstream &io)
Definition: IOstream.H:578
Namespace for OpenFOAM.
const Foam::Enum< errorType > errorNames
Strings corresponding to the errorType.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...