foamDictionary.C 13 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2016 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM is free software: you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.

    You should have received a copy of the GNU General Public License
    along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Application
    foamDictionary

Description
    Interrogates and manipulates dictionaries.

Usage
31
    \b foamDictionary [OPTION] dictionary
32

33
34
      - \par -entry \<name\>
        Selects an entry
35

36
37
38
      - \par -keywords \<name\>
        Prints the keywords (of the selected entry or of the top level if
        no entry was selected
39

40
41
      - \par -add \<value\>
        Adds the entry (should not exist yet)
42

43
44
      - \par -set \<value\>
        Adds or replaces the entry
45

46
47
48
      - \par -remove
        Remove the selected entry

49
50
51
52
      - \par -diff \<dictionary\>
        Write differences with respect to the specified dictionary
        (or sub entry if -entry specified)

53
54
55
      - \par -expand
        Read the specified dictionary file, expand the macros etc. and write
        the resulting dictionary to standard output.
56

57
      - \par -includes
58
        List the \c #include and \c #includeIfPresent files to standard output
59

60
    Example usage:
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
      - Change simulation to run for one timestep only:
        \verbatim
          foamDictionary system/controlDict -entry stopAt -set writeNow
        \endverbatim

      - Change solver:
        \verbatim
           foamDictionary system/fvSolution -entry solvers.p.solver -set PCG
        \endverbatim

      - Print bc type:
        \verbatim
           foamDictionary 0/U -entry boundaryField.movingWall.type
        \endverbatim

      - Change bc parameter:
        \verbatim
           foamDictionary 0/U -entry boundaryField.movingWall.value \
             -set "uniform (2 0 0)"
        \endverbatim

      - Change whole bc type:
        \verbatim
          foamDictionary 0/U -entry boundaryField.movingWall \
            -set "{type uniformFixedValue; uniformValue (2 0 0);}"
        \endverbatim
87

88
89
90
91
92
93
94
95
96
97
98
99
      - Write the differences with respect to a template dictionary:
        \verbatim
          foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U
        \endverbatim

      - Write the differences in boundaryField with respect to a
        template dictionary:
        \verbatim
          foamDictionary 0/U -diff $FOAM_ETC/templates/closedVolume/0/U \
            -entry boundaryField
        \endverbatim

100
101
102
103
104
105
\*---------------------------------------------------------------------------*/

#include "argList.H"
#include "Time.H"
#include "IFstream.H"
#include "OFstream.H"
106
#include "includeEntry.H"
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

using namespace Foam;

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

//- Converts old scope syntax to new syntax
word scope(const fileName& entryName)
{
    if (entryName.find(':') != string::npos)
    {
        wordList entryNames(entryName.components(':'));

        word entry(entryNames[0]);
        for (label i = 1; i < entryNames.size(); i++)
        {
            entry += word('.') + entryNames[i];
        }
        return entry;
    }
    else
    {
        return entryName;
    }
}


133
134
//- Extracts dict name and keyword
Pair<word> dictAndKeyword(const word& scopedName)
135
136
137
138
{
    string::size_type i = scopedName.find_last_of(".");
    if (i != string::npos)
    {
139
140
141
142
143
144
145
146
147
        return Pair<word>
        (
            scopedName.substr(0, i),
            scopedName.substr(i+1, string::npos)
        );
    }
    else
    {
        return Pair<word>("", scopedName);
148
149
150
151
    }
}


152
153
154
155
156
const dictionary& lookupScopedDict
(
    const dictionary& dict,
    const word& subDictName
)
157
{
158
    if (subDictName == "")
159
    {
160
        return dict;
161
162
163
    }
    else
    {
164
165
166
167
168
169
170
        const entry* entPtr = dict.lookupScopedEntryPtr
        (
            subDictName,
            false,
            false
        );
        if (!entPtr || !entPtr->isDict())
171
        {
172
173
174
175
176
177
178
            FatalIOErrorInFunction(dict)
                << "keyword " << subDictName
                << " is undefined in dictionary "
                << dict.name() << " or is not a dictionary"
                << endl
                << "Valid keywords are " << dict.keys()
                << exit(FatalIOError);
179
        }
180
        return entPtr->dict();
181
182
183
184
    }
}


185
void remove(dictionary& dict, const dictionary& removeDict)
186
{
187
    forAllConstIter(dictionary, removeDict, iter)
188
    {
189
        const entry* entPtr = dict.lookupEntryPtr
190
        (
191
192
193
            iter().keyword(),
            false,
            false
194
195
        );

196
        if (entPtr)
197
        {
198
            if (entPtr->isDict())
199
            {
200
                if (iter().isDict())
201
                {
202
203
204
205
206
207
208
209
                    remove
                    (
                        const_cast<dictionary&>(entPtr->dict()),
                        iter().dict()
                    );

                    // Check if dictionary is empty
                    if (!entPtr->dict().size())
210
                    {
211
                        dict.remove(iter().keyword());
212
213
214
                    }
                }
            }
215
            else if (!iter().isDict())
216
            {
217
                if (*entPtr == iter())
218
                {
219
                    dict.remove(iter().keyword());
220
221
222
223
224
225
226
227
228
229
230
231
232
                }
            }
        }
    }
}


int main(int argc, char *argv[])
{
    argList::addNote("manipulates dictionaries");

    argList::noBanner();
    argList::validArgs.append("dictionary");
233
    argList::addBoolOption("keywords", "list keywords");
234
    argList::addOption("entry", "name", "report/select the named entry");
235
236
237
    argList::addBoolOption
    (
        "value",
238
        "Print entry value"
239
    );
240
241
242
243
    argList::addOption
    (
        "set",
        "value",
244
        "Set entry value or add new entry"
245
246
247
248
249
    );
    argList::addOption
    (
        "add",
        "value",
250
        "Add a new entry"
251
    );
252
    argList::addBoolOption
253
254
    (
        "remove",
255
256
257
258
259
260
261
        "Remove the entry."
    );
    argList::addOption
    (
        "diff",
        "dict",
        "Write differences with respect to the specified dictionary"
262
263
    );
    argList::addBoolOption
264
265
    (
        "includes",
266
        "List the #include/#includeIfPresent files to standard output"
267
268
269
270
271
    );
    argList::addBoolOption
    (
        "expand",
        "Read the specified dictionary file, expand the macros etc. and write "
272
        "the resulting dictionary to standard output"
273
274
275
276
277
    );

    argList args(argc, argv);

    const bool listIncludes = args.optionFound("includes");
278

279
280
281
282
    if (listIncludes)
    {
        Foam::functionEntries::includeEntry::log = true;
    }
283

284
    fileName dictFileName(args[1]);
285
286

    autoPtr<IFstream> dictFile(new IFstream(dictFileName));
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
    if (!dictFile().good())
    {
        FatalErrorInFunction
            << "Cannot open file " << dictFileName
            << exit(FatalError, 1);
    }


    bool changed = false;

    // Read but preserve headers
    dictionary dict;
    dict.read(dictFile(), true);

    if (listIncludes)
    {
        return 0;
    }
    else if (args.optionFound("expand"))
    {
        IOobject::writeBanner(Info)
            <<"//\n// " << dictFileName << "\n//\n";
        dict.write(Info, false);
        IOobject::writeDivider(Info);

        return 0;
    }

315

316
317
318
319
    // Second dictionary for -diff
    dictionary diffDict;
    fileName diffFileName;
    if (args.optionReadIfPresent("diff", diffFileName))
320
    {
321
322
323
324
325
326
327
        autoPtr<IFstream> diffFile(new IFstream(diffFileName));
        if (!diffFile().good())
        {
            FatalErrorInFunction
                << "Cannot open file " << diffFileName
                << exit(FatalError, 1);
        }
328
329

        // Read but preserve headers
330
331
        diffDict.read(diffFile(), true);
    }
332

333
334
335
336
337
338
339
340
341
342
343
344

    word entryName;
    if (args.optionReadIfPresent("entry", entryName))
    {
        word scopedName(scope(entryName));

        string newValue;
        if
        (
            args.optionReadIfPresent("set", newValue)
         || args.optionReadIfPresent("add", newValue)
        )
345
        {
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
            bool overwrite = args.optionFound("set");

            Pair<word> dAk(dictAndKeyword(scopedName));

            IStringStream str(string(dAk.second()) + ' ' + newValue + ';');
            entry* ePtr(entry::New(str).ptr());
            const dictionary& d(lookupScopedDict(dict, dAk.first()));

            if (overwrite)
            {
                const_cast<dictionary&>(d).set(ePtr);
            }
            else
            {
                const_cast<dictionary&>(d).add(ePtr, false);
            }
            changed = true;

            // Print the changed entry
            const entry* entPtr = dict.lookupScopedEntryPtr
            (
                scopedName,
                false,
                true            // Support wildcards
            );
            if (entPtr)
            {
                Info<< *entPtr << endl;
            }
375
        }
376
        else if (args.optionFound("remove"))
377
        {
378
379
            // Extract dictionary name and keyword
            Pair<word> dAk(dictAndKeyword(scopedName));
380

381
382
383
            const dictionary& d(lookupScopedDict(dict, dAk.first()));
            const_cast<dictionary&>(d).remove(dAk.second());
            changed = true;
384
        }
385
        else
386
        {
387
388
            // Optionally remove a second dictionary
            if (args.optionFound("diff"))
389
            {
390
391
392
393
394
395
396
397
398
399
400
                Pair<word> dAk(dictAndKeyword(scopedName));

                const dictionary& d(lookupScopedDict(dict, dAk.first()));
                const dictionary& d2(lookupScopedDict(diffDict, dAk.first()));

                const entry* ePtr =
                    d.lookupEntryPtr(dAk.second(), false, true);
                const entry* e2Ptr =
                    d2.lookupEntryPtr(dAk.second(), false, true);

                if (ePtr && e2Ptr)
401
                {
402
403
404
405
406
407
408
409
410
411
412
413
                    if (*ePtr == *e2Ptr)
                    {
                        const_cast<dictionary&>(d).remove(dAk.second());
                    }
                    else if (ePtr->isDict() && e2Ptr->isDict())
                    {
                        remove
                        (
                            const_cast<dictionary&>(ePtr->dict()),
                            e2Ptr->dict()
                        );
                    }
414
415
                }
            }
416
417
418
419
420
421
422
423
424
425


            const entry* entPtr = dict.lookupScopedEntryPtr
            (
                scopedName,
                false,
                true            // Support wildcards
            );

            if (entPtr)
426
            {
427
                if (args.optionFound("keywords"))
428
                {
429
430
                    const dictionary& dict = entPtr->dict();
                    forAllConstIter(dictionary, dict, iter)
431
                    {
432
                        Info<< iter().keyword() << endl;
433
                    }
434
435
436
437
                }
                else
                {
                    if (args.optionFound("value"))
438
                    {
439
                        if (entPtr->isStream())
440
                        {
441
442
                            const tokenList& tokens = entPtr->stream();
                            forAll(tokens, i)
443
                            {
444
                                Info<< tokens[i] << token::SPACE;
445
                            }
446
                            Info<< endl;
447
                        }
448
                        else if (entPtr->isDict())
449
                        {
450
                            Info<< entPtr->dict();
451
                        }
452
                    }
453
454
455
456
                    else
                    {
                        Info<< *entPtr << endl;
                    }
457
458
                }
            }
459
            else
460
            {
461
462
463
                FatalIOErrorInFunction(dictFile)
                    << "Cannot find entry " << entryName
                    << exit(FatalError, 2);
464
465
            }
        }
466
467
468
469
    }
    else if (args.optionFound("keywords"))
    {
        forAllConstIter(dictionary, dict, iter)
470
        {
471
            Info<< iter().keyword() << endl;
472
473
        }
    }
474
475
476
477
478
    else if (args.optionFound("diff"))
    {
        remove(dict, diffDict);
        dict.write(Info, false);
    }
479
480
    else
    {
481
482
483
484
485
486
487
488
489
490
        dict.write(Info, false);
    }

    if (changed)
    {
        dictFile.clear();
        OFstream os(dictFileName);
        IOobject::writeBanner(os);
        dict.write(os, false);
        IOobject::writeEndDivider(os);
491
492
493
494
495
496
497
    }

    return 0;
}


// ************************************************************************* //