FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

readNAS.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Description
00025     Nastran surface reader.
00026 
00027     - Uses the Ansa "$ANSA_NAME" or the Hypermesh "$HMNAME COMP" extensions
00028       to obtain patch names.
00029     - Handles Nastran short and long formats, but not free format.
00030     - Properly handles the Nastran compact floating point notation: \n
00031     @verbatim
00032         GRID          28        10.20269-.030265-2.358-8
00033     @endverbatim
00034 
00035 
00036 \*---------------------------------------------------------------------------*/
00037 
00038 #include <triSurface/triSurface.H>
00039 #include <OpenFOAM/IFstream.H>
00040 #include <OpenFOAM/IStringStream.H>
00041 
00042 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00043 
00044 namespace Foam
00045 {
00046 
00047 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00048 
00049 // Do weird things to extract number
00050 static scalar parseNASCoord(const string& s)
00051 {
00052     size_t expSign = s.find_last_of("+-");
00053 
00054     if (expSign != string::npos && expSign > 0 && !isspace(s[expSign-1]))
00055     {
00056         scalar mantissa = readScalar(IStringStream(s.substr(0, expSign))());
00057         scalar exponent = readScalar(IStringStream(s.substr(expSign+1))());
00058 
00059         if (s[expSign] == '-')
00060         {
00061             exponent = -exponent;
00062         }
00063         return mantissa*pow(10, exponent);
00064     }
00065     else
00066     {
00067         return readScalar(IStringStream(s)());
00068     }
00069 }
00070 
00071 
00072 bool triSurface::readNAS(const fileName& fName)
00073 {
00074     IFstream is(fName);
00075 
00076     if (!is.good())
00077     {
00078         FatalErrorIn("triSurface::readNAS(const fileName&)")
00079             << "Cannot read file " << fName
00080             << exit(FatalError);
00081     }
00082 
00083     // coordinates of point
00084     DynamicList<point> points;
00085     // Nastran index of point
00086     DynamicList<label> indices;
00087     // Faces in terms of Nastran point indices
00088     DynamicList<labelledTri> faces;
00089     // From face group to patch
00090     Map<label> groupToPatch;
00091     label nPatches = 0;
00092     // Name for face group
00093     Map<word> groupToName;
00094 
00095     // Ansa tags. Denoted by $ANSA_NAME. These will appear just before the
00096     // first use of a type. We read them and store the pshell types which
00097     // are used to name the patches.
00098     label ansaId = -1;
00099     word ansaType;
00100     string ansaName;
00101 
00102     // A single warning per unrecognized command
00103     HashSet<word> unhandledCmd;
00104 
00105     while (is.good())
00106     {
00107         string line;
00108         is.getLine(line);
00109 
00110         // Ansa extension
00111         if (line.substr(0, 10) == "$ANSA_NAME")
00112         {
00113             string::size_type sem0 = line.find (';', 0);
00114             string::size_type sem1 = line.find (';', sem0+1);
00115             string::size_type sem2 = line.find (';', sem1+1);
00116 
00117             if
00118             (
00119                 sem0 != string::npos
00120              && sem1 != string::npos
00121              && sem2 != string::npos
00122             )
00123             {
00124                 ansaId = readLabel
00125                 (
00126                     IStringStream(line.substr(sem0+1, sem1-sem0-1))()
00127                 );
00128                 ansaType = line.substr(sem1+1, sem2-sem1-1);
00129 
00130                 string nameString;
00131                 is.getLine(ansaName);
00132                 if (ansaName[ansaName.size()-1] == '\r')
00133                 {
00134                     ansaName = ansaName.substr(1, ansaName.size()-2);
00135                 }
00136                 else
00137                 {
00138                     ansaName = ansaName.substr(1, ansaName.size()-1);
00139                 }
00140 
00141                 // Info<< "ANSA tag for NastranID:" << ansaId
00142                 //     << " of type " << ansaType
00143                 //     << " name " << ansaName << endl;
00144             }
00145         }
00146 
00147 
00148         // Hypermesh extension
00149         // $HMNAME COMP                   1"partName"
00150         if
00151         (
00152             line.substr(0, 12) == "$HMNAME COMP"
00153          && line.find ('"') != string::npos
00154         )
00155         {
00156             label groupId = readLabel
00157             (
00158                 IStringStream(line.substr(16, 16))()
00159             );
00160 
00161             IStringStream lineStream(line.substr(32));
00162 
00163             string rawName;
00164             lineStream >> rawName;
00165 
00166             groupToName.insert(groupId, string::validate<word>(rawName));
00167             Info<< "group " << groupId << " => " << rawName << endl;
00168         }
00169 
00170 
00171         if (line.empty() || line[0] == '$')
00172         {
00173             // Skip empty or comment
00174             continue;
00175         }
00176 
00177         // Check if character 72 is continuation
00178         if (line.size() > 72 && line[72] == '+')
00179         {
00180             line = line.substr(0, 72);
00181 
00182             while (true)
00183             {
00184                 string buf;
00185                 is.getLine(buf);
00186 
00187                 if (buf.size() > 72 && buf[72]=='+')
00188                 {
00189                     line += buf.substr(8, 64);
00190                 }
00191                 else
00192                 {
00193                     line += buf.substr(8, buf.size()-8);
00194                     break;
00195                 }
00196             }
00197         }
00198 
00199         // Read first word
00200         IStringStream lineStream(line);
00201         word cmd;
00202         lineStream >> cmd;
00203 
00204         if (cmd == "CTRIA3")
00205         {
00206             label groupId = readLabel(IStringStream(line.substr(16,8))());
00207             label a = readLabel(IStringStream(line.substr(24,8))());
00208             label b = readLabel(IStringStream(line.substr(32,8))());
00209             label c = readLabel(IStringStream(line.substr(40,8))());
00210 
00211 
00212             // Convert group into patch
00213             Map<label>::const_iterator iter = groupToPatch.find(groupId);
00214 
00215             label patchI;
00216             if (iter == groupToPatch.end())
00217             {
00218                 patchI = nPatches++;
00219                 groupToPatch.insert(groupId, patchI);
00220                 Info<< "patch " << patchI << " => group " << groupId << endl;
00221             }
00222             else
00223             {
00224                 patchI = iter();
00225             }
00226 
00227             faces.append(labelledTri(a, b, c, patchI));
00228         }
00229         else if (cmd == "CQUAD4")
00230         {
00231             label groupId = readLabel(IStringStream(line.substr(16,8))());
00232             label a = readLabel(IStringStream(line.substr(24,8))());
00233             label b = readLabel(IStringStream(line.substr(32,8))());
00234             label c = readLabel(IStringStream(line.substr(40,8))());
00235             label d = readLabel(IStringStream(line.substr(48,8))());
00236 
00237             // Convert group into patch
00238             Map<label>::const_iterator iter = groupToPatch.find(groupId);
00239 
00240             label patchI;
00241             if (iter == groupToPatch.end())
00242             {
00243                 patchI = nPatches++;
00244                 groupToPatch.insert(groupId, patchI);
00245                 Info<< "patch " << patchI << " => group " << groupId << endl;
00246             }
00247             else
00248             {
00249                 patchI = iter();
00250             }
00251 
00252             faces.append(labelledTri(a, b, c, patchI));
00253             faces.append(labelledTri(c, d, a, patchI));
00254         }
00255         else if (cmd == "PSHELL")
00256         {
00257             // Read shell type since group gives patchnames
00258             label groupId = readLabel(IStringStream(line.substr(8,8))());
00259             if (groupId == ansaId && ansaType == "PSHELL")
00260             {
00261                 groupToName.insert(groupId, string::validate<word>(ansaName));
00262                 Info<< "group " << groupId << " => " << ansaName << endl;
00263             }
00264         }
00265         else if (cmd == "GRID")
00266         {
00267             label index = readLabel(IStringStream(line.substr(8,8))());
00268             scalar x = parseNASCoord(line.substr(24, 8));
00269             scalar y = parseNASCoord(line.substr(32, 8));
00270             scalar z = parseNASCoord(line.substr(40, 8));
00271 
00272             indices.append(index);
00273             points.append(point(x, y, z));
00274         }
00275         else if (cmd == "GRID*")
00276         {
00277             // Long format is on two lines with '*' continuation symbol
00278             // on start of second line.
00279             // Typical line (spaces compacted)
00280             // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
00281             // *         2.14897901E+02
00282 
00283             label index = readLabel(IStringStream(line.substr(8,16))());
00284             scalar x = parseNASCoord(line.substr(40, 16));
00285             scalar y = parseNASCoord(line.substr(56, 16));
00286 
00287             is.getLine(line);
00288             if (line[0] != '*')
00289             {
00290                 FatalErrorIn("triSurface::readNAS(const fileName&)")
00291                     << "Expected continuation symbol '*' when reading GRID*"
00292                     << " (double precision coordinate) output" << nl
00293                     << "Read:" << line << nl
00294                     << "File:" << is.name()
00295                     << " line:" << is.lineNumber()
00296                     << exit(FatalError);
00297             }
00298             scalar z = parseNASCoord(line.substr(8, 16));
00299 
00300             indices.append(index);
00301             points.append(point(x, y, z));
00302         }
00303         else if (unhandledCmd.insert(cmd))
00304         {
00305             Info<< "Unhandled Nastran command " << line << nl
00306                 << "File:" << is.name() << " line:" << is.lineNumber() << endl;
00307         }
00308     }
00309 
00310     points.shrink();
00311     indices.shrink();
00312     faces.shrink();
00313 
00314 
00315     Info<< "Read triangles:" << faces.size() << " points:" << points.size()
00316         << endl;
00317 
00318     {
00319         // Build inverse mapping (index to point)
00320         Map<label> indexToPoint(2*indices.size());
00321         forAll(indices, i)
00322         {
00323             indexToPoint.insert(indices[i], i);
00324         }
00325 
00326         // Relabel faces
00327         forAll(faces, i)
00328         {
00329             labelledTri& f = faces[i];
00330 
00331             f[0] = indexToPoint[f[0]];
00332             f[1] = indexToPoint[f[1]];
00333             f[2] = indexToPoint[f[2]];
00334         }
00335     }
00336 
00337 
00338     // Convert groupToPatch to patchList.
00339     geometricSurfacePatchList patches(nPatches);
00340 
00341     forAllConstIter(Map<word>, groupToName, iter)
00342     {
00343         label patchI = groupToPatch[iter.key()];
00344 
00345         patches[patchI] = geometricSurfacePatch
00346         (
00347             "empty",
00348             iter(),
00349             patchI
00350         );
00351     }
00352 
00353     Info<< "patches:" << patches << endl;
00354 
00355     // Transfer DynamicLists to straight ones.
00356     pointField allPoints(points.xfer());
00357 
00358     // Create triSurface
00359     *this = triSurface(faces, patches, allPoints, true);
00360 
00361     return true;
00362 }
00363 
00364 
00365 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00366 
00367 } // End namespace Foam
00368 
00369 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines