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 -------------------------------------------------------------------------------
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 "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 
41 namespace Foam
42 {
43 namespace expressions
44 {
45 
49 
50 } // End namespace expressions
51 } // End namespace Foam
52 
53 // Currently not working?
54 bool Foam::expressions::fvExprDriver::cacheSets_ = true;
55 
56 const 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 {
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  }
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 
247  DebugInfo
248  << "fvExprDriver::updateSpecialVariables(force="
249  << force << ") Updated: " << updated << endl;
250 
251  if (specialVariablesIndex_ < 0)
252  {
253  DebugInfo
254  << "First update: " << eventIndex << endl;
255 
256  specialVariablesIndex_ = eventIndex;
257 
258  for (exprResultStored& v : storedVariables_)
259  {
260  DebugInfo
261  << v.name() << " = " << v.initialValueExpression()
262  << " (has value "
263  << v.hasValue() << ")" << endl;
264 
265  if (!v.hasValue())
266  {
267  DebugInfo
268  << "First value: " << v.initialValueExpression()
269  << " -> " << v.name() << endl;
270 
271  parse(v.initialValueExpression());
272  v = result_;
273  DebugInfo
274  << "Parser size: " << this->size() << nl
275  << "Calculated: " << result_ << nl
276  << "Stored: " << v << nl;
277  }
278  }
279  }
280 
281  if (force || specialVariablesIndex_ != eventIndex)
282  {
283  DebugInfo
284  << "Store variables: " << force << ' '
285  << specialVariablesIndex_ << ' '
286  << eventIndex << endl;
287 
288  for (exprResultStored& v : storedVariables_)
289  {
290  if (variables_.found(v.name()))
291  {
292  DebugInfo
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  {
304  DebugInfo
305  << "Updating delayed variable " << iter().name() << endl;
306 
307  if (!iter().updateReadValue(eventTime))
308  {
309  const exprString& expr = iter().startupValueExpression();
310 
311  DebugInfo
312  << "Evaluate: " << expr << endl;
313 
314  parse(expr);
315  iter().setReadValue(result_);
316 
317  DebugInfo
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 {
333  DebugInfo
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 
379  DebugInfo
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 
390  DebugInfo
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 {
411  DebugInfo
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 
464  DebugInfo
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 
484  DebugInfo
485  << "Remote result: " << otherResult << nl;
486 
487  // Assign
488  if (delayedVariables_.found(varName))
489  {
490  // Avoid potential conflicts?
491  variables_.erase(varName);
492 
493  DebugInfo
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 
507 const 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  (
535  IOobject
536  (
537  regionName,
538  mesh.time().constant(),
539  mesh.time(),
543  )
544  );
545 
546  meshPtr->polyMesh::store();
547  }
548 
549  if (!meshPtr)
550  {
552  << "No mesh region loaded: " << regionName
553  << endl;
554  }
555 
556  return *meshPtr;
557 }
558 
559 
561 (
562  const word& fieldName
563 ) const
564 {
565  return getHeaderClassName(this->mesh(), fieldName);
566 }
567 
568 
570 (
571  const word& name
572 ) const
573 {
574  if (searchRegistry())
575  {
576  const regIOobject* ioptr = this->mesh().findObject<regIOobject>(name);
577 
578  if (ioptr)
579  {
580  return ioptr->type();
581  }
582  }
583 
584  if (searchFiles())
585  {
586  return getHeaderClassName(this->mesh(), name);
587  }
588 
589  return word::null;
590 }
591 
592 
595 {
596  IOobject io(topoSet::findIOobject(mesh(), setName));
597 
598  if (io.isHeaderClass<cellSet>())
599  {
600  return topoSetSource::sourceType::CELLSET_SOURCE;
601  }
602  if (io.isHeaderClass<faceSet>())
603  {
604  return topoSetSource::sourceType::FACESET_SOURCE;
605  }
606  if (io.isHeaderClass<pointSet>())
607  {
608  return topoSetSource::sourceType::POINTSET_SOURCE;
609  }
610 
611  return topoSetSource::sourceType::UNKNOWN_SOURCE;
612 }
613 
614 
617 {
618  if (mesh().cellZones().findZoneID(setName) >= 0)
619  {
620  return topoSetSource::sourceType::CELLZONE_SOURCE;
621  }
622 
623  if (mesh().faceZones().findZoneID(setName) >= 0)
624  {
625  return topoSetSource::sourceType::FACEZONE_SOURCE;
626  }
627 
628  if (mesh().pointZones().findZoneID(setName) >= 0)
629  {
630  return topoSetSource::sourceType::POINTZONE_SOURCE;
631  }
632 
633  return topoSetSource::sourceType::UNKNOWN_SOURCE;
634 }
635 
636 
639 {
640  auto setType = topoZoneType(setName);
641 
642  if (topoSetSource::sourceType::UNKNOWN_SOURCE == setType)
643  {
644  setType = topoSetType(setName);
645  }
646 
647  return setType;
648 }
649 
650 
651 
652 bool Foam::expressions::fvExprDriver::isCellSet(const word& setName) const
653 {
654  return
655  (
656  topoSetSource::sourceType::CELLSET_SOURCE
657  == topoSetType(setName)
658  );
659 }
660 
661 
662 bool Foam::expressions::fvExprDriver::isFaceSet(const word& setName) const
663 {
664  return
665  (
666  topoSetSource::sourceType::FACESET_SOURCE
667  == topoSetType(setName)
668  );
669 }
670 
671 
672 bool Foam::expressions::fvExprDriver::isPointSet(const word& setName) const
673 {
674  return
675  (
676  topoSetSource::sourceType::POINTSET_SOURCE
677  == topoSetType(setName)
678  );
679 }
680 
683 {
684  return (mesh().cellZones().findZoneID(name) >= 0);
685 }
686 
689 {
690  return (mesh().faceZones().findZoneID(name) >= 0);
691 }
692 
693 
695 {
696  return (mesh().pointZones().findZoneID(name) >= 0);
697 }
698 
699 
702 (
703  const word& name
704 ) const
705 {
706  return exprResultGlobals::New(this->mesh()).get(name, globalScopes_);
707 }
708 
709 
711 {
712  return (!storedVariables_.empty() || !delayedVariables_.empty());
713 }
714 
715 
717 (
718  const dictionary& dict
719 )
720 {
721  dict.readIfPresent("storedVariables", storedVariables_);
722 }
723 
724 
726 (
728 ) const
729 {
730  auto& driver = const_cast<fvExprDriver&>(*this);
731 
732  (void)driver.update();
733 
734  if (storedVariables_.size())
735  {
736  driver.updateSpecialVariables(true);
737 
738  dict.add("storedVariables", storedVariables_);
739  }
740 }
741 
742 
743 // ************************************************************************* //
static IOobject findIOobject(const polyMesh &mesh, const word &name, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, IOobjectOption::writeOption wOpt=IOobjectOption::NO_WRITE)
Find IOobject in the polyMesh/sets (used as constructor helper)
Definition: topoSet.C:311
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:39
dictionary dict
word getFieldClassName(const word &name) const
Lookup the field class name (memory or read from disk)
Definition: fvExprDriver.C:563
virtual void prepareData(dictionary &dict) const
Prepare/update special variables and add to dictionary, normally via the reader/writer.
Definition: fvExprDriver.C:719
fvExprDriver(enum exprDriver::searchControls search=exprDriver::searchControls::DEFAULT_SEARCH, const dictionary &dict=dictionary::null)
Default construct, and default construct with search preferences.
Definition: fvExprDriver.C:89
defineTypeNameAndDebug(fvExprDriver, 0)
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A polymorphic field/result from evaluating an expression.
Definition: exprResult.H:121
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
static const fvMesh & regionMesh(const dictionary &dict, const fvMesh &mesh, bool readIfNecessary)
Determine mesh or region mesh as specified in the dictionary with the keyword "region".
Definition: fvExprDriver.C:502
word getTypeOfField(const word &fieldName) const
Read the IOobject for fieldName and return its headerClassName.
Definition: fvExprDriver.C:554
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
virtual ~fvExprDriver()
Destructor.
Definition: fvExprDriver.C:139
defineRunTimeSelectionTable(fvExprDriver, dictionary)
virtual bool readDict(const dictionary &dict)
Read variables, tables etc.
Definition: exprDriver.C:290
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
static autoPtr< fvExprDriver > New(const dictionary &dict, const fvMesh &mesh)
Return a reference to the selected value driver.
Ignore writing from objectRegistry::writeObject()
topoSetSource::sourceType topoSourceType(const word &name) const
Return cell/face/point zone/set type or unknown.
Definition: fvExprDriver.C:631
const exprResult & get(const word &name, const wordUList &scopes) const
Return a global variable, if it exists, or a exprResult::null.
Base driver for parsing value expressions associated with an fvMesh.
Definition: fvExprDriver.H:132
virtual void updateSpecialVariables(bool force=false)
Examine current variable values and update stored variables.
Definition: fvExprDriver.C:233
searchControls
Search/caching controls.
Definition: exprDriver.H:145
virtual bool hasDataToWrite() const
Do we need a data file to be written.
Definition: fvExprDriver.C:703
static const fvMesh & defaultMesh()
Get the default mesh, if one is defined.
Definition: fvExprDriver.C:54
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
bool isFaceSet(const word &name) const
Test if name is a known faceSet.
Definition: fvExprDriver.C:655
A class for handling words, derived from Foam::string.
Definition: word.H:63
#define DebugInFunction
Report an information message using Foam::Info.
virtual void evaluateVariable(const word &varName, const expressions::exprString &expr)
Evaluate the expression and save as the specified named variable.
Definition: fvExprDriver.C:350
A variant of Foam::string with expansion of dictionary variables into a comma-separated form...
Definition: exprString.H:55
An exprResult with persistence.
#define forAllIters(container, iter)
Iterate across all elements in the container object.
Definition: stdFoam.H:336
static const word null
An empty word.
Definition: word.H:84
bool isCellZone(const word &name) const
Test if name is a known cellZone.
Definition: fvExprDriver.C:675
String literal.
Definition: keyType.H:82
virtual void evaluateVariableRemote(string remote, const word &varName, const expressions::exprString &expr)
Evaluate an expression on a remote and save as the specified named variable.
Definition: fvExprDriver.C:398
errorManip< error > abort(error &err)
Definition: errorManip.H:139
#define DebugInfo
Report an information message using Foam::Info.
topoSetSource::sourceType topoSetType(const word &name) const
Return cell/face/point set type or unknown.
Definition: fvExprDriver.C:587
mesh update()
topoSetSource::sourceType topoZoneType(const word &name) const
Return cell/face/point zone type or unknown.
Definition: fvExprDriver.C:609
Base driver for parsing (field) values.
Definition: exprDriver.H:136
virtual bool update()
Update things.
Definition: exprDriver.C:314
virtual void getData(const dictionary &dict)
Read data from dictionary, normally via the reader/writer.
Definition: fvExprDriver.C:710
virtual void clearVariables()
Clear temporary variables, reset from expression strings.
Definition: fvExprDriver.C:324
bool isPointSet(const word &name) const
Test if name is a known pointSet.
Definition: fvExprDriver.C:665
bool isFaceZone(const word &name) const
Test if name is a known faceZone.
Definition: fvExprDriver.C:681
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition: IOobjectI.H:213
#define WarningInFunction
Report a warning using Foam::Warning.
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
A collection of cell labels.
Definition: cellSet.H:47
virtual bool readDict(const dictionary &dict)
Read variables, tables etc.
Definition: fvExprDriver.C:146
sourceType
Enumeration defining the types of sources.
Definition: topoSetSource.H:72
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
static const fvMesh * resetDefaultMesh(const fvMesh &mesh, const bool force=false)
Set the default mesh (if not already set)
Definition: fvExprDriver.C:70
const exprResult & lookupGlobal(const word &name) const
Return the global variable if available or a null result.
Definition: fvExprDriver.C:695
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:642
IOobject io("surfaceFilmProperties", mesh.time().constant(), mesh, IOobject::READ_IF_PRESENT, IOobject::NO_WRITE, IOobject::NO_REGISTER)
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:172
bool isCellSet(const word &name) const
Test if name is a known cellSet.
Definition: fvExprDriver.C:645
Request registration (bool: true)
An input stream of tokens.
Definition: ITstream.H:52
static exprResultGlobals & New(const objectRegistry &obr)
Static constructor for singleton.
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
bool isPointZone(const word &name) const
Test if name is a known pointZone.
Definition: fvExprDriver.C:687