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-------------------------------------------------------------------------------
10License
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
38namespace Foam
39{
40namespace surfaceWriters
41{
45}
46}
47
48// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
49
50// Field writing implementation
52
53// Field writing methods
55
56
57// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
58
59namespace Foam
60{
61
62// Write connectivity as CSV list
63inline 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
85void 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
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
153 fileFormats::ABAQUSCore::writePoints(os, points);
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 (Pstream::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// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
Various functions to operate on Lists.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
label n
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
writer writeGeometry()
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:72
Output to file stream, using an OSstream.
Definition: OFstream.H:57
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
void writeGeometry()
Write the mesh.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
A class for handling file names.
Definition: fileName.H:76
word ext() const
Return file name extension (part after last .)
Definition: fileNameI.H:218
static std::string path(const std::string &str)
Return directory path name (part before last /)
Definition: fileNameI.H:176
static std::string name(const std::string &str)
Return basename (part beyond last /), including its extension.
Definition: fileNameI.H:199
Implements a meshed surface by referencing another meshed surface or faces/points components.
Definition: meshedSurfRef.H:56
Abstract definition of a meshed surface defined by faces and points.
Definition: meshedSurf.H:50
splitCell * master() const
Definition: splitCell.H:113
Base class for surface writers.
virtual void open(const fileName &outputPath)
Open for output on specified path, using existing surface.
A surface writer for the ABAQUS file format - both surface mesh and fields.
virtual fileName write()
Write surface geometry to file.
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeName(Type)
Define the typeName.
Definition: className.H:96
OBJstream os(runTime.globalPath()/outputName)
const pointField & points
word timeName
Definition: getTimeIndex.H:3
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition: ListOps.H:679
Namespace for OpenFOAM.
Pair< label > labelPair
A pair of labels.
Definition: Pair.H:57
List< label > labelList
A List of labels.
Definition: List.H:66
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:515
messageStream Info
Information stream (stdout output on master, null elsewhere)
vectorField pointField
pointField is a vectorField.
Definition: pointFieldFwd.H:44
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
static void writeConnectivity(Ostream &os, const label elemId, const labelUList &elem)
List< face > faceList
A List of faces.
Definition: faceListFwd.H:47
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition: MSwindows.C:651
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
Convenience macros for instantiating surfaceWriter methods.
#define defineSurfaceWriterWriteFields(ThisClass)