GTSsurfaceFormat.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) 2011-2016 OpenFOAM Foundation
9 Copyright (C) 2016-2020 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
12 This file is part of OpenFOAM.
13
14 OpenFOAM is free software: you can redistribute it and/or modify it
15 under the terms of the GNU General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18
19 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26
27\*---------------------------------------------------------------------------*/
28
29#include "GTSsurfaceFormat.H"
30#include "surfaceFormatsCore.H"
31#include "clock.H"
32#include "Fstream.H"
33#include "StringStream.H"
34#include "faceTraits.H"
35
36// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37
38template<class Face>
40(
41 const UList<Face>& faceLst
42)
43{
44 label nNonTris = 0;
45
46 if (!faceTraits<Face>::isTri())
47 {
48 for (const auto& f : faceLst)
49 {
50 if (f.size() != 3)
51 {
52 ++nNonTris;
53 }
54 }
55 }
56
57 if (nNonTris)
58 {
60 << "Surface has " << nNonTris << '/' << faceLst.size()
61 << " non-triangulated faces - not writing!" << endl;
62 }
63
64 return nNonTris == 0;
65}
66
67
68
69// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
70
71template<class Face>
73(
74 const fileName& filename
75)
76{
77 read(filename);
78}
79
80
81// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
82
83template<class Face>
85(
86 const fileName& filename
87)
88{
89 // Clear everything
90 this->clear();
91
92 IFstream is(filename);
93 if (!is.good())
94 {
96 << "Cannot read file " << filename << nl
97 << exit(FatalError);
98 }
99
100 // Read header
101 string line = this->getLineNoComment(is);
102
103 label nPoints, nEdges, nElems;
104 {
105 IStringStream lineStream(line);
106 lineStream
107 >> nPoints
108 >> nEdges
109 >> nElems;
110 }
111
112
113 // Write directly into the lists
114 auto& pointLst = this->storedPoints();
115 auto& faceLst = this->storedFaces();
116 auto& zoneIds = this->storedZoneIds();
117
118 pointLst.resize(nPoints);
119 faceLst.resize(nElems);
120 zoneIds.resize(nElems);
121
122 // Read points
123 forAll(pointLst, pointi)
124 {
125 scalar x, y, z;
126 line = this->getLineNoComment(is);
127 {
128 IStringStream lineStream(line);
129 lineStream
130 >> x >> y >> z;
131 }
132
133 pointLst[pointi] = point(x, y, z);
134 }
135
136 // Read edges (OpenFOAM indexing)
137 edgeList edges(nEdges);
138 forAll(edges, edgei)
139 {
140 label beg, end;
141 line = this->getLineNoComment(is);
142 {
143 IStringStream lineStream(line);
144 lineStream
145 >> beg >> end;
146 }
147 edges[edgei] = edge(beg - 1, end - 1);
148 }
149
150
151 // Read triangles. Convert references to edges into pointlabels
152 label maxZone = 0;
153 forAll(faceLst, facei)
154 {
155 label e0Label, e1Label, e2Label;
156 label zoneI = 0;
157
158 line = this->getLineNoComment(is);
159 {
160 IStringStream lineStream(line);
161 lineStream
162 >> e0Label >> e1Label >> e2Label;
163
164 // Optional zone number: read first, then check stream state
165 if (lineStream)
166 {
167 label num;
168 lineStream >> num;
169 if (!lineStream.bad())
170 {
171 zoneI = num;
172 if (maxZone < zoneI)
173 {
174 maxZone = zoneI;
175 }
176 }
177 }
178 }
179
180 // Determine ordering of edges e0, e1
181 // common: common vertex, shared by e0 and e1
182 // e0Far: vertex on e0 which is not common
183 // e1Far: vertex on e1 which is not common
184 const edge& e0 = edges[e0Label - 1];
185 const edge& e1 = edges[e1Label - 1];
186 const edge& e2 = edges[e2Label - 1];
187
188 label common01 = e0.commonVertex(e1);
189 if (common01 == -1)
190 {
192 << "Edges 0 and 1 of triangle " << facei
193 << " do not share a point.\n"
194 << " edge0:" << e0 << nl
195 << " edge1:" << e1
196 << exit(FatalError);
197 }
198
199 const label e0Far = e0.otherVertex(common01);
200 const label e1Far = e1.otherVertex(common01);
201
202 const label common12 = e1.commonVertex(e2);
203 if (common12 == -1)
204 {
206 << "Edges 1 and 2 of triangle " << facei
207 << " do not share a point.\n"
208 << " edge1:" << e1 << nl
209 << " edge2:" << e2
210 << exit(FatalError);
211 }
212 const label e2Far = e2.otherVertex(common12);
213
214 // Does edge2 sit between edge1 and 0?
215 if (common12 != e1Far || e2Far != e0Far)
216 {
218 << "Edges of triangle " << facei
219 << " reference more than three points.\n"
220 << " edge0:" << e0 << nl
221 << " edge1:" << e1 << nl
222 << " edge2:" << e2 << nl
223 << exit(FatalError);
224 }
225
226 faceLst[facei] = Face{e0Far, common01, e1Far};
227 zoneIds[facei] = zoneI;
228 }
229
230
231 List<surfZoneIdentifier> newZones(maxZone+1);
232 forAll(newZones, zonei)
233 {
234 newZones[zonei] = surfZoneIdentifier
235 (
236 surfZoneIdentifier::defaultName(zonei),
237 zonei
238 );
239 }
240
241 this->storedZoneToc().transfer(newZones);
242 this->addZonesToFaces(); // for labelledTri
243
244 return true;
245}
246
247
248template<class Face>
250(
251 const fileName& filename,
252 const MeshedSurface<Face>& surf,
253 IOstreamOption streamOpt,
254 const dictionary&
255)
256{
257 // ASCII only, allow output compression
258 streamOpt.format(IOstream::ASCII);
259
260 const UList<point>& pointLst = surf.points();
261 const UList<Face>& faceLst = surf.surfFaces();
262
263 const surfZoneList zones =
264 (
265 surf.surfZones().size()
266 ? surf.surfZones()
267 : surfaceFormatsCore::oneZone(faceLst)
268 );
269
270 checkIfTriangulated(faceLst);
271
272 OFstream os(filename, streamOpt);
273 if (!os.good())
274 {
276 << "Cannot write file " << filename << nl
277 << exit(FatalError);
278 }
279
280
281 // Write header, print zone names as comment
282 os << "# GTS file" << nl
283 << "# Zones:" << nl;
284
285 forAll(zones, zonei)
286 {
287 os << "# " << zonei << " "
288 << zones[zonei].name() << nl;
289 }
290 os << "#" << nl;
291
292 os << "# nPoints nEdges nTriangles" << nl
293 << pointLst.size() << ' ' << surf.nEdges() << ' '
294 << surf.size() << nl;
295
296
297 // Write vertex coords
298 for (const point& pt : pointLst)
299 {
300 os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
301 }
302
303
304 // Write edges.
305 // Note: edges are in local point labels so convert
306 const edgeList& es = surf.edges();
307 const labelList& meshPts = surf.meshPoints();
308
309 for (const edge& e : es)
310 {
311 os << meshPts[e.start()] + 1 << ' '
312 << meshPts[e.end()] + 1 << nl;
313 }
314
315 // Write faces in terms of edges
316 const labelListList& faceEs = surf.faceEdges();
317
318 label faceIndex = 0;
319 label zoneIndex = 0;
320
321 for (const surfZone& zone : zones)
322 {
323 for (label nLocal = zone.size(); nLocal--; ++faceIndex)
324 {
325 const label facei = faceIndex;
326
327 const labelList& fEdges = faceEs[facei];
328
329 os << fEdges[0] + 1 << ' '
330 << fEdges[1] + 1 << ' '
331 << fEdges[2] + 1 << ' '
332 << zoneIndex << nl;
333 }
334
335 ++zoneIndex;
336 }
337}
338
339
340template<class Face>
342(
343 const fileName& filename,
344 const UnsortedMeshedSurface<Face>& surf,
345 IOstreamOption streamOpt,
346 const dictionary&
347)
348{
349 // ASCII only, allow output compression
350 streamOpt.format(IOstream::ASCII);
351
352 const UList<point>& pointLst = surf.points();
353 const UList<Face>& faceLst = surf.surfFaces();
354 const UList<label>& zoneIds = surf.zoneIds();
355 const UList<surfZoneIdentifier>& zoneToc = surf.zoneToc();
356
357 checkIfTriangulated(faceLst);
358
359 OFstream os(filename, streamOpt);
360 if (!os.good())
361 {
363 << "Cannot write file " << filename << nl
364 << exit(FatalError);
365 }
366
367
368 // Write header, print zone names as comment
369 os << "# GTS file" << nl
370 << "# Zones:" << nl;
371
372 forAll(zoneToc, zonei)
373 {
374 os << "# " << zonei << " "
375 << zoneToc[zonei].name() << nl;
376 }
377 os << "#" << nl;
378
379 os << "# nPoints nEdges nTriangles" << nl
380 << pointLst.size() << ' ' << surf.nEdges() << ' '
381 << surf.size() << nl;
382
383
384 // Write vertex coords
385 for (const point& pt : pointLst)
386 {
387 os << pt.x() << ' ' << pt.y() << ' ' << pt.z() << nl;
388 }
389
390
391 // Write edges.
392 // Note: edges are in local point labels so convert
393 const edgeList& es = surf.edges();
394 const labelList& meshPts = surf.meshPoints();
395
396 for (const edge& e : es)
397 {
398 os << meshPts[e.start()] + 1 << ' '
399 << meshPts[e.end()] + 1 << nl;
400 }
401
402 // Write faces in terms of edges.
403 const labelListList& faceEs = surf.faceEdges();
404
405 forAll(faceLst, facei)
406 {
407 const labelList& fEdges = faceEs[facei];
408
409 os << fEdges[0] + 1 << ' '
410 << fEdges[1] + 1 << ' '
411 << fEdges[2] + 1 << ' '
412 << zoneIds[facei] << nl;
413 }
414}
415
416
417// ************************************************************************* //
scalar y
Input/output from string buffers.
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
bool bad() const noexcept
True if stream is corrupted.
Definition: IOstream.H:251
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:112
A surface geometry mesh with zone information, not to be confused with the similarly named surfaceMes...
Definition: MeshedSurface.H:99
const surfZoneList & surfZones() const
Const access to the surface zones.
label size() const
The surface size is the number of faces.
const List< Face > & surfFaces() const
Return const access to the faces.
Output to file stream, using an OSstream.
Definition: OFstream.H:57
label nEdges() const
Number of edges in patch.
const edgeList & edges() const
Return list of edges, address into LOCAL point list.
const labelList & meshPoints() const
Return labelList of mesh points in patch.
const Field< point_type > & points() const noexcept
Return reference to global points.
const labelListList & faceEdges() const
Return face-edge addressing.
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
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A surface geometry mesh, in which the surface zone information is conveyed by the 'zoneId' associated...
virtual const labelList & zoneIds() const
Return const access to the zone ids.
label size() const
The surface size is the number of faces.
const List< surfZoneIdentifier > & zoneToc() const
Return const access to the zone table-of-contents.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:66
label otherVertex(const label pointLabel) const
Given the point label for one vertex, return the other one.
Definition: edgeI.H:188
label commonVertex(const edge &other) const
Return vertex common with other edge or -1 on failure.
Definition: edgeI.H:172
A class for handling file names.
Definition: fileName.H:76
virtual bool write()
Write the output fields.
A line primitive.
Definition: line.H:68
Identifies a surface patch/zone by name and index, with optional geometric type.
A surface zone on a MeshedSurface.
Definition: surfZone.H:59
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)
const labelList nEdges(UPstream::listGatherValues< label >(aMesh.nEdges()))
label nPoints
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
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)
volScalarField & e
Definition: createFields.H:11
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333