changeDictionary.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 Application
25  changeDictionary
26 
27 Description
28  Utility to change dictionary entries, e.g. can be used to change the patch
29  type in the field and polyMesh/boundary files.
30 
31  Reads dictionaries (fields) and entries to change from a dictionary.
32  E.g. to make the \em movingWall a \em fixedValue for \em p but all other
33  \em Walls a zeroGradient boundary condition, the
34  \c system/changeDictionaryDict would contain the following:
35  \verbatim
36  p // field to change
37  {
38  boundaryField
39  {
40  ".*Wall" // entry to change
41  {
42  type zeroGradient;
43  }
44  movingWall // entry to change
45  {
46  type fixedValue;
47  value uniform 123.45;
48  }
49  }
50  }
51  \endverbatim
52  Replacement entries starting with '~' will remove the entry.
53 
54 Usage
55  \b changeDictionary [OPTION]
56 
57  Options:
58  - \par -subDict
59  Specify the subDict name of the replacements dictionary.
60 
61  - \par -literalRE
62  Do not interpret regular expressions; treat them as any other keyword.
63 
64  - \par -enableFunctionEntries
65  Enable function entries (default: disabled)
66 
67  - \par -disablePatchGroups
68  Disable the default checking for keys being patchGroups
69 
70  Note:
71  changeDictionary has been superseded by foamDictionary
72  and is now deprecated.
73 
74 \*---------------------------------------------------------------------------*/
75 
76 #include "argList.H"
77 #include "IOobjectList.H"
78 #include "IOPtrList.H"
79 #include "volFields.H"
80 #include "stringListOps.H"
81 #include "timeSelector.H"
82 #include "systemDict.H"
83 #include "mergeDictionaries.H"
84 
85 using namespace Foam;
86 
87 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
88 
89 namespace Foam
90 {
92 }
93 
94 
95 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
96 
97 // Extract groupPatch info from boundary file info
98 HashTable<wordList, word> extractPatchGroups(const dictionary& boundaryDict)
99 {
100  HashTable<wordList, word> groupToPatch;
101 
102  forAllConstIter(dictionary, boundaryDict, iter)
103  {
104  const word& patchName = iter().keyword();
105  const dictionary& patchDict = iter().dict();
106 
107  wordList groups;
108  if (patchDict.readIfPresent("inGroups", groups))
109  {
110  forAll(groups, i)
111  {
112  HashTable<wordList, word>::iterator fndGroup = groupToPatch.find
113  (
114  groups[i]
115  );
116  if (fndGroup == groupToPatch.end())
117  {
118  groupToPatch.insert(groups[i], wordList(1, patchName));
119  }
120  else
121  {
122  fndGroup().append(patchName);
123  }
124  }
125  }
126  }
127  return groupToPatch;
128 }
129 
130 
131 int main(int argc, char *argv[])
132 {
133  #include "addDictOption.H"
135  (
136  "subDict",
137  "name",
138  "specify the subDict name of the replacements dictionary"
139  );
141  (
142  "instance",
143  "name",
144  "override instance setting (default is the time name)"
145  );
146 
147  // Add explicit time option
149 
151  (
152  "literalRE",
153  "treat regular expressions literally (i.e., as a keyword)"
154  );
156  (
157  "enableFunctionEntries",
158  "enable expansion of dictionary directives - #include, #codeStream etc"
159  );
161  (
162  "disablePatchGroups",
163  "disable matching keys to patch groups"
164  );
165 
166  #include "addMeshOption.H"
167  #include "addRegionOption.H"
168 
169  #include "setRootCase.H"
170 
171  Warning
172  << nl
173  << "changeDictionary has been superseded by foamDictionary"
174  " and is now deprecated."
175  << nl << endl;
176 
177  #include "createTime.H"
178 
179  // Optionally override controlDict time with -time options
181  if (times.size() < 1)
182  {
184  << "No times selected." << exit(FatalError);
185  }
186  forAll(times, timei)
187  {
188  word instance;
189  if (args.optionFound("instance"))
190  {
191  if (times.size() > 1)
192  {
194  << "Multiple times selected with 'instance' option"
195  << exit(FatalError);
196  }
197 
198  args.optionLookup("instance")() >> instance;
199  }
200  else
201  {
202  runTime.setTime(times[timei], timei);
203  instance = runTime.name();
204  }
205 
207 
208  const bool literalRE = args.optionFound("literalRE");
209  if (literalRE)
210  {
211  Info<< "Not interpreting any regular expressions (RE)"
212  << " in the changeDictionaryDict." << endl
213  << "Instead they are handled as any other entry, i.e. added if"
214  << " not present." << endl;
215  }
216 
217  const bool enableEntries = args.optionFound("enableFunctionEntries");
218  if (enableEntries)
219  {
220  Info<< "Allowing dictionary preprocessing "
221  "('#include', '#codeStream')."
222  << endl;
223  }
224 
225  int oldFlag = entry::disableFunctionEntries;
226  if (!enableEntries)
227  {
228  // By default disable dictionary expansion for fields
230  }
231 
232 
233  const bool disablePatchGroups = args.optionFound("disablePatchGroups");
234  if (disablePatchGroups)
235  {
236  Info<< "Not interpreting any keys in the changeDictionary"
237  << " as patchGroups"
238  << endl;
239  }
240 
241 
242  fileName regionPrefix = "";
244  {
245  regionPrefix = regionName;
246  }
247 
248 
249  // Make sure we do not use the master-only reading since we read
250  // fields (different per processor) as dictionaries.
252 
253 
254  // Get the replacement rules from a dictionary
255  const dictionary dict(systemDict("changeDictionaryDict", args, mesh));
256 
257  const dictionary* replaceDictsPtr = &dict;
258 
259  if (args.optionFound("subDict"))
260  {
261  word subDictName(args.optionLookup("subDict")());
262  replaceDictsPtr = &dict.subDict(subDictName);
263  }
264 
265  const dictionary& replaceDicts = *replaceDictsPtr;
266 
267  Info<< "Read dictionary " << dict.name()
268  << " with replacements for dictionaries "
269  << replaceDicts.toc() << endl;
270 
271 
272 
273  // Always read boundary to get patch groups
274  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
275 
276  Info<< "Reading polyMesh/boundary file to extract patch names"
277  << endl;
278 
279  // Read PtrList of dictionary as dictionary.
280  const word oldTypeName = IOPtrList<entry>::typeName;
282  IOPtrList<entry> dictList
283  (
284  IOobject
285  (
286  "boundary",
287  runTime.findInstance
288  (
289  regionPrefix/polyMesh::meshSubDir,
290  "boundary",
292  ),
294  mesh,
297  false
298  )
299  );
300  const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
301 
302  // Fake type back to what was in field
303  const_cast<word&>(dictList.type()) = dictList.headerClassName();
304 
305  // Temporary convert to dictionary
306  dictionary fieldDict;
307  forAll(dictList, i)
308  {
309  fieldDict.add(dictList[i].keyword(), dictList[i].dict());
310  }
311 
312  if (dictList.size())
313  {
314  Info<< "Loaded dictionary " << dictList.name()
315  << " with entries " << fieldDict.toc() << endl;
316  }
317 
318  // Extract any patchGroups information (= shortcut for set of
319  // patches)
320  HashTable<wordList, word> patchGroups;
321  if (!disablePatchGroups)
322  {
323  patchGroups = extractPatchGroups(fieldDict);
324  if (patchGroups.size())
325  {
326  Info<< "Extracted patch groups:" << endl;
327  wordList groups(patchGroups.sortedToc());
328  forAll(groups, i)
329  {
330  Info<< " group " << groups[i] << " with patches "
331  << patchGroups[groups[i]] << endl;
332  }
333  }
334  }
335 
336 
337  // Every replacement is a dictionary name and a keyword in this
338 
339  forAllConstIter(dictionary, replaceDicts, fieldIter)
340  {
341  const word& fieldName = fieldIter().keyword();
342  Info<< "Replacing entries in dictionary " << fieldName << endl;
343 
344  // Handle 'boundary' specially:
345  // - is PtrList of dictionaries
346  // - is in polyMesh/
347  if (fieldName == "boundary")
348  {
349  Info<< "Special handling of " << fieldName
350  << " as polyMesh/boundary file." << endl;
351 
352  // Get the replacement dictionary for the field
353  const dictionary& replaceDict = fieldIter().dict();
354  Info<< "Merging entries from " << replaceDict.toc() << endl;
355 
356  // Merge the replacements in
358  (
359  fieldDict,
360  replaceDict,
361  !literalRE,
362  patchGroups
363  );
364 
365  Info<< "fieldDict:" << fieldDict << endl;
366 
367  // Convert back into dictList
368  wordList doneKeys(dictList.size());
369 
370  label nEntries = fieldDict.size();
371 
372  forAll(dictList, i)
373  {
374  doneKeys[i] = dictList[i].keyword();
375  dictList.set
376  (
377  i,
378  fieldDict.lookupEntry
379  (
380  doneKeys[i],
381  false,
382  true
383  ).clone()
384  );
385  fieldDict.remove(doneKeys[i]);
386  }
387 
388  // Add remaining entries
389  label sz = dictList.size();
390  dictList.setSize(nEntries);
391  forAllConstIter(dictionary, fieldDict, iter)
392  {
393  dictList.set(sz++, iter().clone());
394  }
395 
396  Info<< "Writing modified " << fieldName << endl;
397  dictList.writeObject
398  (
399  runTime.writeFormat(),
400  runTime.writeFormat(),
402  true
403  );
404  }
405  else
406  {
407  // Read dictionary. (disable class type checking so we can load
408  // field)
409  Info<< "Loading dictionary " << fieldName << endl;
410  const word oldTypeName = localIOdictionary::typeName;
411  const_cast<word&>(localIOdictionary::typeName) = word::null;
412 
413  localIOdictionary fieldDict
414  (
415  IOobject
416  (
417  fieldName,
418  instance,
419  mesh,
422  false
423  )
424  );
425 
426  const_cast<word&>(localIOdictionary::typeName) = oldTypeName;
427 
428  // Fake type back to what was in field
429  const_cast<word&>(fieldDict.type()) =
430  fieldDict.headerClassName();
431 
432  Info<< "Loaded dictionary " << fieldName
433  << " with entries " << fieldDict.toc() << endl;
434 
435  // Get the replacement dictionary for the field
436  const dictionary& replaceDict = fieldIter().dict();
437  Info<< "Merging entries from " << replaceDict.toc() << endl;
438 
439  // Merge the replacements in
441  (
442  fieldDict,
443  replaceDict,
444  !literalRE,
445  patchGroups
446  );
447 
448  Info<< "Writing modified fieldDict " << fieldName << endl;
449  fieldDict.regIOobject::write();
450  }
451  }
452 
454  }
455 
456  Info<< "\nEnd\n" << endl;
457 
458  return 0;
459 }
460 
461 
462 // ************************************************************************* //
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:433
#define forAllConstIter(Container, container, iter)
Iterate across all elements in the container object of type.
Definition: UList.H:476
An STL-conforming iterator.
Definition: HashTable.H:443
An STL-conforming hash table.
Definition: HashTable.H:127
List< Key > sortedToc() const
Return the table of contents as a sorted list.
Definition: HashTable.C:242
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Definition: HashTable.C:167
A PtrList of objects of type <Type> with automated input and output.
Definition: IOPtrList.H:53
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
@ MUST_READ_IF_MODIFIED
Definition: IOobject.H:119
static fileCheckTypes fileModificationChecking
Type of file modification checking.
Definition: IOobject.H:223
void size(const label)
Override size to be inconsistent with allocated storage.
Definition: ListI.H:164
static void addOption(const word &opt, const string &param="", const string &usage="")
Add to an option to validOptions with usage information.
Definition: argList.C:128
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:118
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:114
IStringStream optionLookup(const word &opt) const
Return an IStringStream from the named option.
Definition: argListI.H:120
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 & lookupEntry(const word &, bool recursive, bool patternMatch) const
Find and return an entry data stream if present otherwise error.
Definition: dictionary.C:697
bool remove(const word &)
Remove an entry specified by keyword.
Definition: dictionary.C:1183
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:849
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1020
bool readIfPresent(const word &, T &, bool recursive=false, bool patternMatch=true) const
Find an entry if present, and assign to T.
wordList toc() const
Return the table of contents.
Definition: dictionary.C:982
virtual autoPtr< entry > clone(const dictionary &parentDict) const =0
Construct on freestore as copy with reference to the.
static int disableFunctionEntries
Definition: entry.H:102
A class for handling file names.
Definition: fileName.H:82
localIOdictionary derived from IOdictionary with global set false to disable parallel master reading.
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:270
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:273
static void addOptions(const bool constant=true, const bool withZero=false)
Add the options handled by timeSelector to argList::validOptions.
Definition: timeSelector.C:114
static instantList selectIfPresent(Time &runTime, const argList &args)
If any time option provided return the set of times (as select0)
Definition: timeSelector.C:283
A class for handling words, derived from string.
Definition: word.H:62
static const word null
An empty word.
Definition: word.H:77
Foam::fvMesh mesh(Foam::IOobject(regionName, runTime.name(), runTime, Foam::IOobject::MUST_READ), false)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:334
int main(int argc, char *argv[])
Definition: financialFoam.C:44
Function with which to merge one dictionary into another. Intended for user-facing dictionary merging...
Namespace for OpenFOAM.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
List< word > wordList
A List of words.
Definition: fileName.H:54
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:258
const word & regionName(const solver &region)
Definition: solver.H:218
messageStream Info
defineTemplateTypeNameAndDebug(prghPressure, 0)
T clone(const T &t)
Definition: List.H:55
error FatalError
IOdictionary systemDict(const word &dictName, const argList &args, const objectRegistry &ob, const word &regionName=polyMesh::defaultRegion, const fileName &path=fileName::null)
Definition: systemDict.C:93
bool mergeDictionaries(dictionary &tgtDict, const dictionary &srcDict, const bool wildcards=true, const HashTable< wordList, word > &shortcuts=HashTable< wordList, word >(0))
static const char nl
Definition: Ostream.H:267
messageStream Warning
dictionary dict
Foam::argList args(argc, argv)
Operations on lists of strings.
static iteratorEnd end()
iteratorEnd set to beyond the end of any HashTable
Definition: HashTable.H:112