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-------------------------------------------------------------------------------
11License
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,
56 IOobject::MUST_READ
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
70 {
71 IOdictionary dict
72 (
73 IOobject
74 (
75 fileName(BCDir/regionType/patchTypes[i]),
76 runTime,
77 IOobject::MUST_READ
78 )
79 );
80
81 regionTemplate.add(patchTypes[i], dictionary(dict));
82 }
83
84 // add solver type boundary types
86 {
87 IOobject io
88 (
89 fileName(BCDir/regionType/solverType/patchTypes[i]),
90 runTime,
91 IOobject::MUST_READ
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
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,
116 IOobject::MUST_READ
117 )
118 );
119
120 regionOptions.add(patchTypes[i], dictionary(dict));
121 }
122 }
123
124 // add solver type boundary options
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,
144 IOobject::MUST_READ
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// ************************************************************************* //
Input/output from string buffers.
Class to store boundary template specifications.
void checkPatch(const word &regionPrefix, const word &condition, const word &category, const word &patchType) const
Check that user supplied patch info is valid.
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.
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.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
const dictionary & subDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary.
Definition: dictionary.C:460
bool merge(const dictionary &dict)
Merge entries from the given dictionary.
Definition: dictionary.C:812
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:640
wordList toc() const
Return the table of contents.
Definition: dictionary.C:602
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:394
engineTime & runTime
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
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))
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
List< word > wordList
A List of words.
Definition: fileName.H:63
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
wordList patchTypes(nPatches)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333