surfaceRedistributePar.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2015-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Application
28  surfaceRedistributePar
29 
30 Group
31  grpSurfaceUtilities
32 
33 Description
34  (Re)distribution of triSurface. Either takes an undecomposed surface
35  or an already decomposed surface and redistributes it so that each
36  processor has all triangles that overlap its mesh.
37 
38 Note
39  - best decomposition option is hierarchical since it guarantees
40  square decompositions.
41  - triangles might be present on multiple processors.
42  - merging uses geometric tolerance so take care with writing precision.
43 
44 \*---------------------------------------------------------------------------*/
45 
46 #include "argList.H"
47 #include "Time.H"
48 #include "polyMesh.H"
50 #include "mapDistribute.H"
51 #include "decompositionModel.H"
52 
53 using namespace Foam;
54 
55 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
56 
57 // Print on master all the per-processor surface stats.
58 void writeProcStats
59 (
60  const triSurface& s,
62 )
63 {
64  // Determine surface bounding boxes, faces, points
65  List<treeBoundBox> surfBb
66  (
67  UPstream::listGatherValues<treeBoundBox>(treeBoundBox(s.points()))
68  );
69  labelList nPoints(UPstream::listGatherValues<label>(s.points().size()));
70  labelList nFaces(UPstream::listGatherValues<label>(s.size()));
71 
72  if (Pstream::master())
73  {
74  forAll(surfBb, proci)
75  {
76  Info<< "processor" << proci << nl;
77 
78  const List<treeBoundBox>& bbs = meshBb[proci];
79  forAll(bbs, i)
80  {
81  if (!i)
82  {
83  Info<< "\tMesh bounds : ";
84  }
85  else
86  {
87  Info<< "\t ";
88  }
89  Info<< bbs[i] << nl;
90  }
91  Info<< "\tSurface bounding box : " << surfBb[proci] << nl
92  << "\tTriangles : " << nFaces[proci] << nl
93  << "\tVertices : " << nPoints[proci]
94  << endl;
95  }
96  Info<< endl;
97  }
98 }
99 
100 
101 
102 int main(int argc, char *argv[])
103 {
105  (
106  "Redistribute a triSurface."
107  " The specified surface must be located in the constant/triSurface"
108  " directory"
109  );
110 
111  argList::addArgument("triSurfaceMesh");
112  argList::addArgument("distributionType");
114  (
115  "keepNonMapped",
116  "Preserve surface outside of mesh bounds"
117  );
118 
119  #include "setRootCase.H"
120  #include "createTime.H"
122 
123  const auto surfFileName = args.get<fileName>(1);
124  const auto distTypeName = args.get<word>(2);
125  const label distType =
127 
128  Info<< "Reading surface from " << surfFileName << nl << nl
129  << "Using distribution method "
130  << distTypeName << nl << endl;
131 
132  const bool keepNonMapped = args.found("keepNonMapped");
133 
134  if (keepNonMapped)
135  {
136  Info<< "Preserving surface outside of mesh bounds." << nl << endl;
137  }
138  else
139  {
140  Info<< "Removing surface outside of mesh bounds." << nl << endl;
141  }
142 
143 
144  if (!Pstream::parRun())
145  {
147  << "Please run this program on the decomposed case."
148  << " It will read surface " << surfFileName
149  << " and decompose it such that it overlaps the mesh bounding box."
150  << exit(FatalError);
151  }
152 
153 
154  Random rndGen(653213);
155 
156  // For independent decomposition, ensure that distributedTriSurfaceMesh
157  // can find the alternative decomposeParDict specified via the
158  // -decomposeParDict option.
160  {
161  // Ensure demand-driven decompositionMethod finds alternative
162  // decomposeParDict location properly.
163 
164  IOdictionary* dictPtr = new IOdictionary
165  (
167  (
168  IOobject
169  (
171  runTime.system(),
172  runTime,
176  ),
177  args.getOrDefault<fileName>("decomposeParDict", "")
178  )
179  );
180 
181  // Store it on the object registry, but to be found it must also
182  // have the expected "decomposeParDict" name.
183 
185  runTime.store(dictPtr);
186  }
187 
188  // Determine mesh bounding boxes:
190  if (distType == distributedTriSurfaceMesh::FOLLOW)
191  {
192  #include "createPolyMesh.H"
193 
195  (
196  1,
197  treeBoundBox(mesh.points()).extend(rndGen, 1e-3)
198  );
200  }
201 
202  IOobject io
203  (
204  surfFileName, // name
205  //runTime.findInstance("triSurface", surfFileName), // instance
206  runTime.constant(), // instance
207  "triSurface", // local
208  runTime, // registry
211  );
212 
213  // Look for file (using searchableSurface rules)
214  const fileName actualPath(io.typeFilePath<searchableSurface>());
215  fileName localPath(actualPath);
216  localPath.replace(runTime.rootPath() + '/', "");
217 
218 
220 
221  if (actualPath == io.objectPath())
222  {
223  Info<< "Loading local (decomposed) surface " << localPath << nl <<endl;
224  surfMeshPtr.reset(new distributedTriSurfaceMesh(io));
225  }
226  else
227  {
228  Info<< "Loading undecomposed surface " << localPath
229  << " on master only" << endl;
230 
231  triSurface s;
232  List<treeBoundBox> bbs;
233  if (Pstream::master())
234  {
235  // Actually load the surface
236  const bool oldParRun = Pstream::parRun(false);
237  triSurfaceMesh surf(io);
238  Pstream::parRun(oldParRun); // Restore parallel state
239  s = surf;
241  }
242  else
243  {
245  }
246 
248  dict.add("distributionType", distTypeName);
249  dict.add("mergeDistance", SMALL);
250  dict.add("bounds", bbs);
251 
252  // Scatter patch information
253  Pstream::broadcast(s.patches());
254 
255  // Construct distributedTrisurfaceMesh from components
256  IOobject notReadIO(io);
257  notReadIO.readOpt(IOobject::NO_READ);
258  surfMeshPtr.reset(new distributedTriSurfaceMesh(notReadIO, s, dict));
259  }
260 
261  distributedTriSurfaceMesh& surfMesh = surfMeshPtr();
262 
263 
264  // Write per-processor stats
265  Info<< "Before redistribution:" << endl;
266  writeProcStats(surfMesh, meshBb);
267 
268 
269  // Do redistribution
270  Info<< "Redistributing surface" << nl << endl;
272  autoPtr<mapDistribute> pointMap;
273  surfMesh.distribute
274  (
276  keepNonMapped,
277  faceMap,
278  pointMap
279  );
280  faceMap.clear();
281  pointMap.clear();
282 
283  Info<< endl;
284 
285 
286  // Write per-processor stats
287  Info<< "After redistribution:" << endl;
288  writeProcStats(surfMesh, meshBb);
289 
290 
291  Info<< "Writing surface." << nl << endl;
292  surfMesh.objectRegistry::write();
293 
294  Info<< "End\n" << endl;
295 
296  return 0;
297 }
298 
299 
300 // ************************************************************************* //
static const Enum< distributionType > distributionTypeNames_
dictionary dict
static void addNote(const string &note)
Add extra notes for the usage information.
Definition: argList.C:462
Required Variables.
static const treeBoundBox & null() noexcept
The null treeBoundBox is the same as an inverted box.
Definition: treeBoundBox.H:187
A class for handling file names.
Definition: fileName.H:72
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void off()
Switch the function objects off.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:608
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Random rndGen
Definition: createFields.H:23
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1061
void clear() noexcept
Same as reset(nullptr)
Definition: autoPtr.H:255
static void addBoolOption(const word &optName, const string &usage="", bool advanced=false)
Add a bool option to validOptions with usage information.
Definition: argList.C:374
bool store()
Register object with its registry and transfer ownership to the registry.
Definition: regIOobjectI.H:36
const fileName & rootPath() const noexcept
Return the rootPath.
Definition: TimePathsI.H:66
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
static const boundBox greatBox
A large boundBox: min/max == -/+ ROOTVGREAT.
Definition: boundBox.H:119
Base class of (analytical or triangulated) surface. Encapsulates all the search routines. WIP.
Ignore writing from objectRegistry::writeObject()
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Can be negative if the process i...
Definition: UPstream.H:1086
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
fileName typeFilePath(const bool search=true) const
Call localFilePath or globalFilePath for given type depending on its is_globalIOobject trait...
Pair< int > faceMap(const label facePi, const face &faceP, const label faceNi, const face &faceN)
static void broadcast(Type &value, const label comm=UPstream::worldComm)
Broadcast content (contiguous or non-contiguous) to all communicator ranks. Does nothing in non-paral...
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1078
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
IOoject and searching on triSurface.
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
static label nProcs(const label communicator=worldComm)
Number of ranks in parallel run (for given communicator). It is 1 for serial run. ...
Definition: UPstream.H:1077
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
dynamicFvMesh & mesh
const functionObjectList & functionObjects() const noexcept
Return the list of function objects.
Definition: Time.H:714
A class for handling words, derived from Foam::string.
Definition: word.H:63
label nPoints
const word & system() const noexcept
Return system name.
Definition: TimePathsI.H:118
Random number generator.
Definition: Random.H:55
A surface mesh consisting of general polygon faces that has IO capabilities and a registry for storin...
Definition: surfMesh.H:62
IOoject and searching on distributed triSurface. All processor hold (possibly overlapping) part of th...
const word & constant() const noexcept
Return constant name.
Definition: TimePathsI.H:112
static const word canonicalName
The canonical name ("decomposeParDict") under which the MeshObject is registered. ...
virtual void rename(const word &newName)
Rename.
Definition: regIOobject.C:484
static void allGatherList(UList< T > &values, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Gather data, but keep individual values separate. Uses MPI_Allgather or manual linear/tree communicat...
T get(const label index) const
Get a value from the argument at index.
Definition: argListI.H:271
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition: UPstream.H:1094
Nothing to be read.
Automatically write from objectRegistry::writeObject()
static void addArgument(const string &argName, const string &usage="")
Append a (mandatory) argument to validArgs.
Definition: argList.C:351
Standard boundBox with extra functionality for use in octree.
Definition: treeBoundBox.H:90
messageStream Info
Information stream (stdout output on master, null elsewhere)
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
Triangulated surface description with patch information.
Definition: triSurface.H:71
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::argList args(argc, argv)
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:180
Request registration (bool: true)
List< treeBoundBox > meshBb(1, treeBoundBox(coarseMesh.points()).extend(rndGen, 1e-3))
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
Namespace for OpenFOAM.
static IOobject selectIO(const IOobject &io, const fileName &altFile, const word &ioName="")
Return the IOobject, but also consider an alternative file name.
Definition: IOobject.C:256