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-2020 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 
227  (
228  name, defaultValue, false, false
229  );
230 }
231 
232 
233 int Foam::debug::infoSwitch(const char* name, const int defaultValue)
234 {
235  if
236  (
237  infoDefaultSwitches().found(name)
238  && infoDefaultSwitches().lookup<int>(name) != defaultValue
239  )
240  {
242  << "Multiple defaults set for info switch " << name
243  << exit(FatalError);
244  }
245 
246  infoDefaultSwitches().set(name, defaultValue);
247 
249  (
250  name, defaultValue, false, false
251  );
252 }
253 
254 
255 int Foam::debug::optimisationSwitch(const char* name, const int defaultValue)
256 {
257  if
258  (
259  optimisationDefaultSwitches().found(name)
260  && optimisationDefaultSwitches().lookup<int>(name) != defaultValue
261  )
262  {
264  << "Multiple defaults set for optimisation switch " << name
265  << exit(FatalError);
266  }
267 
268  optimisationDefaultSwitches().set(name, defaultValue);
269 
271  (
272  name, defaultValue, false, false
273  );
274 }
275 
276 
278 (
279  const char* name,
280  const float defaultValue
281 )
282 {
283  if
284  (
285  optimisationDefaultSwitches().found(name)
286  && optimisationDefaultSwitches().lookup<float>(name) != defaultValue
287  )
288  {
290  << exit(FatalError);
291  }
292 
293  optimisationDefaultSwitches().set(name, defaultValue);
294 
296  (
297  name, defaultValue, false, false
298  );
299 }
300 
301 
303 (
304  const char* name,
305  const word& defaultValue
306 )
307 {
308  if
309  (
310  optimisationDefaultSwitches().found(name)
311  && optimisationDefaultSwitches().lookup<word>(name) != defaultValue
312  )
313  {
315  << exit(FatalError);
316  }
317 
318  optimisationDefaultSwitches().set(name, defaultValue);
319 
321  (
322  name, defaultValue, false, false
323  );
324 }
325 
326 
327 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
328 
329 namespace Foam
330 {
331 
333 (
334  const wordList& debugSwitches,
335  const wordList& infoSwitches,
336  const wordList& optSwitches,
337  const bool unset
338 )
339 {
340  if (unset)
341  {
342  fileNameList controlDictFiles = findEtcFiles("controlDict", true);
344  forAllReverse(controlDictFiles, cdfi)
345  {
346  controlDict.merge(dictionary(IFstream(controlDictFiles[cdfi])()));
347  }
348 
349  wordHashSet controlDictDebug
350  (
351  controlDict.subDict("DebugSwitches").sortedToc()
352  );
353 
354  wordHashSet controlDictInfo
355  (
356  controlDict.subDict("InfoSwitches").sortedToc()
357  );
358 
359  wordHashSet controlDictOpt
360  (
361  controlDict.subDict("OptimisationSwitches").sortedToc()
362  );
363 
364 
366 
367  wordHashSet hashset;
368  hashset = debugSwitches;
369  hashset -= controlDictDebug;
370  Info<< "Unset DebugSwitches" << hashset.sortedToc() << endl;
371 
372  hashset = infoSwitches;
373  hashset -= controlDictInfo;
374  Info<< "Unset InfoSwitches" << hashset.sortedToc() << endl;
375 
376  hashset = optSwitches;
377  hashset -= controlDictOpt;
378  Info<< "Unset OptimisationSwitches" << hashset.sortedToc() << endl;
379  }
380  else
381  {
383  Info<< "DebugSwitches" << debugSwitches << endl;
384  Info<< "InfoSwitches" << infoSwitches << endl;
385  Info<< "OptimisationSwitches" << optSwitches << endl;
386  }
387 }
388 
389 
391 (
392  const word& name,
393  const dictionary& switches,
394  const dictionary& defaultSwitches
395 )
396 {
397  wordHashSet defaultSet;
398  wordHashSet nonDefaultSet;
399  wordHashSet noDefaultSet;
400 
401  forAllConstIter(dictionary, switches, iter)
402  {
403  const word& name = iter().keyword();
404 
405  const bool hasDefault = defaultSwitches.found(name);
406 
407  const bool isDefault =
408  hasDefault
409  && defaultSwitches.lookupEntry(name, false, false) == iter();
410 
411  if (hasDefault)
412  {
413  if (isDefault)
414  {
415  defaultSet.insert(name);
416  }
417  else
418  {
419  nonDefaultSet.insert(name);
420  }
421  }
422  else
423  {
424  noDefaultSet.insert(name);
425  }
426  }
427 
428  auto print = [&](const char* heading, const wordList& names)
429  {
430  Info<< indent << "// " << heading << endl;
431 
432  forAll(names, i)
433  {
434  Info<< switches.lookupEntry(names[i], false, false);
435  }
436  };
437 
438  Info<< name << endl
440 
441  print
442  (
443  "Switches with default values",
444  defaultSet.sortedToc()
445  );
446  Info<< nl;
447  print
448  (
449  "Switches with non-default values",
450  nonDefaultSet.sortedToc()
451  );
452  Info<< nl;
453  print
454  (
455  "Switches without defaults",
456  noDefaultSet.sortedToc()
457  );
458 
460 }
461 
462 } // End namespace Foam
463 
464 
465 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
466 
468 {
470  (
471  "DebugSwitches",
473  debug::debugDefaultSwitches()
474  );
475  Info<< endl;
476 
478  (
479  "InfoSwitches",
481  debug::infoDefaultSwitches()
482  );
483  Info<< endl;
484 
486  (
487  "OptimisationSwitches",
489  debug::optimisationDefaultSwitches()
490  );
491 }
492 
493 
494 // ************************************************************************* //
bool found
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:434
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: UList.H:446
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:477
A HashTable with keys but without contents.
Definition: HashSet.H:62
bool insert(const Key &key)
Insert a new entry.
Definition: HashSet.H:111
List< Key > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:217
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:330
Input from memory buffer stream.
Definition: IStringStream.H:52
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:160
const entry & lookupEntry(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream if present otherwise error.
Definition: dictionary.C:817
T lookupOrAddDefault(const word &, const T &, bool recursive=false, bool patternMatch=true)
Find and return a T, if not found return the given.
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:659
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:156
virtual const dictionary & dict() const =0
Return dictionary if this entry is a dictionary.
@ BEGIN_BLOCK
Definition: token.H:110
@ END_BLOCK
Definition: token.H:111
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:333
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:306
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:278
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:233
int optimisationSwitch(const char *name, const int defaultValue=0)
Lookup optimisation switch or add default value.
Definition: debug.C:255
dictionary & controlDict()
The central control dictionary.
Definition: debug.C:120
void listSwitches()
List debug switches.
Definition: debug.C:467
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:303
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:235
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
messageStream Info
Ostream & incrIndent(Ostream &os)
Increment the indent level.
Definition: Ostream.H:228
void listSwitches(const wordList &debugSwitches, const wordList &infoSwitches, const wordList &optSwitches, const bool unset)
Definition: debug.C:333
void listSwitches(const word &name, const dictionary &switches, const dictionary &defaultSwitches)
Definition: debug.C:391
void deleteDemandDrivenData(DataPtr &dataPtr)
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
error FatalError
word name(const complex &)
Return a string representation of a complex.
Definition: complex.C:47
Ostream & indent(Ostream &os)
Indent stream.
Definition: Ostream.H:221
static const char nl
Definition: Ostream.H:260
runTime controlDict().lookup("adjustTimeStep") >> adjustTimeStep