1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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
26 Extracts triSurface from a polyMesh. Triangulates all boundary faces.
27 Region numbers on triangles are the patch numbers of the polyMesh.
28 Optionally only triangulates named patches.
30 If run in parallel the processor patches get filtered out by default and
31 the mesh gets merged. (based on vertex position, not topology, so might go
34 \*---------------------------------------------------------------------------*/
37 #include "objectRegistry.H"
40 #include "triSurface.H"
41 #include "triSurfaceTools.H"
42 #include "processorPolyPatch.H"
43 #include "ListListOps.H"
47 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
51 int main(int argc, char *argv[])
53 argList::validArgs.append("output file");
54 # include "addRegionOption.H"
55 argList::validOptions.insert("excludeProcPatches", "");
56 argList::validOptions.insert("patches", "(patch0 .. patchN)");
58 # include "setRootCase.H"
59 # include "createTime.H"
61 fileName outFileName(runTime.path()/args.additionalArgs()[0]);
63 Info<< "Extracting triSurface from boundaryMesh ..."
66 Pout<< "Reading mesh from time " << runTime.value() << endl;
68 # include "createNamedPolyMesh.H"
70 bool includeProcPatches =
72 args.optionFound("excludeProcPatches")
76 // Create local surface from:
77 // - explicitly named patches only (-patches option)
78 // - all patches (default in sequential mode)
79 // - all non-processor patches (default in parallel mode)
80 // - all non-processor patches (sequential mode, -excludeProcPatches option)
82 // Construct table of patches to include.
83 const polyBoundaryMesh& bMesh = mesh.boundaryMesh();
85 labelHashSet includePatches(bMesh.size());
87 if (args.optionFound("patches"))
89 wordList patchNames(args.optionLookup("patches")());
91 forAll(patchNames, patchNameI)
93 const word& patchName = patchNames[patchNameI];
95 label patchI = bMesh.findPatchID(patchName);
99 FatalErrorIn(args.executable()) << "No such patch "
100 << patchName << endl << "Patches are " << bMesh.names()
103 includePatches.insert(patchI);
108 forAll(bMesh, patchI)
110 const polyPatch& patch = bMesh[patchI];
112 if (includeProcPatches || !isA<processorPolyPatch>(patch))
114 includePatches.insert(patchI);
118 Pout<< patch.name() << " : skipped since processorPatch"
124 triSurface localSurface
126 triSurfaceTools::triangulate
135 if (!Pstream::parRun())
137 Info<< "Writing surface to " << outFileName << endl;
139 localSurface.write(outFileName);
143 // Write local surface
144 fileName localPath = runTime.path()/runTime.caseName() + ".ftr";
146 Pout<< "Writing local surface to " << localPath << endl;
148 localSurface.write(localPath);
153 // Gather all points on master
154 List<pointField> gatheredPoints(Pstream::nProcs());
156 gatheredPoints[Pstream::myProcNo()] = localSurface.points();
158 Pstream::gatherList(gatheredPoints);
161 // Gather all localSurface patches
162 List<geometricSurfacePatchList> gatheredPatches(Pstream::nProcs());
164 gatheredPatches[Pstream::myProcNo()] = localSurface.patches();
166 Pstream::gatherList(gatheredPatches);
170 List<List<labelledTri> > gatheredFaces(Pstream::nProcs());
172 gatheredFaces[Pstream::myProcNo()] = localSurface;
174 Pstream::gatherList(gatheredFaces);
177 if (Pstream::master())
179 // On master combine all points
180 pointField allPoints =
181 ListListOps::combine<pointField>
184 accessOp<pointField>()
187 // Count number of patches.
190 forAll(gatheredPatches, procI)
192 nPatches += gatheredPatches[procI].size();
195 // Count number of faces.
198 forAll(gatheredFaces, procI)
200 nFaces += gatheredFaces[procI].size();
205 // Loop over all processors and
206 // - construct mapping from local to global patches
207 // - relabel faces (both points and regions)
211 // Name to new patchI
212 HashTable<label> nameToIndex(2*nPatches);
214 // Storage (oversized) for all patches
215 geometricSurfacePatchList allPatches(nPatches);
219 // Storage for all faces
220 List<labelledTri> allFaces(nFaces);
222 // Offset into allPoints for current processor
223 label pointOffset = 0;
225 for (label procI = 0; procI < Pstream::nProcs(); procI++)
227 Info<< "Processor " << procI << endl
228 << "-----------" << endl;
230 const geometricSurfacePatchList& patches =
231 gatheredPatches[procI];
233 // From local patch numbering to global
234 labelList localToGlobal(patches.size());
236 forAll(patches, patchI)
238 const geometricSurfacePatch& sp = patches[patchI];
240 if (!nameToIndex.found(sp.name()))
242 nameToIndex.insert(sp.name(), newPatchI);
244 localToGlobal[patchI] = newPatchI;
246 allPatches[newPatchI] = sp;
252 localToGlobal[patchI] = nameToIndex[sp.name()];
256 Info<< "Local patch to global patch mapping:"
259 forAll(patches, patchI)
261 Info<< " name : " << patches[patchI].name() << endl
262 << " local : " << patchI << endl
263 << " global : " << localToGlobal[patchI]
267 Info<< "Local points added in global points starting at "
272 // Collect and relabel faces
273 const List<labelledTri>& localFaces = gatheredFaces[procI];
276 forAll(localFaces, faceI)
278 const labelledTri& f = localFaces[faceI];
280 allFaces[newFaceI++] =
286 localToGlobal[f.region()]
290 pointOffset += gatheredPoints[procI].size();
294 allPatches.setSize(newPatchI);
296 // We now have allPoints, allFaces and allPatches.
297 // Construct overall (yet unmerged) surface from these.
299 triSurface allSurf(allFaces, allPatches, allPoints);
301 // Cleanup (which does point merge as well
302 allSurf.cleanup(false);
304 // Write surface mesh
306 label slashIndex = runTime.caseName().find_last_of('/');
308 fileName globalCasePath(runTime.caseName().substr(0, slashIndex));
310 Info<< "Writing merged surface to " << globalCasePath << endl;
312 // create database for the sequential run
317 / args.additionalArgs()[0]
320 allSurf.write(globalPath);
324 Info << "End\n" << endl;
330 // ************************************************************************* //