1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2007 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
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 << endl
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[])
102 argList::validArgs.append("triSurfaceMesh");
103 argList::validArgs.append("distributionType");
105 argList::validOptions.insert("keepNonMapped", "");
106 # include "setRootCase.H"
107 # include "createTime.H"
108 runTime.functionObjects().off();
110 fileName surfFileName(args.additionalArgs()[0]);
111 Info<< "Reading surface from " << surfFileName << nl << endl;
113 const word distType(args.additionalArgs()[1]);
115 Info<< "Using distribution method "
116 << distributedTriSurfaceMesh::distributionTypeNames_[distType]
117 << " " << distType << nl << endl;
119 bool keepNonMapped = args.options().found("keepNonMapped");
123 Info<< "Preserving surface outside of mesh bounds." << nl << endl;
127 Info<< "Removing surface outside of mesh bounds." << nl << endl;
131 if (!Pstream::parRun())
133 FatalErrorIn(args.executable())
134 << "Please run this program on the decomposed case."
135 << " It will read surface " << surfFileName
136 << " and decompose it such that it overlaps the mesh bounding box."
141 # include "createPolyMesh.H"
143 Random rndGen(653213);
145 // Determine mesh bounding boxes:
146 List<List<treeBoundBox> > meshBb(Pstream::nProcs());
148 meshBb[Pstream::myProcNo()] = List<treeBoundBox>
153 boundBox(mesh.points(), false)
154 ).extend(rndGen, 1E-3)
156 Pstream::gatherList(meshBb);
157 Pstream::scatterList(meshBb);
162 surfFileName, // name
163 //runTime.findInstance("triSurface", surfFileName), // instance
164 runTime.constant(), // instance
165 "triSurface", // local
171 const fileName actualPath(io.filePath());
172 fileName localPath(actualPath);
173 localPath.replace(runTime.rootPath() + '/', "");
175 if (actualPath == io.objectPath())
177 Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
181 Info<< "Loading undecomposed surface " << localPath << nl << endl;
185 // Create dummy dictionary for bounding boxes if does not exist.
186 if (!isFile(actualPath / "Dict"))
189 dict.add("bounds", meshBb[Pstream::myProcNo()]);
190 dict.add("distributionType", distType);
191 dict.add("mergeDistance", SMALL);
208 Info<< "Writing dummy bounds dictionary to " << ioDict.name()
211 ioDict.regIOobject::writeObject
214 IOstream::currentVersion,
215 ioDict.time().writeCompression()
221 distributedTriSurfaceMesh surfMesh(io);
222 Info<< "Loaded surface" << nl << endl;
225 // Generate a test field
227 const triSurface& s = static_cast<const triSurface&>(surfMesh);
229 autoPtr<triSurfaceVectorField> fcPtr
231 new triSurfaceVectorField
235 surfMesh.searchableSurface::name(), // name
236 surfMesh.searchableSurface::instance(), // instance
237 surfMesh.searchableSurface::local(), // local
246 triSurfaceVectorField& fc = fcPtr();
250 fc[triI] = s[triI].centre(s.points());
253 // Steal pointer and store object on surfMesh
254 fcPtr.ptr()->store();
258 // Write per-processor stats
259 Info<< "Before redistribution:" << endl;
260 writeProcStats(surfMesh, meshBb);
264 Info<< "Redistributing surface" << nl << endl;
265 autoPtr<mapDistribute> faceMap;
266 autoPtr<mapDistribute> pointMap;
269 meshBb[Pstream::myProcNo()],
280 // Write per-processor stats
281 Info<< "After redistribution:" << endl;
282 writeProcStats(surfMesh, meshBb);
285 Info<< "Writing surface." << nl << endl;
286 surfMesh.searchableSurface::write();
288 Info<< "End\n" << endl;
294 // ************************************************************************* //