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-------------------------------------------------------------------------------
11License
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
29#include "dictionaryContent.H"
30
31// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
32
33template<class Type>
35{
36 if (expressions::patchExprFieldBase::debug_ && !debug)
37 {
38 debug = 1;
39 }
40}
41
42
43// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
44
45template<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
63template<class Type>
65(
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{
77 setDebug();
79}
80
81
82template<class Type>
84(
85 const fvPatch& p,
87 const dictionary& dict
88)
89:
90 parent_bctype(p, iF),
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();
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
164 driver_.readDict(dict_);
165
166 // Similar to fvPatchField constructor, which we have bypassed
167 dict.readIfPresent("patchType", this->patchType(), keyType::LITERAL);
168
169 bool needsRefValue = true;
170 if (dict.found("refValue"))
171 {
172 needsRefValue = false;
173 this->refValue() = Field<Type>("refValue", dict, p.size());
174 }
175
176 if (dict.found("value"))
177 {
179 (
180 Field<Type>("value", dict, p.size())
181 );
182
183 if (needsRefValue)
184 {
185 // Ensure refValue has a sensible value for the "update" below
186 this->refValue() = static_cast<const Field<Type>&>(*this);
187 }
188 }
189 else
190 {
191 if (needsRefValue)
192 {
193 this->refValue() = this->patchInternalField();
194 }
195
196 fvPatchField<Type>::operator=(this->refValue());
197
198 #ifdef FULLDEBUG
200 << "No value defined for "
201 << this->internalField().name() << " on "
202 << this->patch().name() << " - using patch internal field" << endl;
203 #endif
204 }
205
206
207 if (dict.found("refGradient"))
208 {
209 this->refGrad() = Field<Type>("refGradient", dict, p.size());
210 }
211 else
212 {
213 this->refGrad() = Zero;
214 }
215
216 if (dict.found("valueFraction"))
217 {
218 this->valueFraction() = Field<scalar>("valueFraction", dict, p.size());
219 }
220 else
221 {
222 this->valueFraction() = scalar(1);
223 }
224
225
226 if (this->evalOnConstruct_)
227 {
228 // For potentialFoam or other solvers that don't evaluate
229 this->evaluate();
230 }
231 else
232 {
233 // Emulate mixedFvPatchField<Type>::evaluate,
234 // but avoid our own updateCoeffs
235 if (!this->updated())
236 {
237 this->parent_bctype::updateCoeffs();
238 }
239
241 (
242 this->valueFraction()*this->refValue()
243 +
244 (1.0 - this->valueFraction())*
245 (
246 this->patchInternalField()
247 + this->refGrad()/this->patch().deltaCoeffs()
248 )
249 );
250
252 }
253}
254
255
256template<class Type>
258(
260)
261:
262 parent_bctype(rhs),
263 expressions::patchExprFieldBase(rhs),
264 dict_(rhs.dict_), // Deep copy
265 driver_(this->patch(), rhs.driver_, dict_)
266{
267 setDebug();
269}
270
271
272template<class Type>
274(
277)
278:
279 parent_bctype(rhs, iF),
280 expressions::patchExprFieldBase(rhs),
281 dict_(rhs.dict_), // Deep copy
282 driver_(this->patch(), rhs.driver_, dict_)
283{
284 setDebug();
286}
287
288
289// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
290
291template<class Type>
293{
294 if (this->updated())
295 {
296 return;
297 }
298
299 if (debug)
300 {
302 << "Value: " << this->valueExpr_ << nl
303 << "Gradient: " << this->gradExpr_ << nl
304 << "Fraction: " << this->fracExpr_ << nl
305 << "Variables: ";
306 driver_.writeVariableStrings(Info) << nl;
307 Info<< "... updating" << endl;
308 }
309
310
311 // Expression evaluation
312 {
313 bool evalValue = (!this->valueExpr_.empty() && this->valueExpr_ != "0");
314 bool evalGrad = (!this->gradExpr_.empty() && this->gradExpr_ != "0");
315 bool evalFrac = (!this->fracExpr_.empty());
316 scalar fraction = 1;
317
318 // Have one or both of valueExpr, gradientExpr (checked in constructor)
319
320 if (this->valueExpr_.empty())
321 {
322 // No value expression -> gradient only
323 fraction = 0;
324 evalValue = false;
325 evalFrac = false;
326 }
327 else if (this->gradExpr_.empty())
328 {
329 // No gradient expression -> value only
330 fraction = 1;
331 evalGrad = false;
332 evalFrac = false;
333 }
334 else if (this->fracExpr_.empty())
335 {
336 // No fractionExpr, but has both valueExpr and gradientExpr
337 // -> treat as value only (warning in constructor)
338 fraction = 1;
339 evalGrad = false;
340 evalFrac = false;
341 }
342 else if (this->fracExpr_ == "0")
343 {
344 // Gradient only
345 fraction = 0;
346 evalValue = false;
347 evalFrac = false;
348 }
349 else if (this->fracExpr_ == "1")
350 {
351 // Value only
352 fraction = 1;
353 evalGrad = false;
354 evalFrac = false;
355 }
356
357
358 driver_.clearVariables();
359
360 if (evalValue)
361 {
362 this->refValue() = driver_.evaluate<Type>(this->valueExpr_);
363 }
364 else
365 {
366 this->refValue() = Zero;
367 }
368
369 if (evalGrad)
370 {
371 this->refGrad() = driver_.evaluate<Type>(this->gradExpr_);
372 }
373 else
374 {
375 this->refGrad() = Zero;
376 }
377
378 if (evalFrac)
379 {
380 this->valueFraction() = driver_.evaluate<scalar>(this->fracExpr_);
381 }
382 else
383 {
384 this->valueFraction() = fraction;
385 }
386 }
387
388 this->parent_bctype::updateCoeffs();
389}
390
391
392template<class Type>
394{
395 this->parent_bctype::write(os);
397
398 driver_.writeCommon(os, this->debug_ || debug);
399}
400
401
402// ************************************************************************* //
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
friend Ostream & operator(Ostream &, const Field< Type > &)
void evaluate()
Evaluate boundary conditions.
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:62
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
A wrapper for dictionary content, without operators that could affect inheritance patterns.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Search for an entry (const access) with the given keyword.
Definition: dictionaryI.H:87
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
A mixed boundary condition with expressions.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
void setDebug()
Set debug ON if "debug" is enabled.
expectedTypes
Enumeration of expected expressions.
virtual bool write()
Write the output fields.
A FieldMapper for finite-volume patch fields.
virtual void operator=(const UList< Type > &)
Definition: fvPatchField.C:408
friend Ostream & operator(Ostream &, const fvPatchField< Type > &)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
@ LITERAL
String literal.
Definition: keyType.H:81
This boundary condition provides a base class for 'mixed' type boundary conditions,...
virtual Field< Type > & refGrad()
virtual Field< Type > & refValue()
virtual scalarField & valueFraction()
volScalarField & p
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:473
OBJstream os(runTime.globalPath()/outputName)
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
#define InfoInFunction
Report an information message using Foam::Info.
const std::string patch
OpenFOAM patch number as a std::string.
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.
messageStream Info
Information stream (stdout output on master, null elsewhere)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
IOerror FatalIOError
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
dictionary dict