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

netgenNeutralToFoam.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 Application
00025     netgenNeutralToFoam
00026 
00027 Description
00028     Converts neutral file format as written by Netgen v4.4.
00029 
00030     Example:
00031 
00032     9
00033       1.000000  1.000000  1.000000
00034       0.000000  1.000000  1.000000
00035       0.000000  0.000000  1.000000
00036       1.000000  0.000000  1.000000
00037       0.000000  1.000000  0.000000
00038       1.000000  1.000000  0.000000
00039       1.000000  0.000000  0.000000
00040       0.000000  0.000000  0.000000
00041       0.500000  0.500000  0.500000
00042     12
00043        1          7        8        9        3
00044        1          5        9        6        8
00045        1          5        9        2        1
00046        1          4        9        7        6
00047        1          7        8        6        9
00048        1          4        6        1        9
00049        1          5        9        8        2
00050        1          4        1        2        9
00051        1          1        6        5        9
00052        1          2        3        4        9
00053        1          8        9        3        2
00054        1          4        9        3        7
00055     12
00056        1            1        2        4
00057        1            3        4        2
00058        2            5        6        8
00059        2            7        8        6
00060        3            1        4        6
00061        3            7        6        4
00062        5            2        1        5
00063        5            6        5        1
00064        5            3        2        8
00065        5            5        8        2
00066        6            4        3        7
00067        6            8        7        3
00068 
00069 NOTE:
00070     - reverse order of boundary faces using geometric test.
00071       (not very space efficient)
00072     - order of tet vertices only tested on one file.
00073     - all patch/cell/vertex numbers offset by one.
00074 
00075 Usage
00076 
00077     - netgenNeutralToFoam [OPTIONS] <Neutral file>
00078 
00079     @param <Neutral file> \n
00080     @todo Detailed description of argument.
00081 
00082     @param -case <dir>\n
00083     Case directory.
00084 
00085     @param -parallel \n
00086     Run in parallel.
00087 
00088     @param -help \n
00089     Display help message.
00090 
00091     @param -doc \n
00092     Display Doxygen API documentation page for this application.
00093 
00094     @param -srcDoc \n
00095     Display Doxygen source documentation page for this application.
00096 
00097 \*---------------------------------------------------------------------------*/
00098 
00099 #include <OpenFOAM/argList.H>
00100 #include <OpenFOAM/Time.H>
00101 #include <OpenFOAM/polyMesh.H>
00102 #include <OpenFOAM/IFstream.H>
00103 #include <OpenFOAM/polyPatch.H>
00104 #include <OpenFOAM/cellModeller.H>
00105 #include <OpenFOAM/triFace.H>
00106 
00107 using namespace Foam;
00108 
00109 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00110 
00111 // Main program:
00112 
00113 int main(int argc, char *argv[])
00114 {
00115     argList::validArgs.append("Neutral file");
00116 
00117 #   include <OpenFOAM/setRootCase.H>
00118 #   include <OpenFOAM/createTime.H>
00119 
00120     fileName neuFile(args.additionalArgs()[0]);
00121 
00122 
00123     IFstream str(neuFile);
00124 
00125 
00126     //
00127     // Read nodes.
00128     //
00129     label nNodes(readLabel(str));
00130 
00131     Info<< "nNodes:" << nNodes << endl;
00132 
00133 
00134     pointField points(nNodes);
00135 
00136     forAll(points, pointI)
00137     {
00138         scalar x,y,z;
00139 
00140         str >> x >> y >> z;
00141 
00142         points[pointI] = point(x, y, z);
00143     }
00144 
00145 
00146 
00147 
00148     label nTets(readLabel(str));
00149 
00150     Info<< "nTets:" << nTets << endl;
00151 
00152     const cellModel& tet = *(cellModeller::lookup("tet"));
00153 
00154     cellShapeList cells(nTets);
00155 
00156     labelList tetPoints(4);
00157 
00158     forAll(cells, cellI)
00159     {
00160         label domain(readLabel(str));
00161 
00162         if (domain != 1)
00163         {
00164             WarningIn(args.executable())
00165                 << "Cannot handle multiple domains"
00166                 << nl << "Ignoring domain " << domain << " setting on line "
00167                 << str.lineNumber() << endl;
00168         }
00169 
00170         tetPoints[1] = readLabel(str) - 1;
00171         tetPoints[0] = readLabel(str) - 1;
00172         tetPoints[2] = readLabel(str) - 1;
00173         tetPoints[3] = readLabel(str) - 1;
00174 
00175         cells[cellI] = cellShape(tet, tetPoints);
00176     }
00177 
00178 
00179 
00180     label nFaces(readLabel(str));
00181 
00182     Info<< "nFaces:" << nFaces << endl;
00183 
00184     // Unsorted boundary faces
00185     faceList boundaryFaces(nFaces);
00186 
00187     // For each boundary faces the Foam patchID
00188     labelList boundaryPatch(nFaces, -1);
00189 
00190     // Max patch.
00191     label maxPatch = 0;
00192 
00193     // Boundary faces as three vertices
00194     HashTable<label, triFace, Hash<triFace> > vertsToBoundary(nFaces);
00195 
00196     forAll(boundaryFaces, faceI)
00197     {
00198         label patchI(readLabel(str));
00199 
00200         if (patchI < 0)
00201         {
00202             FatalErrorIn(args.executable())
00203                 << "Invalid boundary region number " << patchI
00204                 << " on line " << str.lineNumber()
00205                 << exit(FatalError);
00206         }
00207 
00208 
00209         maxPatch = max(maxPatch, patchI);
00210 
00211         triFace tri(readLabel(str)-1, readLabel(str)-1, readLabel(str)-1);
00212 
00213         // Store boundary face as is for now. Later on reverse it.
00214         boundaryFaces[faceI].setSize(3);
00215         boundaryFaces[faceI][0] = tri[0];
00216         boundaryFaces[faceI][1] = tri[1];
00217         boundaryFaces[faceI][2] = tri[2];
00218         boundaryPatch[faceI] = patchI;
00219 
00220         vertsToBoundary.insert(tri, faceI);
00221     }
00222 
00223     label nPatches = maxPatch + 1;
00224 
00225 
00226     // Use hash of points to get owner cell and orient the boundary face.
00227     // For storage reasons I store the triangles and loop over the cells instead
00228     // of the other way around (store cells and loop over triangles) though
00229     // that would be faster.
00230     forAll(cells, cellI)
00231     {
00232         const cellShape& cll = cells[cellI];
00233 
00234         // Get the four (outwards pointing) faces of the cell
00235         faceList tris(cll.faces());
00236 
00237         forAll(tris, i)
00238         {
00239             const face& f = tris[i];
00240 
00241             // Is there any boundary face with same vertices?
00242             // (uses commutative hash)
00243             HashTable<label, triFace, Hash<triFace> >::iterator iter =
00244                 vertsToBoundary.find(triFace(f[0], f[1], f[2]));
00245 
00246             if (iter != vertsToBoundary.end())
00247             {
00248                 label faceI = iter();
00249                 const triFace& tri = iter.key();
00250 
00251                 // Determine orientation of tri v.s. cell centre.
00252                 point cc(cll.centre(points));
00253                 point fc(tri.centre(points));
00254                 vector fn(tri.normal(points));
00255 
00256                 if (((fc - cc) & fn) < 0)
00257                 {
00258                     // Boundary face points inwards. Flip.
00259                     boundaryFaces[faceI] = boundaryFaces[faceI].reverseFace();
00260                 }
00261 
00262                 // Done this face so erase from hash
00263                 vertsToBoundary.erase(iter);
00264             }
00265         }
00266     }
00267 
00268 
00269     if (vertsToBoundary.size())
00270     {
00271         // Didn't find cells connected to boundary faces.
00272         WarningIn(args.executable())
00273             << "There are boundary faces without attached cells."
00274             << "Boundary faces (as triFaces):" << vertsToBoundary.toc()
00275             << endl;
00276     }
00277 
00278 
00279     // Storage for boundary faces sorted into patches
00280 
00281     faceListList patchFaces(nPatches);
00282 
00283     wordList patchNames(nPatches);
00284 
00285     forAll(patchNames, patchI)
00286     {
00287         patchNames[patchI] = word("patch") + name(patchI);
00288     }
00289 
00290     wordList patchTypes(nPatches, polyPatch::typeName);
00291     word defaultFacesName = "defaultFaces";
00292     word defaultFacesType = polyPatch::typeName;
00293     wordList patchPhysicalTypes(nPatches, polyPatch::typeName);
00294 
00295     {
00296         // Sort boundaryFaces by patch.
00297         List<DynamicList<face> > allPatchFaces(nPatches);
00298 
00299         forAll(boundaryPatch, faceI)
00300         {
00301             label patchI = boundaryPatch[faceI];
00302 
00303             allPatchFaces[patchI].append(boundaryFaces[faceI]);
00304         }
00305 
00306         Info<< "Patches:" << nl
00307             << "\tNeutral Boundary\tPatch name\tSize" << nl
00308             << "\t----------------\t----------\t----" << endl;
00309 
00310         forAll(allPatchFaces, patchI)
00311         {
00312             Info<< '\t' << patchI << "\t\t\t"
00313                 << patchNames[patchI] << "\t\t"
00314                 << allPatchFaces[patchI].size() << endl;
00315 
00316             patchFaces[patchI].transfer(allPatchFaces[patchI]);
00317         }
00318 
00319         Info<< endl;
00320     }
00321 
00322 
00323     polyMesh mesh
00324     (
00325         IOobject
00326         (
00327             polyMesh::defaultRegion,
00328             runTime.constant(),
00329             runTime
00330         ),
00331         xferMove(points),
00332         cells,
00333         patchFaces,
00334         patchNames,
00335         patchTypes,
00336         defaultFacesName,
00337         defaultFacesType,
00338         patchPhysicalTypes
00339     );
00340 
00341     Info<< "Writing mesh to " << runTime.constant() << endl << endl;
00342 
00343     mesh.write();
00344 
00345 
00346     Info<< "End\n" << endl;
00347 
00348     return 0;
00349 }
00350 
00351 
00352 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines