functionObjectList.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) 2011-2017 OpenFOAM Foundation
9  Copyright (C) 2015-2022 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 "functionObjectList.H"
30 #include "Time.H"
31 #include "mapPolyMesh.H"
32 #include "profiling.H"
33 #include "argList.H"
35 #include "dictionaryEntry.H"
36 #include "stringOps.H"
37 #include "Switch.H"
38 #include "Tuple2.H"
39 #include "etcFiles.H"
40 #include "IOdictionary.H"
41 #include "Pstream.H"
42 #include "OSspecific.H"
43 
44 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
45 
46 //- Max number of warnings (per functionObject)
47 static constexpr const uint32_t maxWarnings = 10u;
48 
50 (
51  "caseDicts/postProcessing"
52 );
53 
54 
55 const Foam::Enum
56 <
57  Foam::functionObjectList::errorHandlingType
58 >
59 Foam::functionObjectList::errorHandlingNames_
60 ({
61  { errorHandlingType::DEFAULT, "default" },
62  { errorHandlingType::WARN, "warn" },
63  { errorHandlingType::IGNORE, "ignore" },
64  { errorHandlingType::STRICT, "strict" },
65 });
66 
67 
68 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
69 
70 namespace Foam
71 {
72  //- Mimic exit handling of the error class
73  static void exitNow(const error& err)
74  {
75  if (error::useAbort())
76  {
77  Perr<< nl << err << nl
78  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
80  std::abort();
81  }
82  else if (UPstream::parRun())
83  {
84  Perr<< nl << err << nl
85  << "\nFOAM parallel run exiting\n" << endl;
86  UPstream::exit(1);
87  }
88  else
89  {
90  Perr<< nl << err << nl
91  << "\nFOAM exiting\n" << endl;
92  std::exit(1);
93  }
94  }
95 
96 } // End namespace Foam
97 
98 
99 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
100 
101 void Foam::functionObjectList::createPropertiesDict() const
102 {
103  // Cannot set the properties dictionary on construction since Time has not
104  // been fully initialised
105  propsDictPtr_.reset
106  (
107  new functionObjects::properties
108  (
109  IOobject
110  (
111  "functionObjectProperties",
112  time_.timeName(),
113  "uniform"/word("functionObjects"),
114  time_,
118  )
119  )
120  );
121 }
122 
123 
124 void Foam::functionObjectList::createOutputRegistry() const
125 {
126  objectsRegistryPtr_.reset
127  (
128  new objectRegistry
129  (
130  IOobject
131  (
132  "functionObjectObjects",
133  time_.timeName(),
134  time_,
138  )
139  )
140  );
141 }
142 
143 
144 Foam::autoPtr<Foam::functionObject> Foam::functionObjectList::remove
145 (
146  const word& key,
147  label& oldIndex
148 )
149 {
150  autoPtr<functionObject> oldptr;
151 
152  auto iter = indices_.find(key); // Index of existing functionObject
153 
154  if (iter.good())
155  {
156  oldIndex = *iter;
157 
158  // Remove pointer from the old list
159  oldptr = this->release(oldIndex);
160  indices_.erase(iter);
161  }
162  else
163  {
164  oldIndex = -1;
165  }
166 
167  return oldptr;
168 }
169 
170 
171 void Foam::functionObjectList::listDir
172 (
173  const fileName& dir,
174  wordHashSet& available
175 )
176 {
177  // Search specified directory for functionObject configuration files
178  for (const fileName& f : fileHandler().readDir(dir))
179  {
180  if (f.ext().empty())
181  {
182  available.insert(f);
183  }
184  }
185 
186  // Recurse into sub-directories
187  for (const fileName& d : fileHandler().readDir(dir, fileName::DIRECTORY))
188  {
189  listDir(dir/d, available);
190  }
191 }
192 
193 
195 {
196  wordHashSet available;
197 
198  for (const fileName& d : findEtcDirs(functionObjectDictPath))
199  {
200  listDir(d, available);
201  }
202 
203  Info<< nl
204  << "Available configured functionObjects:"
205  << available.sortedToc()
206  << nl;
207 }
208 
209 
211 {
212  // First check for functionObject dictionary file in globalCase system/
213 
214  fileName dictFile = stringOps::expand("<system>")/funcName;
215 
216  if (isFile(dictFile))
217  {
218  return dictFile;
219  }
220 
221  for (const fileName& d : findEtcDirs(functionObjectDictPath))
222  {
223  dictFile = search(funcName, d);
224  if (!dictFile.empty())
225  {
226  return dictFile;
227  }
228  }
229 
230  return fileName::null;
231 }
233 
235 (
236  const string& funcNameArgs,
237  dictionary& functionsDict,
238  HashSet<wordRe>& requiredFields,
239  const word& region
240 )
241 {
242  // Parse the optional functionObject arguments:
243  // 'Q(U)' -> funcName = Q; args = (U); field = U
244  //
245  // Supports named arguments:
246  // 'patchAverage(patch=inlet, p)' -> funcName = patchAverage;
247  // args = (patch=inlet, p); field = p
248 
249  word funcName;
250  wordRes args;
251  List<Tuple2<word, string>> namedArgs;
252 
253  {
254  const auto argsBeg = funcNameArgs.find('(');
255  if (argsBeg == std::string::npos)
256  {
257  // Function name only, no args
258  funcName = word::validate(funcNameArgs);
259  }
260  else
261  {
262  // Leading function name
263  funcName = word::validate(funcNameArgs.substr(0, argsBeg));
264 
265  const auto argsEnd = funcNameArgs.rfind(')');
266 
268  (
269  funcNameArgs.substr
270  (
271  (argsBeg + 1),
272  (
273  (argsEnd != std::string::npos && argsBeg < argsEnd)
274  ? (argsEnd - argsBeg - 1)
275  : std::string::npos
276  )
277  ),
278  args,
279  namedArgs
280  );
281  }
282  }
283 
284 
285  // Search for the functionObject dictionary
287 
288  if (path.empty())
289  {
291  << "Cannot find functionObject file " << funcName << endl;
292  return false;
293  }
294 
295  // Read the functionObject dictionary
296  autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
297  ISstream& fileStream = *fileStreamPtr;
298 
299  dictionary funcsDict(fileStream);
300  dictionary* funcDictPtr = funcsDict.findDict(funcName);
301  dictionary& funcDict = (funcDictPtr ? *funcDictPtr : funcsDict);
302 
303 
304  // Insert the 'field' and/or 'fields' entry corresponding to the optional
305  // arguments or read the 'field' or 'fields' entry and add the required
306  // fields to requiredFields
307  if (args.size() == 1)
308  {
309  funcDict.set("field", args[0]);
310  funcDict.set("fields", args);
311  requiredFields.insert(args[0]);
312  }
313  else if (args.size() > 1)
314  {
315  funcDict.set("fields", args);
316  requiredFields.insert(args);
317  }
318  else if (funcDict.found("field"))
319  {
320  requiredFields.insert(funcDict.get<wordRe>("field"));
321  }
322  else if (funcDict.found("fields"))
323  {
324  requiredFields.insert(funcDict.get<wordRes>("fields"));
325  }
326 
327  // Insert named arguments
328  for (const Tuple2<word, string>& namedArg : namedArgs)
329  {
330  IStringStream entryStream
331  (
332  namedArg.first() + ' ' + namedArg.second() + ';'
333  );
334 
335  funcDict.set(entry::New(entryStream).ptr());
336  }
337 
338  // Insert the region name if specified
339  if (!region.empty())
340  {
341  funcDict.set("region", region);
342  }
343 
344  // Merge this functionObject dictionary into functionsDict
345  dictionary funcArgsDict;
346  funcArgsDict.add(word::validate(funcNameArgs), funcDict);
347  functionsDict.merge(funcArgsDict);
348 
349  return true;
350 }
351 
352 
353 Foam::functionObjectList::errorHandlingType
354 Foam::functionObjectList::getOrDefaultErrorHandling
355 (
356  const word& key,
357  const dictionary& dict,
358  const errorHandlingType deflt
359 ) const
360 {
361  const entry* eptr = dict.findEntry(key, keyType::LITERAL);
362 
363  if (eptr)
364  {
365  if (eptr->isDict())
366  {
367  Warning
368  << "The sub-dictionary '" << key
369  << "' masks error handling for functions" << endl;
370  }
371  else
372  {
373  const word enumName(eptr->get<word>());
374 
375  if (!errorHandlingNames_.found(enumName))
376  {
377  // Failed the name lookup
379  << enumName << " is not in enumeration: "
380  << errorHandlingNames_ << nl
381  << exit(FatalIOError);
382  }
383 
384  return errorHandlingNames_.get(enumName);
385  }
386  }
387 
388  return deflt;
389 }
390 
391 
392 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
393 
394 Foam::functionObjectList::functionObjectList
395 (
396  const Time& runTime,
397  const bool execution
398 )
399 :
401 {}
403 
404 Foam::functionObjectList::functionObjectList
405 (
406  const Time& runTime,
407  const dictionary& parentDict,
408  const bool execution
409 )
410 :
412  errorHandling_(),
413  digests_(),
414  indices_(),
415  warnings_(),
416  time_(runTime),
417  parentDict_(parentDict),
418  propsDictPtr_(nullptr),
419  objectsRegistryPtr_(nullptr),
420  execution_(execution),
421  updated_(false)
422 {}
424 
426 (
427  const argList& args,
428  const Time& runTime,
430  HashSet<wordRe>& requiredFields
431 )
432 {
433  // Merge any functions from the provided controlDict
434  controlDict.add
435  (
437  true
438  );
439 
440  dictionary& functionsDict = controlDict.subDict("functions");
441 
442  const word regionName = args.getOrDefault<word>("region", "");
443 
444  bool modifiedControlDict = false;
445 
446  if (args.found("dict"))
447  {
448  modifiedControlDict = true;
449 
450  controlDict.merge
451  (
453  (
454  IOobject
455  (
456  args["dict"],
457  runTime,
461  )
462  )
463  );
464  }
465 
466  if (args.found("func"))
467  {
468  modifiedControlDict = true;
469 
470  readFunctionObject
471  (
472  args["func"],
473  functionsDict,
474  requiredFields,
475  regionName
476  );
477  }
478 
479  if (args.found("funcs"))
480  {
481  modifiedControlDict = true;
482 
483  for (const word& funcName : args.getList<word>("funcs"))
484  {
485  readFunctionObject
486  (
487  funcName,
488  functionsDict,
489  requiredFields,
490  regionName
491  );
492  }
493  }
494 
495 
496  autoPtr<functionObjectList> functionsPtr;
497 
498  if (modifiedControlDict)
499  {
500  functionsPtr.reset(new functionObjectList(runTime, controlDict));
501  }
502  else
503  {
504  functionsPtr.reset(new functionObjectList(runTime));
505  }
506 
507  functionsPtr->start();
508 
509  return functionsPtr;
510 }
511 
513 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
514 
515 Foam::label Foam::functionObjectList::triggerIndex() const
516 {
517  return propsDict().getTrigger();
518 }
519 
520 
522 {
523  // Reset (re-read) the properties dictionary
524  propsDictPtr_.reset(nullptr);
525  createPropertiesDict();
526 }
527 
528 
530 {
531  if (!propsDictPtr_)
532  {
533  createPropertiesDict();
534  }
535 
536  return *propsDictPtr_;
537 }
539 
542 {
543  if (!propsDictPtr_)
544  {
545  createPropertiesDict();
546  }
547 
548  return *propsDictPtr_;
549 }
550 
551 
553 {
554  if (!objectsRegistryPtr_)
555  {
556  createOutputRegistry();
557  }
558 
559  return *objectsRegistryPtr_;
560 }
561 
562 
564 {
565  if (!objectsRegistryPtr_)
566  {
567  createOutputRegistry();
568  }
569 
570  return *objectsRegistryPtr_;
571 }
572 
573 
575 {
577  errorHandling_.clear();
578  digests_.clear();
579  indices_.clear();
580  warnings_.clear();
581  updated_ = false;
582 }
583 
584 
585 Foam::label Foam::functionObjectList::findObjectID(const word& objName) const
586 {
587  label id = 0;
588 
589  for (const functionObject& funcObj : functions())
590  {
591  if (funcObj.name() == objName)
592  {
593  return id;
594  }
595 
596  ++id;
597  }
598 
599  return -1;
600 }
601 
602 
604 {
605  execution_ = true;
606 }
607 
608 
610 {
611  // For safety, also force a read() when execution is resumed
612  updated_ = execution_ = false;
613 }
614 
615 
617 {
618  return execution_;
619 }
620 
621 
623 {
624  return read();
625 }
626 
627 
629 {
630  bool ok = true;
631 
632  if (execution_)
633  {
634  if (!updated_)
635  {
636  read();
637  }
638 
639  auto errIter = errorHandling_.cbegin();
640 
641  for (functionObject& funcObj : functions())
642  {
643  const errorHandlingType errorHandling = *errIter;
644  ++errIter;
645 
646  const word& objName = funcObj.name();
647 
648  if
649  (
650  errorHandling == errorHandlingType::WARN
651  || errorHandling == errorHandlingType::IGNORE
652  )
653  {
654  // Throw FatalError, FatalIOError as exceptions
655 
656  const bool oldThrowingError = FatalError.throwing(true);
657  const bool oldThrowingIOerr = FatalIOError.throwing(true);
658 
659  bool hadError = false;
660 
661  // execute()
662  try
663  {
665  (
666  fo,
667  "functionObject::" + objName + "::execute"
668  );
669 
670  ok = funcObj.execute() && ok;
671  }
672  catch (const Foam::error& err)
673  {
674  // Treat IOerror and error identically
675  uint32_t nWarnings;
676  hadError = true;
677 
678  if
679  (
680  errorHandling != errorHandlingType::IGNORE
681  && (nWarnings = ++warnings_(objName)) <= maxWarnings
682  )
683  {
684  // Trickery to get original message
685  err.write(Warning, false);
686  Info<< nl
687  << "--> execute() function object '"
688  << objName << "'";
689 
690  if (nWarnings == maxWarnings)
691  {
692  Info<< nl << "... silencing further warnings";
693  }
694 
695  Info<< nl << endl;
696  }
697  }
698 
699  if (hadError)
700  {
701  // Restore previous state
702  FatalError.throwing(oldThrowingError);
703  FatalIOError.throwing(oldThrowingIOerr);
704  continue;
705  }
706 
707  // write()
708  try
709  {
711  (
712  fo,
713  "functionObject::" + objName + ":write"
714  );
715 
716  ok = funcObj.write() && ok;
717  }
718  catch (const Foam::error& err)
719  {
720  // Treat IOerror and error identically
721  uint32_t nWarnings;
722 
723  if
724  (
725  errorHandling != errorHandlingType::IGNORE
726  && (nWarnings = ++warnings_(objName)) <= maxWarnings
727  )
728  {
729  // Trickery to get original message
730  err.write(Warning, false);
731  Info<< nl
732  << "--> write() function object '"
733  << objName << "'";
734 
735  if (nWarnings == maxWarnings)
736  {
737  Info<< nl << "... silencing further warnings";
738  }
739 
740  Info<< nl << endl;
741  }
742  }
743 
744  // Restore previous state
745  FatalError.throwing(oldThrowingError);
746  FatalIOError.throwing(oldThrowingIOerr);
747  }
748  else
749  {
750  // No special trapping of errors
751 
752  // execute()
753  {
755  (
756  fo,
757  "functionObject::" + objName + "::execute"
758  );
759 
760  ok = funcObj.execute() && ok;
761  }
762 
763  // write()
764  {
766  (
767  fo,
768  "functionObject::" + objName + ":write"
769  );
770 
771  ok = funcObj.write() && ok;
772  }
773  }
774  }
775  }
776 
777  // Force writing of properties dictionary after function object execution
778  if (time_.writeTime())
779  {
780  const auto oldPrecision = IOstream::precision_;
782 
783  propsDictPtr_->writeObject
784  (
785  IOstreamOption(IOstreamOption::ASCII, time_.writeCompression()),
786  true
787  );
788 
789  IOstream::precision_ = oldPrecision;
790  }
791 
792  return ok;
793 }
794 
795 
796 bool Foam::functionObjectList::execute(const label subIndex)
797 {
798  bool ok = execution_;
799 
800  if (ok)
801  {
802  for (functionObject& funcObj : functions())
803  {
804  // Probably do not need try/catch...
805 
806  ok = funcObj.execute(subIndex) && ok;
807  }
808  }
809 
810  return ok;
811 }
813 
815 (
816  const UList<wordRe>& functionNames,
817  const label subIndex
818 )
819 {
820  bool ok = execution_;
821 
822  if (ok && functionNames.size())
823  {
824  for (functionObject& funcObj : functions())
825  {
826  if (stringOps::match(functionNames, funcObj.name()))
827  {
828  // Probably do not need try/catch...
829 
830  ok = funcObj.execute(subIndex) && ok;
831  }
832  }
833  }
834 
835  return ok;
836 }
837 
838 
840 {
841  bool ok = true;
842 
843  if (execution_)
844  {
845  if (!updated_)
846  {
847  read();
848  }
849 
850  auto errIter = errorHandling_.cbegin();
851 
852  for (functionObject& funcObj : functions())
853  {
854  const errorHandlingType errorHandling = *errIter;
855  ++errIter;
856 
857  const word& objName = funcObj.name();
858 
859  // Ignore failure on end() - not much we can do anyhow
860 
861  // Throw FatalError, FatalIOError as exceptions
862  const bool oldThrowingError = FatalError.throwing(true);
863  const bool oldThrowingIOerr = FatalIOError.throwing(true);
864 
865  try
866  {
867  addProfiling(fo, "functionObject::" + objName + "::end");
868  ok = funcObj.end() && ok;
869  }
870  catch (const Foam::error& err)
871  {
872  // Treat IOerror and error identically
873  uint32_t nWarnings;
874 
875  if
876  (
877  errorHandling != errorHandlingType::IGNORE
878  && (nWarnings = ++warnings_(objName)) <= maxWarnings
879  )
880  {
881  // Trickery to get original message
882  err.write(Warning, false);
883  Info<< nl
884  << "--> end() function object '"
885  << objName << "'";
886 
887  if (nWarnings == maxWarnings)
888  {
889  Info<< nl << "... silencing further warnings";
890  }
891 
892  Info<< nl << endl;
893  }
894  }
895 
896  // Restore previous state
897  FatalError.throwing(oldThrowingError);
898  FatalIOError.throwing(oldThrowingIOerr);
899  }
900  }
901 
902  return ok;
903 }
904 
905 
907 {
908  bool ok = true;
909 
910  if (execution_)
911  {
912  if (!updated_)
913  {
914  read();
915  }
916 
917  for (functionObject& funcObj : functions())
918  {
919  const word& objName = funcObj.name();
920 
921  // Probably do not need try/catch...
922 
924  (
925  fo,
926  "functionObject::" + objName + "::adjustTimeStep"
927  );
928 
929  ok = funcObj.adjustTimeStep() && ok;
930  }
931  }
932 
933  return ok;
934 }
935 
936 
938 {
939  if (!propsDictPtr_)
940  {
941  createPropertiesDict();
942  }
943 
944  updated_ = execution_;
945 
946  // Avoid reading/initializing if execution is off
947  if (!execution_)
948  {
949  return true;
950  }
951 
952  // Update existing and add new functionObjects
953  const entry* entryPtr =
954  parentDict_.findEntry("functions", keyType::LITERAL);
955 
956  bool ok = true;
957 
958  if (!entryPtr)
959  {
960  // No functions
962  errorHandling_.clear();
963  digests_.clear();
964  indices_.clear();
965  warnings_.clear();
966  }
967  else if (!entryPtr->isDict())
968  {
969  // Bad entry type
970  ok = false;
971  FatalIOErrorInFunction(parentDict_)
972  << "'functions' entry is not a dictionary"
973  << exit(FatalIOError);
974  }
975  else
976  {
977  const dictionary& functionsDict = entryPtr->dict();
978 
979  PtrList<functionObject> newPtrs(functionsDict.size());
980  List<SHA1Digest> newDigs(functionsDict.size());
981 
982  errorHandling_.resize
983  (
984  functionsDict.size(),
985  errorHandlingType::DEFAULT
986  );
987 
988  HashTable<label> newIndices;
989 
990  addProfiling(fo, "functionObjects::read");
991 
992  // Top-level "libs" specification (optional)
993  time_.libs().open
994  (
995  functionsDict,
996  "libs",
997  functionObject::dictionaryConstructorTablePtr_
998  );
999 
1000  // Top-level "errors" specification (optional)
1001  const errorHandlingType errorHandlingFallback =
1002  getOrDefaultErrorHandling
1003  (
1004  "errors",
1005  functionsDict,
1006  errorHandlingType::DEFAULT
1007  );
1008 
1009  label nFunc = 0;
1010 
1011  for (const entry& dEntry : functionsDict)
1012  {
1013  const word& key = dEntry.keyword();
1014 
1015  if (!dEntry.isDict())
1016  {
1017  // Handle or ignore some known/expected keywords
1018 
1019  if (key == "useNamePrefix") // As per functionObject
1020  {
1021  Switch sw(dEntry.stream().front());
1022  if (sw.good())
1023  {
1025  }
1026  else
1027  {
1028  IOWarningInFunction(parentDict_)
1029  << "Entry '" << key << "' is not a valid switch"
1030  << endl;
1031  }
1032  }
1033  else if (key != "errors" && key != "libs")
1034  {
1035  IOWarningInFunction(parentDict_)
1036  << "Entry '" << key << "' is not a dictionary"
1037  << endl;
1038  }
1039 
1040  continue;
1041  }
1042 
1043  const dictionary& dict = dEntry.dict();
1044 
1045  bool enabled = dict.getOrDefault("enabled", true);
1046 
1047  // Per-function "errors" specification
1048  const errorHandlingType errorHandling =
1049  getOrDefaultErrorHandling
1050  (
1051  "errors",
1052  dict,
1053  errorHandlingFallback
1054  );
1055 
1056  errorHandling_[nFunc] = errorHandling;
1057 
1058  newDigs[nFunc] = dict.digest();
1059 
1060  label oldIndex = -1;
1061  autoPtr<functionObject> objPtr = remove(key, oldIndex);
1062 
1063  const bool needsTimeControl =
1065 
1066  if (objPtr)
1067  {
1068  // Existing functionObject:
1069  // Re-read if dictionary content changed and did not
1070  // change timeControl <-> regular
1071 
1072  if (enabled && newDigs[nFunc] != digests_[oldIndex])
1073  {
1074  const bool wasTimeControl =
1075  isA<functionObjects::timeControl>(*objPtr);
1076 
1077  if (needsTimeControl != wasTimeControl)
1078  {
1079  // Changed from timeControl <-> regular
1080 
1081  // Fallthrough to 'new'
1082  objPtr.reset(nullptr);
1083  }
1084  else
1085  {
1086  // Normal read. Assume no errors to trap
1087 
1088  addProfiling
1089  (
1090  fo,
1091  "functionObject::" + objPtr->name() + "::read"
1092  );
1093 
1094  enabled = objPtr->read(dict);
1095  }
1096  }
1097 
1098  if (!enabled)
1099  {
1100  // Delete disabled or an invalid(read) functionObject
1101  objPtr.reset(nullptr);
1102  continue;
1103  }
1104  }
1105 
1106  if (enabled && !objPtr)
1107  {
1108  // Throw FatalError, FatalIOError as exceptions
1109  const bool oldThrowingError = FatalError.throwing(true);
1110  const bool oldThrowingIOerr = FatalIOError.throwing(true);
1111 
1112  try
1113  {
1114  // New functionObject
1115  addProfiling
1116  (
1117  fo,
1118  "functionObject::" + key + "::new"
1119  );
1120  if (needsTimeControl)
1121  {
1122  objPtr.reset
1123  (
1124  new functionObjects::timeControl(key, time_, dict)
1125  );
1126  }
1127  else
1128  {
1129  objPtr = functionObject::New(key, time_, dict);
1130  }
1131  }
1132  catch (const Foam::error& err)
1133  {
1134  objPtr.reset(nullptr); // extra safety
1135 
1136  switch (errorHandling)
1137  {
1138  case errorHandlingType::IGNORE:
1139  break;
1140 
1141  case errorHandlingType::STRICT:
1142  {
1143  exitNow(err);
1144  break;
1145  }
1146 
1147  case errorHandlingType::DEFAULT:
1148  {
1149  if (isA<Foam::IOerror>(err))
1150  {
1151  // Fatal for Foam::IOerror
1152  exitNow(err);
1153  break;
1154  }
1155 
1156  // Emit warning otherwise
1157  [[fallthrough]];
1158  }
1159 
1160  case errorHandlingType::WARN:
1161  {
1162  // Trickery to get original message
1163  err.write(Warning, false);
1164  Info<< nl
1165  << "--> loading function object '"
1166  << key << "'"
1167  << nl << endl;
1168  break;
1169  }
1170  }
1171  }
1172 
1173  // Restore previous state
1174  FatalError.throwing(oldThrowingError);
1175  FatalIOError.throwing(oldThrowingIOerr);
1176 
1177  // Require valid functionObject on all processors
1178  if (!returnReduceAnd(bool(objPtr)))
1179  {
1180  objPtr.reset(nullptr);
1181  ok = false;
1182  }
1183  }
1184 
1185  // Insert active functionObject into the list
1186  if (objPtr)
1187  {
1188  newPtrs.set(nFunc, std::move(objPtr));
1189  newIndices.insert(key, nFunc);
1190  ++nFunc;
1191  }
1192  }
1193 
1194  newPtrs.resize(nFunc);
1195  newDigs.resize(nFunc);
1196  errorHandling_.resize(nFunc);
1197 
1198  // Updating PtrList of functionObjects deletes any
1199  // existing unused functionObjects
1201  digests_.transfer(newDigs);
1202  indices_.transfer(newIndices);
1203  warnings_.clear();
1204  }
1205 
1206  return ok;
1208 
1209 
1211 {
1212  bool ok = false;
1213  if (execution_)
1214  {
1215  for (const functionObject& funcObj : functions())
1216  {
1217  bool changed = funcObj.filesModified();
1218  ok = ok || changed;
1219  }
1220  }
1221  return ok;
1223 
1224 
1226 {
1227  if (execution_)
1228  {
1229  for (functionObject& funcObj : functions())
1230  {
1231  funcObj.updateMesh(mpm);
1232  }
1233  }
1235 
1236 
1238 {
1239  if (execution_)
1240  {
1241  for (functionObject& funcObj : functions())
1242  {
1243  funcObj.movePoints(mesh);
1244  }
1245  }
1246 }
1247 
1248 
1249 // ************************************************************************* //
bool read()
Read and set the function objects if their data have changed.
static word validate(const std::string &s, const bool prefix=false)
Construct validated word (no invalid characters).
Definition: word.C:39
bool match(const UList< wordRe > &patterns, const std::string &text)
Return true if text matches one of the regular expressions.
Definition: stringOps.H:77
prefixOSstream Perr
OSstream wrapped stderr (std::cerr) with parallel prefix.
dictionary dict
label splitFunctionArgs(const std::string &str, wordRes &args, List< Tuple2< word, string >> &namedArgs)
Split out arguments (named or unnamed) from an input string.
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
static constexpr const uint32_t maxWarnings
Max number of warnings (per functionObject)
A class for handling file names.
Definition: fileName.H:71
bool filesModified() const
Did any file get changed during execution?
SHA1Digest digest() const
Return the SHA1 digest of the dictionary contents.
Definition: dictionary.C:220
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
void off()
Switch the function objects off.
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
Storage for function object properties, derived from IOdictionary. Provides functionality to read/wri...
A 2-tuple for storing two objects of dissimilar types. The container is similar in purpose to std::pa...
Definition: stringOps.H:54
static bool entriesPresent(const dictionary &dict)
Helper function to identify if a timeControl object is present.
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
label findObjectID(const word &objName) const
Find the ID of a given function object by name, -1 if not found.
static void list()
Print a list of functionObject configuration files in the directories located using Foam::findEtcDirs...
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:49
bool throwing() const noexcept
Return the current exception throwing state (on or off)
Definition: error.H:198
"ascii" (normal default)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:632
static const fileName null
An empty fileName.
Definition: fileName.H:110
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
List< T > getList(const label index) const
Get a List of values from the argument at index.
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1004
functionObjects::properties & propsDict()
Write access to the properties dictionary ("functionObjectProperties") registered on Time...
void on()
Switch the function objects on.
refPtr< fileOperation > fileHandler(std::nullptr_t)
Delete current file handler - forwards to fileOperation::handler()
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:637
bool adjustTimeStep()
Called at the end of Time::adjustDeltaT() if adjustTime is true.
Ignore writing from objectRegistry::writeObject()
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
T getOrDefault(const word &optName, const T &deflt) const
Get a value from the named option if present, or return default.
Definition: argListI.H:300
Abstract base-class for Time/database function objects.
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:227
A keyword and a list of tokens is a &#39;dictionaryEntry&#39;.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Definition: Time.H:69
bool start()
Called at the start of the time-loop.
Class containing mesh-to-mesh mapping information after a change in polyMesh topology.
Definition: mapPolyMesh.H:157
IOdictionary propsDict(dictIO)
bool read(const char *buf, int32_t &val)
Same as readInt32.
Definition: int32.H:127
bool found(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:100
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
Definition: IOdictionary.H:50
Class to handle errors and exceptions in a simple, consistent stream-based manner.
Definition: error.H:69
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:37
static autoPtr< functionObjectList > New(const argList &args, const Time &runTime, dictionary &controlDict, HashSet< wordRe > &requiredFields)
Construct and return a functionObjectList for an application.
Functions used by OpenFOAM that are specific to POSIX compliant operating systems and need to be repl...
bool merge(const dictionary &dict)
Merge entries from the given dictionary.
Definition: dictionary.C:811
Foam::word regionName(Foam::polyMesh::defaultRegion)
bool execute()
Called at each ++ or += of the time-loop.
void resetPropertiesDict()
Reset/read properties dictionary for current time.
bool returnReduceAnd(const bool value, const label comm=UPstream::worldComm)
Perform logical (and) MPI Allreduce on a copy. Uses UPstream::reduceAnd.
dynamicFvMesh & mesh
static void exit(int errNo=1)
Shutdown (finalize) MPI as required and exit program with errNo.
Definition: UPstream.C:55
static bool useAbort()
True if FOAM_ABORT is on.
Definition: error.C:94
A class for handling words, derived from Foam::string.
Definition: word.H:63
Functions to search &#39;etc&#39; directories for configuration files etc.
Extract command arguments and options from the supplied argc and argv parameters. ...
Definition: argList.H:118
static fileName findDict(const word &funcName)
Find a functionObject dictionary file in the case <system> directory or any directory located using F...
virtual void write(Ostream &os, const bool withTitle=true) const
Print error message.
Definition: error.C:339
Reading is optional [identical to LAZY_READ].
static const dictionary null
An empty dictionary, which is also the parent for all dictionaries.
Definition: dictionary.H:465
label size() const noexcept
The number of arguments.
Definition: argListI.H:139
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
T get() const
Get a T from the stream, FatalIOError if the number of tokens is incorrect.
Definition: entry.H:338
HashSet< word, Hash< word > > wordHashSet
A HashSet of words, uses string hasher.
Definition: HashSet.H:73
List of function objects with start(), execute() and end() functions that is called for each object...
static void exitNow(const error &err)
Mimic exit handling of the error class.
String literal.
Definition: keyType.H:82
runTime controlDict().readEntry("adjustTimeStep"
The central control dictionary, the contents of which are either taken directly from the FOAM_CONTROL...
Definition: debug.C:142
errorManip< error > abort(error &err)
Definition: errorManip.H:139
A wordRe is a Foam::word, but can contain a regular expression for matching words or strings...
Definition: wordRe.H:78
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:99
static bool readFunctionObject(const string &funcNameArgs0, dictionary &functionsDict, HashSet< wordRe > &requiredFields, const word &region=word::null)
Read the specified functionObject configuration dictionary parsing the optional arguments included in...
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:770
fileName path(UMean.rootPath()/UMean.caseName()/"graphs"/UMean.instance())
labelList f(nPoints)
messageStream Warning
Warning stream (stdout output on master, null elsewhere), with additional &#39;FOAM Warning&#39; header text...
void clear()
Clear the list of function objects.
bool isFile(const fileName &name, const bool checkGzip=true, const bool followLink=true)
Does the name exist as a FILE in the file system?
Definition: POSIX.C:877
bool status() const
Return the execution status (on/off) of the function objects.
static unsigned int precision_
Default precision.
Definition: IOstream.H:105
Generic input stream using a standard (STL) stream.
Definition: ISstream.H:51
#define WarningInFunction
Report a warning using Foam::Warning.
Enum is a wrapper around a list of names/values that represent particular enumeration (or int) values...
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:607
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
Input from string buffer, using a ISstream. Always UNCOMPRESSED.
Definition: StringStream.H:120
List< Key > sortedToc() const
The table of contents (the keys) in sorted order.
Definition: HashTable.C:130
static bool defaultUseNamePrefix
Global default for useNamePrefix.
Nothing to be read.
const entry * findEntry(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry (const access) with the given keyword.
Definition: dictionaryI.H:80
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
messageStream Info
Information stream (stdout output on master, null elsewhere)
virtual bool isDict() const noexcept
Return true if this entry is a dictionary.
Definition: entry.H:287
fileNameList findEtcDirs(const fileName &name, unsigned short location=0777, const bool findFirst=false)
Search for directories from user/group/other etc locations.
Definition: etcFiles.C:374
static void printStack(Ostream &os, int size=-1)
Helper function to print a stack, with optional upper limit.
fileName search(const word &file, const fileName &directory)
Recursively search the given directory for the file.
Definition: fileName.C:640
#define IOWarningInFunction(ios)
Report an IO warning using Foam::Warning.
void transfer(PtrList< T > &list)
Transfer into this list and annul the argument list.
Definition: PtrListI.H:252
objectRegistry & storedObjects()
Write access to the output objects ("functionObjectObjects") registered on Time.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:73
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:777
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
static autoPtr< functionObject > New(const word &name, const Time &runTime, const dictionary &dict)
Select from dictionary, based on its "type" entry.
static bool New(dictionary &parentDict, Istream &is, const inputMode inpMode=inputMode::GLOBAL, const int endChar=0)
Construct from an Istream and insert into the dictionary.
Definition: entryIO.C:98
void updateMesh(const mapPolyMesh &mpm)
Update for changes of mesh.
Registry of regIOobjects.
label triggerIndex() const
Return the current trigger index (read from the propsDict)
fileNameList readDir(const fileName &directory, const fileName::Type type=fileName::Type::FILE, const bool filtergz=true, const bool followLink=true)
Read a directory and return the entries as a fileName List.
Definition: POSIX.C:963
Foam::argList args(argc, argv)
void movePoints(const polyMesh &mesh)
Update for changes of mesh.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:171
Request registration (bool: true)
static fileName functionObjectDictPath
Default relative path ("caseDicts/postProcessing") to the directory structure containing functionObje...
bool end()
Called when Time::run() determines that the time-loop exits.
bool found(const word &optName) const
Return true if the named option is found.
Definition: argListI.H:171
Namespace for OpenFOAM.
A keyword and a list of tokens is an &#39;entry&#39;.
Definition: entry.H:63
const dictionary * findDict(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a sub-dictionary pointer if present (and a sub-dictionary) otherwise return nullptr...
Definition: dictionaryI.H:120
string expand(const std::string &s, const HashTable< string > &mapping, const char sigil='$')
Expand occurrences of variables according to the mapping and return the expanded string.
Definition: stringOps.C:704
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...