genericPatchFieldBase.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) 2021 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
29#include "messageStream.H"
30
31// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32
33bool Foam::genericPatchFieldBase::checkFieldSize
34(
35 const label fieldSize,
36 const label patchSize,
37 const word& patchName,
38 const keyType& key,
39 const IOobject& io
40) const
41{
42 const bool ok = (fieldSize == patchSize);
43
44 if (!ok)
45 {
47 << "\n size of field " << key
48 << " (" << fieldSize << ") != patch size (" << patchSize << ')'
49 << "\n on patch " << patchName
50 << " of field " << io.name() << " in file "
51 << io.objectPath() << nl
53 }
54
55 return ok;
56}
57
58
59// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
60
62(
63 const dictionary& dict
64)
65:
66 actualTypeName_(dict.get<word>("type")),
67 dict_(dict)
68{}
69
70
72(
73 const Foam::zero,
74 const genericPatchFieldBase& rhs
75)
76:
77 actualTypeName_(rhs.actualTypeName_),
78 dict_(rhs.dict_)
79{}
80
81
82// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
83
85(
86 const word& patchName,
87 const IOobject& io
88) const
89{
91 << " (actual type " << actualTypeName_ << ')'
92 << "\n on patch " << patchName
93 << " of field " << io.name() << " in file " << io.objectPath() << nl
94 << nl
95 << " You are probably trying to solve for a field with a "
96 "generic boundary condition." << nl;
97}
98
99
101(
102 const word& entryName,
103 const word& patchName,
104 const IOobject& io
105) const
106{
108 << nl
109 << " Missing required '" << entryName << "' entry"
110 << " on patch " << patchName
111 << " of field " << io.name() << " in file " << io.objectPath() << nl
112 << " (Actual type " << actualTypeName_ << ')' << nl << nl
113 << " Please add the '" << entryName << "' entry to the"
114 " write function of the user-defined boundary-condition" << nl
115 << exit(FatalIOError);
116}
117
118
120(
121 const label patchSize,
122 const word& patchName,
123 const IOobject& io,
124 const bool separateValue
125)
126{
127 for (const entry& dEntry : dict_)
128 {
129 const keyType& key = dEntry.keyword();
130
131 if (key == "type" || (separateValue && key == "value"))
132 {
133 // "type" and possibly "value" handled differently
134 }
135 else
136 {
137 processEntry(dEntry, patchSize, patchName, io);
138 }
139 }
140}
141
142
144(
145 const entry& dEntry,
146 const label patchSize,
147 const word& patchName,
148 const IOobject& io
149)
150{
151 if (!dEntry.isStream())
152 {
153 return false;
154 }
155
156 const keyType& key = dEntry.keyword();
157 ITstream& is = dEntry.stream();
158
159 if (is.empty())
160 {
161 return false;
162 }
163
164 #undef FIELDSIZE_CHECK
165 #define FIELDSIZE_CHECK(fieldLen) \
166 checkFieldSize(fieldLen, patchSize, patchName, key, io)
167
168
169 // First token
170 token tok(is);
171
172 if (tok.isWord("nonuniform"))
173 {
174 is >> tok;
175
176 if (tok.isLabel(0))
177 {
178 // For v2006 and earlier, could have a plain untyped 0
179 // without a compound type.
180 // Just treat as scalar and hope for the best.
181 scalarFields_.insert(key, autoPtr<scalarField>::New());
182 }
183 else if (!tok.isCompound())
184 {
186 << "\n non-compound token following 'nonuniform'"
187 << "\n on patch " << patchName << " field "
188 << io.name() << " in file "
189 << io.objectPath() << nl
190 << exit(FatalIOError);
191 return false;
192 }
193 else if
194 (
195 tok.compoundToken().type()
196 == token::Compound<List<scalar>>::typeName
197 )
198 {
199 auto fPtr = autoPtr<scalarField>::New();
200
201 fPtr->transfer
202 (
204 (
205 tok.transferCompoundToken(is)
206 )
207 );
208
209 if (!FIELDSIZE_CHECK(fPtr->size()))
210 {
211 return false;
212 }
213
214 scalarFields_.insert(key, fPtr);
215 }
216 else if
217 (
218 tok.compoundToken().type()
219 == token::Compound<List<vector>>::typeName
220 )
221 {
222 auto fPtr = autoPtr<vectorField>::New();
223
224 fPtr->transfer
225 (
227 (
228 tok.transferCompoundToken(is)
229 )
230 );
231
232 if (!FIELDSIZE_CHECK(fPtr->size()))
233 {
234 return false;
235 }
236 vectorFields_.insert(key, fPtr);
237 }
238 else if
239 (
240 tok.compoundToken().type()
242 )
243 {
245
246 fPtr->transfer
247 (
249 (
250 tok.transferCompoundToken(is)
251 )
252 );
253
254 if (!FIELDSIZE_CHECK(fPtr->size()))
255 {
256 return false;
257 }
258
259 sphTensorFields_.insert(key, fPtr);
260 }
261 else if
262 (
263 tok.compoundToken().type()
265 )
266 {
267 auto fPtr = autoPtr<symmTensorField>::New();
268
269 fPtr->transfer
270 (
272 (
273 tok.transferCompoundToken(is)
274 )
275 );
276
277 if (!FIELDSIZE_CHECK(fPtr->size()))
278 {
279 return false;
280 }
281
282 symmTensorFields_.insert(key, fPtr);
283 }
284 else if
285 (
286 tok.compoundToken().type()
287 == token::Compound<List<tensor>>::typeName
288 )
289 {
290 auto fPtr = autoPtr<tensorField>::New();
291
292 fPtr->transfer
293 (
295 (
296 tok.transferCompoundToken(is)
297 )
298 );
299
300 if (!FIELDSIZE_CHECK(fPtr->size()))
301 {
302 return false;
303 }
304
305 tensorFields_.insert(key, fPtr);
306 }
307 else
308 {
310 << "\n unsupported compound " << tok.compoundToken()
311 << "\n on patch " << patchName << " of field "
312 << io.name() << " in file "
313 << io.objectPath() << nl
314 << exit(FatalIOError);
315 return false;
316 }
317 }
318 else if (tok.isWord("uniform"))
319 {
320 is >> tok;
321
322 if (!tok.isPunctuation())
323 {
324 scalarFields_.insert
325 (
326 key,
327 autoPtr<scalarField>::New(patchSize, tok.number())
328 );
329 }
330 else
331 {
332 // Read vector-space as list of scalars
333 is.putBack(tok);
334
335 scalarList list(is);
336
337 if (list.size() == vector::nComponents)
338 {
339 vector vs(list[0], list[1], list[2]);
340
341 vectorFields_.insert
342 (
343 key,
345 (
346 patchSize,
347 vs
348 )
349 );
350 }
351 else if (list.size() == sphericalTensor::nComponents)
352 {
353 sphericalTensor vs(list[0]);
354
355 sphTensorFields_.insert
356 (
357 key,
359 (
360 patchSize,
361 vs
362 )
363 );
364 }
365 else if (list.size() == symmTensor::nComponents)
366 {
367 symmTensor vs
368 (
369 list[0], list[1], list[2],
370 list[3], list[4],
371 list[5]
372 );
373
374 symmTensorFields_.insert
375 (
376 key,
378 (
379 patchSize,
380 vs
381 )
382 );
383 }
384 else if (list.size() == tensor::nComponents)
385 {
386 tensor vs
387 (
388 list[0], list[1], list[2],
389 list[3], list[4], list[5],
390 list[6], list[7], list[8]
391 );
392
393 tensorFields_.insert
394 (
395 key,
397 (
398 patchSize,
399 vs
400 )
401 );
402 }
403 else
404 {
406 << "\n unrecognised native type " << flatOutput(list)
407 << "\n on patch " << patchName << " of field "
408 << io.name() << " in file "
409 << io.objectPath() << nl
410 << exit(FatalIOError);
411 return false;
412 }
413 }
414 }
415
416 #undef FIELDSIZE_CHECK
417
418 return true;
419}
420
421
423(
424 const entry& e,
425 Ostream& os
426) const
427{
428 const keyType& key = e.keyword();
429
430 if
431 (
432 e.isStream()
433 && e.stream().size()
434 && e.stream()[0].isWord("nonuniform")
435 )
436 {
437 if (scalarFields_.found(key))
438 {
439 scalarFields_.cfind(key)()->writeEntry(key, os);
440 }
441 else if (vectorFields_.found(key))
442 {
443 vectorFields_.cfind(key)()->writeEntry(key, os);
444 }
445 else if (sphTensorFields_.found(key))
446 {
447 sphTensorFields_.cfind(key)()->writeEntry(key, os);
448 }
449 else if (symmTensorFields_.found(key))
450 {
451 symmTensorFields_.cfind(key)()->writeEntry(key, os);
452 }
453 else if (tensorFields_.found(key))
454 {
455 tensorFields_.cfind(key)()->writeEntry(key, os);
456 }
457 }
458 else
459 {
460 e.write(os);
461 }
462}
463
464
466(
467 Ostream& os,
468 const bool separateValue
469) const
470{
471 os.writeEntry("type", actualTypeName_);
472
473 for (const entry& dEntry : dict_)
474 {
475 const keyType& key = dEntry.keyword();
476
477 if (key == "type" || (separateValue && key == "value"))
478 {
479 // NB: "type" written first, "value" possibly separately
480 }
481 else
482 {
483 putEntry(dEntry, os);
484 }
485 }
486}
487
488
490(
491 const genericPatchFieldBase& rhs,
492 const labelList& addr
493)
494{
495 forAllIters(scalarFields_, iter)
496 {
497 const auto iter2 = rhs.scalarFields_.cfind(iter.key());
498
499 if (iter2.found())
500 {
501 (*iter)->rmap(*iter2(), addr);
502 }
503 }
504
505 forAllIters(vectorFields_, iter)
506 {
507 const auto iter2 = rhs.vectorFields_.cfind(iter.key());
508
509 if (iter2.found())
510 {
511 (*iter)->rmap(*iter2(), addr);
512 }
513 }
514
515 forAllIters(sphTensorFields_, iter)
516 {
517 const auto iter2 = rhs.sphTensorFields_.cfind(iter.key());
518
519 if (iter2.found())
520 {
521 (*iter)->rmap(*iter2(), addr);
522 }
523 }
524
525 forAllIters(symmTensorFields_, iter)
526 {
527 const auto iter2 = rhs.symmTensorFields_.cfind(iter.key());
528
529 if (iter2.found())
530 {
531 (*iter)->rmap(*iter2(), addr);
532 }
533 }
534
535 forAllIters(tensorFields_, iter)
536 {
537 const auto iter2 = rhs.tensorFields_.find(iter.key());
538
539 if (iter2.found())
540 {
541 (*iter)->rmap(*iter2(), addr);
542 }
543 }
544}
545
546
547// ************************************************************************* //
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:65
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:214
An input stream of tokens.
Definition: ITstream.H:56
void putBack(const token &tok)
Put back a token. Only a single put back is permitted.
Definition: Istream.C:70
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:239
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
bool empty() const noexcept
True if the UList is empty (ie, size() is zero)
Definition: UListI.H:427
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
virtual bool isStream() const noexcept
Return true if this entry is a stream.
Definition: entry.H:223
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:195
Generic infrastructure for reading/writing unknown patch types.
void writeGeneric(Ostream &os, const bool separateValue) const
genericPatchFieldBase()=default
Default construct, generally not useful.
void rmapGeneric(const genericPatchFieldBase &rhs, const labelList &addr)
HashPtrTable< vectorField > vectorFields_
void reportMissingEntry(const word &entryName, const word &patchName, const IOobject &io) const
FatalError for missing entry.
void putEntry(const entry &e, Ostream &os) const
Write a single entry, with lookup of hashed values.
HashPtrTable< symmTensorField > symmTensorFields_
HashPtrTable< sphericalTensorField > sphTensorFields_
void genericFatalSolveError(const word &patchName, const IOobject &io) const
HashPtrTable< tensorField > tensorFields_
void processGeneric(const label patchSize, const word &patchName, const IOobject &io, const bool separateValue)
HashPtrTable< scalarField > scalarFields_
bool processEntry(const entry &dEntry, const label patchSize, const word &patchName, const IOobject &io)
A class for handling keywords in dictionaries.
Definition: keyType.H:71
static constexpr direction nComponents
Number of components in bool is 1.
Definition: bool.H:98
virtual bool write(const bool valid=true) const
Write using setting from DB.
A templated class for holding compound tokens.
Definition: token.H:250
A token holds an item read from Istream.
Definition: token.H:69
bool isWord() const noexcept
Token is word-variant (WORD, DIRECTIVE)
Definition: tokenI.H:609
A class for handling words, derived from Foam::string.
Definition: word.H:68
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:63
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
OBJstream os(runTime.globalPath()/outputName)
#define FIELDSIZE_CHECK(fieldLen)
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:108
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:215
IOerror FatalIOError
error FatalError
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
To & dynamicCast(From &r)
Definition: typeInfo.H:88
dictionary dict
volScalarField & e
Definition: createFields.H:11
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:260