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