From 139ffcc112ae49d60d8d9f8b0c8c2d7b6315268e Mon Sep 17 00:00:00 2001 From: Will Bainbridge Date: Mon, 5 Feb 2018 15:49:14 +0000 Subject: [PATCH] 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 --- src/OpenFOAM/db/Time/Time.C | 76 +++++++++---------- src/OpenFOAM/db/Time/Time.H | 16 ++-- .../functionObject/functionObject.C | 10 ++- .../functionObject/functionObject.H | 12 ++- .../functionObjectList/functionObjectList.C | 45 ++++++++++- .../functionObjectList/functionObjectList.H | 7 +- .../timeControl/timeControlFunctionObject.C | 41 +++------- .../timeControl/timeControlFunctionObject.H | 4 +- .../setTimeStep/setTimeStepFunctionObject.C | 32 +++----- .../setTimeStep/setTimeStepFunctionObject.H | 6 +- 10 files changed, 131 insertions(+), 118 deletions(-) diff --git a/src/OpenFOAM/db/Time/Time.C b/src/OpenFOAM/db/Time/Time.C index f002f414f..9444eafaa 100644 --- a/src/OpenFOAM/db/Time/Time.C +++ b/src/OpenFOAM/db/Time/Time.C @@ -83,44 +83,34 @@ Foam::word Foam::Time::controlDictName("controlDict"); void Foam::Time::adjustDeltaT() { - bool adjustTime = false; - scalar timeToNextWrite = vGreat; + scalar timeToNextWrite = max + ( + 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; - timeToNextWrite = max - ( - 0.0, - (writeTimeIndex_ + 1)*writeInterval_ - (value() - startTime_) - ); - } + label nStepsToNextWrite = label(nSteps + 0.5); - if (adjustTime) - { - scalar nSteps = timeToNextWrite/deltaT_ - small; + scalar newDeltaT = timeToNextWrite/nStepsToNextWrite; - // For tiny deltaT the label can overflow! - if (nSteps < labelMax) + // Control the increase of the time step to within a factor of 2 + // and the decrease within a factor of 5. + if (newDeltaT >= deltaT_) { - label nStepsToNextWrite = label(nSteps) + 1; - - scalar newDeltaT = timeToNextWrite/nStepsToNextWrite; - - // Control the increase of the time step to within a factor of 2 - // and the decrease within a factor of 5. - if (newDeltaT >= deltaT_) - { - deltaT_ = min(newDeltaT, 2.0*deltaT_); - } - else - { - deltaT_ = max(newDeltaT, 0.2*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 -( - const dimensionedScalar& deltaT, - const bool bAdjustDeltaT -) +void Foam::Time::setDeltaT(const dimensionedScalar& deltaT) { - 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; - deltaTchanged_ = true; + setDeltaTNoAdjust(deltaT); - if (bAdjustDeltaT) + functionObjects_.setTimeStep(); + + if (writeControl_ == wcAdjustableRunTime) { adjustDeltaT(); } } +void Foam::Time::setDeltaTNoAdjust(const scalar deltaT) +{ + deltaT_ = deltaT; + deltaTchanged_ = true; +} + + Foam::TimeState Foam::Time::subCycle(const label nSubCycles) { subCycling_ = true; diff --git a/src/OpenFOAM/db/Time/Time.H b/src/OpenFOAM/db/Time/Time.H index aca338171..edc81da10 100644 --- a/src/OpenFOAM/db/Time/Time.H +++ b/src/OpenFOAM/db/Time/Time.H @@ -516,18 +516,14 @@ public: virtual void setEndTime(const scalar); //- Reset time step - virtual void setDeltaT - ( - const dimensionedScalar&, - const bool adjustDeltaT = true - ); + virtual void setDeltaT(const dimensionedScalar&); //- Reset time step - virtual void setDeltaT - ( - const scalar, - const bool adjustDeltaT = true - ); + virtual void setDeltaT(const scalar); + + //- Reset time step without additional adjustment or modification + // by function objects + virtual void setDeltaTNoAdjust(const scalar); //- Set time to sub-cycle for the given number of steps virtual TimeState subCycle(const label nSubCycles); diff --git a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C index b0a92bc5c..c924f3a12 100644 --- a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C +++ b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -140,12 +140,18 @@ bool Foam::functionObject::end() } -bool Foam::functionObject::adjustTimeStep() +bool Foam::functionObject::setTimeStep() { return false; } +Foam::scalar Foam::functionObject::timeToNextWrite() +{ + return vGreat; +} + + void Foam::functionObject::updateMesh(const mapPolyMesh&) {} diff --git a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H index 4d52ac218..ff3867192 100644 --- a/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H +++ b/src/OpenFOAM/db/functionObjects/functionObject/functionObject.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2011-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -230,8 +230,14 @@ public: // By default it simply calls execute(). virtual bool end(); - //- Called at the end of Time::adjustDeltaT() if adjustTime is true - virtual bool adjustTimeStep(); + //- Called by Time::setDeltaT(). Allows the function object to override + // 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 virtual void updateMesh(const mapPolyMesh& mpm); diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C index 57f06fcdd..0e865e60a 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.C @@ -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_) { @@ -578,11 +615,11 @@ bool Foam::functionObjectList::adjustTimeStep() forAll(*this, objectI) { - ok = operator[](objectI).adjustTimeStep() && ok; + result = min(result, operator[](objectI).timeToNextWrite()); } } - return ok; + return result; } diff --git a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H index dc0bf94ad..f6be58132 100644 --- a/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H +++ b/src/OpenFOAM/db/functionObjects/functionObjectList/functionObjectList.H @@ -274,8 +274,11 @@ public: //- Called when Time::run() determines that the time-loop exits bool end(); - //- Called at the end of Time::adjustDeltaT() if adjustTime is true - bool adjustTimeStep(); + //- Override the time-step value + bool setTimeStep(); + + //- Return the time to the next write + scalar timeToNextWrite(); //- Update for changes of mesh void updateMesh(const mapPolyMesh& mpm); diff --git a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C index ecebd48e9..72bcfb8b2 100644 --- a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C +++ b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.C @@ -119,48 +119,27 @@ bool Foam::functionObjects::timeControl::end() -bool Foam::functionObjects::timeControl::adjustTimeStep() +Foam::scalar Foam::functionObjects::timeControl::timeToNextWrite() { if ( active() - && writeControl_.control() - == Foam::timeControl::ocAdjustableRunTime + && writeControl_.control() == Foam::timeControl::ocAdjustableRunTime ) { const label writeTimeIndex = writeControl_.executionIndex(); const scalar writeInterval = writeControl_.interval(); - scalar timeToNextWrite = max - ( - 0.0, - (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_).setDeltaT(deltaT, false); - } - } + return + max + ( + 0.0, + (writeTimeIndex + 1)*writeInterval + - (time_.value() - time_.startTime().value()) + ); } - return true; + return vGreat; } diff --git a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.H b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.H index b4e5d35d3..a49f05048 100644 --- a/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.H +++ b/src/OpenFOAM/db/functionObjects/timeControl/timeControlFunctionObject.H @@ -158,8 +158,8 @@ public: //- Called when Time::run() determines that the time-loop exits virtual bool end(); - //- Called at the end of Time::adjustDeltaT() if adjustTime is true - virtual bool adjustTimeStep(); + //- Return the time to the next write + virtual scalar timeToNextWrite(); //- Read and set the function object if its data have changed virtual bool read(const dictionary&); diff --git a/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.C b/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.C index 1f4554360..c7319986c 100644 --- a/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.C +++ b/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2016 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2013-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -75,12 +75,11 @@ Foam::functionObjects::setTimeStepFunctionObject::time() const } -bool Foam::functionObjects::setTimeStepFunctionObject::adjustTimeStep() +bool Foam::functionObjects::setTimeStepFunctionObject::setTimeStep() { - const_cast(time()).setDeltaT + const_cast(time()).setDeltaTNoAdjust ( - timeStepPtr_().value(time_.timeOutputValue()), - false + timeStepPtr_().value(time_.timeOutputValue()) ); return true; @@ -94,27 +93,20 @@ bool Foam::functionObjects::setTimeStepFunctionObject::read { timeStepPtr_ = Function1::New("deltaT", dict); - // Check that adjustTimeStep is active - const dictionary& controlDict = time_.controlDict(); - - Switch adjust; - if - ( - !controlDict.readIfPresent("adjustTimeStep", adjust) - || !adjust - ) - { - FatalIOErrorInFunction(dict) - << "Need to set 'adjustTimeStep' true to allow timestep control" - << exit(FatalIOError); - } - return true; } bool Foam::functionObjects::setTimeStepFunctionObject::execute() { + bool adjustTimeStep = + time().controlDict().lookupOrDefault("adjustTimeStep", false); + + if (!adjustTimeStep) + { + return setTimeStep(); + } + return true; } diff --git a/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.H b/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.H index d6e621dcd..a128dfa5a 100644 --- a/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.H +++ b/src/functionObjects/utilities/setTimeStep/setTimeStepFunctionObject.H @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2013-2017 OpenFOAM Foundation + \\ / A nd | Copyright (C) 2013-2018 OpenFOAM Foundation \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -104,8 +104,8 @@ public: //- Return time database const Time& time() const; - //- Called at the end of Time::adjustDeltaT() if adjustTime is true - virtual bool adjustTimeStep(); + //- Override the time-step value + virtual bool setTimeStep(); //- Read and set the function object if its data have changed virtual bool read(const dictionary&);