boundaryTemplates.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) 2015 OpenFOAM Foundation
9  Copyright (C) 2015 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
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 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "boundaryTemplates.H"
30 #include "Time.H"
31 #include "IFstream.H"
32 #include "StringStream.H"
33 
34 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
35 
37 (
38  const fileName& baseDir,
39  const Time& runTime,
40  const word& solverType
41 )
42 :
43  templates_(),
44  options_()
45 {
46  Info<< " Reading boundary templates" << endl;
47 
48  fileName BCDir(baseDir/"boundaryConditions");
49 
50  IOdictionary regionBCs
51  (
52  IOobject
53  (
54  fileName(BCDir/"boundaries"),
55  runTime,
57  )
58  );
59 
60  for (const entry& dEntry : regionBCs)
61  {
62  const word& regionType = dEntry.keyword();
63  wordList patchTypes(regionBCs.lookup(regionType));
64 
65  dictionary regionTemplate;
66  dictionary regionOptions;
67 
68  // read general boundary types
69  forAll(patchTypes, i)
70  {
71  IOdictionary dict
72  (
73  IOobject
74  (
75  fileName(BCDir/regionType/patchTypes[i]),
76  runTime,
78  )
79  );
80 
81  regionTemplate.add(patchTypes[i], dictionary(dict));
82  }
83 
84  // add solver type boundary types
85  forAll(patchTypes, i)
86  {
87  IOobject io
88  (
89  fileName(BCDir/regionType/solverType/patchTypes[i]),
90  runTime,
92  );
93 
94  if (io.typeHeaderOk<IOdictionary>(true))
95  {
96  IOdictionary dict(io);
97  regionTemplate.subDict(patchTypes[i]).merge(dict);
98  }
99  }
100 
101  // read general boundary options
102  forAll(patchTypes, i)
103  {
104  fileName optFile(BCDir/regionType/patchTypes[i] + "Options");
105 
106  IFstream is(optFile);
107 
108  if (is.good())
109  {
110  IOdictionary dict
111  (
112  IOobject
113  (
114  optFile,
115  runTime,
117  )
118  );
119 
120  regionOptions.add(patchTypes[i], dictionary(dict));
121  }
122  }
123 
124  // add solver type boundary options
125  forAll(patchTypes, i)
126  {
127  // options are optional - however, if file exists, assume that it
128  // is to be read
129  fileName optFile
130  (
131  BCDir/regionType/solverType/patchTypes[i] + "Options"
132  );
133 
134  IFstream is(optFile);
135 
136  if (is.good())
137  {
138  IOdictionary dict
139  (
140  IOobject
141  (
142  optFile,
143  runTime,
145  )
146  );
147 
148  regionOptions.subDict(patchTypes[i]).merge(dict);
149  }
150  }
151 
152  templates_.add(regionType, regionTemplate);
153  options_.add(regionType, regionOptions);
154  }
155 }
156 
157 
158 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
159 
161 {
162  return templates_;
163 }
164 
165 
167 (
168  const word& regionPrefix,
169  const word& fieldName,
170  const word& condition,
171  const word& category,
172  const word& patchType,
173  const dictionary& conditionOptions
174 ) const
175 {
176  const dictionary& regionTemplates = templates_.subDict(regionPrefix);
177 
178  // look for inlet, outlet, wall etc
179  if (regionTemplates.found(category))
180  {
181  const dictionary& categoryDict = regionTemplates.subDict(category);
182 
183  // look for subSonic, slip etc
184  if (categoryDict.found(patchType))
185  {
186  dictionary patchDict = categoryDict.subDict(patchType);
187 
188  // add any options
189  if (patchDict.found("OPTIONS"))
190  {
191  const dictionary& regionOptions =
192  options_.subDict(regionPrefix);
193 
194  if (!regionOptions.found(category))
195  {
197  << "No options available for category "
198  << category << exit(FatalError);
199  }
200 
201  const dictionary& dict = regionOptions.subDict(category);
202 
203  const wordList requiredOptions(patchDict.lookup("OPTIONS"));
204 
205  for (const word& option : requiredOptions)
206  {
207  word selected;
208  if (!conditionOptions.readIfPresent(option, selected))
209  {
211  << "Condition " << condition << ": "
212  << "No option '" << option
213  << "' available for category '" << category
214  << "' and patch type '" << patchType
215  << "'. Valid options are: "
216  << conditionOptions.toc()
217  << exit(FatalError);
218  }
219 
220  if (!dict.found(option))
221  {
223  << "Condition " << condition << ": "
224  << "No option '" << option
225  << "' available for category '" << category
226  << "' and patch type '" << patchType
227  << "'. Valid options are " << dict.toc()
228  << exit(FatalError);
229  }
230 
231  const dictionary& optionDict = dict.subDict(option);
232 
233  if (!optionDict.found(selected))
234  {
236  << "Condition " << condition << ": "
237  << "No option '" << selected
238  << "' available for category '" << category
239  << "' and patch type '" << patchType
240  << "'. Valid options are " << optionDict.toc()
241  << exit(FatalError);
242  }
243 
244  const dictionary& dict = optionDict.subDict(selected);
245 
246  patchDict.merge(dict);
247  }
248  }
249 
250  // look for field name
251  if (patchDict.found(fieldName))
252  {
253  dictionary dict;
254  const dictionary& fieldDict = patchDict.subDict(fieldName);
255 
256  for (const entry& dEntry : fieldDict)
257  {
258  OStringStream oss;
259  oss << dEntry;
260 
261  string s(oss.str());
262  s.replace(dEntry.keyword(), "");
263  s.replace
264  (
265  "VALUE",
266  "boundaryConditions." + condition + ".values"
267  );
268  dict.add(dEntry.keyword(), s.c_str());
269  }
270 
271  return dict;
272  }
273  else
274  {
276  << "Condition " << condition << ": "
277  << "No '" << patchType
278  << "' condition found for field '" << fieldName
279  << "' in category type '" << category << "'"
280  << exit(FatalError);
281  }
282  }
283  else
284  {
286  << "Condition " << condition << ": "
287  << "No '" << patchType << "' boundary types defined in "
288  << categoryDict.dictName() << " templates. "
289  << "Available types are: " << categoryDict.toc()
290  << exit(FatalError);
291  }
292  }
293  else
294  {
296  << "Condition " << condition << ": "
297  << "Invalid boundary condition type '" << patchType
298  << "'. Valid types are:" << regionTemplates.toc()
299  << exit(FatalError);
300  }
301 
302  return dictionary::null;
303 }
304 
305 
307 (
308  const word& regionPrefix,
309  const word& condition,
310  const word& category,
311  const word& patchType
312 ) const
313 {
314  const dictionary& regionTemplates = templates_.subDict(regionPrefix);
315 
316  if (!regionTemplates.found(category))
317  {
319  << "Condition " << condition << ": "
320  << "Unknown category '" << category
321  << "'. Valid categories are: " << regionTemplates.toc()
322  << exit(FatalError);
323  }
324 
325  const dictionary& categoryDict = regionTemplates.subDict(category);
326 
327  if (!categoryDict.found(patchType))
328  {
330  << "Condition " << condition << ": "
331  << "Unknown type '" << patchType << "' in category '"
332  << category << "'. Valid types are: " << categoryDict.toc()
333  << exit(FatalError);
334  }
335 }
336 
337 
339 (
340  const word& regionPrefix,
341  const word& category,
342  const word& patchType
343 ) const
344 {
345  const dictionary& regionTemplates = templates_.subDict(regionPrefix);
346 
347  if (regionTemplates.found(category))
348  {
349  const dictionary& categoryDict = regionTemplates.subDict(category);
350 
351  if (categoryDict.found(patchType))
352  {
353  const dictionary& patchDict = categoryDict.subDict(patchType);
354 
355  if (patchDict.found("OPTIONS"))
356  {
357  return true;
358  }
359  }
360  else
361  {
363  << "No type '" << patchType << "' found in category '"
364  << category << "'. Valid types are "
365  << categoryDict.toc()
366  << exit(FatalError);
367  }
368  }
369  else
370  {
372  << "No category '" << category << "' found in templates. "
373  << "Valid categories are " << templates_.toc()
374  << exit(FatalError);
375  }
376 
377  return false;
378 }
379 
380 
381 // ************************************************************************* //
dictionary dict
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:578
Input/output from string buffers.
wordList patchTypes(nPatches)
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:637
boundaryTemplates(const fileName &baseDir, const Time &runTime, const word &solverType)
Constructor.
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:453
wordList toc() const
Return the table of contents.
Definition: dictionary.C:599
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:100
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:414
bool merge(const dictionary &dict)
Merge entries from the given dictionary.
Definition: dictionary.C:811
dictionary generatePatchDict(const word &regionPrefix, const word &fieldName, const word &condition, const word &category, const word &patchType, const dictionary &conditionOptions) const
Generate a dictionary representation of patch boundary condition.
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:465
bool optionsRequired(const word &regionPrefix, const word &category, const word &patchType) const
Return true if condition requires additional user options.
const dictionary & templates() const
Return the dictionary of boundary templates.
List< word > wordList
List of word.
Definition: fileName.H:58
messageStream Info
Information stream (stdout output on master, null elsewhere)
void checkPatch(const word &regionPrefix, const word &condition, const word &category, const word &patchType) const
Check that user supplied patch info is valid.
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))