genericFvsPatchField.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) 2019 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 "genericFvsPatchField.H"
29 #include "fvPatchFieldMapper.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
33 template<class Type>
35 (
36  const fvPatch& p,
38 )
39 :
41 {
43  << "Trying to construct an genericFvsPatchField on patch "
44  << this->patch().name()
45  << " of field " << this->internalField().name()
46  << abort(FatalError);
47 }
48 
49 
50 template<class Type>
52 (
53  const fvPatch& p,
55  const dictionary& dict
56 )
57 :
59  actualTypeName_(dict.get<word>("type")),
60  dict_(dict)
61 {
62  const label patchSize = this->size();
63 
64  if (!dict.found("value"))
65  {
67  << nl << " Cannot find 'value' entry"
68  << " on patch " << this->patch().name()
69  << " of field " << this->internalField().name()
70  << " in file " << this->internalField().objectPath() << nl
71  << " which is required to set the"
72  " values of the generic patch field." << nl
73  << " (Actual type " << actualTypeName_ << ')' << nl << nl
74  << " Please add the 'value' entry to the write function"
75  " of the user-defined boundary-condition" << nl
76  << exit(FatalIOError);
77  }
78 
79  for (const entry& dEntry : dict_)
80  {
81  const keyType& key = dEntry.keyword();
82 
83  if
84  (
85  key == "type"
86  || key == "value"
87  || !dEntry.isStream() || dEntry.stream().empty()
88  )
89  {
90  continue;
91  }
92 
93 
94  ITstream& is = dEntry.stream();
95 
96  // Read first token
97  token firstToken(is);
98 
99  if
100  (
101  firstToken.isWord()
102  && firstToken.wordToken() == "nonuniform"
103  )
104  {
105  token fieldToken(is);
106 
107  if (!fieldToken.isCompound())
108  {
109  if
110  (
111  fieldToken.isLabel()
112  && fieldToken.labelToken() == 0
113  )
114  {
115  scalarFields_.insert(key, autoPtr<scalarField>::New());
116  }
117  else
118  {
120  << "\n token following 'nonuniform' "
121  "is not a compound"
122  << "\n on patch " << this->patch().name()
123  << " of field "
124  << this->internalField().name()
125  << " in file "
126  << this->internalField().objectPath() << nl
127  << exit(FatalIOError);
128  }
129  }
130  else if
131  (
132  fieldToken.compoundToken().type()
133  == token::Compound<List<scalar>>::typeName
134  )
135  {
136  auto fPtr = autoPtr<scalarField>::New();
137 
138  fPtr->transfer
139  (
141  (
142  fieldToken.transferCompoundToken(is)
143  )
144  );
145 
146  if (fPtr->size() != patchSize)
147  {
149  << "\n size of field " << key
150  << " (" << fPtr->size() << ')'
151  << " is not the same size as the patch ("
152  << patchSize << ')'
153  << "\n on patch " << this->patch().name()
154  << " of field "
155  << this->internalField().name()
156  << " in file "
157  << this->internalField().objectPath() << nl
158  << exit(FatalIOError);
159  }
160 
161  scalarFields_.insert(key, fPtr);
162  }
163  else if
164  (
165  fieldToken.compoundToken().type()
166  == token::Compound<List<vector>>::typeName
167  )
168  {
169  auto fPtr = autoPtr<vectorField>::New();
170 
171  fPtr->transfer
172  (
174  (
175  fieldToken.transferCompoundToken(is)
176  )
177  );
178 
179  if (fPtr->size() != patchSize)
180  {
182  << "\n size of field " << key
183  << " (" << fPtr->size() << ')'
184  << " is not the same size as the patch ("
185  << patchSize << ')'
186  << "\n on patch " << this->patch().name()
187  << " of field "
188  << this->internalField().name()
189  << " in file "
190  << this->internalField().objectPath() << nl
191  << exit(FatalIOError);
192  }
193 
194  vectorFields_.insert(key, fPtr);
195  }
196  else if
197  (
198  fieldToken.compoundToken().type()
200  )
201  {
203 
204  fPtr->transfer
205  (
207  (
208  fieldToken.transferCompoundToken(is)
209  )
210  );
211 
212  if (fPtr->size() != patchSize)
213  {
215  << "\n size of field " << key
216  << " (" << fPtr->size() << ')'
217  << " is not the same size as the patch ("
218  << patchSize << ')'
219  << "\n on patch " << this->patch().name()
220  << " of field "
221  << this->internalField().name()
222  << " in file "
223  << this->internalField().objectPath() << nl
224  << exit(FatalIOError);
225  }
226 
227  sphTensorFields_.insert(key, fPtr);
228  }
229  else if
230  (
231  fieldToken.compoundToken().type()
233  )
234  {
235  auto fPtr = autoPtr<symmTensorField>::New();
236 
237  fPtr->transfer
238  (
240  (
241  fieldToken.transferCompoundToken(is)
242  )
243  );
244 
245  if (fPtr->size() != patchSize)
246  {
248  << "\n size of field " << key
249  << " (" << fPtr->size() << ')'
250  << " is not the same size as the patch ("
251  << patchSize << ')'
252  << "\n on patch " << this->patch().name()
253  << " of field "
254  << this->internalField().name()
255  << " in file "
256  << this->internalField().objectPath() << nl
257  << exit(FatalIOError);
258  }
259 
260  symmTensorFields_.insert(key, fPtr);
261  }
262  else if
263  (
264  fieldToken.compoundToken().type()
265  == token::Compound<List<tensor>>::typeName
266  )
267  {
268  auto fPtr = autoPtr<tensorField>::New();
269 
270  fPtr->transfer
271  (
273  (
274  fieldToken.transferCompoundToken(is)
275  )
276  );
277 
278  if (fPtr->size() != patchSize)
279  {
281  << "\n size of field " << key
282  << " (" << fPtr->size() << ')'
283  << " is not the same size as the patch ("
284  << patchSize << ')'
285  << "\n on patch " << this->patch().name()
286  << " of field "
287  << this->internalField().name()
288  << " in file "
289  << this->internalField().objectPath() << nl
290  << exit(FatalIOError);
291  }
292 
293  tensorFields_.insert(key, fPtr);
294  }
295  else
296  {
298  << "\n compound " << fieldToken.compoundToken()
299  << " not supported"
300  << "\n on patch " << this->patch().name()
301  << " of field "
302  << this->internalField().name()
303  << " in file "
304  << this->internalField().objectPath() << nl
305  << exit(FatalIOError);
306  }
307  }
308  else if
309  (
310  firstToken.isWord()
311  && firstToken.wordToken() == "uniform"
312  )
313  {
314  token fieldToken(is);
315 
316  if (!fieldToken.isPunctuation())
317  {
318  scalarFields_.insert
319  (
320  key,
322  (
323  patchSize,
324  fieldToken.number()
325  )
326  );
327  }
328  else
329  {
330  // Read as scalarList.
331  is.putBack(fieldToken);
332 
333  scalarList l(is);
334 
335  if (l.size() == vector::nComponents)
336  {
337  vector vs(l[0], l[1], l[2]);
338 
339  vectorFields_.insert
340  (
341  key,
343  (
344  patchSize,
345  vs
346  )
347  );
348  }
349  else if (l.size() == sphericalTensor::nComponents)
350  {
351  sphericalTensor vs(l[0]);
352 
353  sphTensorFields_.insert
354  (
355  key,
357  (
358  patchSize,
359  vs
360  )
361  );
362  }
363  else if (l.size() == symmTensor::nComponents)
364  {
365  symmTensor vs(l[0], l[1], l[2], l[3], l[4], l[5]);
366 
367  symmTensorFields_.insert
368  (
369  key,
371  (
372  patchSize,
373  vs
374  )
375  );
376  }
377  else if (l.size() == tensor::nComponents)
378  {
379  tensor vs
380  (
381  l[0], l[1], l[2],
382  l[3], l[4], l[5],
383  l[6], l[7], l[8]
384  );
385 
386  tensorFields_.insert
387  (
388  key,
390  (
391  patchSize,
392  vs
393  )
394  );
395  }
396  else
397  {
399  << "\n unrecognised native type " << l
400  << "\n on patch " << this->patch().name()
401  << " of field "
402  << this->internalField().name()
403  << " in file "
404  << this->internalField().objectPath() << nl
405  << exit(FatalIOError);
406  }
407  }
408  }
409  }
410 }
411 
412 
413 template<class Type>
415 (
416  const genericFvsPatchField<Type>& ptf,
417  const fvPatch& p,
419  const fvPatchFieldMapper& mapper
420 )
421 :
422  calculatedFvsPatchField<Type>(ptf, p, iF, mapper),
423  actualTypeName_(ptf.actualTypeName_),
424  dict_(ptf.dict_)
425 {
426  forAllConstIters(ptf.scalarFields_, iter)
427  {
428  scalarFields_.insert
429  (
430  iter.key(),
431  autoPtr<scalarField>::New(*iter(), mapper)
432  );
433  }
434 
435  forAllConstIters(ptf.vectorFields_, iter)
436  {
437  vectorFields_.insert
438  (
439  iter.key(),
440  autoPtr<vectorField>::New(*iter(), mapper)
441  );
442  }
443 
444  forAllConstIters(ptf.sphTensorFields_, iter)
445  {
446  sphTensorFields_.insert
447  (
448  iter.key(),
449  autoPtr<sphericalTensorField>::New(*iter(), mapper)
450  );
451  }
452 
453  forAllConstIters(ptf.symmTensorFields_, iter)
454  {
455  symmTensorFields_.insert
456  (
457  iter.key(),
458  autoPtr<symmTensorField>::New(*iter(), mapper)
459  );
460  }
461 
462  forAllConstIters(ptf.tensorFields_, iter)
463  {
464  tensorFields_.insert
465  (
466  iter.key(),
467  autoPtr<tensorField>::New(*iter(), mapper)
468  );
469  }
470 }
471 
472 
473 template<class Type>
475 (
476  const genericFvsPatchField<Type>& ptf
477 )
478 :
480  actualTypeName_(ptf.actualTypeName_),
481  dict_(ptf.dict_),
482  scalarFields_(ptf.scalarFields_),
483  vectorFields_(ptf.vectorFields_),
484  sphTensorFields_(ptf.sphTensorFields_),
485  symmTensorFields_(ptf.symmTensorFields_),
486  tensorFields_(ptf.tensorFields_)
487 {}
488 
489 
490 template<class Type>
492 (
493  const genericFvsPatchField<Type>& ptf,
495 )
496 :
498  actualTypeName_(ptf.actualTypeName_),
499  dict_(ptf.dict_),
500  scalarFields_(ptf.scalarFields_),
501  vectorFields_(ptf.vectorFields_),
502  sphTensorFields_(ptf.sphTensorFields_),
503  symmTensorFields_(ptf.symmTensorFields_),
504  tensorFields_(ptf.tensorFields_)
505 {}
506 
507 
508 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
509 
510 template<class Type>
512 (
513  const fvPatchFieldMapper& m
514 )
515 {
517 
518  forAllIters(scalarFields_, iter)
519  {
520  (*iter)->autoMap(m);
521  }
522 
523  forAllIters(vectorFields_, iter)
524  {
525  (*iter)->autoMap(m);
526  }
527 
528  forAllIters(sphTensorFields_, iter)
529  {
530  (*iter)->autoMap(m);
531  }
532 
533  forAllIters(symmTensorFields_, iter)
534  {
535  (*iter)->autoMap(m);
536  }
537 
538  forAllIters(tensorFields_, iter)
539  {
540  (*iter)->autoMap(m);
541  }
542 }
543 
544 
545 template<class Type>
547 (
548  const fvsPatchField<Type>& ptf,
549  const labelList& addr
550 )
551 {
553 
554  const genericFvsPatchField<Type>& dptf =
555  refCast<const genericFvsPatchField<Type>>(ptf);
556 
557  forAllIters(scalarFields_, iter)
558  {
559  const auto iter2 = dptf.scalarFields_.cfind(iter.key());
560 
561  if (iter2.found())
562  {
563  (*iter)->rmap(*iter2(), addr);
564  }
565  }
566 
567  forAllIters(vectorFields_, iter)
568  {
569  const auto iter2 = dptf.vectorFields_.find(iter.key());
570 
571  if (iter2.found())
572  {
573  (*iter)->rmap(*iter2(), addr);
574  }
575  }
576 
577  forAllIters(sphTensorFields_, iter)
578  {
579  const auto iter2 = dptf.sphTensorFields_.find(iter.key());
580 
581  if (iter2.found())
582  {
583  (*iter)->rmap(*iter2(), addr);
584  }
585  }
586 
587  forAllIters(symmTensorFields_, iter)
588  {
589  const auto iter2 = dptf.symmTensorFields_.find(iter.key());
590 
591  if (iter2.found())
592  {
593  (*iter)->rmap(*iter2(), addr);
594  }
595  }
596 
597  forAllIters(tensorFields_, iter)
598  {
599  const auto iter2 = dptf.tensorFields_.find(iter.key());
600 
601  if (iter2.found())
602  {
603  (*iter)->rmap(*iter2(), addr);
604  }
605  }
606 }
607 
608 
609 template<class Type>
612 (
613  const tmp<scalarField>&
614 ) const
615 {
617  << "cannot be called for a genericFvsPatchField"
618  " (actual type " << actualTypeName_ << ")"
619  << "\n on patch " << this->patch().name()
620  << " of field " << this->internalField().name()
621  << " in file " << this->internalField().objectPath()
622  << "\n You are probably trying to solve for a field with a "
623  "generic boundary condition."
624  << abort(FatalError);
625 
626  return *this;
627 }
628 
629 
630 template<class Type>
633 (
634  const tmp<scalarField>&
635 ) const
636 {
638  << "cannot be called for a genericFvsPatchField"
639  " (actual type " << actualTypeName_ << ")"
640  << "\n on patch " << this->patch().name()
641  << " of field " << this->internalField().name()
642  << " in file " << this->internalField().objectPath()
643  << "\n You are probably trying to solve for a field with a "
644  "generic boundary condition."
645  << abort(FatalError);
646 
647  return *this;
648 }
649 
650 
651 template<class Type>
654 {
656  << "cannot be called for a genericFvsPatchField"
657  " (actual type " << actualTypeName_ << ")"
658  << "\n on patch " << this->patch().name()
659  << " of field " << this->internalField().name()
660  << " in file " << this->internalField().objectPath()
661  << "\n You are probably trying to solve for a field with a "
662  "generic boundary condition."
663  << abort(FatalError);
664 
665  return *this;
666 }
667 
668 template<class Type>
671 {
673  << "cannot be called for a genericFvsPatchField"
674  " (actual type " << actualTypeName_ << ")"
675  << "\n on patch " << this->patch().name()
676  << " of field " << this->internalField().name()
677  << " in file " << this->internalField().objectPath()
678  << "\n You are probably trying to solve for a field with a "
679  "generic boundary condition."
680  << abort(FatalError);
681 
682  return *this;
683 }
684 
685 
686 template<class Type>
688 {
689  return actualTypeName_;
690 }
691 
692 
693 template<class Type>
695 {
696  os.writeEntry("type", actualTypeName_);
697 
698  for (const entry& dEntry : dict_)
699  {
700  const keyType& key = dEntry.keyword();
701 
702  if (key == "type" || key == "value")
703  {
704  // NB: "type" written first, "value" written last
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::entry
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:67
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::token::isLabel
bool isLabel() const noexcept
Token is LABEL.
Definition: tokenI.H:481
Foam::genericFvsPatchField
This boundary condition provides a generic version of the calculated condition, useful as a fallback ...
Definition: genericFvsPatchField.H:57
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::genericFvsPatchField::valueBoundaryCoeffs
virtual tmp< Field< Type > > valueBoundaryCoeffs(const tmp< scalarField > &) const
Return the matrix source coefficients corresponding to the.
Definition: genericFvsPatchField.C:633
Foam::fvsPatchField
An abstract base class with a fat-interface to all derived classes covering all possible ways in whic...
Definition: fvsPatchField.H:68
Foam::genericFvsPatchField::actualType
const word & actualType() const
Return the actual type.
Definition: genericFvsPatchField.C:687
Foam::calculatedFvsPatchField
Foam::calculatedFvsPatchField.
Definition: calculatedFvsPatchField.H:51
Foam::genericFvsPatchField::gradientInternalCoeffs
tmp< Field< Type > > gradientInternalCoeffs() const
Return the matrix diagonal coefficients corresponding to the.
Definition: genericFvsPatchField.C:653
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
genericFvsPatchField.H
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::genericFvsPatchField::gradientBoundaryCoeffs
tmp< Field< Type > > gradientBoundaryCoeffs() const
Return the matrix source coefficients corresponding to the.
Definition: genericFvsPatchField.C:670
Foam::genericFvsPatchField::write
virtual void write(Ostream &) const
Write.
Definition: genericFvsPatchField.C:694
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::genericFvsPatchField::valueInternalCoeffs
virtual tmp< Field< Type > > valueInternalCoeffs(const tmp< scalarField > &) const
Return the matrix diagonal coefficients corresponding to the.
Definition: genericFvsPatchField.C:612
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
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::genericFvsPatchField::rmap
virtual void rmap(const fvsPatchField< Type > &, const labelList &)
Reverse map the given fvsPatchField onto this fvsPatchField.
Definition: genericFvsPatchField.C:547
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::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::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::genericFvsPatchField::autoMap
virtual void autoMap(const fvPatchFieldMapper &)
Map (and resize as needed) from self given a mapping object.
Definition: genericFvsPatchField.C:512
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::Istream::putBack
void putBack(const token &tok)
Put back token.
Definition: Istream.C:53
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
Foam::genericFvsPatchField::genericFvsPatchField
genericFvsPatchField(const fvPatch &, const DimensionedField< Type, surfaceMesh > &)
Construct from patch and internal field.
Definition: genericFvsPatchField.C:35
FatalIOErrorInFunction
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:401
Foam::fvPatchFieldMapper
Foam::fvPatchFieldMapper.
Definition: fvPatchFieldMapper.H:47
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