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