Loading...
Searching...
No Matches
fileOperationRanks.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) 2022-2025 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28#include "fileOperation.H"
29#include "stringOps.H"
30#include "ITstream.H"
31#include "Pstream.H"
32#include "SHA1.H"
33#include "OSspecific.H" // for hostName()
34#include <cinttypes>
35
36// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
37
38namespace Foam
39{
40
41// Parse space, comma, semicolon separated list of integers, floats etc...
42template<class PrimitiveType>
43static List<PrimitiveType> splitStringToList(const std::string& str)
44{
45 const auto items = stringOps::splitAny(str, " ,;");
46
47 DynamicList<PrimitiveType> values(items.size());
48
49 for (const auto& item : items)
50 {
51 const std::string s(item.str());
52
53 PrimitiveType val;
54
55 if (Foam::read(s, val))
56 {
57 values.push_back(val);
58 }
59 else
60 {
61 // Report errors? Could get noisy...
62 }
63 }
64
65 return List<PrimitiveType>(std::move(values));
67
68} // End namespace Foam
69
70
71// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
72
73Foam::labelRange Foam::fileOperation::subRanks(const labelUList& mainIOranks)
74{
75 // Fast path - no IO ranks.
76 if (mainIOranks.empty())
77 {
78 return labelRange();
79 }
80
81 // The lowest numbered rank is the IO rank
82 // - linear search for the enclosing range
83 // - fallback is proc = 0, which silently adds master (0) into IO ranks
84
85 label begProc = 0;
87
88 const label myProci = UPstream::myProcNo(UPstream::worldComm);
89
90 forAllReverse(mainIOranks, i)
91 {
92 if (mainIOranks[i] <= myProci)
93 {
94 begProc = mainIOranks[i];
95 if (i+1 < mainIOranks.size())
96 {
97 endProc = mainIOranks[i+1];
98 }
99 break;
101 }
102
103 return labelRange(begProc, (endProc-begProc));
104}
105
106
108{
109 // Very similar to the code in UPstream::setHostCommunicators()
110 // except we need the leader information on *all* ranks!
111
112 const label myProci = UPstream::myProcNo(UPstream::worldComm);
113 const label numProc = UPstream::nProcs(UPstream::worldComm);
114
115 // Could also add lowercase etc, but since hostName()
116 // will be consistent within the same node, there is no need.
117 const SHA1Digest myDigest(SHA1(hostName()).digest());
118
119 List<SHA1Digest> digests(numProc);
120 digests[myProci] = myDigest;
121
122 // The fixed-length digest allows use of MPI_Allgather.
124 (
125 digests.data_bytes(), // Send/Recv
126 SHA1Digest::size_bytes(), // Num send/recv per rank
128 );
129
130
132
133 hostLeaders.push_back(0); // Always include master
134 for (label previ = 0, proci = 1; proci < digests.size(); ++proci)
135 {
136 if (digests[previ] != digests[proci])
137 {
138 hostLeaders.push_back(proci);
139 previ = proci;
140 }
141 }
142
143 return labelList(std::move(hostLeaders));
144
145 // Alternative is to recover information from commInterNode()
146 // and broadcast via commLocalNode()
147}
148
149
151(
152 // const bool useHost
153)
154{
155 // bool byHostName = useHost;
156 bool byHostName = false;
157
158 DynamicList<label> dynRanks;
159
160 Foam::string str(Foam::getEnv("FOAM_IORANKS"));
161
162 if (!str.empty())
163 {
164 if (str.contains('('))
165 {
166 // Looks like a list - tokenise it
167 ITstream is(str);
168 if (!is.empty())
169 {
170 is >> dynRanks;
171 }
172 }
173 else if (str == "host")
174 {
175 // Select by hostname
176 byHostName = true;
177 }
178 else
179 {
180 // Manual parse
181 dynRanks = splitStringToList<label>(str);
182 }
183 }
184
185 if (dynRanks.size())
186 {
187 if (!dynRanks.contains(0))
188 {
189 // Could also add silently
190 // dynRanks.push_back(0);
192 << "Rank 0 (master) should be in the IO ranks. Currently:" << nl
193 << " " << flatOutput(dynRanks) << nl
194 << exit(FatalError);
195 }
196
197 // Never trust user input.
198 // Sort and eliminate any duplicates
199
200 std::sort(dynRanks.begin(), dynRanks.end());
201
202 if (dynRanks.front() < 0)
203 {
205 << "Cannot have negative ranks! Currently:" << nl
206 << " " << flatOutput(dynRanks) << nl
207 << exit(FatalError);
208 }
209
210 labelList ranks;
211
212 auto last = std::unique(dynRanks.begin(), dynRanks.end());
213
214 if (last < dynRanks.end())
215 {
216 ranks = dynRanks.slice(0, (last - dynRanks.begin()));
217 }
218 else
219 {
220 ranks = dynRanks;
221 }
222
223 return ranks;
224 }
225 else if (byHostName)
226 {
228 }
229
230 return labelList();
231}
232
233
234bool Foam::fileOperation::isIOrank(const label proci) const
235{
236 return
237 (
239 ? UPstream::master(comm_)
240 : ioRanks_.empty()
241 ? (proci == 0) // No io-ranks, assume single communicator
242 : ioRanks_.contains(proci) // Found proci in IO rank
243 );
244}
245
246
248{
249 // Collect the names of the IO masters
251 if (UPstream::master(comm_))
252 {
254 }
256
257
258 DynamicList<label> offsetMaster;
259
260 // Calculate the offsets/counts
261
263 {
264 label nHostRanks = 0;
265 forAll(hosts, ranki)
266 {
267 if (!hosts[ranki].empty())
268 {
269 ++nHostRanks;
270 }
271 }
272 offsetMaster.reserve(nHostRanks+1);
273
274 forAll(hosts, ranki)
275 {
276 if (!hosts[ranki].empty())
277 {
278 offsetMaster.push_back(ranki);
279 }
280 }
281
282 // End of range is nProcs
283 offsetMaster.push_back(hosts.size());
284 }
285
286 if (offsetMaster.size() > 2)
287 {
289 << "I/O on :" << nl << '(' << nl;
290 for (label group = 1; group < offsetMaster.size(); ++group)
291 {
292 const label beg = offsetMaster[group-1];
293 const label end = offsetMaster[group];
294
296 << " (" << hosts[beg].c_str() << ' '
297 << (end-beg) << ')' << nl;
298 }
300 << ')' << nl;
301 }
302}
303
304
305// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects.
Definition DynamicList.H:68
void push_back(const T &val)
Copy append an element to the end of this list.
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
An input stream of tokens.
Definition ITstream.H:56
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition List.H:72
The SHA1 message digest.
Definition SHA1Digest.H:58
static constexpr unsigned size_bytes() noexcept
The number of bytes in digest (20).
Definition SHA1Digest.H:176
Functions to compute SHA1 message digest according to the NIST specification FIPS-180-1.
Definition SHA1.H:57
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition UListI.H:410
char * data_bytes() noexcept
Return pointer to the underlying array serving as data storage,.
Definition UListI.H:288
bool empty() const noexcept
True if List is empty (ie, size() is zero).
Definition UList.H:701
bool contains(const T &val) const
True if the value is contained in the list.
Definition UListI.H:302
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition UListI.H:454
SubList< T > slice(const label pos, label len=-1)
Return SubList slice (non-const access) - no range checking.
Definition SubList.H:258
T & front()
Access first element of the list, position [0].
Definition UListI.H:239
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
static int myProcNo(const label communicator=worldComm)
Rank of this process in the communicator (starting from masterNo()). Negative if the process is not a...
Definition UPstream.H:1706
static bool parRun(const bool on) noexcept
Set as parallel run on/off.
Definition UPstream.H:1669
static int & msgType() noexcept
Message tag of standard messages.
Definition UPstream.H:1926
static int numNodes() noexcept
The number of shared/host nodes in the (const) world communicator.
Definition UPstream.H:1754
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
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:1697
static label worldComm
Communicator for all ranks. May differ from commGlobal() if local worlds are in use.
Definition UPstream.H:1069
static void mpiAllGather(Type *allData, int count, const int communicator=UPstream::worldComm)
Gather/scatter identically-sized data.
@ gatherList
gatherList [manual algorithm]
Definition UPstream.H:194
static bool & parRun() noexcept
Test if this a parallel run.
Definition UPstream.H:1681
static labelRange subRanks(const labelUList &mainIOranks)
Get (contiguous) range/bounds of ranks addressed within the given main io-ranks.
const labelList ioRanks_
The list of IO ranks (global ranks).
bool isIOrank(const label proci) const
Is proci a master rank in the communicator (in parallel) or a master rank in the IO ranks (non-parall...
label comm_
Communicator to use.
static labelList getGlobalIORanks()
Get list of global IO ranks from FOAM_IORANKS env variable. If set, these correspond to the IO master...
void printRanks() const
Helper: output which ranks are IO.
static labelList getGlobalHostIORanks()
Get list of global IO master ranks based on the hostname. It is assumed that each host range is conti...
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
A class for handling character strings derived from std::string.
Definition string.H:76
bool contains(char c) const noexcept
True if string contains given character (cf. C++23).
Definition string.H:412
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
#define DetailInfo
Definition evalEntry.C:30
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))
const char * end
Definition SVGTools.H:223
constexpr const char *const group
Group name for atomic constants.
Foam::SubStrings splitAny(const std::string &str, const std::string &delim, std::string::size_type pos=0)
Split string into sub-strings using any characters in delimiter.
Namespace for OpenFOAM.
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition POSIX.C:341
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition int32.H:127
List< label > labelList
A List of labels.
Definition List.H:62
List< string > stringList
List of string.
Definition stringList.H:32
string hostName()
Return the system's host name, as per hostname(1).
Definition POSIX.C:373
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition FlatOutput.H:217
static List< PrimitiveType > splitStringToList(const std::string &str)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
UList< label > labelUList
A UList of labels.
Definition UList.H:75
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
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition stdFoam.H:315