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-2023 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 unsigned maxWarnings = 10u;
48 
50 (
51  "caseDicts/postProcessing"
52 );
53 
54 
55 // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
56 
57 namespace Foam
58 {
59  //- Mimic exit handling of the error class
60  static void exitNow(const error& err)
61  {
62  if (error::useAbort())
63  {
64  Perr<< nl << err << nl
65  << "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
67  std::abort();
68  }
69  else if (UPstream::parRun())
70  {
71  Perr<< nl << err << nl
72  << "\nFOAM parallel run exiting\n" << endl;
73  UPstream::exit(1);
74  }
75  else
76  {
77  Perr<< nl << err << nl
78  << "\nFOAM exiting\n" << endl;
79  std::exit(1);
80  }
81  }
82 
83 } // End namespace Foam
84 
85 
86 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
87 
88 void Foam::functionObjectList::createPropertiesDict() const
89 {
90  // Cannot set the properties dictionary on construction since Time has not
91  // been fully initialised
92  propsDictPtr_.reset
93  (
94  new functionObjects::properties
95  (
96  IOobject
97  (
98  "functionObjectProperties",
99  time_.timeName(),
100  "uniform"/word("functionObjects"),
101  time_,
105  )
106  )
107  );
108 }
109 
110 
111 void Foam::functionObjectList::createOutputRegistry() const
112 {
113  objectsRegistryPtr_.reset
114  (
115  new objectRegistry
116  (
117  IOobject
118  (
119  "functionObjectObjects",
120  time_.timeName(),
121  time_,
125  )
126  )
127  );
128 }
129 
130 
131 Foam::autoPtr<Foam::functionObject> Foam::functionObjectList::remove
132 (
133  const word& key,
134  label& oldIndex
135 )
136 {
137  autoPtr<functionObject> oldptr;
138 
139  auto iter = indices_.find(key); // Index of existing functionObject
140 
141  if (iter.good())
142  {
143  oldIndex = *iter;
144 
145  // Remove pointer from the old list
146  oldptr = this->release(oldIndex);
147  indices_.erase(iter);
148  }
149  else
150  {
151  oldIndex = -1;
152  }
153 
154  return oldptr;
155 }
156 
157 
158 void Foam::functionObjectList::listDir
159 (
160  const fileName& dir,
161  wordHashSet& available
162 )
163 {
164  // Search specified directory for functionObject configuration files
165  for (const fileName& f : fileHandler().readDir(dir))
166  {
167  if (f.ext().empty())
168  {
169  available.insert(f);
170  }
171  }
172 
173  // Recurse into sub-directories
174  for (const fileName& d : fileHandler().readDir(dir, fileName::DIRECTORY))
175  {
176  listDir(dir/d, available);
177  }
178 }
179 
180 
182 {
183  wordHashSet available;
184 
185  for (const fileName& d : findEtcDirs(functionObjectDictPath))
186  {
187  listDir(d, available);
188  }
189 
190  Info<< nl
191  << "Available configured functionObjects:"
192  << available.sortedToc()
193  << nl;
194 }
195 
196 
198 {
199  // First check for functionObject dictionary file in globalCase system/
200 
201  fileName dictFile = stringOps::expand("<system>")/funcName;
202 
203  if (isFile(dictFile))
204  {
205  return dictFile;
206  }
207 
208  for (const fileName& d : findEtcDirs(functionObjectDictPath))
209  {
210  dictFile = search(funcName, d);
211  if (!dictFile.empty())
212  {
213  return dictFile;
214  }
215  }
216 
217  return fileName::null;
218 }
220 
222 (
223  const string& funcNameArgs,
224  dictionary& functionsDict,
225  HashSet<wordRe>& requiredFields,
226  const word& region
227 )
228 {
229  // Parse the optional functionObject arguments:
230  // 'Q(U)' -> funcName = Q; args = (U); field = U
231  //
232  // Supports named arguments:
233  // 'patchAverage(patch=inlet, p)' -> funcName = patchAverage;
234  // args = (patch=inlet, p); field = p
235 
236  word funcName;
237  wordRes args;
238  List<Tuple2<word, string>> namedArgs;
239 
240  {
241  const auto argsBeg = funcNameArgs.find('(');
242  if (argsBeg == std::string::npos)
243  {
244  // Function name only, no args
245  funcName = word::validate(funcNameArgs);
246  }
247  else
248  {
249  // Leading function name
250  funcName = word::validate(funcNameArgs.substr(0, argsBeg));
251 
252  const auto argsEnd = funcNameArgs.rfind(')');
253 
255  (
256  funcNameArgs.substr
257  (
258  (argsBeg + 1),
259  (
260  (argsEnd != std::string::npos && argsBeg < argsEnd)
261  ? (argsEnd - argsBeg - 1)
262  : std::string::npos
263  )
264  ),
265  args,
266  namedArgs
267  );
268  }
269  }
270 
271 
272  // Search for the functionObject dictionary
274 
275  if (path.empty())
276  {
278  << "Cannot find functionObject file " << funcName << endl;
279  return false;
280  }
281 
282  // Read the functionObject dictionary
283  autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
284  ISstream& fileStream = *fileStreamPtr;
285 
286  dictionary funcsDict(fileStream);
287  dictionary* funcDictPtr = funcsDict.findDict(funcName);
288  dictionary& funcDict = (funcDictPtr ? *funcDictPtr : funcsDict);
289 
290 
291  // Insert the 'field' and/or 'fields' entry corresponding to the optional
292  // arguments or read the 'field' or 'fields' entry and add the required
293  // fields to requiredFields
294  if (args.size() == 1)
295  {
296  funcDict.set("field", args[0]);
297  funcDict.set("fields", args);
298  requiredFields.insert(args[0]);
299  }
300  else if (args.size() > 1)
301  {
302  funcDict.set("fields", args);
303  requiredFields.insert(args);
304  }
305  else if (funcDict.found("field"))
306  {
307  requiredFields.insert(funcDict.get<wordRe>("field"));
308  }
309  else if (funcDict.found("fields"))
310  {
311  requiredFields.insert(funcDict.get<wordRes>("fields"));
312  }
313 
314  // Insert named arguments
315  for (const Tuple2<word, string>& namedArg : namedArgs)
316  {
317  IStringStream entryStream
318  (
319  namedArg.first() + ' ' + namedArg.second() + ';'
320  );
321 
322  funcDict.set(entry::New(entryStream).ptr());
323  }
324 
325  // Insert the region name if specified
326  if (!region.empty())
327  {
328  funcDict.set("region", region);
329  }
330 
331  // Merge this functionObject dictionary into functionsDict
332  dictionary funcArgsDict;
333  funcArgsDict.add(word::validate(funcNameArgs), funcDict);
334  functionsDict.merge(funcArgsDict);
335 
336  return true;
337 }
338 
339 
341 Foam::functionObjectList::getOrDefaultErrorHandling
342 (
343  const word& key,
344  const dictionary& dict,
345  const error::handlerTypes deflt
346 ) const
347 {
348  const entry* eptr = dict.findEntry(key, keyType::LITERAL);
349 
350  if (eptr)
351  {
352  if (eptr->isDict())
353  {
354  Warning
355  << "The sub-dictionary '" << key
356  << "' masks error handling for functions" << endl;
357  }
358  else
359  {
360  const word enumName(eptr->get<word>());
361 
362  if (!error::handlerNames.found(enumName))
363  {
364  // Failed the name lookup
366  << enumName << " is not in enumeration: "
367  << error::handlerNames << nl
368  << exit(FatalIOError);
369  }
370 
371  return error::handlerNames.get(enumName);
372  }
373  }
374 
375  return deflt;
376 }
377 
378 
379 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
380 
381 Foam::functionObjectList::functionObjectList
382 (
383  const Time& runTime,
384  const bool execution
385 )
386 :
388 {}
390 
391 Foam::functionObjectList::functionObjectList
392 (
393  const Time& runTime,
394  const dictionary& parentDict,
395  const bool execution
396 )
397 :
399  errorHandling_(),
400  digests_(),
401  indices_(),
402  warnings_(0),
403  time_(runTime),
404  parentDict_(parentDict),
405  propsDictPtr_(nullptr),
406  objectsRegistryPtr_(nullptr),
407  execution_(execution),
408  updated_(false)
409 {}
411 
413 (
414  const argList& args,
415  const Time& runTime,
417  HashSet<wordRe>& requiredFields
418 )
419 {
420  // Merge any functions from the provided controlDict
421  controlDict.add
422  (
424  true
425  );
426 
427  dictionary& functionsDict = controlDict.subDict("functions");
428 
429  const word regionName = args.getOrDefault<word>("region", "");
430 
431  bool modifiedControlDict = false;
432 
433  if (args.found("dict"))
434  {
435  modifiedControlDict = true;
436 
437  controlDict.merge
438  (
440  (
441  IOobject
442  (
443  args["dict"],
444  runTime,
448  )
449  )
450  );
451  }
452 
453  if (args.found("func"))
454  {
455  modifiedControlDict = true;
456 
457  readFunctionObject
458  (
459  args["func"],
460  functionsDict,
461  requiredFields,
462  regionName
463  );
464  }
465 
466  if (args.found("funcs"))
467  {
468  modifiedControlDict = true;
469 
470  for (const word& funcName : args.getList<word>("funcs"))
471  {
472  readFunctionObject
473  (
474  funcName,
475  functionsDict,
476  requiredFields,
477  regionName
478  );
479  }
480  }
481 
482 
483  autoPtr<functionObjectList> functionsPtr;
484 
485  if (modifiedControlDict)
486  {
487  functionsPtr.reset(new functionObjectList(runTime, controlDict));
488  }
489  else
490  {
491  functionsPtr.reset(new functionObjectList(runTime));
492  }
493 
494  functionsPtr->start();
495 
496  return functionsPtr;
497 }
498 
500 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
501 
502 Foam::label Foam::functionObjectList::triggerIndex() const
503 {
504  return propsDict().getTrigger();
505 }
506 
507 
509 {
510  // Reset (re-read) the properties dictionary
511  propsDictPtr_.reset(nullptr);
512  createPropertiesDict();
513 }
514 
515 
517 {
518  if (!propsDictPtr_)
519  {
520  createPropertiesDict();
521  }
522 
523  return *propsDictPtr_;
524 }
526 
529 {
530  if (!propsDictPtr_)
531  {
532  createPropertiesDict();
533  }
534 
535  return *propsDictPtr_;
536 }
537 
538 
540 {
541  if (!objectsRegistryPtr_)
542  {
543  createOutputRegistry();
544  }
545 
546  return *objectsRegistryPtr_;
547 }
548 
549 
551 {
552  if (!objectsRegistryPtr_)
553  {
554  createOutputRegistry();
555  }
556 
557  return *objectsRegistryPtr_;
558 }
559 
560 
562 {
564  errorHandling_.clear();
565  digests_.clear();
566  indices_.clear();
567  warnings_.clear();
568  updated_ = false;
569 }
570 
571 
572 Foam::label Foam::functionObjectList::findObjectID(const word& objName) const
573 {
574  label id = 0;
575 
576  for (const functionObject& funcObj : functions())
577  {
578  if (funcObj.name() == objName)
579  {
580  return id;
581  }
582 
583  ++id;
584  }
585 
586  return -1;
587 }
588 
589 
591 {
592  execution_ = true;
593 }
594 
595 
597 {
598  // For safety, also force a read() when execution is resumed
599  updated_ = execution_ = false;
600 }
601 
602 
604 {
605  return execution_;
606 }
607 
608 
610 {
611  return read();
612 }
613 
614 
615 bool Foam::functionObjectList::execute(bool writeProperties)
616 {
617  bool ok = true;
618 
619  if (execution_)
620  {
621  if (!updated_)
622  {
623  read();
624  }
625 
626  auto errIter = errorHandling_.cbegin();
627 
628  for (functionObject& funcObj : functions())
629  {
630  const auto errorHandling = *errIter;
631  ++errIter;
632 
633  const word& objName = funcObj.name();
634 
635  if
636  (
637  errorHandling == error::handlerTypes::WARN
638  || errorHandling == error::handlerTypes::IGNORE
639  )
640  {
641  // Throw FatalError, FatalIOError as exceptions
642 
643  const bool oldThrowingError = FatalError.throwing(true);
644  const bool oldThrowingIOerr = FatalIOError.throwing(true);
645 
646  bool hadError = false;
647 
648  // execute()
649  try
650  {
652  (
653  fo,
654  "functionObject::" + objName + "::execute"
655  );
656 
657  ok = funcObj.execute() && ok;
658  }
659  catch (const Foam::error& err)
660  {
661  // Treat IOerror and error identically
662  unsigned nWarnings;
663  hadError = true;
664 
665  if
666  (
667  (errorHandling == error::handlerTypes::WARN)
668  && (nWarnings = ++warnings_(objName)) <= maxWarnings
669  )
670  {
671  // Trickery to get original message
672  err.write(Warning, false);
673  Info<< nl
674  << "--> execute() function object '"
675  << objName << "'";
676 
677  if (nWarnings == maxWarnings)
678  {
679  Info<< nl << "... silencing further warnings";
680  }
681 
682  Info<< nl << endl;
683  }
684  }
685 
686  if (hadError)
687  {
688  // Restore previous state
689  FatalError.throwing(oldThrowingError);
690  FatalIOError.throwing(oldThrowingIOerr);
691  continue;
692  }
693 
694  // write()
695  try
696  {
698  (
699  fo,
700  "functionObject::" + objName + ":write"
701  );
702 
703  ok = funcObj.write() && ok;
704  }
705  catch (const Foam::error& err)
706  {
707  // Treat IOerror and error identically
708  unsigned nWarnings;
709  hadError = true;
710 
711  if
712  (
713  (errorHandling == error::handlerTypes::WARN)
714  && (nWarnings = ++warnings_(objName)) <= maxWarnings
715  )
716  {
717  // Trickery to get original message
718  err.write(Warning, false);
719  Info<< nl
720  << "--> write() function object '"
721  << objName << "'";
722 
723  if (nWarnings == maxWarnings)
724  {
725  Info<< nl << "... silencing further warnings";
726  }
727 
728  Info<< nl << endl;
729  }
730  }
731 
732  // Restore previous state
733  FatalError.throwing(oldThrowingError);
734  FatalIOError.throwing(oldThrowingIOerr);
735 
736  // Reset the warning counter (if any)
737  // if no errors were encountered
738  if
739  (
740  (errorHandling == error::handlerTypes::WARN)
741  && !hadError && !warnings_.empty()
742  )
743  {
744  warnings_.erase(objName);
745  }
746  }
747  else
748  {
749  // No special trapping of errors
750 
751  // execute()
752  {
754  (
755  fo,
756  "functionObject::" + objName + "::execute"
757  );
758 
759  ok = funcObj.execute() && ok;
760  }
761 
762  // write()
763  {
765  (
766  fo,
767  "functionObject::" + objName + ":write"
768  );
769 
770  ok = funcObj.write() && ok;
771  }
772  }
773  }
774  }
775 
776  // Force writing of properties dictionary after function object execution
777  if (time_.writeTime() && writeProperties)
778  {
779  const auto oldPrecision = IOstream::precision_;
781 
782  propsDictPtr_->writeObject
783  (
784  IOstreamOption(IOstreamOption::ASCII, time_.writeCompression()),
785  true
786  );
787 
788  IOstream::precision_ = oldPrecision;
789  }
790 
791  return ok;
792 }
793 
794 
795 bool Foam::functionObjectList::execute(const label subIndex)
796 {
797  bool ok = execution_;
798 
799  if (ok)
800  {
801  for (functionObject& funcObj : functions())
802  {
803  // Probably do not need try/catch...
804 
805  ok = funcObj.execute(subIndex) && ok;
806  }
807  }
808 
809  return ok;
810 }
812 
814 (
815  const UList<wordRe>& functionNames,
816  const label subIndex
817 )
818 {
819  bool ok = execution_;
820 
821  if (ok && functionNames.size())
822  {
823  for (functionObject& funcObj : functions())
824  {
825  if (stringOps::match(functionNames, funcObj.name()))
826  {
827  // Probably do not need try/catch...
828 
829  ok = funcObj.execute(subIndex) && ok;
830  }
831  }
832  }
833 
834  return ok;
835 }
836 
837 
839 {
840  bool ok = true;
841 
842  if (execution_)
843  {
844  if (!updated_)
845  {
846  read();
847  }
848 
849  auto errIter = errorHandling_.cbegin();
850 
851  for (functionObject& funcObj : functions())
852  {
853  const auto errorHandling = *errIter;
854  ++errIter;
855 
856  const word& objName = funcObj.name();
857 
858  // Ignore failure on end() - not much we can do anyhow
859 
860  // Throw FatalError, FatalIOError as exceptions
861  const bool oldThrowingError = FatalError.throwing(true);
862  const bool oldThrowingIOerr = FatalIOError.throwing(true);
863 
864  try
865  {
866  addProfiling(fo, "functionObject::" + objName + "::end");
867  ok = funcObj.end() && ok;
868  }
869  catch (const Foam::error& err)
870  {
871  // Treat IOerror and error identically
872  // If it somehow failed, emit a warning (unless IGNORE).
873  // Unlike execute(), do not suppress further warning messages
874  // (we want to know about rare issues)
875  // but do reset the warnings counter for the next cycle.
876 
877  if (errorHandling != error::handlerTypes::IGNORE)
878  {
879  // Trickery to get original message
880  err.write(Warning, false);
881  Info<< nl
882  << "--> end() function object '"
883  << objName << "'"
884  << nl << endl;
885  }
886  }
887 
888  // Restore previous state
889  FatalError.throwing(oldThrowingError);
890  FatalIOError.throwing(oldThrowingIOerr);
891 
892  // Reset the corresponding warning counter (if any)
893  if
894  (
895  (errorHandling == error::handlerTypes::WARN)
896  && !warnings_.empty()
897  )
898  {
899  warnings_.erase(objName);
900  }
901  }
902  }
903 
904  return ok;
905 }
906 
907 
909 {
910  bool ok = true;
911 
912  if (execution_)
913  {
914  if (!updated_)
915  {
916  read();
917  }
918 
919  for (functionObject& funcObj : functions())
920  {
921  const word& objName = funcObj.name();
922 
923  // Probably do not need try/catch...
924 
926  (
927  fo,
928  "functionObject::" + objName + "::adjustTimeStep"
929  );
930 
931  ok = funcObj.adjustTimeStep() && ok;
932  }
933  }
934 
935  return ok;
936 }
937 
938 
940 {
941  if (!propsDictPtr_)
942  {
943  createPropertiesDict();
944  }
945 
946  updated_ = execution_;
947 
948  // Avoid reading/initializing if execution is off
949  if (!execution_)
950  {
951  return true;
952  }
953 
954  // Update existing and add new functionObjects
955  const entry* entryPtr =
956  parentDict_.findEntry("functions", keyType::LITERAL);
957 
958  bool ok = true;
959 
960  if (!entryPtr)
961  {
962  // No functions
964  errorHandling_.clear();
965  digests_.clear();
966  indices_.clear();
967  warnings_.clear();
968  }
969  else if (!entryPtr->isDict())
970  {
971  // Bad entry type
972  ok = false;
973  FatalIOErrorInFunction(parentDict_)
974  << "'functions' entry is not a dictionary"
975  << exit(FatalIOError);
976  }
977  else
978  {
979  const dictionary& functionsDict = entryPtr->dict();
980 
981  PtrList<functionObject> newPtrs(functionsDict.size());
982  List<SHA1Digest> newDigs(functionsDict.size());
983 
984  errorHandling_.resize
985  (
986  functionsDict.size(),
988  );
989 
990  HashTable<label> newIndices;
991 
992  addProfiling(fo, "functionObjects::read");
993 
994  // Top-level "libs" specification (optional)
995  time_.libs().open
996  (
997  functionsDict,
998  "libs",
999  functionObject::dictionaryConstructorTablePtr_
1000  );
1001 
1002  // Top-level "errors" specification (optional)
1003  const error::handlerTypes errorHandlingFallback =
1004  getOrDefaultErrorHandling
1005  (
1006  "errors",
1007  functionsDict,
1009  );
1010 
1011  label nFunc = 0;
1012 
1013  for (const entry& dEntry : functionsDict)
1014  {
1015  const word& key = dEntry.keyword();
1016 
1017  if (!dEntry.isDict())
1018  {
1019  // Handle or ignore some known/expected keywords
1020 
1021  if (key == "useNamePrefix") // As per functionObject
1022  {
1023  Switch sw(dEntry.stream().front());
1024  if (sw.good())
1025  {
1027  }
1028  else
1029  {
1030  IOWarningInFunction(parentDict_)
1031  << "Entry '" << key << "' is not a valid switch"
1032  << endl;
1033  }
1034  }
1035  else if (key != "errors" && key != "libs")
1036  {
1037  IOWarningInFunction(parentDict_)
1038  << "Entry '" << key << "' is not a dictionary"
1039  << endl;
1040  }
1041 
1042  continue;
1043  }
1044 
1045  const dictionary& dict = dEntry.dict();
1046 
1047  bool enabled = dict.getOrDefault("enabled", true);
1048 
1049  // Per-function "errors" specification
1050  const error::handlerTypes errorHandling =
1051  getOrDefaultErrorHandling
1052  (
1053  "errors",
1054  dict,
1055  errorHandlingFallback
1056  );
1057 
1058  errorHandling_[nFunc] = errorHandling;
1059 
1060  newDigs[nFunc] = dict.digest();
1061 
1062  label oldIndex = -1;
1063  autoPtr<functionObject> objPtr = remove(key, oldIndex);
1064 
1065  const bool needsTimeControl =
1067 
1068  if (objPtr)
1069  {
1070  // Existing functionObject:
1071  // Re-read if dictionary content changed and did not
1072  // change timeControl <-> regular
1073 
1074  if (enabled && newDigs[nFunc] != digests_[oldIndex])
1075  {
1076  const bool wasTimeControl =
1077  isA<functionObjects::timeControl>(*objPtr);
1078 
1079  if (needsTimeControl != wasTimeControl)
1080  {
1081  // Changed from timeControl <-> regular
1082 
1083  // Fallthrough to 'new'
1084  objPtr.reset(nullptr);
1085  }
1086  else
1087  {
1088  // Normal read. Assume no errors to trap
1089 
1090  addProfiling
1091  (
1092  fo,
1093  "functionObject::" + objPtr->name() + "::read"
1094  );
1095 
1096  enabled = objPtr->read(dict);
1097  }
1098  }
1099 
1100  if (!enabled)
1101  {
1102  // Delete disabled or an invalid(read) functionObject
1103  objPtr.reset(nullptr);
1104  continue;
1105  }
1106  }
1107 
1108  if (enabled && !objPtr)
1109  {
1110  // Throw FatalError, FatalIOError as exceptions
1111  const bool oldThrowingError = FatalError.throwing(true);
1112  const bool oldThrowingIOerr = FatalIOError.throwing(true);
1113 
1114  try
1115  {
1116  // New functionObject
1117  addProfiling
1118  (
1119  fo,
1120  "functionObject::" + key + "::new"
1121  );
1122  if (needsTimeControl)
1123  {
1124  objPtr.reset
1125  (
1126  new functionObjects::timeControl(key, time_, dict)
1127  );
1128  }
1129  else
1130  {
1131  objPtr = functionObject::New(key, time_, dict);
1132  }
1133  }
1134  catch (const Foam::error& err)
1135  {
1136  objPtr.reset(nullptr); // extra safety
1137 
1138  switch (errorHandling)
1139  {
1141  break;
1142 
1144  {
1145  exitNow(err);
1146  break;
1147  }
1148 
1150  {
1151  if (isA<Foam::IOerror>(err))
1152  {
1153  // Fatal for Foam::IOerror
1154  exitNow(err);
1155  break;
1156  }
1157 
1158  // Emit warning otherwise
1159  [[fallthrough]];
1160  }
1161 
1163  {
1164  // Trickery to get original message
1165  err.write(Warning, false);
1166  Info<< nl
1167  << "--> loading function object '"
1168  << key << "'"
1169  << nl << endl;
1170  break;
1171  }
1172  }
1173  }
1174 
1175  // Restore previous state
1176  FatalError.throwing(oldThrowingError);
1177  FatalIOError.throwing(oldThrowingIOerr);
1178 
1179  // Require valid functionObject on all processors
1180  if (!returnReduceAnd(bool(objPtr)))
1181  {
1182  objPtr.reset(nullptr);
1183  ok = false;
1184  }
1185  }
1186 
1187  // Insert active functionObject into the list
1188  if (objPtr)
1189  {
1190  newPtrs.set(nFunc, std::move(objPtr));
1191  newIndices.insert(key, nFunc);
1192  ++nFunc;
1193  }
1194  }
1195 
1196  newPtrs.resize(nFunc);
1197  newDigs.resize(nFunc);
1198  errorHandling_.resize(nFunc);
1199 
1200  // Updating PtrList of functionObjects deletes any
1201  // existing unused functionObjects
1203  digests_.transfer(newDigs);
1204  indices_.transfer(newIndices);
1205  warnings_.clear();
1206  }
1207 
1208  return ok;
1210 
1211 
1213 {
1214  bool ok = false;
1215  if (execution_)
1216  {
1217  for (const functionObject& funcObj : functions())
1218  {
1219  bool changed = funcObj.filesModified();
1220  ok = ok || changed;
1221  }
1222  }
1223  return ok;
1225 
1226 
1228 {
1229  if (execution_)
1230  {
1231  for (functionObject& funcObj : functions())
1232  {
1233  funcObj.updateMesh(mpm);
1234  }
1235  }
1237 
1238 
1240 {
1241  if (execution_)
1242  {
1243  for (functionObject& funcObj : functions())
1244  {
1245  funcObj.movePoints(mesh);
1246  }
1247  }
1248 }
1249 
1250 
1251 // ************************************************************************* //
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
EnumType get(const word &enumName) const
The enumeration corresponding to the given name.
Definition: Enum.C:68
Warn on errors/problems.
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
A class for handling file names.
Definition: fileName.H:72
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
handlerTypes
Handling of errors. The exact handling depends on the local context.
Definition: error.H:109
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:129
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:50
bool throwing() const noexcept
Return the current exception throwing state (on or off)
Definition: error.H:218
"ascii" (normal default)
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:666
static const fileName null
An empty fileName.
Definition: fileName.H:111
engineTime & runTime
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
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:1049
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:625
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.
Default behaviour (local meaning)
bool insert(const Key &key)
Insert a new entry, not overwriting existing entries.
Definition: HashSet.H:232
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:104
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:70
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:799
void resetPropertiesDict()
Reset/read properties dictionary for current time.
#define addProfiling(Name, Descr)
Define profiling trigger with specified name and description string.
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:110
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:355
Ignore on errors/problems.
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:474
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:105
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 a time name for the given scalar time value formatted with the given precision.
Definition: Time.C:714
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
static constexpr const unsigned maxWarnings
Max number of warnings (per functionObject)
#define WarningInFunction
Report a warning using Foam::Warning.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
Foam::word regionName(args.getOrDefault< word >("region", Foam::polyMesh::defaultRegion))
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:139
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:84
void clear()
Clear the PtrList. Delete allocated entries and set size to zero.
Definition: PtrListI.H:81
bool execute(bool writeProperties=true)
Called at each ++ or += of the time-loop.
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:642
#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:272
objectRegistry & storedObjects()
Write access to the output objects ("functionObjectObjects") registered on Time.
Mesh consisting of general polyhedral cells.
Definition: polyMesh.H:74
entry * set(entry *entryPtr)
Assign a new entry, overwriting any existing entry.
Definition: dictionary.C:765
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:172
Request registration (bool: true)
static fileName functionObjectDictPath
Default relative path ("caseDicts/postProcessing") to the directory structure containing functionObje...
Fatal on errors/problems.
bool end()
Called when Time::run() determines that the time-loop exits.
bool found
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
static const Enum< handlerTypes > handlerNames
Names of the error handler types.
Definition: error.H:120
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:124
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:705
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...