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

stitchMesh.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     stitchMesh
00026 
00027 Description
00028     'Stitches' a mesh.
00029 
00030     Takes a mesh and two patches and merges the faces on the two patches
00031     (if geometrically possible) so the faces become internal.
00032 
00033     Can do
00034     - 'perfect' match: faces and points on patches align exactly. Order might
00035     be different though.
00036     - 'integral' match: where the surfaces on both patches exactly
00037     match but the individual faces not
00038     - 'partial' match: where the non-overlapping part of the surface remains
00039     in the respective patch.
00040 
00041 Note
00042     Is just a front-end to perfectInterface/slidingInterface.
00043 
00044     Comparable to running a meshModifier of the form
00045     (if masterPatch is called "M" and slavePatch "S"):
00046 
00047     couple
00048     {
00049         type                    slidingInterface;
00050         masterFaceZoneName      MSMasterZone
00051         slaveFaceZoneName       MSSlaveZone
00052         cutPointZoneName        MSCutPointZone
00053         cutFaceZoneName         MSCutFaceZone
00054         masterPatchName         M;
00055         slavePatchName          S;
00056         typeOfMatch             partial or integral
00057     }
00058 
00059 
00060 Usage
00061 
00062     - stitchMesh [OPTIONS] <masterPatch> <slavePatch>
00063 
00064     @param <masterPatch> \n
00065     @todo Detailed description of argument.
00066 
00067     @param <slavePatch> \n
00068     @todo Detailed description of argument.
00069 
00070     @param -perfect \n
00071     The patches, vertices and face centres are perfectly aligned.
00072 
00073     @param -partial \n
00074     The surface overlap only partialy.
00075 
00076     @param -overwrite \n
00077     Overwrite existing data.
00078 
00079     @param -case <dir>\n
00080     Case directory.
00081 
00082     @param -help \n
00083     Display help message.
00084 
00085     @param -doc \n
00086     Display Doxygen API documentation page for this application.
00087 
00088     @param -srcDoc \n
00089     Display Doxygen source documentation page for this application.
00090 
00091 \*---------------------------------------------------------------------------*/
00092 
00093 #include <finiteVolume/fvCFD.H>
00094 #include <dynamicMesh/polyTopoChanger.H>
00095 #include <OpenFOAM/mapPolyMesh.H>
00096 #include <OpenFOAM/ListOps.H>
00097 #include <dynamicMesh/slidingInterface.H>
00098 #include <dynamicMesh/perfectInterface.H>
00099 #include <OpenFOAM/IOobjectList.H>
00100 #include <OpenFOAM/ReadFields.H>
00101 
00102 
00103 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00104 
00105 label addPointZone(const polyMesh& mesh, const word& name)
00106 {
00107     label zoneID = mesh.pointZones().findZoneID(name);
00108 
00109     if (zoneID != -1)
00110     {
00111         Info<< "Reusing existing pointZone "
00112             << mesh.pointZones()[zoneID].name()
00113             << " at index " << zoneID << endl;
00114     }
00115     else
00116     {
00117         pointZoneMesh& pointZones = const_cast<polyMesh&>(mesh).pointZones();
00118         zoneID = pointZones.size();
00119         Info<< "Adding pointZone " << name << " at index " << zoneID << endl;
00120 
00121         pointZones.setSize(zoneID+1);
00122         pointZones.set
00123         (
00124             zoneID,
00125             new pointZone
00126             (
00127                 name,
00128                 labelList(0),
00129                 zoneID,
00130                 pointZones
00131             )
00132         );
00133     }
00134     return zoneID;
00135 }
00136 
00137 
00138 label addFaceZone(const polyMesh& mesh, const word& name)
00139 {
00140     label zoneID = mesh.faceZones().findZoneID(name);
00141 
00142     if (zoneID != -1)
00143     {
00144         Info<< "Reusing existing faceZone " << mesh.faceZones()[zoneID].name()
00145             << " at index " << zoneID << endl;
00146     }
00147     else
00148     {
00149         faceZoneMesh& faceZones = const_cast<polyMesh&>(mesh).faceZones();
00150         zoneID = faceZones.size();
00151         Info<< "Adding faceZone " << name << " at index " << zoneID << endl;
00152 
00153         faceZones.setSize(zoneID+1);
00154         faceZones.set
00155         (
00156             zoneID,
00157             new faceZone
00158             (
00159                 name,
00160                 labelList(0),
00161                 boolList(),
00162                 zoneID,
00163                 faceZones
00164             )
00165         );
00166     }
00167     return zoneID;
00168 }
00169 
00170 
00171 label addCellZone(const polyMesh& mesh, const word& name)
00172 {
00173     label zoneID = mesh.cellZones().findZoneID(name);
00174 
00175     if (zoneID != -1)
00176     {
00177         Info<< "Reusing existing cellZone " << mesh.cellZones()[zoneID].name()
00178             << " at index " << zoneID << endl;
00179     }
00180     else
00181     {
00182         cellZoneMesh& cellZones = const_cast<polyMesh&>(mesh).cellZones();
00183         zoneID = cellZones.size();
00184         Info<< "Adding cellZone " << name << " at index " << zoneID << endl;
00185 
00186         cellZones.setSize(zoneID+1);
00187         cellZones.set
00188         (
00189             zoneID,
00190             new cellZone
00191             (
00192                 name,
00193                 labelList(0),
00194                 zoneID,
00195                 cellZones
00196             )
00197         );
00198     }
00199     return zoneID;
00200 }
00201 
00202 
00203 // Checks whether patch present
00204 void checkPatch(const polyBoundaryMesh& bMesh, const word& name)
00205 {
00206     label patchI = bMesh.findPatchID(name);
00207 
00208     if (patchI == -1)
00209     {
00210         FatalErrorIn("checkPatch(const polyBoundaryMesh&, const word&)")
00211             << "Cannot find patch " << name << endl
00212             << "It should be present and of non-zero size" << endl
00213             << "Valid patches are " << bMesh.names()
00214             << exit(FatalError);
00215     }
00216 
00217     if (bMesh[patchI].empty())
00218     {
00219         FatalErrorIn("checkPatch(const polyBoundaryMesh&, const word&)")
00220             << "Patch " << name << " is present but zero size"
00221             << exit(FatalError);
00222     }
00223 }
00224 
00225 
00226 // Main program:
00227 
00228 int main(int argc, char *argv[])
00229 {
00230     Foam::argList::noParallel();
00231 #   include <OpenFOAM/addRegionOption.H>
00232     Foam::argList::validArgs.append("masterPatch");
00233     Foam::argList::validArgs.append("slavePatch");
00234 
00235     Foam::argList::validOptions.insert("partial", "");
00236     Foam::argList::validOptions.insert("perfect", "");
00237 
00238     Foam::argList::validOptions.insert("overwrite", "");
00239 
00240     Foam::argList::validOptions.insert("toleranceDict", "file with tolerances");
00241 
00242 #   include <OpenFOAM/setRootCase.H>
00243 #   include <OpenFOAM/createTime.H>
00244     runTime.functionObjects().off();
00245     #include <OpenFOAM/createNamedMesh.H>
00246     const word oldInstance = mesh.pointsInstance();
00247 
00248 
00249     word masterPatchName(args.additionalArgs()[0]);
00250     word slavePatchName(args.additionalArgs()[1]);
00251 
00252     bool partialCover = args.optionFound("partial");
00253     bool perfectCover = args.optionFound("perfect");
00254     bool overwrite    = args.optionFound("overwrite");
00255 
00256     if (partialCover && perfectCover)
00257     {
00258         FatalErrorIn(args.executable())
00259             << "Cannot both supply partial and perfect." << endl
00260             << "Use perfect match option if the patches perfectly align"
00261             << " (both vertex positions and face centres)" << endl
00262             << exit(FatalError);
00263     }
00264 
00265 
00266     const word mergePatchName(masterPatchName + slavePatchName);
00267     const word cutZoneName(mergePatchName + "CutFaceZone");
00268 
00269     slidingInterface::typeOfMatch tom = slidingInterface::INTEGRAL;
00270 
00271     if (partialCover)
00272     {
00273         Info<< "Coupling partially overlapping patches "
00274             << masterPatchName << " and " << slavePatchName << nl
00275             << "Resulting internal faces will be in faceZone " << cutZoneName
00276             << nl
00277             << "Any uncovered faces will remain in their patch"
00278             << endl;
00279 
00280         tom = slidingInterface::PARTIAL;
00281     }
00282     else if (perfectCover)
00283     {
00284         Info<< "Coupling perfectly aligned patches "
00285             << masterPatchName << " and " << slavePatchName << nl
00286             << "Resulting (internal) faces will be in faceZone " << cutZoneName
00287             << nl << nl
00288             << "Note: both patches need to align perfectly." << nl
00289             << "Both the vertex"
00290             << " positions and the face centres need to align to within" << nl
00291             << "a tolerance given by the minimum edge length on the patch"
00292             << endl;
00293     }
00294     else
00295     {
00296         Info<< "Coupling patches " << masterPatchName << " and "
00297             << slavePatchName << nl
00298             << "Resulting (internal) faces will be in faceZone " << cutZoneName
00299             << nl << nl
00300             << "Note: the overall area covered by both patches should be"
00301             << " identical (\"integral\" interface)." << endl
00302             << "If this is not the case use the -partial option" << nl << endl;
00303     }
00304 
00305     // set up the tolerances for the sliding mesh
00306     dictionary slidingTolerances;
00307     if (args.options().found("toleranceDict")) 
00308     {
00309         IOdictionary toleranceFile(
00310             IOobject(
00311                 args.options()["toleranceDict"],
00312                 runTime.constant(),
00313                 mesh,
00314                 IOobject::MUST_READ,
00315                 IOobject::NO_WRITE                 
00316             )
00317         );
00318         slidingTolerances += toleranceFile;
00319     }
00320 
00321     // Check for non-empty master and slave patches
00322     checkPatch(mesh.boundaryMesh(), masterPatchName);
00323     checkPatch(mesh.boundaryMesh(), slavePatchName);
00324 
00325     // Create and add face zones and mesh modifiers
00326 
00327     // Master patch
00328     const polyPatch& masterPatch =
00329         mesh.boundaryMesh()
00330         [
00331             mesh.boundaryMesh().findPatchID(masterPatchName)
00332         ];
00333 
00334     // Make list of masterPatch faces
00335     labelList isf(masterPatch.size());
00336 
00337     forAll (isf, i)
00338     {
00339         isf[i] = masterPatch.start() + i;
00340     }
00341 
00342     polyTopoChanger stitcher(mesh);
00343     stitcher.setSize(1);
00344 
00345     mesh.pointZones().clearAddressing();
00346     mesh.faceZones().clearAddressing();
00347     mesh.cellZones().clearAddressing();
00348 
00349     if (perfectCover)
00350     {
00351         // Add empty zone for resulting internal faces
00352         label cutZoneID = addFaceZone(mesh, cutZoneName);
00353 
00354         mesh.faceZones()[cutZoneID].resetAddressing
00355         (
00356             isf,
00357             boolList(masterPatch.size(), false)
00358         );
00359 
00360         // Add the perfect interface mesh modifier
00361         stitcher.set
00362         (
00363             0,
00364             new perfectInterface
00365             (
00366                 "couple",
00367                 0,
00368                 stitcher,
00369                 cutZoneName,
00370                 masterPatchName,
00371                 slavePatchName
00372             )
00373         );
00374     }
00375     else
00376     {
00377         label pointZoneID = addPointZone(mesh, mergePatchName + "CutPointZone");
00378         mesh.pointZones()[pointZoneID] = labelList(0);
00379 
00380         label masterZoneID = addFaceZone(mesh, mergePatchName + "MasterZone");
00381 
00382         mesh.faceZones()[masterZoneID].resetAddressing
00383         (
00384             isf,
00385             boolList(masterPatch.size(), false)
00386         );
00387 
00388         // Slave patch
00389         const polyPatch& slavePatch =
00390             mesh.boundaryMesh()
00391             [
00392                 mesh.boundaryMesh().findPatchID(slavePatchName)
00393             ];
00394 
00395         labelList osf(slavePatch.size());
00396 
00397         forAll (osf, i)
00398         {
00399             osf[i] = slavePatch.start() + i;
00400         }
00401 
00402         label slaveZoneID = addFaceZone(mesh, mergePatchName + "SlaveZone");
00403         mesh.faceZones()[slaveZoneID].resetAddressing
00404         (
00405             osf,
00406             boolList(slavePatch.size(), false)
00407         );
00408 
00409         // Add empty zone for cut faces
00410         label cutZoneID = addFaceZone(mesh, cutZoneName);
00411         mesh.faceZones()[cutZoneID].resetAddressing
00412         (
00413             labelList(0),
00414             boolList(0, false)
00415         );
00416 
00417 
00418         // Add the sliding interface mesh modifier
00419         stitcher.set
00420         (
00421             0,
00422             new slidingInterface
00423             (
00424                 "couple",
00425                 0,
00426                 stitcher,
00427                 mergePatchName + "MasterZone",
00428                 mergePatchName + "SlaveZone",
00429                 mergePatchName + "CutPointZone",
00430                 cutZoneName,
00431                 masterPatchName,
00432                 slavePatchName,
00433                 tom,                    // integral or partial
00434                 true                    // couple/decouple mode
00435             )
00436         );
00437         static_cast<slidingInterface&>(stitcher[0]).setTolerances
00438         (
00439             slidingTolerances,
00440             true
00441         );
00442     }
00443 
00444 
00445     // Search for list of objects for this time
00446     IOobjectList objects(mesh, runTime.timeName());
00447 
00448     // Read all current fvFields so they will get mapped
00449     Info<< "Reading all current volfields" << endl;
00450     PtrList<volScalarField> volScalarFields;
00451     ReadFields(mesh, objects, volScalarFields);
00452 
00453     PtrList<volVectorField> volVectorFields;
00454     ReadFields(mesh, objects, volVectorFields);
00455 
00456     PtrList<volSphericalTensorField> volSphericalTensorFields;
00457     ReadFields(mesh, objects, volSphericalTensorFields);
00458 
00459     PtrList<volSymmTensorField> volSymmTensorFields;
00460     ReadFields(mesh, objects, volSymmTensorFields);
00461 
00462     PtrList<volTensorField> volTensorFields;
00463     ReadFields(mesh, objects, volTensorFields);
00464 
00465     //- uncomment if you want to interpolate surface fields (usually bad idea)
00466     //Info<< "Reading all current surfaceFields" << endl;
00467     //PtrList<surfaceScalarField> surfaceScalarFields;
00468     //ReadFields(mesh, objects, surfaceScalarFields);
00469     //
00470     //PtrList<surfaceVectorField> surfaceVectorFields;
00471     //ReadFields(mesh, objects, surfaceVectorFields);
00472     //
00473     //PtrList<surfaceTensorField> surfaceTensorFields;
00474     //ReadFields(mesh, objects, surfaceTensorFields);
00475 
00476     if (!overwrite)
00477     {
00478         runTime++;
00479     }
00480 
00481     // Execute all polyMeshModifiers
00482     autoPtr<mapPolyMesh> morphMap = stitcher.changeMesh(true);
00483 
00484     mesh.movePoints(morphMap->preMotionPoints());
00485 
00486     // Write mesh
00487     if (overwrite)
00488     {
00489         mesh.setInstance(oldInstance);
00490         stitcher.instance() = oldInstance;
00491     }
00492     Info << nl << "Writing polyMesh to time " << runTime.timeName() << endl;
00493 
00494     IOstream::defaultPrecision(10);
00495 
00496     // Bypass runTime write (since only writes at outputTime)
00497     if
00498     (
00499        !runTime.objectRegistry::writeObject
00500         (
00501             runTime.writeFormat(),
00502             IOstream::currentVersion,
00503             runTime.writeCompression()
00504         )
00505     )
00506     {
00507         FatalErrorIn(args.executable())
00508             << "Failed writing polyMesh."
00509             << exit(FatalError);
00510     }
00511 
00512     mesh.faceZones().write();
00513     mesh.pointZones().write();
00514     mesh.cellZones().write();
00515 
00516     // Write fields
00517     runTime.write();
00518 
00519     Info<< nl << "end" << endl;
00520 
00521     return 0;
00522 }
00523 
00524 
00525 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines