functionObject: Fixed bugs in function object time-step adjustment

The logic governing function objects' ability to change the time-step
has been modified so that it is compatible with the time-step adjustment
done in the Time class. The behaviour has been split into a method which
sets the step directly, and another which moidifies the time until the
next write operation (i.e., the time that the solver "aims" for).

This fixes an issue where the adjustments in Time and the function
objects interfere and cause the time step to decrease exponentially down
to machine precision. It also means that the set-time-step function
object now does not break the adjustable run-time setting.

This resolves bug report https://bugs.openfoam.org/view.php?id=2820
This commit is contained in:
Will Bainbridge
2018-02-05 15:49:14 +00:00
parent 2b76b83343
commit 139ffcc112
10 changed files with 131 additions and 118 deletions

View File

@ -83,44 +83,34 @@ Foam::word Foam::Time::controlDictName("controlDict");
void Foam::Time::adjustDeltaT() void Foam::Time::adjustDeltaT()
{ {
bool adjustTime = false; scalar timeToNextWrite = max
scalar timeToNextWrite = vGreat; (
0.0,
(writeTimeIndex_ + 1)*writeInterval_ - (value() - startTime_)
);
if (writeControl_ == wcAdjustableRunTime) timeToNextWrite = min(timeToNextWrite, functionObjects_.timeToNextWrite());
scalar nSteps = timeToNextWrite/deltaT_;
// For tiny deltaT the label can overflow!
if (nSteps < labelMax)
{ {
adjustTime = true; label nStepsToNextWrite = label(nSteps + 0.5);
timeToNextWrite = max
(
0.0,
(writeTimeIndex_ + 1)*writeInterval_ - (value() - startTime_)
);
}
if (adjustTime) scalar newDeltaT = timeToNextWrite/nStepsToNextWrite;
{
scalar nSteps = timeToNextWrite/deltaT_ - small;
// For tiny deltaT the label can overflow! // Control the increase of the time step to within a factor of 2
if (nSteps < labelMax) // and the decrease within a factor of 5.
if (newDeltaT >= deltaT_)
{ {
label nStepsToNextWrite = label(nSteps) + 1; deltaT_ = min(newDeltaT, 2.0*deltaT_);
}
scalar newDeltaT = timeToNextWrite/nStepsToNextWrite; else
{
// Control the increase of the time step to within a factor of 2 deltaT_ = max(newDeltaT, 0.2*deltaT_);
// and the decrease within a factor of 5.
if (newDeltaT >= deltaT_)
{
deltaT_ = min(newDeltaT, 2.0*deltaT_);
}
else
{
deltaT_ = max(newDeltaT, 0.2*deltaT_);
}
} }
} }
functionObjects_.adjustTimeStep();
} }
@ -921,28 +911,32 @@ void Foam::Time::setEndTime(const scalar endTime)
} }
void Foam::Time::setDeltaT void Foam::Time::setDeltaT(const dimensionedScalar& deltaT)
(
const dimensionedScalar& deltaT,
const bool bAdjustDeltaT
)
{ {
setDeltaT(deltaT.value(), bAdjustDeltaT); setDeltaT(deltaT.value());
} }
void Foam::Time::setDeltaT(const scalar deltaT, const bool bAdjustDeltaT) void Foam::Time::setDeltaT(const scalar deltaT)
{ {
deltaT_ = deltaT; setDeltaTNoAdjust(deltaT);
deltaTchanged_ = true;
if (bAdjustDeltaT) functionObjects_.setTimeStep();
if (writeControl_ == wcAdjustableRunTime)
{ {
adjustDeltaT(); adjustDeltaT();
} }
} }
void Foam::Time::setDeltaTNoAdjust(const scalar deltaT)
{
deltaT_ = deltaT;
deltaTchanged_ = true;
}
Foam::TimeState Foam::Time::subCycle(const label nSubCycles) Foam::TimeState Foam::Time::subCycle(const label nSubCycles)
{ {
subCycling_ = true; subCycling_ = true;

View File

@ -516,18 +516,14 @@ public:
virtual void setEndTime(const scalar); virtual void setEndTime(const scalar);
//- Reset time step //- Reset time step
virtual void setDeltaT virtual void setDeltaT(const dimensionedScalar&);
(
const dimensionedScalar&,
const bool adjustDeltaT = true
);
//- Reset time step //- Reset time step
virtual void setDeltaT virtual void setDeltaT(const scalar);
(
const scalar, //- Reset time step without additional adjustment or modification
const bool adjustDeltaT = true // by function objects
); virtual void setDeltaTNoAdjust(const scalar);
//- Set time to sub-cycle for the given number of steps //- Set time to sub-cycle for the given number of steps
virtual TimeState subCycle(const label nSubCycles); virtual TimeState subCycle(const label nSubCycles);

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -140,12 +140,18 @@ bool Foam::functionObject::end()
} }
bool Foam::functionObject::adjustTimeStep() bool Foam::functionObject::setTimeStep()
{ {
return false; return false;
} }
Foam::scalar Foam::functionObject::timeToNextWrite()
{
return vGreat;
}
void Foam::functionObject::updateMesh(const mapPolyMesh&) void Foam::functionObject::updateMesh(const mapPolyMesh&)
{} {}

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -230,8 +230,14 @@ public:
// By default it simply calls execute(). // By default it simply calls execute().
virtual bool end(); virtual bool end();
//- Called at the end of Time::adjustDeltaT() if adjustTime is true //- Called by Time::setDeltaT(). Allows the function object to override
virtual bool adjustTimeStep(); // the time-step value. Returns whether or not the value was overriden.
virtual bool setTimeStep();
//- Called by Time::adjustTimeStep(). Allows the function object to
// insert a write time earlier than that already in use by the run
// time. Returns the write time, or vGreat.
virtual scalar timeToNextWrite();
//- Update for changes of mesh //- Update for changes of mesh
virtual void updateMesh(const mapPolyMesh& mpm); virtual void updateMesh(const mapPolyMesh& mpm);

View File

@ -565,9 +565,46 @@ bool Foam::functionObjectList::end()
} }
bool Foam::functionObjectList::adjustTimeStep() bool Foam::functionObjectList::setTimeStep()
{ {
bool ok = true; bool set = true;
if (execution_)
{
if (!updated_)
{
read();
}
wordList names;
forAll(*this, objectI)
{
if (operator[](objectI).setTimeStep())
{
names.append(operator[](objectI).name());
set = true;
}
}
if (names.size() > 1)
{
WarningInFunction << "Multiple function objects (" << names[0];
for (label i = 1; i < names.size(); ++ i)
{
WarningInFunction << ", " << names[i];
}
WarningInFunction << ") are setting the time step." << endl;
}
}
return set;
}
Foam::scalar Foam::functionObjectList::timeToNextWrite()
{
scalar result = vGreat;
if (execution_) if (execution_)
{ {
@ -578,11 +615,11 @@ bool Foam::functionObjectList::adjustTimeStep()
forAll(*this, objectI) forAll(*this, objectI)
{ {
ok = operator[](objectI).adjustTimeStep() && ok; result = min(result, operator[](objectI).timeToNextWrite());
} }
} }
return ok; return result;
} }

View File

@ -274,8 +274,11 @@ public:
//- Called when Time::run() determines that the time-loop exits //- Called when Time::run() determines that the time-loop exits
bool end(); bool end();
//- Called at the end of Time::adjustDeltaT() if adjustTime is true //- Override the time-step value
bool adjustTimeStep(); bool setTimeStep();
//- Return the time to the next write
scalar timeToNextWrite();
//- Update for changes of mesh //- Update for changes of mesh
void updateMesh(const mapPolyMesh& mpm); void updateMesh(const mapPolyMesh& mpm);

View File

@ -119,48 +119,27 @@ bool Foam::functionObjects::timeControl::end()
bool Foam::functionObjects::timeControl::adjustTimeStep() Foam::scalar Foam::functionObjects::timeControl::timeToNextWrite()
{ {
if if
( (
active() active()
&& writeControl_.control() && writeControl_.control() == Foam::timeControl::ocAdjustableRunTime
== Foam::timeControl::ocAdjustableRunTime
) )
{ {
const label writeTimeIndex = writeControl_.executionIndex(); const label writeTimeIndex = writeControl_.executionIndex();
const scalar writeInterval = writeControl_.interval(); const scalar writeInterval = writeControl_.interval();
scalar timeToNextWrite = max return
( max
0.0, (
(writeTimeIndex + 1)*writeInterval 0.0,
- (time_.value() - time_.startTime().value()) (writeTimeIndex + 1)*writeInterval
); - (time_.value() - time_.startTime().value())
);
scalar deltaT = time_.deltaTValue();
scalar nSteps = timeToNextWrite/deltaT - small;
// functionObjects modify deltaT within nStepsToStartTimeChange
// NOTE: Potential problems arise if two function objects dump within
// the same interval
if (nSteps < nStepsToStartTimeChange_)
{
label nStepsToNextWrite = label(nSteps) + 1;
scalar newDeltaT = timeToNextWrite/nStepsToNextWrite;
// Adjust time step
if (newDeltaT < deltaT)
{
deltaT = max(newDeltaT, 0.2*deltaT);
const_cast<Time&>(time_).setDeltaT(deltaT, false);
}
}
} }
return true; return vGreat;
} }

View File

@ -158,8 +158,8 @@ public:
//- Called when Time::run() determines that the time-loop exits //- Called when Time::run() determines that the time-loop exits
virtual bool end(); virtual bool end();
//- Called at the end of Time::adjustDeltaT() if adjustTime is true //- Return the time to the next write
virtual bool adjustTimeStep(); virtual scalar timeToNextWrite();
//- Read and set the function object if its data have changed //- Read and set the function object if its data have changed
virtual bool read(const dictionary&); virtual bool read(const dictionary&);

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2013-2018 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -75,12 +75,11 @@ Foam::functionObjects::setTimeStepFunctionObject::time() const
} }
bool Foam::functionObjects::setTimeStepFunctionObject::adjustTimeStep() bool Foam::functionObjects::setTimeStepFunctionObject::setTimeStep()
{ {
const_cast<Time&>(time()).setDeltaT const_cast<Time&>(time()).setDeltaTNoAdjust
( (
timeStepPtr_().value(time_.timeOutputValue()), timeStepPtr_().value(time_.timeOutputValue())
false
); );
return true; return true;
@ -94,27 +93,20 @@ bool Foam::functionObjects::setTimeStepFunctionObject::read
{ {
timeStepPtr_ = Function1<scalar>::New("deltaT", dict); timeStepPtr_ = Function1<scalar>::New("deltaT", dict);
// Check that adjustTimeStep is active
const dictionary& controlDict = time_.controlDict();
Switch adjust;
if
(
!controlDict.readIfPresent<Switch>("adjustTimeStep", adjust)
|| !adjust
)
{
FatalIOErrorInFunction(dict)
<< "Need to set 'adjustTimeStep' true to allow timestep control"
<< exit(FatalIOError);
}
return true; return true;
} }
bool Foam::functionObjects::setTimeStepFunctionObject::execute() bool Foam::functionObjects::setTimeStepFunctionObject::execute()
{ {
bool adjustTimeStep =
time().controlDict().lookupOrDefault("adjustTimeStep", false);
if (!adjustTimeStep)
{
return setTimeStep();
}
return true; return true;
} }

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation \\ / A nd | Copyright (C) 2013-2018 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -104,8 +104,8 @@ public:
//- Return time database //- Return time database
const Time& time() const; const Time& time() const;
//- Called at the end of Time::adjustDeltaT() if adjustTime is true //- Override the time-step value
virtual bool adjustTimeStep(); virtual bool setTimeStep();
//- Read and set the function object if its data have changed //- Read and set the function object if its data have changed
virtual bool read(const dictionary&); virtual bool read(const dictionary&);