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-2021 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 "surfaceMesh.H"
30 #include "fvsPatchField.H"
31 #include "pointPatchField.H"
32 #include "typeInfo.H"
33 
34 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
35 
36 template<class Type>
38 (
39  const word& name,
40  const bool wantPointData,
41  const label expectedSize
42 ) const
43 {
44  DebugInfo
45  << "Looking for global" << (wantPointData ? " point" : "")
46  << " field name:" << name;
47 
48  const expressions::exprResult& result = lookupGlobal(name);
49 
50  DebugInfo
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 = (result.size() == expectedSize);
62  reduce(good, andOp<bool>());
63 
64  if (debug && !good)
65  {
66  Info<< " size is";
67  }
68  }
69 
70  DebugInfo << (good ? " good" : " bad") << endl;
71 
72  return good;
73 }
74 
75 
76 template<class Type>
79 (
80  const word& name,
81  const label expectedSize,
82  const bool mandatory
83 ) const
84 {
86 
87  if (hasVariable(name) && variable(name).isType<Type>())
88  {
89  tvar.cref(variable(name));
90  }
91  else if (isGlobalVariable<Type>(name))
92  {
93  tvar.cref(lookupGlobal(name));
94  }
95 
96 
97  if (tvar.valid())
98  {
99  const auto& var = tvar.cref();
100 
101  const Field<Type>& vals = var.cref<Type>();
102 
103  if
104  (
105  expectedSize < 0
106  || returnReduce((vals.size() == expectedSize), andOp<bool>())
107  )
108  {
109  // Return a copy of the field
110  return tmp<Field<Type>>::New(vals);
111  }
112 
113  if (!var.isUniform())
114  {
116  << "Variable " << name
117  << " is nonuniform and does not fit the size "
118  << expectedSize << ". Using average" << endl;
119  }
120 
121  return tmp<Field<Type>>::New(expectedSize, gAverage(vals));
122  }
123 
124  if (mandatory)
125  {
127  << "Variable (" << name << ") not found." << nl
128  << exit(FatalError);
129  }
130 
131  return nullptr;
132 }
133 
134 
135 template<class Type>
137 (
138  const word& name
139 ) const
140 {
141  if (debug)
142  {
143  Info<< "fvExprDriver::foundField. Name: " << name
144  << " Type: " << Type::typeName
145  << " registry:" << searchRegistry()
146  << " disk:" << searchFiles() << endl;
147  }
148 
149 
150  for (int checki = 0; checki < 2; ++checki)
151  {
152  // Check 0: object context (first)
153  // Check 1: regular objectRegistry
154  const regIOobject* ioptr = nullptr;
155 
156  if (checki == 0)
157  {
158  ioptr = exprDriver::cfindContextIOobject(name);
159  }
160  else if (searchRegistry())
161  {
162  ioptr = this->mesh().cfindIOobject(name);
163  }
164  if (!ioptr) continue;
165 
166  const Type* fldPtr = dynamic_cast<const Type*>(ioptr);
167 
168  if (fldPtr)
169  {
170  if (debug)
171  {
172  if (checki)
173  {
174  Info<< "Found registered:";
175  }
176  else
177  {
178  Info<< "Found context object:";
179  }
180  Info<< name << endl;
181  }
182  return true;
183  }
184  else if (ioptr)
185  {
186  if (debug)
187  {
188  if (checki)
189  {
190  Info<< "Registered:";
191  }
192  else
193  {
194  Info<< "Context object:";
195  }
196  Info<< name << " type:"
197  << ioptr->headerClassName() << " != type:"
198  << Type::typeName << nl;
199  }
200  }
201  }
202 
203 
204  if (searchFiles() && getTypeOfField(name) == Type::typeName)
205  {
206  if (debug)
207  {
208  Info<< "Found file: " << name << nl;
209  }
210  return true;
211  }
212 
213  if (debug)
214  {
215  Info<< name << " not found" << endl;
216  }
217  return false;
218 }
219 
220 
221 template<class Type>
223 (
224  const word& name,
225  bool wantPointData,
226  label
227 ) const
228 {
229  if (debug)
230  {
231  Info<< "fvExprDriver::isField <" << name << '>' << endl;
232  }
233 
234  typedef GeometricField<Type, fvPatchField, volMesh> vfieldType;
235  typedef GeometricField<Type, fvsPatchField, surfaceMesh> sfieldType;
236  typedef GeometricField<Type, pointPatchField, pointMesh> pfieldType;
237 
238  return
239  (
240  wantPointData
241  ? this->foundField<pfieldType>(name)
242  :
243  (
244  this->foundField<vfieldType>(name)
245  || this->foundField<sfieldType>(name)
246  )
247  );
248 }
249 
250 
251 template<class GeomField, class Mesh>
252 Foam::tmp<GeomField> Foam::expressions::fvExprDriver::getOrReadFieldImpl
253 (
254  const word& name,
255  const Mesh& meshRef,
256  bool mandatory,
257  bool getOldTime
258 )
259 {
260  typedef typename GeomField::value_type Type;
261 
262  tmp<GeomField> tfield;
263 
264  if (debug)
265  {
266  Info<< "fvExprDriver::getOrReadField <" << name
267  << "> Type: " << GeomField::typeName << endl;
268  }
269 
270 
271  // Handle variables
272  // ~~~~~~~~~~~~~~~~
273 
274  refPtr<expressions::exprResult> tvar;
275 
276  if (hasVariable(name) && variable(name).isType<Type>())
277  {
278  tvar.cref(variable(name));
279  }
280  else if (isGlobalVariable<Type>(name))
281  {
282  tvar.cref(lookupGlobal(name));
283  }
284 
285  if (tvar.valid())
286  {
287  const auto& var = tvar.cref();
288  const Type deflt(var.getValue<Type>());
289 
290  if (debug)
291  {
292  Info<< "Getting " << name << " from variables. Default: "
293  << deflt << endl;
294  }
295 
296  if (debug)
297  {
298  Info<< "Creating field " << name << " of type "
299  << GeomField::typeName << nl;
300  }
301 
302  tfield = GeomField::New
303  (
304  name,
305  meshRef,
306  dimensioned<Type>(deflt),
307  // Patch is zeroGradient (volFields) or calculated (other)
308  defaultBoundaryType(GeomField::null())
309  );
310  auto& fld = tfield.ref();
311 
312  if (debug)
313  {
314  Info<< "New field: " << name << " ownedByRegistry"
315  << fld.ownedByRegistry() << endl;
316  }
317 
318  const Field<Type>& vals = var.cref<Type>();
319 
320  if (debug)
321  {
322  Pout<< "sizes: " << vals.size() << ' ' << fld.size() << endl;
323  }
324 
325  if (returnReduce((vals.size() == fld.size()), andOp<bool>()))
326  {
327  fld.primitiveFieldRef() = vals;
328  }
329  else
330  {
331  const Type avg = gAverage(vals);
332 
333  bool noWarn = false;
334 
335  if (!noWarn)
336  {
337  MinMax<Type> range = gMinMax(vals);
338 
339  if (range.mag() > SMALL)
340  {
341  WarningInFunction
342  << "The min/max ranges differ " << range
343  << " - using average " << avg << nl;
344  }
345  }
346 
347  fld.primitiveFieldRef() = avg;
348  }
349 
350  correctField(fld);
351 
352  return tfield;
353  }
354 
355 
356  // Find context or registered field
357  // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
358 
359  const GeomField* origFldPtr = nullptr;
360 
361  for (int checki = 0; !origFldPtr && checki < 2; ++checki)
362  {
363  // Check 0: object context (first)
364  // Check 1: regular objectRegistry
365 
366  if (checki == 0)
367  {
368  origFldPtr = exprDriver::cfindContextObject<GeomField>(name);
369  }
370  else if (searchRegistry())
371  {
372  origFldPtr =
373  meshRef.thisDb().template cfindObject<GeomField>(name);
374  }
375  }
376 
377  if (origFldPtr)
378  {
379  // Found from context or registry
380 
381  if (debug)
382  {
383  Info<< "Retrieve context/registered:" << name << nl;
384  }
385 
386  const GeomField& origFld = *origFldPtr;
387 
388  // Make a deep copy of the data to return. Avoids shadowing
389  // the original object, but most importantly the backend
390  // parser (eg, lemon) will be working with combining via plain
391  // pointers. We thus lose any of the tmp<> shallow copy semantics
392  // anyhow. Additionally, need to disable dimension checking here or
393  // elsewhere too.
394 
395  tfield = GeomField::New(name + "_exprDriverCopy", origFld);
396 
397  if (getOldTime)
398  {
399  if (debug)
400  {
401  Info<< "Getting oldTime of " << name << " has "
402  << origFld.nOldTimes() << endl;
403  }
404 
405  if (!origFld.nOldTimes() && this->prevIterIsOldTime())
406  {
407  if (debug)
408  {
409  Info<< "No oldTime, using previous iteration" << endl;
410  }
411  tfield.ref().oldTime() = origFld.prevIter();
412  }
413  }
414  }
415  else if (searchFiles() && getTypeOfField(name) == GeomField::typeName)
416  {
417  if (debug)
418  {
419  Info<< "Reading " << name << " from disc" << endl;
420  }
421 
422  tfield.reset
423  (
424  this->readAndRegister<GeomField>(name, meshRef)
425  );
426  // oldTime automatically read
427  }
428 
429 
430  if (debug)
431  {
432  Info<< "field: valid()=" << Switch::name(tfield.valid()) << endl;
433  }
434 
435  if (tfield.valid())
436  {
437  GeomField& fld = tfield.ref();
438 
439  if (debug)
440  {
441  Info<< "Valid " << name << " found. Removing dimensions" << nl;
442  }
443 
444  fld.dimensions().clear();
445 
446  if (fld.nOldTimes())
447  {
448  if (debug)
449  {
450  Info<< "Removing dimensions of oldTime of " << name
451  << " has " << fld.nOldTimes() << nl;
452  }
453 
454  // Switch dimension checking off
455  const bool oldDimChecking = dimensionSet::checking(false);
456 
457  // go through ALL old times
458  GeomField* fp = &(fld);
459 
460  while (fp->nOldTimes())
461  {
462  fp = &(fp->oldTime());
463  fp->dimensions().clear();
464  }
465 
466  // Restore old value of dimension checking
467  dimensionSet::checking(oldDimChecking);
468  }
469  }
470  else if (mandatory)
471  {
472  FatalErrorInFunction
473  << "Could not find field " << name
474  << " in registry or on file-system" << nl
475  << exit(FatalError);
476  }
477 
478  return tfield;
479 }
480 
481 
482 template<class T>
483 Foam::autoPtr<T> Foam::expressions::fvExprDriver::getTopoSet
484 (
485  const fvMesh& mesh,
486  const word& name,
487  SetOrigin& origin
488 ) const
489 {
490  // Avoid possible name clashes
491  const word regName = name + "RegisteredNameFor" + T::typeName;
492 
493  if (debug)
494  {
495  Info<< "Looking for " << T::typeName << " named " << name
496  << " or registered as " << regName << " with mesh "
497  << "Caching:" << cacheSets()
498  << " Found:" << (mesh.foundObject<T>(name))
499  << " Found registered:" << mesh.foundObject<T>(regName)
500  << endl;
501  }
502 
503 
504  origin = SetOrigin::INVALID;
505  autoPtr<T> setPtr;
506 
507  if
508  (
509  !cacheSets()
510  ||
511  (
512  !mesh.thisDb().foundObject<T>(regName)
513  && !mesh.thisDb().foundObject<T>(name)
514  )
515  )
516  {
517  if (debug)
518  {
519  Info<< "Constructing new " << T::typeName << ' ' << name << nl;
520 
521  if (debug > 1)
522  {
523  Pout<< mesh.thisDb().names();
524  }
525  }
526 
527  origin = SetOrigin::FILE;
528  setPtr.reset(new T(mesh, name, IOobject::MUST_READ));
529 
530  if (cacheSets())
531  {
532  if (debug)
533  {
534  Info<< "Registering a copy of " << name << " with mesh" << nl;
535  }
536 
537  autoPtr<T> toCache(new T(mesh, regName, *setPtr));
538  toCache->store(toCache);
539  }
540  }
541  else
542  {
543  const T* ptr = mesh.thisDb().template cfindObject<T>(name);
544 
545  if (ptr)
546  {
547  if (debug)
548  {
549  Info<< "Getting existing " << name << endl;
550  }
551 
552  origin = SetOrigin::MEMORY;
553  setPtr.reset(new T(mesh, name, *ptr));
554  }
555  else
556  {
557  if (debug)
558  {
559  Info<< "Getting existing " << regName << endl;
560  }
561 
562  origin = SetOrigin::CACHE;
563  setPtr.reset(new T(mesh, name, mesh.lookupObject<T>(regName)));
564  }
565  }
566 
567 
568  return setPtr;
569 }
570 
571 
572 template<class T>
573 bool Foam::expressions::fvExprDriver::updateSet
574 (
575  autoPtr<T>& setPtr,
576  const word& name,
577  SetOrigin origin
578 ) const
579 {
580  const label oldSize = setPtr->size();
581 
582  bool updated = false;
583  const auto& mesh = dynamicCast<const polyMesh>(setPtr->db());
584 
585  if (debug)
586  {
587  Info<< "UpdateSet: " << setPtr->name() << " Id: " << name
588  << " Origin: " << int(origin) << endl;
589  }
590 
591  switch (origin)
592  {
593  case SetOrigin::FILE:
594  {
595  IOobject header
596  (
597  name,
598  mesh.time().timeName(),
599  polyMesh::meshSubDir/"sets",
600  mesh,
601  IOobject::MUST_READ,
602  IOobject::NO_WRITE
603  );
604 
605  if (header.typeHeaderOk<T>())
606  {
607  if (debug)
608  {
609  Pout<< "Rereading from "
610  << header.localFilePath(T::typeName) << endl;
611  }
612  setPtr.reset(new T(header));
613  updated = true;
614  }
615  break;
616  }
617 
618  case SetOrigin::NEW:
619  case SetOrigin::MEMORY:
620  case SetOrigin::CACHE:
621  {
622  if (origin == SetOrigin::NEW)
623  {
624  WarningInFunction
625  << "State NEW shouldn't exist"
626  << endl;
627  }
628 
629  word sName = name;
630 
631  const T* ptr = mesh.thisDb().template cfindObject<T>(name);
632 
633  if (ptr)
634  {
635  if (debug)
636  {
637  Info<< "Found " << name
638  << " and rereading it" << endl;
639  }
640 
641  setPtr.reset(new T(mesh, name, *ptr));
642  }
643  else
644  {
645  FatalErrorInFunction
646  << name << " Not found" << endl
647  << "In registry: " << mesh.thisDb().names() << endl
648  << exit(FatalError);
649  }
650  updated = true;
651  break;
652  }
653 
654  case INVALID:
655  {
656  FatalErrorInFunction
657  << T::typeName << ' ' << name << " is invalid" << endl
658  << exit(FatalError);
659  break;
660  }
661 
662  default:
663  {
664  if (debug)
665  {
666  Info<< "Origin " << int(origin) << " not implemented" << endl;
667  }
668  break;
669  }
670  }
671 
672  if (debug)
673  {
674  Pout<< name << " old size " << oldSize << " new: "
675  << setPtr->size() << endl;
676  }
677 
678  return updated;
679 }
680 
681 
682 // ************************************************************************* //
Foam::expressions::patchExpr::debug
int debug
Static debugging option.
fvsPatchField.H
Foam::word
A class for handling words, derived from Foam::string.
Definition: word.H:65
Foam::returnReduce
T returnReduce(const T &Value, const BinaryOp &bop, const int tag=Pstream::msgType(), const label comm=UPstream::worldComm)
Definition: PstreamReduceOps.H:94
typeInfo.H
Foam::tmp
A class for managing temporary objects.
Definition: PtrList.H:61
Foam::gAverage
Type gAverage(const FieldField< Field, Type > &f)
Definition: FieldFieldFunctions.C:604
pointPatchField.H
Foam::expressions::fvExprDriver::foundField
bool foundField(const word &name) const
Test if specified field can be found in memory or disk.
Definition: fvExprDriverTemplates.C:137
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
Foam::IOobject::headerClassName
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition: IOobjectI.H:83
Foam::expressions::fvExprDriver::isGlobalVariable
bool isGlobalVariable(const word &name, const bool wantPointData=false, const label expectedSize=-1) const
Test existence of a global variable.
Definition: fvExprDriverTemplates.C:38
Foam::refPtr::valid
bool valid() const noexcept
Identical to good(), or bool operator.
Definition: refPtr.H:300
Foam::expressions::exprResult
A polymorphic field/result from evaluating an expression.
Definition: exprResult.H:124
Foam::Field
Generic templated field type.
Definition: Field.H:63
Foam::expressions::fvExprDriver::getVariable
tmp< Field< Type > > getVariable(const word &name, const label expectSize, const bool mandatory=true) const
Retrieve local/global variable as a tmp field.
Foam::refPtr::cref
const T & cref() const
Definition: refPtrI.H:189
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::andOp
Definition: ops.H:233
Foam::FatalError
error FatalError
surfaceMesh.H
reduce
reduce(hasMovingMesh, orOp< bool >())
mesh
dynamicFvMesh & mesh
Definition: createDynamicFvMesh.H:6
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::New
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tdf1, const word &name, const dimensionSet &dimensions)
Global function forwards to reuseTmpDimensionedField::New.
Definition: DimensionedFieldReuseFunctions.H:105
found
bool found
Definition: TABSMDCalcMethod2.H:32
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:73
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
DebugInfo
#define DebugInfo
Report an information message using Foam::Info.
Definition: messageStream.H:382
Foam::nl
constexpr char nl
Definition: Ostream.H:404
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
Foam::expressions::fvExprDriver::isField
bool isField(const word &name, const bool wantPointData=false, const label expectSize=-1) const
Test for the existence of a mesh field.
Definition: fvExprDriverTemplates.C:223
Foam::refPtr
A class for managing references or pointers (no reference counting)
Definition: PtrList.H:60