debug.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) 2011-2018 OpenFOAM Foundation
9  Copyright (C) 2019-2022 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 Description
28  Class for handling debugging switches.
29 
30 Note
31  Included by global/globals.C
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #include "debug.H"
36 #include "dictionary.H"
37 #include "IFstream.H"
38 #include "etcFiles.H"
39 #include "Ostream.H"
40 #include "demandDrivenData.H"
41 #include "simpleObjectRegistry.H"
42 #include "IOobject.H"
43 #include "HashSet.H"
44 #include "nullObject.H"
45 
46 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
47 
48 namespace Foam
49 {
50 namespace debug
51 {
52 
54 //- Skip documentation : local scope only
55 
56 dictionary* controlDictPtr_(nullptr);
57 dictionary* debugSwitchesPtr_(nullptr);
58 dictionary* infoSwitchesPtr_(nullptr);
59 dictionary* optimisationSwitchesPtr_(nullptr);
60 
61 // Debug switch read and write callback tables.
62 simpleObjectRegistry* debugObjectsPtr_(nullptr);
63 simpleObjectRegistry* infoObjectsPtr_(nullptr);
64 simpleObjectRegistry* optimisationObjectsPtr_(nullptr);
65 simpleObjectRegistry* dimensionSetObjectsPtr_(nullptr);
66 simpleObjectRegistry* dimensionedConstantObjectsPtr_(nullptr);
67 
68 
69 // To ensure controlDictPtr_ is deleted at the end of the run
70 struct deleteControlDictPtr
71 {
72  ~deleteControlDictPtr()
73  {
74  deleteDemandDrivenData(debugObjectsPtr_);
75  deleteDemandDrivenData(infoObjectsPtr_);
76  deleteDemandDrivenData(optimisationObjectsPtr_);
77  deleteDemandDrivenData(dimensionSetObjectsPtr_);
78  deleteDemandDrivenData(dimensionedConstantObjectsPtr_);
79 
80  debugSwitchesPtr_ = nullptr;
81  infoSwitchesPtr_ = nullptr;
82  optimisationSwitchesPtr_ = nullptr;
83  deleteDemandDrivenData(controlDictPtr_);
84  }
85 };
86 
87 deleteControlDictPtr deleteControlDictPtr_;
89 
90 
91 } // End namespace debug
92 } // End namespace Foam
93 
94 
95 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
96 
97 namespace Foam
98 {
99 
100 // Like dictionary getOrAdd with LITERAL, but circumventing
101 // writeOptionalEntries to avoid extremely noisy output
102 template<class T>
103 static inline T getOrAdd
104 (
105  dictionary& dict,
106  const char* name,
107  const T deflt
108 )
109 {
110  const entry* eptr = dict.findEntry(name, keyType::LITERAL);
111 
112  if (eptr)
113  {
114  return eptr->get<T>();
115  }
116 
117  dict.add(new primitiveEntry(name, deflt));
118  return deflt;
119 }
121 
122 // Append object to a registry
123 static inline void appendNamedEntry
124 (
126  const char* name,
127  simpleRegIOobject* obj
128 )
129 {
130  simpleObjectRegistryEntry* ptr = obr.find(name);
131  if (ptr)
132  {
133  ptr->append(obj);
134  }
135  else
136  {
137  obr.append(name, new simpleObjectRegistryEntry(obj));
138  }
139 }
140 
141 } // End namespace Foam
143 
144 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
145 
147 {
148  if (!controlDictPtr_)
149  {
150  string controlDictString(Foam::getEnv("FOAM_CONTROLDICT"));
151  if (!controlDictString.empty())
152  {
153  // Read from environment
154  IStringStream is(controlDictString);
155  controlDictPtr_ = new dictionary(is);
156  }
157  else
158  {
159  fileNameList controlDictFiles = findEtcFiles("controlDict", true);
160  controlDictPtr_ = new dictionary();
161  forAllReverse(controlDictFiles, i)
162  {
163  IFstream is(controlDictFiles[i]);
164 
165  if (!is.good())
166  {
168  (
169  is,
170  "Cannot open controlDict"
171  );
172  }
173  controlDictPtr_->merge(dictionary(is));
174  }
175  }
176  }
177 
178  return *controlDictPtr_;
179 }
180 
181 
183 (
184  const char* subDictName,
185  dictionary*& subDictPtr
186 )
187 {
188  if (!subDictPtr)
189  {
190  subDictPtr = controlDict().findDict(subDictName, keyType::LITERAL);
191 
192  if (!subDictPtr)
193  {
194  std::cerr
195  << "debug::switchSet(const char*, dictionary*&):\n"
196  << " Cannot find " << subDictName << " in dictionary "
197  << controlDict().name().c_str()
198  << std::endl << std::endl;
199 
200  std::exit(1);
201  }
202  }
203 
204  return *subDictPtr;
205 }
206 
207 
209 {
210  return switchSet("DebugSwitches", debugSwitchesPtr_);
211 }
212 
213 
215 {
216  return switchSet("InfoSwitches", infoSwitchesPtr_);
217 }
218 
219 
221 {
222  return switchSet("OptimisationSwitches", optimisationSwitchesPtr_);
223 }
224 
225 
226 int Foam::debug::debugSwitch(const char* name, const int deflt)
227 {
228  return getOrAdd(debugSwitches(), name, deflt);
229 }
230 
231 
232 int Foam::debug::infoSwitch(const char* name, const int deflt)
233 {
234  return getOrAdd(infoSwitches(), name, deflt);
235 }
236 
237 
238 int Foam::debug::optimisationSwitch(const char* name, const int deflt)
239 {
240  return getOrAdd(optimisationSwitches(), name, deflt);
241 }
242 
243 
244 float Foam::debug::floatOptimisationSwitch(const char* name, const float deflt)
245 {
246  return getOrAdd(optimisationSwitches(), name, deflt);
247 }
248 
249 
250 void Foam::debug::addDebugObject(const char* name, simpleRegIOobject* obj)
251 {
253 }
254 
255 
256 void Foam::debug::addInfoObject(const char* name, simpleRegIOobject* obj)
257 {
259 }
260 
261 
263 (
264  const char* name,
265  simpleRegIOobject* obj
266 )
267 {
269 }
270 
271 
273 (
274  const char* name,
275  simpleRegIOobject* obj
276 )
277 {
279 }
280 
281 
283 (
284  const char* name,
285  simpleRegIOobject* obj
286 )
287 {
289 }
290 
291 
293 {
294  if (!debugObjectsPtr_)
295  {
296  debugObjectsPtr_ = new simpleObjectRegistry(128);
297  }
298 
299  return *debugObjectsPtr_;
300 }
301 
302 
304 {
305  if (!infoObjectsPtr_)
306  {
307  infoObjectsPtr_ = new simpleObjectRegistry(128);
308  }
309 
310  return *infoObjectsPtr_;
311 }
312 
313 
315 {
316  if (!optimisationObjectsPtr_)
317  {
318  optimisationObjectsPtr_ = new simpleObjectRegistry(128);
319  }
320 
321  return *optimisationObjectsPtr_;
322 }
323 
324 
326 {
327  if (!dimensionSetObjectsPtr_)
328  {
329  dimensionSetObjectsPtr_ = new simpleObjectRegistry(128);
330  }
331 
332  return *dimensionSetObjectsPtr_;
333 }
334 
335 
337 {
338  if (!dimensionedConstantObjectsPtr_)
339  {
340  dimensionedConstantObjectsPtr_ = new simpleObjectRegistry(128);
341  }
342 
343  return *dimensionedConstantObjectsPtr_;
344 }
345 
346 
347 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
348 
349 namespace Foam
350 {
351 
352 // Print the switch status
353 static inline void printStatus
354 (
355  const char * const message,
356  const wordList& list
357 )
358 {
359  // Use writeList with length = -1 to ensure we always have newlines,
360  // even for short lists
361 
362  Info<< message << nl;
363  list.writeList(Info, -1) << nl;
364 }
365 
366 
367 // Write the switch names.
368 //
369 // Use writeList with -1 for the length to ensure we always have newlines,
370 // even if the lists are short
371 
372 static void listSwitches
373 (
374  const wordList& debugSwitches,
375  const wordList& infoSwitches,
376  const wordList& optSwitches,
377  const bool unset
378 )
379 {
381 
382  if (unset)
383  {
384  fileNameList controlDictFiles = findEtcFiles("controlDict", true);
386  forAllReverse(controlDictFiles, i)
387  {
388  IFstream is(controlDictFiles[i]);
389 
390  controlDict.merge(dictionary(is));
391  }
392 
393  // HashSet to track switches that have not been set
394  wordHashSet hashed;
395 
396  // DebugSwitches
397  if (notNull(debugSwitches))
398  {
399  hashed = debugSwitches;
400  hashed.unset(controlDict.subDict("DebugSwitches").toc());
401  printStatus("Unset DebugSwitches", hashed.sortedToc());
402  }
403 
404  // InfoSwitches
405  if (notNull(infoSwitches))
406  {
407  hashed = infoSwitches;
408  hashed.unset(controlDict.subDict("InfoSwitches").toc());
409  printStatus("Unset InfoSwitches", hashed.sortedToc());
410  }
411 
412  // OptimisationSwitches
413  if (notNull(optSwitches))
414  {
415  hashed = optSwitches;
416  hashed.unset(controlDict.subDict("OptimisationSwitches").toc());
417  printStatus("Unset OptimisationSwitches", hashed.sortedToc());
418  }
419  }
420  else
421  {
422  // DebugSwitches
423  if (notNull(debugSwitches))
424  {
425  printStatus("DebugSwitches", debugSwitches);
426  }
427 
428  // InfoSwitches
429  if (notNull(infoSwitches))
430  {
431  printStatus("InfoSwitches", infoSwitches);
432  }
433 
434  // OptimisationSwitches
435  if (notNull(optSwitches))
436  {
437  printStatus("OptimisationSwitches", optSwitches);
438  }
439  }
440 }
441 
442 } // End namespace Foam
444 
445 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
446 
447 void Foam::debug::listSwitches(const bool unset)
448 {
450  (
454  unset
455  );
456 }
457 
458 
459 void Foam::debug::listDebugSwitches(const bool unset)
460 {
462  (
464  wordList::null(),
465  wordList::null(),
466  unset
467  );
468 }
469 
470 
471 void Foam::debug::listInfoSwitches(const bool unset)
472 {
474  (
475  wordList::null(),
477  wordList::null(),
478  unset
479  );
480 }
481 
482 
484 {
486  (
487  wordList::null(),
488  wordList::null(),
490  unset
491  );
492 }
493 
494 
496 {
498  (
502  unset
503  );
504 }
505 
506 
508 {
510  (
512  wordList::null(),
513  wordList::null(),
514  unset
515  );
516 }
517 
518 
520 {
522  (
523  wordList::null(),
525  wordList::null(),
526  unset
527  );
528 }
529 
530 
532 {
534  (
535  wordList::null(),
536  wordList::null(),
538  unset
539  );
540 }
541 
542 
543 // ************************************************************************* //
Abstract base class for registered object with I/O. Used in debug symbol registration.
void listRegisteredInfoSwitches(const bool unset=false)
List info switches.
Definition: debug.C:515
dictionary dict
void listRegisteredOptimisationSwitches(const bool unset=false)
List optimisation switches.
Definition: debug.C:527
void addInfoObject(const char *name, simpleRegIOobject *obj)
Register info switch read/write object.
Definition: debug.C:252
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
dictionary & switchSet(const char *subDictName, dictionary *&subDictPtr)
Internal function to lookup a sub-dictionary from controlDict.
Definition: debug.C:179
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
void append(const T &val)
Append an element at the end of the list.
Definition: List.H:517
static void printStatus(const char *const message, const wordList &list)
Definition: debug.C:350
fileNameList findEtcFiles(const fileName &name, const bool mandatory=false, unsigned short location=0777, const bool findFirst=false)
Search for files from user/group/other etc locations.
Definition: etcFiles.C:385
static void listSwitches(const wordList &debugSwitches, const wordList &infoSwitches, const wordList &optSwitches, const bool unset)
Definition: debug.C:369
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
int debugSwitch(const char *name, const int deflt=0)
Lookup debug switch or add default value.
Definition: debug.C:222
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static Ostream & writeDivider(Ostream &os)
Write the standard file section divider.
void append(const word &k, T *ptr)
Add to back of dictionary.
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:625
simpleObjectRegistry & debugObjects()
Access to registered DebugSwitch objects.
Definition: debug.C:288
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: POSIX.C:339
void listDebugSwitches(const bool unset=false)
List debug switches.
Definition: debug.C:455
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:228
simpleObjectRegistry & optimisationObjects()
Access to registered OptimisationSwitch objects.
Definition: debug.C:310
void unset(List< bool > &bools, const labelUList &locations)
Unset the listed locations (assign &#39;false&#39;).
Definition: BitOps.C:99
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read...
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: UListIO.C:76
void addDimensionedConstantObject(const char *name, simpleRegIOobject *)
Register DimensionedConstant read/write object.
Definition: debug.C:279
static void appendNamedEntry(simpleObjectRegistry &obr, const char *name, simpleRegIOobject *obj)
Definition: debug.C:120
bool unset(const Key &key)
Unset the specified key - same as erase.
Definition: HashSet.H:250
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
Functions to search &#39;etc&#39; directories for configuration files etc.
dictionary & infoSwitches()
The InfoSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:210
void listInfoSwitches(const bool unset=false)
List info switches.
Definition: debug.C:467
T get() const
Get a T from the stream, FatalIOError if the number of tokens is incorrect.
Definition: entry.H:338
String literal.
Definition: keyType.H:82
runTime controlDict().readEntry("adjustTimeStep"
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:234
int debug
Static debugging option.
void listOptimisationSwitches(const bool unset=false)
List optimisation switches.
Definition: debug.C:479
simpleObjectRegistry & infoObjects()
Access to registered InfoSwitch objects.
Definition: debug.C:299
Input from file stream, using an ISstream.
Definition: IFstream.H:49
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
simpleObjectRegistry & dimensionSetObjects()
Access to registered DimensionSets objects.
Definition: debug.C:321
void listSwitches(const bool unset=false)
List debug/info/optimisation switches.
Definition: debug.C:443
Template functions to aid in the implementation of demand driven data.
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:240
Object registry for simpleRegIOobject. Maintains ordering.
simpleObjectRegistry & dimensionedConstantObjects()
Access to registered DimensionedConstants objects.
Definition: debug.C:332
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:139
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:84
T * find(const word &keyword)
Find and return an entry, nullptr on failure.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
messageStream Info
Information stream (stdout output on master, null elsewhere)
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:216
static T getOrAdd(dictionary &dict, const char *name, const T deflt)
Definition: debug.C:100
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:437
void addDimensionSetObject(const char *name, simpleRegIOobject *obj)
Register DimensionSets read/write object.
Definition: debug.C:269
void addOptimisationObject(const char *name, simpleRegIOobject *obj)
Register optimisation switch read/write object.
Definition: debug.C:259
dictionary & debugSwitches()
The DebugSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:204
void addDebugObject(const char *name, simpleRegIOobject *obj)
Register debug switch read/write object.
Definition: debug.C:246
List< fileName > fileNameList
List of fileName.
Definition: fileNameList.H:32
void listRegisteredSwitches(const bool unset=false)
List registered debug/info/optimisation switches.
Definition: debug.C:491
dictionary & controlDict()
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
void deleteDemandDrivenData(DataPtr &dataPtr)
void listRegisteredDebugSwitches(const bool unset=false)
List debug switches.
Definition: debug.C:503
bool notNull(const T *ptr)
True if ptr is not a pointer (of type T) to the nullObject.
Definition: nullObject.H:246
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
#define SafeFatalIOErrorInFunction(ios, msg)
Report an error message using Foam::FatalIOError.
Definition: error.H:660