ENH: partialWrite: support lagrangian
[OpenFOAM-1.7.x.git] / applications / utilities / surface / surfaceRedistributePar / surfaceRedistributePar.C
blobe21b82b27ae8c25dfab0f67414afe306d779b2aa
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2007 OpenCFD Ltd.
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 << endl
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::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");
121     if (keepNonMapped)
122     {
123         Info<< "Preserving surface outside of mesh bounds." << nl << endl;
124     }
125     else
126     {
127         Info<< "Removing surface outside of mesh bounds." << nl << endl;
128     }
131     if (!Pstream::parRun())
132     {
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."
137             << exit(FatalError);
138     }
141 #   include "createPolyMesh.H"
143     Random rndGen(653213);
145     // Determine mesh bounding boxes:
146     List<List<treeBoundBox> > meshBb(Pstream::nProcs());
147     {
148         meshBb[Pstream::myProcNo()] = List<treeBoundBox>
149         (
150             1,
151             treeBoundBox
152             (
153                 boundBox(mesh.points(), false)
154             ).extend(rndGen, 1E-3)
155         );
156         Pstream::gatherList(meshBb);
157         Pstream::scatterList(meshBb);
158     }
160     IOobject io
161     (
162         surfFileName,         // name
163         //runTime.findInstance("triSurface", surfFileName),   // instance
164         runTime.constant(),   // instance
165         "triSurface",         // local
166         runTime,              // registry
167         IOobject::MUST_READ,
168         IOobject::NO_WRITE
169     );
171     const fileName actualPath(io.filePath());
172     fileName localPath(actualPath);
173     localPath.replace(runTime.rootPath() + '/', "");
175     if (actualPath == io.objectPath())
176     {
177         Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
178     }
179     else
180     {
181         Info<< "Loading undecomposed surface " << localPath << nl << endl;
182     }
185     // Create dummy dictionary for bounding boxes if does not exist.
186     if (!isFile(actualPath / "Dict"))
187     {
188         dictionary dict;
189         dict.add("bounds", meshBb[Pstream::myProcNo()]);
190         dict.add("distributionType", distType);
191         dict.add("mergeDistance", SMALL);
193         IOdictionary ioDict
194         (
195             IOobject
196             (
197                 io.name() + "Dict",
198                 io.instance(),
199                 io.local(),
200                 io.db(),
201                 IOobject::NO_READ,
202                 IOobject::NO_WRITE,
203                 false
204             ),
205             dict
206         );
208         Info<< "Writing dummy bounds dictionary to " << ioDict.name()
209             << nl << endl;
211         ioDict.regIOobject::writeObject
212         (
213             IOstream::ASCII,
214             IOstream::currentVersion,
215             ioDict.time().writeCompression()        
216         );
217     }
220     // Load surface
221     distributedTriSurfaceMesh surfMesh(io);
222     Info<< "Loaded surface" << nl << endl;
225     // Generate a test field
226     {
227         const triSurface& s = static_cast<const triSurface&>(surfMesh);
229         autoPtr<triSurfaceVectorField> fcPtr
230         (
231             new triSurfaceVectorField
232             (
233                 IOobject
234                 (
235                     surfMesh.searchableSurface::name(),     // name
236                     surfMesh.searchableSurface::instance(), // instance
237                     surfMesh.searchableSurface::local(),    // local
238                     surfMesh,
239                     IOobject::NO_READ,
240                     IOobject::AUTO_WRITE
241                 ),
242                 surfMesh,
243                 dimLength
244             )
245         );
246         triSurfaceVectorField& fc = fcPtr();
248         forAll(fc, triI)
249         {
250             fc[triI] = s[triI].centre(s.points());
251         }
253         // Steal pointer and store object on surfMesh
254         fcPtr.ptr()->store();
255     }
258     // Write per-processor stats
259     Info<< "Before redistribution:" << endl;
260     writeProcStats(surfMesh, meshBb);
263     // Do redistribution
264     Info<< "Redistributing surface" << nl << endl;
265     autoPtr<mapDistribute> faceMap;
266     autoPtr<mapDistribute> pointMap;
267     surfMesh.distribute
268     (
269         meshBb[Pstream::myProcNo()],
270         keepNonMapped,
271         faceMap,
272         pointMap
273     );
274     faceMap.clear();
275     pointMap.clear();
277     Info<< endl;
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;
290     return 0;
294 // ************************************************************************* //