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-2023 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 "error.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 
165  // First token
166  token tok(is);
167 
168  if (tok.isWord("nonuniform"))
169  {
170  is >> tok;
171 
172  if (tok.isLabel(0))
173  {
174  // For v2006 and earlier, could have a plain untyped 0
175  // without a compound type.
176  // Just treat as scalar and hope for the best.
177  scalarFields_.insert(key, autoPtr<scalarField>::New());
178  return true;
179  }
180  else if (!tok.isCompound())
181  {
183  << "\n non-compound token following 'nonuniform'"
184  << "\n on patch " << patchName << " field "
185  << io.name() << " in file "
186  << io.objectPath() << nl
187  << exit(FatalIOError);
188  return false;
189  }
190 
191  #undef doLocalCode
192  #define doLocalCode(ValueType, Member) \
193  if (tok.isCompound<List<ValueType>>()) \
194  { \
195  auto fPtr = autoPtr<Field<ValueType>>::New(); \
196  \
197  fPtr->transfer \
198  ( \
199  tok.transferCompoundToken<List<ValueType>>(is) \
200  ); \
201  \
202  if (!checkFieldSize(fPtr->size(), patchSize, patchName, key, io)) \
203  { \
204  return false; \
205  } \
206  \
207  this->Member.insert(key, fPtr); \
208  return true; \
209  }
210 
211  //doLocalCode(label, labelFields_);
212  doLocalCode(scalar, scalarFields_);
213  doLocalCode(vector, vectorFields_);
214  doLocalCode(sphericalTensor, sphTensorFields_);
215  doLocalCode(symmTensor, symmTensorFields_);
216  doLocalCode(tensor, tensorFields_);
217  #undef doLocalCode
218 
219  // Fall-through
221  << "\n unsupported compound " << tok.compoundToken() << nl
222  << "\n on patch " << patchName << " of field "
223  << io.name() << " in file "
224  << io.objectPath() << nl
225  << exit(FatalIOError);
226  return false;
227  }
228  else if (tok.isWord("uniform"))
229  {
230  is >> tok;
231 
232  if (!tok.isPunctuation())
233  {
234  // Unfortunately cannot distinguish between
235  // labelField and scalarField...
236 
237  scalarFields_.insert
238  (
239  key,
240  autoPtr<scalarField>::New(patchSize, tok.number())
241  );
242  }
243  else
244  {
245  // Read vector-space as list of scalars
246  is.putBack(tok);
247 
248  scalarList list(is);
249 
250  if (list.size() == vector::nComponents)
251  {
252  vector vs(list[0], list[1], list[2]);
253 
254  vectorFields_.insert
255  (
256  key,
258  (
259  patchSize,
260  vs
261  )
262  );
263  }
264  else if (list.size() == sphericalTensor::nComponents)
265  {
266  sphericalTensor vs(list[0]);
267 
268  sphTensorFields_.insert
269  (
270  key,
272  (
273  patchSize,
274  vs
275  )
276  );
277  }
278  else if (list.size() == symmTensor::nComponents)
279  {
280  symmTensor vs
281  (
282  list[0], list[1], list[2],
283  list[3], list[4],
284  list[5]
285  );
286 
287  symmTensorFields_.insert
288  (
289  key,
291  (
292  patchSize,
293  vs
294  )
295  );
296  }
297  else if (list.size() == tensor::nComponents)
298  {
299  tensor vs
300  (
301  list[0], list[1], list[2],
302  list[3], list[4], list[5],
303  list[6], list[7], list[8]
304  );
305 
306  tensorFields_.insert
307  (
308  key,
310  (
311  patchSize,
312  vs
313  )
314  );
315  }
316  else
317  {
319  << "\n unrecognised native type " << flatOutput(list)
320  << "\n on patch " << patchName << " of field "
321  << io.name() << " in file "
322  << io.objectPath() << nl
323  << exit(FatalIOError);
324  return false;
325  }
326  }
327  }
328 
329  return true;
330 }
331 
332 
334 (
335  const entry& e,
336  Ostream& os
337 ) const
338 {
339  const keyType& key = e.keyword();
340 
341  if
342  (
343  e.isStream()
344  && e.stream().peek().isWord("nonuniform")
345  )
346  {
347  #undef doLocalCode
348  #define doLocalCode(ValueType, Member) \
349  { \
350  const auto iter = this->Member.cfind(key); \
351  if (iter.good()) \
352  { \
353  iter.val()->writeEntry(key, os); \
354  return; \
355  } \
356  }
357 
358  //doLocalCode(label, labelFields_);
359  doLocalCode(scalar, scalarFields_);
360  doLocalCode(vector, vectorFields_);
361  doLocalCode(sphericalTensor, sphTensorFields_);
362  doLocalCode(symmTensor, symmTensorFields_);
363  doLocalCode(tensor, tensorFields_);
364  #undef doLocalCode
365  }
366  else
367  {
368  e.write(os);
369  }
370 }
371 
372 
374 (
375  Ostream& os,
376  const bool separateValue
377 ) const
378 {
379  os.writeEntry("type", actualTypeName_);
380 
381  for (const entry& dEntry : dict_)
382  {
383  const keyType& key = dEntry.keyword();
384 
385  if (key == "type" || (separateValue && key == "value"))
386  {
387  // NB: "type" written first, "value" possibly separately
388  }
389  else
390  {
391  putEntry(dEntry, os);
392  }
393  }
394 }
395 
396 
398 (
399  const genericPatchFieldBase& rhs,
400  const labelList& addr
401 )
402 {
403  #undef doLocalCode
404  #define doLocalCode(ValueType, Member) \
405  forAllIters(this->Member, iter) \
406  { \
407  const auto iter2 = rhs.Member.cfind(iter.key()); \
408  \
409  if (iter2.good()) \
410  { \
411  iter.val()->rmap(*iter2.val(), addr); \
412  } \
413  }
414 
415  //doLocalCode(label, labelFields_);
416  doLocalCode(scalar, scalarFields_);
417  doLocalCode(vector, vectorFields_);
418  doLocalCode(sphericalTensor, sphTensorFields_);
419  doLocalCode(symmTensor, symmTensorFields_);
420  doLocalCode(tensor, tensorFields_);
421  #undef doLocalCode
422 }
423 
424 
425 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
List< scalar > scalarList
List of scalar.
Definition: scalarList.H:32
A class for handling keywords in dictionaries.
Definition: keyType.H:66
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:129
void writeGeneric(Ostream &os, const bool separateValue) const
Write all generic entries from dictionary, optionally treating the "value" entry separately.
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:195
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Tensor< scalar > tensor
Definition: symmTensor.H:57
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:321
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
bool processEntry(const entry &dEntry, const label patchSize, const word &patchName, const IOobject &io)
fileName objectPath() const
The complete path + object name.
Definition: IOobjectI.H:284
void reportMissingEntry(const word &entryName, const word &patchName, const IOobject &io) const
FatalError for missing entry.
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
const keyType & keyword() const noexcept
Return keyword.
Definition: entry.H:231
void genericFatalSolveError(const word &patchName, const IOobject &io) const
Add error message to FatalError about solving with generic condition.
SymmTensor< scalar > symmTensor
SymmTensor of scalars, i.e. SymmTensor<scalar>.
Definition: symmTensor.H:55
A class for handling words, derived from Foam::string.
Definition: word.H:63
void processGeneric(const label patchSize, const word &patchName, const IOobject &io, const bool separateValue)
Vector< scalar > vector
Definition: vector.H:57
static constexpr direction nComponents
Number of components in this vector space.
Definition: VectorSpace.H:109
void rmapGeneric(const genericPatchFieldBase &rhs, const labelList &addr)
Implementation for reverse map given patch field onto this patch field.
OBJstream os(runTime.globalPath()/outputName)
Generic infrastructure for reading/writing unknown patch types.
void putEntry(const entry &e, Ostream &os) const
Write a single entry, with lookup of hashed values.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
SphericalTensor< scalar > sphericalTensor
SphericalTensor of scalars, i.e. SphericalTensor<scalar>.
List< label > labelList
A List of labels.
Definition: List.H:62
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
static autoPtr< T > New(Args &&... args)
Construct autoPtr with forwarding arguments.
Definition: autoPtr.H:178
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
#define doLocalCode(ValueType, Member)
genericPatchFieldBase()=default
Default construct, generally not useful.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
Definition: FlatOutput.H:225
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...