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 -------------------------------------------------------------------------------
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 "ABAQUSsurfaceFormat.H"
29 #include "IFstream.H"
30 #include "IOmanip.H"
31 #include "faceTraits.H"
32 #include "stringOps.H"
33 
34 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
35 
36 template<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 
113 template<class Face>
115 (
116  const fileName& filename
117 )
118 {
119  read(filename);
120 }
121 
122 
123 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
124 
125 template<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 
158 
159  // Convert connectivity to faces
160 
161  DynamicList<Face> dynFaces(reader.connectivity_.size());
162 
163  for (labelList& conn : reader.connectivity_)
164  {
165  dynFaces.append(Face(std::move(conn)));
166  }
167 
168 
169  // Rationalize the zones (elset)
170 
171  // Only retain element sets that are actually used
172  labelHashSet elsetUsed(reader.elsetIds_);
173 
174  labelList newToOldZone(elsetUsed.sortedToc());
175 
176  // Extra safety
177  if (newToOldZone.empty())
178  {
179  newToOldZone.resize(1, Zero);
180  }
181 
182  Map<label> oldToNewZone(2*newToOldZone.size());
183 
184  forAll(newToOldZone, zonei)
185  {
186  oldToNewZone.set(newToOldZone[zonei], zonei);
187  }
188 
189  wordList zoneNames(newToOldZone.size());
190  labelList zoneSizes(newToOldZone.size(), Zero);
191 
192  forAllConstIters(reader.elsetMap_, iter)
193  {
194  const label zonei = oldToNewZone.lookup(iter.val(), -1);
195 
196  if (zonei >= 0)
197  {
198  zoneNames[zonei] = word::validate(iter.key());
199  }
200  }
201 
202  // No empty strings
203  forAll(zoneNames, zonei)
204  {
205  if (zoneNames[zonei].empty())
206  {
207  zoneNames[zonei] = surfZoneIdentifier::defaultName(zonei);
208  }
209  }
210 
211  // Steal the elset Ids for our zones
212  DynamicList<label> dynZones(std::move(reader.elsetIds_));
213 
214  // Renumber elset -> zoneId and increment the count
215  for (label& zonei : dynZones)
216  {
217  zonei = oldToNewZone.lookup(zonei, 0);
218 
219  ++zoneSizes[zonei];
220  }
221 
222 
223  // Transfer to normal lists
224  this->storedPoints().transfer(reader.points_);
225 
226  this->sortFacesAndStore
227  (
228  dynFaces,
229  dynZones,
230  reader.elemIds_,
231  true // sorted
232  );
233 
234  // Add zones (retaining empty ones)
235  this->addZones(zoneSizes, zoneNames);
236  this->addZonesToFaces(); // for labelledTri
237 
238  return true;
239 }
240 
241 
242 template<class Face>
244 (
245  const fileName& filename,
246  const MeshedSurfaceProxy<Face>& surf,
247  IOstreamOption streamOpt,
248  const dictionary&
249 )
250 {
251  // ASCII only, allow output compression
252  streamOpt.format(IOstream::ASCII);
253 
254  const UList<point>& pointLst = surf.points();
255  const UList<Face>& faceLst = surf.surfFaces();
256  const UList<label>& faceMap = surf.faceMap();
257  const UList<label>& elemIds = surf.faceIds();
258 
259  // for no zones, suppress the group name
260  const surfZoneList zones =
261  (
262  surf.surfZones().empty()
263  ? surfaceFormatsCore::oneZone(faceLst, "")
264  : surf.surfZones()
265  );
266 
267  const bool useFaceMap = (surf.useFaceMap() && zones.size() > 1);
268 
269  // Possible to use faceIds?
270  bool useOrigFaceIds =
271  (!useFaceMap && elemIds.size() == faceLst.size());
272 
273  if (useOrigFaceIds)
274  {
275  // Not possible with on-the-fly face decomposition
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 // ************************************************************************* //
Foam::Pair::second
const T & second() const noexcept
Return second element, which is also the last element.
Definition: PairI.H:122
Foam::faceMap
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
Definition: blockMeshMergeTopological.C:94
Foam::fileFormats::ABAQUSsurfaceFormat::read
virtual bool read(const fileName &filename)
Read from file.
Definition: ABAQUSsurfaceFormat.C:127
Foam::fileFormats::ABAQUSsurfaceFormat::write
static void write(const fileName &filename, const MeshedSurfaceProxy< Face > &surf, IOstreamOption streamOpt=IOstreamOption(), const dictionary &=dictionary::null)
Write surface mesh components by proxy.
Definition: ABAQUSsurfaceFormat.C:244
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::MeshedSurfaceProxy::useFaceMap
bool useFaceMap() const
Can/should use faceMap?
Definition: MeshedSurfaceProxy.H:203
Foam::Zero
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Foam::IFstream
Input from file stream, using an ISstream.
Definition: IFstream.H:85
Foam::DynamicList
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition: DynamicList.H:55
Foam::fileFormats::ABAQUSCore::readHelper::elemIds_
DynamicList< label > elemIds_
The 1-based abaqus Id for the element.
Definition: ABAQUSCore.H:332
validate
thermo validate(args.executable(), "h")
Foam::zone
Base class for mesh zones.
Definition: zone.H:63
Foam::IOstreamOption::format
streamFormat format() const noexcept
Get the current stream format.
Definition: IOstreamOption.H:289
Foam::fileFormats::ABAQUSCore::readHelper::read
void read(ISstream &is)
Read an abaqus input file.
Definition: ABAQUSCore.C:407
Foam::Map< label >
Foam::MeshedSurfaceProxy::points
const pointField & points() const
Return const access to the points.
Definition: MeshedSurfaceProxy.H:171
Foam::fileFormats::ABAQUSCore::readHelper::elsetMap_
HashTable< label, string > elsetMap_
Mapping of elem set names.
Definition: ABAQUSCore.H:341
Foam::HashSet< label, Hash< label > >
Foam::MeshedSurfaceProxy
A proxy for writing MeshedSurface, UnsortedMeshedSurface and surfMesh to various file formats.
Definition: MeshedSurface.H:82
Foam::MeshedSurfaceProxy::faceMap
const labelUList & faceMap() const
Const access to the faceMap, zero-sized when unused.
Definition: MeshedSurfaceProxy.H:191
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::fileFormats::ABAQUSCore::readHelper::compact_nodes
void compact_nodes()
Compact unused points and relabel connectivity.
Definition: ABAQUSCore.C:532
ABAQUSsurfaceFormat.H
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::fileFormats::ABAQUSCore::readHelper
Raw reader structure.
Definition: ABAQUSCore.H:307
Foam::DynamicList::append
DynamicList< T, SizeMin > & append(const T &val)
Append an element to the end of this list.
Definition: DynamicListI.H:472
Foam::IOstreamOption
The IOstreamOption is a simple container for options an IOstream can normally have.
Definition: IOstreamOption.H:63
IOmanip.H
Istream and Ostream manipulators taking arguments.
Foam::fileFormats::ABAQUSCore::readHelper::points_
DynamicList< point > points_
Locations of the points (nodes)
Definition: ABAQUSCore.H:318
Foam::defaultName
static const word defaultName("coeffs")
IFstream.H
Foam::List::resize
void resize(const label newSize)
Adjust allocated size of list.
Definition: ListI.H:139
Foam::blockMeshTools::read
void read(Istream &, label &, const dictionary &)
In-place read with dictionary lookup.
Definition: blockMeshTools.C:33
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::zone::name
const word & name() const
Return name.
Definition: zone.H:158
Foam::HashTable::sortedToc
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:136
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::OFstream
Output to file stream, using an OSstream.
Definition: OFstream.H:87
Foam::fileFormats::ABAQUSCore::readHelper::purge_solids
void purge_solids()
Remove non-shell elements and compact the points.
Definition: ABAQUSCore.C:506
Foam::fileFormats::ABAQUSsurfaceFormat::ABAQUSsurfaceFormat
ABAQUSsurfaceFormat()=default
Default construct.
Foam::MeshedSurfaceProxy::faceIds
const labelUList & faceIds() const
Const access to the faceIds, zero-sized when unused.
Definition: MeshedSurfaceProxy.H:197
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:372
Foam::fileFormats::ABAQUSCore::readHelper::elsetIds_
DynamicList< label > elsetIds_
The element set ids.
Definition: ABAQUSCore.H:338
clear
patchWriters clear()
Foam::nl
constexpr char nl
Definition: Ostream.H:385
Foam::Pair< label >
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
f
labelList f(nPoints)
Foam::List< label >
Foam::surfZone
A surface zone on a MeshedSurface.
Definition: surfZone.H:56
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::fileFormats::ABAQUSCore::readHelper::connectivity_
DynamicList< labelList > connectivity_
The element connectivity.
Definition: ABAQUSCore.H:329
Foam::UList::size
void size(const label n) noexcept
Override size to be inconsistent with allocated storage.
Definition: UListI.H:360
Foam::MeshedSurfaceProxy::surfFaces
const UList< Face > & surfFaces() const
Return const access to the faces.
Definition: MeshedSurfaceProxy.H:177
Foam::IOstream::good
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:224
Foam::fileFormats::ABAQUSsurfaceFormat
Abaqus surface reader.
Definition: ABAQUSsurfaceFormat.H:62
faceTraits.H
stringOps.H
Foam::MeshedSurfaceProxy::surfZones
const UList< surfZone > & surfZones() const
Const access to the surface zones.
Definition: MeshedSurfaceProxy.H:185