debug.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration | Website: https://openfoam.org
5  \\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
11  OpenFOAM is free software: you can redistribute it and/or modify it
12  under the terms of the GNU General Public License as published by
13  the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
19  for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
23 
24 Description
25  Class for handling debugging switches.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "debug.H"
30 #include "dictionary.H"
31 #include "IFstream.H"
32 #include "etcFiles.H"
33 #include "Ostream.H"
34 #include "demandDrivenData.H"
35 #include "IOobject.H"
36 #include "HashSet.H"
37 
38 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42 namespace debug
43 {
44 
46 //- Skip documentation : local scope only
47 
48 dictionary* controlDictPtr_(nullptr);
49 
50 dictionary* debugSwitchesPtr_(nullptr);
51 dictionary* infoSwitchesPtr_(nullptr);
52 dictionary* optimisationSwitchesPtr_(nullptr);
53 
54 dictionary* debugDefaultSwitchesPtr_(nullptr);
55 dictionary* infoDefaultSwitchesPtr_(nullptr);
56 dictionary* optimisationDefaultSwitchesPtr_(nullptr);
57 
58 dictionary& debugDefaultSwitches()
59 {
60  if (!debugDefaultSwitchesPtr_)
61  {
62  debugDefaultSwitchesPtr_ = new dictionary();
63  }
64 
65  return *debugDefaultSwitchesPtr_;
66 }
67 
68 dictionary& infoDefaultSwitches()
69 {
70  if (!infoDefaultSwitchesPtr_)
71  {
72  infoDefaultSwitchesPtr_ = new dictionary();
73  }
74 
75  return *infoDefaultSwitchesPtr_;
76 }
77 
78 dictionary& optimisationDefaultSwitches()
79 {
80  if (!optimisationDefaultSwitchesPtr_)
81  {
82  optimisationDefaultSwitchesPtr_ = new dictionary();
83  }
84 
85  return *optimisationDefaultSwitchesPtr_;
86 }
87 
88 
89 // To ensure controlDictPtr_ is deleted at the end of the run
90 class deleteControlDictPtr
91 {
92 public:
93 
94  deleteControlDictPtr()
95  {}
96 
97  ~deleteControlDictPtr()
98  {
99  deleteDemandDrivenData(debugDefaultSwitchesPtr_);
100  deleteDemandDrivenData(infoDefaultSwitchesPtr_);
101  deleteDemandDrivenData(optimisationDefaultSwitchesPtr_);
102 
103  debugSwitchesPtr_ = nullptr;
104  infoSwitchesPtr_ = nullptr;
105  optimisationSwitchesPtr_ = nullptr;
106 
107  deleteDemandDrivenData(controlDictPtr_);
108  }
109 };
110 
111 deleteControlDictPtr deleteControlDictPtr_;
113 
114 
115 } // End namespace debug
116 } // End namespace Foam
117 
118 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
119 
121 {
122  if (!controlDictPtr_)
123  {
124  string controlDictString(getEnv("FOAM_CONTROLDICT"));
125  if (!controlDictString.empty())
126  {
127  // Read from environment
128  IStringStream is(controlDictString);
129  controlDictPtr_ = new dictionary(is);
130  }
131  else
132  {
133  fileNameList controlDictFiles = findEtcFiles("controlDict", true);
134  controlDictPtr_ = new dictionary();
135  forAllReverse(controlDictFiles, cdfi)
136  {
137  IFstream ifs(controlDictFiles[cdfi]);
138 
139  if (!ifs.good())
140  {
142  (
143  ifs,
144  "Cannot open controlDict"
145  );
146  }
147  controlDictPtr_->merge(dictionary(ifs));
148  }
149  }
150 
151  IFstream ifs("system/controlDict");
152  if (ifs.good())
153  {
154  entry::disableFunctionEntries = true;
155  controlDictPtr_->merge(dictionary(ifs));
156  }
157  }
158 
159  return *controlDictPtr_;
160 }
161 
162 
164 (
165  const char* subDictName,
166  dictionary*& subDictPtr
167 )
168 {
169  if (!subDictPtr)
170  {
171  entry* ePtr = controlDict().lookupEntryPtr
172  (
173  subDictName, false, false
174  );
175 
176  if (!ePtr || !ePtr->isDict())
177  {
178  cerr<< "debug::switchSet(const char*, dictionary*&):\n"
179  << " Cannot find " << subDictName << " in dictionary "
180  << controlDict().name().c_str()
181  << std::endl << std::endl;
182 
183  ::exit(1);
184  }
185 
186  subDictPtr = &ePtr->dict();
187  }
188 
189  return *subDictPtr;
190 }
191 
192 
194 {
195  return switchSet("DebugSwitches", debugSwitchesPtr_);
196 }
197 
198 
200 {
201  return switchSet("InfoSwitches", infoSwitchesPtr_);
202 }
203 
204 
206 {
207  return switchSet("OptimisationSwitches", optimisationSwitchesPtr_);
208 }
209 
210 
211 int Foam::debug::debugSwitch(const char* name, const int defaultValue)
212 {
213  if
214  (
215  debugDefaultSwitches().found(name)
216  && debugDefaultSwitches().lookup<int>(name) != defaultValue
217  )
218  {
220  << "Multiple defaults set for debug switch " << name
221  << exit(FatalError);
222  }
223 
224  debugDefaultSwitches().set(name, defaultValue);
225 
226  return debugSwitches().lookupOrAddDefault(name, defaultValue);
227 }
228 
229 
230 int Foam::debug::infoSwitch(const char* name, const int defaultValue)
231 {
232  if
233  (
234  infoDefaultSwitches().found(name)
235  && infoDefaultSwitches().lookup<int>(name) != defaultValue
236  )
237  {
239  << "Multiple defaults set for info switch " << name
240  << exit(FatalError);
241  }
242 
243  infoDefaultSwitches().set(name, defaultValue);
244 
245  return infoSwitches().lookupOrAddDefault(name, defaultValue);
246 }
247 
248 
249 int Foam::debug::optimisationSwitch(const char* name, const int defaultValue)
250 {
251  if
252  (
253  optimisationDefaultSwitches().found(name)
254  && optimisationDefaultSwitches().lookup<int>(name) != defaultValue
255  )
256  {
258  << "Multiple defaults set for optimisation switch " << name
259  << exit(FatalError);
260  }
261 
262  optimisationDefaultSwitches().set(name, defaultValue);
263 
264  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
265 }
266 
267 
269 (
270  const char* name,
271  const float defaultValue
272 )
273 {
274  if
275  (
276  optimisationDefaultSwitches().found(name)
277  && optimisationDefaultSwitches().lookup<float>(name) != defaultValue
278  )
279  {
281  << exit(FatalError);
282  }
283 
284  optimisationDefaultSwitches().set(name, defaultValue);
285 
286  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
287 }
288 
289 
291 (
292  const char* name,
293  const word& defaultValue
294 )
295 {
296  if
297  (
298  optimisationDefaultSwitches().found(name)
299  && optimisationDefaultSwitches().lookup<word>(name) != defaultValue
300  )
301  {
303  << exit(FatalError);
304  }
305 
306  optimisationDefaultSwitches().set(name, defaultValue);
307 
308  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
309 }
310 
311 
312 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
313 
314 namespace Foam
315 {
316 
318 (
319  const wordList& debugSwitches,
320  const wordList& infoSwitches,
321  const wordList& optSwitches,
322  const bool unset
323 )
324 {
325  if (unset)
326  {
327  fileNameList controlDictFiles = findEtcFiles("controlDict", true);
329  forAllReverse(controlDictFiles, cdfi)
330  {
331  controlDict.merge(dictionary(IFstream(controlDictFiles[cdfi])()));
332  }
333 
334  wordHashSet controlDictDebug
335  (
336  controlDict.subDict("DebugSwitches").sortedToc()
337  );
338 
339  wordHashSet controlDictInfo
340  (
341  controlDict.subDict("InfoSwitches").sortedToc()
342  );
343 
344  wordHashSet controlDictOpt
345  (
346  controlDict.subDict("OptimisationSwitches").sortedToc()
347  );
348 
349 
351 
352  wordHashSet hashset;
353  hashset = debugSwitches;
354  hashset -= controlDictDebug;
355  Info<< "Unset DebugSwitches" << hashset.sortedToc() << endl;
356 
357  hashset = infoSwitches;
358  hashset -= controlDictInfo;
359  Info<< "Unset InfoSwitches" << hashset.sortedToc() << endl;
360 
361  hashset = optSwitches;
362  hashset -= controlDictOpt;
363  Info<< "Unset OptimisationSwitches" << hashset.sortedToc() << endl;
364  }
365  else
366  {
368  Info<< "DebugSwitches" << debugSwitches << endl;
369  Info<< "InfoSwitches" << infoSwitches << endl;
370  Info<< "OptimisationSwitches" << optSwitches << endl;
371  }
372 }
373 
374 
376 (
377  const word& name,
378  const dictionary& switches,
379  const dictionary& defaultSwitches
380 )
381 {
382  wordHashSet defaultSet;
383  wordHashSet nonDefaultSet;
384  wordHashSet noDefaultSet;
385 
386  forAllConstIter(dictionary, switches, iter)
387  {
388  const word& name = iter().keyword();
389 
390  const bool hasDefault = defaultSwitches.found(name);
391 
392  const bool isDefault =
393  hasDefault
394  && defaultSwitches.lookupEntry(name, false, false) == iter();
395 
396  if (hasDefault)
397  {
398  if (isDefault)
399  {
400  defaultSet.insert(name);
401  }
402  else
403  {
404  nonDefaultSet.insert(name);
405  }
406  }
407  else
408  {
409  noDefaultSet.insert(name);
410  }
411  }
412 
413  auto print = [&](const char* heading, const wordList& names)
414  {
415  Info<< indent << "// " << heading << endl;
416 
417  forAll(names, i)
418  {
419  Info<< switches.lookupEntry(names[i], false, false);
420  }
421  };
422 
423  Info<< name << endl
425 
426  print
427  (
428  "Switches with default values",
429  defaultSet.sortedToc()
430  );
431  Info<< nl;
432  print
433  (
434  "Switches with non-default values",
435  nonDefaultSet.sortedToc()
436  );
437  Info<< nl;
438  print
439  (
440  "Switches without defaults",
441  noDefaultSet.sortedToc()
442  );
443 
445 }
446 
447 } // End namespace Foam
448 
449 
450 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
451 
453 {
455  (
456  "DebugSwitches",
458  debug::debugDefaultSwitches()
459  );
460  Info<< endl;
461 
463  (
464  "InfoSwitches",
466  debug::infoDefaultSwitches()
467  );
468  Info<< endl;
469 
471  (
472  "OptimisationSwitches",
474  debug::optimisationDefaultSwitches()
475  );
476 }
477 
478 
479 // ************************************************************************* //
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:445
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
A HashTable with keys but without contents.
Definition: HashSet.H:62
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:109
List< Key > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:242
Input from file stream.
Definition: IFstream.H:85
static Stream & writeDivider(Stream &os)
Write the standard file section divider.
Definition: IOobjectI.H:93
bool good() const
Return true if next operation might succeed.
Definition: IOstream.H:333
Input from memory buffer stream.
Definition: IStringStream.H:52
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
T lookupOrAddDefault(const word &, const T &)
Find and return a T, if not found return the given.
const entry & lookupEntry(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream if present otherwise error.
Definition: dictionary.C:697
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:539
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:68
virtual bool isDict() const
Return true if this entry is a dictionary.
Definition: entry.H:178
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
@ BEGIN_BLOCK
Definition: token.H:113
@ END_BLOCK
Definition: token.H:114
A class for handling words, derived from string.
Definition: word.H:62
Template functions to aid in the implementation of demand driven data.
#define SafeFatalIOErrorInFunction(ios, msg)
Report an error message using Foam::FatalIOError.
Definition: error.H:361
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
Functions to search 'etc' directories for configuration files etc.
dictionary & switchSet(const char *subDictName, dictionary *&subDictPtr)
Internal function to lookup a sub-dictionary from controlDict.
Definition: debug.C:164
float floatOptimisationSwitch(const char *name, const float defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:269
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict.
Definition: debug.C:205
int debugSwitch(const char *name, const int defaultValue=0)
Lookup debug switch or add default value.
Definition: debug.C:211
int infoSwitch(const char *name, const int defaultValue=0)
Lookup info switch or add default value.
Definition: debug.C:230
int optimisationSwitch(const char *name, const int defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:249
dictionary & controlDict()
The central control dictionary.
Definition: debug.C:120
void listSwitches()
List debug switches.
Definition: debug.C:452
dictionary & infoSwitches()
The InfoSwitches sub-dictionary in the central controlDict.
Definition: debug.C:199
const word wordOptimisationSwitch(const char *name, const word &defaultValue)
Lookup optimisation switch or add default value.
Definition: debug.C:291
dictionary & debugSwitches()
The DebugSwitches sub-dictionary in the central controlDict.
Definition: debug.C:193
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Ostream & decrIndent(Ostream &os)
Decrement the indent level.
Definition: Ostream.H:242
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
void deleteDemandDrivenData(DataType *&dataPtr)
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:235
void listSwitches(const wordList &debugSwitches, const wordList &infoSwitches, const wordList &optSwitches, const bool unset)
Definition: debug.C:318
void listSwitches(const word &name, const dictionary &switches, const dictionary &defaultSwitches)
Definition: debug.C:376
string getEnv(const word &)
Return environment variable of given name.
Definition: POSIX.C:97
fileNameList findEtcFiles(const fileName &, bool mandatory=false, bool findFirst=false)
Search for files from user/group/shipped directories.
Definition: etcFiles.C:119
word name(const LagrangianState state)
Return a string representation of a Lagrangian state enumeration.
error FatalError
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:228
static const char nl
Definition: Ostream.H:267
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep