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

reconstructParMesh.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     reconstructParMesh
00026 
00027 Description
00028     Reconstructs a mesh using geometric information only.
00029 
00030     Writes point/face/cell procAddressing so afterwards reconstructPar can be
00031     used to reconstruct fields.
00032 
00033 Note
00034     Uses geometric matching tolerance (set with -mergeTol option)
00035 
00036     If the parallel case does not have correct procBoundaries use the
00037     -fullMatch option which will check all boundary faces (bit slower).
00038 
00039 Usage
00040 
00041     - reconstructParMesh [OPTIONS]
00042 
00043     @param -fullMatch \n
00044     Check all boundary faces.
00045 
00046     @param -mergeTol <number>\n
00047     Relative merge distance.
00048 
00049     @param -region <name>\n
00050     Only apply to named mesh region.
00051 
00052     @param -noZero \n
00053     Ignore timestep 0.
00054 
00055     @param -constant \n
00056     Include the constant directory.
00057 
00058     @param -time <time>\n
00059     Apply only to specific time.
00060 
00061     @param -latestTime \n
00062     Only apply to latest time step.
00063 
00064     @param -case <dir>\n
00065     Case directory.
00066 
00067     @param -help \n
00068     Display help message.
00069 
00070     @param -doc \n
00071     Display Doxygen API documentation page for this application.
00072 
00073     @param -srcDoc \n
00074     Display Doxygen source documentation page for this application.
00075 
00076 \*---------------------------------------------------------------------------*/
00077 
00078 #include <OpenFOAM/argList.H>
00079 #include <OpenFOAM/Time.H>
00080 #include <OpenFOAM/IOobjectList.H>
00081 #include <OpenFOAM/labelIOList.H>
00082 #include <OpenFOAM/processorPolyPatch.H>
00083 #include <OpenFOAM/mapAddedPolyMesh.H>
00084 #include <dynamicMesh/polyMeshAdder.H>
00085 #include <dynamicMesh/faceCoupleInfo.H>
00086 #include <dynamicMesh/fvMeshAdder.H>
00087 #include <dynamicMesh/polyTopoChange.H>
00088 
00089 using namespace Foam;
00090 
00091 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00092 
00093 // Tolerance (as fraction of the bounding box). Needs to be fairly lax since
00094 // usually meshes get written with limited precision (6 digits)
00095 static const scalar defaultMergeTol = 1E-7;
00096 
00097 
00098 static void renumber
00099 (
00100     const labelList& map,
00101     labelList& elems
00102 )
00103 {
00104     forAll(elems, i)
00105     {
00106         if (elems[i] >= 0)
00107         {
00108             elems[i] = map[elems[i]];
00109         }
00110     }
00111 }
00112 
00113 
00114 // Determine which faces are coupled. Uses geometric merge distance.
00115 // Looks either at all boundaryFaces (fullMatch) or only at the
00116 // procBoundaries for procI. Assumes that masterMesh contains already merged
00117 // all the processors < procI.
00118 autoPtr<faceCoupleInfo> determineCoupledFaces
00119 (
00120     const bool fullMatch,
00121     const label procI,
00122     const polyMesh& masterMesh,
00123     const polyMesh& meshToAdd,
00124     const scalar mergeDist
00125 )
00126 {
00127     if (fullMatch || masterMesh.nCells() == 0)
00128     {
00129         return autoPtr<faceCoupleInfo>
00130         (
00131             new faceCoupleInfo
00132             (
00133                 masterMesh,
00134                 meshToAdd,
00135                 mergeDist,      // absolute merging distance
00136                 true            // matching faces identical
00137             )
00138         );
00139     }
00140     else
00141     {
00142         // Pick up all patches on masterMesh ending in "toDDD" where DDD is
00143         // the processor number procI.
00144 
00145         const polyBoundaryMesh& masterPatches = masterMesh.boundaryMesh();
00146 
00147         const string toProcString("to" + name(procI));
00148 
00149         DynamicList<label> masterFaces
00150         (
00151             masterMesh.nFaces()
00152           - masterMesh.nInternalFaces()
00153         );
00154 
00155         forAll(masterPatches, patchI)
00156         {
00157             const polyPatch& pp = masterPatches[patchI];
00158 
00159             if
00160             (
00161                 isA<processorPolyPatch>(pp)
00162              && (
00163                     pp.name().rfind(toProcString)
00164                  == (pp.name().size()-toProcString.size())
00165                 )
00166             )
00167             {
00168                 label meshFaceI = pp.start();
00169                 forAll(pp, i)
00170                 {
00171                     masterFaces.append(meshFaceI++);
00172                 }
00173             }
00174         }
00175         masterFaces.shrink();
00176 
00177 
00178         // Pick up all patches on meshToAdd ending in "procBoundaryDDDtoYYY"
00179         // where DDD is the processor number procI and YYY is < procI.
00180 
00181         const polyBoundaryMesh& addPatches = meshToAdd.boundaryMesh();
00182 
00183         DynamicList<label> addFaces
00184         (
00185             meshToAdd.nFaces()
00186           - meshToAdd.nInternalFaces()
00187         );
00188 
00189         forAll(addPatches, patchI)
00190         {
00191             const polyPatch& pp = addPatches[patchI];
00192 
00193             if (isA<processorPolyPatch>(pp))
00194             {
00195                 bool isConnected = false;
00196 
00197                 for (label mergedProcI = 0; mergedProcI < procI; mergedProcI++)
00198                 {
00199                     const string fromProcString
00200                     (
00201                         "procBoundary"
00202                       + name(procI)
00203                       + "to"
00204                       + name(mergedProcI)
00205                     );
00206 
00207                     if (pp.name() == fromProcString)
00208                     {
00209                         isConnected = true;
00210                         break;
00211                     }
00212                 }
00213 
00214                 if (isConnected)
00215                 {
00216                     label meshFaceI = pp.start();
00217                     forAll(pp, i)
00218                     {
00219                         addFaces.append(meshFaceI++);
00220                     }
00221                 }
00222             }
00223         }
00224         addFaces.shrink();
00225 
00226         return autoPtr<faceCoupleInfo>
00227         (
00228             new faceCoupleInfo
00229             (
00230                 masterMesh,
00231                 masterFaces,
00232                 meshToAdd,
00233                 addFaces,
00234                 mergeDist,      // absolute merging distance
00235                 true,           // matching faces identical?
00236                 false,          // if perfectmatch are faces already ordered
00237                                 // (e.g. processor patches)
00238                 false           // are faces each on separate patch?
00239             )
00240         );
00241     }
00242 }
00243 
00244 
00245 autoPtr<mapPolyMesh> mergeSharedPoints
00246 (
00247     const scalar mergeDist,
00248     polyMesh& mesh,
00249     labelListList& pointProcAddressing
00250 )
00251 {
00252     // Find out which sets of points get merged and create a map from
00253     // mesh point to unique point.
00254     Map<label> pointToMaster
00255     (
00256         fvMeshAdder::findSharedPoints
00257         (
00258             mesh,
00259             mergeDist
00260         )
00261     );
00262 
00263     Info<< "mergeSharedPoints : detected " << pointToMaster.size()
00264         << " points that are to be merged." << endl;
00265 
00266     if (returnReduce(pointToMaster.size(), sumOp<label>()) == 0)
00267     {
00268         return autoPtr<mapPolyMesh>(NULL);
00269     }
00270 
00271     polyTopoChange meshMod(mesh);
00272 
00273     fvMeshAdder::mergePoints(mesh, pointToMaster, meshMod);
00274 
00275     // Change the mesh (no inflation). Note: parallel comms allowed.
00276     autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false, true);
00277 
00278     // Update fields. No inflation, parallel sync.
00279     mesh.updateMesh(map);
00280 
00281     // pointProcAddressing give indices into the master mesh so adapt them
00282     // for changed point numbering.
00283 
00284     // Adapt constructMaps for merged points.
00285     forAll(pointProcAddressing, procI)
00286     {
00287         labelList& constructMap = pointProcAddressing[procI];
00288 
00289         forAll(constructMap, i)
00290         {
00291             label oldPointI = constructMap[i];
00292 
00293             // New label of point after changeMesh.
00294             label newPointI = map().reversePointMap()[oldPointI];
00295 
00296             if (newPointI < -1)
00297             {
00298                 constructMap[i] = -newPointI-2;
00299             }
00300             else if (newPointI >= 0)
00301             {
00302                 constructMap[i] = newPointI;
00303             }
00304             else
00305             {
00306                 FatalErrorIn("fvMeshDistribute::mergeSharedPoints()")
00307                     << "Problem. oldPointI:" << oldPointI
00308                     << " newPointI:" << newPointI << abort(FatalError);
00309             }
00310         }
00311     }
00312 
00313     return map;
00314 }
00315 
00316 
00317 int main(int argc, char *argv[])
00318 {
00319     argList::noParallel();
00320     argList::validOptions.insert("mergeTol", "relative merge distance");
00321     argList::validOptions.insert("fullMatch", "");
00322 
00323 #   include <OpenFOAM/addTimeOptions.H>
00324 #   include <OpenFOAM/addRegionOption.H>
00325 #   include <OpenFOAM/setRootCase.H>
00326 #   include <OpenFOAM/createTime.H>
00327 
00328     Info<< "This is an experimental tool which tries to merge"
00329         << " individual processor" << nl
00330         << "meshes back into one master mesh. Use it if the original"
00331         << " master mesh has" << nl
00332         << "been deleted or if the processor meshes have been modified"
00333         << " (topology change)." << nl
00334         << "This tool will write the resulting mesh to a new time step"
00335         << " and construct" << nl
00336         << "xxxxProcAddressing files in the processor meshes so"
00337         << " reconstructPar can be" << nl
00338         << "used to regenerate the fields on the master mesh." << nl
00339         << nl
00340         << "Not well tested & use at your own risk!" << nl
00341         << endl;
00342 
00343 
00344     word regionName = polyMesh::defaultRegion;
00345     fileName regionPrefix = "";
00346     if (args.optionFound("region"))
00347     {
00348         regionName = args.option("region");
00349         regionPrefix = regionName;
00350         Info<< "Operating on region " << regionName << nl << endl;
00351     }
00352 
00353     scalar mergeTol = defaultMergeTol;
00354     args.optionReadIfPresent("mergeTol", mergeTol);
00355 
00356     scalar writeTol = Foam::pow(10.0, -scalar(IOstream::defaultPrecision()));
00357 
00358     Info<< "Merge tolerance : " << mergeTol << nl
00359         << "Write tolerance : " << writeTol << endl;
00360 
00361     if (runTime.writeFormat() == IOstream::ASCII && mergeTol < writeTol)
00362     {
00363         FatalErrorIn(args.executable())
00364             << "Your current settings specify ASCII writing with "
00365             << IOstream::defaultPrecision() << " digits precision." << endl
00366             << "Your merging tolerance (" << mergeTol << ") is finer than this."
00367             << endl
00368             << "Please change your writeFormat to binary"
00369             << " or increase the writePrecision" << endl
00370             << "or adjust the merge tolerance (-mergeTol)."
00371             << exit(FatalError);
00372     }
00373 
00374 
00375     const bool fullMatch = args.optionFound("fullMatch");
00376 
00377     if (fullMatch)
00378     {
00379         Info<< "Doing geometric matching on all boundary faces." << nl << endl;
00380     }
00381     else
00382     {
00383         Info<< "Doing geometric matching on correct procBoundaries only."
00384             << nl << "This assumes a correct decomposition." << endl;
00385     }
00386 
00387 
00388 
00389     int nProcs = 0;
00390 
00391     while
00392     (
00393         isDir
00394         (
00395             args.rootPath()
00396           / args.caseName()
00397           / fileName(word("processor") + name(nProcs))
00398         )
00399     )
00400     {
00401         nProcs++;
00402     }
00403 
00404     Info<< "Found " << nProcs << " processor directories" << nl << endl;
00405 
00406 
00407     // Read all databases.
00408     PtrList<Time> databases(nProcs);
00409 
00410     forAll (databases, procI)
00411     {
00412         Info<< "Reading database "
00413             << args.caseName()/fileName(word("processor") + name(procI))
00414             << endl;
00415 
00416         databases.set
00417         (
00418             procI,
00419             new Time
00420             (
00421                 Time::controlDictName,
00422                 args.rootPath(),
00423                 args.caseName()/fileName(word("processor") + name(procI))
00424             )
00425         );
00426 
00427         Time& procTime = databases[procI];
00428 
00429         instantList Times = procTime.times();
00430 
00431         // set startTime and endTime depending on -time and -latestTime options
00432 #       include <OpenFOAM/checkTimeOptions.H>
00433 
00434         procTime.setTime(Times[startTime], startTime);
00435 
00436         if (procI > 0 && databases[procI-1].value() != procTime.value())
00437         {
00438             FatalErrorIn(args.executable())
00439                 << "Time not equal on processors." << nl
00440                 << "Processor:" << procI-1
00441                 << " time:" << databases[procI-1].value() << nl
00442                 << "Processor:" << procI
00443                 << " time:" << procTime.value()
00444                 << exit(FatalError);
00445         }
00446     }
00447 
00448     // Set master time
00449     Info<< "Setting master time to " << databases[0].timeName() << nl << endl;
00450     runTime.setTime(databases[0]);
00451 
00452 
00453     // Read point on individual processors to determine merge tolerance
00454     // (otherwise single cell domains might give problems)
00455 
00456     boundBox bb = boundBox::invertedBox;
00457 
00458     for (label procI = 0; procI < nProcs; procI++)
00459     {
00460         fileName pointsInstance
00461         (
00462             databases[procI].findInstance
00463             (
00464                 regionPrefix/polyMesh::meshSubDir,
00465                 "points"
00466             )
00467         );
00468 
00469         if (pointsInstance != databases[procI].timeName())
00470         {
00471             FatalErrorIn(args.executable())
00472                 << "Your time was specified as " << databases[procI].timeName()
00473                 << " but there is no polyMesh/points in that time." << endl
00474                 << "(there is a points file in " << pointsInstance
00475                 << ")" << endl
00476                 << "Please rerun with the correct time specified"
00477                 << " (through the -constant, -time or -latestTime option)."
00478                 << endl << exit(FatalError);
00479         }
00480 
00481         Info<< "Reading points from "
00482             << databases[procI].caseName()
00483             << " for time = " << databases[procI].timeName()
00484             << nl << endl;
00485 
00486         pointIOField points
00487         (
00488             IOobject
00489             (
00490                 "points",
00491                 databases[procI].findInstance
00492                 (
00493                     regionPrefix/polyMesh::meshSubDir,
00494                     "points"
00495                 ),
00496                 regionPrefix/polyMesh::meshSubDir,
00497                 databases[procI],
00498                 IOobject::MUST_READ,
00499                 IOobject::NO_WRITE,
00500                 false
00501             )
00502         );
00503 
00504         boundBox domainBb(points, false);
00505 
00506         bb.min() = min(bb.min(), domainBb.min());
00507         bb.max() = max(bb.max(), domainBb.max());
00508     }
00509     const scalar mergeDist = mergeTol * bb.mag();
00510 
00511     Info<< "Overall mesh bounding box  : " << bb << nl
00512         << "Relative tolerance         : " << mergeTol << nl
00513         << "Absolute matching distance : " << mergeDist << nl
00514         << endl;
00515 
00516 
00517     // Addressing from processor to reconstructed case
00518     labelListList cellProcAddressing(nProcs);
00519     labelListList faceProcAddressing(nProcs);
00520     labelListList pointProcAddressing(nProcs);
00521     labelListList boundaryProcAddressing(nProcs);
00522 
00523     // Internal faces on the final reconstructed mesh
00524     label masterInternalFaces;
00525     // Owner addressing on the final reconstructed mesh
00526     labelList masterOwner;
00527 
00528     {
00529         // Construct empty mesh.
00530         Info<< "Constructing empty mesh to add to." << nl << endl;
00531         polyMesh masterMesh
00532         (
00533             IOobject
00534             (
00535                 regionName,
00536                 runTime.timeName(),
00537                 runTime,
00538                 IOobject::NO_READ
00539             ),
00540             xferCopy(pointField()),
00541             xferCopy(faceList()),
00542             xferCopy(cellList())
00543         );
00544 
00545         for (label procI = 0; procI < nProcs; procI++)
00546         {
00547             Info<< "Reading mesh to add from "
00548                 << databases[procI].caseName()
00549                 << " for time = " << databases[procI].timeName()
00550                 << nl << endl;
00551 
00552             polyMesh meshToAdd
00553             (
00554                 IOobject
00555                 (
00556                     regionName,
00557                     databases[procI].timeName(),
00558                     databases[procI]
00559                 )
00560             );
00561 
00562             // Initialize its addressing
00563             cellProcAddressing[procI] = identity(meshToAdd.nCells());
00564             faceProcAddressing[procI] = identity(meshToAdd.nFaces());
00565             pointProcAddressing[procI] = identity(meshToAdd.nPoints());
00566             boundaryProcAddressing[procI] =
00567                 identity(meshToAdd.boundaryMesh().size());
00568 
00569 
00570             // Find geometrically shared points/faces.
00571             autoPtr<faceCoupleInfo> couples = determineCoupledFaces
00572             (
00573                 fullMatch,
00574                 procI,
00575                 masterMesh,
00576                 meshToAdd,
00577                 mergeDist
00578             );
00579 
00580 
00581             // Add elements to mesh
00582             Info<< "Adding to master mesh" << nl << endl;
00583 
00584             autoPtr<mapAddedPolyMesh> map = polyMeshAdder::add
00585             (
00586                 masterMesh,
00587                 meshToAdd,
00588                 couples
00589             );
00590 
00591             // Update all addressing so xxProcAddressing points to correct item
00592             // in masterMesh.
00593 
00594             // Processors that were already in masterMesh
00595             for (label mergedI = 0; mergedI < procI; mergedI++)
00596             {
00597                 renumber(map().oldCellMap(), cellProcAddressing[mergedI]);
00598                 renumber(map().oldFaceMap(), faceProcAddressing[mergedI]);
00599                 renumber(map().oldPointMap(), pointProcAddressing[mergedI]);
00600                 // Note: boundary is special since can contain -1.
00601                 renumber(map().oldPatchMap(), boundaryProcAddressing[mergedI]);
00602             }
00603 
00604             // Added processor
00605             renumber(map().addedCellMap(), cellProcAddressing[procI]);
00606             renumber(map().addedFaceMap(), faceProcAddressing[procI]);
00607             renumber(map().addedPointMap(), pointProcAddressing[procI]);
00608             renumber(map().addedPatchMap(), boundaryProcAddressing[procI]);
00609 
00610             Info<< endl;
00611         }
00612 
00613         // See if any points on the mastermesh have become connected
00614         // because of connections through processor meshes.
00615         mergeSharedPoints(mergeDist, masterMesh, pointProcAddressing);
00616 
00617         // Save some properties on the reconstructed mesh
00618         masterInternalFaces = masterMesh.nInternalFaces();
00619         masterOwner = masterMesh.faceOwner();
00620 
00621 
00622         Info<< "\nWriting merged mesh to "
00623             << runTime.path()/runTime.timeName()
00624             << nl << endl;
00625 
00626         if (!masterMesh.write())
00627         {
00628             FatalErrorIn(args.executable())
00629                 << "Failed writing polyMesh."
00630                 << exit(FatalError);
00631         }
00632     }
00633 
00634 
00635     // Write the addressing
00636 
00637     Info<< "Reconstructing the addressing from the processor meshes"
00638         << " to the newly reconstructed mesh" << nl << endl;
00639 
00640     forAll(databases, procI)
00641     {
00642         Info<< "Reading processor " << procI << " mesh from "
00643             << databases[procI].caseName() << endl;
00644 
00645         polyMesh procMesh
00646         (
00647             IOobject
00648             (
00649                 regionName,
00650                 databases[procI].timeName(),
00651                 databases[procI]
00652             )
00653         );
00654 
00655 
00656         // From processor point to reconstructed mesh point
00657 
00658         Info<< "Writing pointProcAddressing to "
00659             << databases[procI].caseName()
00660               /procMesh.facesInstance()
00661               /polyMesh::meshSubDir
00662             << endl;
00663 
00664         labelIOList
00665         (
00666             IOobject
00667             (
00668                 "pointProcAddressing",
00669                 procMesh.facesInstance(),
00670                 polyMesh::meshSubDir,
00671                 procMesh,
00672                 IOobject::NO_READ,
00673                 IOobject::NO_WRITE,
00674                 false                       // do not register
00675             ),
00676             pointProcAddressing[procI]
00677         ).write();
00678 
00679 
00680         // From processor face to reconstructed mesh face
00681 
00682         Info<< "Writing faceProcAddressing to "
00683             << databases[procI].caseName()
00684               /procMesh.facesInstance()
00685               /polyMesh::meshSubDir
00686             << endl;
00687 
00688         labelIOList faceProcAddr
00689         (
00690             IOobject
00691             (
00692                 "faceProcAddressing",
00693                 procMesh.facesInstance(),
00694                 polyMesh::meshSubDir,
00695                 procMesh,
00696                 IOobject::NO_READ,
00697                 IOobject::NO_WRITE,
00698                 false                       // do not register
00699             ),
00700             faceProcAddressing[procI]
00701         );
00702 
00703         // Now add turning index to faceProcAddressing.
00704         // See reconstrurPar for meaning of turning index.
00705         forAll(faceProcAddr, procFaceI)
00706         {
00707             label masterFaceI = faceProcAddr[procFaceI];
00708 
00709             if
00710             (
00711                !procMesh.isInternalFace(procFaceI)
00712              && masterFaceI < masterInternalFaces
00713             )
00714             {
00715                 // proc face is now external but used to be internal face.
00716                 // Check if we have owner or neighbour.
00717 
00718                 label procOwn = procMesh.faceOwner()[procFaceI];
00719                 label masterOwn = masterOwner[masterFaceI];
00720 
00721                 if (cellProcAddressing[procI][procOwn] == masterOwn)
00722                 {
00723                     // No turning. Offset by 1.
00724                     faceProcAddr[procFaceI]++;
00725                 }
00726                 else
00727                 {
00728                     // Turned face.
00729                     faceProcAddr[procFaceI] =
00730                         -1 - faceProcAddr[procFaceI];
00731                 }
00732             }
00733             else
00734             {
00735                 // No turning. Offset by 1.
00736                 faceProcAddr[procFaceI]++;
00737             }
00738         }
00739 
00740         faceProcAddr.write();
00741 
00742 
00743         // From processor cell to reconstructed mesh cell
00744 
00745         Info<< "Writing cellProcAddressing to "
00746             << databases[procI].caseName()
00747               /procMesh.facesInstance()
00748               /polyMesh::meshSubDir
00749             << endl;
00750 
00751         labelIOList
00752         (
00753             IOobject
00754             (
00755                 "cellProcAddressing",
00756                 procMesh.facesInstance(),
00757                 polyMesh::meshSubDir,
00758                 procMesh,
00759                 IOobject::NO_READ,
00760                 IOobject::NO_WRITE,
00761                 false                       // do not register
00762             ),
00763             cellProcAddressing[procI]
00764         ).write();
00765 
00766 
00767 
00768         // From processor patch to reconstructed mesh patch
00769 
00770         Info<< "Writing boundaryProcAddressing to "
00771             << databases[procI].caseName()
00772               /procMesh.facesInstance()
00773               /polyMesh::meshSubDir
00774             << endl;
00775 
00776         labelIOList
00777         (
00778             IOobject
00779             (
00780                 "boundaryProcAddressing",
00781                 procMesh.facesInstance(),
00782                 polyMesh::meshSubDir,
00783                 procMesh,
00784                 IOobject::NO_READ,
00785                 IOobject::NO_WRITE,
00786                 false                       // do not register
00787             ),
00788             boundaryProcAddressing[procI]
00789         ).write();
00790 
00791         Info<< endl;
00792     }
00793 
00794     Info<< "End.\n" << endl;
00795 
00796     return 0;
00797 }
00798 
00799 
00800 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines