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

NASsurfaceFormat.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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "NASsurfaceFormat.H"
00027 #include <OpenFOAM/IFstream.H>
00028 #include <OpenFOAM/IStringStream.H>
00029 
00030 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00031 
00032 template<class Face>
00033 Foam::fileFormats::NASsurfaceFormat<Face>::NASsurfaceFormat
00034 (
00035     const fileName& filename
00036 )
00037 {
00038     read(filename);
00039 }
00040 
00041 
00042 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00043 
00044 template<class Face>
00045 bool Foam::fileFormats::NASsurfaceFormat<Face>::read
00046 (
00047     const fileName& filename
00048 )
00049 {
00050     const bool mustTriangulate = this->isTri();
00051     this->clear();
00052 
00053     IFstream is(filename);
00054     if (!is.good())
00055     {
00056         FatalErrorIn
00057         (
00058             "fileFormats::NASsurfaceFormat::read(const fileName&)"
00059         )
00060             << "Cannot read file " << filename
00061             << exit(FatalError);
00062     }
00063 
00064     // Nastran index of points
00065     DynamicList<label>  pointId;
00066     DynamicList<point>  dynPoints;
00067     DynamicList<Face>   dynFaces;
00068     DynamicList<label>  dynZones;
00069     DynamicList<label>  dynSizes;
00070     Map<label>          lookup;
00071 
00072     // assume the types are not intermixed
00073     // leave faces that didn't have a group in 0
00074     bool sorted = true;
00075     label zoneI = 0;
00076 
00077     // Name for face group
00078     Map<word> nameLookup;
00079 
00080     // Ansa tags. Denoted by $ANSA_NAME.
00081     // These will appear just before the first use of a type.
00082     // We read them and store the PSHELL types which are used to name
00083     // the zones.
00084     label ansaId = -1;
00085     word  ansaType, ansaName;
00086 
00087     // A single warning per unrecognized command
00088     HashSet<word> unhandledCmd;
00089 
00090     while (is.good())
00091     {
00092         string line;
00093         is.getLine(line);
00094 
00095         // Ansa extension
00096         if (line.substr(0, 10) == "$ANSA_NAME")
00097         {
00098             string::size_type sem0 = line.find (';', 0);
00099             string::size_type sem1 = line.find (';', sem0+1);
00100             string::size_type sem2 = line.find (';', sem1+1);
00101 
00102             if
00103             (
00104                 sem0 != string::npos
00105              && sem1 != string::npos
00106              && sem2 != string::npos
00107             )
00108             {
00109                 ansaId = readLabel
00110                 (
00111                     IStringStream(line.substr(sem0+1, sem1-sem0-1))()
00112                 );
00113                 ansaType = line.substr(sem1+1, sem2-sem1-1);
00114 
00115                 string rawName;
00116                 is.getLine(rawName);
00117                 if (rawName[rawName.size()-1] == '\r')
00118                 {
00119                     rawName = rawName.substr(1, rawName.size()-2);
00120                 }
00121                 else
00122                 {
00123                     rawName = rawName.substr(1, rawName.size()-1);
00124                 }
00125 
00126                 string::stripInvalid<word>(rawName);
00127                 ansaName = rawName;
00128 
00129                 // Info<< "ANSA tag for NastranID:" << ansaId
00130                 //     << " of type " << ansaType
00131                 //     << " name " << ansaName << endl;
00132             }
00133         }
00134 
00135 
00136         // Hypermesh extension
00137         // $HMNAME COMP                   1"partName"
00138         if
00139         (
00140             line.substr(0, 12) == "$HMNAME COMP"
00141          && line.find ('"') != string::npos
00142         )
00143         {
00144             label groupId = readLabel
00145             (
00146                 IStringStream(line.substr(16, 16))()
00147             );
00148 
00149             IStringStream lineStream(line.substr(32));
00150 
00151             string rawName;
00152             lineStream >> rawName;
00153             string::stripInvalid<word>(rawName);
00154 
00155             word groupName(rawName);
00156             nameLookup.insert(groupId, groupName);
00157 
00158             // Info<< "group " << groupId << " => " << groupName << endl;
00159         }
00160 
00161 
00162         // Skip empty or comment
00163         if (line.empty() || line[0] == '$')
00164         {
00165             continue;
00166         }
00167 
00168         // Check if character 72 is continuation
00169         if (line.size() > 72 && line[72] == '+')
00170         {
00171             line = line.substr(0, 72);
00172 
00173             while (true)
00174             {
00175                 string buf;
00176                 is.getLine(buf);
00177 
00178                 if (buf.size() > 72 && buf[72] == '+')
00179                 {
00180                     line += buf.substr(8, 64);
00181                 }
00182                 else
00183                 {
00184                     line += buf.substr(8, buf.size()-8);
00185                     break;
00186                 }
00187             }
00188         }
00189 
00190 
00191         // Read first word
00192         IStringStream lineStream(line);
00193         word cmd;
00194         lineStream >> cmd;
00195 
00196         if (cmd == "CTRIA3")
00197         {
00198             triFace fTri;
00199 
00200             label groupId = readLabel(IStringStream(line.substr(16,8))());
00201             fTri[0] = readLabel(IStringStream(line.substr(24,8))());
00202             fTri[1] = readLabel(IStringStream(line.substr(32,8))());
00203             fTri[2] = readLabel(IStringStream(line.substr(40,8))());
00204 
00205             // Convert groupID into zoneId
00206             Map<label>::const_iterator fnd = lookup.find(groupId);
00207             if (fnd != lookup.end())
00208             {
00209                 if (zoneI != fnd())
00210                 {
00211                     // pshell types are intermixed
00212                     sorted = false;
00213                 }
00214                 zoneI = fnd();
00215             }
00216             else
00217             {
00218                 zoneI = dynSizes.size();
00219                 lookup.insert(groupId, zoneI);
00220                 dynSizes.append(0);
00221                 // Info<< "zone" << zoneI << " => group " << groupId <<endl;
00222             }
00223 
00224             dynFaces.append(fTri);
00225             dynZones.append(zoneI);
00226             dynSizes[zoneI]++;
00227         }
00228         else if (cmd == "CQUAD4")
00229         {
00230             face fQuad(4);
00231             UList<label>& f = static_cast<UList<label>&>(fQuad);
00232 
00233             label groupId = readLabel(IStringStream(line.substr(16,8))());
00234             fQuad[0] = readLabel(IStringStream(line.substr(24,8))());
00235             fQuad[1] = readLabel(IStringStream(line.substr(32,8))());
00236             fQuad[2] = readLabel(IStringStream(line.substr(40,8))());
00237             fQuad[3] = readLabel(IStringStream(line.substr(48,8))());
00238 
00239             // Convert groupID into zoneId
00240             Map<label>::const_iterator fnd = lookup.find(groupId);
00241             if (fnd != lookup.end())
00242             {
00243                 if (zoneI != fnd())
00244                 {
00245                     // pshell types are intermixed
00246                     sorted = false;
00247                 }
00248                 zoneI = fnd();
00249             }
00250             else
00251             {
00252                 zoneI = dynSizes.size();
00253                 lookup.insert(groupId, zoneI);
00254                 dynSizes.append(0);
00255                 // Info<< "zone" << zoneI << " => group " << groupId <<endl;
00256             }
00257 
00258 
00259             if (mustTriangulate)
00260             {
00261                 dynFaces.append(triFace(f[0], f[1], f[2]));
00262                 dynFaces.append(triFace(f[0], f[2], f[3]));
00263                 dynZones.append(zoneI);
00264                 dynZones.append(zoneI);
00265                 dynSizes[zoneI] += 2;
00266             }
00267             else
00268             {
00269                 dynFaces.append(Face(f));
00270                 dynZones.append(zoneI);
00271                 dynSizes[zoneI]++;
00272             }
00273         }
00274         else if (cmd == "GRID")
00275         {
00276             label index = readLabel(IStringStream(line.substr(8,8))());
00277             scalar x = parseNASCoord(line.substr(24, 8));
00278             scalar y = parseNASCoord(line.substr(32, 8));
00279             scalar z = parseNASCoord(line.substr(40, 8));
00280 
00281             pointId.append(index);
00282             dynPoints.append(point(x, y, z));
00283         }
00284         else if (cmd == "GRID*")
00285         {
00286             // Long format is on two lines with '*' continuation symbol
00287             // on start of second line.
00288             // Typical line (spaces compacted)
00289             // GRID*      126   0 -5.55999875E+02 -5.68730474E+02
00290             // *         2.14897901E+02
00291 
00292             label index = readLabel(IStringStream(line.substr(8,16))());
00293             scalar x = parseNASCoord(line.substr(40, 16));
00294             scalar y = parseNASCoord(line.substr(56, 16));
00295 
00296             is.getLine(line);
00297             if (line[0] != '*')
00298             {
00299                 FatalErrorIn
00300                 (
00301                     "fileFormats::NASsurfaceFormat::read(const fileName&)"
00302                 )
00303                     << "Expected continuation symbol '*' when reading GRID*"
00304                     << " (double precision coordinate) format" << nl
00305                     << "Read:" << line << nl
00306                     << "File:" << is.name() << " line:" << is.lineNumber()
00307                     << exit(FatalError);
00308             }
00309             scalar z = parseNASCoord(line.substr(8, 16));
00310 
00311             pointId.append(index);
00312             dynPoints.append(point(x, y, z));
00313         }
00314         else if (cmd == "PSHELL")
00315         {
00316             // pshell type for zone names with the Ansa extension
00317             label groupId = readLabel(IStringStream(line.substr(8,8))());
00318 
00319             if (groupId == ansaId && ansaType == "PSHELL")
00320             {
00321                 nameLookup.insert(ansaId, ansaName);
00322                 // Info<< "group " << groupId << " => " << ansaName << endl;
00323             }
00324         }
00325         else if (unhandledCmd.insert(cmd))
00326         {
00327             Info<< "Unhandled Nastran command " << line << nl
00328                 << "File:" << is.name() << " line:" << is.lineNumber()
00329                 << endl;
00330         }
00331     }
00332 
00333     //    Info<< "Read faces:" << dynFaces.size()
00334     //        << " points:" << dynPoints.size()
00335     //        << endl;
00336 
00337     // transfer to normal lists
00338     this->storedPoints().transfer(dynPoints);
00339 
00340     pointId.shrink();
00341     dynFaces.shrink();
00342 
00343     // Build inverse mapping (NASTRAN pointId -> index)
00344     Map<label> mapPointId(2*pointId.size());
00345     forAll(pointId, i)
00346     {
00347         mapPointId.insert(pointId[i], i);
00348     }
00349 
00350     // Relabel faces
00351     // ~~~~~~~~~~~~~
00352     forAll(dynFaces, i)
00353     {
00354         Face& f = dynFaces[i];
00355         forAll(f, fp)
00356         {
00357             f[fp] = mapPointId[f[fp]];
00358         }
00359     }
00360     pointId.clearStorage();
00361     mapPointId.clear();
00362 
00363 
00364     // create default zone names, or from ANSA/Hypermesh information
00365     List<word> names(dynSizes.size());
00366     forAllConstIter(Map<label>, lookup, iter)
00367     {
00368         const label zoneI  = iter();
00369         const label groupI = iter.key();
00370 
00371         Map<word>::const_iterator fnd = nameLookup.find(groupI);
00372         if (fnd != nameLookup.end())
00373         {
00374             names[zoneI] = fnd();
00375         }
00376         else
00377         {
00378             names[zoneI] = word("zone") + ::Foam::name(zoneI);
00379         }
00380     }
00381 
00382     this->sortFacesAndStore(dynFaces.xfer(), dynZones.xfer(), sorted);
00383 
00384     // add zones, culling empty ones
00385     this->addZones(dynSizes, names, true);
00386 
00387     return true;
00388 }
00389 
00390 
00391 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines