Loading...
Searching...
No Matches
externalFileCoupler.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) 2015-2022 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 "externalFileCoupler.H"
29#include "Pstream.H"
30#include "PstreamReduceOps.H"
31#include "OSspecific.H"
32#include "Switch.H"
33#include <fstream>
34
35// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
36
37namespace Foam
38{
40}
41
43
44
45// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
46
47namespace Foam
48{
49
50// Read file contents and return a stop control as follows:
51// - contains "done" (should actually be status=done, but we are generous) :
52// The master (OpenFOAM) has signalled that it is done. Report as <endTime>
53//
54// - action=writeNow, action=nextWrite action=noWriteNow :
55// The slave has signalled that it is done and wants the master to exit with
56// the specified type of action. Report as corresponding <action>.
57//
58// Anything else (empty file, no action=, etc) is reported as <unknown>.
59//
60static enum Time::stopAtControls getStopAction(const std::string& filename)
61{
62 // Slurp entire input file (must exist) as a single string
63 string fileContent;
64
65 std::ifstream is(filename);
66 std::getline(is, fileContent, '\0');
67
68 if (fileContent.contains("done"))
69 {
71 }
72
73 const auto equals = fileContent.find('=');
74
75 if (equals != std::string::npos)
76 {
77 const word actionName(word::validate(fileContent.substr(equals+1)));
78
79 return
81 (
82 actionName,
84 );
85 }
86
89
90} // End namespace Foam
91
92
93// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
94
96:
97 runState_(NONE),
98 commsDir_("<case>/comms"),
99 statusDone_("done"),
100 waitInterval_(1u),
101 timeOut_(100u),
102 slaveFirst_(false),
103 log(false)
104{
105 commsDir_.expand();
106 commsDir_.clean(); // Remove unneeded ".."
107}
108
109
111:
112 runState_(NONE),
113 commsDir_(commsDir),
114 statusDone_("done"),
115 waitInterval_(1u),
116 timeOut_(100u),
117 slaveFirst_(false),
118 log(false)
119{
120 commsDir_.expand();
121 commsDir_.clean(); // Remove unneeded ".."
122
124 {
125 mkDir(commsDir_);
126 }
127}
128
129
131:
132 externalFileCoupler()
133{
134 readDict(dict);
135
136 if (Pstream::master())
137 {
138 mkDir(commsDir_);
139 }
140}
141
142
143// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
144
147 shutdown();
148}
149
150
151// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
152
154{
155 // Normally cannot change directory or initialization
156 // if things have already been initialized
157 if (!initialized())
158 {
159 dict.readEntry("commsDir", commsDir_);
160 commsDir_.expand();
161 commsDir_.clean(); // Remove unneeded ".."
162 statusDone_ = dict.getOrDefault<word>("statusDone", "done");
163 slaveFirst_ = dict.getOrDefault("initByExternal", false);
164
165 Info<< type() << ": initialize" << nl
166 << " directory: " << commsDir_ << nl
167 << " slave-first: " << Switch(slaveFirst_) << endl;
168 }
169
170 waitInterval_ = dict.getOrDefault("waitInterval", 1u);
171 if (!waitInterval_)
172 {
173 // Enforce non-zero sleep
174 waitInterval_ = 1u;
175 }
176
177 timeOut_ = dict.getOrDefault("timeOut", 100*waitInterval_);
178
179 log = dict.getOrDefault("log", false);
180
181 return true;
182}
183
184
186Foam::externalFileCoupler::useMaster(const bool wait) const
187{
188 const bool wasInit = initialized();
189 runState_ = MASTER;
190
191 if (Pstream::master())
192 {
193 if (!wasInit)
194 {
195 // First time
196 mkDir(commsDir_);
197 }
198
199 const fileName lck(lockFile());
200
201 // Create lock file - only if it doesn't already exist
202 if (!Foam::isFile(lck))
203 {
204 Log << type()
205 << ": creating lock file with status=openfoam" << endl;
206
207 std::ofstream os(lck);
208 os << "status=openfoam\n";
209 }
210 }
211
212 if (wait)
213 {
214 return waitForMaster();
216
218}
219
220
222Foam::externalFileCoupler::useSlave(const bool wait) const
223{
224 const bool wasInit = initialized();
225 runState_ = SLAVE;
226
227 if (Pstream::master())
228 {
229 if (!wasInit)
230 {
231 // First time
232 mkDir(commsDir_);
233 }
234
235 Log << type() << ": removing lock file" << endl;
236
237 Foam::rm(lockFile());
238 }
239
240 if (wait)
241 {
242 return waitForSlave();
244
246}
247
248
251{
252 if (!initialized())
253 {
254 useMaster(); // was not initialized
255 }
256
258
259 if (Pstream::master())
260 {
261 const fileName lck(lockFile());
262
263 double prevTime = 0;
264 double modTime = 0;
265
266 // Wait until file disappears (modTime == 0)
267 // But also check for status=done content in the file
268 while ((modTime = highResLastModified(lck)) > 0)
269 {
270 if (prevTime < modTime)
271 {
272 prevTime = modTime;
273
275 {
276 // Found 'done' - slave should not wait for master
278 break;
279 }
280 }
281 sleep(waitInterval_);
282 }
283 }
284
285 // Send to sub-ranks. Also acts as an MPI barrier
286 int intAction(action);
288
289 return Time::stopAtControls(intAction);
290}
291
292
295{
296 if (!initialized())
297 {
298 useSlave(); // was not initialized
299 }
300
302
303 if (Pstream::master())
304 {
305 const fileName lck(lockFile());
306 unsigned totalTime = 0;
307
308 Log << type() << ": waiting for lock file to appear " << lck << endl;
309
310 while (!Foam::isFile(lck))
311 {
312 sleep(waitInterval_);
313
314 if (timeOut_ && (totalTime += waitInterval_) > timeOut_)
315 {
317 << "Wait time exceeded timeout of " << timeOut_
318 << " s" << abort(FatalError);
319 }
320
321 Log << type() << ": wait time = " << totalTime << endl;
322 }
323
324 action = getStopAction(lck);
325
326 Log << type() << ": found lock file " << lck << endl;
327 }
328
329 // Send to sub-ranks. Also acts as an MPI barrier
330 int intAction(action);
331 Pstream::broadcast(intAction);
332
333 return Time::stopAtControls(intAction);
335
336
339
340
343
344
347
348
351
352
355
356
358{}
359
360
362{
363 if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_))
364 {
365 Log << type() << ": lock file status=" << statusDone_ << endl;
366
367 std::ofstream os(lockFile());
368 os << "status=" << statusDone_ << nl;
369 }
370
371 runState_ = DONE; // Avoid re-triggering in destructor
372}
373
374
375// ************************************************************************* //
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
#define Log
Definition PDRblock.C:28
Inter-processor communication reduction functions.
A simple wrapper around bool so that it can be read as a word: true/false, on/off,...
Definition Switch.H:81
static const Enum< stopAtControls > stopAtControlNames
Names for stopAtControls.
Definition Time.H:113
stopAtControls
Stop-run control options, which are primarily used when altering the stopAt condition.
Definition Time.H:97
@ saUnknown
Dummy no-op. Do not change current value.
Definition Time.H:102
@ saEndTime
Stop when Time reaches prescribed endTime.
Definition Time.H:98
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Definition UPstream.H:1714
@ broadcast
broadcast [MPI]
Definition UPstream.H:189
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
Encapsulates the logic for coordinating between OpenFOAM and an external application.
enum Time::stopAtControls useSlave(const bool wait=false) const
Remove lock file to indicate that the external program is in charge.
@ SLAVE
The slave (external program) is in charge.
@ MASTER
The master (OpenFOAM) is in charge.
virtual void writeDataMaster() const
Write data files from master (OpenFOAM).
virtual void removeDataSlave() const
Remove data files written by slave (external program).
enum Time::stopAtControls useMaster(const bool wait=false) const
Create lock file to indicate that OpenFOAM is in charge.
virtual ~externalFileCoupler()
Destructor.
fileName lockFile() const
Return the file path to the lock file.
bool readDict(const dictionary &dict)
Read communication settings from dictionary.
static word lockName
Name of the lock file.
virtual void readDataSlave()
Read data files on slave (external program).
enum Time::stopAtControls waitForMaster() const
Wait for master to complete.
virtual void writeDataSlave() const
Write data files from slave (external program).
virtual void readDataMaster()
Read data files on master (OpenFOAM).
virtual void removeDataMaster() const
Remove data files written by master (OpenFOAM).
enum Time::stopAtControls waitForSlave() const
Wait for slave to complete.
void shutdown() const
Generate status=done in lock (only when run-state = master).
externalFileCoupler()
Construct using standard defaults.
bool initialized() const
True if state has been initialized.
A class for handling file names.
Definition fileName.H:75
static bool clean(std::string &str)
Cleanup filename string, possibly applies other transformations such as changing the path separator e...
Definition fileName.C:192
bool contains(char c) const noexcept
True if string contains given character (cf. C++23).
Definition string.H:412
string & expand(const bool allowEmpty=false)
Inplace expand initial tags, tildes, and all occurrences of environment variables as per stringOps::e...
Definition string.C:166
A class for handling words, derived from Foam::string.
Definition word.H:66
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
OBJstream os(runTime.globalPath()/outputName)
Namespace for OpenFOAM.
bool rm(const fileName &file)
Remove a file (or its gz equivalent), returning true if successful.
Definition POSIX.C:1406
static enum Time::stopAtControls getStopAction(const std::string &filename)
Definition abort.C:61
bool mkDir(const fileName &pathName, mode_t mode=0777)
Make a directory and return an error if it could not be created.
Definition POSIX.C:616
messageStream Info
Information stream (stdout output on master, null elsewhere).
unsigned int sleep(const unsigned int sec)
Sleep for the specified number of seconds.
Definition POSIX.C:1549
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition POSIX.C:801
dimensionedScalar log(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
errorManip< error > abort(error &err)
Definition errorManip.H:139
double highResLastModified(const fileName &, const bool followLink=true)
Return time of last file modification.
Definition POSIX.C:948
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition POSIX.C:879
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
bool isDir(const fileName &name, const bool followLink=true)
Does the name exist as a DIRECTORY in the file system?
Definition POSIX.C:862
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
dictionary dict