1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2008 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 Takes a mesh and two patches and merges the faces on the two patches
29 (if geometrically possible) so the faces become internal.
32 - 'perfect' match: faces and points on patches align exactly. Order might
34 - 'integral' match: where the surfaces on both patches exactly
35 match but the individual faces not
36 - 'partial' match: where the non-overlapping part of the surface remains
37 in the respective patch.
39 Note : Is just a front-end to perfectInterface/slidingInterface.
41 Comparable to running a meshModifier of the form
42 (if masterPatch is called "M" and slavePatch "S"):
46 type slidingInterface;
47 masterFaceZoneName MSMasterZone
48 slaveFaceZoneName MSSlaveZone
49 cutPointZoneName MSCutPointZone
50 cutFaceZoneName MSCutFaceZone
53 typeOfMatch partial or integral
57 \*---------------------------------------------------------------------------*/
60 #include "polyTopoChanger.H"
61 #include "mapPolyMesh.H"
63 #include "IndirectList.H"
64 #include "slidingInterface.H"
65 #include "perfectInterface.H"
66 #include "IOobjectList.H"
69 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
71 // Checks whether patch present
72 void checkPatch(const polyBoundaryMesh& bMesh, const word& name)
74 label patchI = bMesh.findPatchID(name);
78 FatalErrorIn("checkPatch(const polyBoundaryMesh&, const word&)")
79 << "Cannot find patch " << name << endl
80 << "It should be present and of non-zero size" << endl
81 << "Valid patches are " << bMesh.names()
85 if (bMesh[patchI].size() == 0)
87 FatalErrorIn("checkPatch(const polyBoundaryMesh&, const word&)")
88 << "Patch " << name << " is present but zero size"
95 template<class GeoField>
99 const IOobjectList& objects,
100 PtrList<GeoField>& fields
103 // Search list of objects for volScalarFields
104 IOobjectList fieldObjects(objects.lookupClass(GeoField::typeName));
106 // Construct the vol scalar fields
107 fields.setSize(fieldObjects.size());
112 IOobjectList::iterator iter = fieldObjects.begin();
113 iter != fieldObjects.end();
117 fields.set(fieldi++, new GeoField(*iter(), mesh));
124 int main(int argc, char *argv[])
126 Foam::argList::noParallel();
128 Foam::argList::validArgs.append("masterPatch");
129 Foam::argList::validArgs.append("slavePatch");
131 Foam::argList::validOptions.insert("partial", "");
132 Foam::argList::validOptions.insert("perfect", "");
134 Foam::argList::validOptions.insert("overwrite", "");
136 # include "setRootCase.H"
137 # include "createTime.H"
138 # include "createMesh.H"
141 word masterPatchName(args.additionalArgs()[0]);
142 word slavePatchName(args.additionalArgs()[1]);
144 bool partialCover = args.options().found("partial");
145 bool perfectCover = args.options().found("perfect");
146 bool overwrite = args.options().found("overwrite");
148 if (partialCover && perfectCover)
150 FatalErrorIn(args.executable())
151 << "Cannot both supply partial and perfect." << endl
152 << "Use perfect match option if the patches perfectly align"
153 << " (both vertex positions and face centres)" << endl
158 const word mergePatchName(masterPatchName + slavePatchName);
159 const word cutZoneName(mergePatchName + "CutFaceZone");
161 slidingInterface::typeOfMatch tom = slidingInterface::INTEGRAL;
165 Info<< "Coupling partially overlapping patches "
166 << masterPatchName << " and " << slavePatchName << nl
167 << "Resulting internal faces will be in faceZone " << cutZoneName
169 << "Any uncovered faces will remain in their patch"
172 tom = slidingInterface::PARTIAL;
174 else if (perfectCover)
176 Info<< "Coupling perfectly aligned patches "
177 << masterPatchName << " and " << slavePatchName << nl
178 << "Resulting (internal) faces will be in faceZone " << cutZoneName
180 << "Note: both patches need to align perfectly." << nl
182 << " positions and the face centres need to align to within" << nl
183 << "a tolerance given by the minimum edge length on the patch"
188 Info<< "Coupling patches " << masterPatchName << " and "
189 << slavePatchName << nl
190 << "Resulting (internal) faces will be in faceZone " << cutZoneName
192 << "Note: the overall area covered by both patches should be"
193 << " identical (\"integral\" interface)." << endl
194 << "If this is not the case use the -partial option" << nl << endl;
197 // Check for non-empty master and slave patches
198 checkPatch(mesh.boundaryMesh(), masterPatchName);
199 checkPatch(mesh.boundaryMesh(), slavePatchName);
201 // Create and add face zones and mesh modifiers
204 const polyPatch& masterPatch =
207 mesh.boundaryMesh().findPatchID(masterPatchName)
210 // Make list of masterPatch faces
211 labelList isf(masterPatch.size());
215 isf[i] = masterPatch.start() + i;
218 polyTopoChanger stitcher(mesh);
221 DynamicList<pointZone*> pz;
222 DynamicList<faceZone*> fz;
223 DynamicList<cellZone*> cz;
227 // Add empty zone for resulting internal faces
234 boolList(masterPatch.size(), false),
240 // Note: make sure to add the zones BEFORE constructing polyMeshModifier
241 // (since looks up various zones at construction time)
242 Info << "Adding point and face zones" << endl;
243 mesh.addZones(pz.shrink(), fz.shrink(), cz.shrink());
245 // Add the perfect interface mesh modifier
266 mergePatchName + "CutPointZone",
277 mergePatchName + "MasterZone",
279 boolList(masterPatch.size(), false),
286 const polyPatch& slavePatch =
289 mesh.boundaryMesh().findPatchID(slavePatchName)
292 labelList osf(slavePatch.size());
296 osf[i] = slavePatch.start() + i;
303 mergePatchName + "SlaveZone",
305 boolList(slavePatch.size(), false),
311 // Add empty zone for cut faces
325 // Note: make sure to add the zones BEFORE constructing polyMeshModifier
326 // (since looks up various zones at construction time)
327 Info << "Adding point and face zones" << endl;
328 mesh.addZones(pz.shrink(), fz.shrink(), cz.shrink());
330 // Add the sliding interface mesh modifier
339 mergePatchName + "MasterZone",
340 mergePatchName + "SlaveZone",
341 mergePatchName + "CutPointZone",
345 tom // integral or partial
351 // Search for list of objects for this time
352 IOobjectList objects(mesh, runTime.timeName());
354 // Read all current fvFields so they will get mapped
355 Info<< "Reading all current volfields" << endl;
356 PtrList<volScalarField> volScalarFields;
357 readFields(mesh, objects, volScalarFields);
359 PtrList<volVectorField> volVectorFields;
360 readFields(mesh, objects, volVectorFields);
362 PtrList<volSphericalTensorField> volSphericalTensorFields;
363 readFields(mesh, objects, volSphericalTensorFields);
365 PtrList<volSymmTensorField> volSymmTensorFields;
366 readFields(mesh, objects, volSymmTensorFields);
368 PtrList<volTensorField> volTensorFields;
369 readFields(mesh, objects, volTensorFields);
371 //- uncomment if you want to interpolate surface fields (usually bad idea)
372 //Info<< "Reading all current surfaceFields" << endl;
373 //PtrList<surfaceScalarField> surfaceScalarFields;
374 //readFields(mesh, objects, surfaceScalarFields);
376 //PtrList<surfaceVectorField> surfaceVectorFields;
377 //readFields(mesh, objects, surfaceVectorFields);
379 //PtrList<surfaceTensorField> surfaceTensorFields;
380 //readFields(mesh, objects, surfaceTensorFields);
387 // Execute all polyMeshModifiers
388 autoPtr<mapPolyMesh> morphMap = stitcher.changeMesh(true);
390 mesh.movePoints(morphMap->preMotionPoints());
393 Info << nl << "Writing polyMesh to time " << runTime.timeName() << endl;
395 IOstream::defaultPrecision(10);
398 FatalErrorIn(args.executable())
399 << "Failed writing polyMesh."
403 mesh.faceZones().write();
404 mesh.pointZones().write();
405 mesh.cellZones().write();
410 Info<< nl << "end" << endl;
416 // ************************************************************************* //