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

gmshToFoam.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     gmshToFoam
00026 
00027 Description
00028     Reads .msh file as written by Gmsh.
00029 
00030     Needs surface elements on mesh to be present and aligned with outside faces
00031     of the mesh. I.e. if the mesh is hexes, the outside faces need to be quads
00032 
00033 Note
00034     There is something seriously wrong with the ordering written in the
00035     .msh file. Normal operation is to check the ordering and invert prisms
00036     and hexes if found to be wrong way round.
00037     Use the -keepOrientation to keep the raw information.
00038 
00039     The code now uses the element (cell,face) physical region id number
00040     to create cell zones and faces zones (similar to
00041     fluentMeshWithInternalFaces).
00042 
00043     A use of the cell zone information, is for field initialization with the
00044     "setFields" utility. see the classes:  topoSetSource, zoneToCell.
00045 
00046 Usage
00047 
00048     - gmshToFoam [OPTIONS] <.msh file>
00049 
00050     @param <.msh file> \n
00051     @todo Detailed description of argument.
00052 
00053     @param -keepOrientation \n
00054     Do not check ordering.
00055 
00056     @param -help \n
00057     Display help message.
00058 
00059     @param -doc \n
00060     Display Doxygen API documentation page for this application.
00061 
00062     @param -srcDoc \n
00063     Display Doxygen source documentation page for this application.
00064 
00065 \*---------------------------------------------------------------------------*/
00066 
00067 #include <OpenFOAM/argList.H>
00068 #include <OpenFOAM/polyMesh.H>
00069 #include <OpenFOAM/Time.H>
00070 #include <OpenFOAM/polyMesh.H>
00071 #include <OpenFOAM/IFstream.H>
00072 #include <OpenFOAM/cellModeller.H>
00073 #include <dynamicMesh/repatchPolyTopoChanger.H>
00074 #include <meshTools/cellSet.H>
00075 #include <meshTools/faceSet.H>
00076 
00077 using namespace Foam;
00078 
00079 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00080 
00081 // Element type numbers
00082 static label MSHTRI   = 2;
00083 static label MSHQUAD  = 3;
00084 static label MSHTET   = 4;
00085 static label MSHPYR   = 7;
00086 static label MSHPRISM = 6;
00087 static label MSHHEX   = 5;
00088 
00089 
00090 // Skips till end of section. Returns false if end of file.
00091 bool skipSection(IFstream& inFile)
00092 {
00093     string line;
00094     do
00095     {
00096         inFile.getLine(line);
00097 
00098         if (!inFile.good())
00099         {
00100             return false;
00101         }
00102     }
00103     while (line.size() < 4 || line.substr(0, 4) != "$End");
00104 
00105     return true;
00106 }
00107 
00108 
00109 void renumber
00110 (
00111     const Map<label>& mshToFoam,
00112     labelList& labels
00113 )
00114 {
00115     forAll(labels, labelI)
00116     {
00117         labels[labelI] = mshToFoam[labels[labelI]];
00118     }
00119 }
00120 
00121 
00122 // Find face in pp which uses all vertices in meshF (in mesh point labels)
00123 label findFace(const primitivePatch& pp, const labelList& meshF)
00124 {
00125     const Map<label>& meshPointMap = pp.meshPointMap();
00126 
00127     // meshF[0] in pp labels.
00128     if (!meshPointMap.found(meshF[0]))
00129     {
00130         Warning<< "Not using gmsh face " << meshF
00131             << " since zero vertex is not on boundary of polyMesh" << endl;
00132         return -1;
00133     }
00134 
00135     // Find faces using first point
00136     const labelList& pFaces = pp.pointFaces()[meshPointMap[meshF[0]]];
00137 
00138     // Go through all these faces and check if there is one which uses all of
00139     // meshF vertices (in any order ;-)
00140     forAll(pFaces, i)
00141     {
00142         label faceI = pFaces[i];
00143 
00144         const face& f = pp[faceI];
00145 
00146         // Count uses of vertices of meshF for f
00147         label nMatched = 0;
00148 
00149         forAll(f, fp)
00150         {
00151             if (findIndex(meshF, f[fp]) != -1)
00152             {
00153                 nMatched++;
00154             }
00155         }
00156 
00157         if (nMatched == meshF.size())
00158         {
00159             return faceI;
00160         }
00161     }
00162 
00163     return -1;
00164 }
00165 
00166 
00167 // Same but find internal face. Expensive addressing.
00168 label findInternalFace(const primitiveMesh& mesh, const labelList& meshF)
00169 {
00170     const labelList& pFaces = mesh.pointFaces()[meshF[0]];
00171 
00172     forAll(pFaces, i)
00173     {
00174         label faceI = pFaces[i];
00175 
00176         const face& f = mesh.faces()[faceI];
00177 
00178         // Count uses of vertices of meshF for f
00179         label nMatched = 0;
00180 
00181         forAll(f, fp)
00182         {
00183             if (findIndex(meshF, f[fp]) != -1)
00184             {
00185                 nMatched++;
00186             }
00187         }
00188 
00189         if (nMatched == meshF.size())
00190         {
00191             return faceI;
00192         }
00193     }
00194     return -1;
00195 }
00196 
00197 
00198 // Determine whether cell is inside-out by checking for any wrong-oriented
00199 // face.
00200 bool correctOrientation(const pointField& points, const cellShape& shape)
00201 {
00202     // Get centre of shape.
00203     point cc(shape.centre(points));
00204 
00205     // Get outwards pointing faces.
00206     faceList faces(shape.faces());
00207 
00208     forAll(faces, i)
00209     {
00210         const face& f = faces[i];
00211 
00212         vector n(f.normal(points));
00213 
00214         // Check if vector from any point on face to cc points outwards
00215         if (((points[f[0]] - cc) & n) < 0)
00216         {
00217             // Incorrectly oriented
00218             return false;
00219         }
00220     }
00221 
00222     return true;
00223 }
00224 
00225 
00226 void storeCellInZone
00227 (
00228     const label regPhys,
00229     const label cellI,
00230     Map<label>& physToZone,
00231 
00232     labelList& zoneToPhys,
00233     List<DynamicList<label> >& zoneCells
00234 )
00235 {
00236     Map<label>::const_iterator zoneFnd = physToZone.find(regPhys);
00237 
00238     if (zoneFnd == physToZone.end())
00239     {
00240         // New region. Allocate zone for it.
00241         label zoneI = zoneCells.size();
00242         zoneCells.setSize(zoneI+1);
00243         zoneToPhys.setSize(zoneI+1);
00244 
00245         Info<< "Mapping region " << regPhys << " to Foam cellZone "
00246             << zoneI << endl;
00247         physToZone.insert(regPhys, zoneI);
00248 
00249         zoneToPhys[zoneI] = regPhys;
00250         zoneCells[zoneI].append(cellI);
00251     }
00252     else
00253     {
00254         // Existing zone for region
00255         zoneCells[zoneFnd()].append(cellI);
00256     }
00257 }
00258 
00259 
00260 // Reads mesh format
00261 scalar readMeshFormat(IFstream& inFile)
00262 {
00263     Info<< "Starting to read mesh format at line " << inFile.lineNumber() << endl;
00264 
00265     string line;
00266     inFile.getLine(line);
00267     IStringStream lineStr(line);
00268 
00269     scalar version;
00270     label asciiFlag, nBytes;
00271     lineStr >> version >> asciiFlag >> nBytes;
00272 
00273     Info<< "Read format version " << version << "  ascii " << asciiFlag << endl;
00274 
00275     if (asciiFlag != 0)
00276     {
00277         FatalIOErrorIn("readMeshFormat(IFstream&)", inFile)
00278             << "Can only read ascii msh files."
00279             << exit(FatalIOError);
00280     }
00281 
00282     inFile.getLine(line);
00283     IStringStream tagStr(line);
00284     word tag(tagStr);
00285 
00286     if (tag != "$EndMeshFormat")
00287     {
00288         FatalIOErrorIn("readMeshFormat(IFstream&)", inFile)
00289             << "Did not find $ENDNOD tag on line "
00290             << inFile.lineNumber() << exit(FatalIOError);
00291     }
00292     Info<< endl;
00293 
00294     return version;
00295 }
00296 
00297 
00298 // Reads points and map
00299 void readPoints(IFstream& inFile, pointField& points, Map<label>& mshToFoam)
00300 {
00301     Info<< "Starting to read points at line " << inFile.lineNumber() << endl;
00302 
00303     string line;
00304     inFile.getLine(line);
00305     IStringStream lineStr(line);
00306 
00307     label nVerts;
00308     lineStr >> nVerts;
00309 
00310     Info<< "Vertices to be read:" << nVerts << endl;
00311 
00312     points.setSize(nVerts);
00313     mshToFoam.resize(2*nVerts);
00314 
00315     for (label pointI = 0; pointI < nVerts; pointI++)
00316     {
00317         label mshLabel;
00318         scalar xVal, yVal, zVal;
00319 
00320         string line;
00321         inFile.getLine(line);
00322         IStringStream lineStr(line);
00323 
00324         lineStr >> mshLabel >> xVal >> yVal >> zVal;
00325 
00326         point& pt = points[pointI];
00327 
00328         pt.x() = xVal;
00329         pt.y() = yVal;
00330         pt.z() = zVal;
00331 
00332         mshToFoam.insert(mshLabel, pointI);
00333     }
00334 
00335     Info<< "Vertices read:" << mshToFoam.size() << endl;
00336 
00337     inFile.getLine(line);
00338     IStringStream tagStr(line);
00339     word tag(tagStr);
00340 
00341     if (tag != "$ENDNOD" && tag != "$EndNodes")
00342     {
00343         FatalIOErrorIn("readPoints(..)", inFile)
00344             << "Did not find $ENDNOD tag on line "
00345             << inFile.lineNumber() << exit(FatalIOError);
00346     }
00347     Info<< endl;
00348 }
00349 
00350 
00351 // Reads physical names
00352 void readPhysNames(IFstream& inFile, Map<word>& physicalNames)
00353 {
00354     Info<< "Starting to read physical names at line " << inFile.lineNumber()
00355         << endl;
00356 
00357     string line;
00358     inFile.getLine(line);
00359     IStringStream lineStr(line);
00360 
00361     label nNames;
00362     lineStr >> nNames;
00363 
00364     Info<< "Physical names:" << nNames << endl;
00365 
00366     physicalNames.resize(nNames);
00367 
00368     for (label i = 0; i < nNames; i++)
00369     {
00370         label regionI;
00371         string regionName;
00372 
00373         string line;
00374         inFile.getLine(line);
00375         IStringStream lineStr(line);
00376         label nSpaces = lineStr.str().count(' ');
00377 
00378         if(nSpaces == 1)
00379         {
00380             lineStr >> regionI >> regionName;
00381 
00382             Info<< "    " << regionI << '\t'
00383                 << string::validate<word>(regionName) << endl;
00384         }
00385         else if(nSpaces == 2)
00386         {
00387             // >= Gmsh2.4 physical types has tag in front.
00388             label physType;
00389             lineStr >> physType >> regionI >> regionName;
00390             if (physType == 1)
00391             {
00392                 Info<< "    " << "Line " << regionI << '\t'
00393                     << string::validate<word>(regionName) << endl;
00394             }
00395             else if (physType == 2)
00396             {
00397                 Info<< "    " << "Surface " << regionI << '\t'
00398                     << string::validate<word>(regionName) << endl;
00399             }
00400             else if (physType == 3)
00401             {
00402                 Info<< "    " << "Volume " << regionI << '\t'
00403                     << string::validate<word>(regionName) << endl;
00404             }
00405         }
00406 
00407         physicalNames.insert(regionI, string::validate<word>(regionName));
00408     }
00409 
00410     inFile.getLine(line);
00411     IStringStream tagStr(line);
00412     word tag(tagStr);
00413 
00414     if (tag != "$EndPhysicalNames")
00415     {
00416         FatalIOErrorIn("readPhysicalNames(..)", inFile)
00417             << "Did not find $EndPhysicalNames tag on line "
00418             << inFile.lineNumber() << exit(FatalIOError);
00419     }
00420     Info<< endl;
00421 }
00422 
00423 
00424 // Reads cells and patch faces
00425 void readCells
00426 (
00427     const scalar versionFormat,
00428     const bool keepOrientation,
00429     const pointField& points,
00430     const Map<label>& mshToFoam,
00431     IFstream& inFile,
00432     cellShapeList& cells,
00433 
00434     labelList& patchToPhys,
00435     List<DynamicList<face> >& patchFaces,
00436 
00437     labelList& zoneToPhys,
00438     List<DynamicList<label> >& zoneCells
00439 )
00440 {
00441     Info<< "Starting to read cells at line " << inFile.lineNumber() << endl;
00442 
00443     const cellModel& hex = *(cellModeller::lookup("hex"));
00444     const cellModel& prism = *(cellModeller::lookup("prism"));
00445     const cellModel& pyr = *(cellModeller::lookup("pyr"));
00446     const cellModel& tet = *(cellModeller::lookup("tet"));
00447 
00448     face triPoints(3);
00449     face quadPoints(4);
00450     labelList tetPoints(4);
00451     labelList pyrPoints(5);
00452     labelList prismPoints(6);
00453     labelList hexPoints(8);
00454 
00455 
00456     string line;
00457     inFile.getLine(line);
00458     IStringStream lineStr(line);
00459 
00460     label nElems;
00461     lineStr >> nElems;
00462 
00463     Info<< "Cells to be read:" << nElems << endl << endl;
00464 
00465 
00466     // Storage for all cells. Too big. Shrink later
00467     cells.setSize(nElems);
00468 
00469     label cellI = 0;
00470     label nTet = 0;
00471     label nPyr = 0;
00472     label nPrism = 0;
00473     label nHex = 0;
00474 
00475 
00476     // From gmsh physical region to Foam patch
00477     Map<label> physToPatch;
00478 
00479     // From gmsh physical region to Foam cellZone
00480     Map<label> physToZone;
00481 
00482 
00483     for (label elemI = 0; elemI < nElems; elemI++)
00484     {
00485         string line;
00486         inFile.getLine(line);
00487         IStringStream lineStr(line);
00488 
00489         label elmNumber, elmType, regPhys;
00490 
00491         if (versionFormat >= 2)
00492         {
00493             lineStr >> elmNumber >> elmType;
00494 
00495             label nTags;
00496             lineStr>> nTags;
00497 
00498             if (nTags > 0)
00499             {
00500                 // Assume the first tag is the physical surface
00501                 lineStr >> regPhys;
00502                 for (label i = 1; i < nTags; i++)
00503                 {
00504                     label dummy;
00505                     lineStr>> dummy;
00506                 }
00507             }
00508         }
00509         else
00510         {
00511             label regElem, nNodes;
00512             lineStr >> elmNumber >> elmType >> regPhys >> regElem >> nNodes;
00513         }
00514 
00515         // regPhys on surface elements is region number.
00516 
00517         if (elmType == MSHTRI)
00518         {
00519             lineStr >> triPoints[0] >> triPoints[1] >> triPoints[2];
00520 
00521             renumber(mshToFoam, triPoints);
00522 
00523             Map<label>::iterator regFnd = physToPatch.find(regPhys);
00524 
00525             label patchI = -1;
00526             if (regFnd == physToPatch.end())
00527             {
00528                 // New region. Allocate patch for it.
00529                 patchI = patchFaces.size();
00530 
00531                 patchFaces.setSize(patchI + 1);
00532                 patchToPhys.setSize(patchI + 1);
00533 
00534                 Info<< "Mapping region " << regPhys << " to Foam patch "
00535                     << patchI << endl;
00536                 physToPatch.insert(regPhys, patchI);
00537                 patchToPhys[patchI] = regPhys;
00538             }
00539             else
00540             {
00541                 // Existing patch for region
00542                 patchI = regFnd();
00543             }
00544 
00545             // Add triangle to correct patchFaces.
00546             patchFaces[patchI].append(triPoints);
00547         }
00548         else if (elmType == MSHQUAD)
00549         {
00550             lineStr
00551                 >> quadPoints[0] >> quadPoints[1] >> quadPoints[2]
00552                 >> quadPoints[3];
00553 
00554             renumber(mshToFoam, quadPoints);
00555 
00556             Map<label>::iterator regFnd = physToPatch.find(regPhys);
00557 
00558             label patchI = -1;
00559             if (regFnd == physToPatch.end())
00560             {
00561                 // New region. Allocate patch for it.
00562                 patchI = patchFaces.size();
00563 
00564                 patchFaces.setSize(patchI + 1);
00565                 patchToPhys.setSize(patchI + 1);
00566 
00567                 Info<< "Mapping region " << regPhys << " to Foam patch "
00568                     << patchI << endl;
00569                 physToPatch.insert(regPhys, patchI);
00570                 patchToPhys[patchI] = regPhys;
00571             }
00572             else
00573             {
00574                 // Existing patch for region
00575                 patchI = regFnd();
00576             }
00577 
00578             // Add quad to correct patchFaces.
00579             patchFaces[patchI].append(quadPoints);
00580         }
00581         else if (elmType == MSHTET)
00582         {
00583             storeCellInZone
00584             (
00585                 regPhys,
00586                 cellI,
00587                 physToZone,
00588                 zoneToPhys,
00589                 zoneCells
00590             );
00591 
00592             lineStr
00593                 >> tetPoints[0] >> tetPoints[1] >> tetPoints[2]
00594                 >> tetPoints[3];
00595 
00596             renumber(mshToFoam, tetPoints);
00597 
00598             cells[cellI++] = cellShape(tet, tetPoints);
00599 
00600             nTet++;
00601         }
00602         else if (elmType == MSHPYR)
00603         {
00604             storeCellInZone
00605             (
00606                 regPhys,
00607                 cellI,
00608                 physToZone,
00609                 zoneToPhys,
00610                 zoneCells
00611             );
00612 
00613             lineStr
00614                 >> pyrPoints[0] >> pyrPoints[1] >> pyrPoints[2]
00615                 >> pyrPoints[3] >> pyrPoints[4];
00616 
00617             renumber(mshToFoam, pyrPoints);
00618 
00619             cells[cellI++] = cellShape(pyr, pyrPoints);
00620 
00621             nPyr++;
00622         }
00623         else if (elmType == MSHPRISM)
00624         {
00625             storeCellInZone
00626             (
00627                 regPhys,
00628                 cellI,
00629                 physToZone,
00630                 zoneToPhys,
00631                 zoneCells
00632             );
00633 
00634             lineStr
00635                 >> prismPoints[0] >> prismPoints[1] >> prismPoints[2]
00636                 >> prismPoints[3] >> prismPoints[4] >> prismPoints[5];
00637 
00638             renumber(mshToFoam, prismPoints);
00639 
00640             cells[cellI] = cellShape(prism, prismPoints);
00641 
00642             const cellShape& cell = cells[cellI];
00643 
00644             if (!keepOrientation && !correctOrientation(points, cell))
00645             {
00646                 Info<< "Inverting prism " << cellI << endl;
00647                 // Reorder prism.
00648                 prismPoints[0] = cell[0];
00649                 prismPoints[1] = cell[2];
00650                 prismPoints[2] = cell[1];
00651                 prismPoints[3] = cell[3];
00652                 prismPoints[4] = cell[4];
00653                 prismPoints[5] = cell[5];
00654 
00655                 cells[cellI] = cellShape(prism, prismPoints);
00656             }
00657 
00658             cellI++;
00659 
00660             nPrism++;
00661         }
00662         else if (elmType == MSHHEX)
00663         {
00664             storeCellInZone
00665             (
00666                 regPhys,
00667                 cellI,
00668                 physToZone,
00669                 zoneToPhys,
00670                 zoneCells
00671             );
00672 
00673             lineStr
00674                 >> hexPoints[0] >> hexPoints[1]
00675                 >> hexPoints[2] >> hexPoints[3]
00676                 >> hexPoints[4] >> hexPoints[5]
00677                 >> hexPoints[6] >> hexPoints[7];
00678 
00679             renumber(mshToFoam, hexPoints);
00680 
00681             cells[cellI] = cellShape(hex, hexPoints);
00682 
00683             const cellShape& cell = cells[cellI];
00684 
00685             if (!keepOrientation && !correctOrientation(points, cell))
00686             {
00687                 Info<< "Inverting hex " << cellI << endl;
00688                 // Reorder hex.
00689                 hexPoints[0] = cell[4];
00690                 hexPoints[1] = cell[5];
00691                 hexPoints[2] = cell[6];
00692                 hexPoints[3] = cell[7];
00693                 hexPoints[4] = cell[0];
00694                 hexPoints[5] = cell[1];
00695                 hexPoints[6] = cell[2];
00696                 hexPoints[7] = cell[3];
00697 
00698                 cells[cellI] = cellShape(hex, hexPoints);
00699             }
00700 
00701             cellI++;
00702 
00703             nHex++;
00704         }
00705         else
00706         {
00707             Info<< "Unhandled element " << elmType << " at line "
00708                 << inFile.lineNumber() << endl;
00709         }
00710     }
00711 
00712 
00713     inFile.getLine(line);
00714     IStringStream tagStr(line);
00715     word tag(tagStr);
00716 
00717     if (tag != "$ENDELM" && tag != "$EndElements")
00718     {
00719         FatalIOErrorIn("readCells(..)", inFile)
00720             << "Did not find $ENDELM tag on line "
00721             << inFile.lineNumber() << exit(FatalIOError);
00722     }
00723 
00724 
00725     cells.setSize(cellI);
00726 
00727     forAll(patchFaces, patchI)
00728     {
00729         patchFaces[patchI].shrink();
00730     }
00731 
00732 
00733     Info<< "Cells:" << endl
00734     << "    total:" << cells.size() << endl
00735     << "    hex  :" << nHex << endl
00736     << "    prism:" << nPrism << endl
00737     << "    pyr  :" << nPyr << endl
00738     << "    tet  :" << nTet << endl
00739     << endl;
00740 
00741     if (cells.size() == 0)
00742     {
00743         FatalIOErrorIn("readCells(..)", inFile)
00744             << "No cells read from file " << inFile.name() << nl
00745             << "Does your file specify any 3D elements (hex=" << MSHHEX
00746             << ", prism=" << MSHPRISM << ", pyramid=" << MSHPYR
00747             << ", tet=" << MSHTET << ")?" << nl
00748             << "Perhaps you have not exported the 3D elements?"
00749             << exit(FatalIOError);
00750     }
00751 
00752     Info<< "CellZones:" << nl
00753         << "Zone\tSize" << endl;
00754 
00755     forAll(zoneCells, zoneI)
00756     {
00757         zoneCells[zoneI].shrink();
00758 
00759         const labelList& zCells = zoneCells[zoneI];
00760 
00761         if (zCells.size())
00762         {
00763             Info<< "    " << zoneI << '\t' << zCells.size() << endl;
00764         }
00765     }
00766     Info<< endl;
00767 }
00768 
00769 
00770 // Main program:
00771 
00772 int main(int argc, char *argv[])
00773 {
00774     argList::noParallel();
00775     argList::validArgs.append(".msh file");
00776     argList::validOptions.insert("keepOrientation", "");
00777 
00778 #   include <OpenFOAM/setRootCase.H>
00779 #   include <OpenFOAM/createTime.H>
00780 
00781     fileName mshName(args.additionalArgs()[0]);
00782 
00783     bool keepOrientation = args.optionFound("keepOrientation");
00784 
00785     // Storage for points
00786     pointField points;
00787     Map<label> mshToFoam;
00788 
00789     // Storage for all cells.
00790     cellShapeList cells;
00791 
00792     // Map from patch to gmsh physical region
00793     labelList patchToPhys;
00794     // Storage for patch faces.
00795     List<DynamicList<face> > patchFaces(0);
00796 
00797     // Map from cellZone to gmsh physical region
00798     labelList zoneToPhys;
00799     // Storage for cell zones.
00800     List<DynamicList<label> > zoneCells(0);
00801 
00802     // Name per physical region
00803     Map<word> physicalNames;
00804 
00805     // Version 1 or 2 format
00806     scalar versionFormat = 1;
00807 
00808 
00809     IFstream inFile(mshName);
00810 
00811     while (inFile.good())
00812     {
00813         string line;
00814         inFile.getLine(line);
00815         IStringStream lineStr(line);
00816 
00817         word tag(lineStr);
00818 
00819         if (tag == "$MeshFormat")
00820         {
00821             Info<< "Found $MeshFormat tag; assuming version 2 file format."
00822                 << endl;
00823             versionFormat = readMeshFormat(inFile);
00824         }
00825         else if (tag == "$PhysicalNames")
00826         {
00827             readPhysNames(inFile, physicalNames);
00828         }
00829         else if (tag == "$NOD" || tag == "$Nodes")
00830         {
00831             readPoints(inFile, points, mshToFoam);
00832         }
00833         else if (tag == "$ELM" || tag == "$Elements")
00834         {
00835             readCells
00836             (
00837                 versionFormat,
00838                 keepOrientation,
00839                 points,
00840                 mshToFoam,
00841                 inFile,
00842                 cells,
00843                 patchToPhys,
00844                 patchFaces,
00845                 zoneToPhys,
00846                 zoneCells
00847             );
00848         }
00849         else
00850         {
00851             Info<< "Skipping tag " << tag << " at line "
00852                 << inFile.lineNumber()
00853                 << endl;
00854 
00855             if (!skipSection(inFile))
00856             {
00857                 break;
00858             }
00859         }
00860     }
00861 
00862 
00863     label nValidCellZones = 0;
00864 
00865     forAll(zoneCells, zoneI)
00866     {
00867         if (zoneCells[zoneI].size())
00868         {
00869             nValidCellZones++;
00870         }
00871     }
00872 
00873 
00874     // Problem is that the orientation of the patchFaces does not have to
00875     // be consistent with the outwards orientation of the mesh faces. So
00876     // we have to construct the mesh in two stages:
00877     // 1. define mesh with all boundary faces in one patch
00878     // 2. use the read patchFaces to find the corresponding boundary face
00879     //    and repatch it.
00880 
00881 
00882     // Create correct number of patches
00883     // (but without any faces in it)
00884     faceListList boundaryFaces(patchFaces.size());
00885 
00886     wordList boundaryPatchNames(boundaryFaces.size());
00887 
00888     forAll(boundaryPatchNames, patchI)
00889     {
00890         label physReg = patchToPhys[patchI];
00891 
00892         Map<word>::const_iterator iter = physicalNames.find(physReg);
00893 
00894         if (iter != physicalNames.end())
00895         {
00896             boundaryPatchNames[patchI] = iter();
00897         }
00898         else
00899         {
00900             boundaryPatchNames[patchI] = word("patch") + name(patchI);
00901         }
00902         Info<< "Patch " << patchI << " gets name "
00903             << boundaryPatchNames[patchI] << endl;
00904     }
00905     Info<< endl;
00906 
00907     wordList boundaryPatchTypes(boundaryFaces.size(), polyPatch::typeName);
00908     word defaultFacesName = "defaultFaces";
00909     word defaultFacesType = polyPatch::typeName;
00910     wordList boundaryPatchPhysicalTypes
00911     (
00912         boundaryFaces.size(),
00913         polyPatch::typeName
00914     );
00915 
00916     polyMesh mesh
00917     (
00918         IOobject
00919         (
00920             polyMesh::defaultRegion,
00921             runTime.constant(),
00922             runTime
00923         ),
00924         xferMove(points),
00925         cells,
00926         boundaryFaces,
00927         boundaryPatchNames,
00928         boundaryPatchTypes,
00929         defaultFacesName,
00930         defaultFacesType,
00931         boundaryPatchPhysicalTypes
00932     );
00933 
00934     repatchPolyTopoChanger repatcher(mesh);
00935 
00936     // Now use the patchFaces to patch up the outside faces of the mesh.
00937 
00938     // Get the patch for all the outside faces (= default patch added as last)
00939     const polyPatch& pp = mesh.boundaryMesh()[mesh.boundaryMesh().size()-1];
00940 
00941     // Storage for faceZones.
00942     List<DynamicList<label> > zoneFaces(patchFaces.size());
00943 
00944 
00945     // Go through all the patchFaces and find corresponding face in pp.
00946     forAll(patchFaces, patchI)
00947     {
00948         const DynamicList<face>& pFaces = patchFaces[patchI];
00949 
00950         Info<< "Finding faces of patch " << patchI << endl;
00951 
00952         forAll(pFaces, i)
00953         {
00954             const face& f = pFaces[i];
00955 
00956             // Find face in pp using all vertices of f.
00957             label patchFaceI = findFace(pp, f);
00958 
00959             if (patchFaceI != -1)
00960             {
00961                 label meshFaceI = pp.start() + patchFaceI;
00962 
00963                 repatcher.changePatchID(meshFaceI, patchI);
00964             }
00965             else
00966             {
00967                 // Maybe internal face? If so add to faceZone with same index
00968                 // - might be useful.
00969                 label meshFaceI = findInternalFace(mesh, f);
00970 
00971                 if (meshFaceI != -1)
00972                 {
00973                     zoneFaces[patchI].append(meshFaceI);
00974                 }
00975                 else
00976                 {
00977                     WarningIn(args.executable())
00978                         << "Could not match gmsh face " << f
00979                         << " to any of the interior or exterior faces"
00980                         << " that share the same 0th point" << endl;
00981                 }
00982             }
00983         }
00984     }
00985     Info<< nl;
00986 
00987     // Face zones
00988     label nValidFaceZones = 0;
00989 
00990     Info<< "FaceZones:" << nl
00991         << "Zone\tSize" << endl;
00992 
00993     forAll(zoneFaces, zoneI)
00994     {
00995         zoneFaces[zoneI].shrink();
00996 
00997         const labelList& zFaces = zoneFaces[zoneI];
00998 
00999         if (zFaces.size())
01000         {
01001             nValidFaceZones++;
01002 
01003             Info<< "    " << zoneI << '\t' << zFaces.size() << endl;
01004         }
01005     }
01006     Info<< endl;
01007 
01008 
01009     //Get polyMesh to write to constant
01010     runTime.setTime(instant(runTime.constant()), 0);
01011 
01012     repatcher.repatch();
01013 
01014     List<cellZone*> cz;
01015     List<faceZone*> fz;
01016 
01017     // Construct and add the zones. Note that cell ordering does not change
01018     // because of repatch() and neither does internal faces so we can
01019     // use the zoneCells/zoneFaces as is.
01020 
01021     if (nValidCellZones > 0)
01022     {
01023         cz.setSize(nValidCellZones);
01024 
01025         nValidCellZones = 0;
01026 
01027         forAll(zoneCells, zoneI)
01028         {
01029             if (zoneCells[zoneI].size())
01030             {
01031                 label physReg = zoneToPhys[zoneI];
01032 
01033                 Map<word>::const_iterator iter = physicalNames.find(physReg);
01034 
01035                 word zoneName = "cellZone_" + name(zoneI);
01036                 if (iter != physicalNames.end())
01037                 {
01038                     zoneName = iter();
01039                 }
01040 
01041                 Info<< "Writing zone " << zoneI << " to cellZone "
01042                     << zoneName << " and cellSet"
01043                     << endl;
01044 
01045                 cellSet cset(mesh, zoneName, zoneCells[zoneI]);
01046                 cset.write();
01047 
01048                 cz[nValidCellZones] = new cellZone
01049                 (
01050                     zoneName,
01051                     zoneCells[zoneI],
01052                     nValidCellZones,
01053                     mesh.cellZones()
01054                 );
01055                 nValidCellZones++;
01056             }
01057         }
01058     }
01059 
01060     if (nValidFaceZones > 0)
01061     {
01062         fz.setSize(nValidFaceZones);
01063 
01064         nValidFaceZones = 0;
01065 
01066         forAll(zoneFaces, zoneI)
01067         {
01068             if (zoneFaces[zoneI].size())
01069             {
01070                 label physReg = zoneToPhys[zoneI];
01071 
01072                 Map<word>::const_iterator iter = physicalNames.find(physReg);
01073 
01074                 word zoneName = "faceZone_" + name(zoneI);
01075                 if (iter != physicalNames.end())
01076                 {
01077                     zoneName = iter();
01078                 }
01079 
01080                 Info<< "Writing zone " << zoneI << " to faceZone "
01081                     << zoneName << " and faceSet"
01082                     << endl;
01083 
01084                 faceSet fset(mesh, zoneName, zoneFaces[zoneI]);
01085                 fset.write();
01086 
01087                 fz[nValidFaceZones] = new faceZone
01088                 (
01089                     zoneName,
01090                     zoneFaces[zoneI],
01091                     boolList(zoneFaces[zoneI].size(), true),
01092                     nValidFaceZones,
01093                     mesh.faceZones()
01094                 );
01095                 nValidFaceZones++;
01096             }
01097         }
01098     }
01099 
01100     if (cz.size() || fz.size())
01101     {
01102         mesh.addZones(List<pointZone*>(0), fz, cz);
01103     }
01104 
01105     mesh.write();
01106 
01107     Info<< "End\n" << endl;
01108 
01109     return 0;
01110 }
01111 
01112 
01113 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines