Loading...
Searching...
No Matches
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 * * * * * * * * * * * * * //
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
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 }
89 return ptr;
90}
91
92
93// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
94
96(
98 const dictionary& dict
99)
100:
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:
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:
133 globalScopes_(),
134 delayedVariables_(),
135 storedVariables_(),
136 specialVariablesIndex_(-1),
137 otherMeshName_(),
138 writer_(nullptr)
141}
142
143
144// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
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
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
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 (
535 IOobject
536 (
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
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);
588
589 return word::null;
590}
591
592
595{
597
598 if (io.isHeaderClass<cellSet>())
599 {
601 }
602 if (io.isHeaderClass<faceSet>())
603 {
605 }
606 if (io.isHeaderClass<pointSet>())
607 {
610
612}
613
614
617{
618 if (mesh().cellZones().findZoneID(setName) >= 0)
619 {
621 }
622
623 if (mesh().faceZones().findZoneID(setName) >= 0)
624 {
626 }
627
628 if (mesh().pointZones().findZoneID(setName) >= 0)
629 {
632
634}
635
636
639{
640 auto setType = topoZoneType(setName);
641
643 {
644 setType = topoSetType(setName);
646
647 return setType;
648}
649
650
651
652bool Foam::expressions::fvExprDriver::isCellSet(const word& setName) const
653{
654 return
657 == topoSetType(setName)
658 );
659}
660
661
662bool Foam::expressions::fvExprDriver::isFaceSet(const word& setName) const
663{
664 return
667 == topoSetType(setName)
668 );
669}
670
671
672bool Foam::expressions::fvExprDriver::isPointSet(const word& setName) const
673{
674 return
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
711{
712 return (!storedVariables_.empty() || !delayedVariables_.empty());
713}
714
715
717(
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// ************************************************************************* //
@ REGISTER
Request registration (bool: true).
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition IOobjectI.H:223
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:72
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
A collection of cell labels.
Definition cellSet.H:50
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
A keyword and a list of tokens is an 'entry'.
Definition entry.H:66
virtual ITstream & stream() const =0
Return token stream, if entry is a primitive entry.
Base driver for parsing (field) values.
Definition exprDriver.H:137
bool searchFiles() const noexcept
exprResult result_
The result.
Definition exprDriver.H:201
void addVariables(const expressions::exprString &expr, bool clear=true)
Add/set string expressions for variables.
Definition exprDriver.C:372
bool searchRegistry() const noexcept
exprDriver(const exprDriver &)=delete
No copy construct.
bool allowShadowing_
Allow variable names to mask field names.
Definition exprDriver.H:266
searchControls
Search/caching controls.
Definition exprDriver.H:146
virtual bool readDict(const dictionary &dict)
Read variables, tables etc.
Definition exprDriver.C:290
List< expressions::exprString > variableStrings_
Variable definitions, as read from a dictionary.
Definition exprDriver.H:206
HashTable< exprResult > variables_
The variables table.
Definition exprDriver.H:211
virtual exprResult getRemoteResult(const exprDriver &other) const
Get the result from another driver.
Definition exprDriver.C:362
virtual bool update()
Update things.
Definition exprDriver.C:314
virtual unsigned parse(const std::string &expr, size_t pos=0, size_t len=std::string::npos)=0
Execute the parser.
const dictionary & dict() const noexcept
The dictionary with all input data/specification.
Definition exprDriver.H:455
const exprResult & get(const word &name, const wordUList &scopes) const
Return a global variable, if it exists, or a exprResult::null.
static exprResultGlobals & New(const objectRegistry &obr)
Static constructor for singleton.
An exprResult with persistence.
A polymorphic field/result from evaluating an expression.
Definition exprResult.H:122
void testIfSingleValue(const bool parRun=UPstream::parRun())
Test if field corresponds to a single-value and thus uniform.
Definition exprResult.C:440
bool isUniform() const
True if single, uniform value.
A variant of Foam::string with expansion of dictionary variables into a comma-separated form.
Definition exprString.H:58
Base driver for parsing value expressions associated with an fvMesh.
static autoPtr< fvExprDriver > New(const dictionary &dict, const fvMesh &mesh)
Return a reference to the selected value driver.
bool isPointSet(const word &name) const
Test if name is a known pointSet.
bool isFaceSet(const word &name) const
Test if name is a known faceSet.
virtual void updateSpecialVariables(bool force=false)
Examine current variable values and update stored variables.
virtual void prepareData(dictionary &dict) const
Prepare/update special variables and add to dictionary, normally via the reader/writer.
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".
virtual bool hasDataToWrite() const
Do we need a data file to be written.
const exprResult & lookupGlobal(const word &name) const
Return the global variable if available or a null result.
static const fvMesh & defaultMesh()
Get the default mesh, if one is defined.
bool isCellSet(const word &name) const
Test if name is a known cellSet.
bool isPointZone(const word &name) const
Test if name is a known pointZone.
virtual const fvMesh & mesh() const =0
The mesh we are attached to.
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.
topoSetSource::sourceType topoZoneType(const word &name) const
Return cell/face/point zone type or unknown.
virtual bool readDict(const dictionary &dict)
Read variables, tables etc.
word getFieldClassName(const word &name) const
Lookup the field class name (memory or read from disk).
bool isCellZone(const word &name) const
Test if name is a known cellZone.
fvExprDriver(enum exprDriver::searchControls search=exprDriver::searchControls::DEFAULT_SEARCH, const dictionary &dict=dictionary::null)
Default construct, and default construct with search preferences.
virtual label size() const =0
The natural field size for the expression.
bool isFaceZone(const word &name) const
Test if name is a known faceZone.
virtual void evaluateVariable(const word &varName, const expressions::exprString &expr)
Evaluate the expression and save as the specified named variable.
topoSetSource::sourceType topoSetType(const word &name) const
Return cell/face/point set type or unknown.
virtual ~fvExprDriver()
Destructor.
virtual void clearVariables()
Clear temporary variables, reset from expression strings.
static const fvMesh * resetDefaultMesh(const fvMesh &mesh, const bool force=false)
Set the default mesh (if not already set).
topoSetSource::sourceType topoSourceType(const word &name) const
Return cell/face/point zone/set type or unknown.
virtual void getData(const dictionary &dict)
Read data from dictionary, normally via the reader/writer.
word getTypeOfField(const word &fieldName) const
Read the IOobject for fieldName and return its headerClassName.
A list of face labels.
Definition faceSet.H:50
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
const Time & time() const
Return the top-level database.
Definition fvMesh.H:360
@ LITERAL
String literal.
Definition keyType.H:82
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:50
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
sourceType
Enumeration defining the types of sources.
@ POINTSET_SOURCE
Points as set.
@ FACESET_SOURCE
Faces as set.
@ FACEZONE_SOURCE
Faces as zone.
@ UNKNOWN_SOURCE
Placeholder.
@ POINTZONE_SOURCE
Points as zone.
@ CELLSET_SOURCE
Cells as set.
@ CELLZONE_SOURCE
Cells as zone.
static IOobject findIOobject(const polyMesh &mesh, const word &name, IOobjectOption::readOption rOpt=IOobjectOption::MUST_READ, IOobjectOption::writeOption wOpt=IOobjectOption::NO_WRITE, IOobjectOption::registerOption reg=IOobjectOption::LEGACY_REGISTER)
Find IOobject in the polyMesh/sets/ (used as constructor helper).
Definition topoSet.C:352
A class for handling words, derived from Foam::string.
Definition word.H:66
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition word.C:39
static const word null
An empty word.
Definition word.H:84
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
mesh update()
dynamicFvMesh & mesh
Foam::autoPtr< Foam::dynamicFvMesh > meshPtr
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
const auto & io
#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.
ListConstRefWrap< typename Expr::value_type > expr
Fully self-contained constant field wrapper. Not needed?
A namespace for expression-related classes/traits etc.
Namespace for OpenFOAM.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
errorManip< error > abort(error &err)
Definition errorManip.H:139
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition exprTraits.C:127
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition fileName.C:642
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
#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:214