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-2020 OpenCFD Ltd.
10-------------------------------------------------------------------------------
11License
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
27Description
28 Class for handling debugging switches.
29
30\*---------------------------------------------------------------------------*/
31
32#include "debug.H"
33#include "dictionary.H"
34#include "IFstream.H"
35#include "etcFiles.H"
36#include "Ostream.H"
37#include "demandDrivenData.H"
39#include "IOobject.H"
40#include "HashSet.H"
41#include "nullObject.H"
42
43// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44
45namespace Foam
46{
47namespace debug
48{
49
51//- Skip documentation : local scope only
52
53dictionary* controlDictPtr_(nullptr);
54dictionary* debugSwitchesPtr_(nullptr);
55dictionary* infoSwitchesPtr_(nullptr);
56dictionary* optimisationSwitchesPtr_(nullptr);
57
58// Debug switch read and write callback tables.
59simpleObjectRegistry* debugObjectsPtr_(nullptr);
60simpleObjectRegistry* infoObjectsPtr_(nullptr);
61simpleObjectRegistry* optimisationObjectsPtr_(nullptr);
62simpleObjectRegistry* dimensionSetObjectsPtr_(nullptr);
63simpleObjectRegistry* dimensionedConstantObjectsPtr_(nullptr);
64
65
66// To ensure controlDictPtr_ is deleted at the end of the run
67struct deleteControlDictPtr
68{
69 ~deleteControlDictPtr()
70 {
71 deleteDemandDrivenData(debugObjectsPtr_);
72 deleteDemandDrivenData(infoObjectsPtr_);
73 deleteDemandDrivenData(optimisationObjectsPtr_);
74 deleteDemandDrivenData(dimensionSetObjectsPtr_);
75 deleteDemandDrivenData(dimensionedConstantObjectsPtr_);
76
77 debugSwitchesPtr_ = nullptr;
78 infoSwitchesPtr_ = nullptr;
79 optimisationSwitchesPtr_ = nullptr;
80 deleteDemandDrivenData(controlDictPtr_);
81 }
82};
83
84deleteControlDictPtr deleteControlDictPtr_;
86
87
88} // End namespace debug
89} // End namespace Foam
90
91
92// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
93
94namespace Foam
95{
96
97// Like dictionary getOrAdd with LITERAL, but circumventing
98// writeOptionalEntries to avoid extremely noisy output
99template<class T>
100static inline T getOrAdd
101(
103 const char* name,
104 const T deflt
105)
106{
107 const entry* eptr = dict.findEntry(name, keyType::LITERAL);
108
109 if (eptr)
110 {
111 return eptr->get<T>();
112 }
113
114 dict.add(new primitiveEntry(name, deflt));
115 return deflt;
116}
117
118
119// Append object to a registry
120static inline void appendNamedEntry
121(
123 const char* name,
125)
126{
128 if (ptr)
129 {
130 ptr->append(obj);
131 }
132 else
133 {
135 }
136}
137
138} // End namespace Foam
139
140
141// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
142
144{
145 if (!controlDictPtr_)
146 {
147 string controlDictString(Foam::getEnv("FOAM_CONTROLDICT"));
148 if (!controlDictString.empty())
149 {
150 // Read from environment
151 IStringStream is(controlDictString);
152 controlDictPtr_ = new dictionary(is);
153 }
154 else
155 {
156 fileNameList controlDictFiles = findEtcFiles("controlDict", true);
157 controlDictPtr_ = new dictionary();
158 forAllReverse(controlDictFiles, i)
159 {
160 IFstream is(controlDictFiles[i]);
161
162 if (!is.good())
163 {
165 (
166 is,
167 "Cannot open controlDict"
168 );
169 }
170 controlDictPtr_->merge(dictionary(is));
171 }
172 }
173 }
174
175 return *controlDictPtr_;
176}
177
178
180(
181 const char* subDictName,
182 dictionary*& subDictPtr
183)
184{
185 if (!subDictPtr)
186 {
187 entry* eptr = controlDict().findEntry(subDictName, keyType::LITERAL);
188
189 if (!eptr || !eptr->isDict())
190 {
191 std::cerr
192 << "debug::switchSet(const char*, dictionary*&):\n"
193 << " Cannot find " << subDictName << " in dictionary "
194 << controlDict().name().c_str()
195 << std::endl << std::endl;
196
197 std::exit(1);
198 }
199
200 subDictPtr = &(eptr->dict());
201 }
202
203 return *subDictPtr;
204}
205
206
208{
209 return switchSet("DebugSwitches", debugSwitchesPtr_);
210}
211
212
214{
215 return switchSet("InfoSwitches", infoSwitchesPtr_);
216}
217
218
220{
221 return switchSet("OptimisationSwitches", optimisationSwitchesPtr_);
222}
223
224
225int Foam::debug::debugSwitch(const char* name, const int deflt)
226{
227 return getOrAdd(debugSwitches(), name, deflt);
228}
229
230
231int Foam::debug::infoSwitch(const char* name, const int deflt)
232{
233 return getOrAdd(infoSwitches(), name, deflt);
234}
235
236
237int Foam::debug::optimisationSwitch(const char* name, const int deflt)
238{
239 return getOrAdd(optimisationSwitches(), name, deflt);
240}
241
242
243float Foam::debug::floatOptimisationSwitch(const char* name, const float deflt)
244{
245 return getOrAdd(optimisationSwitches(), name, deflt);
246}
247
248
250{
252}
253
254
256{
258}
259
260
262(
263 const char* name,
265)
266{
268}
269
270
272(
273 const char* name,
275)
276{
278}
279
280
282(
283 const char* name,
285)
286{
288}
289
290
292{
293 if (!debugObjectsPtr_)
294 {
295 debugObjectsPtr_ = new simpleObjectRegistry(128);
296 }
297
298 return *debugObjectsPtr_;
299}
300
301
303{
304 if (!infoObjectsPtr_)
305 {
306 infoObjectsPtr_ = new simpleObjectRegistry(128);
307 }
308
309 return *infoObjectsPtr_;
310}
311
312
314{
315 if (!optimisationObjectsPtr_)
316 {
317 optimisationObjectsPtr_ = new simpleObjectRegistry(128);
318 }
319
320 return *optimisationObjectsPtr_;
321}
322
323
325{
326 if (!dimensionSetObjectsPtr_)
327 {
328 dimensionSetObjectsPtr_ = new simpleObjectRegistry(128);
329 }
330
331 return *dimensionSetObjectsPtr_;
332}
333
334
336{
337 if (!dimensionedConstantObjectsPtr_)
338 {
339 dimensionedConstantObjectsPtr_ = new simpleObjectRegistry(128);
340 }
341
342 return *dimensionedConstantObjectsPtr_;
343}
344
345
346// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
347
348namespace Foam
349{
350
351// Print the switch status
352static inline void printStatus
353(
354 const char * const message,
355 const wordList& list
356)
357{
358 // Use writeList with length = -1 to ensure we always have newlines,
359 // even for short lists
360
361 Info<< message << nl;
362 list.writeList(Info, -1) << nl;
363}
364
365
366// Write the switch names.
367//
368// Use writeList with -1 for the length to ensure we always have newlines,
369// even if the lists are short
370
371static void listSwitches
372(
373 const wordList& debugSwitches,
374 const wordList& infoSwitches,
375 const wordList& optSwitches,
376 const bool unset
377)
378{
380
381 if (unset)
382 {
383 fileNameList controlDictFiles = findEtcFiles("controlDict", true);
385 forAllReverse(controlDictFiles, i)
386 {
387 IFstream is(controlDictFiles[i]);
388
389 controlDict.merge(dictionary(is));
390 }
391
392 // HashSet to track switches that have not been set
393 wordHashSet hashed;
394
395 // DebugSwitches
396 if (notNull(debugSwitches))
397 {
398 hashed = debugSwitches;
399 hashed.unset(controlDict.subDict("DebugSwitches").toc());
400 printStatus("Unset DebugSwitches", hashed.sortedToc());
401 }
402
403 // InfoSwitches
404 if (notNull(infoSwitches))
405 {
406 hashed = infoSwitches;
407 hashed.unset(controlDict.subDict("InfoSwitches").toc());
408 printStatus("Unset InfoSwitches", hashed.sortedToc());
409 }
410
411 // OptimisationSwitches
412 if (notNull(optSwitches))
413 {
414 hashed = optSwitches;
415 hashed.unset(controlDict.subDict("OptimisationSwitches").toc());
416 printStatus("Unset OptimisationSwitches", hashed.sortedToc());
417 }
418 }
419 else
420 {
421 // DebugSwitches
422 if (notNull(debugSwitches))
423 {
424 printStatus("DebugSwitches", debugSwitches);
425 }
426
427 // InfoSwitches
428 if (notNull(infoSwitches))
429 {
430 printStatus("InfoSwitches", infoSwitches);
431 }
432
433 // OptimisationSwitches
434 if (notNull(optSwitches))
435 {
436 printStatus("OptimisationSwitches", optSwitches);
437 }
438 }
439}
440
441} // End namespace Foam
442
443
444// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
445
446void Foam::debug::listSwitches(const bool unset)
447{
449 (
450 debug::debugSwitches().sortedToc(),
451 debug::infoSwitches().sortedToc(),
452 debug::optimisationSwitches().sortedToc(),
453 unset
454 );
455}
456
457
458void Foam::debug::listDebugSwitches(const bool unset)
459{
461 (
462 debug::debugSwitches().sortedToc(),
465 unset
466 );
467}
468
469
470void Foam::debug::listInfoSwitches(const bool unset)
471{
473 (
475 debug::infoObjects().sortedToc(),
477 unset
478 );
479}
480
481
483{
485 (
488 debug::optimisationSwitches().sortedToc(),
489 unset
490 );
491}
492
493
495{
497 (
498 debug::debugObjects().sortedToc(),
499 debug::infoObjects().sortedToc(),
500 debug::optimisationObjects().sortedToc(),
501 unset
502 );
503}
504
505
507{
509 (
510 debug::debugObjects().sortedToc(),
513 unset
514 );
515}
516
517
519{
521 (
523 debug::infoObjects().sortedToc(),
525 unset
526 );
527}
528
529
531{
533 (
536 debug::optimisationObjects().sortedToc(),
537 unset
538 );
539}
540
541
542// ************************************************************************* //
T * find(const word &keyword)
Find and return an entry, nullptr on failure.
void append(const word &keyword, T *ptr)
Add to back of dictionary.
bool unset(const Key &key)
Unset the specified key - same as erase.
Definition: HashSet.H:204
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:137
Input from file stream, using an ISstream.
Definition: IFstream.H:57
static Ostream & writeDivider(Ostream &os)
Write the standard file section divider.
bool good() const noexcept
True if next operation might succeed.
Definition: IOstream.H:233
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:112
void append(const T &val)
Append an element at the end of the list.
Definition: ListI.H:175
Ostream & writeList(Ostream &os, const label shortLen=0) const
Write List, with line-breaks in ASCII when length exceeds shortLen.
Definition: UListIO.C:79
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find for an entry (non-const access) with the given keyword.
Definition: dictionaryI.H:97
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:233
virtual const dictionary & dict() const =0
Return dictionary, if entry is a dictionary.
T get() const
Definition: entry.H:269
@ LITERAL
String literal.
Definition: keyType.H:81
A keyword and a list of tokens comprise a primitiveEntry. A primitiveEntry can be read,...
Object registry for simpleRegIOobject. Maintains ordering.
Abstract base class for registered object with I/O. Used in debug symbol registration.
runTime controlDict().readEntry("adjustTimeStep"
const volScalarField & T
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:497
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:180
int infoSwitch(const char *name, const int deflt=0)
Lookup info switch or add default value.
Definition: debug.C:231
void listDebugSwitches(const bool unset=false)
List debug switches.
Definition: debug.C:458
int debugSwitch(const char *name, const int deflt=0)
Lookup debug switch or add default value.
Definition: debug.C:225
void addDebugObject(const char *name, simpleRegIOobject *obj)
Register debug switch read/write object.
Definition: debug.C:249
void listSwitches(const bool unset=false)
List debug/info/optimisation switches.
Definition: debug.C:446
void listRegisteredOptimisationSwitches(const bool unset=false)
List optimisation switches.
Definition: debug.C:530
simpleObjectRegistry & infoObjects()
Access to registered InfoSwitch objects.
Definition: debug.C:302
simpleObjectRegistry & dimensionSetObjects()
Access to registered DimensionSets objects.
Definition: debug.C:324
float floatOptimisationSwitch(const char *name, const float deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:243
void addDimensionedConstantObject(const char *name, simpleRegIOobject *)
Register DimensionedConstant read/write object.
Definition: debug.C:282
simpleObjectRegistry & dimensionedConstantObjects()
Access to registered DimensionedConstants objects.
Definition: debug.C:335
dictionary & optimisationSwitches()
The OptimisationSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:219
void listRegisteredSwitches(const bool unset=false)
List registered debug/info/optimisation switches.
Definition: debug.C:494
void listRegisteredDebugSwitches(const bool unset=false)
List debug switches.
Definition: debug.C:506
void addOptimisationObject(const char *name, simpleRegIOobject *obj)
Register optimisation switch read/write object.
Definition: debug.C:262
void listOptimisationSwitches(const bool unset=false)
List optimisation switches.
Definition: debug.C:482
void addInfoObject(const char *name, simpleRegIOobject *obj)
Register info switch read/write object.
Definition: debug.C:255
dictionary & controlDict()
Definition: debug.C:143
void listRegisteredInfoSwitches(const bool unset=false)
List info switches.
Definition: debug.C:518
simpleObjectRegistry & optimisationObjects()
Access to registered OptimisationSwitch objects.
Definition: debug.C:313
dictionary & infoSwitches()
The InfoSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:213
void listInfoSwitches(const bool unset=false)
List info switches.
Definition: debug.C:470
simpleObjectRegistry & debugObjects()
Access to registered DebugSwitch objects.
Definition: debug.C:291
int optimisationSwitch(const char *name, const int deflt=0)
Lookup optimisation switch or add default value.
Definition: debug.C:237
void addDimensionSetObject(const char *name, simpleRegIOobject *obj)
Register DimensionSets read/write object.
Definition: debug.C:272
dictionary & debugSwitches()
The DebugSwitches sub-dictionary in the central controlDict(s).
Definition: debug.C:207
Namespace for OpenFOAM.
string getEnv(const std::string &envName)
Get environment value for given envName.
Definition: MSwindows.C:371
static void appendNamedEntry(simpleObjectRegistry &obr, const char *name, simpleRegIOobject *obj)
Definition: debug.C:121
messageStream Info
Information stream (stdout output on master, null elsewhere)
static void listSwitches(const wordList &debugSwitches, const wordList &infoSwitches, const wordList &optSwitches, const bool unset)
Definition: debug.C:372
static void printStatus(const char *const message, const wordList &list)
Definition: debug.C:353
bool notNull(const T *ptr)
True if ptr is not a pointer (of type T) to the nullObject.
Definition: nullObject.H:207
static T getOrAdd(dictionary &dict, const char *name, const T deflt)
Definition: debug.C:101
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
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:392
void deleteDemandDrivenData(DataPtr &dataPtr)
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict
#define forAllReverse(list, i)
Reverse loop across all elements in list.
Definition: stdFoam.H:346