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:
|
sub-dictionary, typically as in the following example:
|
||||||
|
|
||||||
\verbatim
|
\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
|
// Mandatory entries
|
||||||
type <functionObjectTypeName>;
|
type <functionObjectTypeName>;
|
||||||
libs (<libType>FunctionObjects);
|
libs (<libType>FunctionObjects);
|
||||||
|
|
||||||
// Mandatory entries defined in <functionObjectType>
|
// Mandatory entries defined in <functionObjectType>
|
||||||
...
|
...
|
||||||
@ -82,14 +84,14 @@ Description
|
|||||||
writeInterval 1;
|
writeInterval 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
<userDefinedSubDictName2>
|
<dictName2>
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
<userDefinedSubDictNameN>
|
<dictNameN>
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
@ -101,6 +103,7 @@ Description
|
|||||||
Property | Description | Type | Reqd | Deflt
|
Property | Description | Type | Reqd | Deflt
|
||||||
type | Type name of function object | word | yes | -
|
type | Type name of function object | word | yes | -
|
||||||
libs | Library name(s) for implementation | words | no | -
|
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
|
region | Name of region for multi-region cases | word | no | region0
|
||||||
enabled | Switch to turn function object on/off | bool | no | true
|
enabled | Switch to turn function object on/off | bool | no | true
|
||||||
log | Switch to write log info to standard output | 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
|
writeInterval | Steps/time between write phases | label | no | 1
|
||||||
\endtable
|
\endtable
|
||||||
|
|
||||||
|
If the \c errors entry is missing, it uses the value (if any)
|
||||||
|
specified within the top-level functionObjectList.
|
||||||
|
|
||||||
Time controls:
|
Time controls:
|
||||||
\table
|
\table
|
||||||
Option | Description
|
Option | Description
|
||||||
|
|||||||
@ -37,15 +37,64 @@ License
|
|||||||
#include "Tuple2.H"
|
#include "Tuple2.H"
|
||||||
#include "etcFiles.H"
|
#include "etcFiles.H"
|
||||||
#include "IOdictionary.H"
|
#include "IOdictionary.H"
|
||||||
|
#include "Pstream.H"
|
||||||
|
#include "OSspecific.H"
|
||||||
|
|
||||||
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
/* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
|
||||||
|
|
||||||
|
//- Max number of warnings (per functionObject)
|
||||||
|
static constexpr const uint32_t maxWarnings = 10u;
|
||||||
|
|
||||||
Foam::fileName Foam::functionObjectList::functionObjectDictPath
|
Foam::fileName Foam::functionObjectList::functionObjectDictPath
|
||||||
(
|
(
|
||||||
"caseDicts/postProcessing"
|
"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 * * * * * * * * * * * * //
|
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::functionObjectList::createStateDict() const
|
void Foam::functionObjectList::createStateDict() const
|
||||||
@ -282,7 +331,7 @@ bool Foam::functionObjectList::readFunctionObject
|
|||||||
// Search for the functionObject dictionary
|
// Search for the functionObject dictionary
|
||||||
fileName path = functionObjectList::findDict(funcName);
|
fileName path = functionObjectList::findDict(funcName);
|
||||||
|
|
||||||
if (path == fileName::null)
|
if (path.empty())
|
||||||
{
|
{
|
||||||
WarningInFunction
|
WarningInFunction
|
||||||
<< "Cannot find functionObject file " << funcName << endl;
|
<< "Cannot find functionObject file " << funcName << endl;
|
||||||
@ -291,7 +340,7 @@ bool Foam::functionObjectList::readFunctionObject
|
|||||||
|
|
||||||
// Read the functionObject dictionary
|
// Read the functionObject dictionary
|
||||||
autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
|
autoPtr<ISstream> fileStreamPtr(fileHandler().NewIFstream(path));
|
||||||
ISstream& fileStream = fileStreamPtr();
|
ISstream& fileStream = *fileStreamPtr;
|
||||||
|
|
||||||
dictionary funcsDict(fileStream);
|
dictionary funcsDict(fileStream);
|
||||||
dictionary* funcDictPtr = funcsDict.findDict(funcName);
|
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 * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::functionObjectList::functionObjectList
|
Foam::functionObjectList::functionObjectList
|
||||||
@ -355,15 +443,7 @@ Foam::functionObjectList::functionObjectList
|
|||||||
const bool execution
|
const bool execution
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
PtrList<functionObject>(),
|
functionObjectList(runTime, runTime.controlDict(), execution)
|
||||||
digests_(),
|
|
||||||
indices_(),
|
|
||||||
time_(runTime),
|
|
||||||
parentDict_(runTime.controlDict()),
|
|
||||||
stateDictPtr_(),
|
|
||||||
objectsRegistryPtr_(),
|
|
||||||
execution_(execution),
|
|
||||||
updated_(false)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -375,12 +455,14 @@ Foam::functionObjectList::functionObjectList
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
PtrList<functionObject>(),
|
PtrList<functionObject>(),
|
||||||
|
errorHandling_(),
|
||||||
digests_(),
|
digests_(),
|
||||||
indices_(),
|
indices_(),
|
||||||
|
warnings_(),
|
||||||
time_(runTime),
|
time_(runTime),
|
||||||
parentDict_(parentDict),
|
parentDict_(parentDict),
|
||||||
stateDictPtr_(),
|
stateDictPtr_(nullptr),
|
||||||
objectsRegistryPtr_(),
|
objectsRegistryPtr_(nullptr),
|
||||||
execution_(execution),
|
execution_(execution),
|
||||||
updated_(false)
|
updated_(false)
|
||||||
{}
|
{}
|
||||||
@ -442,9 +524,7 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
|
|||||||
{
|
{
|
||||||
modifiedControlDict = true;
|
modifiedControlDict = true;
|
||||||
|
|
||||||
wordList funcNames = args.getList<word>("funcs");
|
for (const word& funcName : args.getList<word>("funcs"))
|
||||||
|
|
||||||
for (const word& funcName : funcNames)
|
|
||||||
{
|
{
|
||||||
readFunctionObject
|
readFunctionObject
|
||||||
(
|
(
|
||||||
@ -478,17 +558,14 @@ Foam::autoPtr<Foam::functionObjectList> Foam::functionObjectList::New
|
|||||||
|
|
||||||
Foam::label Foam::functionObjectList::triggerIndex() const
|
Foam::label Foam::functionObjectList::triggerIndex() const
|
||||||
{
|
{
|
||||||
label triggeri = labelMin;
|
return stateDict().getOrDefault<label>("triggerIndex", labelMin);
|
||||||
stateDict().readIfPresent("triggerIndex", triggeri);
|
|
||||||
|
|
||||||
return triggeri;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::functionObjectList::resetState()
|
void Foam::functionObjectList::resetState()
|
||||||
{
|
{
|
||||||
// Reset (re-read) the state dictionary
|
// Reset (re-read) the state dictionary
|
||||||
stateDictPtr_.clear();
|
stateDictPtr_.reset(nullptr);
|
||||||
createStateDict();
|
createStateDict();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -540,19 +617,21 @@ const Foam::objectRegistry& Foam::functionObjectList::storedObjects() const
|
|||||||
void Foam::functionObjectList::clear()
|
void Foam::functionObjectList::clear()
|
||||||
{
|
{
|
||||||
PtrList<functionObject>::clear();
|
PtrList<functionObject>::clear();
|
||||||
|
errorHandling_.clear();
|
||||||
digests_.clear();
|
digests_.clear();
|
||||||
indices_.clear();
|
indices_.clear();
|
||||||
|
warnings_.clear();
|
||||||
updated_ = false;
|
updated_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::label Foam::functionObjectList::findObjectID(const word& name) const
|
Foam::label Foam::functionObjectList::findObjectID(const word& objName) const
|
||||||
{
|
{
|
||||||
label id = 0;
|
label id = 0;
|
||||||
|
|
||||||
for (const functionObject& funcObj : functions())
|
for (const functionObject& funcObj : functions())
|
||||||
{
|
{
|
||||||
if (funcObj.name() == name)
|
if (funcObj.name() == objName)
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
@ -600,19 +679,140 @@ bool Foam::functionObjectList::execute()
|
|||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto errIter = errorHandling_.cbegin();
|
||||||
|
|
||||||
for (functionObject& funcObj : functions())
|
for (functionObject& funcObj : functions())
|
||||||
{
|
{
|
||||||
|
const errorHandlingType errorHandling = *errIter;
|
||||||
|
++errIter;
|
||||||
|
|
||||||
const word& objName = funcObj.name();
|
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
|
// Force writing of state dictionary after function object execution
|
||||||
if (time_.writeTime())
|
if (time_.writeTime())
|
||||||
{
|
{
|
||||||
label oldPrecision = IOstream::precision_;
|
const auto oldPrecision = IOstream::precision_;
|
||||||
IOstream::precision_ = 16;
|
IOstream::precision_ = 16;
|
||||||
|
|
||||||
stateDictPtr_->writeObject
|
stateDictPtr_->writeObject
|
||||||
@ -644,6 +844,8 @@ bool Foam::functionObjectList::execute(const label subIndex)
|
|||||||
{
|
{
|
||||||
for (functionObject& funcObj : functions())
|
for (functionObject& funcObj : functions())
|
||||||
{
|
{
|
||||||
|
// Probably do not need try/catch...
|
||||||
|
|
||||||
ok = funcObj.execute(subIndex) && ok;
|
ok = funcObj.execute(subIndex) && ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -666,6 +868,8 @@ bool Foam::functionObjectList::execute
|
|||||||
{
|
{
|
||||||
if (stringOps::match(functionNames, funcObj.name()))
|
if (stringOps::match(functionNames, funcObj.name()))
|
||||||
{
|
{
|
||||||
|
// Probably do not need try/catch...
|
||||||
|
|
||||||
ok = funcObj.execute(subIndex) && ok;
|
ok = funcObj.execute(subIndex) && ok;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -686,13 +890,55 @@ bool Foam::functionObjectList::end()
|
|||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto errIter = errorHandling_.cbegin();
|
||||||
|
|
||||||
for (functionObject& funcObj : functions())
|
for (functionObject& funcObj : functions())
|
||||||
{
|
{
|
||||||
|
const errorHandlingType errorHandling = *errIter;
|
||||||
|
++errIter;
|
||||||
|
|
||||||
const word& objName = funcObj.name();
|
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();
|
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;
|
ok = funcObj.adjustTimeStep() && ok;
|
||||||
}
|
}
|
||||||
@ -750,8 +1002,10 @@ bool Foam::functionObjectList::read()
|
|||||||
{
|
{
|
||||||
// No functions
|
// No functions
|
||||||
PtrList<functionObject>::clear();
|
PtrList<functionObject>::clear();
|
||||||
|
errorHandling_.clear();
|
||||||
digests_.clear();
|
digests_.clear();
|
||||||
indices_.clear();
|
indices_.clear();
|
||||||
|
warnings_.clear();
|
||||||
}
|
}
|
||||||
else if (!entryPtr->isDict())
|
else if (!entryPtr->isDict())
|
||||||
{
|
{
|
||||||
@ -767,10 +1021,18 @@ bool Foam::functionObjectList::read()
|
|||||||
|
|
||||||
PtrList<functionObject> newPtrs(functionsDict.size());
|
PtrList<functionObject> newPtrs(functionsDict.size());
|
||||||
List<SHA1Digest> newDigs(functionsDict.size());
|
List<SHA1Digest> newDigs(functionsDict.size());
|
||||||
|
|
||||||
|
errorHandling_.resize
|
||||||
|
(
|
||||||
|
functionsDict.size(),
|
||||||
|
errorHandlingType::DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
HashTable<label> newIndices;
|
HashTable<label> newIndices;
|
||||||
|
|
||||||
addProfiling(fo, "functionObjects::read");
|
addProfiling(fo, "functionObjects::read");
|
||||||
|
|
||||||
|
// Top-level "libs" specification (optional)
|
||||||
time_.libs().open
|
time_.libs().open
|
||||||
(
|
(
|
||||||
functionsDict,
|
functionsDict,
|
||||||
@ -778,6 +1040,15 @@ bool Foam::functionObjectList::read()
|
|||||||
functionObject::dictionaryConstructorTablePtr_
|
functionObject::dictionaryConstructorTablePtr_
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Top-level "errors" specification (optional)
|
||||||
|
const errorHandlingType errorHandlingFallback =
|
||||||
|
getOrDefaultErrorHandling
|
||||||
|
(
|
||||||
|
"errors",
|
||||||
|
functionsDict,
|
||||||
|
errorHandlingType::DEFAULT
|
||||||
|
);
|
||||||
|
|
||||||
label nFunc = 0;
|
label nFunc = 0;
|
||||||
|
|
||||||
for (const entry& dEntry : functionsDict)
|
for (const entry& dEntry : functionsDict)
|
||||||
@ -786,7 +1057,7 @@ bool Foam::functionObjectList::read()
|
|||||||
|
|
||||||
if (!dEntry.isDict())
|
if (!dEntry.isDict())
|
||||||
{
|
{
|
||||||
if (key != "libs")
|
if (key != "errors" && key != "libs")
|
||||||
{
|
{
|
||||||
IOWarningInFunction(parentDict_)
|
IOWarningInFunction(parentDict_)
|
||||||
<< "Entry " << key << " is not a dictionary" << endl;
|
<< "Entry " << key << " is not a dictionary" << endl;
|
||||||
@ -799,66 +1070,67 @@ bool Foam::functionObjectList::read()
|
|||||||
|
|
||||||
bool enabled = dict.getOrDefault("enabled", true);
|
bool enabled = dict.getOrDefault("enabled", true);
|
||||||
|
|
||||||
|
// Per-function "errors" specification
|
||||||
|
const errorHandlingType errorHandling =
|
||||||
|
getOrDefaultErrorHandling
|
||||||
|
(
|
||||||
|
"errors",
|
||||||
|
dict,
|
||||||
|
errorHandlingFallback
|
||||||
|
);
|
||||||
|
|
||||||
|
errorHandling_[nFunc] = errorHandling;
|
||||||
|
|
||||||
newDigs[nFunc] = dict.digest();
|
newDigs[nFunc] = dict.digest();
|
||||||
|
|
||||||
label oldIndex = -1;
|
label oldIndex = -1;
|
||||||
autoPtr<functionObject> objPtr = remove(key, oldIndex);
|
autoPtr<functionObject> objPtr = remove(key, oldIndex);
|
||||||
|
|
||||||
|
const bool needsTimeControl =
|
||||||
|
functionObjects::timeControl::entriesPresent(dict);
|
||||||
|
|
||||||
if (objPtr)
|
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])
|
if (enabled && newDigs[nFunc] != digests_[oldIndex])
|
||||||
{
|
{
|
||||||
addProfiling
|
const bool wasTimeControl =
|
||||||
(
|
isA<functionObjects::timeControl>(*objPtr);
|
||||||
fo2,
|
|
||||||
"functionObject::" + objPtr->name() + "::read"
|
|
||||||
);
|
|
||||||
|
|
||||||
if (functionObjects::timeControl::entriesPresent(dict))
|
if (needsTimeControl != wasTimeControl)
|
||||||
{
|
{
|
||||||
if (isA<functionObjects::timeControl>(objPtr()))
|
// Changed from timeControl <-> regular
|
||||||
{
|
|
||||||
// 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
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
enabled = true;
|
// Fallthrough to 'new'
|
||||||
}
|
objPtr.reset(nullptr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Plain function object - normal read
|
// Normal read. Assume no errors to trap
|
||||||
|
|
||||||
|
addProfiling
|
||||||
|
(
|
||||||
|
fo,
|
||||||
|
"functionObject::" + objPtr->name() + "::read"
|
||||||
|
);
|
||||||
|
|
||||||
enabled = objPtr->read(dict);
|
enabled = objPtr->read(dict);
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = enabled && ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!enabled)
|
if (!enabled)
|
||||||
{
|
{
|
||||||
// Delete disabled or an invalid(read) functionObject
|
// Delete disabled or an invalid(read) functionObject
|
||||||
objPtr.clear();
|
objPtr.reset(nullptr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (enabled)
|
|
||||||
{
|
|
||||||
autoPtr<functionObject> foPtr;
|
|
||||||
|
|
||||||
|
if (enabled && !objPtr)
|
||||||
|
{
|
||||||
// Throw FatalError, FatalIOError as exceptions
|
// Throw FatalError, FatalIOError as exceptions
|
||||||
const bool throwingError = FatalError.throwExceptions();
|
const bool throwingError = FatalError.throwExceptions();
|
||||||
const bool throwingIOerr = FatalIOError.throwExceptions();
|
const bool throwingIOerr = FatalIOError.throwExceptions();
|
||||||
@ -868,47 +1140,70 @@ bool Foam::functionObjectList::read()
|
|||||||
// New functionObject
|
// New functionObject
|
||||||
addProfiling
|
addProfiling
|
||||||
(
|
(
|
||||||
fo2,
|
fo,
|
||||||
"functionObject::" + key + "::new"
|
"functionObject::" + key + "::new"
|
||||||
);
|
);
|
||||||
if (functionObjects::timeControl::entriesPresent(dict))
|
if (needsTimeControl)
|
||||||
{
|
{
|
||||||
foPtr.reset
|
objPtr.reset
|
||||||
(
|
(
|
||||||
new functionObjects::timeControl(key, time_, dict)
|
new functionObjects::timeControl(key, time_, dict)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
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)
|
catch (const Foam::error& err)
|
||||||
{
|
{
|
||||||
// Bit of trickery to get the original message
|
objPtr.reset(nullptr); // extra safety
|
||||||
err.write(Warning, false);
|
|
||||||
InfoInFunction
|
switch (errorHandling)
|
||||||
<< nl
|
{
|
||||||
<< "--> while loading function object '" << key << "'"
|
case errorHandlingType::IGNORE:
|
||||||
<< nl << endl;
|
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);
|
FatalError.throwExceptions(throwingError);
|
||||||
FatalIOError.throwExceptions(throwingIOerr);
|
FatalIOError.throwExceptions(throwingIOerr);
|
||||||
|
|
||||||
// Required functionObject to be valid on all processors
|
// Require valid functionObject on all processors
|
||||||
if (returnReduce(bool(foPtr), andOp<bool>()))
|
if (!returnReduce(bool(objPtr), andOp<bool>()))
|
||||||
{
|
|
||||||
objPtr.reset(foPtr.release());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
objPtr.reset(nullptr);
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -924,12 +1219,14 @@ bool Foam::functionObjectList::read()
|
|||||||
|
|
||||||
newPtrs.resize(nFunc);
|
newPtrs.resize(nFunc);
|
||||||
newDigs.resize(nFunc);
|
newDigs.resize(nFunc);
|
||||||
|
errorHandling_.resize(nFunc);
|
||||||
|
|
||||||
// Updating PtrList of functionObjects deletes any
|
// Updating PtrList of functionObjects deletes any
|
||||||
// existing unused functionObjects
|
// existing unused functionObjects
|
||||||
PtrList<functionObject>::transfer(newPtrs);
|
PtrList<functionObject>::transfer(newPtrs);
|
||||||
digests_.transfer(newDigs);
|
digests_.transfer(newDigs);
|
||||||
indices_.transfer(newIndices);
|
indices_.transfer(newIndices);
|
||||||
|
warnings_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ok;
|
return ok;
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
Copyright (C) 2015-2019 OpenCFD Ltd.
|
Copyright (C) 2015-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -31,6 +31,43 @@ Description
|
|||||||
List of function objects with start(), execute() and end() functions
|
List of function objects with start(), execute() and end() functions
|
||||||
that is called for each object.
|
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
|
See also
|
||||||
Foam::functionObject
|
Foam::functionObject
|
||||||
Foam::functionObjects::timeControl
|
Foam::functionObjects::timeControl
|
||||||
@ -44,6 +81,7 @@ SourceFiles
|
|||||||
#define functionObjectList_H
|
#define functionObjectList_H
|
||||||
|
|
||||||
#include "PtrList.H"
|
#include "PtrList.H"
|
||||||
|
#include "Enum.H"
|
||||||
#include "functionObject.H"
|
#include "functionObject.H"
|
||||||
#include "SHA1Digest.H"
|
#include "SHA1Digest.H"
|
||||||
#include "HashTable.H"
|
#include "HashTable.H"
|
||||||
@ -55,7 +93,7 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
// Forward declarations
|
// Forward Declarations
|
||||||
class argList;
|
class argList;
|
||||||
class mapPolyMesh;
|
class mapPolyMesh;
|
||||||
class wordRe;
|
class wordRe;
|
||||||
@ -68,14 +106,37 @@ class functionObjectList
|
|||||||
:
|
:
|
||||||
private PtrList<functionObject>
|
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
|
//- A list of SHA1 digests for the function object dictionaries
|
||||||
List<SHA1Digest> digests_;
|
List<SHA1Digest> digests_;
|
||||||
|
|
||||||
//- Quick lookup of the index into functions/digests
|
//- Quick lookup of the index into functions/digests/errorHandling
|
||||||
HashTable<label> indices_;
|
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
|
//- Reference to Time
|
||||||
const Time& time_;
|
const Time& time_;
|
||||||
|
|
||||||
@ -119,6 +180,19 @@ class functionObjectList
|
|||||||
//- configuration files, add to the given map and recurse
|
//- configuration files, add to the given map and recurse
|
||||||
static void listDir(const fileName& dir, wordHashSet& available);
|
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
|
//- No copy construct
|
||||||
functionObjectList(const functionObjectList&) = delete;
|
functionObjectList(const functionObjectList&) = delete;
|
||||||
|
|
||||||
@ -214,7 +288,7 @@ public:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
//- Find the ID of a given function object by name, -1 if not found.
|
//- 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
|
//- Print a list of functionObject configuration files in the
|
||||||
//- directories located using
|
//- directories located using
|
||||||
|
|||||||
Reference in New Issue
Block a user