mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: finer granularity for handling functionObject failure (#1779)
- additional "errors" entry with enumerated values (default|warn|ignore|strict) for defining warning or error at construct or runtime stage - default : construct = warn, runtime = fatal - warn : construct = warn, runtime = warn - ignore : construct = silent, runtime = silent - strict : construct = fatal, runtime = fatal The errors control can be added at the top-level and/or for individual function objects.
This commit is contained in:
@ -56,13 +56,15 @@ Description
|
||||
sub-dictionary, typically as in the following example:
|
||||
|
||||
\verbatim
|
||||
functions // sub-dictionary name under the system/controlDict file
|
||||
functions // sub-dictionary name under the system/controlDict file
|
||||
{
|
||||
<userDefinedSubDictName1>
|
||||
..optional entries..
|
||||
|
||||
<dictName1>
|
||||
{
|
||||
// Mandatory entries
|
||||
type <functionObjectTypeName>;
|
||||
libs (<libType>FunctionObjects);
|
||||
type <functionObjectTypeName>;
|
||||
libs (<libType>FunctionObjects);
|
||||
|
||||
// Mandatory entries defined in <functionObjectType>
|
||||
...
|
||||
@ -82,14 +84,14 @@ Description
|
||||
writeInterval 1;
|
||||
}
|
||||
|
||||
<userDefinedSubDictName2>
|
||||
<dictName2>
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
<userDefinedSubDictNameN>
|
||||
<dictNameN>
|
||||
{
|
||||
...
|
||||
}
|
||||
@ -101,6 +103,7 @@ Description
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
type | Type name of function object | word | yes | -
|
||||
libs | Library name(s) for implementation | words | no | -
|
||||
errors | Error handling (default/warn/ignore/strict) | word | no | inherits
|
||||
region | Name of region for multi-region cases | word | no | region0
|
||||
enabled | Switch to turn function object on/off | bool | no | true
|
||||
log | Switch to write log info to standard output | bool | no | true
|
||||
@ -112,6 +115,9 @@ Description
|
||||
writeInterval | Steps/time between write phases | label | no | 1
|
||||
\endtable
|
||||
|
||||
If the \c errors entry is missing, it uses the value (if any)
|
||||
specified within the top-level functionObjectList.
|
||||
|
||||
Time controls:
|
||||
\table
|
||||
Option | Description
|
||||
|
||||
@ -37,15 +37,64 @@ License
|
||||
#include "Tuple2.H"
|
||||
#include "etcFiles.H"
|
||||
#include "IOdictionary.H"
|
||||
#include "Pstream.H"
|
||||
#include "OSspecific.H"
|
||||
|
||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||
|
||||
//- Max number of warnings (per functionObject)
|
||||
static constexpr const uint32_t maxWarnings = 10u;
|
||||
|
||||
Foam::fileName Foam::functionObjectList::functionObjectDictPath
|
||||
(
|
||||
"caseDicts/postProcessing"
|
||||
);
|
||||
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::functionObjectList::errorHandlingType
|
||||
>
|
||||
Foam::functionObjectList::errorHandlingNames_
|
||||
({
|
||||
{ errorHandlingType::DEFAULT, "default" },
|
||||
{ errorHandlingType::WARN, "warn" },
|
||||
{ errorHandlingType::IGNORE, "ignore" },
|
||||
{ errorHandlingType::STRICT, "strict" },
|
||||
});
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
//- Mimic exit handling of the error class
|
||||
static void exitNow(const error& err)
|
||||
{
|
||||
if (hasEnv("FOAM_ABORT"))
|
||||
{
|
||||
Perr<< nl << err << nl
|
||||
<< "\nFOAM aborting (FOAM_ABORT set)\n" << endl;
|
||||
error::printStack(Perr);
|
||||
std::abort();
|
||||
}
|
||||
else if (Pstream::parRun())
|
||||
{
|
||||
Perr<< nl << err << nl
|
||||
<< "\nFOAM parallel run exiting\n" << endl;
|
||||
Pstream::exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Perr<< nl << err << nl
|
||||
<< "\nFOAM exiting\n" << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjectList::createStateDict() const
|
||||
@ -282,7 +331,7 @@ bool Foam::functionObjectList::readFunctionObject
|
||||
// Search for the functionObject dictionary
|
||||
fileName path = functionObjectList::findDict(funcName);
|
||||
|
||||
if (path == fileName::null)
|
||||
if (path.empty())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Cannot find functionObject file " << funcName << endl;
|
||||
@ -291,7 +340,7 @@ bool Foam::functionObjectList::readFunctionObject
|
||||
|
||||
// Read the functionObject dictionary
|
||||
autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
|
||||
ISstream& fileStream = fileStreamPtr();
|
||||
ISstream& fileStream = *fileStreamPtr;
|
||||
|
||||
dictionary funcsDict(fileStream);
|
||||
dictionary* funcDictPtr = funcsDict.findDict(funcName);
|
||||
@ -347,6 +396,45 @@ bool Foam::functionObjectList::readFunctionObject
|
||||
}
|
||||
|
||||
|
||||
Foam::functionObjectList::errorHandlingType
|
||||
Foam::functionObjectList::getOrDefaultErrorHandling
|
||||
(
|
||||
const word& key,
|
||||
const dictionary& dict,
|
||||
const errorHandlingType deflt
|
||||
) const
|
||||
{
|
||||
const entry* eptr = dict.findEntry(key, keyType::LITERAL);
|
||||
|
||||
if (eptr)
|
||||
{
|
||||
if (eptr->isDict())
|
||||
{
|
||||
Warning
|
||||
<< "The sub-dictionary '" << key
|
||||
<< "' masks error handling for functions" << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
const word enumName(eptr->get<word>());
|
||||
|
||||
if (!errorHandlingNames_.found(enumName))
|
||||
{
|
||||
// Failed the name lookup
|
||||
FatalIOErrorInFunction(dict)
|
||||
<< enumName << " is not in enumeration: "
|
||||
<< errorHandlingNames_ << nl
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return errorHandlingNames_.get(enumName);
|
||||
}
|
||||
}
|
||||
|
||||
return deflt;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjectList::functionObjectList
|
||||
@ -355,15 +443,7 @@ Foam::functionObjectList::functionObjectList
|
||||
const bool execution
|
||||
)
|
||||
:
|
||||
PtrList<functionObject>(),
|
||||
digests_(),
|
||||
indices_(),
|
||||
time_(runTime),
|
||||
parentDict_(runTime.controlDict()),
|
||||
stateDictPtr_(),
|
||||
objectsRegistryPtr_(),
|
||||
execution_(execution),
|
||||
updated_(false)
|
||||
functionObjectList(runTime, runTime.controlDict(), execution)
|
||||
{}
|
||||
|
||||
|
||||
@ -375,12 +455,14 @@ Foam::functionObjectList::functionObjectList
|
||||
)
|
||||
:
|
||||
PtrList<functionObject>(),
|
||||
errorHandling_(),
|
||||
digests_(),
|
||||
indices_(),
|
||||
warnings_(),
|
||||
time_(runTime),
|
||||
parentDict_(parentDict),
|
||||
stateDictPtr_(),
|
||||
objectsRegistryPtr_(),
|
||||
stateDictPtr_(nullptr),
|
||||
objectsRegistryPtr_(nullptr),
|
||||
execution_(execution),
|
||||
updated_(false)
|
||||
{}
|
||||
@ -442,9 +524,7 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
|
||||
{
|
||||
modifiedControlDict = true;
|
||||
|
||||
wordList funcNames = args.getList<word>("funcs");
|
||||
|
||||
for (const word& funcName : funcNames)
|
||||
for (const word& funcName : args.getList<word>("funcs"))
|
||||
{
|
||||
readFunctionObject
|
||||
(
|
||||
@ -478,17 +558,14 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
|
||||
|
||||
Foam::label Foam::functionObjectList::triggerIndex() const
|
||||
{
|
||||
label triggeri = labelMin;
|
||||
stateDict().readIfPresent("triggerIndex", triggeri);
|
||||
|
||||
return triggeri;
|
||||
return stateDict().getOrDefault<label>("triggerIndex", labelMin);
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjectList::resetState()
|
||||
{
|
||||
// Reset (re-read) the state dictionary
|
||||
stateDictPtr_.clear();
|
||||
stateDictPtr_.reset(nullptr);
|
||||
createStateDict();
|
||||
}
|
||||
|
||||
@ -540,19 +617,21 @@ const Foam::objectRegistry& Foam::functionObjectList::storedObjects() const
|
||||
void Foam::functionObjectList::clear()
|
||||
{
|
||||
PtrList<functionObject>::clear();
|
||||
errorHandling_.clear();
|
||||
digests_.clear();
|
||||
indices_.clear();
|
||||
warnings_.clear();
|
||||
updated_ = false;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::functionObjectList::findObjectID(const word& name) const
|
||||
Foam::label Foam::functionObjectList::findObjectID(const word& objName) const
|
||||
{
|
||||
label id = 0;
|
||||
|
||||
for (const functionObject& funcObj : functions())
|
||||
{
|
||||
if (funcObj.name() == name)
|
||||
if (funcObj.name() == objName)
|
||||
{
|
||||
return id;
|
||||
}
|
||||
@ -600,19 +679,140 @@ bool Foam::functionObjectList::execute()
|
||||
read();
|
||||
}
|
||||
|
||||
auto errIter = errorHandling_.cbegin();
|
||||
|
||||
for (functionObject& funcObj : functions())
|
||||
{
|
||||
const errorHandlingType errorHandling = *errIter;
|
||||
++errIter;
|
||||
|
||||
const word& objName = funcObj.name();
|
||||
{
|
||||
addProfiling(fo, "functionObject::" + objName + "::execute");
|
||||
|
||||
ok = funcObj.execute() && ok;
|
||||
if
|
||||
(
|
||||
errorHandling == errorHandlingType::WARN
|
||||
|| errorHandling == errorHandlingType::IGNORE
|
||||
)
|
||||
{
|
||||
// Throw FatalError, FatalIOError as exceptions
|
||||
|
||||
const bool throwingError = FatalError.throwExceptions();
|
||||
const bool throwingIOerr = FatalIOError.throwExceptions();
|
||||
|
||||
bool hadError = false;
|
||||
|
||||
// execute()
|
||||
try
|
||||
{
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objName + "::execute"
|
||||
);
|
||||
|
||||
ok = funcObj.execute() && ok;
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
// Treat IOerror and error identically
|
||||
uint32_t nWarnings;
|
||||
hadError = true;
|
||||
|
||||
if
|
||||
(
|
||||
errorHandling != errorHandlingType::IGNORE
|
||||
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
|
||||
)
|
||||
{
|
||||
// Trickery to get original message
|
||||
err.write(Warning, false);
|
||||
Info<< nl
|
||||
<< "--> execute() function object '"
|
||||
<< objName << "'";
|
||||
|
||||
if (nWarnings == maxWarnings)
|
||||
{
|
||||
Info<< nl << "... silencing further warnings";
|
||||
}
|
||||
|
||||
Info<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (hadError)
|
||||
{
|
||||
// Restore previous state
|
||||
FatalError.throwExceptions(throwingError);
|
||||
FatalIOError.throwExceptions(throwingIOerr);
|
||||
continue;
|
||||
}
|
||||
|
||||
// write()
|
||||
try
|
||||
{
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objName + ":write"
|
||||
);
|
||||
|
||||
ok = funcObj.write() && ok;
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
// Treat IOerror and error identically
|
||||
uint32_t nWarnings;
|
||||
|
||||
if
|
||||
(
|
||||
errorHandling != errorHandlingType::IGNORE
|
||||
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
|
||||
)
|
||||
{
|
||||
// Trickery to get original message
|
||||
err.write(Warning, false);
|
||||
Info<< nl
|
||||
<< "--> write() function object '"
|
||||
<< objName << "'";
|
||||
|
||||
if (nWarnings == maxWarnings)
|
||||
{
|
||||
Info<< nl << "... silencing further warnings";
|
||||
}
|
||||
|
||||
Info<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore previous state
|
||||
FatalError.throwExceptions(throwingError);
|
||||
FatalIOError.throwExceptions(throwingIOerr);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
addProfiling(fo, "functionObject::" + objName + "::write");
|
||||
// No special trapping of errors
|
||||
|
||||
ok = funcObj.write() && ok;
|
||||
// execute()
|
||||
{
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objName + "::execute"
|
||||
);
|
||||
|
||||
ok = funcObj.execute() && ok;
|
||||
}
|
||||
|
||||
// write()
|
||||
{
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objName + ":write"
|
||||
);
|
||||
|
||||
ok = funcObj.write() && ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -620,7 +820,7 @@ bool Foam::functionObjectList::execute()
|
||||
// Force writing of state dictionary after function object execution
|
||||
if (time_.writeTime())
|
||||
{
|
||||
label oldPrecision = IOstream::precision_;
|
||||
const auto oldPrecision = IOstream::precision_;
|
||||
IOstream::precision_ = 16;
|
||||
|
||||
stateDictPtr_->writeObject
|
||||
@ -644,6 +844,8 @@ bool Foam::functionObjectList::execute(const label subIndex)
|
||||
{
|
||||
for (functionObject& funcObj : functions())
|
||||
{
|
||||
// Probably do not need try/catch...
|
||||
|
||||
ok = funcObj.execute(subIndex) && ok;
|
||||
}
|
||||
}
|
||||
@ -666,6 +868,8 @@ bool Foam::functionObjectList::execute
|
||||
{
|
||||
if (stringOps::match(functionNames, funcObj.name()))
|
||||
{
|
||||
// Probably do not need try/catch...
|
||||
|
||||
ok = funcObj.execute(subIndex) && ok;
|
||||
}
|
||||
}
|
||||
@ -686,13 +890,55 @@ bool Foam::functionObjectList::end()
|
||||
read();
|
||||
}
|
||||
|
||||
auto errIter = errorHandling_.cbegin();
|
||||
|
||||
for (functionObject& funcObj : functions())
|
||||
{
|
||||
const errorHandlingType errorHandling = *errIter;
|
||||
++errIter;
|
||||
|
||||
const word& objName = funcObj.name();
|
||||
|
||||
addProfiling(fo, "functionObject::" + objName + "::end");
|
||||
// Ignore failure on end() - not much we can do anyhow
|
||||
|
||||
ok = funcObj.end() && ok;
|
||||
// Throw FatalError, FatalIOError as exceptions
|
||||
const bool throwingError = FatalError.throwExceptions();
|
||||
const bool throwingIOerr = FatalIOError.throwExceptions();
|
||||
|
||||
try
|
||||
{
|
||||
addProfiling(fo, "functionObject::" + objName + "::end");
|
||||
ok = funcObj.end() && ok;
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
// Treat IOerror and error identically
|
||||
uint32_t nWarnings;
|
||||
|
||||
if
|
||||
(
|
||||
errorHandling != errorHandlingType::IGNORE
|
||||
&& (nWarnings = ++warnings_(objName)) <= maxWarnings
|
||||
)
|
||||
{
|
||||
// Trickery to get original message
|
||||
err.write(Warning, false);
|
||||
Info<< nl
|
||||
<< "--> end() function object '"
|
||||
<< objName << "'";
|
||||
|
||||
if (nWarnings == maxWarnings)
|
||||
{
|
||||
Info<< nl << "... silencing further warnings";
|
||||
}
|
||||
|
||||
Info<< nl << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// Restore previous state
|
||||
FatalError.throwExceptions(throwingError);
|
||||
FatalIOError.throwExceptions(throwingIOerr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,7 +961,13 @@ bool Foam::functionObjectList::adjustTimeStep()
|
||||
{
|
||||
const word& objName = funcObj.name();
|
||||
|
||||
addProfiling(fo, "functionObject::" + objName + "::adjustTimeStep");
|
||||
// Probably do not need try/catch...
|
||||
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objName + "::adjustTimeStep"
|
||||
);
|
||||
|
||||
ok = funcObj.adjustTimeStep() && ok;
|
||||
}
|
||||
@ -750,8 +1002,10 @@ bool Foam::functionObjectList::read()
|
||||
{
|
||||
// No functions
|
||||
PtrList<functionObject>::clear();
|
||||
errorHandling_.clear();
|
||||
digests_.clear();
|
||||
indices_.clear();
|
||||
warnings_.clear();
|
||||
}
|
||||
else if (!entryPtr->isDict())
|
||||
{
|
||||
@ -767,10 +1021,18 @@ bool Foam::functionObjectList::read()
|
||||
|
||||
PtrList<functionObject> newPtrs(functionsDict.size());
|
||||
List<SHA1Digest> newDigs(functionsDict.size());
|
||||
|
||||
errorHandling_.resize
|
||||
(
|
||||
functionsDict.size(),
|
||||
errorHandlingType::DEFAULT
|
||||
);
|
||||
|
||||
HashTable<label> newIndices;
|
||||
|
||||
addProfiling(fo, "functionObjects::read");
|
||||
|
||||
// Top-level "libs" specification (optional)
|
||||
time_.libs().open
|
||||
(
|
||||
functionsDict,
|
||||
@ -778,6 +1040,15 @@ bool Foam::functionObjectList::read()
|
||||
functionObject::dictionaryConstructorTablePtr_
|
||||
);
|
||||
|
||||
// Top-level "errors" specification (optional)
|
||||
const errorHandlingType errorHandlingFallback =
|
||||
getOrDefaultErrorHandling
|
||||
(
|
||||
"errors",
|
||||
functionsDict,
|
||||
errorHandlingType::DEFAULT
|
||||
);
|
||||
|
||||
label nFunc = 0;
|
||||
|
||||
for (const entry& dEntry : functionsDict)
|
||||
@ -786,7 +1057,7 @@ bool Foam::functionObjectList::read()
|
||||
|
||||
if (!dEntry.isDict())
|
||||
{
|
||||
if (key != "libs")
|
||||
if (key != "errors" && key != "libs")
|
||||
{
|
||||
IOWarningInFunction(parentDict_)
|
||||
<< "Entry " << key << " is not a dictionary" << endl;
|
||||
@ -799,66 +1070,67 @@ bool Foam::functionObjectList::read()
|
||||
|
||||
bool enabled = dict.getOrDefault("enabled", true);
|
||||
|
||||
// Per-function "errors" specification
|
||||
const errorHandlingType errorHandling =
|
||||
getOrDefaultErrorHandling
|
||||
(
|
||||
"errors",
|
||||
dict,
|
||||
errorHandlingFallback
|
||||
);
|
||||
|
||||
errorHandling_[nFunc] = errorHandling;
|
||||
|
||||
newDigs[nFunc] = dict.digest();
|
||||
|
||||
label oldIndex = -1;
|
||||
autoPtr<functionObject> objPtr = remove(key, oldIndex);
|
||||
|
||||
const bool needsTimeControl =
|
||||
functionObjects::timeControl::entriesPresent(dict);
|
||||
|
||||
if (objPtr)
|
||||
{
|
||||
// Re-read if dictionary content changed for
|
||||
// existing functionObject
|
||||
// Existing functionObject:
|
||||
// Re-read if dictionary content changed and did not
|
||||
// change timeControl <-> regular
|
||||
|
||||
if (enabled && newDigs[nFunc] != digests_[oldIndex])
|
||||
{
|
||||
addProfiling
|
||||
(
|
||||
fo2,
|
||||
"functionObject::" + objPtr->name() + "::read"
|
||||
);
|
||||
const bool wasTimeControl =
|
||||
isA<functionObjects::timeControl>(*objPtr);
|
||||
|
||||
if (functionObjects::timeControl::entriesPresent(dict))
|
||||
if (needsTimeControl != wasTimeControl)
|
||||
{
|
||||
if (isA<functionObjects::timeControl>(objPtr()))
|
||||
{
|
||||
// Already a time control - normal read
|
||||
enabled = objPtr->read(dict);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Was not a time control - need to re-create
|
||||
objPtr.reset
|
||||
(
|
||||
new functionObjects::timeControl
|
||||
(
|
||||
key,
|
||||
time_,
|
||||
dict
|
||||
)
|
||||
);
|
||||
// Changed from timeControl <-> regular
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
// Fallthrough to 'new'
|
||||
objPtr.reset(nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Plain function object - normal read
|
||||
// Normal read. Assume no errors to trap
|
||||
|
||||
addProfiling
|
||||
(
|
||||
fo,
|
||||
"functionObject::" + objPtr->name() + "::read"
|
||||
);
|
||||
|
||||
enabled = objPtr->read(dict);
|
||||
}
|
||||
|
||||
ok = enabled && ok;
|
||||
}
|
||||
|
||||
if (!enabled)
|
||||
{
|
||||
// Delete disabled or an invalid(read) functionObject
|
||||
objPtr.clear();
|
||||
objPtr.reset(nullptr);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (enabled)
|
||||
{
|
||||
autoPtr<functionObject> foPtr;
|
||||
|
||||
if (enabled && !objPtr)
|
||||
{
|
||||
// Throw FatalError, FatalIOError as exceptions
|
||||
const bool throwingError = FatalError.throwExceptions();
|
||||
const bool throwingIOerr = FatalIOError.throwExceptions();
|
||||
@ -868,47 +1140,70 @@ bool Foam::functionObjectList::read()
|
||||
// New functionObject
|
||||
addProfiling
|
||||
(
|
||||
fo2,
|
||||
fo,
|
||||
"functionObject::" + key + "::new"
|
||||
);
|
||||
if (functionObjects::timeControl::entriesPresent(dict))
|
||||
if (needsTimeControl)
|
||||
{
|
||||
foPtr.reset
|
||||
objPtr.reset
|
||||
(
|
||||
new functionObjects::timeControl(key, time_, dict)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
foPtr = functionObject::New(key, time_, dict);
|
||||
objPtr = functionObject::New(key, time_, dict);
|
||||
}
|
||||
}
|
||||
catch (const Foam::IOerror& ioErr)
|
||||
{
|
||||
Info<< ioErr << nl << endl;
|
||||
std::exit(1);
|
||||
}
|
||||
catch (const Foam::error& err)
|
||||
{
|
||||
// Bit of trickery to get the original message
|
||||
err.write(Warning, false);
|
||||
InfoInFunction
|
||||
<< nl
|
||||
<< "--> while loading function object '" << key << "'"
|
||||
<< nl << endl;
|
||||
objPtr.reset(nullptr); // extra safety
|
||||
|
||||
switch (errorHandling)
|
||||
{
|
||||
case errorHandlingType::IGNORE:
|
||||
break;
|
||||
|
||||
case errorHandlingType::STRICT:
|
||||
{
|
||||
exitNow(err);
|
||||
break;
|
||||
}
|
||||
|
||||
case errorHandlingType::DEFAULT:
|
||||
{
|
||||
if (isA<Foam::IOerror>(err))
|
||||
{
|
||||
// Fatal for Foam::IOerror
|
||||
exitNow(err);
|
||||
break;
|
||||
}
|
||||
|
||||
// Emit warning otherwise
|
||||
[[fallthrough]];
|
||||
}
|
||||
|
||||
case errorHandlingType::WARN:
|
||||
{
|
||||
// Trickery to get original message
|
||||
err.write(Warning, false);
|
||||
Info<< nl
|
||||
<< "--> loading function object '"
|
||||
<< key << "'"
|
||||
<< nl << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Restore previous exception throwing state
|
||||
// Restore previous state
|
||||
FatalError.throwExceptions(throwingError);
|
||||
FatalIOError.throwExceptions(throwingIOerr);
|
||||
|
||||
// Required functionObject to be valid on all processors
|
||||
if (returnReduce(bool(foPtr), andOp<bool>()))
|
||||
{
|
||||
objPtr.reset(foPtr.release());
|
||||
}
|
||||
else
|
||||
// Require valid functionObject on all processors
|
||||
if (!returnReduce(bool(objPtr), andOp<bool>()))
|
||||
{
|
||||
objPtr.reset(nullptr);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
@ -924,12 +1219,14 @@ bool Foam::functionObjectList::read()
|
||||
|
||||
newPtrs.resize(nFunc);
|
||||
newDigs.resize(nFunc);
|
||||
errorHandling_.resize(nFunc);
|
||||
|
||||
// Updating PtrList of functionObjects deletes any
|
||||
// existing unused functionObjects
|
||||
PtrList<functionObject>::transfer(newPtrs);
|
||||
digests_.transfer(newDigs);
|
||||
indices_.transfer(newIndices);
|
||||
warnings_.clear();
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2019 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2020 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -31,6 +31,43 @@ Description
|
||||
List of function objects with start(), execute() and end() functions
|
||||
that is called for each object.
|
||||
|
||||
\verbatim
|
||||
functions // sub-dictionary name under the system/controlDict file
|
||||
{
|
||||
..optional entries..
|
||||
|
||||
<userDict1>
|
||||
{
|
||||
// Mandatory entries
|
||||
type <typeName>;
|
||||
libs (<libName> .. <libName>);
|
||||
...
|
||||
}
|
||||
|
||||
<userDict2>
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
with optional entries:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
libs | Preloaded library names | words | no | -
|
||||
errors | Error handling (default/warn/ignore/strict) | word | no | inherits
|
||||
\endtable
|
||||
|
||||
The optional \c errors entry controls how FatalError is caught
|
||||
during construction and execute/write. FatalIOError is unaffected.
|
||||
- \c default : warn on construction errors, fatal on runtime errors
|
||||
- \c warn : warn on construction and runtime errors
|
||||
- \c ignore : ignore construction and runtime errors
|
||||
- \c strict : fatal on construction and runtime errors
|
||||
.
|
||||
|
||||
See also
|
||||
Foam::functionObject
|
||||
Foam::functionObjects::timeControl
|
||||
@ -44,6 +81,7 @@ SourceFiles
|
||||
#define functionObjectList_H
|
||||
|
||||
#include "PtrList.H"
|
||||
#include "Enum.H"
|
||||
#include "functionObject.H"
|
||||
#include "SHA1Digest.H"
|
||||
#include "HashTable.H"
|
||||
@ -55,7 +93,7 @@ SourceFiles
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward declarations
|
||||
// Forward Declarations
|
||||
class argList;
|
||||
class mapPolyMesh;
|
||||
class wordRe;
|
||||
@ -68,14 +106,37 @@ class functionObjectList
|
||||
:
|
||||
private PtrList<functionObject>
|
||||
{
|
||||
// Private data
|
||||
// Data Types
|
||||
|
||||
//- Handling of construction or execution errors
|
||||
enum class errorHandlingType : uint8_t
|
||||
{
|
||||
DEFAULT = 0, //!< Warn on construct, Fatal on runtime
|
||||
WARN, //!< Warn on construct, Warn on runtime
|
||||
IGNORE, //!< Ignore on construct, Ignore on runtime
|
||||
STRICT, //!< Fatal on construct, Fatal on runtime
|
||||
};
|
||||
|
||||
//- Names for error handling types
|
||||
static const Enum<errorHandlingType> errorHandlingNames_;
|
||||
|
||||
|
||||
// Private Data
|
||||
|
||||
//- A list of error/warning handling
|
||||
List<errorHandlingType> errorHandling_;
|
||||
|
||||
//- A list of SHA1 digests for the function object dictionaries
|
||||
List<SHA1Digest> digests_;
|
||||
|
||||
//- Quick lookup of the index into functions/digests
|
||||
//- Quick lookup of the index into functions/digests/errorHandling
|
||||
HashTable<label> indices_;
|
||||
|
||||
//- Track the number of warnings per function object and limit
|
||||
// to a predefined number to avoid flooding the display.
|
||||
// Clear on re-read of functions.
|
||||
HashTable<uint32_t> warnings_;
|
||||
|
||||
//- Reference to Time
|
||||
const Time& time_;
|
||||
|
||||
@ -119,6 +180,19 @@ class functionObjectList
|
||||
//- configuration files, add to the given map and recurse
|
||||
static void listDir(const fileName& dir, wordHashSet& available);
|
||||
|
||||
//- Like Enum::getOrDefault, but with additional code to warn if
|
||||
//- the 'key' is not a primitive entry.
|
||||
//
|
||||
// This additional treatment is to ensure that potentially existing
|
||||
// code with an "errors" functionObject will continue to run.
|
||||
errorHandlingType getOrDefaultErrorHandling
|
||||
(
|
||||
const word& key,
|
||||
const dictionary& dict,
|
||||
const errorHandlingType deflt
|
||||
) const;
|
||||
|
||||
|
||||
//- No copy construct
|
||||
functionObjectList(const functionObjectList&) = delete;
|
||||
|
||||
@ -214,7 +288,7 @@ public:
|
||||
void clear();
|
||||
|
||||
//- Find the ID of a given function object by name, -1 if not found.
|
||||
label findObjectID(const word& name) const;
|
||||
label findObjectID(const word& objName) const;
|
||||
|
||||
//- Print a list of functionObject configuration files in the
|
||||
//- directories located using
|
||||
|
||||
Reference in New Issue
Block a user