fvExpressionField.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) 2021 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "fvExpressionField.H"
29 #include "volFields.H"
30 #include "surfaceFields.H"
31 #include "pointMesh.H"
32 #include "pointFields.H"
33 #include "volumeExprDriver.H"
34 #include "calculatedFvPatchField.H"
36 
37 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 namespace functionObjects
42 {
43  defineTypeNameAndDebug(fvExpressionField, 0);
44  addToRunTimeSelectionTable(functionObject, fvExpressionField, dictionary);
45 }
46 }
47 
48 
49 const Foam::Enum
50 <
52 >
54 ({
55  { actionType::opNone, "none" },
56  { actionType::opNew, "new" },
57  { actionType::opModify, "modify" },
58 });
59 
60 
61 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
62 
63 namespace Foam
64 {
65 
67 {
68  switch (geoType)
69  {
70  case expressions::FieldAssociation::POINT_DATA : return "points"; break;
71  case expressions::FieldAssociation::FACE_DATA : return "faces"; break;
72  case expressions::FieldAssociation::VOLUME_DATA : return "cells"; break;
73  default: break;
74  }
75  return "unknown";
76 }
77 
78 
79 template<class Type>
81 (
82  bool correctBCs,
84 )
85 {
86  if (correctBCs)
87  {
88  // Info<< "Correcting boundary conditions: " << field.name() << nl;
89  field.correctBoundaryConditions();
90 
91  // Ensure that calculated patches are updated
92  for (auto& pf : field.boundaryFieldRef())
93  {
95  {
96  pf = pf.patchInternalField();
97  }
98  }
99  }
100 }
101 
102 
103 template<class Type>
105 (
106  bool correctBCs,
108 )
109 {
110  if (correctBCs)
111  {
112  // Info<< "Correcting boundary conditions: " << field.name() << nl;
113  field.correctBoundaryConditions();
114  }
115 }
116 
117 
118 template<class Type>
120 (
121  bool correctBCs,
123 )
124 {}
125 
126 } // End namespace Foam
127 
128 
129 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
130 
131 template<class FieldType>
133 {
134  if (FieldType::typeName == io.headerClassName())
135  {
136  // Store field on mesh database
137  Log << " Reading " << io.name()
138  << " (" << FieldType::typeName << ')' << endl;
139 
140  mesh_.objectRegistry::store(new FieldType(io, mesh_));
141  return true;
142  }
143 
144  return false;
145 }
146 
147 
148 template<class Type>
150 {
151  typedef GeometricField<Type, fvPatchField, volMesh> VolFieldType;
152  // typedef typename VolFieldType::Internal IntVolFieldType;
153  typedef GeometricField<Type, fvsPatchField, surfaceMesh> SurfaceFieldType;
154 
155  return
156  (
157  loadAndStore<VolFieldType>(io)
159  || loadAndStore<SurfaceFieldType>(io)
160  );
161 }
162 
163 
165 (
166  const UList<word>& fieldSet_
167 )
168 {
169  label nLoaded = 0;
170 
171  for (const word& fieldName : fieldSet_)
172  {
173  // Already loaded?
174  const auto* ptr = mesh_.cfindObject<regIOobject>(fieldName);
175 
176  if (ptr)
177  {
178  ++nLoaded;
179  DebugInfo
180  << "readFields : "
181  << ptr->name() << " (" << ptr->type()
182  << ") already in database" << endl;
183  continue;
184  }
185 
186  // Load field as necessary
187  IOobject io
188  (
189  fieldName,
190  mesh_.time().timeName(),
191  mesh_,
194  );
195 
196  const bool ok =
197  (
198  io.typeHeaderOk<regIOobject>(false) // Preload header info
199  && !io.headerClassName().empty() // Extra safety
200  &&
201  (
202  loadField<scalar>(io)
203  || loadField<vector>(io)
204  || loadField<sphericalTensor>(io)
205  || loadField<symmTensor>(io)
206  || loadField<tensor>(io)
207  )
208  );
209 
210  if (ok)
211  {
212  ++nLoaded;
213  }
214  else
215  {
216  DebugInfo
217  << "readFields : failed to load " << fieldName << endl;
218  }
219  }
220 
221  return nLoaded;
222 }
223 
224 
225 template<class GeoField>
227 (
228  GeoField& output,
229  const GeoField& evaluated,
230  const boolField& fieldMask
231 )
232 {
233  label numValuesChanged = 0;
234 
235  // Internal field
236  if (fieldMask.empty())
237  {
238  // No field-mask - set all
239  numValuesChanged = output.size();
240 
241  output.primitiveFieldRef() = evaluated;
242  }
243  else
244  {
245  auto& internal = output.primitiveFieldRef();
246 
247  forAll(internal, idx)
248  {
249  if (fieldMask[idx])
250  {
251  internal[idx] = evaluated[idx];
252  ++numValuesChanged;
253  }
254  }
255  }
256 
257  // Boundary fields
258  forAll(evaluated.boundaryField(), patchi)
259  {
260  auto& pf = output.boundaryFieldRef()[patchi];
261 
262  if (pf.patch().coupled())
263  {
264  pf == evaluated.boundaryField()[patchi];
265  }
266  }
267 
269 
270  if (action_ == actionType::opModify && log)
271  {
272  const label numTotal = returnReduce(output.size(), plusOp<label>());
273  reduce(numValuesChanged, plusOp<label>());
274 
275  Info<< this->name() << ": set ";
276  if (numValuesChanged == numTotal)
277  {
278  Info<< "all ";
279  }
280  else
281  {
282  Info<< numValuesChanged << " of ";
283  }
284  Info<< numTotal << " values (field: "
285  << output.name() << ')' << nl << endl;
286  }
287 
288  if (hasDimensions_)
289  {
290  // Log<< "Setting dimensions to " << dims << endl;
291  output.dimensions().reset(dimensions_);
292  }
293 
294  return true;
295 }
296 
297 
298 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
299 
301 (
302  const word& name,
303  const Time& runTime,
304  const dictionary& dict,
305  const bool loadFromFiles
306 )
307 :
309  dict_(dict), // Deep copy
310  fieldName_(),
311  preloadFields_(),
312  maskExpr_(),
313  valueExpr_(),
314  dimensions_(),
315  action_(actionType::opNew),
316  autowrite_(false),
317  store_(true),
318  hasDimensions_(false),
319  loadFromFiles_(loadFromFiles)
320 {
321  read(dict);
322 }
323 
324 
325 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
326 
328 {}
329 
330 
331 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
332 
334 {
335  switch (action_)
336  {
337  case actionType::opNone:
338  {
339  break; // No-op
340  }
341  case actionType::opNew:
342  {
343  return scopedName(fieldName_);
344  }
345  case actionType::opModify:
346  {
347  return fieldName_;
348  }
349  }
350 
351  return word::null;
352 }
353 
354 
356 {
358 
359  action_ = actionNames_.getOrDefault("action", dict, actionType::opNew);
360 
361  fieldName_ = dict.get<word>("field");
362  const word fldName = fieldName();
363 
364  Log << type() << ' ' << this->name() << ':' << nl
365  << " action = " << actionNames_[action_] << nl
366  << " field = " << fldName << nl;
367 
368  maskExpr_.clear();
369  valueExpr_.clear();
370 
371  preloadFields_.clear();
372  dict.readIfPresent("readFields", preloadFields_);
373 
374  switch (action_)
375  {
376  case actionType::opNone:
377  {
378  // No-op
379  break;
380  }
381  case actionType::opModify:
382  {
383  // Optional <fieldMask> for modify
384  maskExpr_.readEntry("fieldMask", dict, false);
385  [[fallthrough]];
386  }
387  case actionType::opNew:
388  {
389  // Mandatory <expression> for new and modify
390  valueExpr_.readEntry("expression", dict);
391  break;
392  }
393  }
394 
395  autowrite_ = dict.getOrDefault("autowrite", false);
396  store_ = dict.getOrDefault("autowrite", true);
397 
398  // "dimensions" is optional
399  dimensions_.clear();
400  hasDimensions_ = dimensions_.readEntry("dimensions", dict, false);
401 
402  if (action_ == actionType::opNew)
403  {
404  if (!hasDimensions_)
405  {
406  Log << " no 'dimensions' : treat '" << fldName
407  << "' as dimensionless" << endl;
408  }
409  }
410  else
411  {
412  // Ignore for none/modify
413  hasDimensions_ = false;
414  }
415 
416 
417  if (action_ == actionType::opNone)
418  {
419  driver_.reset(nullptr);
420  return true; // Done
421  }
422 
423  driver_.reset
424  (
425  new expressions::volumeExprDriver(mesh_, dict_)
426  );
427 
428  driver_->setSearchBehaviour
429  (
431  (
433  | (
434  loadFromFiles_
436  : int(0)
437  )
438  ),
439  false // No caching
440  );
441 
442  driver_->readDict(dict_);
443 
444  return true;
445 }
446 
447 
449 {
451 
452  if (!driver_ || action_ == actionType::opNone)
453  {
454  // No-op
455  return true;
456  }
457 
458  const word fldName = fieldName();
459 
460  if (loadFromFiles_)
461  {
462  loadFields(preloadFields_);
463  }
464 
465  if (action_ == actionType::opModify && loadFromFiles_)
466  {
467  loadFields(wordList({fldName}));
468  }
469 
470  auto& driver = *driver_;
471 
472 
473  // Current availability
474  auto* regIOobjectPtr = mesh_.getObjectPtr<regIOobject>(fldName);
475 
476  if (action_ == actionType::opModify && !regIOobjectPtr)
477  {
478  // Cannot continue
480  << type() << ' ' << this->name() << ':' << nl
481  << " missing-field: " << fldName << nl
482  << exit(FatalError);
483 
484  return false;
485  }
486 
487 
488  // Handle "field-mask" evaluation
489  bool evalFieldMask
490  (
491  (action_ == actionType::opModify)
492  && maskExpr_.size() && maskExpr_ != "true" && maskExpr_ != "1"
493  );
494 
495  boolField fieldMask;
497 
498  if (evalFieldMask)
499  {
500  driver.parse(maskExpr_);
501 
502  if (driver.isLogical())
503  {
504  auto& result = driver.result();
505  if (result.is_bool())
506  {
507  fieldMask = result.getResult<bool>();
508  maskFieldAssoc = driver.fieldAssociation();
509  }
510  }
511 
512  // Slightly pedantic...
513  driver.clearField();
514  driver.clearResult();
515 
516  evalFieldMask = (maskFieldAssoc != FieldAssociation::NO_DATA);
517 
518  if (!evalFieldMask)
519  {
521  << "field-mask: " << maskExpr_
522  << " does not evaluate to a logical expression: "
523  << driver.resultType() << nl
524  #ifdef FULLDEBUG
525  << "contents: " << fieldMask
526  #endif
527  << exit(FatalError);
528  }
529  }
530 
531 
532  // Start "expression" evaluation
533 
534  bool applied = false;
535  autoPtr<regIOobject> toutputField;
536 
537  {
538  driver.clearVariables();
539 
540  driver.parse(valueExpr_);
541 
542  if (evalFieldMask && maskFieldAssoc != driver.fieldAssociation())
543  {
545  << "Mismatch between field-mask geometric type ("
546  << fieldGeoType(maskFieldAssoc) << ") and" << nl
547  << "expression geometric type ("
548  << fieldGeoType(driver.fieldAssociation()) << ')' << nl
549  << nl
550  << "Expression: " << valueExpr_ << nl
551  << "Field-mask: " << maskExpr_ << nl
552  << nl
553  << exit(FatalError);
554  }
555 
556  // The output field does not appear to exist
557  // - create a new 'blank slate'
558  if (!regIOobjectPtr)
559  {
560  toutputField.reset(driver.dupZeroField());
561 
562  if (toutputField)
563  {
564  toutputField->rename(fldName);
565 
566  if (autowrite_)
567  {
568  toutputField->writeOpt(IOobject::AUTO_WRITE);
569  }
570  }
571 
572  if (!store_)
573  {
574  // Local (non-registered) field only
575  regIOobjectPtr = toutputField.get();
576  }
577  else
578  {
579  if (toutputField->checkIn() && toutputField->store())
580  {
581  // Register and transfer ownership to registry
582  toutputField.release();
583  }
584 
585  regIOobjectPtr = mesh_.getObjectPtr<regIOobject>(fldName);
586  }
587  }
588 
589 
590  // Additional checks (TBD):
591 
592  if (!regIOobjectPtr)
593  {
594  // Cannot continue
596  << type() << ' ' << this->name() << ':' << nl
597  << " missing-field: " << fldName << nl
598  << exit(FatalError);
599  }
600 
601  // const word oldFieldType = regIOobjectPtr->type();
602 
603  // if (driver.resultType() != oldFieldType)
604  // {
605  // FatalErrorInFunction
606  // << "Inconsistent types: " << fldName << " is "
607  // << oldFieldType
608  // << " but the expression evaluates to "
609  // << driver.resultType()
610  // << exit(FatalError);
611  // }
612 
613  switch (driver.fieldAssociation())
614  {
615  #undef doLocalCode
616  #define doLocalCode(GeoField) \
617  { \
618  /* FieldType */ \
619  auto* outPtr = dynamic_cast<GeoField*>(regIOobjectPtr); \
620  const auto* ptr = driver.isResultType<GeoField>(); \
621  \
622  if (outPtr && ptr) \
623  { \
624  applied = setField(*outPtr, *ptr, fieldMask); \
625  if (doWrite) \
626  { \
627  outPtr->write(); \
628  } \
629  break; \
630  } \
631  }
632 
634  {
640  break;
641  }
643  {
649  break;
650  }
652  {
658  break;
659  }
660 
661  default: break;
662  #undef doLocalCode
663  }
664  }
665 
666 
667  // Clear out heavier data
668  driver.clearResult();
669  driver.clearField();
670 
671  if (!applied)
672  {
673  // Or error?
675  << type() << ' ' << this->name() << ": Failed to apply "
676  << actionNames_[action_] << " for " << fldName
677  << nl;
678  }
679 
680  return true;
681 }
682 
683 
685 {
686  return performAction(false);
687 }
688 
689 
691 {
692  return performAction(true);
693 }
694 
695 
696 // ************************************************************************* //
Foam::IOobject::NO_WRITE
Definition: IOobject.H:195
volFields.H
runTime
engineTime & runTime
Definition: createEngineTime.H:13
Foam::IOobject
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:169
Foam::functionObjects::fvExpressionField::read
virtual bool read(const dictionary &dict)
Read the data.
Definition: fvExpressionField.C:355
Foam::Enum
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
Definition: IOstreamOption.H:57
Foam::IOobject::AUTO_WRITE
Definition: IOobject.H:194
Log
#define Log
Definition: PDRblock.C:35
Foam::Time
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:73
Foam::output
static Ostream & output(Ostream &os, const IntRange< T > &range)
Definition: IntRanges.C:66
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
Foam::functionObjects::fvExpressionField::~fvExpressionField
virtual ~fvExpressionField()
Destructor.
Definition: fvExpressionField.C:327
Foam::expressions::NO_DATA
No data.
Definition: exprFieldAssociation.H:45
Foam::read
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:108
Foam::expressions::volumeExpr::parseDriver
Driver for volume, surface, point field expressions.
Definition: volumeExprDriver.H:230
Foam::functionObjects::fvExpressionField::loadAndStore
bool loadAndStore(const IOobject &io)
Attempt load from io, store on database if successful.
Definition: fvExpressionField.C:132
calculatedFvPatchField.H
Foam::functionObjects::fvExpressionField::loadField
bool loadField(const IOobject &io)
Forward to loadAndStore for supported types.
Definition: fvExpressionField.C:149
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:369
surfaceFields.H
Foam::surfaceFields.
Foam::IOobject::headerClassName
const word & headerClassName() const noexcept
Return name of the class name read from header.
Definition: IOobjectI.H:83
Foam::expressions::VOLUME_DATA
Volume data.
Definition: exprFieldAssociation.H:48
Foam::functionObjects::fvMeshFunctionObject
Specialization of Foam::functionObject for an Foam::fvMesh, providing a reference to the Foam::fvMesh...
Definition: fvMeshFunctionObject.H:64
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:296
Foam::expressions::FieldAssociation
FieldAssociation
Definition: exprFieldAssociation.H:43
Foam::fieldGeoType
word fieldGeoType(const expressions::FieldAssociation geoType)
Definition: fvExpressionField.C:66
Foam::wordList
List< word > wordList
A List of words.
Definition: fileName.H:62
Foam::functionObjects::fvExpressionField::actionNames_
static const Enum< actionType > actionNames_
Action type names.
Definition: fvExpressionField.H:212
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::expressions::FACE_DATA
Face data.
Definition: exprFieldAssociation.H:47
Foam::Field< bool >
Foam::expressions::exprDriver::searchControls
searchControls
Search/caching controls.
Definition: exprDriver.H:146
Foam::expressions::exprDriver::SEARCH_FILES
Search disk (eg, standalone app)
Definition: exprDriver.H:150
Foam::Info
messageStream Info
Information stream (stdout output on master, null elsewhere)
Foam::doCorrectBoundaryConditions
static void doCorrectBoundaryConditions(bool correctBCs, GeometricField< Type, fvPatchField, volMesh > &field)
Definition: fvExpressionField.C:81
Foam::autoPtr::release
T * release() noexcept
Release ownership and return the pointer.
Definition: autoPtrI.H:100
Foam::autoPtr::get
T * get() noexcept
Return pointer to managed object without nullptr checking.
Definition: autoPtr.H:152
volumeExprDriver.H
Foam::IOstream::name
virtual const fileName & name() const
Return the name of the stream.
Definition: IOstream.C:40
field
rDeltaTY field()
fvExpressionField.H
dict
dictionary dict
Definition: searchingEngine.H:14
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:123
Foam::functionObjects::regionFunctionObject::read
virtual bool read(const dictionary &dict)
Read optional controls.
Definition: regionFunctionObject.C:173
Foam::functionObjects::fvExpressionField::fieldName
virtual word fieldName() const
Qualified/unqualified field name (depends on action)
Definition: fvExpressionField.C:333
addToRunTimeSelectionTable.H
Macros for easy insertion into run-time selection tables.
Foam::functionObjects::fvExpressionField::performAction
bool performAction(bool doWrite)
Definition: fvExpressionField.C:448
Foam::calculatedFvPatchField
This boundary condition is not designed to be evaluated; it is assmued that the value is assigned via...
Definition: calculatedFvPatchField.H:66
Foam
Namespace for OpenFOAM.
Definition: atmBoundaryLayer.C:33
Foam::functionObjects::fvExpressionField::setField
bool setField(GeoField &output, const GeoField &evaluated, const boolField &cond)
Definition: fvExpressionField.C:227
Foam::functionObjects::fvExpressionField::loadFields
label loadFields(const UList< word > &fieldSet_)
Attempt to load specified fields.
Definition: fvExpressionField.C:165
Foam::functionObjects::fvExpressionField::fvExpressionField
fvExpressionField(const word &name, const Time &runTime, const dictionary &dict, const bool loadFromFiles=false)
Construct from Time and dictionary.
Definition: fvExpressionField.C:301
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:130
Foam::autoPtr::reset
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
Foam::IOobject::name
const word & name() const noexcept
Return name.
Definition: IOobjectI.H:65
Foam::autoPtr
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: HashPtrTable.H:53
Foam::regIOobject
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:73
Foam::isA
const TargetType * isA(const Type &t)
Check if dynamic_cast to TargetType is possible.
Definition: typeInfo.H:197
Foam::expressions::exprDriver::SEARCH_REGISTRY
Search registry before disk.
Definition: exprDriver.H:149
Foam::plusOp
Definition: ops.H:215
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::functionObjects::fvExpressionField::write
virtual bool write()
Write.
Definition: fvExpressionField.C:690
Foam::functionObjects::addToRunTimeSelectionTable
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
Foam::type
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:590
Foam::functionObjects::fvMeshFunctionObject::mesh_
const fvMesh & mesh_
Reference to the fvMesh.
Definition: fvMeshFunctionObject.H:73
Foam::UList
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:103
Foam::functionObjects::defineTypeNameAndDebug
defineTypeNameAndDebug(ObukhovLength, 0)
Foam::word::null
static const word null
An empty word.
Definition: word.H:80
Foam::expressions::POINT_DATA
Point data.
Definition: exprFieldAssociation.H:46
Foam::functionObjects::fvExpressionField::execute
virtual bool execute()
Execute.
Definition: fvExpressionField.C:684
Foam::name
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for INVALID.
Definition: exprTraits.C:59
Foam::functionObjects::log
Computes the natural logarithm of an input volScalarField.
Definition: log.H:227
Foam::GeometricField< Type, fvPatchField, volMesh >
Foam::functionObjects::fvExpressionField::actionType
actionType
Action type enumeration.
Definition: fvExpressionField.H:204
WarningInFunction
#define WarningInFunction
Report a warning using Foam::Warning.
Definition: messageStream.H:328
doLocalCode
#define doLocalCode(GeoField)
pointFields.H
pointMesh.H
Foam::IOobject::MUST_READ
Definition: IOobject.H:185
FieldAssociation
The field association for mesh (patch/volume) values.