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-2021 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"
27 #include "polygonTriangulate.H"
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34  makeSurfaceWriterType(nastranSurfaceWriter);
35  addToRunTimeSelectionTable(surfaceWriter, nastranSurfaceWriter, wordDict);
36 
37  // create write methods
38  defineSurfaceWriterWriteFields(nastranSurfaceWriter);
39 
40  template<>
42  {
43  "short",
44  "long",
45  "free"
46  };
47 
50 }
51 
52 
53 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
54 
55 void Foam::nastranSurfaceWriter::formatOS(OFstream& os) const
56 {
58 
59  // Capitalise the E marker
60  os.setf(ios_base::uppercase);
61 
62  label prec = 0;
63  label offset = 7;
64  switch (format_)
65  {
66  case (wfShort):
67  case (wfFree):
68  {
69  prec = 8 - offset;
70  break;
71  }
72  case (wfLong):
73  {
74  prec = 16 - offset;
75  break;
76  }
77  default:
78  {
79  }
80  }
81 
82  os.precision(prec);
83 }
84 
85 
86 void Foam::nastranSurfaceWriter::writeCoord
87 (
88  const point& p,
89  const label pointi,
90  OFstream& os
91 ) const
92 {
93  // Fixed short/long formats:
94  // 1 GRID
95  // 2 ID : point ID - requires starting index of 1
96  // 3 CP : co-ordinate system ID (blank)
97  // 4 X1 : point x cp-ordinate
98  // 5 X2 : point x cp-ordinate
99  // 6 X3 : point x cp-ordinate
100  // 7 CD : co-ordinate system for displacements (blank)
101  // 8 PS : single point constraints (blank)
102  // 9 SEID : super-element ID
103 
104  switch (format_)
105  {
106  case wfShort:
107  {
108  os.setf(ios_base::left);
109  os << setw(8) << "GRID";
110  os.unsetf(ios_base::left);
111  os.setf(ios_base::right);
112  os << setw(8) << pointi + 1
113  << " "
114  << setw(8) << p.x()
115  << setw(8) << p.y()
116  << setw(8) << p.z()
117  << nl;
118  os.unsetf(ios_base::right);
119 
120  break;
121  }
122  case wfLong:
123  {
124  os.setf(ios_base::left);
125  os << setw(8) << "GRID*";
126  os.unsetf(ios_base::left);
127  os.setf(ios_base::right);
128  os << setw(16) << pointi + 1
129  << " "
130  << setw(16) << p.x()
131  << setw(16) << p.y()
132  << nl;
133  os.unsetf(ios_base::right);
134  os.setf(ios_base::left);
135  os << setw(8) << "*";
136  os.unsetf(ios_base::left);
137  os.setf(ios_base::right);
138  os << setw(16) << p.z()
139  << nl;
140  os.unsetf(ios_base::right);
141 
142  break;
143  }
144  case wfFree:
145  {
146  os << "GRID"
147  << ',' << pointi + 1
148  << ','
149  << ',' << p.x()
150  << ',' << p.y()
151  << ',' << p.z()
152  << nl;
153 
154  break;
155  }
156  default:
157  {
159  << "Unknown format enumeration" << abort(FatalError);
160  }
161  }
162 }
163 
164 void Foam::nastranSurfaceWriter::writeFace
165 (
166  const word& faceType,
167  const labelList& facePts,
168  label& nFace,
169  OFstream& os
170 ) const
171 {
172  // Only valid surface elements are CTRIA3 and CQUAD4
173 
174  // Fixed short/long formats:
175  // 1 CQUAD4
176  // 2 EID : element ID
177  // 3 PID : property element ID; default = EID (blank)
178  // 4 G1 : grid point index - requires starting index of 1
179  // 5 G2 : grid point index
180  // 6 G3 : grid point index
181  // 7 G4 : grid point index
182  // 8 onwards - not used
183 
184  // For CTRIA3 elements, cols 7 onwards are not used
185 
186  switch (format_)
187  {
188  case wfShort:
189  {
190  os.setf(ios_base::left);
191  os << setw(8) << faceType;
192  os.unsetf(ios_base::left);
193  os.setf(ios_base::right);
194  os << setw(8) << nFace++
195  << " ";
196 
197  forAll(facePts, i)
198  {
199  os << setw(8) << facePts[i] + 1;
200  }
201 
202  os << nl;
203  os.unsetf(ios_base::right);
204 
205  break;
206  }
207  case wfLong:
208  {
209  os.setf(ios_base::left);
210  os << setw(8) << word(faceType + "*");
211  os.unsetf(ios_base::left);
212  os.setf(ios_base::right);
213  os << setw(16) << nFace++
214  << " ";
215 
216  forAll(facePts, i)
217  {
218  os << setw(16) << facePts[i] + 1;
219  if (i == 1)
220  {
221  os << nl;
222  os.unsetf(ios_base::right);
223  os.setf(ios_base::left);
224  os << setw(8) << "*";
225  os.unsetf(ios_base::left);
226  os.setf(ios_base::right);
227  }
228  }
229 
230  os << nl;
231  os.unsetf(ios_base::right);
232 
233  break;
234  }
235  case wfFree:
236  {
237  os << faceType << ','
238  << ++nFace << ',';
239 
240  forAll(facePts, i)
241  {
242  os << ',' << facePts[i] + 1;
243  }
244 
245  os << nl;
246 
247  break;
248  }
249  default:
250  {
252  << "Unknown format enumeration" << abort(FatalError);
253  }
254  }
255 
256 }
257 
258 
259 void Foam::nastranSurfaceWriter::writeGeometry
260 (
261  const pointField& points,
262  const faceList& faces,
263  List<DynamicList<face>>& decomposedFaces,
264  OFstream& os
265 ) const
266 {
267  // write points
268 
269  os << "$" << nl
270  << "$ Points" << nl
271  << "$" << nl;
272 
273  forAll(points, pointi)
274  {
275  writeCoord(points[pointi], pointi, os);
276  }
277 
278 
279  // write faces
280 
281  os << "$" << nl
282  << "$ Faces" << nl
283  << "$" << nl;
284 
285  label nFace = 1;
286 
287  polygonTriangulate triEngine;
288 
289  forAll(faces, facei)
290  {
291  const face& f = faces[facei];
292 
293  if (f.size() == 3)
294  {
295  writeFace("CTRIA3", faces[facei], nFace, os);
296  decomposedFaces[facei].append(faces[facei]);
297  }
298  else if (f.size() == 4)
299  {
300  writeFace("CQUAD4", faces[facei], nFace, os);
301  decomposedFaces[facei].append(faces[facei]);
302  }
303  else
304  {
305  // decompose poly face into tris
306  triEngine.triangulate(UIndirectList<point>(points, f));
307  forAll(triEngine.triPoints(), triI)
308  {
309  const face f(triEngine.triPoints(triI, f));
310  writeFace("CTRIA3", f, nFace, os);
311  decomposedFaces[facei].append(f);
312  }
313  }
314  }
315 }
316 
317 
318 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
319 
321 (
322  const IOstream::streamFormat writeFormat
323 )
324 :
325  surfaceWriter(writeFormat),
326  format_(wfShort),
327  fieldMap_(),
328  scale_(1.0)
329 {}
330 
331 
333 :
334  surfaceWriter(optDict),
335  format_(wfLong),
336  fieldMap_(),
337  scale_(1.0)
338 {
339  const dictionary& nastranDict(optDict.lookup("nastranOptions"));
340 
341  if (nastranDict.found("format"))
342  {
343  format_ = formatNames_.read(nastranDict.lookup("format"));
344  }
345 
346  List<Tuple2<word, word>> fieldSet(nastranDict.lookup("fields"));
347 
348  forAll(fieldSet, i)
349  {
350  fieldMap_.insert(fieldSet[i].first(), fieldSet[i].second());
351  }
352 
353  if (nastranDict.found("scale"))
354  {
355  nastranDict.lookup("scale") >> scale_;
356  }
357 }
358 
359 
360 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
361 
363 {}
364 
365 
366 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
367 
369 (
370  const fileName& outputDir,
371  const fileName& surfaceName,
372  const pointField& points,
373  const faceList& faces
374 ) const
375 {
376  if (!isDir(outputDir))
377  {
378  mkDir(outputDir);
379  }
380 
381  OFstream os(outputDir/surfaceName + ".dat");
382  formatOS(os);
383 
384  if (debug)
385  {
386  Info<< "Writing nastran file to " << os.name() << endl;
387  }
388 
389  os << "TITLE=OpenFOAM " << surfaceName.c_str() << " mesh" << nl
390  << "$" << nl
391  << "BEGIN BULK" << nl;
392 
393  List<DynamicList<face>> decomposedFaces(faces.size());
394 
395  writeGeometry(points, faces, decomposedFaces, os);
396 
397  if (!isDir(outputDir))
398  {
399  mkDir(outputDir);
400  }
401 
402  os << "ENDDATA" << endl;
403 }
404 
405 
406 // ************************************************************************* //
#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:509
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:493
error FatalError
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:156
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:323
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
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)
Triangulation of three-dimensional polygons.
A List with indirect addressing.
Definition: fvMatrix.H:106
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
const UList< triFace > & triPoints() const
Get the triangles&#39; points.
IOstream & scientific(IOstream &io)
Definition: IOstream.H:579
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:844