1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
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
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/>.
25 Makes internal faces into boundary faces. Does not duplicate points, unlike
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"
39 #include "polyTopoChange.H"
40 #include "polyModifyFace.H"
41 #include "polyAddFace.H"
42 #include "ReadFields.H"
43 #include "volFields.H"
44 #include "surfaceFields.H"
46 #include "fvMeshMapper.H"
47 #include "SetPatchFields.H"
51 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
55 polyTopoChange& meshMod,
59 const bool flipFaceFlux,
60 const label newPatchI,
64 PackedBoolList& modifiedFace
67 if (!modifiedFace[faceI])
69 // First usage of face. Modify.
75 faceI, // label of face
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
85 modifiedFace[faceI] = 1;
89 // Second or more usage of face. Add.
100 flipFaceFlux, // face flip
101 newPatchI, // patch for face
102 zoneID, // zone for face
103 zoneFlip // face flip in zone
110 label findPatchID(const polyMesh& mesh, const word& name)
112 const label patchI = mesh.boundaryMesh().findPatchID(name);
116 FatalErrorIn("findPatchID(const polyMesh&, const word&)")
117 << "Cannot find patch " << name << endl
118 << "Valid patches are " << mesh.boundaryMesh().names()
127 int main(int argc, char *argv[])
131 "Makes internal faces into boundary faces.\n"
132 "Does not duplicate points, unlike mergeOrSplitBaffles."
135 #include "addOverwriteOption.H"
136 #include "addRegionOption.H"
138 argList::validArgs.append("faceZone");
139 argList::validArgs.append("(masterPatch slavePatch)");
143 "((master2 slave2) .. (masterN slaveN))"
145 argList::addBoolOption("internalFacesOnly");
150 "(patch2 .. patchN)",
151 "specify additional patches for creating baffles"
153 argList::addBoolOption
156 "do not convert boundary faces"
158 argList::addBoolOption
161 "update fields to include new patches:"
162 " NOTE: updated field values may need to be edited"
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();
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)
183 FatalErrorIn(args.executable()) << "Cannot find faceZone "
184 << zoneID.name() << endl
185 << "Valid zones are " << faceZones.names()
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"))
214 const List<Pair<word> > patchNames
216 args.optionLookup("additionalPatches")()
219 newMasterPatches.reserve(patchNames.size() + 1);
220 newSlavePatches.reserve(patchNames.size() + 1);
221 forAll(patchNames, i)
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()
233 const bool overwrite = args.optionFound("overwrite");
234 const bool internalFacesOnly = args.optionFound("internalFacesOnly");
236 if (internalFacesOnly)
238 Info<< "Not converting faces on non-coupled patches." << nl << endl;
242 // Read objects in time directory
243 IOobjectList objects(mesh, runTime.timeName());
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());
295 forAll(newMasterPatches, i)
297 // Pass 1. Do selected side of zone
298 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
300 for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
302 label zoneFaceI = fZone.whichFace(faceI);
306 if (!fZone.flipMap()[zoneFaceI])
308 // Use owner side of face
312 mesh.faces()[faceI], // modified face
313 faceI, // label of face
314 mesh.faceOwner()[faceI],// owner
316 newMasterPatches[i], // patch for face
317 zoneID.index(), // zone for face
318 false, // face flip in zone
319 modifiedFace // modify or add status
324 // Use neighbour side of face
328 mesh.faces()[faceI].reverseFace(), // modified face
329 faceI, // label of face
330 mesh.faceNeighbour()[faceI],// owner
332 newMasterPatches[i], // patch for face
333 zoneID.index(), // zone for face
334 true, // face flip in zone
335 modifiedFace // modify or add status
344 // Pass 2. Do other side of zone
345 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
347 for (label faceI = 0; faceI < mesh.nInternalFaces(); faceI++)
349 label zoneFaceI = fZone.whichFace(faceI);
353 if (!fZone.flipMap()[zoneFaceI])
355 // Use neighbour side of face
359 mesh.faces()[faceI].reverseFace(), // modified face
360 faceI, // label of face
361 mesh.faceNeighbour()[faceI], // owner
363 newSlavePatches[i], // patch for face
364 zoneID.index(), // zone for face
365 true, // face flip in zone
366 modifiedFace // modify or add
371 // Use owner side of face
375 mesh.faces()[faceI], // modified face
376 faceI, // label of face
377 mesh.faceOwner()[faceI],// owner
379 newSlavePatches[i], // patch for face
380 zoneID.index(), // zone for face
381 false, // face flip in zone
382 modifiedFace // modify or add status
389 // Modify any boundary faces
390 // ~~~~~~~~~~~~~~~~~~~~~~~~~
393 // - move to new patch. Might already be back-to-back baffle
394 // you want to add cyclic to. Do warn though.
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)
405 const polyPatch& pp = patches[patchI];
407 label newPatchI = newMasterPatches[i];
409 if (pp.coupled() && patches[newPatchI].coupled())
411 // Do not allow coupled faces to be moved to different coupled
414 else if (pp.coupled() || !internalFacesOnly)
418 label faceI = pp.start()+i;
420 label zoneFaceI = fZone.whichFace(faceI);
424 if (patchWarned.insert(patchI))
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()
432 << " Run with -internalFacesOnly option"
433 << " if you don't wish to convert"
434 << " boundary faces." << endl;
440 mesh.faces()[faceI], // modified face
441 faceI, // label of face
442 mesh.faceOwner()[faceI], // owner
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
457 Info<< "Converted " << returnReduce(nModified, sumOp<label>())
458 << " faces into boundary faces on patches " << patchNames << nl << endl;
465 // Change the mesh. Change points directly (no inflation).
466 autoPtr<mapPolyMesh> map = meshMod.changeMesh(mesh, false);
469 mesh.updateMesh(map);
471 // Correct boundary faces mapped-out-of-nothing.
473 fvMeshMapper mapper(mesh, map);
474 bool hasWarned = false;
475 forAll(newMasterPatches, i)
477 label patchI = newMasterPatches[i];
478 const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
479 if (pm.sizeBeforeMapping() == 0)
484 WarningIn(args.executable())
485 << "Setting field on boundary faces to zero." << endl
486 << "You might have to edit these fields." << endl;
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);
502 forAll(newSlavePatches, i)
504 label patchI = newSlavePatches[i];
505 const fvPatchMapper& pm = mapper.boundaryMap()[patchI];
506 if (pm.sizeBeforeMapping() == 0)
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);
523 // Move mesh (since morphing might not do this)
524 if (map().hasMotionPoints())
526 mesh.movePoints(map().preMotionPoints());
531 mesh.setInstance(oldInstance);
533 Info<< "Writing mesh to " << runTime.timeName() << endl;
537 Info<< "End\n" << endl;
543 // ************************************************************************* //