surfaceRedistributePar.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2023 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 Application
25  surfaceRedistributePar
26 
27 Description
28  (Re)distribution of triSurface. Either takes an undecomposed surface
29  or an already decomposed surface and redistributes it so that each
30  processor has all triangles that overlap its mesh.
31 
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.
37 
38 \*---------------------------------------------------------------------------*/
39 
40 #include "argList.H"
41 #include "Time.H"
42 #include "polyMesh.H"
44 #include "distributionMap.H"
45 #include "localIOdictionary.H"
46 
47 using namespace Foam;
48 
49 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
50 
51 // Print on master all the per-processor surface stats.
52 void writeProcStats
53 (
54  const triSurface& s,
56 )
57 {
58  // Determine surface bounding boxes, faces, points
60  {
61  surfBb[Pstream::myProcNo()] = treeBoundBox(s.points());
62  Pstream::gatherList(surfBb);
63  Pstream::scatterList(surfBb);
64  }
65 
67  nPoints[Pstream::myProcNo()] = s.points().size();
70 
71  labelList nFaces(Pstream::nProcs());
72  nFaces[Pstream::myProcNo()] = s.size();
73  Pstream::gatherList(nFaces);
74  Pstream::scatterList(nFaces);
75 
76  forAll(surfBb, proci)
77  {
78  const List<treeBoundBox>& bbs = meshBb[proci];
79 
80  Info<< "processor" << proci << nl
81  << "\tMesh bounds : " << bbs[0] << nl;
82  for (label i = 1; i < bbs.size(); i++)
83  {
84  Info<< "\t " << bbs[i]<< nl;
85  }
86  Info<< "\tSurface bounding box : " << surfBb[proci] << nl
87  << "\tTriangles : " << nFaces[proci] << nl
88  << "\tVertices : " << nPoints[proci]
89  << endl;
90  }
91  Info<< endl;
92 }
93 
94 
95 
96 int main(int argc, char *argv[])
97 {
99  (
100  "redistribute a triSurface"
101  );
102 
103  argList::validArgs.append("surface file");
104  argList::validArgs.append("distribution type");
106  (
107  "keepNonMapped",
108  "preserve surface outside of mesh bounds"
109  );
110 
111  #include "setRootCase.H"
113 
114  const fileName surfFileName = args[1];
115  const word distType = args[2];
116 
117  Info<< "Reading surface from " << surfFileName << nl << nl
118  << "Using distribution method "
120  << " " << distType << nl << endl;
121 
122  const bool keepNonMapped = args.options().found("keepNonMapped");
123 
124  if (keepNonMapped)
125  {
126  Info<< "Preserving surface outside of mesh bounds." << nl << endl;
127  }
128  else
129  {
130  Info<< "Removing surface outside of mesh bounds." << nl << endl;
131  }
132 
133 
134  if (!Pstream::parRun())
135  {
137  << "Please run this program on the decomposed case."
138  << " It will read surface " << surfFileName
139  << " and decompose it such that it overlaps the mesh bounding box."
140  << exit(FatalError);
141  }
142 
143 
144  #include "createPolyMesh.H"
145 
146  // Determine mesh bounding boxes:
148  {
150  (
151  1,
152  treeBoundBox(boundBox(mesh.points(), false)).extend(1e-3)
153  );
156  }
157 
159  (
160  surfFileName,
161  runTime.constant(),
163  runTime,
166  );
167 
168  // Look for file (using searchableSurface rules)
169  const fileName actualPath(io.filePath());
170  fileName localPath(actualPath);
171  localPath.replace(runTime.rootPath() + '/', "");
172 
173  if (actualPath == io.objectPath(false))
174  {
175  Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
176  }
177  else
178  {
179  Info<< "Loading undecomposed surface " << localPath << nl << endl;
180  }
181 
182 
183  // Create dummy dictionary for bounding boxes if does not exist.
184  if (!isFile(actualPath / "Dict"))
185  {
187  dict.add("bounds", meshBb[Pstream::myProcNo()]);
188  dict.add("distributionType", distType);
189  dict.add("mergeDistance", small);
190 
191  localIOdictionary ioDict
192  (
193  IOobject
194  (
195  io.name() + "Dict",
196  io.instance(),
197  io.local(),
198  io.db(),
201  false
202  ),
203  dict
204  );
205 
206  Info<< "Writing dummy bounds dictionary to " << ioDict.name()
207  << nl << endl;
208 
209  // Force writing in ascii
210  ioDict.regIOobject::writeObject
211  (
214  ioDict.time().writeCompression(),
215  true
216  );
217  }
218 
219 
220  // Load surface
222  Info<< "Loaded surface" << nl << endl;
223 
224 
225  // Generate a test field
226  {
227  const triSurface& s = static_cast<const triSurface&>(surfMesh);
228 
230  (
232  (
233  IOobject
234  (
235  "faceCentres", // name
236  surfMesh.searchableSurface::time().name(), // instance
237  surfMesh,
240  ),
241  surfMesh,
242  dimLength,
243  s.faceCentres()
244  )
245  );
246 
247  // Steal pointer and store object on surfMesh
248  fcPtr.ptr()->store();
249  }
250 
251 
252  // Write per-processor stats
253  Info<< "Before redistribution:" << endl;
254  writeProcStats(surfMesh, meshBb);
255 
256 
257  // Do redistribution
258  Info<< "Redistributing surface" << nl << endl;
260  autoPtr<distributionMap> pointMap;
261  surfMesh.distribute
262  (
264  keepNonMapped,
265  faceMap,
266  pointMap
267  );
268  faceMap.clear();
269  pointMap.clear();
270 
271  Info<< endl;
272 
273 
274  // Write per-processor stats
275  Info<< "After redistribution:" << endl;
276  writeProcStats(surfMesh, meshBb);
277 
278 
279  Info<< "Writing surface." << nl << endl;
280  surfMesh.objectRegistry::write();
281 
282  Info<< "End\n" << endl;
283 
284  return 0;
285 }
286 
287 
288 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
const word & name() const
Return name.
Definition: IOobject.H:310
static const versionNumber currentVersion
Current version number.
Definition: IOstream.H:203
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:91
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static void scatterList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Scatter data. Reverse of gatherList.
static void gatherList(const List< commsStruct > &comms, List< T > &Values, const int tag, const label comm)
Gather data but keep individual values separate.
static label nProcs(const label communicator=0)
Number of processes in parallel run.
Definition: UPstream.H:411
static bool & parRun()
Is this a parallel run?
Definition: UPstream.H:399
static int myProcNo(const label communicator=0)
Number of this process (starting from masterNo() = 0)
Definition: UPstream.H:429
static void addNote(const string &)
Add extra notes for the usage information.
Definition: argList.C:159
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
const Foam::HashTable< string > & options() const
Return options.
Definition: argListI.H:96
static SLList< string > validArgs
A list of valid (mandatory) arguments.
Definition: argList.H:153
An auto-pointer similar to the STL auto_ptr but with automatic casting to a reference to the type and...
Definition: autoPtr.H:51
void clear()
Delete object (if the pointer is valid) and set pointer to.
Definition: autoPtrI.H:126
A bounding box defined in terms of the points at its extremities.
Definition: boundBox.H:59
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1169
IOoject and searching on distributed triSurface. All processor hold (possibly overlapping) part of th...
static const NamedEnum< distributionType, 3 > distributionTypeNames_
A class for handling file names.
Definition: fileName.H:82
localIOdictionary derived from IOdictionary with global set false to disable parallel master reading.
static const word & geometryDir()
Return the geometry directory name.
A surface mesh consisting of general polygon faces.
Definition: surfMesh.H:60
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:90
treeBoundBox extend(const scalar s) const
Return asymetrically extended bounding box, with guaranteed.
Triangulated surface description with patch information.
Definition: triSurface.H:69
Templated form of IOobject providing type information for file reading and header type checking.
Definition: IOobject.H:531
A class for handling words, derived from string.
Definition: word.H:62
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
int main(int argc, char *argv[])
Definition: financialFoam.C:44
label nPoints
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.name(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Namespace for OpenFOAM.
bool isFile(const fileName &, const bool checkVariants=true, const bool followLink=true)
Does the name exist as a file in the file system?
Definition: POSIX.C:555
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
const doubleScalar e
Definition: doubleScalar.H:105
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
messageStream Info
const dimensionSet dimLength
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
error FatalError
static const char nl
Definition: Ostream.H:260
List< treeBoundBox > meshBb(1, treeBoundBox(boundBox(coarseMesh.points(), false)).extend(1e-3))
dictionary dict
Foam::argList args(argc, argv)