exprMixedFvPatchField.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) 2009-2018 Bernhard Gschaider
9  Copyright (C) 2019-2021 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 #include "exprMixedFvPatchField.H"
29 #include "dictionaryContent.H"
30 
31 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
32 
33 template<class Type>
35 {
36  if (expressions::patchExprFieldBase::debug_ && !debug)
37  {
38  debug = 1;
39  }
40 }
41 
42 
43 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44 
45 template<class Type>
47 (
48  const fvPatch& p,
50 )
51 :
52  parent_bctype(p, iF),
53  expressions::patchExprFieldBase(),
54  dict_(),
55  driver_(this->patch())
56 {
57  this->refValue() = Zero;
58  this->refGrad() = Zero;
59  this->valueFraction() = scalar(1);
60 }
61 
62 
63 template<class Type>
65 (
66  const exprMixedFvPatchField<Type>& rhs,
67  const fvPatch& p,
69  const fvPatchFieldMapper& mapper
70 )
71 :
72  parent_bctype(rhs, p, iF, mapper),
73  expressions::patchExprFieldBase(rhs),
74  dict_(rhs.dict_), // Deep copy
75  driver_(this->patch(), rhs.driver_, dict_)
76 {
79 }
80 
81 
82 template<class Type>
84 (
85  const fvPatch& p,
87  const dictionary& dict
88 )
89 :
90  parent_bctype(p, iF), // bypass dictionary constructor
91  expressions::patchExprFieldBase
92  (
93  dict,
94  expressions::patchExprFieldBase::expectedTypes::MIXED_TYPE
95  ),
96  dict_
97  (
98  // Copy dictionary without "heavy" data chunks
99  dictionaryContent::copyDict
100  (
101  dict,
102  wordList(), // allow
103  wordList // deny
104  ({
105  "type", // redundant
106  "value", "refValue", "refGradient", "valueFraction"
107  })
108  )
109  ),
110  driver_(this->patch(), dict_)
111 {
112  setDebug();
113  DebugInFunction << nl;
114 
115  // Require one or both of valueExpr, gradientExpr
116  if (this->valueExpr_.empty() && this->gradExpr_.empty())
117  {
119  << "For " << this->internalField().name() << " on "
120  << this->patch().name() << nl
121  << "Require either or both: valueExpr and gradientExpr" << nl
122  << exit(FatalIOError);
123  }
124 
125  if (this->fracExpr_.empty())
126  {
127  // No fractionExpr. Expect only one of valueExpr or gradientExpr
128  if (!this->valueExpr_.empty() && !this->gradExpr_.empty())
129  {
131  << "For " << this->internalField().name() << " on "
132  << this->patch().name() << nl
133  << "Recommend using fractionExpr when specifying both"
134  << " valueExpr and gradientExpr. Assuming a value of 1."
135  << nl << endl;
136  }
137  }
138  else if (this->fracExpr_ == "0")
139  {
140  // Gradient only. Expect gradientExpr
141  if (this->gradExpr_.empty())
142  {
144  << "For " << this->internalField().name() << " on "
145  << this->patch().name() << nl
146  << "Gradient only, but did not specify gradientExpr."
147  << nl << endl;
148  }
149  }
150  else if (this->fracExpr_ == "1")
151  {
152  // Value only. Expect valueExpr
153  if (this->valueExpr_.empty())
154  {
156  << "For " << this->internalField().name() << " on "
157  << this->patch().name() << nl
158  << "Value only, but did not specify valueExpr."
159  << nl << endl;
160  }
161  }
162 
163  driver_.readDict(dict_);
164 
165  // Similar to fvPatchField constructor, which we have bypassed
166  dict.readIfPresent("patchType", this->patchType(), keyType::LITERAL);
167 
168 
169  const auto* hasValue = dict.findEntry("value", keyType::LITERAL);
170  const auto* hasRefValue = dict.findEntry("refValue", keyType::LITERAL);
171 
172  const auto* hasRefGradient
173  = dict.findEntry("refGradient", keyType::LITERAL);
174 
175  const auto* hasValueFraction
176  = dict.findEntry("valueFraction", keyType::LITERAL);
177 
178 
179  if (hasRefValue)
180  {
181  this->refValue().assign(*hasRefValue, p.size());
182  }
183 
184  if (hasValue)
185  {
186  Field<Type>::assign(*hasValue, p.size());
187 
188  if (!hasRefValue)
189  {
190  // Ensure refValue has a sensible value for the "update" below
191  this->refValue() = static_cast<const Field<Type>&>(*this);
192  }
193  }
194  else
195  {
196  if (!hasRefValue)
197  {
198  this->refValue() = this->patchInternalField();
199  }
200 
201  fvPatchField<Type>::operator=(this->refValue());
202 
203  #ifdef FULLDEBUG
205  << "No value defined for "
206  << this->internalField().name() << " on "
207  << this->patch().name() << " - using patch internal field" << endl;
208  #endif
209  }
210 
211 
212  if (hasRefGradient)
213  {
214  this->refGrad().assign(*hasRefGradient, p.size());
215  }
216  else
217  {
218  this->refGrad() = Zero;
219  }
220 
221  if (hasValueFraction)
222  {
223  this->valueFraction().assign(*hasValueFraction, p.size());
224  }
225  else
226  {
227  this->valueFraction() = scalar(1);
228  }
229 
230 
231  if (this->evalOnConstruct_)
232  {
233  // For potentialFoam or other solvers that don't evaluate
234  this->evaluate();
235  }
236  else
237  {
238  // Emulate mixedFvPatchField<Type>::evaluate,
239  // but avoid our own updateCoeffs
240  if (!this->updated())
241  {
242  this->parent_bctype::updateCoeffs();
243  }
244 
246  (
247  this->valueFraction()*this->refValue()
248  +
249  (1.0 - this->valueFraction())*
250  (
251  this->patchInternalField()
252  + this->refGrad()/this->patch().deltaCoeffs()
253  )
254  );
255 
257  }
258 }
259 
260 
261 template<class Type>
263 (
264  const exprMixedFvPatchField<Type>& rhs
265 )
266 :
267  parent_bctype(rhs),
268  expressions::patchExprFieldBase(rhs),
269  dict_(rhs.dict_), // Deep copy
270  driver_(this->patch(), rhs.driver_, dict_)
271 {
273  DebugInFunction << nl;
274 }
275 
276 
277 template<class Type>
279 (
280  const exprMixedFvPatchField<Type>& rhs,
282 )
283 :
284  parent_bctype(rhs, iF),
285  expressions::patchExprFieldBase(rhs),
286  dict_(rhs.dict_), // Deep copy
287  driver_(this->patch(), rhs.driver_, dict_)
288 {
289  setDebug();
291 }
292 
293 
294 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
295 
296 template<class Type>
298 {
299  if (this->updated())
300  {
301  return;
302  }
303 
304  if (debug)
305  {
307  << "Value: " << this->valueExpr_ << nl
308  << "Gradient: " << this->gradExpr_ << nl
309  << "Fraction: " << this->fracExpr_ << nl
310  << "Variables: ";
311  driver_.writeVariableStrings(Info) << nl;
312  Info<< "... updating" << endl;
313  }
314 
315 
316  // Expression evaluation
317  {
318  bool evalValue = (!this->valueExpr_.empty() && this->valueExpr_ != "0");
319  bool evalGrad = (!this->gradExpr_.empty() && this->gradExpr_ != "0");
320  bool evalFrac = (!this->fracExpr_.empty());
321  scalar fraction = 1;
322 
323  // Have one or both of valueExpr, gradientExpr (checked in constructor)
324 
325  if (this->valueExpr_.empty())
326  {
327  // No value expression -> gradient only
328  fraction = 0;
329  evalValue = false;
330  evalFrac = false;
331  }
332  else if (this->gradExpr_.empty())
333  {
334  // No gradient expression -> value only
335  fraction = 1;
336  evalGrad = false;
337  evalFrac = false;
338  }
339  else if (this->fracExpr_.empty())
340  {
341  // No fractionExpr, but has both valueExpr and gradientExpr
342  // -> treat as value only (warning in constructor)
343  fraction = 1;
344  evalGrad = false;
345  evalFrac = false;
346  }
347  else if (this->fracExpr_ == "0")
348  {
349  // Gradient only
350  fraction = 0;
351  evalValue = false;
352  evalFrac = false;
353  }
354  else if (this->fracExpr_ == "1")
355  {
356  // Value only
357  fraction = 1;
358  evalGrad = false;
359  evalFrac = false;
360  }
361 
362 
363  driver_.clearVariables();
364 
365  if (evalValue)
366  {
367  this->refValue() = driver_.evaluate<Type>(this->valueExpr_);
368  }
369  else
370  {
371  this->refValue() = Zero;
372  }
373 
374  if (evalGrad)
375  {
376  this->refGrad() = driver_.evaluate<Type>(this->gradExpr_);
377  }
378  else
379  {
380  this->refGrad() = Zero;
381  }
382 
383  if (evalFrac)
384  {
385  this->valueFraction() = driver_.evaluate<scalar>(this->fracExpr_);
386  }
387  else
388  {
389  this->valueFraction() = fraction;
390  }
391  }
392 
393  this->parent_bctype::updateCoeffs();
394 }
395 
396 
397 template<class Type>
398 void Foam::exprMixedFvPatchField<Type>::write(Ostream& os) const
399 {
400  this->parent_bctype::write(os);
402 
403  driver_.writeCommon(os, this->debug_ || debug);
404 }
405 
406 
407 // ************************************************************************* //
dictionary dict
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:118
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
A mixed boundary condition with expressions.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:68
virtual void write(Ostream &os) const
Write.
virtual Field< Type > & refValue()
void write(vtk::formatter &fmt, const Type &val, const label n=1)
Component-wise write of a value (N times)
friend Ostream & operator(Ostream &, const Field< Type > &)
exprMixedFvPatchField(const fvPatch &p, const DimensionedField< Type, volMesh > &)
Construct from patch and internal field.
virtual scalarField & valueFraction()
#define DebugInFunction
Report an information message using Foam::Info.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
A FieldMapper for finite-volume patch fields.
string evaluate(label fieldWidth, const std::string &s, size_t pos=0, size_t len=std::string::npos)
String evaluation with specified (positive, non-zero) field width.
String literal.
Definition: keyType.H:82
A wrapper for dictionary content, without operators that could affect inheritance patterns...
int debug
Static debugging option.
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
OBJstream os(runTime.globalPath()/outputName)
void assign(const entry &e, const label len)
Assign from a dictionary (primitive) entry.
Definition: Field.C:195
virtual void evaluate(const Pstream::commsTypes commsType=Pstream::commsTypes::blocking)
Evaluate the patch field, sets Updated to false.
Definition: fvPatchField.C:290
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
virtual void operator=(const UList< Type > &)
Definition: fvPatchField.C:352
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
const std::string patch
OpenFOAM patch number as a std::string.
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:80
messageStream Info
Information stream (stdout output on master, null elsewhere)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
volScalarField & p
void setDebug()
Set debug ON if "debug" is enabled.
virtual Field< Type > & refGrad()
void write(Ostream &os) const
Write.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...
#define InfoInFunction
Report an information message using Foam::Info.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157