minor correction to prevsious commit
[OpenFOAM-1.5.x.git] / src / triSurface / triSurface / interfaces / NAS / readNAS.C
blob5ca2c3112301ee0fc5d0f4be02cf8b04a32f823e
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software; you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation; either version 2 of the License, or (at your
14     option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM; if not, write to the Free Software Foundation,
23     Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 Description
26     Nastran surface reader.
28     - Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions
29       to obtain patch names.
30     - Handles Nastran short and long formats, but not free format.
31     - Properly handles the Nastran compact floating point notation: \n
32     @verbatim
33         GRID          28        10.20269-.030265-2.358-8
34     @endverbatim
37 \*---------------------------------------------------------------------------*/
39 #include "triSurface.H"
40 #include "IFstream.H"
41 #include "IStringStream.H"
43 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 namespace Foam
48 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
50 // Do weird things to extract number
51 static scalar parseNASCoord(const string& s)
53     size_t expSign = s.find_last_of("+-");
55     if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1]))
56     {
57         scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))());
58         scalar exponent = readScalar(IStringStream(s.substr(expSign+1))());
60         if (s[expSign] == '-')
61         {
62             exponent = -exponent;
63         }
64         return mantissa*pow(10, exponent);
65     }
66     else
67     {
68         return readScalar(IStringStream(s)());
69     }
73 bool triSurface::readNAS(const fileName& fName)
75     IFstream is(fName);
77     if (!is.good())
78     {
79         FatalErrorIn("triSurface::readNAS(const fileName&)")
80             << "Cannot read file " << fName
81             << exit(FatalError);
82     }
84     // coordinates of point
85     DynamicList<point> points;
86     // Nastran index of point
87     DynamicList<label> indices;
88     // Faces in terms of Nastran point indices
89     DynamicList<labelledTri> faces;
90     // From face group to patch
91     Map<label> groupToPatch;
92     label nPatches = 0;
93     // Name for face group
94     Map<word> groupToName;
96     // Ansa tags. Denoted by $ANSA_NAME. These will appear just before the
97     // first use of a type. We read them and store the pshell types which
98     // are used to name the patches.
99     label ansaId = -1;
100     word ansaType;
101     string ansaName;
103     // A single warning per unrecognized command
104     HashSet<word> unhandledCmd;
106     while (is.good())
107     {
108         string line;
109         is.getLine(line);
111         // Ansa extension
112         if (line.substr(0, 10) == "$ANSA_NAME")
113         {
114             string::size_type sem0 = line.find (';', 0);
115             string::size_type sem1 = line.find (';', sem0+1);
116             string::size_type sem2 = line.find (';', sem1+1);
118             if
119             (
120                 sem0 != string::npos
121              && sem1 != string::npos
122              && sem2 != string::npos
123             )
124             {
125                 ansaId = readLabel
126                 (
127                     IStringStream(line.substr(sem0+1, sem1-sem0-1))()
128                 );
129                 ansaType = line.substr(sem1+1, sem2-sem1-1);
131                 string nameString;
132                 is.getLine(ansaName);
133                 if (ansaName[ansaName.size()-1] == '\r')
134                 {
135                     ansaName = ansaName.substr(1, ansaName.size()-2);
136                 }
137                 else
138                 {
139                     ansaName = ansaName.substr(1, ansaName.size()-1);
140                 }
142                 // Info<< "ANSA tag for NastranID:" << ansaId
143                 //     << " of type " << ansaType
144                 //     << " name " << ansaName << endl;
145             }
146         }
149         // Hypermesh extension
150         // $HMNAME COMP                   1"partName"
151         if
152         (
153             line.substr(0, 12) == "$HMNAME COMP"
154          && line.find ('"') != string::npos
155         )
156         {
157             label groupId = readLabel
158             (
159                 IStringStream(line.substr(16, 16))()
160             );
162             IStringStream lineStream(line.substr(32));
164             string rawName;
165             lineStream >> rawName;
167             groupToName.insert(groupId, string::validate<word>(rawName));
168             Info<< "group " << groupId << " => " << rawName << endl;
169         }
172         if (line.size() == 0 || line[0] == '$')
173         {
174             // Skip empty or comment
175             continue;
176         }
178         // Check if character 72 is continuation
179         if (line.size() > 72 && line[72] == '+')
180         {
181             line = line.substr(0, 72);
183             while (true)
184             {
185                 string buf;
186                 is.getLine(buf);
188                 if (buf.size() > 72 && buf[72]=='+')
189                 {
190                     line += buf.substr(8, 64);
191                 }
192                 else
193                 {
194                     line += buf.substr(8, buf.size()-8);
195                     break;
196                 }
197             }
198         }
200         // Read first word
201         IStringStream lineStream(line);
202         word cmd;
203         lineStream >> cmd;
205         if (cmd == "CTRIA3")
206         {
207             label groupId = readLabel(IStringStream(line.substr(16,8))());
208             label a = readLabel(IStringStream(line.substr(24,8))());
209             label b = readLabel(IStringStream(line.substr(32,8))());
210             label c = readLabel(IStringStream(line.substr(40,8))());
213             // Convert group into patch
214             Map<label>::const_iterator iter = groupToPatch.find(groupId);
216             label patchI;
217             if (iter == groupToPatch.end())
218             {
219                 patchI = nPatches++;
220                 groupToPatch.insert(groupId, patchI);
221                 Info<< "patch " << patchI << " => group " << groupId << endl;
222             }
223             else
224             {
225                 patchI = iter();
226             }
228             faces.append(labelledTri(a, b, c, patchI));
229         }
230         else if (cmd == "CQUAD4")
231         {
232             label groupId = readLabel(IStringStream(line.substr(16,8))());
233             label a = readLabel(IStringStream(line.substr(24,8))());
234             label b = readLabel(IStringStream(line.substr(32,8))());
235             label c = readLabel(IStringStream(line.substr(40,8))());
236             label d = readLabel(IStringStream(line.substr(48,8))());
238             // Convert group into patch
239             Map<label>::const_iterator iter = groupToPatch.find(groupId);
241             label patchI;
242             if (iter == groupToPatch.end())
243             {
244                 patchI = nPatches++;
245                 groupToPatch.insert(groupId, patchI);
246                 Info<< "patch " << patchI << " => group " << groupId << endl;
247             }
248             else
249             {
250                 patchI = iter();
251             }
253             faces.append(labelledTri(a, b, c, patchI));
254             faces.append(labelledTri(c, d, a, patchI));
255         }
256         else if (cmd == "PSHELL")
257         {
258             // Read shell type since group gives patchnames
259             label groupId = readLabel(IStringStream(line.substr(8,8))());
260             if (groupId == ansaId && ansaType == "PSHELL")
261             {
262                 groupToName.insert(groupId, string::validate<word>(ansaName));
263                 Info<< "group " << groupId << " => " << ansaName << endl;
264             }
265         }
266         else if (cmd == "GRID")
267         {
268             label index = readLabel(IStringStream(line.substr(8,8))());
269             scalar x = parseNASCoord(line.substr(24, 8));
270             scalar y = parseNASCoord(line.substr(32, 8));
271             scalar z = parseNASCoord(line.substr(40, 8));
273             indices.append(index);
274             points.append(point(x, y, z));
275         }
276         else if (cmd == "GRID*")
277         {
278             // Long format is on two lines with '*' continuation symbol
279             // on start of second line.
280             // Typical line (spaces compacted)
281             // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
282             // *         2.14897901E+02
284             label index = readLabel(IStringStream(line.substr(8,16))());
285             scalar x = parseNASCoord(line.substr(40, 16));
286             scalar y = parseNASCoord(line.substr(56, 16));
288             is.getLine(line);
289             if (line[0] != '*')
290             {
291                 FatalErrorIn("triSurface::readNAS(const fileName&)")
292                     << "Expected continuation symbol '*' when reading GRID*"
293                     << " (double precision coordinate) output" << nl
294                     << "Read:" << line << nl
295                     << "File:" << is.name()
296                     << " line:" << is.lineNumber()
297                     << exit(FatalError);
298             }
299             scalar z = parseNASCoord(line.substr(8, 16));
301             indices.append(index);
302             points.append(point(x, y, z));
303         }
304         else if (unhandledCmd.insert(cmd))
305         {
306             Info<< "Unhandled Nastran command " << line << nl
307                 << "File:" << is.name() << " line:" << is.lineNumber() << endl;
308         }
309     }
311     points.shrink();
312     indices.shrink();
313     faces.shrink();
316     Info<< "Read triangles:" << faces.size() << " points:" << points.size()
317         << endl;
319     {
320         // Build inverse mapping (index to point)
321         Map<label> indexToPoint(2*indices.size());
322         forAll(indices, i)
323         {
324             indexToPoint.insert(indices[i], i);
325         }
327         // Relabel faces
328         forAll(faces, i)
329         {
330             labelledTri& f = faces[i];
332             f[0] = indexToPoint[f[0]];
333             f[1] = indexToPoint[f[1]];
334             f[2] = indexToPoint[f[2]];
335         }
336     }
339     // Convert groupToPatch to patchList.
340     geometricSurfacePatchList patches(nPatches);
342     forAllConstIter(Map<word>, groupToName, iter)
343     {
344         label patchI = groupToPatch[iter.key()];
346         patches[patchI] = geometricSurfacePatch
347         (
348             "empty",
349             iter(),
350             patchI
351         );
352     }
354     Info<< "patches:" << patches << endl;
357     // Transfer DynamicLists to straight ones.
358     pointField allPoints;
359     allPoints.transfer(points);
360     points.clear();
362     // Create triSurface
363     *this = triSurface(faces, patches, allPoints);
365     return true;
369 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
371 } // End namespace Foam
373 // ************************************************************************* //