BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / applications / utilities / surface / surfaceRedistributePar / surfaceRedistributePar.C
blob98c56dabd6a5830dd4a003dca00377efe6a016b0
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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/>.
24 Application
25     surfaceRedistributePar
27 Description
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.
32 Note
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"
42 #include "argList.H"
43 #include "Time.H"
44 #include "polyMesh.H"
45 #include "distributedTriSurfaceMesh.H"
46 #include "mapDistribute.H"
47 #include "triSurfaceFields.H"
48 #include "Pair.H"
50 using namespace Foam;
52 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
54 // Print on master all the per-processor surface stats.
55 void writeProcStats
57     const triSurface& s,
58     const List<List<treeBoundBox> >& meshBb
61     // Determine surface bounding boxes, faces, points
62     List<treeBoundBox> surfBb(Pstream::nProcs());
63     {
64         surfBb[Pstream::myProcNo()] = treeBoundBox(s.points());
65         Pstream::gatherList(surfBb);
66         Pstream::scatterList(surfBb);
67     }
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);
79     forAll(surfBb, procI)
80     {
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++)
86         {
87             Info<< "\t                       " << bbs[i]<< nl;
88         }
89         Info<< "\tSurface bounding box : " << surfBb[procI] << nl
90             << "\tTriangles            : " << nFaces[procI] << nl
91             << "\tVertices             : " << nPoints[procI]
92             << endl;
93     }
94     Info<< endl;
98 // Main program:
100 int main(int argc, char *argv[])
102     argList::addNote
103     (
104         "redistribute a triSurface"
105     );
107     argList::validArgs.append("triSurfaceMesh");
108     argList::validArgs.append("distributionType");
109     argList::addBoolOption
110     (
111         "keepNonMapped",
112         "preserve surface outside of mesh bounds"
113     );
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");
129     if (keepNonMapped)
130     {
131         Info<< "Preserving surface outside of mesh bounds." << nl << endl;
132     }
133     else
134     {
135         Info<< "Removing surface outside of mesh bounds." << nl << endl;
136     }
139     if (!Pstream::parRun())
140     {
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."
145             << exit(FatalError);
146     }
149     #include "createPolyMesh.H"
151     Random rndGen(653213);
153     // Determine mesh bounding boxes:
154     List<List<treeBoundBox> > meshBb(Pstream::nProcs());
155     {
156         meshBb[Pstream::myProcNo()] = List<treeBoundBox>
157         (
158             1,
159             treeBoundBox
160             (
161                 boundBox(mesh.points(), false)
162             ).extend(rndGen, 1E-3)
163         );
164         Pstream::gatherList(meshBb);
165         Pstream::scatterList(meshBb);
166     }
168     IOobject io
169     (
170         surfFileName,         // name
171         //runTime.findInstance("triSurface", surfFileName),   // instance
172         runTime.constant(),   // instance
173         "triSurface",         // local
174         runTime,              // registry
175         IOobject::MUST_READ,
176         IOobject::NO_WRITE
177     );
179     const fileName actualPath(io.filePath());
180     fileName localPath(actualPath);
181     localPath.replace(runTime.rootPath() + '/', "");
183     if (actualPath == io.objectPath())
184     {
185         Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
186     }
187     else
188     {
189         Info<< "Loading undecomposed surface " << localPath << nl << endl;
190     }
193     // Create dummy dictionary for bounding boxes if does not exist.
194     if (!isFile(actualPath / "Dict"))
195     {
196         dictionary dict;
197         dict.add("bounds", meshBb[Pstream::myProcNo()]);
198         dict.add("distributionType", distType);
199         dict.add("mergeDistance", SMALL);
201         IOdictionary ioDict
202         (
203             IOobject
204             (
205                 io.name() + "Dict",
206                 io.instance(),
207                 io.local(),
208                 io.db(),
209                 IOobject::NO_READ,
210                 IOobject::NO_WRITE,
211                 false
212             ),
213             dict
214         );
216         Info<< "Writing dummy bounds dictionary to " << ioDict.name()
217             << nl << endl;
219         ioDict.regIOobject::writeObject
220         (
221             IOstream::ASCII,
222             IOstream::currentVersion,
223             ioDict.time().writeCompression()
224         );
225     }
228     // Load surface
229     distributedTriSurfaceMesh surfMesh(io);
230     Info<< "Loaded surface" << nl << endl;
233     // Generate a test field
234     {
235         const triSurface& s = static_cast<const triSurface&>(surfMesh);
237         autoPtr<triSurfaceVectorField> fcPtr
238         (
239             new triSurfaceVectorField
240             (
241                 IOobject
242                 (
243                     surfMesh.searchableSurface::name(),     // name
244                     surfMesh.searchableSurface::instance(), // instance
245                     surfMesh.searchableSurface::local(),    // local
246                     surfMesh,
247                     IOobject::NO_READ,
248                     IOobject::AUTO_WRITE
249                 ),
250                 surfMesh,
251                 dimLength
252             )
253         );
254         triSurfaceVectorField& fc = fcPtr();
256         forAll(fc, triI)
257         {
258             fc[triI] = s[triI].centre(s.points());
259         }
261         // Steal pointer and store object on surfMesh
262         fcPtr.ptr()->store();
263     }
266     // Write per-processor stats
267     Info<< "Before redistribution:" << endl;
268     writeProcStats(surfMesh, meshBb);
271     // Do redistribution
272     Info<< "Redistributing surface" << nl << endl;
273     autoPtr<mapDistribute> faceMap;
274     autoPtr<mapDistribute> pointMap;
275     surfMesh.distribute
276     (
277         meshBb[Pstream::myProcNo()],
278         keepNonMapped,
279         faceMap,
280         pointMap
281     );
282     faceMap.clear();
283     pointMap.clear();
285     Info<< endl;
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;
298     return 0;
302 // ************************************************************************* //