fvExprDriver.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) 2010-2018 Bernhard Gschaider
9 Copyright (C) 2019-2022 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\*---------------------------------------------------------------------------*/
28
29#include "fvExprDriver.H"
30#include "fvExprDriverWriter.H"
31#include "expressionEntry.H"
32#include "exprResultGlobals.H"
33
34#include "cellSet.H"
35#include "faceSet.H"
36#include "pointSet.H"
37#include "stringOps.H"
38
39// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
40
41namespace Foam
42{
43namespace expressions
44{
45
49
50} // End namespace expressions
51} // End namespace Foam
52
53// Currently not working?
54bool Foam::expressions::fvExprDriver::cacheSets_ = true;
55
56const Foam::fvMesh* Foam::expressions::fvExprDriver::defaultMeshPtr_ = nullptr;
57
58
59// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
60
62{
63 if (!defaultMeshPtr_)
64 {
66 << "No default mesh set" << nl
67 << "Try the 'fvExprDriverFunctionObject' as a workaround"
68 << endl
69 << abort(FatalError);
70 }
71
72 return *defaultMeshPtr_;
73}
74
75
77(
78 const fvMesh& mesh,
79 const bool force
80)
81{
82 const fvMesh* ptr = defaultMeshPtr_;
83
84 if (force || (ptr != nullptr))
85 {
86 defaultMeshPtr_ = &mesh;
87 }
88
89 return ptr;
90}
91
92
93// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
94
96(
98 const dictionary& dict
99)
100:
101 expressions::exprDriver(search, dict),
102 globalScopes_(),
103 delayedVariables_(),
104 storedVariables_(),
105 specialVariablesIndex_(-1),
106 otherMeshName_(),
107 writer_(nullptr)
108{}
109
110
112(
113 const fvExprDriver& rhs,
114 const dictionary& dict
115)
116:
117 expressions::exprDriver(rhs, dict),
118 globalScopes_(rhs.globalScopes_),
119 delayedVariables_(rhs.delayedVariables_),
120 storedVariables_(rhs.storedVariables_),
121 specialVariablesIndex_(rhs.specialVariablesIndex_),
122 otherMeshName_(),
123 writer_(nullptr)
124{}
125
126
128(
129 const dictionary& dict
130)
131:
132 expressions::exprDriver(dict),
133 globalScopes_(),
134 delayedVariables_(),
135 storedVariables_(),
136 specialVariablesIndex_(-1),
137 otherMeshName_(),
138 writer_(nullptr)
139{
140 readDict(dict);
141}
142
143
144// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
145
147{}
148
149
150// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
151
153(
154 const dictionary& dict
155)
156{
157 expressions::exprDriver::readDict(dict);
158
159 // fileNameList plugins;
160 // if (dict.readIfPresent("functionPlugins", plugins))
161 // {
162 // for (const fileName& libName : plugins)
163 // {
164 // this->mesh().time().libs().open
165 // (
166 // "libswak" + libName + "FunctionPlugin" // verbose = true
167 // );
168 // }
169 // }
170
171 dict.readIfPresent("globalScopes", globalScopes_);
172
173 const entry* eptr = nullptr;
174
175 // Special variables
176
177 if
178 (
179 // storedVariables
180 (eptr = dict.findEntry("storedVariables", keyType::LITERAL))
181 != nullptr
182 )
183 {
184 ITstream& is = eptr->stream();
185
186 if (writer_ && !storedVariables_.empty())
187 {
189 // << "Context: " << driverContext_ << nl
190 << "The 'storedVariables' was already read."
191 << " No update from " << is
192 << endl;
193 }
194 else
195 {
196 storedVariables_ = List<exprResultStored>(is);
197
198 // Check for excess tokens
199 dict.checkITstream(is, "storedVariables");
200 }
201 }
202
203 if
204 (
205 // delayedVariables
206 (eptr = dict.findEntry("delayedVariables", keyType::LITERAL))
207 != nullptr
208 )
209 {
210 ITstream& is = eptr->stream();
211
212 if (writer_ && !delayedVariables_.empty())
213 {
215 // << "Context: " << driverContext_ << nl
216 << "Seems like 'delayedVariables' was already read."
217 << " No update from " << is
218 << endl;
219 }
220 else
221 {
222 List<exprResultDelayed> inputs(is);
223
224 // Check for excess tokens
225 dict.checkITstream(is, "delayedVariables");
226
227 for (auto& var : inputs)
228 {
229 delayedVariables_.insert(var.name(), var);
230 }
231 }
232 }
233
234 return true;
235}
236
237
238// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
239
241{
242 const bool updated = this->update();
243
244 const label eventIndex = mesh().time().timeIndex();
245 const scalar eventTime = mesh().time().value();
246
248 << "fvExprDriver::updateSpecialVariables(force="
249 << force << ") Updated: " << updated << endl;
250
251 if (specialVariablesIndex_ < 0)
252 {
254 << "First update: " << eventIndex << endl;
255
256 specialVariablesIndex_ = eventIndex;
257
258 for (exprResultStored& v : storedVariables_)
259 {
261 << v.name() << " = " << v.initialValueExpression()
262 << " (has value "
263 << v.hasValue() << ")" << endl;
264
265 if (!v.hasValue())
266 {
268 << "First value: " << v.initialValueExpression()
269 << " -> " << v.name() << endl;
270
271 parse(v.initialValueExpression());
272 v = result_;
274 << "Parser size: " << this->size() << nl
275 << "Calculated: " << result_ << nl
276 << "Stored: " << v << nl;
277 }
278 }
279 }
280
281 if (force || specialVariablesIndex_ != eventIndex)
282 {
284 << "Store variables: " << force << ' '
285 << specialVariablesIndex_ << ' '
286 << eventIndex << endl;
287
288 for (exprResultStored& v : storedVariables_)
289 {
290 if (variables_.found(v.name()))
291 {
293 << "Storing variable: " << v.name() << " "
294 << variables_[v.name()] << endl;
295
296 v = variables_[v.name()];
297 }
298 }
299 specialVariablesIndex_ = eventIndex;
300 }
301
302 forAllIters(delayedVariables_, iter)
303 {
305 << "Updating delayed variable " << iter().name() << endl;
306
307 if (!iter().updateReadValue(eventTime))
308 {
309 const exprString& expr = iter().startupValueExpression();
310
312 << "Evaluate: " << expr << endl;
313
314 parse(expr);
315 iter().setReadValue(result_);
316
318 << "Value " << iter() << nl
319 << "Type " << iter().valueType() << "("
320 << result_.valueType() << ")" << endl;
321 }
322 else
323 {
325 << iter().name() << " updated without problem" << endl;
326 }
327 }
328}
329
330
332{
334 << "Clearing variables" << endl;
335
336 const scalar eventTime = mesh().time().value();
337
338 (void)this->update();
339
340 updateSpecialVariables();
341 variables_.clear();
342 for (exprResultStored& v : storedVariables_)
343 {
344 variables_.insert(v.name(), v);
345 }
346
347 addVariables(variableStrings_, false);
348
349 forAllIters(delayedVariables_, iter)
350 {
351 iter().storeValue(eventTime);
352 }
353}
354
355
357(
358 const word& varName,
359 const expressions::exprString& expr
360)
361{
362 const regIOobject* objPtr = mesh().findObject<regIOobject>(varName);
363
364 if (!allowShadowing_ && objPtr)
365 {
367 // << "Context: " << driverContext_ << nl
368 << "Field '" << varName << "' (type " << objPtr->headerClassName()
369 << ") is shadowed by a variable of the same name." << nl
370 << "This may lead to trouble" << nl
371 << "If this is OK set 'allowShadowing'"
372 << " in the relevant parser" << nl
373 << endl;
374 }
375
376 parse(expr);
377 result_.testIfSingleValue();
378
380 << "Evaluating: " << expr << " -> " << varName << endl
381 << result_;
382
383
384 // Assign
385 if (delayedVariables_.found(varName))
386 {
387 // Avoid potential conflicts?
388 variables_.erase(varName);
389
391 << varName << " is delayed" << endl;
392
393 // Copy assignment
394 delayedVariables_[varName] = result_;
395 }
396 else
397 {
398 // Overwrite with a copy
399 variables_.set(varName, exprResult(result_));
400 }
401}
402
403
405(
406 string remote,
407 const word& varName,
408 const expressions::exprString& expr
409)
410{
412 << "Evaluating remote " << remote.c_str()
413 << " : " << expr << " -> " << varName << endl;
414
415 word driverType("patch"); // default is patch
416 word identName, regionName;
417
418 const auto slashPos = remote.find('/');
419 if (slashPos != std::string::npos)
420 {
421 regionName = word::validate(remote.substr(slashPos+1));
422 remote.resize(slashPos);
423 }
424
425 const auto quotePos = remote.find('\'');
426 if (quotePos != std::string::npos)
427 {
428 driverType = word::validate(remote.substr(0, quotePos));
429 identName = word::validate(remote.substr(quotePos+1));
430 }
431 else
432 {
433 identName = word::validate(remote);
434 }
435
436 if
437 (
438 driverType == "patch"
439 &&
440 (
441 identName.empty()
442 || identName == "volume"
443 || identName == "internalField"
444 )
445 )
446 {
447 driverType = "internalField";
448 }
449
450 const fvMesh* pRegion = &(this->mesh());
451
452 if (!regionName.empty())
453 {
454 pRegion = pRegion->time().cfindObject<fvMesh>(regionName);
455
456 if (!pRegion)
457 {
459 << "Cannot resolve mesh region: " << regionName << nl
460 << exit(FatalError);
461 }
462 }
463
465 << "Call other with ("
466 << driverType << ", " << identName << ", " << regionName << ")\n";
467
468 autoPtr<fvExprDriver> otherDriver =
469 fvExprDriver::New(driverType, identName, *pRegion);
470
471 otherDriver->setSearchBehaviour(*this);
472 otherDriver->setGlobalScopes(this->globalScopes_);
473
474 otherDriver->parse(expr);
475
476 exprResult otherResult(this->getRemoteResult(*otherDriver));
477
478 // Check / re-check for uniform. Not normally needed
479 if (!otherResult.isUniform())
480 {
481 otherResult.testIfSingleValue();
482 }
483
485 << "Remote result: " << otherResult << nl;
486
487 // Assign
488 if (delayedVariables_.found(varName))
489 {
490 // Avoid potential conflicts?
491 variables_.erase(varName);
492
494 << varName << " is delayed - setting" << nl;
495
496 // Move assignment
497 delayedVariables_[varName] = std::move(otherResult);
498 }
499 else
500 {
501 // Overwrite with a copy
502 variables_.set(varName, std::move(otherResult));
503 }
504}
505
506
507const Foam::fvMesh&
509(
510 const dictionary& dict,
511 const fvMesh& mesh,
512 bool readIfNecessary
513)
514{
516
517 if (!dict.readIfPresent("region", regionName))
518 {
519 DebugInFunction << "Using original mesh " << nl;
520 return mesh;
521 }
522
523 DebugInFunction << "Using mesh " << regionName << endl;
524
525 fvMesh* meshPtr = mesh.time().getObjectPtr<fvMesh>(regionName);
526
527 if (!meshPtr && readIfNecessary)
528 {
530 << "Region " << regionName
531 << " not in memory. Loading it" << endl;
532
533 meshPtr = new fvMesh
534 (
536 (
538 mesh.time().constant(),
539 mesh.time(),
541 )
542 );
543
544 meshPtr->polyMesh::store();
545 }
546
547 if (!meshPtr)
548 {
550 << "No mesh region loaded: " << regionName
551 << endl;
552 }
553
554 return *meshPtr;
555}
556
557
559(
560 const word& fieldName
561) const
562{
563 return getHeaderClassName(this->mesh(), fieldName);
564}
565
566
568(
569 const word& name
570) const
571{
572 if (searchRegistry())
573 {
574 const regIOobject* ioptr = this->mesh().findObject<regIOobject>(name);
575
576 if (ioptr)
577 {
578 return ioptr->type();
579 }
580 }
581
582 if (searchFiles())
583 {
584 return getHeaderClassName(this->mesh(), name);
585 }
586
587 return word::null;
588}
589
590
593{
595
596 if (io.isHeaderClass<cellSet>())
597 {
599 }
600 if (io.isHeaderClass<faceSet>())
601 {
603 }
604 if (io.isHeaderClass<pointSet>())
605 {
607 }
608
610}
611
612
615{
616 if (mesh().cellZones().findZoneID(setName) >= 0)
617 {
619 }
620
621 if (mesh().faceZones().findZoneID(setName) >= 0)
622 {
624 }
625
626 if (mesh().pointZones().findZoneID(setName) >= 0)
627 {
629 }
630
632}
633
634
637{
638 auto setType = topoZoneType(setName);
639
641 {
642 setType = topoSetType(setName);
643 }
644
645 return setType;
646}
647
648
649
651{
652 return
653 (
655 == topoSetType(setName)
656 );
657}
658
659
661{
662 return
663 (
665 == topoSetType(setName)
666 );
667}
668
669
671{
672 return
673 (
675 == topoSetType(setName)
676 );
677}
678
679
681{
682 return (mesh().cellZones().findZoneID(name) >= 0);
683}
684
685
687{
688 return (mesh().faceZones().findZoneID(name) >= 0);
689}
690
691
693{
694 return (mesh().pointZones().findZoneID(name) >= 0);
695}
696
697
700(
701 const word& name
702) const
703{
704 return exprResultGlobals::New(this->mesh()).get(name, globalScopes_);
705}
706
707
709{
710 return (!storedVariables_.empty() || !delayedVariables_.empty());
711}
712
713
715(
716 const dictionary& dict
717)
718{
719 dict.readIfPresent("storedVariables", storedVariables_);
720}
721
722
724(
726) const
727{
728 auto& driver = const_cast<fvExprDriver&>(*this);
729
730 (void)driver.update();
731
732 if (storedVariables_.size())
733 {
734 driver.updateSpecialVariables(true);
735
736 dict.add("storedVariables", storedVariables_);
737 }
738}
739
740
741// ************************************************************************* //
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition: IOobjectI.H:83
An input stream of tokens.
Definition: ITstream.H:56
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: List.H:77
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A collection of cell labels.
Definition: cellSet.H:54
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
A keyword and a list of tokens is an 'entry'.
Definition: entry.H:70
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
Base driver for parsing (field) values.
Definition: exprDriver.H:141
searchControls
Search/caching controls.
Definition: exprDriver.H:148
virtual bool update()
Update things.
Definition: exprDriver.C:321
const dictionary & dict() const noexcept
The dictionary with all input data/specification.
Definition: exprDriver.H:385
An exprResult with persistence.
A polymorphic field/result from evaluating an expression.
Definition: exprResult.H:127
void testIfSingleValue(const bool parRun=Pstream::parRun())
Test if field corresponds to a single-value and thus uniform.
Definition: exprResult.C:471
bool isUniform() const
True if single, uniform value.
Definition: exprResultI.H:250
Base driver for parsing value expressions associated with an fvMesh.
Definition: fvExprDriver.H:139
bool isPointSet(const word &name) const
Test if name is a known pointSet.
Definition: fvExprDriver.C:670
bool isFaceSet(const word &name) const
Test if name is a known faceSet.
Definition: fvExprDriver.C:660
virtual void updateSpecialVariables(bool force=false)
Examine current variable values and update stored variables.
Definition: fvExprDriver.C:240
virtual void prepareData(dictionary &dict) const
Definition: fvExprDriver.C:724
virtual bool hasDataToWrite() const
Do we need a data file to be written.
Definition: fvExprDriver.C:708
const exprResult & lookupGlobal(const word &name) const
Return the global variable if available or a null result.
Definition: fvExprDriver.C:700
static const fvMesh & defaultMesh()
Get the default mesh, if one is defined.
Definition: fvExprDriver.C:61
bool isCellSet(const word &name) const
Test if name is a known cellSet.
Definition: fvExprDriver.C:650
bool isPointZone(const word &name) const
Test if name is a known pointZone.
Definition: fvExprDriver.C:692
virtual void evaluateVariableRemote(string remote, const word &varName, const expressions::exprString &expr)
Definition: fvExprDriver.C:405
topoSetSource::sourceType topoZoneType(const word &name) const
Return cell/face/point zone type or unknown.
Definition: fvExprDriver.C:614
virtual bool readDict(const dictionary &dict)
Read variables, tables etc.
Definition: fvExprDriver.C:153
word getFieldClassName(const word &name) const
Lookup the field class name (memory or read from disk)
Definition: fvExprDriver.C:568
bool isCellZone(const word &name) const
Test if name is a known cellZone.
Definition: fvExprDriver.C:680
bool isFaceZone(const word &name) const
Test if name is a known faceZone.
Definition: fvExprDriver.C:686
virtual void evaluateVariable(const word &varName, const expressions::exprString &expr)
Definition: fvExprDriver.C:357
topoSetSource::sourceType topoSetType(const word &name) const
Return cell/face/point set type or unknown.
Definition: fvExprDriver.C:592
virtual ~fvExprDriver()
Destructor.
Definition: fvExprDriver.C:146
virtual void clearVariables()
Clear temporary variables, reset from expression strings.
Definition: fvExprDriver.C:331
static const fvMesh * resetDefaultMesh(const fvMesh &mesh, const bool force=false)
Set the default mesh (if not already set)
Definition: fvExprDriver.C:77
topoSetSource::sourceType topoSourceType(const word &name) const
Return cell/face/point zone/set type or unknown.
Definition: fvExprDriver.C:636
virtual void getData(const dictionary &dict)
Read data from dictionary, normally via the reader/writer.
Definition: fvExprDriver.C:715
word getTypeOfField(const word &fieldName) const
Read the IOobject for fieldName and return its headerClassName.
Definition: fvExprDriver.C:559
const fvMesh & regionMesh() const
Return region mesh.
A list of face labels.
Definition: faceSet.H:54
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
virtual void validate()
Validate the turbulence fields after construction.
Definition: kkLOmega.C:597
@ LITERAL
String literal.
Definition: keyType.H:81
const Type * cfindObject(const word &name, const bool recursive=false) const
Return const pointer to the object of the given Type.
A set of point labels.
Definition: pointSet.H:54
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:76
sourceType
Enumeration defining the types of sources.
Definition: topoSetSource.H:75
@ POINTSET_SOURCE
Points as set.
Definition: topoSetSource.H:84
@ FACESET_SOURCE
Faces as set.
Definition: topoSetSource.H:83
@ FACEZONE_SOURCE
Faces as zone.
Definition: topoSetSource.H:88
@ UNKNOWN_SOURCE
Placeholder.
Definition: topoSetSource.H:76
@ POINTZONE_SOURCE
Points as zone.
Definition: topoSetSource.H:89
@ CELLSET_SOURCE
Cells as set.
Definition: topoSetSource.H:82
@ CELLZONE_SOURCE
Cells as zone.
Definition: topoSetSource.H:87
static IOobject findIOobject(const polyMesh &mesh, const word &name, readOption r=MUST_READ, writeOption w=NO_WRITE)
Find IOobject in the polyMesh/sets (used as constructor helper)
Definition: topoSet.C:318
A class for handling words, derived from Foam::string.
Definition: word.H:68
static const word null
An empty word.
Definition: word.H:80
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
mesh update()
dynamicFvMesh & mesh
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
Foam::word regionName(Foam::polyMesh::defaultRegion)
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, false)
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
#define DebugInFunction
Report an information message using Foam::Info.
Namespace for OpenFOAM.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
errorManip< error > abort(error &err)
Definition: errorManip.H:144
error FatalError
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:624
constexpr char nl
The newline '\n' character (0x0a)
Definition: Ostream.H:53
#define defineRunTimeSelectionTable(baseType, argNames)
Define run-time selection table.
dictionary dict
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:260