foamUpgradeCyclics.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 | Copyright (C) 2011-2016 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  foamUpgradeCyclics
26 
27 Description
28  Tool to upgrade mesh and fields for split cyclics.
29 
30 Usage
31  \b foamUpgradeCyclics [OPTION]
32 
33  Options:
34  - \par -test
35  Suppress writing the updated files with split cyclics
36 
37  - \par -enableFunctionEntries
38  By default all dictionary preprocessing of fields is disabled
39 
40 \*---------------------------------------------------------------------------*/
41 
42 #include "argList.H"
43 #include "Time.H"
44 #include "timeSelector.H"
45 #include "IOdictionary.H"
46 #include "polyMesh.H"
47 #include "entry.H"
48 #include "IOPtrList.H"
49 #include "cyclicPolyPatch.H"
50 #include "dictionaryEntry.H"
51 #include "IOobjectList.H"
52 #include "volFields.H"
53 #include "pointFields.H"
54 #include "surfaceFields.H"
55 #include "string.H"
56 
57 using namespace Foam;
58 
59 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
60 
61 namespace Foam
62 {
64 }
65 
66 
67 // Read boundary file without reading mesh
68 void rewriteBoundary
69 (
70  const bool isTestRun,
71  const IOobject& io,
72  const fileName& regionPrefix,
73  HashTable<word>& thisNames,
74  HashTable<word>& nbrNames
75 )
76 {
77  Info<< "Reading boundary from " << io.filePath() << endl;
78 
79  // Read PtrList of dictionary.
80  const word oldTypeName = IOPtrList<entry>::typeName;
83  const_cast<word&>(IOPtrList<entry>::typeName) = oldTypeName;
84  // Fake type back to what was in field
85  const_cast<word&>(patches.type()) = patches.headerClassName();
86 
87 
88  // Replace any 'cyclic'
89  label nOldCyclics = 0;
91  {
92  const dictionary& patchDict = patches[patchi].dict();
93 
94  if (word(patchDict["type"]) == cyclicPolyPatch::typeName)
95  {
96  if (!patchDict.found("neighbourPatch"))
97  {
98  Info<< "Patch " << patches[patchi].keyword()
99  << " does not have 'neighbourPatch' entry; assuming it"
100  << " is of the old type." << endl;
101  nOldCyclics++;
102  }
103  }
104  }
105 
106  Info<< "Detected " << nOldCyclics << " old cyclics." << nl << endl;
107 
108 
109  // Save old patches.
110  PtrList<entry> oldPatches(patches);
111 
112  // Extend
113  label nOldPatches = patches.size();
114  patches.setSize(nOldPatches+nOldCyclics);
115 
116  // Create reordering map
117  labelList oldToNew(patches.size());
118 
119 
120  // Add new entries
121  label addedPatchi = nOldPatches;
122  label newPatchi = 0;
123  forAll(oldPatches, patchi)
124  {
125  const dictionary& patchDict = oldPatches[patchi].dict();
126 
127  if
128  (
129  word(patchDict["type"]) == cyclicPolyPatch::typeName
130  )
131  {
132  const word& name = oldPatches[patchi].keyword();
133 
134  if (patchDict.found("neighbourPatch"))
135  {
136  patches.set(patchi, oldPatches.set(patchi, NULL));
137  oldToNew[patchi] = newPatchi++;
138 
139  // Check if patches come from automatic conversion
140  word oldName;
141 
142  string::size_type i = name.rfind("_half0");
143  if (i != string::npos)
144  {
145  oldName = name.substr(0, i);
146  thisNames.insert(oldName, name);
147  Info<< "Detected converted cyclic patch " << name
148  << " ; assuming it originates from " << oldName
149  << endl;
150  }
151  else
152  {
153  i = name.rfind("_half1");
154  if (i != string::npos)
155  {
156  oldName = name.substr(0, i);
157  nbrNames.insert(oldName, name);
158  Info<< "Detected converted cyclic patch " << name
159  << " ; assuming it originates from " << oldName
160  << endl;
161  }
162  }
163  }
164  else
165  {
166  label nFaces = readLabel(patchDict["nFaces"]);
167  label startFace = readLabel(patchDict["startFace"]);
168 
169  Info<< "Detected old style " << word(patchDict["type"])
170  << " patch " << name << " with" << nl
171  << " nFaces : " << nFaces << nl
172  << " startFace : " << startFace << endl;
173 
174  word thisName = name + "_half0";
175  word nbrName = name + "_half1";
176 
177  thisNames.insert(name, thisName);
178  nbrNames.insert(name, nbrName);
179 
180  // Save current dictionary
181  const dictionary patchDict(patches[patchi].dict());
182 
183  // Change entry on this side
184  patches.set(patchi, oldPatches.set(patchi, NULL));
185  oldToNew[patchi] = newPatchi++;
186  dictionary& thisPatchDict = patches[patchi].dict();
187  thisPatchDict.add("neighbourPatch", nbrName);
188  thisPatchDict.set("nFaces", nFaces/2);
189  patches[patchi].keyword() = thisName;
190 
191  // Add entry on other side
192  patches.set
193  (
194  addedPatchi,
195  new dictionaryEntry
196  (
197  nbrName,
199  patchDict
200  )
201  );
202  oldToNew[addedPatchi] = newPatchi++;
203  dictionary& nbrPatchDict = patches[addedPatchi].dict();
204  nbrPatchDict.set("neighbourPatch", thisName);
205  nbrPatchDict.set("nFaces", nFaces/2);
206  nbrPatchDict.set("startFace", startFace+nFaces/2);
207  patches[addedPatchi].keyword() = nbrName;
208 
209  Info<< "Replaced with patches" << nl
210  << patches[patchi].keyword() << " with" << nl
211  << " nFaces : "
212  << readLabel(thisPatchDict.lookup("nFaces"))
213  << nl
214  << " startFace : "
215  << readLabel(thisPatchDict.lookup("startFace")) << nl
216  << patches[addedPatchi].keyword() << " with" << nl
217  << " nFaces : "
218  << readLabel(nbrPatchDict.lookup("nFaces"))
219  << nl
220  << " startFace : "
221  << readLabel(nbrPatchDict.lookup("startFace"))
222  << nl << endl;
223 
224  addedPatchi++;
225  }
226  }
227  else
228  {
229  patches.set(patchi, oldPatches.set(patchi, NULL));
230  oldToNew[patchi] = newPatchi++;
231  }
232  }
233 
234  patches.reorder(oldToNew);
235 
236  if (returnReduce(nOldCyclics, sumOp<label>()) > 0)
237  {
238  if (isTestRun)
239  {
240  //Info<< "-test option: no changes made" << nl << endl;
241  }
242  else
243  {
244  if (mvBak(patches.objectPath(), "old"))
245  {
246  Info<< "Backup to "
247  << (patches.objectPath() + ".old") << nl;
248  }
249 
250  Info<< "Write to "
251  << patches.objectPath() << nl << endl;
252  patches.write();
253  }
254  }
255  else
256  {
257  Info<< "No changes made to boundary file." << nl << endl;
258  }
259 }
260 
261 
262 void rewriteField
263 (
264  const bool isTestRun,
265  const Time& runTime,
266  const word& fieldName,
267  const HashTable<word>& thisNames,
268  const HashTable<word>& nbrNames
269 )
270 {
271  // Read dictionary. (disable class type checking so we can load
272  // field)
273  Info<< "Loading field " << fieldName << endl;
274  const word oldTypeName = IOdictionary::typeName;
275  const_cast<word&>(IOdictionary::typeName) = word::null;
276 
277  IOdictionary fieldDict
278  (
279  IOobject
280  (
281  fieldName,
282  runTime.timeName(),
283  runTime,
286  false
287  )
288  );
289  const_cast<word&>(IOdictionary::typeName) = oldTypeName;
290  // Fake type back to what was in field
291  const_cast<word&>(fieldDict.type()) = fieldDict.headerClassName();
292 
293 
294 
295  dictionary& boundaryField = fieldDict.subDict("boundaryField");
296 
297  label nChanged = 0;
298 
299  forAllConstIter(HashTable<word>, thisNames, iter)
300  {
301  const word& patchName = iter.key();
302  const word& newName = iter();
303 
304  Info<< "Looking for entry for patch " << patchName << endl;
305 
306  // Find old patch name either direct or through wildcards
307  // Find new patch name direct only
308 
309  if
310  (
311  boundaryField.found(patchName)
312  && !boundaryField.found(newName, false, false)
313  )
314  {
315  Info<< " Changing entry " << patchName << " to " << newName
316  << endl;
317 
318  dictionary& patchDict = boundaryField.subDict(patchName);
319 
320  if (patchDict.found("value"))
321  {
322  // Remove any value field since wrong size.
323  patchDict.remove("value");
324  }
325 
326 
327  boundaryField.changeKeyword(patchName, newName);
328  boundaryField.add
329  (
330  nbrNames[patchName],
331  patchDict
332  );
333  Info<< " Adding entry " << nbrNames[patchName] << endl;
334 
335  nChanged++;
336  }
337  }
338 
339  //Info<< "New boundaryField:" << boundaryField << endl;
340 
341  if (returnReduce(nChanged, sumOp<label>()) > 0)
342  {
343  if (isTestRun)
344  {
345  //Info<< "-test option: no changes made" << endl;
346  }
347  else
348  {
349  if (mvBak(fieldDict.objectPath(), "old"))
350  {
351  Info<< "Backup to "
352  << (fieldDict.objectPath() + ".old") << nl;
353  }
354 
355  Info<< "Write to "
356  << fieldDict.objectPath() << endl;
357  fieldDict.regIOobject::write();
358  }
359  }
360  else
361  {
362  Info<< "No changes made to field " << fieldName << endl;
363  }
364  Info<< endl;
365 }
366 
367 
368 void rewriteFields
369 (
370  const bool isTestRun,
371  const Time& runTime,
372  const wordList& fieldNames,
373  const HashTable<word>& thisNames,
374  const HashTable<word>& nbrNames
375 )
376 {
377  forAll(fieldNames, i)
378  {
379  rewriteField
380  (
381  isTestRun,
382  runTime,
383  fieldNames[i],
384  thisNames,
385  nbrNames
386  );
387  }
388 }
389 
390 
391 
392 int main(int argc, char *argv[])
393 {
395 
396  argList::addBoolOption("test", "test only; do not change any files");
398  (
399  "enableFunctionEntries",
400  "enable expansion of dictionary directives - #include, #codeStream etc"
401  );
402  #include "addRegionOption.H"
403 
404  #include "setRootCase.H"
405  #include "createTime.H"
406 
407 
408  // Make sure we do not use the master-only reading since we read
409  // fields (different per processor) as dictionaries.
411 
412 
413  instantList timeDirs = timeSelector::select0(runTime, args);
414 
415  const bool isTestRun = args.optionFound("test");
416  if (isTestRun)
417  {
418  Info<< "-test option: no changes made" << nl << endl;
419  }
420  const bool enableEntries = args.optionFound("enableFunctionEntries");
421 
422 
423  Foam::word regionName = polyMesh::defaultRegion;
424  args.optionReadIfPresent("region", regionName);
425 
426  fileName regionPrefix = "";
427  if (regionName != polyMesh::defaultRegion)
428  {
429  regionPrefix = regionName;
430  }
431 
432 
433  // Per cyclic patch the new name for this side and the other side
434  HashTable<word> thisNames;
435  HashTable<word> nbrNames;
436 
437  // Rewrite constant boundary file. Return any patches that have been split.
438  IOobject io
439  (
440  "boundary",
441  runTime.constant(),
443  runTime,
446  false
447  );
448 
449  if (io.headerOk())
450  {
451  rewriteBoundary
452  (
453  isTestRun,
454  io,
455  regionPrefix,
456  thisNames,
457  nbrNames
458  );
459  }
460 
461 
462 
463  // Convert any fields
464 
465  forAll(timeDirs, timeI)
466  {
467  runTime.setTime(timeDirs[timeI], timeI);
468 
469  Info<< "Time: " << runTime.timeName() << endl;
470 
471  // See if mesh in time directory
472  IOobject io
473  (
474  "boundary",
475  runTime.timeName(),
477  runTime,
480  false
481  );
482 
483  if (io.headerOk())
484  {
485  rewriteBoundary
486  (
487  isTestRun,
488  io,
489  regionPrefix,
490  thisNames,
491  nbrNames
492  );
493  }
494 
495 
496  IOobjectList objects(runTime, runTime.timeName());
497 
498 
499  int oldFlag = entry::disableFunctionEntries;
500  if (!enableEntries)
501  {
502  // By default disable dictionary expansion for fields
504  }
505 
506  // volFields
507  // ~~~~~~~~~
508 
509  rewriteFields
510  (
511  isTestRun,
512  runTime,
513  objects.names(volScalarField::typeName),
514  thisNames,
515  nbrNames
516  );
517  rewriteFields
518  (
519  isTestRun,
520  runTime,
521  objects.names(volVectorField::typeName),
522  thisNames,
523  nbrNames
524  );
525  rewriteFields
526  (
527  isTestRun,
528  runTime,
529  objects.names(volSphericalTensorField::typeName),
530  thisNames,
531  nbrNames
532  );
533  rewriteFields
534  (
535  isTestRun,
536  runTime,
537  objects.names(volSymmTensorField::typeName),
538  thisNames,
539  nbrNames
540  );
541  rewriteFields
542  (
543  isTestRun,
544  runTime,
545  objects.names(volTensorField::typeName),
546  thisNames,
547  nbrNames
548  );
549 
550 
551  // pointFields
552  // ~~~~~~~~~~~
553 
554  rewriteFields
555  (
556  isTestRun,
557  runTime,
558  objects.names(pointScalarField::typeName),
559  thisNames,
560  nbrNames
561  );
562  rewriteFields
563  (
564  isTestRun,
565  runTime,
566  objects.names(pointVectorField::typeName),
567  thisNames,
568  nbrNames
569  );
570  rewriteFields
571  (
572  isTestRun,
573  runTime,
575  thisNames,
576  nbrNames
577  );
578  rewriteFields
579  (
580  isTestRun,
581  runTime,
582  objects.names(pointSymmTensorField::typeName),
583  thisNames,
584  nbrNames
585  );
586  rewriteFields
587  (
588  isTestRun,
589  runTime,
590  objects.names(pointTensorField::typeName),
591  thisNames,
592  nbrNames
593  );
594 
595 
596  // surfaceFields
597  // ~~~~~~~~~~~
598 
599  rewriteFields
600  (
601  isTestRun,
602  runTime,
603  objects.names(surfaceScalarField::typeName),
604  thisNames,
605  nbrNames
606  );
607  rewriteFields
608  (
609  isTestRun,
610  runTime,
611  objects.names(surfaceVectorField::typeName),
612  thisNames,
613  nbrNames
614  );
615  rewriteFields
616  (
617  isTestRun,
618  runTime,
620  thisNames,
621  nbrNames
622  );
623  rewriteFields
624  (
625  isTestRun,
626  runTime,
627  objects.names(surfaceSymmTensorField::typeName),
628  thisNames,
629  nbrNames
630  );
631  rewriteFields
632  (
633  isTestRun,
634  runTime,
635  objects.names(surfaceTensorField::typeName),
636  thisNames,
637  nbrNames
638  );
639 
641  }
642 
643  return 0;
644 }
645 
646 
647 // ************************************************************************* //
Foam::surfaceFields.
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:428
bool remove(const word &)
Remove an entry specified by keyword.
Definition: dictionary.C:889
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
A class for handling file names.
Definition: fileName.H:69
List of IOobjects with searching and retrieving facilities.
Definition: IOobjectList.H:50
A list of keyword definitions, which are a keyword followed by any number of values (e...
Definition: dictionary.H:137
static const char *const typeName
Definition: Field.H:94
Foam::word regionName
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh")
Definition: polyMesh.H:309
bool optionReadIfPresent(const word &opt, T &) const
Read a value from the named option if present.
Definition: argListI.H:198
static const dictionary null
Null dictionary.
Definition: dictionary.H:193
const dictionary & subDict(const word &) const
Find and return a sub-dictionary.
Definition: dictionary.C:633
static word defaultRegion
Return the default region name.
Definition: polyMesh.H:306
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:253
static word timeName(const scalar, const int precision=precision_)
Return time name of given scalar time.
Definition: Time.C:715
patches[0]
A keyword and a list of tokens is a &#39;dictionaryEntry&#39;.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:68
bool mvBak(const fileName &, const std::string &ext="bak")
Rename to a corresponding backup file.
Definition: POSIX.C:782
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:737
static List< word > fieldNames
Definition: globalFoam.H:46
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:53
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
static fileCheckTypes fileModificationChecking
Definition: regIOobject.H:128
bool changeKeyword(const keyType &oldKeyword, const keyType &newKeyword, bool forceOverwrite=false)
Change the keyword for an entry,.
Definition: dictionary.C:922
static int disableFunctionEntries
Definition: entry.H:83
fileName filePath() const
Return complete path + object name if the file exists.
Definition: IOobject.C:299
bool optionFound(const word &opt) const
Return true if the named option is found.
Definition: argListI.H:108
A class for handling words, derived from string.
Definition: word.H:59
static const word null
An empty word.
Definition: word.H:77
const word & constant() const
Return constant name.
Definition: TimePaths.H:124
bool found(const word &, bool recursive=false, bool patternMatch=true) const
Search dictionary for given keyword.
Definition: dictionary.C:306
An STL-conforming hash table.
Definition: HashTable.H:61
graph_traits< Graph >::vertices_size_type size_type
Definition: SloanRenumber.C:73
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:29
label readLabel(Istream &is)
Definition: label.H:64
defineTemplateTypeNameAndDebug(IOPtrList< ensightPart >, 0)
static const char nl
Definition: Ostream.H:262
static instantList select0(Time &runTime, const argList &args)
Return the set of times selected based on the argList options.
Definition: timeSelector.C:253
A PtrList of objects of type <T> with automated input and output.
Definition: IOPtrList.H:50
label patchi
void set(entry *)
Assign a new entry, overwrite any existing entry.
Definition: dictionary.C:864
messageStream Info
bool headerOk()
Read and check header info.
Definition: IOobject.C:400
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
static void addBoolOption(const word &opt, const string &usage="")
Add to a bool option to validOptions with usage information.
Definition: argList.C:83
Foam::argList args(argc, argv)
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:91
static void addOptions(const bool constant=true, const bool withZero=false)
Add the options handled by timeSelector to argList::validOptions.
Definition: timeSelector.C:114
Namespace for OpenFOAM.
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:451