nastranSurfaceWriter.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2012-2020 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "nastranSurfaceWriter.H"
28 
29 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
30 
31 namespace Foam
32 {
33  makeSurfaceWriterType(nastranSurfaceWriter);
34  addToRunTimeSelectionTable(surfaceWriter, nastranSurfaceWriter, wordDict);
35 
36  // create write methods
37  defineSurfaceWriterWriteFields(nastranSurfaceWriter);
38 
39  template<>
41  {
42  "short",
43  "long",
44  "free"
45  };
46 
49 }
50 
51 
52 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
53 
54 void Foam::nastranSurfaceWriter::formatOS(OFstream& os) const
55 {
57 
58  // capitalize the E marker
59  os.setf(ios_base::uppercase);
60 
61  label prec = 0;
62  label offset = 7;
63  switch (format_)
64  {
65  case (wfShort):
66  case (wfFree):
67  {
68  prec = 8 - offset;
69  break;
70  }
71  case (wfLong):
72  {
73  prec = 16 - offset;
74  break;
75  }
76  default:
77  {
78  }
79  }
80 
81  os.precision(prec);
82 }
83 
84 
85 void Foam::nastranSurfaceWriter::writeCoord
86 (
87  const point& p,
88  const label pointi,
89  OFstream& os
90 ) const
91 {
92  // Fixed short/long formats:
93  // 1 GRID
94  // 2 ID : point ID - requires starting index of 1
95  // 3 CP : co-ordinate system ID (blank)
96  // 4 X1 : point x cp-ordinate
97  // 5 X2 : point x cp-ordinate
98  // 6 X3 : point x cp-ordinate
99  // 7 CD : co-ordinate system for displacements (blank)
100  // 8 PS : single point constraints (blank)
101  // 9 SEID : super-element ID
102 
103  switch (format_)
104  {
105  case wfShort:
106  {
107  os.setf(ios_base::left);
108  os << setw(8) << "GRID";
109  os.unsetf(ios_base::left);
110  os.setf(ios_base::right);
111  os << setw(8) << pointi + 1
112  << " "
113  << setw(8) << p.x()
114  << setw(8) << p.y()
115  << setw(8) << p.z()
116  << nl;
117  os.unsetf(ios_base::right);
118 
119  break;
120  }
121  case wfLong:
122  {
123  os.setf(ios_base::left);
124  os << setw(8) << "GRID*";
125  os.unsetf(ios_base::left);
126  os.setf(ios_base::right);
127  os << setw(16) << pointi + 1
128  << " "
129  << setw(16) << p.x()
130  << setw(16) << p.y()
131  << nl;
132  os.unsetf(ios_base::right);
133  os.setf(ios_base::left);
134  os << setw(8) << "*";
135  os.unsetf(ios_base::left);
136  os.setf(ios_base::right);
137  os << setw(16) << p.z()
138  << nl;
139  os.unsetf(ios_base::right);
140 
141  break;
142  }
143  case wfFree:
144  {
145  os << "GRID"
146  << ',' << pointi + 1
147  << ','
148  << ',' << p.x()
149  << ',' << p.y()
150  << ',' << p.z()
151  << nl;
152 
153  break;
154  }
155  default:
156  {
158  << "Unknown format enumeration" << abort(FatalError);
159  }
160  }
161 }
162 
163 void Foam::nastranSurfaceWriter::writeFace
164 (
165  const word& faceType,
166  const labelList& facePts,
167  label& nFace,
168  OFstream& os
169 ) const
170 {
171  // Only valid surface elements are CTRIA3 and CQUAD4
172 
173  // Fixed short/long formats:
174  // 1 CQUAD4
175  // 2 EID : element ID
176  // 3 PID : property element ID; default = EID (blank)
177  // 4 G1 : grid point index - requires starting index of 1
178  // 5 G2 : grid point index
179  // 6 G3 : grid point index
180  // 7 G4 : grid point index
181  // 8 onwards - not used
182 
183  // For CTRIA3 elements, cols 7 onwards are not used
184 
185  switch (format_)
186  {
187  case wfShort:
188  {
189  os.setf(ios_base::left);
190  os << setw(8) << faceType;
191  os.unsetf(ios_base::left);
192  os.setf(ios_base::right);
193  os << setw(8) << nFace++
194  << " ";
195 
196  forAll(facePts, i)
197  {
198  os << setw(8) << facePts[i] + 1;
199  }
200 
201  os << nl;
202  os.unsetf(ios_base::right);
203 
204  break;
205  }
206  case wfLong:
207  {
208  os.setf(ios_base::left);
209  os << setw(8) << word(faceType + "*");
210  os.unsetf(ios_base::left);
211  os.setf(ios_base::right);
212  os << setw(16) << nFace++
213  << " ";
214 
215  forAll(facePts, i)
216  {
217  os << setw(16) << facePts[i] + 1;
218  if (i == 1)
219  {
220  os << nl;
221  os.unsetf(ios_base::right);
222  os.setf(ios_base::left);
223  os << setw(8) << "*";
224  os.unsetf(ios_base::left);
225  os.setf(ios_base::right);
226  }
227  }
228 
229  os << nl;
230  os.unsetf(ios_base::right);
231 
232  break;
233  }
234  case wfFree:
235  {
236  os << faceType << ','
237  << ++nFace << ',';
238 
239  forAll(facePts, i)
240  {
241  os << ',' << facePts[i] + 1;
242  }
243 
244  os << nl;
245 
246  break;
247  }
248  default:
249  {
251  << "Unknown format enumeration" << abort(FatalError);
252  }
253  }
254 
255 }
256 
257 
258 void Foam::nastranSurfaceWriter::writeGeometry
259 (
260  const pointField& points,
261  const faceList& faces,
262  List<DynamicList<face>>& decomposedFaces,
263  OFstream& os
264 ) const
265 {
266  // write points
267 
268  os << "$" << nl
269  << "$ Points" << nl
270  << "$" << nl;
271 
272  forAll(points, pointi)
273  {
274  writeCoord(points[pointi], pointi, os);
275  }
276 
277 
278  // write faces
279 
280  os << "$" << nl
281  << "$ Faces" << nl
282  << "$" << nl;
283 
284  label nFace = 1;
285 
286  forAll(faces, facei)
287  {
288  const face& f = faces[facei];
289 
290  if (f.size() == 3)
291  {
292  writeFace("CTRIA3", faces[facei], nFace, os);
293  decomposedFaces[facei].append(faces[facei]);
294  }
295  else if (f.size() == 4)
296  {
297  writeFace("CQUAD4", faces[facei], nFace, os);
298  decomposedFaces[facei].append(faces[facei]);
299  }
300  else
301  {
302  // decompose poly face into tris
303  label nTri = 0;
304  faceList triFaces;
305  f.triangles(points, nTri, triFaces);
306 
307  forAll(triFaces, triI)
308  {
309  writeFace("CTRIA3", triFaces[triI], nFace, os);
310  decomposedFaces[facei].append(triFaces[triI]);
311  }
312  }
313  }
314 }
315 
316 
317 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
318 
320 (
321  const IOstream::streamFormat writeFormat
322 )
323 :
324  surfaceWriter(writeFormat),
325  format_(wfShort),
326  fieldMap_(),
327  scale_(1.0)
328 {}
329 
330 
332 :
333  surfaceWriter(optDict),
334  format_(wfLong),
335  fieldMap_(),
336  scale_(1.0)
337 {
338  const dictionary& nastranDict(optDict.lookup("nastranOptions"));
339 
340  if (nastranDict.found("format"))
341  {
342  format_ = formatNames_.read(nastranDict.lookup("format"));
343  }
344 
345  List<Tuple2<word, word>> fieldSet(nastranDict.lookup("fields"));
346 
347  forAll(fieldSet, i)
348  {
349  fieldMap_.insert(fieldSet[i].first(), fieldSet[i].second());
350  }
351 
352  if (nastranDict.found("scale"))
353  {
354  nastranDict.lookup("scale") >> scale_;
355  }
356 }
357 
358 
359 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
360 
362 {}
363 
364 
365 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
366 
368 (
369  const fileName& outputDir,
370  const fileName& surfaceName,
371  const pointField& points,
372  const faceList& faces
373 ) const
374 {
375  if (!isDir(outputDir))
376  {
377  mkDir(outputDir);
378  }
379 
380  OFstream os(outputDir/surfaceName + ".dat");
381  formatOS(os);
382 
383  if (debug)
384  {
385  Info<< "Writing nastran file to " << os.name() << endl;
386  }
387 
388  os << "TITLE=OpenFOAM " << surfaceName.c_str() << " mesh" << nl
389  << "$" << nl
390  << "BEGIN BULK" << nl;
391 
392  List<DynamicList<face>> decomposedFaces(faces.size());
393 
394  writeGeometry(points, faces, decomposedFaces, os);
395 
396  if (!isDir(outputDir))
397  {
398  mkDir(outputDir);
399  }
400 
401  os << "ENDDATA" << endl;
402 }
403 
404 
405 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
nastranSurfaceWriter(const IOstream::streamFormat writeFormat)
Construct given write format.
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
A class for handling file names.
Definition: fileName.H:79
void unsetf(const ios_base::fmtflags uf)
Unset flags of stream.
Definition: IOstream.H:512
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
virtual int precision() const
Get precision of output field.
Definition: OSstream.C:246
ios_base::fmtflags setf(const ios_base::fmtflags f)
Set flags of stream.
Definition: IOstream.H:496
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:158
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:319
Output to file stream.
Definition: OFstream.H:82
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
const Cmpt & z() const
Definition: VectorI.H:87
virtual ~nastranSurfaceWriter()
Destructor.
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:120
Initialise the NamedEnum HashTable from the static list of names.
Definition: NamedEnum.H:51
label triangles(const pointField &points, label &triI, faceList &triFaces) const
Split into triangles using existing points.
Definition: face.C:724
const Cmpt & y() const
Definition: VectorI.H:81
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:56
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Definition: POSIX.C:539
A class for handling words, derived from string.
Definition: word.H:59
Convenience macros for instantiating writer methods for surfaceWriter classes.
streamFormat
Enumeration for the format of data in the stream.
Definition: IOstream.H:86
defineSurfaceWriterWriteFields(nastranSurfaceWriter)
errorManip< error > abort(error &err)
Definition: errorManip.H:131
const Cmpt & x() const
Definition: VectorI.H:75
addToRunTimeSelectionTable(ensightPart, ensightPartCells, istream)
static const char nl
Definition: Ostream.H:260
labelList f(nPoints)
bool mkDir(const fileName &, mode_t=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:290
makeSurfaceWriterType(ensightSurfaceWriter)
static const NamedEnum< format, 3 > formatNames_
messageStream Info
Enum read(Istream &) const
Read a word from Istream and return the corresponding.
Definition: NamedEnum.C:61
Base class for surface writers.
Definition: surfaceWriter.H:54
virtual void write(const fileName &outputDir, const fileName &surfaceName, const pointField &points, const faceList &faces) const
Write single surface geometry to file.
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
IOstream & scientific(IOstream &io)
Definition: IOstream.H:582
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:812