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 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>
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
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.resize(1, Zero);
181 }
182
183 Map<label> oldToNewZone(2*newToOldZone.size());
184
185 forAll(newToOldZone, zonei)
186 {
187 oldToNewZone.set(newToOldZone[zonei], zonei);
188 }
189
190 wordList zoneNames(newToOldZone.size());
191 labelList zoneSizes(newToOldZone.size(), Zero);
192
193 forAllConstIters(reader.elsetMap_, iter)
194 {
195 const label zonei = oldToNewZone.lookup(iter.val(), -1);
196
197 if (zonei >= 0)
198 {
199 zoneNames[zonei] = word::validate(iter.key());
200 }
201 }
202
203 // No empty strings
204 forAll(zoneNames, zonei)
205 {
206 if (zoneNames[zonei].empty())
207 {
208 zoneNames[zonei] = surfZoneIdentifier::defaultName(zonei);
209 }
210 }
211
212 // Steal the elset Ids for our zones
213 DynamicList<label> dynZones(std::move(reader.elsetIds_));
214
215 // Renumber elset -> zoneId and increment the count
216 for (label& zonei : dynZones)
217 {
218 zonei = oldToNewZone.lookup(zonei, 0);
219
220 ++zoneSizes[zonei];
221 }
222
223
224 // Transfer to normal lists
225 this->storedPoints().transfer(reader.points_);
226
227 this->sortFacesAndStore
228 (
229 dynFaces,
230 dynZones,
231 reader.elemIds_,
232 true // sorted
233 );
234
235 // Add zones (retaining empty ones)
236 this->addZones(zoneSizes, zoneNames);
237 this->addZonesToFaces(); // for labelledTri
238
239 return true;
240}
241
242
243template<class Face>
245(
246 const fileName& filename,
247 const MeshedSurfaceProxy<Face>& surf,
248 IOstreamOption streamOpt,
249 const dictionary&
250)
251{
252 // ASCII only, allow output compression
253 streamOpt.format(IOstream::ASCII);
254
255 const UList<point>& pointLst = surf.points();
256 const UList<Face>& faceLst = surf.surfFaces();
257 const UList<label>& faceMap = surf.faceMap();
258 const UList<label>& elemIds = surf.faceIds();
259
260 // for no zones, suppress the group name
261 const surfZoneList zones =
262 (
263 surf.surfZones().empty()
264 ? surfaceFormatsCore::oneZone(faceLst, "")
265 : surf.surfZones()
266 );
267
268 const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
269
270 // Possible to use faceIds?
271 // - cannot if there are negative ids (eg, encoded solid/side)
272 bool useOrigFaceIds =
273 (
274 !useFaceMap
275 && elemIds.size() == faceLst.size()
276 && !ListOps::found(elemIds, lessOp1<label>(0))
277 );
278
279 // Not possible with on-the-fly face decomposition
280 if (useOrigFaceIds)
281 {
282 for (const auto& f : faceLst)
283 {
284 if (f.size() > 4)
285 {
286 useOrigFaceIds = false;
287 break;
288 }
289 }
290 }
291
292
293 OFstream os(filename, streamOpt);
294 if (!os.good())
295 {
297 << "Cannot write file " << filename << nl
298 << exit(FatalError);
299 }
300
301
302 os << "*HEADING" << nl;
303
304 os << nl
305 << "**" << nl
306 << "** Points" << nl
307 << "**" << nl;
308
309 writePoints(os, pointLst);
310
311 os << "**" << nl
312 << "** Faces" << nl
313 << "**" << nl
314 << nl;
315
316
317 // Simple tracking for change of element type/set
318 labelPair prevOutput(-1, -1);
319
320 label faceIndex = 0;
321 label zoneIndex = 0;
322 label elemId = 0;
323
324 for (const surfZone& zone : zones)
325 {
326 for (label nLocal = zone.size(); nLocal--; ++faceIndex)
327 {
328 const label facei =
329 (useFaceMap ? faceMap[faceIndex] : faceIndex);
330
331 const Face& f = faceLst[facei];
332
333 if (useOrigFaceIds)
334 {
335 elemId = elemIds[facei];
336 }
337
338 const label n = f.size();
339
340 bool header =
341 (prevOutput.first() != n || prevOutput.second() != zoneIndex);
342
343 if (header)
344 {
345 // Update values
346 prevOutput.first() = n;
347 prevOutput.second() = zoneIndex;
348 }
349
350 elemId = writeShell(os, f, elemId, zone.name(), header);
351 }
352
353 ++zoneIndex;
354 }
355
356 os << "**" << nl
357 << "**" << nl;
358}
359
360
361// ************************************************************************* //
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:72
void append(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:503
T & first() noexcept
The first element of the list, position [0].
Definition: FixedListI.H:207
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:137
bool set(const Key &key, const T &obj)
Copy assign a new entry, overwriting existing entries.
Definition: HashTableI.H:202
const T & lookup(const Key &key, const T &deflt) const
Return hashed entry if it exists, or return the given default.
Definition: HashTableI.H:224
Input from file stream, using an ISstream.
Definition: IFstream.H:57
The IOstreamOption is a simple container for options an IOstream can normally have.
streamFormat format() const noexcept
Get the current stream format.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
void transfer(List< T > &list)
Definition: List.C:447
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:139
A HashTable to objects of type <T> with a label key.
Definition: Map.H:60
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
const UList< surfZone > & surfZones() const
Const access to the surface zones.
const UList< Face > & surfFaces() const
Return const access to the faces.
bool useFaceMap() const
Can/should use faceMap?
const labelUList & faceIds() const
Const access to the faceIds, zero-sized when unused.
const pointField & points() const
Return const access to the points.
const labelUList & faceMap() const
Const access to the faceMap, zero-sized when unused.
Output to file stream, using an OSstream.
Definition: OFstream.H:57
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:120
virtual bool read()
Re-read model coefficients if they have changed.
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:94
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
ABAQUSsurfaceFormat()=default
Default construct.
A class for handling file names.
Definition: fileName.H:76
virtual bool write()
Write the output fields.
A surface zone on a MeshedSurface.
Definition: surfZone.H:59
const word & name() const noexcept
The zone name.
Base class for mesh zones.
Definition: zone.H:67
patchWriters clear()
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
OBJstream os(runTime.globalPath()/outputName)
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
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
#define forAllConstIters(container, iter)
Iterate across all elements of the container object with const access.
Definition: stdFoam.H:278
DynamicList< label > elemIds_
The 1-based abaqus Id for the element.
Definition: ABAQUSCore.H:382
DynamicList< point > points_
Locations of the points (nodes)
Definition: ABAQUSCore.H:368
HashTable< label, string > elsetMap_
Mapping of elem set names.
Definition: ABAQUSCore.H:391
void renumber_elements_1to0()
Renumber elements from 1-based to 0-based.
Definition: ABAQUSCore.C:778
void read(ISstream &is)
Read an abaqus input file.
Definition: ABAQUSCore.C:531
DynamicList< labelList > connectivity_
The element connectivity.
Definition: ABAQUSCore.H:379
void purge_solids()
Remove non-shell elements and compact the points.
Definition: ABAQUSCore.C:658
DynamicList< label > elsetIds_
The element set ids.
Definition: ABAQUSCore.H:388
void compact_nodes()
Compact unused points and relabel connectivity.
Definition: ABAQUSCore.C:684