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 -------------------------------------------------------------------------------
10 License
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 
28 #include "genericPatchFieldBase.H"
29 #include "messageStream.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 bool 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
52  << exit(FatalIOError);
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 // ************************************************************************* //
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::autoPtr::New
static autoPtr< T > New(Args &&... args)
Construct autoPtr of T with forwarding arguments.
Foam::Tensor< scalar >
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::SymmTensor< scalar >
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::token::Compound
A templated class for holding compound tokens.
Definition: token.H:246
Foam::entry::stream
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
Foam::genericPatchFieldBase
Generic infrastructure for reading/writing unknown patch types.
Definition: genericPatchFieldBase.H:54
Foam::genericPatchFieldBase::reportMissingEntry
void reportMissingEntry(const word &entryName, const word &patchName, const IOobject &io) const
FatalError for missing entry.
Definition: genericPatchFieldBase.C:101
Foam::entry::isStream
virtual bool isStream() const noexcept
Return true if this entry is a stream.
Definition: entry.H:223
Foam::genericPatchFieldBase::genericFatalSolveError
void genericFatalSolveError(const word &patchName, const IOobject &io) const
Definition: genericPatchFieldBase.C:85
Foam::glTF::key
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
Foam::entry::keyword
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:195
Foam::FatalIOError
IOerror FatalIOError
Foam::token
A token holds an item read from Istream.
Definition: token.H:68
Foam::dictionary::get
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Definition: dictionaryTemplates.C:107
Foam::genericPatchFieldBase::writeGeneric
void writeGeneric(Ostream &os, const bool separateValue) const
Definition: genericPatchFieldBase.C:466
Foam::genericPatchFieldBase::vectorFields_
HashPtrTable< vectorField > vectorFields_
Definition: genericPatchFieldBase.H:78
FIELDSIZE_CHECK
#define FIELDSIZE_CHECK(fieldLen)
Foam::token::isWord
bool isWord() const noexcept
Token is word-variant (WORD, DIRECTIVE)
Definition: tokenI.H:609
Foam::keyType
A class for handling keywords in dictionaries.
Definition: keyType.H:68
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:52
Foam::genericPatchFieldBase::rmapGeneric
void rmapGeneric(const genericPatchFieldBase &rhs, const labelList &addr)
Definition: genericPatchFieldBase.C:490
Foam::genericPatchFieldBase::symmTensorFields_
HashPtrTable< symmTensorField > symmTensorFields_
Definition: genericPatchFieldBase.H:80
Foam::genericPatchFieldBase::tensorFields_
HashPtrTable< tensorField > tensorFields_
Definition: genericPatchFieldBase.H:81
forAllIters
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:223
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::genericPatchFieldBase::processEntry
bool processEntry(const entry &dEntry, const label patchSize, const word &patchName, const IOobject &io)
Definition: genericPatchFieldBase.C:144
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
os
OBJstream os(runTime.globalPath()/outputName)
Foam::flatOutput
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:216
Foam::SphericalTensor< scalar >
Foam::genericPatchFieldBase::sphTensorFields_
HashPtrTable< sphericalTensorField > sphTensorFields_
Definition: genericPatchFieldBase.H:79
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
messageStream.H
Foam::genericPatchFieldBase::processGeneric
void processGeneric(const label patchSize, const word &patchName, const IOobject &io, const bool separateValue)
Definition: genericPatchFieldBase.C:120
Foam::IOobject::name
const word & name() const noexcept
Return name.
Definition: IOobjectI.H:65
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::genericPatchFieldBase::genericPatchFieldBase
genericPatchFieldBase()=default
Default construct, generally not useful.
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::Vector< scalar >
Foam::dynamicCast
To & dynamicCast(From &r)
Definition: typeInfo.H:88
Foam::genericPatchFieldBase::scalarFields_
HashPtrTable< scalarField > scalarFields_
Definition: genericPatchFieldBase.H:77
Foam::List< scalar >
Foam::Istream::putBack
void putBack(const token &tok)
Put back a token. Only a single put back is permitted.
Definition: Istream.C:70
Foam::constant::electromagnetic::e
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
Foam::genericPatchFieldBase::dict_
dictionary dict_
Definition: genericPatchFieldBase.H:75
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:236
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::IOobject::objectPath
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:214
genericPatchFieldBase.H
Foam::genericPatchFieldBase::putEntry
void putEntry(const entry &e, Ostream &os) const
Write a single entry, with lookup of hashed values.
Definition: genericPatchFieldBase.C:423
Foam::VectorSpace< Vector< scalar >, scalar, 3 >::nComponents
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:101
Foam::zero
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:62
Foam::genericPatchFieldBase::actualTypeName_
word actualTypeName_
The non-generic patch name.
Definition: genericPatchFieldBase.H:73