abaqusSurfaceWriter.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) 2020-2022 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 "abaqusSurfaceWriter.H"
29 #include "ABAQUSCore.H"
30 #include "IOmanip.H"
31 #include "ListOps.H"
32 #include "OSspecific.H"
35 
36 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
37 
38 namespace Foam
39 {
40 namespace surfaceWriters
41 {
45 }
46 }
47 
48 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49 
50 // Field writing implementation
52 
53 // Field writing methods
55 
56 
57 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
58 
59 namespace Foam
60 {
61 
62 // Write connectivity as CSV list
63 inline static void writeConnectivity
64 (
65  Ostream& os,
66  const label elemId,
67  const labelUList& elem
68 )
69 {
70  os << " " << elemId;
71 
72  for (const label vert : elem)
73  {
74  os << ", " << (vert + 1);
75  }
76 
77  os << nl;
78 }
79 
80 } // End namespace Foam
81 
82 
83 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
84 
85 void Foam::surfaceWriters::abaqusWriter::writeFace
86 (
87  Ostream& os,
88  const labelUList& f,
89  const label elemId,
90  const label propId,
91  bool header
92 ) const
93 {
94  // Only called with 3 or 4 points!
95 
96  if (header)
97  {
98  os << "*ELEMENT, TYPE=S" << f.size();
99 
100  if (propId >= 0)
101  {
102  os << ", ELSET=_" << propId;
103  }
104 
105  os << nl;
106  }
107 
108  writeConnectivity(os, elemId, f);
109 }
110 
111 
112 void Foam::surfaceWriters::abaqusWriter::writeGeometry
113 (
114  Ostream& os,
115  const meshedSurf& surf,
116  labelList& decompOffsets,
117  DynamicList<face>& decompFaces
118 ) const
119 {
120  const pointField& points = surf.points();
121  const faceList& faces = surf.faces();
122  const labelList& zones = surf.zoneIds();
123  const labelList& elemIds = surf.faceIds();
124 
125  // Possible to use faceIds?
126  bool useOrigFaceIds =
127  (
128  elemIds.size() == faces.size()
129  && !ListOps::found(elemIds, lessOp1<label>(0))
130  );
131 
132  if (useOrigFaceIds)
133  {
134  // Not possible with on-the-fly face decomposition
135  for (const auto& f : faces)
136  {
137  if (f.size() > 4)
138  {
139  useOrigFaceIds = false;
140  break;
141  }
142  }
143  }
144 
145 
146  os << "** Geometry" << nl;
147 
148  os << nl
149  << "**" << nl
150  << "** Points" << nl
151  << "**" << nl;
152 
154 
155 
156  // Write faces, with on-the-fly decomposition (triangulation)
157  decompOffsets.resize(faces.size()+1);
158  decompFaces.clear();
159 
160  decompOffsets[0] = 0; // The first offset is always zero
161 
162  os << "**" << nl
163  << "** Faces" << nl
164  << "**" << nl;
165 
166  // Simple tracking for change of element type/set
167  labelPair prevOutput(-1, -1);
168 
169  label elemId = 0; // The element-id
170  forAll(faces, facei)
171  {
172  const face& f = faces[facei];
173 
174  if (useOrigFaceIds)
175  {
176  // When available and not decomposed
177  elemId = elemIds[facei];
178  }
179 
180  // 1-offset for PID
181  const label propId = 1 + (facei < zones.size() ? zones[facei] : 0);
182 
183  const label n = f.size();
184 
185  bool header =
186  (prevOutput.first() != n || prevOutput.second() != propId);
187 
188  if (header)
189  {
190  // Update values
191  prevOutput.first() = n;
192  prevOutput.second() = propId;
193  }
194 
195  if (n == 3 || n == 4)
196  {
197  writeFace(os, f, ++elemId, propId, header);
198  }
199  else
200  {
201  // Decompose into tris
202  prevOutput.first() = 3;
203 
204  f.triangles(points, decompFaces);
205 
206  for
207  (
208  label decompi = decompOffsets[facei];
209  decompi < decompFaces.size();
210  ++decompi
211  )
212  {
213  writeFace
214  (
215  os,
216  decompFaces[decompi],
217  ++elemId,
218  propId,
219  header
220  );
221 
222  header = false;
223  }
224  }
225 
226  // The end offset, which is the next begin offset
227  decompOffsets[facei+1] = decompFaces.size();
228  }
229 
230  os << "**" << nl
231  << "**" << nl;
232 }
233 
234 
235 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
236 
238 :
240  noGeometry_(false),
241  outputLayout_(outputLayoutType::BY_FIELD)
242 {}
243 
244 
246 (
247  const dictionary& options
248 )
249 :
250  surfaceWriter(options),
251  noGeometry_(options.getOrDefault("noGeometry", false)),
252  outputLayout_(outputLayoutType::BY_FIELD)
253 {}
254 
255 
257 (
258  const meshedSurf& surf,
259  const fileName& outputPath,
260  bool parallel,
261  const dictionary& options
262 )
263 :
264  abaqusWriter(options)
265 {
266  open(surf, outputPath, parallel);
267 }
268 
269 
271 (
272  const pointField& points,
273  const faceList& faces,
274  const fileName& outputPath,
275  bool parallel,
276  const dictionary& options
277 )
278 :
279  abaqusWriter(options)
280 {
281  open(points, faces, outputPath, parallel);
282 }
283 
284 
285 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
286 
288 {
289  checkOpen();
290 
291  // Geometry:
292  // 1) rootdir/<TIME>/surfaceName.abq
293  // 2) rootdir/geometry/surfaceName_<TIME>.abq
294 
295  fileName outputFile;
296 
297  switch (outputLayout_)
298  {
299  case outputLayoutType::BY_TIME:
300  {
301  outputFile = outputPath_;
302  if (useTimeDir() && !timeName().empty())
303  {
304  // Splice in time-directory
305  outputFile =
306  outputPath_.path() / timeName() / outputPath_.name();
307  }
308  break;
309  }
310  case outputLayoutType::BY_FIELD:
311  {
312  outputFile = outputPath_ / "geometry" / outputPath_.name();
313  if (!timeName().empty())
314  {
315  // Append time information to file name
316  outputFile += '_' + timeName();
317  }
318  break;
319  }
320  }
321  outputFile.ext("abq");
322 
323  if (verbose_)
324  {
325  Info<< "Writing abaqus geometry to " << outputFile << endl;
326  }
327 
328 
329  // const meshedSurf& surf = surface();
330  const meshedSurfRef& surf = adjustSurface();
331 
332  if (UPstream::master() || !parallel_)
333  {
334  if (!isDir(outputFile.path()))
335  {
336  mkDir(outputFile.path());
337  }
338 
339  OFstream os(outputFile);
340 
341  labelList decompOffsets;
342  DynamicList<face> decompFaces;
343 
344  writeGeometry(os, surf, decompOffsets, decompFaces);
345  }
346 
347  wroteGeom_ = true;
348  return outputFile;
349 }
350 
351 
352 // ************************************************************************* //
A class for handling file names.
Definition: fileName.H:72
writer writeGeometry()
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition: ListOps.H:826
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:169
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:211
Macros for easy insertion into run-time selection tables.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:43
Various functions to operate on Lists.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: POSIX.C:860
List< face > faceList
List of faces.
Definition: faceListFwd.H:39
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
word timeName
Definition: getTimeIndex.H:3
static void writePoints(Ostream &os, const UList< point > &points, const scalar scaleFactor=1.0)
Write &#39;*NODE&#39; header and entries to file, optionally with scaling.
Definition: ABAQUSCore.C:782
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:38
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition: POSIX.C:614
const pointField & points
A class for handling words, derived from Foam::string.
Definition: word.H:63
defineSurfaceWriterWriteFields(Foam::surfaceWriters::abaqusWriter)
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.
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:192
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:51
OBJstream os(runTime.globalPath()/outputName)
labelList f(nPoints)
static void writeConnectivity(Ostream &os, const label elemId, const labelUList &elem)
Convenience macros for instantiating surfaceWriter methods.
defineTypeName(abaqusWriter)
A surface writer for the ABAQUS file format - both surface mesh and fields.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1082
messageStream Info
Information stream (stdout output on master, null elsewhere)
label n
virtual fileName write()
Write surface geometry to file.
Base class for surface writers.
List< label > labelList
A List of labels.
Definition: List.H:62
addToRunTimeSelectionTable(surfaceWriter, abaqusWriter, word)
Namespace for OpenFOAM.