loadOrCreateMesh.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) 2012-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2024 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 \*---------------------------------------------------------------------------*/
28 
29 #include "loadOrCreateMesh.H"
30 #include "faMesh.H"
31 #include "Pstream.H"
32 #include "OSspecific.H"
33 #include "decomposedBlockData.H"
34 #include "IFstream.H"
35 
36 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
37 
38 bool Foam::checkFileExistence(const fileName& fName)
39 {
40  // Trimmed-down version of lookupAndCacheProcessorsPath
41  // with Foam::exists() check. No caching.
42 
43  // Check for two conditions:
44  // - file has to exist
45  // - if collated the entry has to exist inside the file
46 
47  // Note: bypass fileOperation::filePath(IOobject&) since has problems
48  // with going to a different number of processors
49  // (in collated format). Use file-based searching instead
50 
51  const auto& handler = Foam::fileHandler();
52  typedef fileOperation::procRangeType procRangeType;
53 
54  fileName path, pDir, local;
55  procRangeType group;
56  label numProcs;
57  const label proci =
58  fileOperation::splitProcessorPath
59  (fName, path, pDir, local, group, numProcs);
60 
61  bool found = false;
62 
63  if (proci != -1)
64  {
65  // Read all directories to see any beginning with processor
66  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
67 
68  const fileNameList dirEntries
69  (
70  handler.readDir(path, fileName::Type::DIRECTORY)
71  );
72 
73  // Extract info from processorN or processorsNN
74  // - highest processor number
75  // - directory+offset containing data for proci
76 
77  // label nProcs = 0;
78  for (const fileName& dirN : dirEntries)
79  {
80  // Analyse directory name
81  fileName rp, rd, rl;
82  label rNum;
83  const label readProci =
84  fileOperation::splitProcessorPath
85  (dirN, rp, rd, rl, group, rNum);
86 
87  if (proci == readProci)
88  {
89  // Found "processorN"
90  if (Foam::exists(path/dirN/local))
91  {
92  found = true;
93  break;
94  }
95  }
96  else if (rNum != -1)
97  {
98  // "processorsNN" or "processorsNN_start-end"
99  if (group.empty())
100  {
101  // "processorsNN"
102  if (proci < rNum && Foam::exists(path/dirN/local))
103  {
104  found = true;
105  break;
106  }
107  }
108  else if (group.contains(proci))
109  {
110  // "processorsNN_start-end"
111  // - save the local proc offset
112 
113  if (Foam::exists(path/dirN/local))
114  {
115  found = true;
116  break;
117  }
118  }
119  }
120  }
121  }
122 
123  if (!found)
124  {
125  found = Foam::exists(fName);
126  }
127 
128  return found;
129 }
130 
131 
133 (
134  const Time& runTime,
135  const fileName& meshPath,
136  const word& meshFile,
137  const bool verbose
138 )
139 {
140  #if 0
141 
142  // Simple directory scanning - too fragile
143  bool found = checkFileExistence(runTime.path()/meshPath/meshFile);
144 
145  #else
146 
147  // Trimmed-down version of lookupAndCacheProcessorsPath
148  // with Foam::exists() check. No caching.
149 
150  // Check for two conditions:
151  // - file has to exist
152  // - if collated the entry has to exist inside the file
153 
154  // Note: bypass fileOperation::filePath(IOobject&) since has problems
155  // with going to a different number of processors
156  // (in collated format). Use file-based searching instead
157 
158  const auto& handler = Foam::fileHandler();
159  typedef fileOperation::procRangeType procRangeType;
160 
161  const fileName fName
162  (
163  handler.filePath(runTime.path()/meshPath/meshFile)
164  );
165  bool found = handler.isFile(fName);
166  if (returnReduceAnd(found)) // worldComm
167  {
168  // Bit tricky: avoid having all slaves open file since this involves
169  // reading it on master and broadcasting it. This fails if file > 2G.
170  // So instead only read on master
171 
172  bool isCollated = false;
173 
174  // Note: can test only world-master. Since even host-collated will have
175  // same file format type for all processors
176  if (UPstream::master(UPstream::worldComm))
177  {
178  const bool oldParRun = UPstream::parRun(false);
179 
180  IFstream is(fName);
181  if (is.good())
182  {
183  IOobject io(meshFile, meshPath, runTime);
184  io.readHeader(is);
185 
186  isCollated = decomposedBlockData::isCollatedType(io);
187  }
188  UPstream::parRun(oldParRun);
189  }
190  Pstream::broadcast(isCollated); //UPstream::worldComm
191 
192 
193  // Collect block-number in individual filenames (might differ
194  // on different processors)
195  if (isCollated)
196  {
197  const label nProcs = UPstream::nProcs(fileHandler().comm());
198  const label myProcNo = UPstream::myProcNo(fileHandler().comm());
199 
200  // Collect file names on master of local communicator
201  const fileNameList fNames
202  (
203  Pstream::listGatherValues
204  (
205  fName,
206  fileHandler().comm(),
207  UPstream::msgType()
208  )
209  );
210 
211  // Collect local block number
212  label myBlockNumber = -1;
213  {
214  fileName path, pDir, local;
215  procRangeType group;
216  label numProcs;
217  label proci = fileOperation::splitProcessorPath
218  (
219  fName,
220  path,
221  pDir,
222  local,
223  group,
224  numProcs
225  );
226 
227  if (proci == -1 && group.empty())
228  {
229  // 'processorsXXX' format so contains all ranks
230  // according to worldComm
231  myBlockNumber = UPstream::myProcNo(UPstream::worldComm);
232  }
233  else
234  {
235  // 'processorsXXX_n-m' format so check for the
236  // relative rank
237  myBlockNumber = myProcNo;
238  }
239  }
240  const labelList myBlockNumbers
241  (
242  Pstream::listGatherValues
243  (
244  myBlockNumber,
245  fileHandler().comm(),
246  UPstream::msgType()
247  )
248  );
249 
250 
251 
252  // Determine for all whether the filename exists in the collated
253  // file.
254  boolList allFound(nProcs, false);
255 
256  if (UPstream::master(fileHandler().comm()))
257  {
258  // Store nBlocks and index of file that was used for nBlocks
259  label nBlocks = -1;
260  label blockRanki = -1;
261  forAll(fNames, ranki)
262  {
263  if
264  (
265  blockRanki == -1
266  || (fNames[ranki] != fNames[blockRanki])
267  )
268  {
269  blockRanki = ranki;
270  IFstream is(fNames[ranki]);
271  nBlocks = decomposedBlockData::getNumBlocks(is);
272  }
273 
274  allFound[ranki] = (myBlockNumbers[ranki] < nBlocks);
275  }
276  }
277 
278  found = Pstream::listScatterValues
279  (
280  allFound,
281  fileHandler().comm(),
282  UPstream::msgType()
283  );
284  }
285  }
286  #endif
287 
288  // Globally consistent information about who has a mesh
289  boolList haveFileOnProc
290  (
291  UPstream::allGatherValues<bool>(found, UPstream::worldComm)
292  );
293 
294  if (verbose)
295  {
296  Info<< "Per processor availability of \""
297  << meshFile << "\" file in " << meshPath << nl
298  << " " << flatOutput(haveFileOnProc) << nl << endl;
299  }
300 
301  return haveFileOnProc;
302 }
303 
304 
305 void Foam::removeProcAddressing(const faMesh& mesh)
306 {
307  IOobject io
308  (
309  "procAddressing",
310  mesh.facesInstance(),
311  faMesh::meshSubDir,
312  mesh.thisDb()
313  );
314 
315  for (const auto prefix : {"boundary", "edge", "face", "point"})
316  {
317  io.rename(prefix + word("ProcAddressing"));
318 
319  const fileName procFile(io.objectPath());
320  Foam::rm(procFile);
321  }
322 }
323 
324 
325 void Foam::removeProcAddressing(const polyMesh& mesh)
326 {
327  IOobject io
328  (
329  "procAddressing",
330  mesh.facesInstance(),
331  polyMesh::meshSubDir,
332  mesh.thisDb()
333  );
334 
335  for (const auto prefix : {"boundary", "cell", "face", "point"})
336  {
337  io.rename(prefix + word("ProcAddressing"));
338 
339  const fileName procFile(io.objectPath());
340  Foam::rm(procFile);
341  }
342 }
343 
344 
346 (
347  const IOobject& io,
348  fileName& facesInstance,
349  fileName& pointsInstance
350 )
351 {
352  const fileName meshSubDir
353  (
354  polyMesh::meshDir(io.name())
355  );
356 
357  if (UPstream::master())
358  {
359  const bool oldParRun = UPstream::parRun(false);
360  const label oldNumProcs = fileHandler().nProcs();
361  const int oldCache = fileOperation::cacheLevel(0);
362 
363  facesInstance = io.time().findInstance
364  (
365  meshSubDir,
366  "faces",
367  IOobjectOption::MUST_READ
368  );
369  pointsInstance = io.time().findInstance
370  (
371  meshSubDir,
372  "points",
373  IOobjectOption::MUST_READ
374  );
375 
376  fileOperation::cacheLevel(oldCache);
377  if (oldParRun)
378  {
379  const_cast<fileOperation&>(fileHandler()).nProcs(oldNumProcs);
380  }
381  UPstream::parRun(oldParRun);
382  }
383 
384  // Broadcast information to all
385  Pstream::broadcasts
386  (
387  UPstream::worldComm,
388  facesInstance,
389  pointsInstance
390  );
391 }
392 
393 
394 // ************************************************************************* //
boolList haveMeshFile(const Time &runTime, const fileName &meshPath, const word &meshFile="faces", const bool verbose=true)
Check for availability of specified mesh file (default: "faces")
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
constexpr const char *const group
Group name for atomic constants.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
dynamicFvMesh & mesh
void masterMeshInstance(const IOobject &io, fileName &facesInstance, fileName &pointsInstance)
Determine master faces instance.
regionProperties rp(runTime)
Miscellaneous file handling for meshes.
bool exists(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist (as DIRECTORY or FILE) in the file system?
Definition: POSIX.C:835
bool local
Definition: EEqn.H:20
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
bool checkFileExistence(const fileName &fName)
Check for availability of given file.
messageStream Info
Information stream (stdout output on master, null elsewhere)
void removeProcAddressing(const faMesh &mesh)
Remove procAddressing.
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
List< bool > boolList
A List of bools.
Definition: List.H:60
bool found
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition: POSIX.C:1404