Loading...
Searching...
No Matches
ABAQUSsurfaceFormat.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-2024 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 "ABAQUSsurfaceFormat.H"
29#include "ListOps.H"
30#include "IFstream.H"
31#include "IOmanip.H"
32#include "faceTraits.H"
33
34// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35
36template<class Face>
37inline Foam::label Foam::fileFormats::ABAQUSsurfaceFormat<Face>::writeShell
38(
39 Ostream& os,
40 const Face& f,
41 label elemId,
42 const std::string& elsetName,
43 bool header
44)
45{
46 const label n = f.size();
47
48 if (n == 4)
49 {
50 if (header)
51 {
52 os << "*ELEMENT, TYPE=S4";
53
54 if (!elsetName.empty())
55 {
56 os << ", ELSET=" << elsetName;
57 }
58 os << nl;
59 }
60
61 os << " "
62 << (++elemId) << ','
63 << (f[0] + 1) << ','
64 << (f[1] + 1) << ','
65 << (f[2] + 1) << ','
66 << (f[3] + 1) << nl;
67 }
68 else
69 {
70 if (header)
71 {
72 os << "*ELEMENT, TYPE=S3";
73
74 if (!elsetName.empty())
75 {
76 os << ", ELSET=" << elsetName;
77 }
78 os << nl;
79 }
80
81 if (n == 3)
82 {
83 os << " "
84 << (++elemId) << ','
85 << (f[0] + 1) << ','
86 << (f[1] + 1) << ','
87 << (f[2] + 1) << nl;
88 }
89 else
90 {
91 // simple triangulation about f[0].
92 // better triangulation should have been done before
93
94 for (label fp1 = 1; fp1 < f.size() - 1; ++fp1)
95 {
96 const label fp2 = f.fcIndex(fp1);
97
98 os << " "
99 << (++elemId) << ','
100 << (f[0] + 1) << ','
101 << (f[fp1] + 1) << ','
102 << (f[fp2] + 1) << nl;
103 }
104 }
105 }
106
107 return elemId;
108}
109
110
111// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112
113template<class Face>
115(
116 const fileName& filename
117)
118{
119 read(filename);
120}
121
122
123// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
124
125template<class Face>
127(
128 const fileName& filename
129)
130{
131 // Clear everything
132 this->clear();
133
134 IFstream is(filename);
135 if (!is.good())
136 {
138 << "Cannot read file " << filename << nl
139 << exit(FatalError);
140 }
141
142
143 #ifdef FULLDEBUG
144 ABAQUSCore::readHelper reader(true); // Debugging verbosity
145 #else
146 ABAQUSCore::readHelper reader;
147 #endif
148
149
150 reader.read(is);
151
152 // This needs more work
153
154 // No solids
155 reader.purge_solids();
156 reader.compact_nodes();
157 reader.renumber_elements_1to0(); // Convert 1-based -> 0-based
158
159
160 // Convert connectivity to faces
161
162 DynamicList<Face> dynFaces(reader.connectivity_.size());
163
164 for (labelList& conn : reader.connectivity_)
165 {
166 dynFaces.append(Face(std::move(conn)));
167 }
168
169
170 // Rationalize the zones (elset)
171
172 // Only retain element sets that are actually used
173 labelHashSet elsetUsed(reader.elsetIds_);
174
175 labelList newToOldZone(elsetUsed.sortedToc());
176
177 // Extra safety
178 if (newToOldZone.empty())
179 {
180 newToOldZone.push_back(0);
181 }
182
183 wordList zoneNames(newToOldZone.size());
184 labelList zoneSizes(newToOldZone.size(), Foam::zero{});
185
186 Map<label> oldToNewZone(invertToMap(newToOldZone));
187
188 forAllConstIters(reader.elsetMap_, iter)
189 {
190 const label zonei = oldToNewZone.lookup(iter.val(), -1);
191
192 if (zonei >= 0)
193 {
194 zoneNames[zonei] = word::validate(iter.key());
195 }
196 }
197
198 // No empty strings
199 forAll(zoneNames, zonei)
200 {
201 if (zoneNames[zonei].empty())
202 {
203 zoneNames[zonei] = surfZoneIdentifier::defaultName(zonei);
204 }
205 }
206
207 // Steal the elset Ids for our zones
208 DynamicList<label> dynZones(std::move(reader.elsetIds_));
209
210 // Renumber elset -> zoneId and increment the count
211 for (label& zonei : dynZones)
212 {
213 zonei = oldToNewZone.lookup(zonei, 0);
214
215 ++zoneSizes[zonei];
216 }
217
218
219 // Transfer to normal lists
220 this->storedPoints().transfer(reader.points_);
221
222 this->sortFacesAndStore
223 (
224 dynFaces,
225 dynZones,
226 reader.elemIds_,
227 true // sorted
228 );
229
230 // Add zones (retaining empty ones)
231 this->addZones(zoneSizes, zoneNames);
232 this->addZonesToFaces(); // for labelledTri
233
234 return true;
235}
236
237
238template<class Face>
240(
241 const fileName& filename,
242 const MeshedSurfaceProxy<Face>& surf,
243 IOstreamOption streamOpt,
244 const dictionary&
245)
246{
247 // ASCII only, allow output compression
248 streamOpt.format(IOstreamOption::ASCII);
249
250 const UList<point>& pointLst = surf.points();
251 const UList<Face>& faceLst = surf.surfFaces();
252 const UList<label>& faceMap = surf.faceMap();
253 const UList<label>& elemIds = surf.faceIds();
254
255 // for no zones, suppress the group name
256 const surfZoneList zones
257 (
258 surf.surfZones().empty()
259 ? surfaceFormatsCore::oneZone(faceLst, "")
260 : surf.surfZones()
261 );
262
263 const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
264
265 // Possible to use faceIds?
266 // - cannot if there are negative ids (eg, encoded solid/side)
267 bool useOrigFaceIds =
268 (
269 !useFaceMap
270 && elemIds.size() == faceLst.size()
271 && !ListOps::found(elemIds, lessOp1<label>(0))
272 );
273
274 // Not possible with on-the-fly face decomposition
275 if (useOrigFaceIds)
276 {
277 for (const auto& f : faceLst)
278 {
279 if (f.size() > 4)
280 {
281 useOrigFaceIds = false;
282 break;
283 }
284 }
285 }
286
287
288 OFstream os(filename, streamOpt);
289 if (!os.good())
290 {
292 << "Cannot write file " << filename << nl
293 << exit(FatalError);
294 }
295
296
297 os << "*HEADING" << nl;
298
299 os << nl
300 << "**" << nl
301 << "** Points" << nl
302 << "**" << nl;
303
304 writePoints(os, pointLst);
305
306 os << "**" << nl
307 << "** Faces" << nl
308 << "**" << nl
309 << nl;
310
311
312 // Simple tracking for change of element type/set
313 labelPair prevOutput(-1, -1);
314
315 label faceIndex = 0;
316 label zoneIndex = 0;
317 label elemId = 0;
318
319 for (const surfZone& zone : zones)
320 {
321 for (label nLocal = zone.size(); nLocal--; ++faceIndex)
322 {
323 const label facei =
324 (useFaceMap ? faceMap[faceIndex] : faceIndex);
325
326 const Face& f = faceLst[facei];
327
328 if (useOrigFaceIds)
329 {
330 elemId = elemIds[facei];
331 }
332
333 const label n = f.size();
334
335 bool header =
336 (prevOutput.first() != n || prevOutput.second() != zoneIndex);
337
338 if (header)
339 {
340 // Update values
341 prevOutput.first() = n;
342 prevOutput.second() = zoneIndex;
343 }
344
345 elemId = writeShell(os, f, elemId, zone.name(), header);
346 }
347
348 ++zoneIndex;
349 }
350
351 os << "**" << nl
352 << "**" << nl;
353}
354
355
356// ************************************************************************* //
Istream and Ostream manipulators taking arguments.
Various functions to operate on Lists.
label n
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void append(const T &val)
Copy append an element to the end of this list.
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition HashTable.C:156
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition HashTableI.H:222
Input from file stream as an ISstream, normally using std::ifstream for the actual input.
Definition IFstream.H:55
A simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
@ ASCII
"ascii" (normal default)
bool good() const noexcept
True if next operation might succeed.
Definition IOstream.H:281
void push_back(const T &val)
Append an element at the end of the list.
Definition ListI.H:221
A HashTable to objects of type <T> with a label key.
Definition Map.H:54
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const UList< surfZone > & surfZones() const noexcept
Const access to the surface zones.
const UList< Face > & surfFaces() const noexcept
Return const access to the faces.
const labelUList & faceIds() const noexcept
Const access to the faceIds, zero-sized when unused.
const labelUList & faceMap() const noexcept
Const access to the faceMap, zero-sized when unused.
const pointField & points() const noexcept
Return const access to the points.
bool useFaceMap() const noexcept
Can/should use faceMap?
pointField & storedPoints()
Non-const access to global points.
virtual void addZones(const UList< surfZone > &, const bool cullEmpty=false)
Add surface zones.
void sortFacesAndStore(DynamicList< Face > &unsortedFaces, DynamicList< label > &zoneIds, DynamicList< label > &elemIds, bool sorted)
Sort faces by zones and store sorted faces.
bool addZonesToFaces()
Propagate zone information on face regions.
Output to file stream as an OSstream, normally using std::ofstream for the actual output.
Definition OFstream.H:75
const T & first() const noexcept
Access the first element.
Definition Pair.H:137
const T & second() const noexcept
Access the second element.
Definition Pair.H:147
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
static void writePoints(Ostream &os, const UList< point > &points, const scalar scaleFactor=1.0)
Write '*NODE' header and entries to file, optionally with scaling.
Definition ABAQUSCore.C:782
ABAQUSsurfaceFormat()=default
Default construct.
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components (by proxy) in ABAQUS format.
virtual bool read(const fileName &filename) override
Read from file.
static List< surfZone > oneZone(const Container &container, const word &name="zone0")
Return a surfZone list with a single entry, the size of which corresponds to that of the container.
A class for handling file names.
Definition fileName.H:75
static word defaultName(const label n=-1)
Default zone name: "zone" or "zoneN".
A surface zone on a MeshedSurface.
Definition surfZone.H:55
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
const word & name() const noexcept
The zone name.
Base class for mesh zones.
Definition zone.H:63
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
surface1 clear()
bool found(const ListType &input, const UnaryPredicate &pred, const label start=0)
Same as found_if.
Definition ListOps.H:886
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Pair< label > labelPair
A pair of labels.
Definition Pair.H:54
List< word > wordList
List of word.
Definition fileName.H:60
Map< label > invertToMap(const labelUList &values)
Create inverse mapping, which is a lookup table into the given list.
Definition ListOps.C:105
List< label > labelList
A List of labels.
Definition List.H:62
HashSet< label, Hash< label > > labelHashSet
A HashSet of labels, uses label hasher.
Definition HashSet.H:85
List< surfZone > surfZoneList
List of surfZone.
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
labelList f(nPoints)
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition stdFoam.H:235
DynamicList< label > elemIds_
The 1-based abaqus Id for the element.
Definition ABAQUSCore.H:417
DynamicList< point > points_
Locations of the points (nodes).
Definition ABAQUSCore.H:396
HashTable< label, string > elsetMap_
Mapping of elem set names.
Definition ABAQUSCore.H:432
void renumber_elements_1to0()
Renumber elements from 1-based to 0-based.
Definition ABAQUSCore.C:772
void read(ISstream &is)
Read an abaqus input file.
Definition ABAQUSCore.C:525
DynamicList< labelList > connectivity_
The element connectivity.
Definition ABAQUSCore.H:412
void purge_solids()
Remove non-shell elements and compact the points.
Definition ABAQUSCore.C:652
DynamicList< label > elsetIds_
The element set ids.
Definition ABAQUSCore.H:427
void compact_nodes()
Compact unused points and relabel connectivity.
Definition ABAQUSCore.C:678