BUG: createBaffles.C: converting coupled faces into baffles
[OpenFOAM-2.0.x.git] / applications / utilities / mesh / manipulation / createBaffles / createBaffles.C
blobcd0c02ce64da1161a98835f6da7404027bb02699
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
9     This file is part of OpenFOAM.
11     OpenFOAM is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by
13     the Free Software Foundation, either version 3 of the License, or
14     (at your option) any later version.
16     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
19     for more details.
21     You should have received a copy of the GNU General Public License
22     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
24 Description
25     Makes internal faces into boundary faces. Does not duplicate points, unlike
26     mergeOrSplitBaffles.
28     Note: if any coupled patch face is selected for baffling the opposite
29     member has to be selected for baffling as well. Note that this
30     is the same as repatching. This was added only for convenience so
31     you don't have to filter coupled boundary out of your set.
33 \*---------------------------------------------------------------------------*/
35 #include "syncTools.H"
36 #include "argList.H"
37 #include "Time.H"
38 #include "faceSet.H"
39 #include "polyTopoChange.H"
40 #include "polyModifyFace.H"
41 #include "polyAddFace.H"
42 #include "ReadFields.H"
43 #include "volFields.H"
44 #include "surfaceFields.H"
45 #include "ZoneIDs.H"
46 #include "fvMeshMapper.H"
47 #include "SetPatchFields.H"
49 using namespace Foam;
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
53 void modifyOrAddFace
55     polyTopoChange& meshMod,
56     const face& f,
57     const label faceI,
58     const label own,
59     const bool flipFaceFlux,
60     const label newPatchI,
61     const label zoneID,
62     const bool zoneFlip,
64     PackedBoolList& modifiedFace
67     if (!modifiedFace[faceI])
68     {
69         // First usage of face. Modify.
70         meshMod.setAction
71         (
72             polyModifyFace
73             (
74                 f,                          // modified face
75                 faceI,                      // label of face
76                 own,                        // owner
77                 -1,                         // neighbour
78                 flipFaceFlux,               // face flip
79                 newPatchI,                  // patch for face
80                 false,                      // remove from zone
81                 zoneID,                     // zone for face
82                 zoneFlip                    // face flip in zone
83             )
84         );
85         modifiedFace[faceI] = 1;
86     }
87     else
88     {
89         // Second or more usage of face. Add.
90         meshMod.setAction
91         (
92             polyAddFace
93             (
94                 f,                          // modified face
95                 own,                        // owner
96                 -1,                         // neighbour
97                 -1,                         // master point
98                 -1,                         // master edge
99                 faceI,                      // master face
100                 flipFaceFlux,               // face flip
101                 newPatchI,                  // patch for face
102                 zoneID,                     // zone for face
103                 zoneFlip                    // face flip in zone
104             )
105         );
106     }
110 label findPatchID(const polyMesh& mesh, const word& name)
112     const label patchI = mesh.boundaryMesh().findPatchID(name);
114     if (patchI == -1)
115     {
116         FatalErrorIn("findPatchID(const polyMesh&, const word&)")
117             << "Cannot find patch " << name << endl
118             << "Valid patches are " << mesh.boundaryMesh().names()
119             << exit(FatalError);
120     }
121     return patchI;
125 // Main program:
127 int main(int argc, char *argv[])
129     argList::addNote
130     (
131         "Makes internal faces into boundary faces.\n"
132         "Does not duplicate points, unlike mergeOrSplitBaffles."
133     );
135     #include "addOverwriteOption.H"
136     #include "addRegionOption.H"
138     argList::validArgs.append("faceZone");
139     argList::validArgs.append("(masterPatch slavePatch)");
140     argList::addOption
141     (
142         "additionalPatches",
143         "((master2 slave2) .. (masterN slaveN))"
144     );
145     argList::addBoolOption("internalFacesOnly");
147     argList::addOption
148     (
149         "additionalPatches",
150         "(patch2 .. patchN)",
151         "specify additional patches for creating baffles"
152     );
153     argList::addBoolOption
154     (
155         "internalFacesOnly",
156         "do not convert boundary faces"
157     );
158     argList::addBoolOption
159     (
160         "updateFields",
161         "update fields to include new patches:"
162         " NOTE: updated field values may need to be edited"
163     );
165     #include "setRootCase.H"
166     #include "createTime.H"
167     runTime.functionObjects().off();
168     #include "createNamedMesh.H"
170     const word oldInstance = mesh.pointsInstance();
172     const polyBoundaryMesh& patches = mesh.boundaryMesh();
173     const faceZoneMesh& faceZones = mesh.faceZones();
175     // Faces to baffle
176     faceZoneID zoneID(args.additionalArgs()[0], faceZones);
178     Info<< "Converting faces on zone " << zoneID.name()
179         << " into baffles." << nl << endl;
181     if (zoneID.index() == -1)
182     {
183         FatalErrorIn(args.executable()) << "Cannot find faceZone "
184             << zoneID.name() << endl
185             << "Valid zones are " << faceZones.names()
186             << exit(FatalError);
187     }
189     const faceZone& fZone = faceZones[zoneID.index()];
191     Info<< "Found " << returnReduce(fZone.size(), sumOp<label>())
192         << " faces on zone " << zoneID.name() << nl << endl;
194     // Make sure patches and zoneFaces are synchronised across couples
195     patches.checkParallelSync(true);
196     fZone.checkParallelSync(true);
198     // Patches to put baffles into
199     DynamicList<label> newMasterPatches(1);
200     DynamicList<label> newSlavePatches(1);
202     const Pair<word> patchNames(IStringStream(args.additionalArgs()[1])());
203     newMasterPatches.append(findPatchID(mesh, patchNames[0]));
204     newSlavePatches.append(findPatchID(mesh, patchNames[1]));
205     Info<< "Using master patch " << patchNames[0]
206         << " at index " << newMasterPatches[0] << endl;
207     Info<< "Using slave patch " << patchNames[1]
208         << " at index " << newSlavePatches[0] << endl;
211     // Additional patches
212     if (args.optionFound("additionalPatches"))
213     {
214         const List<Pair<word> > patchNames
215         (
216             args.optionLookup("additionalPatches")()
217         );
219         newMasterPatches.reserve(patchNames.size() + 1);
220         newSlavePatches.reserve(patchNames.size() + 1);
221         forAll(patchNames, i)
222         {
223             newMasterPatches.append(findPatchID(mesh, patchNames[i][0]));
224             newSlavePatches.append(findPatchID(mesh, patchNames[i][1]));
225             Info<< "Using additional patches " << patchNames[i]
226                 << " at indices " << newMasterPatches.last()
227                 << " and " << newSlavePatches.last()
228                 << endl;
229         }
230     }
233     const bool overwrite = args.optionFound("overwrite");
234     const bool internalFacesOnly = args.optionFound("internalFacesOnly");
236     if (internalFacesOnly)
237     {
238         Info<< "Not converting faces on non-coupled patches." << nl << endl;
239     }
242     // Read objects in time directory
243     IOobjectList objects(mesh, runTime.timeName());
245     // Read vol fields.
246     Info<< "Reading geometric fields" << nl << endl;
247     PtrList<volScalarField> vsFlds;
248     ReadFields(mesh, objects, vsFlds);
250     PtrList<volVectorField> vvFlds;
251     ReadFields(mesh, objects, vvFlds);
253     PtrList<volSphericalTensorField> vstFlds;
254     ReadFields(mesh, objects, vstFlds);
256     PtrList<volSymmTensorField> vsymtFlds;
257     ReadFields(mesh, objects, vsymtFlds);
259     PtrList<volTensorField> vtFlds;
260     ReadFields(mesh, objects, vtFlds);
262     // Read surface fields.
264     PtrList<surfaceScalarField> ssFlds;
265     ReadFields(mesh, objects, ssFlds);
267     PtrList<surfaceVectorField> svFlds;
268     ReadFields(mesh, objects, svFlds);
270     PtrList<surfaceSphericalTensorField> sstFlds;
271     ReadFields(mesh, objects, sstFlds);
273     PtrList<surfaceSymmTensorField> ssymtFlds;
274     ReadFields(mesh, objects, ssymtFlds);
276     PtrList<surfaceTensorField> stFlds;
277     ReadFields(mesh, objects, stFlds);
280     // Mesh change container
281     polyTopoChange meshMod(mesh);
284     // Do the actual changes. Note:
285     // - loop in incrementing face order (not necessary if faceZone ordered).
286     //   Preserves any existing ordering on patch faces.
287     // - two passes, do non-flip faces first and flip faces second. This
288     //   guarantees that when e.g. creating a cyclic all faces from one
289     //   side come first and faces from the other side next.
291     // Whether first use of face (modify) or consecutive (add)
292     PackedBoolList modifiedFace(mesh.nFaces());
293     label nModified = 0;
295     forAll(newMasterPatches, i)
296     {
297         // Pass 1. Do selected side of zone
298         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
300         for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
301         {
302             label zoneFaceI = fZone.whichFace(faceI);
304             if (zoneFaceI != -1)
305             {
306                 if (!fZone.flipMap()[zoneFaceI])
307                 {
308                     // Use owner side of face
309                     modifyOrAddFace
310                     (
311                         meshMod,
312                         mesh.faces()[faceI],    // modified face
313                         faceI,                  // label of face
314                         mesh.faceOwner()[faceI],// owner
315                         false,                  // face flip
316                         newMasterPatches[i],    // patch for face
317                         zoneID.index(),         // zone for face
318                         false,                  // face flip in zone
319                         modifiedFace            // modify or add status
320                     );
321                 }
322                 else
323                 {
324                     // Use neighbour side of face
325                     modifyOrAddFace
326                     (
327                         meshMod,
328                         mesh.faces()[faceI].reverseFace(),  // modified face
329                         faceI,                      // label of face
330                         mesh.faceNeighbour()[faceI],// owner
331                         true,                       // face flip
332                         newMasterPatches[i],        // patch for face
333                         zoneID.index(),             // zone for face
334                         true,                       // face flip in zone
335                         modifiedFace                // modify or add status
336                     );
337                 }
339                 nModified++;
340             }
341         }
344         // Pass 2. Do other side of zone
345         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
347         for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
348         {
349             label zoneFaceI = fZone.whichFace(faceI);
351             if (zoneFaceI != -1)
352             {
353                 if (!fZone.flipMap()[zoneFaceI])
354                 {
355                     // Use neighbour side of face
356                     modifyOrAddFace
357                     (
358                         meshMod,
359                         mesh.faces()[faceI].reverseFace(),  // modified face
360                         faceI,                              // label of face
361                         mesh.faceNeighbour()[faceI],        // owner
362                         true,                               // face flip
363                         newSlavePatches[i],                 // patch for face
364                         zoneID.index(),                     // zone for face
365                         true,                               // face flip in zone
366                         modifiedFace                        // modify or add
367                     );
368                 }
369                 else
370                 {
371                     // Use owner side of face
372                     modifyOrAddFace
373                     (
374                         meshMod,
375                         mesh.faces()[faceI],    // modified face
376                         faceI,                  // label of face
377                         mesh.faceOwner()[faceI],// owner
378                         false,                  // face flip
379                         newSlavePatches[i],     // patch for face
380                         zoneID.index(),         // zone for face
381                         false,                  // face flip in zone
382                         modifiedFace            // modify or add status
383                     );
384                 }
385             }
386         }
389         // Modify any boundary faces
390         // ~~~~~~~~~~~~~~~~~~~~~~~~~
392         // Normal boundary:
393         // - move to new patch. Might already be back-to-back baffle
394         // you want to add cyclic to. Do warn though.
395         //
396         // Processor boundary:
397         // - do not move to cyclic
398         // - add normal patches though.
400         // For warning once per patch.
401         labelHashSet patchWarned;
403         forAll(patches, patchI)
404         {
405             const polyPatch& pp = patches[patchI];
407             label newPatchI = newMasterPatches[i];
409             if (pp.coupled() && patches[newPatchI].coupled())
410             {
411                 // Do not allow coupled faces to be moved to different coupled
412                 // patches.
413             }
414             else if (pp.coupled() || !internalFacesOnly)
415             {
416                 forAll(pp, i)
417                 {
418                     label faceI = pp.start()+i;
420                     label zoneFaceI = fZone.whichFace(faceI);
422                     if (zoneFaceI != -1)
423                     {
424                         if (patchWarned.insert(patchI))
425                         {
426                             WarningIn(args.executable())
427                                 << "Found boundary face (in patch " << pp.name()
428                                 << ") in faceZone " << fZone.name()
429                                 << " to convert to baffle patch "
430                                 << patches[newPatchI].name()
431                                 << endl
432                                 << "    Run with -internalFacesOnly option"
433                                 << " if you don't wish to convert"
434                                 << " boundary faces." << endl;
435                         }
437                         modifyOrAddFace
438                         (
439                             meshMod,
440                             mesh.faces()[faceI],        // modified face
441                             faceI,                      // label of face
442                             mesh.faceOwner()[faceI],    // owner
443                             false,                      // face flip
444                             newPatchI,                  // patch for face
445                             zoneID.index(),             // zone for face
446                             fZone.flipMap()[zoneFaceI], // face flip in zone
447                             modifiedFace                // modify or add status
448                         );
449                         nModified++;
450                     }
451                 }
452             }
453         }
454     }
457     Info<< "Converted " << returnReduce(nModified, sumOp<label>())
458         << " faces into boundary faces on patches " << patchNames << nl << endl;
460     if (!overwrite)
461     {
462         runTime++;
463     }
465     // Change the mesh. Change points directly (no inflation).
466     autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
468     // Update fields
469     mesh.updateMesh(map);
471     // Correct boundary faces mapped-out-of-nothing.
472     {
473         fvMeshMapper mapper(mesh, map);
474         bool hasWarned = false;
475         forAll(newMasterPatches, i)
476         {
477             label patchI = newMasterPatches[i];
478             const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
479             if (pm.sizeBeforeMapping() == 0)
480             {
481                 if (!hasWarned)
482                 {
483                     hasWarned = true;
484                     WarningIn(args.executable())
485                         << "Setting field on boundary faces to zero." << endl
486                         << "You might have to edit these fields." << endl;
487                 }
489                 SetPatchFields(vsFlds, patchI, pTraits<scalar>::zero);
490                 SetPatchFields(vvFlds, patchI, pTraits<vector>::zero);
491                 SetPatchFields(vstFlds, patchI, pTraits<sphericalTensor>::zero);
492                 SetPatchFields(vsymtFlds, patchI, pTraits<symmTensor>::zero);
493                 SetPatchFields(vtFlds, patchI, pTraits<tensor>::zero);
495                 SetPatchFields(ssFlds, patchI, pTraits<scalar>::zero);
496                 SetPatchFields(svFlds, patchI, pTraits<vector>::zero);
497                 SetPatchFields(sstFlds, patchI, pTraits<sphericalTensor>::zero);
498                 SetPatchFields(ssymtFlds, patchI, pTraits<symmTensor>::zero);
499                 SetPatchFields(stFlds, patchI, pTraits<tensor>::zero);
500             }
501         }
502         forAll(newSlavePatches, i)
503         {
504             label patchI = newSlavePatches[i];
505             const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
506             if (pm.sizeBeforeMapping() == 0)
507             {
508                 SetPatchFields(vsFlds, patchI, pTraits<scalar>::zero);
509                 SetPatchFields(vvFlds, patchI, pTraits<vector>::zero);
510                 SetPatchFields(vstFlds, patchI, pTraits<sphericalTensor>::zero);
511                 SetPatchFields(vsymtFlds, patchI, pTraits<symmTensor>::zero);
512                 SetPatchFields(vtFlds, patchI, pTraits<tensor>::zero);
514                 SetPatchFields(ssFlds, patchI, pTraits<scalar>::zero);
515                 SetPatchFields(svFlds, patchI, pTraits<vector>::zero);
516                 SetPatchFields(sstFlds, patchI, pTraits<sphericalTensor>::zero);
517                 SetPatchFields(ssymtFlds, patchI, pTraits<symmTensor>::zero);
518                 SetPatchFields(stFlds, patchI, pTraits<tensor>::zero);
519             }
520         }
521     }
523     // Move mesh (since morphing might not do this)
524     if (map().hasMotionPoints())
525     {
526         mesh.movePoints(map().preMotionPoints());
527     }
529     if (overwrite)
530     {
531         mesh.setInstance(oldInstance);
532     }
533     Info<< "Writing mesh to " << runTime.timeName() << endl;
535     mesh.write();
537     Info<< "End\n" << endl;
539     return 0;
543 // ************************************************************************* //