foamSetupCHT.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) 2018-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  foamSetupCHT
26 
27 Description
28  This utility sets up a multi-region case using template files for
29  material properties, field and system files.
30 
31  The utility reads constant/materialProperties to create a regionSolvers list
32  and to create region directories containing required files within the 0,
33  system and constant directories. The materialProperties file contains mesh
34  region names with an associated solver and a material:
35 
36  bottomAir
37  {
38  solver fluid;
39  material air;
40  }
41 
42  The case must contain a directory called templates, with e.g. the
43  following directories and files:
44  + 0
45  + fluid: p, p_rgh, U, T, k, omega, epsilon, nut, alphat
46  + solid: p, T
47  + system
48  + fluid: fvSchemes, fvSolution, decomposeParDict
49  + solid: fvSchemes, fvSolution, decomposeParDict
50  + constant
51  + fluid: g
52  + solid
53  + materials
54  + air: radiationProperties, thermophysicalProperties, momentumTransport
55  + aluminium: radiationProperties, thermophysicalProperties
56  + ...
57 
58  foamSetupCHT can optionally write a template createNonConformalCouplesDict
59  file, with entries for pairs of patches connecting fluid-solid and
60  solid-solid region meshes. The user can edit the file accordingly.
61 
62 \*---------------------------------------------------------------------------*/
63 
64 #include "argList.H"
65 #include "Time.H"
66 #include "IOdictionary.H"
67 #include "dictionaryEntry.H"
68 #include "OFstream.H"
69 
70 using namespace Foam;
71 
72 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
73 
74 int main(int argc, char *argv[])
75 {
77  (
78  "nonConformalCouples",
79  "creates a template \'createNonConformalCouplesDict\' file"
80  );
81 
82  #include "setRootCase.H"
83  #include "createTime.H"
84 
85  // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
86 
87  Info<< "Reading material properties\n" << endl;
88 
89  IOdictionary materialProperties
90  (
91  IOobject
92  (
93  "materialProperties",
94  runTime.constant(),
95  runTime,
98  )
99  );
100 
101  const fileName currentDir(runTime.path());
102  const fileName materialsDir(currentDir/"templates"/"materials");
103  const fileName systemDir(currentDir/"templates"/"system");
104  const fileName constantDir(currentDir/"templates"/"constant");
105  const fileName timeDir(currentDir/"templates"/"0");
106 
107  // Set of valid region names, corresponding to polyMesh sub-directories
108  wordHashSet regions
109  (
110  wordList(readDir(currentDir/"constant", fileType::directory))
111  );
112 
113  wordList regionDirs(regions.toc());
114 
115  forAll(regionDirs, i)
116  {
117  if(!isDir(currentDir/"constant"/regionDirs[i]/"polyMesh"))
118  {
119  regions.erase(regionDirs[i]);
120  }
121  }
122 
123  // Set of valid solver names, listed by:
124  /*
125  grep -rwl thermo $FOAM_MODULES | \
126  sed "s@$FOAM_MODULES/\‍([^/]*\‍).*@\1@g" | sort -u
127  */
128  const wordHashSet solvers
129  {
130  "compressibleMultiphaseVoF",
131  "compressibleVoF",
132  "film",
133  "fluid",
134  "isothermalFilm",
135  "isothermalFluid",
136  "multicomponentFluid",
137  "multiphaseEuler",
138  "shockFluid",
139  "solid",
140  "solidDisplacement",
141  "XiFluid"
142  };
143 
144  // Set of valid material names
145  wordHashSet materials
146  (
147  wordList(readDir(materialsDir, fileType::directory))
148  );
149 
150  wordList regionList;
151  wordList solverList;
152  wordList materialList;
153 
154  forAllConstIter(dictionary, materialProperties, regionIter)
155  {
156  regionList.append(regionIter().keyword());
157  const dictionary& regionDict = regionIter().dict();
158  solverList.append(regionDict.lookup("solver"));
159  materialList.append(regionDict.lookup("material"));
160 
161  if (!regions.found(regionList.last()))
162  {
163  FatalIOErrorIn(args.executable().c_str(), materialProperties)
164  << "Cannot find region polyMesh directory "
165  << "constant"/regionList.last()/"polyMesh" << nl << nl
166  << "Existing regions are "
167  << regions
168  << exit(FatalIOError);
169  }
170 
171  if (!solvers.found(solverList.last()))
172  {
173  FatalIOErrorIn(args.executable().c_str(), materialProperties)
174  << "Cannot find solver "
175  << solverList.last() << nl << nl
176  << "Available solvers are "
177  << solvers.sortedToc()
178  << exit(FatalIOError);
179  }
180 
181  if (!materials.found(materialList.last()))
182  {
183  FatalIOErrorIn(args.executable().c_str(), materialProperties)
184  << "Cannot find region material directory "
185  << "templates/materials"/materialList.last() << nl << nl
186  << "Available materials are "
187  << materials
188  << exit(FatalIOError);
189  }
190  }
191 
193  (
194  "regionSolvers",
197  );
198 
199  forAll(regionList, i)
200  {
201  const word region(regionList[i]);
202  const word material(materialList[i]);
203  const word solver(solverList[i]);
204 
205  Info<< "\nRegion " << region << ":\n"
206  << "\tCreating 0/" << region << " directory" << endl;
207  cpFiles(timeDir/solver, currentDir/"0"/region);
208 
209  Info<< "\tCreating constant/" << region
210  << " directory with " << material << " material" << endl;
211  cpFiles(constantDir/solver, currentDir/"constant"/region);
212  cpFiles(materialsDir/material, currentDir/"constant"/region);
213 
214  Info<< "\tCreating system/" << region << " directory" << endl;
215  cpFiles(systemDir/solver, currentDir/"system"/region);
216 
217  regionSolvers.add(region, solver);
218  }
219 
220  Info<< "\nWriting regionSolvers\n" << endl;
221  {
222  OFstream regionSolversFile
223  (
224  currentDir/runTime.system()/"regionSolvers"
225  );
226  regionSolvers.write(regionSolversFile);
227  }
228 
229  if (args.optionFound("nonConformalCouples"))
230  {
231  IOdictionary NCCdict
232  (
233  IOobject
234  (
235  "createNonConformalCouplesDict",
236  runTime.system(),
237  runTime
238  )
239  );
240 
241  NCCdict.add("fields", "no");
242 
243  label NCCi(1);
244  dictionary couplesDict("nonConformalCouples");
245 
246  forAll(regionList, i)
247  {
248  forAll(regionList, j)
249  {
250  if
251  (
252  i <= j
253  || (
254  solverList[i] != "solid"
255  && solverList[j] != "solid"
256  )
257  )
258  {
259  break;
260  }
261 
262  if (solverList[i] == "solid" && solverList[j] == "solid")
263  {
264  dictionary couple;
265 
266  wordList keywords{"regions", "patches"};
267  forAll(keywords, key)
268  {
269  couple.add
270  (
271  keywords[key],
272  Pair<word>{regionList[i], regionList[j]},
273  true
274  );
275  }
276 
277  couplesDict.add
278  (
279  word("NCC" + std::to_string((NCCi++))),
280  couple,
281  true
282  );
283  }
284  else
285  {
286  word solidRegion;
287  word fluidRegion;
288 
289  if (solverList[i] == "solid")
290  {
291  solidRegion = regionList[i];
292  fluidRegion = regionList[j];
293  }
294  else
295  {
296  solidRegion = regionList[j];
297  fluidRegion = regionList[i];
298  }
299 
300  dictionary couple;
301  couple.add
302  (
303  "regions",
304  Pair<word>{solidRegion, fluidRegion},
305  true
306  );
307 
308  couple.add
309  (
310  "patches",
311  Pair<word>{solidRegion, solidRegion},
312  true
313  );
314 
315  couplesDict.add
316  (
317  word("NCC" + std::to_string((NCCi++))),
318  couple,
319  true
320  );
321  }
322  }
323  }
324 
325  NCCdict.add("nonConformalCouples", couplesDict);
326 
327  Info<< "Writing " << NCCdict.name() << "\n" << endl;
328 
329  NCCdict.regIOobject::write();
330  }
331 
332  Info<< "End\n" << endl;
333 
334  return 0;
335 }
336 
337 
338 // ************************************************************************* //
#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
A HashTable with keys but without contents.
Definition: HashSet.H:62
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:57
IOobject defines the attributes of an object for which implicit objectRegistry management is supporte...
Definition: IOobject.H:99
void append(const T &)
Append an element at the end of the list.
Definition: ListI.H:178
Output to file stream.
Definition: OFstream.H:87
T & last()
Return the last element of the list.
Definition: UListI.H: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
const word & executable() const
Name of executable without the path.
Definition: argListI.H:36
A keyword and a list of tokens is a 'dictionaryEntry'.
A list of keywords followed by any number of values (e.g. words and numbers) or sub-dictionaries.
Definition: dictionary.H:162
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:740
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:1020
static const dictionary null
Null dictionary.
Definition: dictionary.H:273
A class for handling file names.
Definition: fileName.H:82
Class to hold the lists of region meshes and solvers.
Definition: regionSolvers.H:82
Abstract base class for run-time selectable region solvers.
Definition: solver.H:56
A class for handling words, derived from string.
Definition: word.H:62
#define FatalIOErrorIn(functionName, ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:340
int main(int argc, char *argv[])
Definition: financialFoam.C:44
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
void cpFiles(const fileName &srcDir, const fileName &targetDir)
Copy all the files from the source to the target directory.
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
messageStream Info
bool isDir(const fileName &, const bool followLink=true)
Does the name exist as a directory in the file system?
Definition: POSIX.C:539
IOerror FatalIOError
static const char nl
Definition: Ostream.H:267
fileNameList readDir(const fileName &, const fileType=fileType::file, const bool filterVariants=true, const bool followLink=true)
Read a directory and return the entries as a string list.
Definition: POSIX.C:662
Foam::argList args(argc, argv)