nastranSurfaceWriter.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) 2012-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2019 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 "nastranSurfaceWriter.H"
30 #include "Pair.H"
31 #include "IOmanip.H"
32 #include "OSspecific.H"
33 #include "surfaceWriterMethods.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace surfaceWriters
41 {
42  defineTypeName(nastranWriter);
43  addToRunTimeSelectionTable(surfaceWriter, nastranWriter, word);
44  addToRunTimeSelectionTable(surfaceWriter, nastranWriter, wordDict);
45 }
46 }
47 
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 
50 // Field writing implementation
52 
53 // Field writing methods
55 
56 
57 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
58 
59 Foam::Ostream& Foam::surfaceWriters::nastranWriter::writeKeyword
60 (
61  Ostream& os,
62  const word& keyword
63 ) const
64 {
65  return fileFormats::NASCore::writeKeyword(os, keyword, writeFormat_);
66 }
67 
68 
69 void Foam::surfaceWriters::nastranWriter::writeCoord
70 (
71  Ostream& os,
72  const point& pt,
73  const label pointI
74 ) const
75 {
76  // Fixed short/long formats:
77  // 1 GRID
78  // 2 ID : point ID - requires starting index of 1
79  // 3 CP : coordinate system ID (blank)
80  // 4 X1 : point x coordinate
81  // 5 X2 : point x coordinate
82  // 6 X3 : point x coordinate
83  // 7 CD : coordinate system for displacements (blank)
84  // 8 PS : single point constraints (blank)
85  // 9 SEID : super-element ID
86 
87  writeKeyword(os, "GRID") << separator_;
88 
89  os.setf(std::ios_base::right);
90 
91  writeValue(os, pointI+1) << separator_;
92  writeValue(os, "") << separator_;
93  writeValue(os, pt.x()) << separator_;
94  writeValue(os, pt.y()) << separator_;
95 
96  switch (writeFormat_)
97  {
98  case fieldFormat::SHORT :
99  {
100  os << setw(8) << pt.z() << nl;
101  os.unsetf(std::ios_base::right);
102  break;
103  }
104 
105  case fieldFormat::LONG :
106  {
107  os << nl;
108  os.unsetf(std::ios_base::right);
109  writeKeyword(os, "");
110  os.setf(std::ios_base::right);
111 
112  writeValue(os, pt.z()) << nl;
113  break;
114  }
115 
116  case fieldFormat::FREE :
117  {
118  writeValue(os, pt.z()) << nl;
119  break;
120  }
121  }
122 
123  os.unsetf(std::ios_base::right);
124 }
125 
126 
127 void Foam::surfaceWriters::nastranWriter::writeFace
128 (
129  Ostream& os,
130  const word& faceType,
131  const labelUList& facePts,
132  const label nFace,
133  const label PID
134 ) const
135 {
136  // Only valid surface elements are CTRIA3 and CQUAD4
137 
138  // Fixed short/long formats:
139  // 1 CQUAD4
140  // 2 EID : element ID
141  // 3 PID : property element ID; default = EID (blank)
142  // 4 G1 : grid point index - requires starting index of 1
143  // 5 G2 : grid point index
144  // 6 G3 : grid point index
145  // 7 G4 : grid point index
146  // 8 onwards - not used
147 
148  // For CTRIA3 elements, cols 7 onwards are not used
149 
150  writeKeyword(os, faceType) << separator_;
151 
152  os.setf(std::ios_base::right);
153 
154  writeValue(os, nFace) << separator_;
155  writeValue(os, PID);
156 
157  switch (writeFormat_)
158  {
159  case fieldFormat::SHORT :
160  {
161  for (const label pointi : facePts)
162  {
163  writeValue(os, pointi + 1);
164  }
165 
166  break;
167  }
168 
169  case fieldFormat::LONG :
170  {
171  forAll(facePts, i)
172  {
173  writeValue(os, facePts[i] + 1);
174  if (i == 1)
175  {
176  os << nl;
177  os.unsetf(std::ios_base::right);
178  writeKeyword(os, "");
179  os.setf(std::ios_base::right);
180  }
181  }
182 
183  break;
184  }
185 
186  case fieldFormat::FREE :
187  {
188  for (const label pointi : facePts)
189  {
190  os << separator_;
191  writeValue(os, pointi + 1);
192  }
193 
194  break;
195  }
196  }
197 
198  os << nl;
199  os.unsetf(std::ios_base::right);
200 }
201 
202 
203 void Foam::surfaceWriters::nastranWriter::writeGeometry
204 (
205  Ostream& os,
206  const meshedSurf& surf,
207  List<DynamicList<face>>& decomposedFaces
208 ) const
209 {
210  const pointField& points = surf.points();
211  const faceList& faces = surf.faces();
212  const labelList& zones = surf.zoneIds();
213 
214  // Write points
215 
216  os << "$" << nl
217  << "$ Points" << nl
218  << "$" << nl;
219 
220  forAll(points, pointi)
221  {
222  writeCoord(os, points[pointi], pointi);
223  }
224 
225  // Write faces
226  decomposedFaces.clear();
227  decomposedFaces.setSize(faces.size());
228 
229  os << "$" << nl
230  << "$ Faces" << nl
231  << "$" << nl;
232 
233  label nFace = 0; // the element-id
234  forAll(faces, facei)
235  {
236  const face& f = faces[facei];
237  // 1-offset for PID
238  const label PID = 1 + (facei < zones.size() ? zones[facei] : 0);
239 
240  if (f.size() == 3)
241  {
242  writeFace(os, "CTRIA3", f, ++nFace, PID);
243  decomposedFaces[facei].append(f);
244  }
245  else if (f.size() == 4)
246  {
247  writeFace(os, "CQUAD4", f, ++nFace, PID);
248  decomposedFaces[facei].append(f);
249  }
250  else
251  {
252  // Decompose poly face into tris
253  label nTri = 0;
254  faceList triFaces;
255  f.triangles(points, nTri, triFaces);
256 
257  forAll(triFaces, trii)
258  {
259  writeFace(os, "CTRIA3", triFaces[trii], ++nFace, PID);
260  decomposedFaces[facei].append(triFaces[trii]);
261  }
262  }
263  }
264 }
265 
266 
267 Foam::Ostream& Foam::surfaceWriters::nastranWriter::writeFooter
268 (
269  Ostream& os,
270  const meshedSurf& surf
271 ) const
272 {
273  // Zone id have been used for the PID. Find unique values.
274 
275  labelList pidsUsed = labelHashSet(surf.zoneIds()).sortedToc();
276  if (pidsUsed.empty())
277  {
278  pidsUsed.setSize(1, Zero); // fallback
279  }
280 
281  for (auto pid : pidsUsed)
282  {
283  writeKeyword(os, "PSHELL") << separator_;
284  writeValue(os, pid+1); // 1-offset for PID
285 
286  for (label i = 0; i < 7; ++i)
287  {
288  // Dummy values
289  os << separator_;
290  writeValue(os, 1);
291  }
292  os << nl;
293  }
294 
295 
296  // Use single material ID
297 
298  const label MID = 1;
299 
300  writeKeyword(os, "MAT1") << separator_;
301  writeValue(os, MID);
302 
303  for (label i = 0; i < 7; ++i)
304  {
305  // Dummy values
306  os << separator_;
307  writeValue(os, "");
308  }
309  os << nl;
310 
311  return os;
312 }
313 
314 
315 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
316 
318 :
319  surfaceWriter(),
320  writeFormat_(fieldFormat::SHORT),
321  fieldMap_(),
322  scale_(1.0),
323  separator_()
324 {}
325 
326 
328 (
329  const dictionary& options
330 )
331 :
332  surfaceWriter(options),
333  writeFormat_
334  (
336  (
337  "format",
338  options,
339  fieldFormat::LONG
340  )
341  ),
342  fieldMap_(),
343  scale_(options.lookupOrDefault<scalar>("scale", 1)),
344  separator_()
345 {
346  if (writeFormat_ == fieldFormat::FREE)
347  {
348  separator_ = ",";
349  }
350 
351  List<Pair<word>> fieldPairs;
352  options.readEntry("fields", fieldPairs);
353 
354  for (const Pair<word>& item : fieldPairs)
355  {
356  // (field name => load format)
357  fieldMap_.insert
358  (
359  item.first(),
361  );
362  }
363 }
364 
365 
367 (
368  const meshedSurf& surf,
369  const fileName& outputPath,
370  bool parallel,
371  const dictionary& options
372 )
373 :
374  nastranWriter(options)
375 {
376  open(surf, outputPath, parallel);
377 }
378 
379 
381 (
382  const pointField& points,
383  const faceList& faces,
384  const fileName& outputPath,
385  bool parallel,
386  const dictionary& options
387 )
388 :
389  nastranWriter(options)
390 {
391  open(points, faces, outputPath, parallel);
392 }
393 
394 
395 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
396 
398 {
399  checkOpen();
400 
401  // Geometry: rootdir/<TIME>/surfaceName.nas
402 
403  fileName outputFile = outputPath_;
404  if (useTimeDir() && !timeName().empty())
405  {
406  // Splice in time-directory
407  outputFile = outputPath_.path() / timeName() / outputPath_.name();
408  }
409  outputFile.ext("nas");
410 
411  if (verbose_)
412  {
413  Info<< "Writing nastran geometry to " << outputFile << endl;
414  }
415 
416 
417  const meshedSurf& surf = surface();
418 
419  if (Pstream::master() || !parallel_)
420  {
421  if (!isDir(outputFile.path()))
422  {
423  mkDir(outputFile.path());
424  }
425 
426  OFstream os(outputFile);
427  fileFormats::NASCore::setPrecision(os, writeFormat_);
428 
429  os << "TITLE=OpenFOAM " << outputPath_.name()
430  << " mesh" << nl
431  << "$" << nl
432  << "BEGIN BULK" << nl;
433 
434  List<DynamicList<face>> decomposedFaces;
435  writeGeometry(os, surf, decomposedFaces);
436 
437  writeFooter(os, surf)
438  << "ENDDATA" << nl;
439  }
440 
441  wroteGeom_ = true;
442  return outputFile;
443 }
444 
445 
446 // ************************************************************************* //
Foam::labelList
List< label > labelList
A List of labels.
Definition: List.H:74
Foam::pointField
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
OSspecific.H
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
Foam::surfaceWriter
Base class for surface writers.
Definition: surfaceWriter.H:111
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::OFstream::name
virtual const fileName & name() const
Read/write access to the name of the stream.
Definition: OSstream.H:91
Foam::fileName::path
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:186
Foam::Zero
static constexpr const zero Zero
Global zero.
Definition: zero.H:128
Foam::fileFormats::NASCore::loadFormatNames
static const Enum< loadFormat > loadFormatNames
Selection names for the NASTRAN file field formats.
Definition: NASCore.H:81
Foam::meshedSurf
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:49
Foam::surfaceWriters::defineTypeName
defineTypeName(boundaryDataWriter)
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:337
Pair.H
Foam::dictionary::lookupOrDefault
T lookupOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionary.H:1241
surfaceWriterMethods.H
Convenience macros for instantiating surfaceWriter methods.
Foam::fileFormats::NASCore::setPrecision
static void setPrecision(Ostream &os, const fieldFormat format)
Set output stream precision and format flags.
Definition: NASCore.C:131
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:290
nastranSurfaceWriter.H
Foam::fileFormats::NASCore::writeKeyword
static Ostream & writeKeyword(Ostream &os, const word &keyword, const fieldFormat format)
Definition: NASCore.C:165
Foam::label
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:62
Foam::Field< vector >
Foam::Info
messageStream Info
Information stream (uses stdout - output is on the master only)
Foam::pid
pid_t pid()
Return the PID of this process.
Definition: MSwindows.C:330
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::dictionary::readEntry
bool readEntry(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX, bool mandatory=true) const
Definition: dictionaryTemplates.C:314
timeName
word timeName
Definition: getTimeIndex.H:3
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::fileName::ext
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:228
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::setw
Omanip< int > setw(const int i)
Definition: IOmanip.H:199
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:99
Foam::UPstream::master
static bool master(const label communicator=0)
Am I the master process.
Definition: UPstream.H:438
Foam::surfaceWriters::addToRunTimeSelectionTable
addToRunTimeSelectionTable(surfaceWriter, boundaryDataWriter, word)
Foam::nl
constexpr char nl
Definition: Ostream.H:372
Foam::Pair< word >
f
labelList f(nPoints)
Foam::faceList
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
Foam::surfaceWriters::nastranWriter::write
virtual fileName write()
Write surface geometry to file.
Definition: nastranSurfaceWriter.C:397
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:102
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::point
vector point
Point is a vector.
Definition: point.H:43
Foam::labelUList
UList< label > labelUList
A UList of labels.
Definition: UList.H:79
Foam::surfaceWriters::nastranWriter
A surface writer for the Nastran file format - both surface mesh and fields.
Definition: nastranSurfaceWriter.H:127
Foam::labelHashSet
HashSet< label, Hash< label > > labelHashSet
A HashSet with label keys and label hasher.
Definition: HashSet.H:415
Foam::fileFormats::NASCore::fieldFormatNames
static const Enum< fieldFormat > fieldFormatNames
Selection names for the NASTRAN file field formats.
Definition: NASCore.H:71
Foam::mkDir
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: MSwindows.C:507
nastranSurfaceWriterImpl.C
Foam::surfaceWriters::nastranWriter::nastranWriter
nastranWriter()
Construct null.
Definition: nastranSurfaceWriter.C:317
defineSurfaceWriterWriteFields
defineSurfaceWriterWriteFields(Foam::surfaceWriters::nastranWriter)
Foam::fileFormats::NASCore::fieldFormat
fieldFormat
File field formats.
Definition: NASCore.H:63
Foam::isDir
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:643