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