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-2025 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 
50 
54 
56 {
58  {
60  }
61 
63 }
64 
66 {
68  {
70  }
71 
73 }
74 
76 {
78  {
80  }
81 
83 }
84 
85 
86 // To ensure configDictPtr_ is deleted at the end of the run
88 {
89 public:
90 
92  {}
93 
95  {
99 
100  debugSwitchesPtr_ = nullptr;
101  infoSwitchesPtr_ = nullptr;
102  optimisationSwitchesPtr_ = nullptr;
103 
105  }
106 };
107 
110 
111 
112 } // End namespace debug
113 } // End namespace Foam
114 
115 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
116 
118 {
119  if (!configDictPtr_)
120  {
121  string configDictString(getEnv("FOAM_CONFIGDICT"));
122  if (!configDictString.empty())
123  {
124  // Read from environment
125  IStringStream is(configDictString);
126  configDictPtr_ = new dictionary(is);
127  }
128  else
129  {
130  fileNameList configDictFiles = findEtcFiles("configDict", true);
131  configDictPtr_ = new dictionary();
132  forAllReverse(configDictFiles, cdfi)
133  {
134  IFstream ifs(configDictFiles[cdfi]);
135 
136  if (!ifs.good())
137  {
139  (
140  ifs,
141  "Cannot open configDict"
142  );
143  }
145  }
146 
147  // Check for legacy etc controlDict files
148  // for backwards compatibility
149  fileNameList controlDictFiles = findEtcFiles("controlDict", false);
150 
151  if (controlDictFiles.size())
152  {
153  cout<< "--> FOAM Warning: legacy controlDict"
154  " configuration files found:" << std::endl;
155 
156  forAll(controlDictFiles, i)
157  {
158  cout<< " " << controlDictFiles[i] << std::endl;
159  }
160 
161  cout<< " Please rename these files controlDict -> configDict"
162  << std::endl;
163  }
164 
165  forAllReverse(controlDictFiles, cdfi)
166  {
167  IFstream ifs(controlDictFiles[cdfi]);
168 
169  if (!ifs.good())
170  {
172  (
173  ifs,
174  "Cannot open controlDict"
175  );
176  }
178  }
179 
180 
181  }
182 
183  IFstream ifs("system/configDict");
184  if (ifs.good())
185  {
186  entry::disableFunctionEntries = true;
188  }
189  }
190 
191  return *configDictPtr_;
192 }
193 
194 
196 (
197  const char* subDictName,
198  dictionary*& subDictPtr
199 )
200 {
201  if (!subDictPtr)
202  {
204  (
205  subDictName, false, false
206  );
207 
208  if (!ePtr || !ePtr->isDict())
209  {
210  cerr<< "debug::switchSet(const char*, dictionary*&):\n"
211  << " Cannot find " << subDictName << " in dictionary "
212  << configDict().name().c_str()
213  << std::endl << std::endl;
214 
215  ::exit(1);
216  }
217 
218  subDictPtr = &ePtr->dict();
219  }
220 
221  return *subDictPtr;
222 }
223 
224 
226 {
227  return switchSet("DebugSwitches", debugSwitchesPtr_);
228 }
229 
230 
232 {
233  return switchSet("InfoSwitches", infoSwitchesPtr_);
234 }
235 
236 
238 {
239  return switchSet("OptimisationSwitches", optimisationSwitchesPtr_);
240 }
241 
242 
243 int Foam::debug::debugSwitch(const char* name, const int defaultValue)
244 {
245  if
246  (
248  && debugDefaultSwitches().lookup<int>(name) != defaultValue
249  )
250  {
252  << "Multiple defaults set for debug switch " << name
253  << exit(FatalError);
254  }
255 
256  debugDefaultSwitches().set(name, defaultValue);
257 
258  return debugSwitches().lookupOrAddDefault(name, defaultValue);
259 }
260 
261 
262 int Foam::debug::infoSwitch(const char* name, const int defaultValue)
263 {
264  if
265  (
267  && infoDefaultSwitches().lookup<int>(name) != defaultValue
268  )
269  {
271  << "Multiple defaults set for info switch " << name
272  << exit(FatalError);
273  }
274 
275  infoDefaultSwitches().set(name, defaultValue);
276 
277  return infoSwitches().lookupOrAddDefault(name, defaultValue);
278 }
279 
280 
281 int Foam::debug::optimisationSwitch(const char* name, const int defaultValue)
282 {
283  if
284  (
286  && optimisationDefaultSwitches().lookup<int>(name) != defaultValue
287  )
288  {
290  << "Multiple defaults set for optimisation switch " << name
291  << exit(FatalError);
292  }
293 
294  optimisationDefaultSwitches().set(name, defaultValue);
295 
296  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
297 }
298 
299 
301 (
302  const char* name,
303  const float defaultValue
304 )
305 {
306  if
307  (
309  && optimisationDefaultSwitches().lookup<float>(name) != defaultValue
310  )
311  {
313  << exit(FatalError);
314  }
315 
316  optimisationDefaultSwitches().set(name, defaultValue);
317 
318  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
319 }
320 
321 
323 (
324  const char* name,
325  const word& defaultValue
326 )
327 {
328  if
329  (
331  && optimisationDefaultSwitches().lookup<word>(name) != defaultValue
332  )
333  {
335  << exit(FatalError);
336  }
337 
338  optimisationDefaultSwitches().set(name, defaultValue);
339 
340  return optimisationSwitches().lookupOrAddDefault(name, defaultValue);
341 }
342 
343 
344 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
345 
346 namespace Foam
347 {
348 
350 (
351  const wordList& debugSwitches,
352  const wordList& infoSwitches,
353  const wordList& optSwitches,
354  const bool unset
355 )
356 {
357  if (unset)
358  {
359  fileNameList configDictFiles = findEtcFiles("configDict", true);
361  forAllReverse(configDictFiles, cdfi)
362  {
363  configDict.merge(dictionary(IFstream(configDictFiles[cdfi])()));
364  }
365 
366  wordHashSet configDictDebug
367  (
368  configDict.subDict("DebugSwitches").sortedToc()
369  );
370 
371  wordHashSet configDictInfo
372  (
373  configDict.subDict("InfoSwitches").sortedToc()
374  );
375 
376  wordHashSet configDictOpt
377  (
378  configDict.subDict("OptimisationSwitches").sortedToc()
379  );
380 
381 
383 
384  wordHashSet hashset;
385  hashset = debugSwitches;
386  hashset -= configDictDebug;
387  Info<< "Unset DebugSwitches" << hashset.sortedToc() << endl;
388 
389  hashset = infoSwitches;
390  hashset -= configDictInfo;
391  Info<< "Unset InfoSwitches" << hashset.sortedToc() << endl;
392 
393  hashset = optSwitches;
394  hashset -= configDictOpt;
395  Info<< "Unset OptimisationSwitches" << hashset.sortedToc() << endl;
396  }
397  else
398  {
400  Info<< "DebugSwitches" << debugSwitches << endl;
401  Info<< "InfoSwitches" << infoSwitches << endl;
402  Info<< "OptimisationSwitches" << optSwitches << endl;
403  }
404 }
405 
406 
408 (
409  const word& name,
410  const dictionary& switches,
411  const dictionary& defaultSwitches
412 )
413 {
414  wordHashSet defaultSet;
415  wordHashSet nonDefaultSet;
416  wordHashSet noDefaultSet;
417 
418  forAllConstIter(dictionary, switches, iter)
419  {
420  const word& name = iter().keyword();
421 
422  const bool hasDefault = defaultSwitches.found(name);
423 
424  const bool isDefault =
425  hasDefault
426  && defaultSwitches.lookupEntry(name, false, false) == iter();
427 
428  if (hasDefault)
429  {
430  if (isDefault)
431  {
432  defaultSet.insert(name);
433  }
434  else
435  {
436  nonDefaultSet.insert(name);
437  }
438  }
439  else
440  {
441  noDefaultSet.insert(name);
442  }
443  }
444 
445  auto print = [&](const char* heading, const wordList& names)
446  {
447  Info<< indent << "// " << heading << endl;
448 
449  forAll(names, i)
450  {
451  Info<< switches.lookupEntry(names[i], false, false);
452  }
453  };
454 
455  Info<< name << endl
457 
458  print
459  (
460  "Switches with default values",
461  defaultSet.sortedToc()
462  );
463  Info<< nl;
464  print
465  (
466  "Switches with non-default values",
467  nonDefaultSet.sortedToc()
468  );
469  Info<< nl;
470  print
471  (
472  "Switches without defaults",
473  noDefaultSet.sortedToc()
474  );
475 
477 }
478 
479 } // End namespace Foam
480 
481 
482 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
483 
485 {
487  (
488  "DebugSwitches",
491  );
492  Info<< endl;
493 
495  (
496  "InfoSwitches",
499  );
500  Info<< endl;
501 
503  (
504  "OptimisationSwitches",
507  );
508 }
509 
510 
511 // ************************************************************************* //
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:449
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:461
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:492
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
Input from memory buffer stream.
Definition: IStringStream.H:52
bool good() const
Return true if next operation might succeed.
Definition: Istream.H:101
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
const fileName & name() const
Return the dictionary name.
Definition: dictionary.H:111
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
const entry * lookupEntryPtr(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream pointer if present.
Definition: dictionary.C:507
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:626
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:778
wordList sortedToc() const
Return the sorted table of contents.
Definition: dictionary.C:995
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:468
bool merge(const dictionary &)
Merge entries from the given dictionary.
Definition: dictionary.C:1313
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:114
@ END_BLOCK
Definition: token.H:115
A class for handling words, derived from string.
Definition: word.H:63
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 configDict.
Definition: debug.C:196
float floatOptimisationSwitch(const char *name, const float defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:301
dictionary * infoDefaultSwitchesPtr_(nullptr)
dictionary & configDict()
The central control dictionary.
Definition: debug.C:117
dictionary * optimisationSwitchesPtr_(nullptr)
dictionary * debugSwitchesPtr_(nullptr)
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central configDict.
Definition: debug.C:237
dictionary * configDictPtr_(nullptr)
int debugSwitch(const char *name, const int defaultValue=0)
Lookup debug switch or add default value.
Definition: debug.C:243
dictionary * optimisationDefaultSwitchesPtr_(nullptr)
int infoSwitch(const char *name, const int defaultValue=0)
Lookup info switch or add default value.
Definition: debug.C:262
int optimisationSwitch(const char *name, const int defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:281
void listSwitches()
List debug switches.
Definition: debug.C:484
dictionary * debugDefaultSwitchesPtr_(nullptr)
dictionary & infoDefaultSwitches()
Definition: debug.C:65
deleteControlDictPtr deleteControlDictPtr_
Definition: debug.C:108
dictionary & infoSwitches()
The InfoSwitches sub-dictionary in the central configDict.
Definition: debug.C:231
const word wordOptimisationSwitch(const char *name, const word &defaultValue)
Lookup optimisation switch or add default value.
Definition: debug.C:323
dictionary * infoSwitchesPtr_(nullptr)
dictionary & debugSwitches()
The DebugSwitches sub-dictionary in the central configDict.
Definition: debug.C:225
dictionary & optimisationDefaultSwitches()
Definition: debug.C:75
dictionary & debugDefaultSwitches()
Definition: debug.C:55
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:272
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:288
void deleteDemandDrivenData(DataType *&dataPtr)
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:265
void listSwitches(const wordList &debugSwitches, const wordList &infoSwitches, const wordList &optSwitches, const bool unset)
Definition: debug.C:350
void listSwitches(const word &name, const dictionary &switches, const dictionary &defaultSwitches)
Definition: debug.C:408
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:243
static const char nl
Definition: Ostream.H:297