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 surfaceRedistributePar
28 (Re)distribution of triSurface. Either takes an undecomposed surface
29 or an already decomposed surface and redistribute it so each processor
30 has all triangles that overlap its mesh.
33 - best decomposition option is hierarchGeomDecomp since
34 guarantees square decompositions.
35 - triangles might be present on multiple processors.
36 - merging uses geometric tolerance so take care with writing precision.
38 \*---------------------------------------------------------------------------*/
40 #include "treeBoundBox.H"
41 #include "FixedList.H"
45 #include "distributedTriSurfaceMesh.H"
46 #include "mapDistribute.H"
47 #include "triSurfaceFields.H"
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 // Print on master all the per-processor surface stats.
58 const List<List<treeBoundBox> >& meshBb
61 // Determine surface bounding boxes, faces, points
62 List<treeBoundBox> surfBb(Pstream::nProcs());
64 surfBb[Pstream::myProcNo()] = treeBoundBox(s.points());
65 Pstream::gatherList(surfBb);
66 Pstream::scatterList(surfBb);
69 labelList nPoints(Pstream::nProcs());
70 nPoints[Pstream::myProcNo()] = s.points().size();
71 Pstream::gatherList(nPoints);
72 Pstream::scatterList(nPoints);
74 labelList nFaces(Pstream::nProcs());
75 nFaces[Pstream::myProcNo()] = s.size();
76 Pstream::gatherList(nFaces);
77 Pstream::scatterList(nFaces);
81 const List<treeBoundBox>& bbs = meshBb[procI];
83 Info<< "processor" << procI << nl
84 << "\tMesh bounds : " << bbs[0] << nl;
85 for (label i = 1; i < bbs.size(); i++)
87 Info<< "\t " << bbs[i]<< nl;
89 Info<< "\tSurface bounding box : " << surfBb[procI] << nl
90 << "\tTriangles : " << nFaces[procI] << nl
91 << "\tVertices : " << nPoints[procI]
100 int main(int argc, char *argv[])
104 "redistribute a triSurface"
107 argList::validArgs.append("triSurfaceMesh");
108 argList::validArgs.append("distributionType");
109 argList::addBoolOption
112 "preserve surface outside of mesh bounds"
115 #include "setRootCase.H"
116 #include "createTime.H"
117 runTime.functionObjects().off();
119 const fileName surfFileName = args[1];
120 const word distType = args[2];
122 Info<< "Reading surface from " << surfFileName << nl << nl
123 << "Using distribution method "
124 << distributedTriSurfaceMesh::distributionTypeNames_[distType]
125 << " " << distType << nl << endl;
127 const bool keepNonMapped = args.options().found("keepNonMapped");
131 Info<< "Preserving surface outside of mesh bounds." << nl << endl;
135 Info<< "Removing surface outside of mesh bounds." << nl << endl;
139 if (!Pstream::parRun())
141 FatalErrorIn(args.executable())
142 << "Please run this program on the decomposed case."
143 << " It will read surface " << surfFileName
144 << " and decompose it such that it overlaps the mesh bounding box."
149 #include "createPolyMesh.H"
151 Random rndGen(653213);
153 // Determine mesh bounding boxes:
154 List<List<treeBoundBox> > meshBb(Pstream::nProcs());
156 meshBb[Pstream::myProcNo()] = List<treeBoundBox>
161 boundBox(mesh.points(), false)
162 ).extend(rndGen, 1E-3)
164 Pstream::gatherList(meshBb);
165 Pstream::scatterList(meshBb);
170 surfFileName, // name
171 //runTime.findInstance("triSurface", surfFileName), // instance
172 runTime.constant(), // instance
173 "triSurface", // local
179 const fileName actualPath(io.filePath());
180 fileName localPath(actualPath);
181 localPath.replace(runTime.rootPath() + '/', "");
183 if (actualPath == io.objectPath())
185 Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
189 Info<< "Loading undecomposed surface " << localPath << nl << endl;
193 // Create dummy dictionary for bounding boxes if does not exist.
194 if (!isFile(actualPath / "Dict"))
197 dict.add("bounds", meshBb[Pstream::myProcNo()]);
198 dict.add("distributionType", distType);
199 dict.add("mergeDistance", SMALL);
216 Info<< "Writing dummy bounds dictionary to " << ioDict.name()
219 ioDict.regIOobject::writeObject
222 IOstream::currentVersion,
223 ioDict.time().writeCompression()
229 distributedTriSurfaceMesh surfMesh(io);
230 Info<< "Loaded surface" << nl << endl;
233 // Generate a test field
235 const triSurface& s = static_cast<const triSurface&>(surfMesh);
237 autoPtr<triSurfaceVectorField> fcPtr
239 new triSurfaceVectorField
243 surfMesh.searchableSurface::name(), // name
244 surfMesh.searchableSurface::instance(), // instance
245 surfMesh.searchableSurface::local(), // local
254 triSurfaceVectorField& fc = fcPtr();
258 fc[triI] = s[triI].centre(s.points());
261 // Steal pointer and store object on surfMesh
262 fcPtr.ptr()->store();
266 // Write per-processor stats
267 Info<< "Before redistribution:" << endl;
268 writeProcStats(surfMesh, meshBb);
272 Info<< "Redistributing surface" << nl << endl;
273 autoPtr<mapDistribute> faceMap;
274 autoPtr<mapDistribute> pointMap;
277 meshBb[Pstream::myProcNo()],
288 // Write per-processor stats
289 Info<< "After redistribution:" << endl;
290 writeProcStats(surfMesh, meshBb);
293 Info<< "Writing surface." << nl << endl;
294 surfMesh.searchableSurface::write();
296 Info<< "End\n" << endl;
302 // ************************************************************************* //