genericFvPatchField.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) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2019 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 "genericFvPatchField.H"
30 #include "fvPatchFieldMapper.H"
31 
32 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
33 
34 template<class Type>
36 (
37  const fvPatch& p,
39 )
40 :
42 {
44  << "Trying to construct an genericFvPatchField on patch "
45  << this->patch().name()
46  << " of field " << this->internalField().name()
47  << abort(FatalError);
48 }
49 
50 
51 template<class Type>
53 (
54  const fvPatch& p,
56  const dictionary& dict
57 )
58 :
60  actualTypeName_(dict.get<word>("type")),
61  dict_(dict)
62 {
63  const label patchSize = this->size();
64 
65  if (!dict.found("value"))
66  {
68  << nl << " Cannot find 'value' entry"
69  << " on patch " << this->patch().name()
70  << " of field " << this->internalField().name()
71  << " in file " << this->internalField().objectPath() << nl
72  << " which is required to set the"
73  " values of the generic patch field." << nl
74  << " (Actual type " << actualTypeName_ << ')' << nl << nl
75  << " Please add the 'value' entry to the write function"
76  " of the user-defined boundary-condition" << nl
77  << exit(FatalIOError);
78  }
79 
80  for (const entry& dEntry : dict_)
81  {
82  const keyType& key = dEntry.keyword();
83 
84  if
85  (
86  key == "type"
87  || key == "value"
88  || !dEntry.isStream() || dEntry.stream().empty()
89  )
90  {
91  continue;
92  }
93 
94 
95  ITstream& is = dEntry.stream();
96 
97  // Read first token
98  token firstToken(is);
99 
100  if
101  (
102  firstToken.isWord()
103  && firstToken.wordToken() == "nonuniform"
104  )
105  {
106  token fieldToken(is);
107 
108  if (!fieldToken.isCompound())
109  {
110  if
111  (
112  fieldToken.isLabel()
113  && fieldToken.labelToken() == 0
114  )
115  {
116  scalarFields_.insert(key, autoPtr<scalarField>::New());
117  }
118  else
119  {
121  << "\n token following 'nonuniform' "
122  "is not a compound"
123  << "\n on patch " << this->patch().name()
124  << " of field "
125  << this->internalField().name()
126  << " in file "
127  << this->internalField().objectPath() << nl
128  << exit(FatalIOError);
129  }
130  }
131  else if
132  (
133  fieldToken.compoundToken().type()
134  == token::Compound<List<scalar>>::typeName
135  )
136  {
137  auto fPtr = autoPtr<scalarField>::New();
138 
139  fPtr->transfer
140  (
142  (
143  fieldToken.transferCompoundToken(is)
144  )
145  );
146 
147  if (fPtr->size() != patchSize)
148  {
150  << "\n size of field " << key
151  << " (" << fPtr->size() << ')'
152  << " is not the same size as the patch ("
153  << patchSize << ')'
154  << "\n on patch " << this->patch().name()
155  << " of field "
156  << this->internalField().name()
157  << " in file "
158  << this->internalField().objectPath() << nl
159  << exit(FatalIOError);
160  }
161 
162  scalarFields_.insert(key, fPtr);
163  }
164  else if
165  (
166  fieldToken.compoundToken().type()
167  == token::Compound<List<vector>>::typeName
168  )
169  {
170  auto fPtr = autoPtr<vectorField>::New();
171 
172  fPtr->transfer
173  (
175  (
176  fieldToken.transferCompoundToken(is)
177  )
178  );
179 
180  if (fPtr->size() != patchSize)
181  {
183  << "\n size of field " << key
184  << " (" << fPtr->size() << ')'
185  << " is not the same size as the patch ("
186  << patchSize << ')'
187  << "\n on patch " << this->patch().name()
188  << " of field "
189  << this->internalField().name()
190  << " in file "
191  << this->internalField().objectPath() << nl
192  << exit(FatalIOError);
193  }
194 
195  vectorFields_.insert(key, fPtr);
196  }
197  else if
198  (
199  fieldToken.compoundToken().type()
201  )
202  {
204 
205  fPtr->transfer
206  (
208  (
209  fieldToken.transferCompoundToken(is)
210  )
211  );
212 
213  if (fPtr->size() != patchSize)
214  {
216  << "\n size of field " << key
217  << " (" << fPtr->size() << ')'
218  << " is not the same size as the patch ("
219  << patchSize << ')'
220  << "\n on patch " << this->patch().name()
221  << " of field "
222  << this->internalField().name()
223  << " in file "
224  << this->internalField().objectPath() << nl
225  << exit(FatalIOError);
226  }
227 
228  sphTensorFields_.insert(key, fPtr);
229  }
230  else if
231  (
232  fieldToken.compoundToken().type()
234  )
235  {
236  auto fPtr = autoPtr<symmTensorField>::New();
237 
238  fPtr->transfer
239  (
241  (
242  fieldToken.transferCompoundToken(is)
243  )
244  );
245 
246  if (fPtr->size() != patchSize)
247  {
249  << "\n size of field " << key
250  << " (" << fPtr->size() << ')'
251  << " is not the same size as the patch ("
252  << patchSize << ')'
253  << "\n on patch " << this->patch().name()
254  << " of field "
255  << this->internalField().name()
256  << " in file "
257  << this->internalField().objectPath() << nl
258  << exit(FatalIOError);
259  }
260 
261  symmTensorFields_.insert(key, fPtr);
262  }
263  else if
264  (
265  fieldToken.compoundToken().type()
266  == token::Compound<List<tensor>>::typeName
267  )
268  {
269  auto fPtr = autoPtr<tensorField>::New();
270 
271  fPtr->transfer
272  (
274  (
275  fieldToken.transferCompoundToken(is)
276  )
277  );
278 
279  if (fPtr->size() != patchSize)
280  {
282  << "\n size of field " << key
283  << " (" << fPtr->size() << ')'
284  << " is not the same size as the patch ("
285  << patchSize << ')'
286  << "\n on patch " << this->patch().name()
287  << " of field "
288  << this->internalField().name()
289  << " in file "
290  << this->internalField().objectPath() << nl
291  << exit(FatalIOError);
292  }
293 
294  tensorFields_.insert(key, fPtr);
295  }
296  else
297  {
299  << "\n compound " << fieldToken.compoundToken()
300  << " not supported"
301  << "\n on patch " << this->patch().name()
302  << " of field "
303  << this->internalField().name()
304  << " in file "
305  << this->internalField().objectPath() << nl
306  << exit(FatalIOError);
307  }
308  }
309  else if
310  (
311  firstToken.isWord()
312  && firstToken.wordToken() == "uniform"
313  )
314  {
315  token fieldToken(is);
316 
317  if (!fieldToken.isPunctuation())
318  {
319  scalarFields_.insert
320  (
321  key,
323  (
324  patchSize,
325  fieldToken.number()
326  )
327  );
328  }
329  else
330  {
331  // Read as scalarList.
332  is.putBack(fieldToken);
333 
334  scalarList l(is);
335 
336  if (l.size() == vector::nComponents)
337  {
338  vector vs(l[0], l[1], l[2]);
339 
340  vectorFields_.insert
341  (
342  key,
344  (
345  patchSize,
346  vs
347  )
348  );
349  }
350  else if (l.size() == sphericalTensor::nComponents)
351  {
352  sphericalTensor vs(l[0]);
353 
354  sphTensorFields_.insert
355  (
356  key,
358  (
359  patchSize,
360  vs
361  )
362  );
363  }
364  else if (l.size() == symmTensor::nComponents)
365  {
366  symmTensor vs(l[0], l[1], l[2], l[3], l[4], l[5]);
367 
368  symmTensorFields_.insert
369  (
370  key,
372  (
373  patchSize,
374  vs
375  )
376  );
377  }
378  else if (l.size() == tensor::nComponents)
379  {
380  tensor vs
381  (
382  l[0], l[1], l[2],
383  l[3], l[4], l[5],
384  l[6], l[7], l[8]
385  );
386 
387  tensorFields_.insert
388  (
389  key,
391  (
392  patchSize,
393  vs
394  )
395  );
396  }
397  else
398  {
400  << "\n unrecognised native type " << l
401  << "\n on patch " << this->patch().name()
402  << " of field "
403  << this->internalField().name()
404  << " in file "
405  << this->internalField().objectPath() << nl
406  << exit(FatalIOError);
407  }
408  }
409  }
410  }
411 }
412 
413 
414 template<class Type>
416 (
417  const genericFvPatchField<Type>& ptf,
418  const fvPatch& p,
420  const fvPatchFieldMapper& mapper
421 )
422 :
423  calculatedFvPatchField<Type>(ptf, p, iF, mapper),
424  actualTypeName_(ptf.actualTypeName_),
425  dict_(ptf.dict_)
426 {
427  forAllConstIters(ptf.scalarFields_, iter)
428  {
429  scalarFields_.insert
430  (
431  iter.key(),
432  autoPtr<scalarField>::New(*iter(), mapper)
433  );
434  }
435 
436  forAllConstIters(ptf.vectorFields_, iter)
437  {
438  vectorFields_.insert
439  (
440  iter.key(),
441  autoPtr<vectorField>::New(*iter(), mapper)
442  );
443  }
444 
445  forAllConstIters(ptf.sphTensorFields_, iter)
446  {
447  sphTensorFields_.insert
448  (
449  iter.key(),
450  autoPtr<sphericalTensorField>::New(*iter(), mapper)
451  );
452  }
453 
454  forAllConstIters(ptf.symmTensorFields_, iter)
455  {
456  symmTensorFields_.insert
457  (
458  iter.key(),
459  autoPtr<symmTensorField>::New(*iter(), mapper)
460  );
461  }
462 
463  forAllConstIters(ptf.tensorFields_, iter)
464  {
465  tensorFields_.insert
466  (
467  iter.key(),
468  autoPtr<tensorField>::New(*iter(), mapper)
469  );
470  }
471 }
472 
473 
474 template<class Type>
476 (
477  const genericFvPatchField<Type>& ptf
478 )
479 :
481  actualTypeName_(ptf.actualTypeName_),
482  dict_(ptf.dict_),
483  scalarFields_(ptf.scalarFields_),
484  vectorFields_(ptf.vectorFields_),
485  sphTensorFields_(ptf.sphTensorFields_),
486  symmTensorFields_(ptf.symmTensorFields_),
487  tensorFields_(ptf.tensorFields_)
488 {}
489 
490 
491 template<class Type>
493 (
494  const genericFvPatchField<Type>& ptf,
496 )
497 :
499  actualTypeName_(ptf.actualTypeName_),
500  dict_(ptf.dict_),
501  scalarFields_(ptf.scalarFields_),
502  vectorFields_(ptf.vectorFields_),
503  sphTensorFields_(ptf.sphTensorFields_),
504  symmTensorFields_(ptf.symmTensorFields_),
505  tensorFields_(ptf.tensorFields_)
506 {}
507 
508 
509 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
510 
511 template<class Type>
513 (
514  const fvPatchFieldMapper& m
515 )
516 {
518 
519  forAllIters(scalarFields_, iter)
520  {
521  (*iter)->autoMap(m);
522  }
523 
524  forAllIters(vectorFields_, iter)
525  {
526  (*iter)->autoMap(m);
527  }
528 
529  forAllIters(sphTensorFields_, iter)
530  {
531  (*iter)->autoMap(m);
532  }
533 
534  forAllIters(symmTensorFields_, iter)
535  {
536  (*iter)->autoMap(m);
537  }
538 
539  forAllIters(tensorFields_, iter)
540  {
541  (*iter)->autoMap(m);
542  }
543 }
544 
545 
546 template<class Type>
548 (
549  const fvPatchField<Type>& ptf,
550  const labelList& addr
551 )
552 {
554 
555  const genericFvPatchField<Type>& dptf =
556  refCast<const genericFvPatchField<Type>>(ptf);
557 
558  forAllIters(scalarFields_, iter)
559  {
560  const auto iter2 = dptf.scalarFields_.cfind(iter.key());
561 
562  if (iter2.found())
563  {
564  (*iter)->rmap(*iter2(), addr);
565  }
566  }
567 
568  forAllIters(vectorFields_, iter)
569  {
570  const auto iter2 = dptf.vectorFields_.find(iter.key());
571 
572  if (iter2.found())
573  {
574  (*iter)->rmap(*iter2(), addr);
575  }
576  }
577 
578  forAllIters(sphTensorFields_, iter)
579  {
580  const auto iter2 = dptf.sphTensorFields_.find(iter.key());
581 
582  if (iter2.found())
583  {
584  (*iter)->rmap(*iter2(), addr);
585  }
586  }
587 
588  forAllIters(symmTensorFields_, iter)
589  {
590  const auto iter2 = dptf.symmTensorFields_.find(iter.key());
591 
592  if (iter2.found())
593  {
594  (*iter)->rmap(*iter2(), addr);
595  }
596  }
597 
598  forAllIters(tensorFields_, iter)
599  {
600  const auto iter2 = dptf.tensorFields_.find(iter.key());
601 
602  if (iter2.found())
603  {
604  (*iter)->rmap(*iter2(), addr);
605  }
606  }
607 }
608 
609 
610 template<class Type>
613 (
614  const tmp<scalarField>&
615 ) const
616 {
618  << "cannot be called for a genericFvPatchField"
619  " (actual type " << actualTypeName_ << ")"
620  << "\n on patch " << this->patch().name()
621  << " of field " << this->internalField().name()
622  << " in file " << this->internalField().objectPath()
623  << "\n You are probably trying to solve for a field with a "
624  "generic boundary condition."
625  << abort(FatalError);
626 
627  return *this;
628 }
629 
630 
631 template<class Type>
634 (
635  const tmp<scalarField>&
636 ) const
637 {
639  << "cannot be called for a genericFvPatchField"
640  " (actual type " << actualTypeName_ << ")"
641  << "\n on patch " << this->patch().name()
642  << " of field " << this->internalField().name()
643  << " in file " << this->internalField().objectPath()
644  << "\n You are probably trying to solve for a field with a "
645  "generic boundary condition."
646  << abort(FatalError);
647 
648  return *this;
649 }
650 
651 
652 template<class Type>
655 {
657  << "cannot be called for a genericFvPatchField"
658  " (actual type " << actualTypeName_ << ")"
659  << "\n on patch " << this->patch().name()
660  << " of field " << this->internalField().name()
661  << " in file " << this->internalField().objectPath()
662  << "\n You are probably trying to solve for a field with a "
663  "generic boundary condition."
664  << abort(FatalError);
665 
666  return *this;
667 }
668 
669 template<class Type>
672 {
674  << "cannot be called for a genericFvPatchField"
675  " (actual type " << actualTypeName_ << ")"
676  << "\n on patch " << this->patch().name()
677  << " of field " << this->internalField().name()
678  << " in file " << this->internalField().objectPath()
679  << "\n You are probably trying to solve for a field with a "
680  "generic boundary condition."
681  << abort(FatalError);
682 
683  return *this;
684 }
685 
686 
687 template<class Type>
689 {
690  return actualTypeName_;
691 }
692 
693 
694 template<class Type>
696 {
697  os.writeEntry("type", actualTypeName_);
698 
699  for (const entry& dEntry : dict_)
700  {
701  const keyType& key = dEntry.keyword();
702 
703  if (key == "type" || key == "value")
704  {
705  continue;
706  }
707  else if
708  (
709  dEntry.isStream()
710  && dEntry.stream().size()
711  && dEntry.stream()[0].isWord()
712  && dEntry.stream()[0].wordToken() == "nonuniform"
713  )
714  {
715  if (scalarFields_.found(key))
716  {
717  scalarFields_.cfind(key)()->writeEntry(key, os);
718  }
719  else if (vectorFields_.found(key))
720  {
721  vectorFields_.cfind(key)()->writeEntry(key, os);
722  }
723  else if (sphTensorFields_.found(key))
724  {
725  sphTensorFields_.cfind(key)()->writeEntry(key, os);
726  }
727  else if (symmTensorFields_.found(key))
728  {
729  symmTensorFields_.cfind(key)()->writeEntry(key, os);
730  }
731  else if (tensorFields_.found(key))
732  {
733  tensorFields_.cfind(key)()->writeEntry(key, os);
734  }
735  }
736  else
737  {
738  dEntry.write(os);
739  }
740  }
741 
742  this->writeEntry("value", os);
743 }
744 
745 
746 // ************************************************************************* //
Foam::fvPatchField
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Definition: volSurfaceMapping.H:50
Foam::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
Foam::genericFvPatchField
This boundary condition provides a generic version of the calculated condition, useful as a fallback ...
Definition: genericFvPatchField.H:58
Foam::genericFvPatchField::gradientInternalCoeffs
tmp< Field< Type > > gradientInternalCoeffs() const
Return the matrix diagonal coefficients corresponding to the.
Definition: genericFvPatchField.C:654
Foam::Tensor< scalar >
Foam::token::labelToken
label labelToken() const
Return label value.
Definition: tokenI.H:487
Foam::SymmTensor< scalar >
p
volScalarField & p
Definition: createFieldRefs.H:8
Foam::genericFvPatchField::genericFvPatchField
genericFvPatchField(const fvPatch &, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
Definition: genericFvPatchField.C:36
Foam::token::isLabel
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:481
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:62
Foam::token::Compound
A templated class for holding compound tokens.
Definition: token.H:225
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::FatalIOError
IOerror FatalIOError
fvPatchFieldMapper.H
Foam::token
A token holds an item read from Istream.
Definition: token.H:68
Foam::token::compoundToken
const compound & compoundToken() const
Read access for compound token.
Definition: tokenI.H:676
Foam::token::isWord
bool isWord() const noexcept
Token is WORD or DIRECTIVE word.
Definition: tokenI.H:583
Foam::keyType
A class for handling keywords in dictionaries.
Definition: keyType.H:60
Foam::token::number
scalar number() const
Return label, float or double value.
Definition: tokenI.H:567
Foam::ITstream
An input stream of tokens.
Definition: ITstream.H:55
Foam::fvPatch
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:65
Foam::token::isPunctuation
bool isPunctuation() const noexcept
Token is PUNCTUATION.
Definition: tokenI.H:453
Foam::genericFvPatchField::rmap
virtual void rmap(const fvPatchField< Type > &, const labelList &)
Reverse map the given fvPatchField onto this fvPatchField.
Definition: genericFvPatchField.C:548
genericFvPatchField.H
Foam::genericFvPatchField::write
virtual void write(Ostream &) const
Write.
Definition: genericFvPatchField.C:695
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::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:121
Foam::calculatedFvPatchField
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
Definition: calculatedFvPatchField.H:66
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:144
Foam::token::transferCompoundToken
compound & transferCompoundToken()
Return reference to compound and mark internally as released.
Definition: token.C:90
Foam::SphericalTensor< scalar >
Foam::token::wordToken
const word & wordToken() const
Return const reference to the word contents.
Definition: tokenI.H:599
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
Foam::genericFvPatchField::valueInternalCoeffs
virtual tmp< Field< Type > > valueInternalCoeffs(const tmp< scalarField > &) const
Return the matrix diagonal coefficients corresponding to the.
Definition: genericFvPatchField.C:613
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:381
Foam::genericFvPatchField::gradientBoundaryCoeffs
tmp< Field< Type > > gradientBoundaryCoeffs() const
Return the matrix source coefficients corresponding to the.
Definition: genericFvPatchField.C:671
Foam::nl
constexpr char nl
Definition: Ostream.H:385
forAllConstIters
forAllConstIters(mixture.phases(), phase)
Definition: pEqn.H:28
Foam::foamVersion::patch
const std::string patch
OpenFOAM patch number as a std::string.
Foam::Vector< scalar >
Foam::dynamicCast
To & dynamicCast(From &r)
Definition: typeInfo.H:88
Foam::List< scalar >
Foam::genericFvPatchField::actualType
const word & actualType() const
Return the actual type.
Definition: genericFvPatchField.C:688
Foam::Istream::putBack
void putBack(const token &tok)
Put back token.
Definition: Istream.C:53
Foam::genericFvPatchField::valueBoundaryCoeffs
virtual tmp< Field< Type > > valueBoundaryCoeffs(const tmp< scalarField > &) const
Return the matrix source coefficients corresponding to the.
Definition: genericFvPatchField.C:634
Foam::Ostream::writeEntry
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:232
Foam::token::isCompound
bool isCompound() const noexcept
Token is COMPOUND.
Definition: tokenI.H:670
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:401
Foam::fvPatchFieldMapper
Foam::fvPatchFieldMapper.
Definition: fvPatchFieldMapper.H:47
Foam::genericFvPatchField::autoMap
virtual void autoMap(const fvPatchFieldMapper &)
Map (and resize as needed) from self given a mapping object.
Definition: genericFvPatchField.C:513
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:56
Foam::DimensionedField
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: DimensionedField.H:54