Loading...
Searching...
No Matches
fvExprDriverTemplates.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 "surfaceMesh.H"
31#include "pointPatchField.H"
32#include "typeInfo.H"
33
34// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
35
36template<class Type>
38(
39 const word& name,
40 const bool wantPointData,
41 const label expectedSize
42) const
43{
45 << "Looking for global" << (wantPointData ? " point" : "")
46 << " field name:" << name;
47
49
51 << " - found (" << result.valueType() << ' '
52 << result.isPointData() << ')';
53
54
55 bool good =
56 (result.isType<Type>() && result.isPointData(wantPointData));
57
58 // Do size checking if requested
59 if (good && expectedSize >= 0)
60 {
61 good = returnReduceAnd(result.size() == expectedSize);
62
63 if (debug && !good)
64 {
65 Info<< " size is";
66 }
67 }
68
69 DebugInfo << (good ? " good" : " bad") << endl;
71 return good;
72}
73
74
75template<class Type>
78(
79 const word& name,
80 const label expectedSize,
81 const bool mandatory
82) const
83{
85
86 if (hasVariable(name) && variable(name).isType<Type>())
87 {
88 tvar.cref(variable(name));
89 }
90 else if (isGlobalVariable<Type>(name))
91 {
92 tvar.cref(lookupGlobal(name));
93 }
94
95
96 if (tvar.valid())
97 {
98 const auto& var = tvar.cref();
99
100 const Field<Type>& vals = var.cref<Type>();
101
102 if
103 (
104 expectedSize < 0
105 || returnReduceAnd(vals.size() == expectedSize)
106 )
107 {
108 // Return a copy of the field
109 return tmp<Field<Type>>::New(vals);
110 }
111
112 if (!var.isUniform())
113 {
115 << "Variable " << name
116 << " is nonuniform and does not fit the size "
117 << expectedSize << ". Using average" << endl;
118 }
119
120 return tmp<Field<Type>>::New(expectedSize, gAverage(vals));
121 }
122
123 if (mandatory)
124 {
126 << "Variable (" << name << ") not found." << nl
127 << exit(FatalError);
129
130 return nullptr;
131}
132
133
134template<class Type>
136(
137 const word& name
138) const
139{
140 if (debug)
141 {
142 Info<< "fvExprDriver::foundField. Name: " << name
143 << " Type: " << Type::typeName
144 << " registry:" << searchRegistry()
145 << " disk:" << searchFiles() << endl;
146 }
147
148
149 for (int checki = 0; checki < 2; ++checki)
150 {
151 // Check 0: object context (first)
152 // Check 1: regular objectRegistry
153 const regIOobject* ioptr = nullptr;
154
155 if (checki == 0)
156 {
158 }
159 else if (searchRegistry())
160 {
161 ioptr = this->mesh().cfindIOobject(name);
162 }
163 if (!ioptr) continue;
164
165 const Type* fldPtr = dynamic_cast<const Type*>(ioptr);
166
167 if (fldPtr)
168 {
169 if (debug)
170 {
171 if (checki)
172 {
173 Info<< "Found registered:";
174 }
175 else
176 {
177 Info<< "Found context object:";
178 }
179 Info<< name << endl;
180 }
181 return true;
182 }
183 else if (ioptr)
184 {
185 if (debug)
186 {
187 if (checki)
188 {
189 Info<< "Registered:";
190 }
191 else
192 {
193 Info<< "Context object:";
194 }
195 Info<< name << " type:"
196 << ioptr->headerClassName() << " != type:"
197 << Type::typeName << nl;
198 }
199 }
200 }
201
202
203 if (searchFiles() && getTypeOfField(name) == Type::typeName)
204 {
205 if (debug)
206 {
207 Info<< "Found file: " << name << nl;
208 }
209 return true;
210 }
211
212 if (debug)
213 {
214 Info<< name << " not found" << endl;
215 }
216 return false;
217}
218
219
220template<class Type>
222(
223 const word& name,
224 bool wantPointData,
225 label
226) const
227{
228 if (debug)
229 {
230 Info<< "fvExprDriver::isField <" << name << '>' << endl;
231 }
232
233 return
234 (
235 wantPointData
236 ? this->foundField<PointField<Type>>(name)
237 :
238 (
239 this->foundField<VolumeField<Type>>(name)
241 )
242 );
243}
244
245
246template<class GeomField, class Mesh>
248(
249 const word& name,
250 const Mesh& meshRef,
251 bool mandatory,
252 bool getOldTime
253)
254{
255 typedef typename GeomField::value_type Type;
256
257 tmp<GeomField> tfield;
258
259 if (debug)
260 {
261 Info<< "fvExprDriver::getOrReadField <" << name
262 << "> Type: " << GeomField::typeName << endl;
263 }
264
265
266 // Handle variables
267 // ~~~~~~~~~~~~~~~~
268
270
271 if (hasVariable(name) && variable(name).isType<Type>())
272 {
273 tvar.cref(variable(name));
274 }
275 else if (isGlobalVariable<Type>(name))
276 {
277 tvar.cref(lookupGlobal(name));
278 }
279
280 if (tvar.valid())
281 {
282 const auto& var = tvar.cref();
283 const Type deflt(var.getValue<Type>());
284
285 if (debug)
286 {
287 Info<< "Getting " << name << " from variables. Default: "
288 << deflt << endl;
289 }
290
291 if (debug)
292 {
293 Info<< "Creating field " << name << " of type "
294 << GeomField::typeName << nl;
295 }
296
297 tfield = GeomField::New
298 (
299 name,
300 meshRef,
301 dimensioned<Type>(deflt),
302 // Patch is zeroGradient (volFields) or calculated (other)
303 defaultBoundaryType(GeomField::null())
304 );
305 auto& fld = tfield.ref();
306
307 if (debug)
308 {
309 Info<< "New field: " << name << " ownedByRegistry"
310 << fld.ownedByRegistry() << endl;
311 }
312
313 const Field<Type>& vals = var.cref<Type>();
314
315 if (debug)
316 {
317 Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl;
318 }
319
320 if (returnReduceAnd(vals.size() == fld.size()))
321 {
322 fld.primitiveFieldRef() = vals;
323 }
324 else
325 {
326 const Type avg = gAverage(vals);
327
328 bool noWarn = false;
329
330 if (!noWarn)
331 {
332 MinMax<Type> range = gMinMax(vals);
333
334 if (range.mag() > SMALL)
335 {
337 << "The min/max ranges differ " << range
338 << " - using average " << avg << nl;
339 }
340 }
341
342 fld.primitiveFieldRef() = avg;
343 }
344
345 correctField(fld);
346
347 return tfield;
348 }
349
350
351 // Find context or registered field
352 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
353
354 const GeomField* origFldPtr = nullptr;
355
356 for (int checki = 0; !origFldPtr && checki < 2; ++checki)
357 {
358 // Check 0: object context (first)
359 // Check 1: regular objectRegistry
360
361 if (checki == 0)
362 {
364 }
365 else if (searchRegistry())
366 {
367 origFldPtr =
368 meshRef.thisDb().template cfindObject<GeomField>(name);
369 }
370 }
371
372 if (origFldPtr)
373 {
374 // Found from context or registry
375
376 if (debug)
377 {
378 Info<< "Retrieve context/registered:" << name << nl;
379 }
380
381 const GeomField& origFld = *origFldPtr;
382
383 // Make a deep copy of the data to return. Avoids shadowing
384 // the original object, but most importantly the backend
385 // parser (eg, lemon) will be working with combining via plain
386 // pointers. We thus lose any of the tmp<> shallow copy semantics
387 // anyhow. Additionally, need to disable dimension checking here or
388 // elsewhere too.
389
390 tfield = GeomField::New(name + "_exprDriverCopy", origFld);
391
392 if (getOldTime)
393 {
394 if (debug)
395 {
396 Info<< "Getting oldTime of " << name << " has "
397 << origFld.nOldTimes() << endl;
398 }
399
400 if (!origFld.nOldTimes() && this->prevIterIsOldTime())
401 {
402 if (debug)
403 {
404 Info<< "No oldTime, using previous iteration" << endl;
405 }
406 tfield.ref().oldTime() = origFld.prevIter();
407 }
408 }
409 }
410 else if (searchFiles() && getTypeOfField(name) == GeomField::typeName)
411 {
412 if (debug)
413 {
414 Info<< "Reading " << name << " from disc" << endl;
415 }
416
417 tfield.reset
418 (
419 this->readAndRegister<GeomField>(name, meshRef)
420 );
421 // oldTime automatically read
422 }
423
424
425 if (debug)
426 {
427 Info<< "field: valid()=" << Switch::name(tfield.valid()) << endl;
428 }
429
430 if (tfield.valid())
431 {
432 GeomField& fld = tfield.ref();
433
434 if (debug)
435 {
436 Info<< "Valid " << name << " found. Removing dimensions" << nl;
437 }
438
439 fld.dimensions().clear();
440
441 if (fld.nOldTimes())
442 {
443 if (debug)
444 {
445 Info<< "Removing dimensions of oldTime of " << name
446 << " has " << fld.nOldTimes() << nl;
447 }
448
449 // Switch dimension checking off
450 const bool oldDimChecking = dimensionSet::checking(false);
451
452 // go through ALL old times
453 GeomField* fp = &(fld);
454
455 while (fp->nOldTimes())
456 {
457 fp = &(fp->oldTime());
458 fp->dimensions().clear();
459 }
460
461 // Restore old value of dimension checking
462 dimensionSet::checking(oldDimChecking);
463 }
464 }
465 else if (mandatory)
466 {
468 << "Could not find field " << name
469 << " in registry or on file-system" << nl
470 << exit(FatalError);
472
473 return tfield;
474}
475
476
477template<class T>
479(
480 const fvMesh& mesh,
481 const word& name,
482 SetOrigin& origin
483) const
484{
485 // Avoid possible name clashes
486 const word regName = name + "RegisteredNameFor" + T::typeName;
487
488 if (debug)
489 {
490 Info<< "Looking for " << T::typeName << " named " << name
491 << " or registered as " << regName << " with mesh "
492 << "Caching:" << cacheSets()
493 << " Found:" << (mesh.foundObject<T>(name))
494 << " Found registered:" << mesh.foundObject<T>(regName)
495 << endl;
496 }
497
498
499 origin = SetOrigin::INVALID;
500 autoPtr<T> setPtr;
501
502 if
503 (
504 !cacheSets()
505 ||
506 (
507 !mesh.thisDb().foundObject<T>(regName)
508 && !mesh.thisDb().foundObject<T>(name)
509 )
510 )
511 {
512 if (debug)
513 {
514 Info<< "Constructing new " << T::typeName << ' ' << name << nl;
515
516 if (debug > 1)
517 {
518 Pout<< mesh.thisDb().names();
519 }
520 }
521
522 origin = SetOrigin::FILE;
523 setPtr.reset(new T(mesh, name, IOobject::MUST_READ));
524
525 if (cacheSets())
526 {
527 if (debug)
528 {
529 Info<< "Registering a copy of " << name << " with mesh" << nl;
530 }
531
532 autoPtr<T> toCache(new T(mesh, regName, *setPtr));
533 toCache->store(toCache);
534 }
535 }
536 else
537 {
538 const T* ptr = mesh.thisDb().template cfindObject<T>(name);
539
540 if (ptr)
541 {
542 if (debug)
543 {
544 Info<< "Getting existing " << name << endl;
545 }
546
547 origin = SetOrigin::MEMORY;
548 setPtr.reset(new T(mesh, name, *ptr));
549 }
550 else
551 {
552 if (debug)
553 {
554 Info<< "Getting existing " << regName << endl;
555 }
556
557 origin = SetOrigin::CACHE;
558 setPtr.reset(new T(mesh, name, mesh.lookupObject<T>(regName)));
559 }
560 }
562
563 return setPtr;
564}
565
566
567template<class T>
569(
570 autoPtr<T>& setPtr,
571 const word& name,
572 SetOrigin origin
573) const
574{
575 const label oldSize = setPtr->size();
576
577 bool updated = false;
578 const auto& mesh = refCast<const polyMesh>(setPtr->db());
579
580 if (debug)
581 {
582 Info<< "UpdateSet: " << setPtr->name() << " Id: " << name
583 << " Origin: " << int(origin) << endl;
584 }
585
586 switch (origin)
587 {
588 case SetOrigin::FILE:
589 {
590 IOobject header
591 (
592 name,
593 mesh.time().timeName(),
595 mesh,
598 );
599
600 if (header.typeHeaderOk<T>())
601 {
602 if (debug)
603 {
604 Pout<< "Rereading from "
605 << header.localFilePath(T::typeName) << endl;
606 }
607 setPtr.reset(new T(header));
608 updated = true;
609 }
610 break;
611 }
612
613 case SetOrigin::NEW:
614 case SetOrigin::MEMORY:
615 case SetOrigin::CACHE:
616 {
617 if (origin == SetOrigin::NEW)
618 {
620 << "State NEW shouldn't exist"
621 << endl;
622 }
623
624 word sName = name;
625
626 const T* ptr = mesh.thisDb().template cfindObject<T>(name);
627
628 if (ptr)
629 {
630 if (debug)
631 {
632 Info<< "Found " << name
633 << " and rereading it" << endl;
634 }
635
636 setPtr.reset(new T(mesh, name, *ptr));
637 }
638 else
639 {
641 << name << " Not found" << endl
642 << "In registry: " << mesh.thisDb().names() << endl
643 << exit(FatalError);
644 }
645 updated = true;
646 break;
647 }
648
649 case INVALID:
650 {
652 << T::typeName << ' ' << name << " is invalid" << endl
653 << exit(FatalError);
654 break;
655 }
656
657 default:
658 {
659 if (debug)
660 {
661 Info<< "Origin " << int(origin) << " not implemented" << endl;
662 }
663 break;
664 }
665 }
666
667 if (debug)
668 {
669 Pout<< name << " old size " << oldSize << " new: "
670 << setPtr->size() << endl;
671 }
672
673 return updated;
674}
675
676
677// ************************************************************************* //
scalar range
Info<< nl;Info<< "Write faMesh in vtk format:"<< nl;{ vtk::uindirectPatchWriter writer(aMesh.patch(), fileName(aMesh.time().globalPath()/vtkBaseFileName));writer.writeGeometry();globalIndex procAddr(aMesh.nFaces());labelList cellIDs;if(UPstream::master()) { cellIDs.resize(procAddr.totalSize());for(const labelRange &range :procAddr.ranges()) { auto slice=cellIDs.slice(range);slice=identity(range);} } writer.beginCellData(4);writer.writeProcIDs();writer.write("cellID", cellIDs);writer.write("area", aMesh.S().field());writer.write("normal", aMesh.faceAreaNormals());writer.beginPointData(1);writer.write("normal", aMesh.pointAreaNormals());Info<< " "<< writer.output().name()<< nl;}{ vtk::lineWriter writer(aMesh.points(), aMesh.edges(), fileName(aMesh.time().globalPath()/(vtkBaseFileName+"-edges")));writer.writeGeometry();writer.beginCellData(4);writer.writeProcIDs();{ Field< scalar > fld(faMeshTools::flattenEdgeField(aMesh.magLe(), true))
Generic templated field type that is much like a Foam::List except that it is expected to hold numeri...
Definition Field.H:172
@ 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
bool typeHeaderOk(const bool checkType=true, const bool search=true, const bool verbose=true)
Read header (respects is_globalIOobject trait) and check its info. A void type suppresses trait and t...
fileName localFilePath(const word &typeName, const bool search=true) const
Redirect to fileHandler filePath, searching locally.
Definition IOobject.C:593
A min/max value pair with additional methods. In addition to conveniently storing values,...
Definition MinMax.H:106
static const char * name(bool b) noexcept
A string representation of bool as "false" / "true".
void size(const label n)
Older name for setAddressableSize.
Definition UList.H:118
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
static bool checking() noexcept
True if dimension checking is enabled (the usual default).
Generic dimensioned Type class.
bool searchFiles() const noexcept
bool searchRegistry() const noexcept
const ObjType * cfindContextObject(const word &name) const
Find context field object of specified type.
const exprResult & result() const noexcept
Const access to expression result.
Definition exprDriver.H:463
const regIOobject * cfindContextIOobject(const word &name) const
Find named context field, if it exists.
A polymorphic field/result from evaluating an expression.
Definition exprResult.H:122
virtual exprResult & variable(const word &name)
Non-const access to the named variable (sub-classes only).
bool foundField(const word &name) const
Test if specified field can be found in memory or disk.
tmp< Field< Type > > getVariable(const word &name, const label expectSize, const bool mandatory=true) const
Retrieve local/global variable as a tmp field.
tmp< GeomField > readAndRegister(const word &name, const MeshRef &meshRef)
Helper function for getOrReadField.
const exprResult & lookupGlobal(const word &name) const
Return the global variable if available or a null result.
tmp< GeomField > getOrReadFieldImpl(const word &name, const MeshRef &meshRef, const bool mandatory=true, const bool getOldTime=false)
Retrieve field from memory or disk (implementation).
virtual const fvMesh & mesh() const =0
The mesh we are attached to.
static word defaultBoundaryType(const T &)
Default boundary type is calculated.
bool isField(const word &name, const bool wantPointData=false, const label expectSize=-1) const
Test for the existence of a mesh field.
static void correctField(T &)
Apply correctBoundaryConditions (volume fields only).
autoPtr< T > getTopoSet(const fvMesh &mesh, const word &setName, SetOrigin &origin) const
Get topoSet.
virtual bool hasVariable(const word &name) const
True if named variable exists.
bool cacheSets() const
Status of cache-sets (static variable).
bool updateSet(autoPtr< T > &setPtr, const word &setName, SetOrigin origin) const
Update topoSet.
word getTypeOfField(const word &fieldName) const
Read the IOobject for fieldName and return its headerClassName.
SetOrigin
The origin of the topoSet.
bool isGlobalVariable(const word &name, const bool wantPointData=false, const label expectedSize=-1) const
Test existence of a global variable.
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
static word meshSubDir
Return the mesh sub-directory name (usually "polyMesh").
Definition polyMesh.H:411
A class for managing references or pointers (no reference counting).
Definition refPtr.H:54
const T & cref() const
Return const reference to the object or to the contents of a (non-null) managed pointer.
Definition refPtrI.H:216
bool valid() const noexcept
Identical to good(), or bool operator.
Definition refPtr.H:512
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition regIOobject.H:71
A class for managing temporary objects.
Definition tmp.H:75
bool valid() const noexcept
Identical to good(), or bool operator.
Definition tmp.H:481
void reset(tmp< T > &&other) noexcept
Clear existing and transfer ownership.
Definition tmpI.H:338
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition tmpI.H:235
A class for handling words, derived from Foam::string.
Definition word.H:66
const volScalarField & T
dynamicFvMesh & mesh
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
auto & name
#define DebugInfo
Report an information message using Foam::Info.
#define WarningInFunction
Report a warning using Foam::Warning.
Namespace for handling debugging switches.
Definition debug.C:45
@ INVALID
Invalid/unknown/error type.
Definition exprTraits.H:84
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
Type & refCast(U &obj)
A dynamic_cast (for references) to Type reference.
Definition typeInfo.H:172
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh > > &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
GeometricField< Type, fvPatchField, volMesh > VolumeField
A volume field for a given type.
messageStream Info
Information stream (stdout output on master, null elsewhere).
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
bool returnReduceAnd(const bool value, const int communicator=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
MinMax< Type > gMinMax(const FieldField< Field, Type > &f)
bool isType(const U &obj)
Check if typeid of the object and Type are identical.
Definition typeInfo.H:112
GeometricField< Type, pointPatchField, pointMesh > PointField
A point field for a given type.
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
prefixOSstream Pout
OSstream wrapped stdout (std::cout) with parallel prefix.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition errorManip.H:125
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
GeometricField< Type, fvsPatchField, surfaceMesh > SurfaceField
A (volume) surface field for a given type.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
Basic run-time type information using word as the type's name. Used to enhance the standard RTTI to c...