Merge branch 'feature-externalCoupled' into 'develop'

preliminary improvements for externalCoupled

See merge request Development/OpenFOAM-plus!175
This commit is contained in:
Mark Olesen
2017-11-28 16:54:06 +00:00
38 changed files with 903 additions and 456 deletions

View File

@ -309,7 +309,7 @@ int main(int argc, char *argv[])
if if
( (
matchName != "perfect" matchName != "perfect"
&& !slidingInterface::typeOfMatchNames.hasEnum(matchName) && !slidingInterface::typeOfMatchNames.found(matchName)
) )
{ {
Info<< "Error: unknown match type - " << matchName Info<< "Error: unknown match type - " << matchName

View File

@ -229,7 +229,7 @@ int main(int argc, char *argv[])
word patchMapMethod; word patchMapMethod;
if (meshToMesh::interpolationMethodNames_.hasEnum(mapMethod)) if (meshToMesh::interpolationMethodNames_.found(mapMethod))
{ {
// Lookup corresponding AMI method // Lookup corresponding AMI method
meshToMesh::interpolationMethod method = meshToMesh::interpolationMethod method =

View File

@ -1577,7 +1577,7 @@ int main(int argc, char *argv[])
{ booleanSurface::DIFFERENCE, "difference" } { booleanSurface::DIFFERENCE, "difference" }
}; };
if (!validActions.hasEnum(action)) if (!validActions.found(action))
{ {
FatalErrorInFunction FatalErrorInFunction
<< "Unsupported action " << action << endl << "Unsupported action " << action << endl

View File

@ -284,6 +284,7 @@ $(Time)/Time.C
$(Time)/TimeIO.C $(Time)/TimeIO.C
$(Time)/findTimes.C $(Time)/findTimes.C
$(Time)/subCycleTime.C $(Time)/subCycleTime.C
$(Time)/subLoopTime.C
$(Time)/findInstance.C $(Time)/findInstance.C
$(Time)/timeSelector.C $(Time)/timeSelector.C

View File

@ -112,10 +112,10 @@ class subCycle
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
subCycle(const subCycle<GeometricField>&); subCycle(const subCycle<GeometricField>&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const subCycle<GeometricField>&); void operator=(const subCycle<GeometricField>&) = delete;
public: public:
@ -123,10 +123,10 @@ public:
// Constructors // Constructors
//- Construct field and number of sub-cycles //- Construct field and number of sub-cycles
subCycle(GeometricField& gf, const label nSubCycles) subCycle(GeometricField& gf, const label nCycles)
: :
subCycleField<GeometricField>(gf), subCycleField<GeometricField>(gf),
subCycleTime(const_cast<Time&>(gf.time()), nSubCycles) subCycleTime(const_cast<Time&>(gf.time()), nCycles)
{ {
// Update the field time index to correspond to the sub-cycle time // Update the field time index to correspond to the sub-cycle time
this->updateTimeIndex(); this->updateTimeIndex();

View File

@ -44,12 +44,14 @@ const Foam::Enum
< <
Foam::Time::stopAtControls Foam::Time::stopAtControls
> >
Foam::Time::stopAtControlNames_ Foam::Time::stopAtControlNames
{ {
{ stopAtControls::saEndTime, "endTime" }, { stopAtControls::saEndTime, "endTime" },
{ stopAtControls::saNoWriteNow, "noWriteNow" }, { stopAtControls::saNoWriteNow, "noWriteNow" },
{ stopAtControls::saWriteNow, "writeNow" }, { stopAtControls::saWriteNow, "writeNow" },
{ stopAtControls::saNextWrite, "nextWrite" }, { stopAtControls::saNextWrite, "nextWrite" },
// NOTE: stopAtControls::saUnknown is left untabulated here so that it can
// be used as fallback value to flag unknown settings
}; };
@ -57,7 +59,7 @@ const Foam::Enum
< <
Foam::Time::writeControls Foam::Time::writeControls
> >
Foam::Time::writeControlNames_ Foam::Time::writeControlNames
{ {
{ writeControls::wcTimeStep, "timeStep" }, { writeControls::wcTimeStep, "timeStep" },
{ writeControls::wcRunTime, "runTime" }, { writeControls::wcRunTime, "runTime" },
@ -433,8 +435,8 @@ Foam::Time::Time
writeControl_(wcTimeStep), writeControl_(wcTimeStep),
writeInterval_(GREAT), writeInterval_(GREAT),
purgeWrite_(0), purgeWrite_(0),
subCycling_(0),
writeOnce_(false), writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this), sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this), sigStopAtWriteNow_(true, *this),
@ -502,8 +504,8 @@ Foam::Time::Time
writeControl_(wcTimeStep), writeControl_(wcTimeStep),
writeInterval_(GREAT), writeInterval_(GREAT),
purgeWrite_(0), purgeWrite_(0),
subCycling_(0),
writeOnce_(false), writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this), sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this), sigStopAtWriteNow_(true, *this),
@ -581,8 +583,8 @@ Foam::Time::Time
writeControl_(wcTimeStep), writeControl_(wcTimeStep),
writeInterval_(GREAT), writeInterval_(GREAT),
purgeWrite_(0), purgeWrite_(0),
subCycling_(0),
writeOnce_(false), writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this), sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this), sigStopAtWriteNow_(true, *this),
@ -651,9 +653,8 @@ Foam::Time::Time
writeControl_(wcTimeStep), writeControl_(wcTimeStep),
writeInterval_(GREAT), writeInterval_(GREAT),
purgeWrite_(0), purgeWrite_(0),
subCycling_(0),
writeOnce_(false), writeOnce_(false),
subCycling_(false),
writeFormat_(IOstream::ASCII), writeFormat_(IOstream::ASCII),
writeVersion_(IOstream::currentVersion), writeVersion_(IOstream::currentVersion),
writeCompression_(IOstream::UNCOMPRESSED), writeCompression_(IOstream::UNCOMPRESSED),
@ -825,6 +826,12 @@ Foam::dimensionedScalar Foam::Time::endTime() const
} }
Foam::Time::stopAtControls Foam::Time::stopAt() const
{
return stopAt_;
}
bool Foam::Time::run() const bool Foam::Time::run() const
{ {
deleteDemandDrivenData(loopProfiling_); deleteDemandDrivenData(loopProfiling_);
@ -913,20 +920,23 @@ bool Foam::Time::end() const
} }
bool Foam::Time::stopAt(const stopAtControls sa) const bool Foam::Time::stopAt(const stopAtControls stopCtrl) const
{ {
const bool changed = (stopAt_ != sa); if (stopCtrl == stopAtControls::saUnknown)
stopAt_ = sa; {
return false;
}
// adjust endTime const bool changed = (stopAt_ != stopCtrl);
if (sa == saEndTime) stopAt_ = stopCtrl;
endTime_ = GREAT;
// Adjust endTime
if (stopCtrl == stopAtControls::saEndTime)
{ {
controlDict_.lookup("endTime") >> endTime_; controlDict_.lookup("endTime") >> endTime_;
} }
else
{
endTime_ = GREAT;
}
return changed; return changed;
} }
@ -1018,26 +1028,41 @@ void Foam::Time::setDeltaT(const scalar deltaT, const bool adjust)
Foam::TimeState Foam::Time::subCycle(const label nSubCycles) Foam::TimeState Foam::Time::subCycle(const label nSubCycles)
{ {
subCycling_ = true; prevTimeState_.set(new TimeState(*this)); // Fatal if already set
prevTimeState_.reset(new TimeState(*this));
setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles); setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles);
deltaT_ /= nSubCycles; deltaT_ /= nSubCycles;
deltaT0_ /= nSubCycles; deltaT0_ /= nSubCycles;
deltaTSave_ = deltaT0_; deltaTSave_ = deltaT0_;
subCycling_ = nSubCycles;
return prevTimeState(); return prevTimeState();
} }
void Foam::Time::subCycleIndex(const label index)
{
// Only permit adjustment if sub-cycling was already active
// and if the index is valid (positive, non-zero).
// This avoids potential mixups for deleting.
if (subCycling_ && index > 0)
{
subCycling_ = index;
}
}
void Foam::Time::endSubCycle() void Foam::Time::endSubCycle()
{ {
if (subCycling_) if (subCycling_)
{ {
subCycling_ = false;
TimeState::operator=(prevTimeState()); TimeState::operator=(prevTimeState());
prevTimeState_.clear(); prevTimeState_.clear();
} }
subCycling_ = 0;
} }
@ -1113,7 +1138,7 @@ Foam::Time& Foam::Time::operator++()
case wcRunTime: case wcRunTime:
case wcAdjustableRunTime: case wcAdjustableRunTime:
{ {
label writeIndex = label const label writeIndex = label
( (
((value() - startTime_) + 0.5*deltaT_) ((value() - startTime_) + 0.5*deltaT_)
/ writeInterval_ / writeInterval_
@ -1129,7 +1154,7 @@ Foam::Time& Foam::Time::operator++()
case wcCpuTime: case wcCpuTime:
{ {
label writeIndex = label const label writeIndex = label
( (
returnReduce(elapsedCpuTime(), maxOp<double>()) returnReduce(elapsedCpuTime(), maxOp<double>())
/ writeInterval_ / writeInterval_
@ -1144,7 +1169,7 @@ Foam::Time& Foam::Time::operator++()
case wcClockTime: case wcClockTime:
{ {
label writeIndex = label const label writeIndex = label
( (
returnReduce(label(elapsedClockTime()), maxOp<label>()) returnReduce(label(elapsedClockTime()), maxOp<label>())
/ writeInterval_ / writeInterval_
@ -1201,7 +1226,7 @@ Foam::Time& Foam::Time::operator++()
// reinterpretation of the word // reinterpretation of the word
if if
( (
readScalar(dimensionedScalar::name().c_str(), timeNameValue) readScalar(dimensionedScalar::name(), timeNameValue)
&& (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol) && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
) )
{ {
@ -1209,7 +1234,7 @@ Foam::Time& Foam::Time::operator++()
while while
( (
precision_ < maxPrecision_ precision_ < maxPrecision_
&& readScalar(dimensionedScalar::name().c_str(), timeNameValue) && readScalar(dimensionedScalar::name(), timeNameValue)
&& (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol) && (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
) )
{ {
@ -1242,7 +1267,7 @@ Foam::Time& Foam::Time::operator++()
scalar oldTimeNameValue = -VGREAT; scalar oldTimeNameValue = -VGREAT;
if if
( (
readScalar(oldTimeName.c_str(), oldTimeNameValue) readScalar(oldTimeName, oldTimeNameValue)
&& ( && (
sign(timeNameValue - oldTimeNameValue) sign(timeNameValue - oldTimeNameValue)
!= sign(deltaT_) != sign(deltaT_)

View File

@ -75,6 +75,47 @@ class Time
public objectRegistry, public objectRegistry,
public TimeState public TimeState
{ {
public:
//- Write control options
enum writeControls
{
wcTimeStep, //!< "timeStep"
wcRunTime, //!< "runTime"
wcAdjustableRunTime, //!< "adjustableRunTime"
wcClockTime, //!< "clockTime"
wcCpuTime //!< "cpuTime"
};
//- Stop-run control options, which are primarily used when
//- altering the stopAt condition.
enum stopAtControls
{
saEndTime, //!< Stop when Time reaches prescribed endTime
saNoWriteNow, //!< Adjust endTime to stop immediately w/o writing
saWriteNow, //!< adjust endTime to stop immediately w/ writing
saNextWrite, //!< stop at the next data write interval
saUnknown //!< Dummy no-op. Do not change current value.
};
//- Supported time directory name formats
enum fmtflags
{
general = 0, //!< default float notation
fixed = ios_base::fixed, //!< fixed-point notation
scientific = ios_base::scientific //!< scientific notation
};
//- Names for writeControls
static const Enum<writeControls> writeControlNames;
//- Names for stopAtControls
static const Enum<stopAtControls> stopAtControlNames;
private:
// Private data // Private data
//- Profiling trigger for time-loop (for run, loop) //- Profiling trigger for time-loop (for run, loop)
@ -88,36 +129,6 @@ class Time
unwatchedIOdictionary controlDict_; unwatchedIOdictionary controlDict_;
public:
//- Write control options
enum writeControls
{
wcTimeStep,
wcRunTime,
wcAdjustableRunTime,
wcClockTime,
wcCpuTime
};
//- Stop-run control options
enum stopAtControls
{
saEndTime, //!< stop when Time reaches the prescribed endTime
saNoWriteNow, //!< set endTime to stop immediately w/o writing
saWriteNow, //!< set endTime to stop immediately w/ writing
saNextWrite //!< stop the next time data are written
};
//- Supported time directory name formats
enum fmtflags
{
general = 0,
fixed = ios_base::fixed,
scientific = ios_base::scientific
};
protected: protected:
// Protected data // Protected data
@ -126,33 +137,30 @@ protected:
scalar startTime_; scalar startTime_;
mutable scalar endTime_; mutable scalar endTime_;
static const Enum<stopAtControls> stopAtControlNames_;
mutable stopAtControls stopAt_; mutable stopAtControls stopAt_;
static const Enum<writeControls> writeControlNames_;
writeControls writeControl_; writeControls writeControl_;
scalar writeInterval_; scalar writeInterval_;
label purgeWrite_; label purgeWrite_;
mutable FIFOStack<word> previousWriteTimes_; mutable FIFOStack<word> previousWriteTimes_;
//- The total number of sub-cycles, the current sub-cycle index,
//- or 0 if time is not being sub-cycled
label subCycling_;
// One-shot writing // One-shot writing
bool writeOnce_; bool writeOnce_;
//- Is the time currently being sub-cycled?
bool subCycling_;
//- If time is being sub-cycled this is the previous TimeState //- If time is being sub-cycled this is the previous TimeState
autoPtr<TimeState> prevTimeState_; autoPtr<TimeState> prevTimeState_;
//- Signal handler for one-shot writing upon signal
// Signal handlers for writing
//- Enable one-shot writing upon signal
sigWriteNow sigWriteNow_; sigWriteNow sigWriteNow_;
//- Enable write and clean exit upon signal //- Signal handler for write and clean exit upon signal
sigStopAtWriteNow sigStopAtWriteNow_; sigStopAtWriteNow sigStopAtWriteNow_;
@ -165,6 +173,7 @@ protected:
//- Maximum time directory name precision //- Maximum time directory name precision
static const int maxPrecision_; static const int maxPrecision_;
//- Adjust the time step so that writing occurs at the specified time //- Adjust the time step so that writing occurs at the specified time
void adjustDeltaT(); void adjustDeltaT();
@ -179,7 +188,7 @@ protected:
virtual void readDict(); virtual void readDict();
//- Find IOobject in the objectPath //- Find IOobject in the objectPath
static bool exists(IOobject&); static bool exists(IOobject& io);
private: private:
@ -423,6 +432,9 @@ public:
//- Return end time //- Return end time
virtual dimensionedScalar endTime() const; virtual dimensionedScalar endTime() const;
//- Return the stop control information
virtual stopAtControls stopAt() const;
//- Return the list of function objects //- Return the list of function objects
const functionObjectList& functionObjects() const const functionObjectList& functionObjects() const
{ {
@ -441,8 +453,12 @@ public:
return libs_; return libs_;
} }
//- Return true if time currently being sub-cycled, otherwise false //- Zero (tests as false) if time is not being sub-cycled,
bool subCycling() const //- otherwise the current sub-cycle index or the total number of
//- sub-cycles.
// The interpretation of non-zero values is dependent on the
// routine.
label subCycling() const
{ {
return subCycling_; return subCycling_;
} }
@ -498,10 +514,13 @@ public:
// Edit // Edit
//- Adjust the current stopAtControl. Note that this value //- Adjust the current stopAtControl.
// only persists until the next time the dictionary is read. // \param stopCtrl the new stop control, whereby
// Return true if the stopAtControl changed. // stopAtControls::saUnknown is treated as a no-op.
virtual bool stopAt(const stopAtControls sa) const; // \note this value only persists until the next time the
// dictionary is read.
// \return true if the stopAt() value was changed.
virtual bool stopAt(const stopAtControls stopCtrl) const;
//- Reset the time and time-index to those of the given time //- Reset the time and time-index to those of the given time
virtual void setTime(const Time& t); virtual void setTime(const Time& t);
@ -542,6 +561,13 @@ public:
//- 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);
//- Adjust the reported sub-cycle index.
// \param index is the sub-cycle index.
// This index is ignored sub-cycling was
// not already registered, or if the index is zero or
// negative.
virtual void subCycleIndex(const label index);
//- Reset time after sub-cycling back to previous TimeState //- Reset time after sub-cycling back to previous TimeState
virtual void endSubCycle(); virtual void endSubCycle();

View File

@ -240,7 +240,7 @@ void Foam::Time::readDict()
if (controlDict_.found("writeControl")) if (controlDict_.found("writeControl"))
{ {
writeControl_ = writeControlNames_.lookup writeControl_ = writeControlNames.lookup
( (
"writeControl", "writeControl",
controlDict_ controlDict_
@ -328,7 +328,7 @@ void Foam::Time::readDict()
// if nothing is specified, the endTime is zero // if nothing is specified, the endTime is zero
if (controlDict_.found("stopAt")) if (controlDict_.found("stopAt"))
{ {
stopAt_ = stopAtControlNames_.lookup("stopAt", controlDict_); stopAt_ = stopAtControlNames.lookup("stopAt", controlDict_);
if (stopAt_ == saEndTime) if (stopAt_ == saEndTime)
{ {
@ -439,10 +439,8 @@ bool Foam::Time::read()
return true; return true;
} }
else
{
return false; return false;
}
} }
@ -567,10 +565,8 @@ bool Foam::Time::writeObject
return writeOK; return writeOK;
} }
else
{
return false; return false;
}
} }

View File

@ -27,13 +27,14 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::subCycleTime::subCycleTime(Time& t, const label nSubCycles) Foam::subCycleTime::subCycleTime(Time& runTime, const label nCycles)
: :
time_(t), time_(runTime),
nSubCycles_(nSubCycles), index_(0),
subCycleIndex_(0) total_(nCycles)
{ {
time_.subCycle(nSubCycles_); // Could avoid 0 or 1 nCycles here on construction
time_.subCycle(nCycles);
} }
@ -47,15 +48,38 @@ Foam::subCycleTime::~subCycleTime()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::subCycleTime::status() const
{
return (index_ <= total_);
}
bool Foam::subCycleTime::end() const bool Foam::subCycleTime::end() const
{ {
return subCycleIndex_ > nSubCycles_; return (index_ > total_); // or !(status())
} }
void Foam::subCycleTime::endSubCycle() void Foam::subCycleTime::endSubCycle()
{ {
time_.endSubCycle(); time_.endSubCycle();
// If called manually, ensure status() will return false
index_ = total_ + 1;
}
bool Foam::subCycleTime::loop()
{
const bool active = status();
if (active)
{
operator++();
}
return active;
} }
@ -63,8 +87,12 @@ void Foam::subCycleTime::endSubCycle()
Foam::subCycleTime& Foam::subCycleTime::operator++() Foam::subCycleTime& Foam::subCycleTime::operator++()
{ {
time_++; ++time_;
subCycleIndex_++; ++index_;
// Register index change with Time, in case someone wants this information
time_.subCycleIndex(index_);
return *this; return *this;
} }

View File

@ -50,17 +50,22 @@ class subCycleTime
{ {
// Private data // Private data
//- Reference to the underlying time
Time& time_; Time& time_;
label nSubCycles_; //- Current index in the sub-cycle
label subCycleIndex_; label index_;
//- Total number of cycles in the sub-cycle
label total_;
public: public:
// Constructors // Constructors
//- Construct from original time and number of sub-cycles //- Construct referencing the original time and number of sub-cycles
subCycleTime(Time&, const label nSubCycles); subCycleTime(Time& runTime, const label nCycle);
//- Destructor //- Destructor
@ -69,23 +74,36 @@ public:
// Member functions // Member functions
//- Return the current sub-cycle index
inline label index() const
{
return index_;
}
//- Return the total number of sub-cycles
inline label nSubCycles() const
{
return total_;
}
//- True if the sub-cycle is active.
bool status() const;
//- Return true if the number of sub-cycles has been reached //- Return true if the number of sub-cycles has been reached
bool end() const; bool end() const;
//- End the sub-cycling and reset the time-state //- End the sub-cycling and reset the time-state
void endSubCycle(); void endSubCycle();
//- Return the total number of sub-cycles //- True if looping is active, increments the index.
label nSubCycles() const // Example usage,
{ // \code
return nSubCycles_; // while (subcycle.loop())
} // {
// solve;
//- Return the current sub-cycle index // }
label index() const // \endcode
{ bool loop();
return subCycleIndex_;
}
// Member operators // Member operators
@ -93,7 +111,7 @@ public:
//- Prefix increment //- Prefix increment
subCycleTime& operator++(); subCycleTime& operator++();
//- Postfix increment //- Postfix increment, this is identical to the prefix increment
subCycleTime& operator++(int); subCycleTime& operator++(int);
}; };

View File

@ -0,0 +1,85 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "subLoopTime.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::subLoopTime::subLoopTime(Time& runTime, const label nCycles)
:
time_(runTime),
index_(0),
total_(nCycles)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::subLoopTime::~subLoopTime()
{
stop();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::subLoopTime::status() const
{
return (index_ < total_);
}
void Foam::subLoopTime::stop()
{
// If called manually, ensure status() will return false
index_ = total_ + 1;
}
bool Foam::subLoopTime::loop()
{
const bool active = (index_ < total_); // as per status()
if (active)
{
operator++();
}
else if (index_)
{
// Not active, the loop condition has now exiting on the last subloop
}
return active;
}
Foam::subLoopTime& Foam::subLoopTime::operator++()
{
++index_;
return *this;
}
// ************************************************************************* //

View File

@ -0,0 +1,137 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::subLoopTime
Description
A class for managing sub-loops referencing Time.
SourceFiles
subLoopTime.C
SeeAlso
subCycleTime
\*---------------------------------------------------------------------------*/
#ifndef subLoopTime_H
#define subLoopTime_H
#include "Time.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class subLoopTime Declaration
\*---------------------------------------------------------------------------*/
class subLoopTime
{
// Private Member Functions
//- Disallow default bitwise copy construct
subLoopTime(const subLoopTime&) = delete;
//- Disallow default bitwise assignment
void operator=(const subLoopTime&) = delete;
protected:
// Protected data
Time& time_;
//- The current sub-cycle index
label index_;
//- The total number of cycles in the sub-cycle
label total_;
public:
// Constructors
//- Construct from time with fixed number of cycles
// \param runTime the top-level time
// \param nCycles the number of times to loop
subLoopTime(Time& runTime, const label nCycles);
//- Destructor
~subLoopTime();
// Member Functions
//- The current cycle index
inline label index() const
{
return index_;
}
//- The total number of cycles
inline label nCycles() const
{
return total_;
}
//- Return true if looping is active
bool status() const;
//- Force terminate the loop
void stop();
//- True if looping is active, increments the index.
// Example usage,
// \code
// while (control.loop())
// {
// solve;
// }
// \endcode
bool loop();
// Member Operators
//- Prefix increment
subLoopTime& operator++();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -117,7 +117,7 @@ bool Foam::functionEntries::inputMode::execute
const word modeName(is); const word modeName(is);
// Behaviour like Enum lookupOrFailsafe() // Behaviour like Enum lookupOrFailsafe()
if (selectableNames.hasEnum(modeName)) if (selectableNames.found(modeName))
{ {
entry::globalInputMode = selectableNames[modeName]; entry::globalInputMode = selectableNames[modeName];
} }

View File

@ -105,12 +105,8 @@ Foam::instantList Foam::fileOperation::sortTimes
// Read and parse all the entries in the directory // Read and parse all the entries in the directory
forAll(dirEntries, i) forAll(dirEntries, i)
{ {
//IStringStream timeStream(dirEntries[i]);
//token timeToken(timeStream);
//if (timeToken.isNumber() && timeStream.eof())
scalar timeValue; scalar timeValue;
if (readScalar(dirEntries[i].c_str(), timeValue)) if (readScalar(dirEntries[i], timeValue))
{ {
Times[nTimes].value() = timeValue; Times[nTimes].value() = timeValue;
Times[nTimes].name() = dirEntries[i]; Times[nTimes].name() = dirEntries[i];

View File

@ -291,25 +291,24 @@ Foam::fileOperations::masterUncollatedFileOperation::splitProcessorPath
local = objectPath.substr(pos+9); local = objectPath.substr(pos+9);
} }
label proci;
pos = local.find('/'); pos = local.find('/');
if (pos == string::npos) if (pos == string::npos)
{ {
// processorXXX without local // processorXXX without local
label proci; if (Foam::read(local, proci))
if (Foam::read(local.c_str(), proci))
{ {
local.clear(); local.clear();
return proci; return proci;
} }
return -1;
} }
string procName(local.substr(0, pos)); else if (Foam::read(local.substr(0, pos), proci))
label proci;
if (Foam::read(procName.c_str(), proci))
{ {
local = local.substr(pos+1); local = local.substr(pos+1);
return proci; return proci;
} }
return -1; return -1;
} }

View File

@ -63,10 +63,10 @@ class data
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
data(const data&); data(const data&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const data&); void operator=(const data&) = delete;
public: public:
@ -83,11 +83,8 @@ public:
// Member Functions // Member Functions
// Access //- Return the dictionary of solver performance data which
//- includes initial and final residuals for convergence checking
//- Return the dictionary of solver performance data
// which includes initial and final residuals for convergence
// checking
const dictionary& solverPerformanceDict() const; const dictionary& solverPerformanceDict() const;
//- Add/set the solverPerformance entry for the named field //- Add/set the solverPerformance entry for the named field
@ -95,14 +92,14 @@ public:
void setSolverPerformance void setSolverPerformance
( (
const word& name, const word& name,
const SolverPerformance<Type>& const SolverPerformance<Type>& sp
) const; ) const;
//- Add/set the solverPerformance entry, using its fieldName //- Add/set the solverPerformance entry, using its fieldName
template<class Type> template<class Type>
void setSolverPerformance void setSolverPerformance
( (
const SolverPerformance<Type>& const SolverPerformance<Type>& sp
) const; ) const;
}; };

View File

@ -87,10 +87,8 @@ const Foam::word& Foam::Enum<EnumType>::getName(const EnumType e) const
{ {
return word::null; return word::null;
} }
else
{
return names_[idx]; return names_[idx];
}
} }
@ -233,16 +231,14 @@ EnumType Foam::Enum<EnumType>::lookupOrFailsafe
const word enumName(dict.lookup(key)); const word enumName(dict.lookup(key));
const label idx = getIndex(enumName); const label idx = getIndex(enumName);
if (idx < 0) if (idx >= 0)
{
IOWarningInFunction(dict)
<< "bad " << key <<" specifier " << enumName
<< " using " << getName(deflt) << endl;
}
else
{ {
return EnumType(values_[idx]); return EnumType(values_[idx]);
} }
IOWarningInFunction(dict)
<< "bad " << key <<" specifier " << enumName
<< " using " << getName(deflt) << endl;
} }
return deflt; return deflt;

View File

@ -25,10 +25,11 @@ Class
Foam::Enum Foam::Enum
Description Description
A Enum is a wrapper around a list of names/values that represent Enum is a wrapper around a list of names/values that represent particular
particular enumeration values. enumeration values.
SourceFiles SourceFiles
EnumI.H
Enum.C Enum.C
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -132,9 +133,17 @@ public:
// Query // Query
//- Test if there is an enumeration corresponding to the given name. //- Test if there is an enumeration corresponding to the given name.
inline bool found(const word& enumName) const;
//- Test if there is a name corresponding to the given enumeration.
inline bool found(const EnumType e) const;
//- Test if there is an enumeration corresponding to the given name.
// \deprecated Use found() - for compatibility with NamedEnum
inline bool hasEnum(const word& enumName) const; inline bool hasEnum(const word& enumName) const;
//- Test if there is a name corresponding to the given enumeration. //- Test if there is a name corresponding to the given enumeration.
// \deprecated Use found() - for compatibility with NamedEnum
inline bool hasName(const EnumType e) const; inline bool hasName(const EnumType e) const;
@ -142,7 +151,7 @@ public:
//- Lookup the key in the dictionary and return the corresponding //- Lookup the key in the dictionary and return the corresponding
//- enumeration element based on its name. //- enumeration element based on its name.
// Fatal if anything is incorrect. // FatalError if anything is incorrect.
EnumType lookup EnumType lookup
( (
const word& key, const word& key,
@ -152,7 +161,7 @@ public:
//- Find the key in the dictionary and return the corresponding //- Find the key in the dictionary and return the corresponding
//- enumeration element based on its name. //- enumeration element based on its name.
// Return the default value if the key was not found in the dictionary. // Return the default value if the key was not found in the dictionary.
// Fatal if the enumerated name was incorrect. // FatalError if the enumerated name was incorrect.
EnumType lookupOrDefault EnumType lookupOrDefault
( (
const word& key, const word& key,
@ -193,13 +202,23 @@ public:
// Member Operators // Member Operators
//- Return the enumeration corresponding to the given name //- Return the enumeration corresponding to the given name
// Fatal if the name cannot be found. // FatalError if the name is not found.
inline const EnumType operator[](const word& name) const; // Identical to getEnum()
inline EnumType operator[](const word& enumName) const;
//- Return the first name corresponding to the given enumeration. //- Return the first name corresponding to the given enumeration.
// Returns an empty word on failure. // Returns an empty word on failure.
// Identical to getName()
inline const word& operator[](const EnumType e) const; inline const word& operator[](const EnumType e) const;
//- Return the enumeration corresponding to the given name or deflt
//- if the name is not found.
inline EnumType operator()
(
const word& enumName,
const EnumType deflt
) const;
// IOstream operators // IOstream operators

View File

@ -53,6 +53,20 @@ inline const Foam::List<int>& Foam::Enum<EnumType>::values() const
} }
template<class EnumType>
inline bool Foam::Enum<EnumType>::found(const word& enumName) const
{
return getIndex(enumName) >= 0;
}
template<class EnumType>
inline bool Foam::Enum<EnumType>::found(const EnumType e) const
{
return getIndex(e) >= 0;
}
template<class EnumType> template<class EnumType>
inline bool Foam::Enum<EnumType>::hasEnum(const word& enumName) const inline bool Foam::Enum<EnumType>::hasEnum(const word& enumName) const
{ {
@ -81,12 +95,12 @@ inline Foam::Ostream& Foam::Enum<EnumType>::writeList
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class EnumType> template<class EnumType>
inline const EnumType Foam::Enum<EnumType>::operator[] inline EnumType Foam::Enum<EnumType>::operator[]
( (
const word& name const word& enumName
) const ) const
{ {
return getEnum(name); return getEnum(enumName);
} }
@ -100,4 +114,22 @@ inline const Foam::word& Foam::Enum<EnumType>::operator[]
} }
template<class EnumType>
inline EnumType Foam::Enum<EnumType>::operator()
(
const word& enumName,
const EnumType deflt
) const
{
const label idx = getIndex(enumName);
if (idx >= 0)
{
return EnumType(values_[idx]);
}
return deflt;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -176,7 +176,7 @@ bool Foam::UPstream::init(int& argc, char**& argv)
int bufSize = 0; int bufSize = 0;
const std::string str = Foam::getEnv("MPI_BUFFER_SIZE"); const std::string str = Foam::getEnv("MPI_BUFFER_SIZE");
if (str.empty() || !Foam::read(str.c_str(), bufSize) || bufSize <= 0) if (str.empty() || !Foam::read(str, bufSize) || bufSize <= 0)
{ {
bufSize = mpiBufferSize; bufSize = mpiBufferSize;
} }

View File

@ -377,7 +377,7 @@ bool Foam::fileFormats::FIREMeshReader::readGeometry(const scalar scaleFactor)
IOstream::streamFormat fmt = IOstream::ASCII; IOstream::streamFormat fmt = IOstream::ASCII;
const word ext = geometryFile_.ext(); const word ext = geometryFile_.ext();
bool supported = FIRECore::file3dExtensions.hasEnum(ext); bool supported = FIRECore::file3dExtensions.found(ext);
if (supported) if (supported)
{ {
FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext]; FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext];

View File

@ -278,7 +278,7 @@ bool Foam::fileFormats::FIREMeshWriter::write(const fileName& meshName) const
{ {
const word ext = baseName.ext(); const word ext = baseName.ext();
if (FIRECore::file3dExtensions.hasEnum(ext)) if (FIRECore::file3dExtensions.found(ext))
{ {
FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext]; FIRECore::fileExt3d fireFileType = FIRECore::file3dExtensions[ext];
if (fireFileType == FIRECore::fileExt3d::POLY_ASCII) if (fireFileType == FIRECore::fileExt3d::POLY_ASCII)

View File

@ -40,17 +40,51 @@ namespace Foam
Foam::word Foam::externalFileCoupler::lockName = "OpenFOAM"; Foam::word Foam::externalFileCoupler::lockName = "OpenFOAM";
// file-scope namespace Foam
// check file (must exist) for "status=done" content
static bool checkIsDone(const std::string& lck)
{ {
std::string content;
std::ifstream is(lck);
is >> content;
return (content.find("done") != std::string::npos); // file-scope
// Read file contents and return a stop control as follows:
// - contains "done" (should actually be status=done, but we are generous) :
// The master (OpenFOAM) has signalled that it is done. Report as <endTime>
//
// - action=writeNow, action=nextWrite action=noWriteNow :
// The slave has signalled that it is done and wants the master to exit with
// the specified type of action. Report as corresponding <action>.
//
// Anything else (empty file, no action=, etc) is reported as <unknown>.
//
static enum Time::stopAtControls getStopAction(const std::string& filename)
{
// Slurp entire input file (must exist) as a single string
std::string fileContent;
std::ifstream is(filename);
std::getline(is, fileContent, '\0');
if (fileContent.find("done") != std::string::npos)
{
return Time::stopAtControls::saEndTime;
}
const auto equals = fileContent.find('=');
if (equals != std::string::npos)
{
const word actionName(word::validate(fileContent.substr(equals+1)));
return
Time::stopAtControlNames
(
actionName,
Time::stopAtControls::saUnknown
);
}
return Time::stopAtControls::saUnknown;
} }
} // End namespace Foam
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -141,7 +175,8 @@ bool Foam::externalFileCoupler::readDict(const dictionary& dict)
} }
void Foam::externalFileCoupler::useMaster(const bool wait) const enum Foam::Time::stopAtControls
Foam::externalFileCoupler::useMaster(const bool wait) const
{ {
const bool wasInit = initialized(); const bool wasInit = initialized();
runState_ = MASTER; runState_ = MASTER;
@ -163,18 +198,20 @@ void Foam::externalFileCoupler::useMaster(const bool wait) const
std::ofstream os(lck); std::ofstream os(lck);
os << "status=openfoam\n"; os << "status=openfoam\n";
os.flush();
} }
} }
if (wait) if (wait)
{ {
waitForMaster(); return waitForMaster();
} }
return Time::stopAtControls::saUnknown;
} }
void Foam::externalFileCoupler::useSlave(const bool wait) const enum Foam::Time::stopAtControls
Foam::externalFileCoupler::useSlave(const bool wait) const
{ {
const bool wasInit = initialized(); const bool wasInit = initialized();
runState_ = SLAVE; runState_ = SLAVE;
@ -194,19 +231,23 @@ void Foam::externalFileCoupler::useSlave(const bool wait) const
if (wait) if (wait)
{ {
waitForSlave(); return waitForSlave();
} }
return Time::stopAtControls::saUnknown;
} }
bool Foam::externalFileCoupler::waitForMaster() const enum Foam::Time::stopAtControls
Foam::externalFileCoupler::waitForMaster() const
{ {
if (!initialized()) if (!initialized())
{ {
useMaster(); // was not initialized useMaster(); // was not initialized
} }
bool isDone = false; auto action = Time::stopAtControls::saUnknown;
if (Pstream::master()) if (Pstream::master())
{ {
const fileName lck(lockFile()); const fileName lck(lockFile());
@ -221,9 +262,11 @@ bool Foam::externalFileCoupler::waitForMaster() const
if (prevTime < modTime) if (prevTime < modTime)
{ {
prevTime = modTime; prevTime = modTime;
isDone = checkIsDone(lck);
if (isDone) if (Time::stopAtControls::saEndTime == getStopAction(lck))
{ {
// Found 'done' - slave should not wait for master
action = Time::stopAtControls::saEndTime;
break; break;
} }
} }
@ -231,21 +274,24 @@ bool Foam::externalFileCoupler::waitForMaster() const
} }
} }
// MPI barrier label intAction(action);
Pstream::scatter(isDone);
return !isDone; Pstream::scatter(intAction); // Also acts as MPI barrier
return Time::stopAtControls(intAction);
} }
bool Foam::externalFileCoupler::waitForSlave() const enum Foam::Time::stopAtControls
Foam::externalFileCoupler::waitForSlave() const
{ {
if (!initialized()) if (!initialized())
{ {
useSlave(); // was not initialized useSlave(); // was not initialized
} }
bool isDone = false; auto action = Time::stopAtControls::saUnknown;
if (Pstream::master()) if (Pstream::master())
{ {
const fileName lck(lockFile()); const fileName lck(lockFile());
@ -267,16 +313,16 @@ bool Foam::externalFileCoupler::waitForSlave() const
Log << type() << ": wait time = " << totalTime << endl; Log << type() << ": wait time = " << totalTime << endl;
} }
// But check for status=done content in the file action = getStopAction(lck);
isDone = checkIsDone(lck);
Log << type() << ": found lock file " << lck << endl; Log << type() << ": found lock file " << lck << endl;
} }
// MPI barrier label intAction(action);
Pstream::scatter(isDone);
return !isDone; Pstream::scatter(intAction); // Also acts as MPI barrier
return Time::stopAtControls(intAction);
} }
@ -308,12 +354,10 @@ void Foam::externalFileCoupler::shutdown() const
{ {
if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_)) if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_))
{ {
const fileName lck(lockFile());
Log << type() << ": lock file status=done" << endl; Log << type() << ": lock file status=done" << endl;
std::ofstream os(lck);
std::ofstream os(lockFile());
os << "status=done\n"; os << "status=done\n";
os.flush();
} }
runState_ = DONE; // Avoid re-triggering in destructor runState_ = DONE; // Avoid re-triggering in destructor

View File

@ -60,21 +60,26 @@ Description
A typical coupling loop would look like this (on the master-side): A typical coupling loop would look like this (on the master-side):
\verbatim \verbatim
initialize - master takes control initialize - master takes control
write data for slave writeDataMaster() - write data for slave
use slave, wait for slave useSlave()
cleanup old data from master waitForSlave()
read data from slave removeDataMaster() - cleanup old data from master [optional?]
use master readDataMaster() - read data from slave
useMaster()
\endverbatim \endverbatim
On the slave-side: On the slave-side:
\verbatim \verbatim
wait for master waitForMaster()
read data from master readDataSlave() - read data from master
write data for master writeDataSlave() - write data for master
use master useMaster()
\endverbatim \endverbatim
Note that since the waitForSlave() method not only waits for the lock file
to be reinstated but also does a simple check of its contents, it can
also serve to communicate some control from the slave to the master.
SourceFiles SourceFiles
externalFileCoupler.C externalFileCoupler.C
externalFileCouplerI.H externalFileCouplerI.H
@ -86,6 +91,7 @@ SourceFiles
#include "fileName.H" #include "fileName.H"
#include "dictionary.H" #include "dictionary.H"
#include "Time.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -207,24 +213,45 @@ public:
// Handshaking // Handshaking
//- Create lock file to indicate that OpenFOAM is in charge //- Create lock file to indicate that OpenFOAM is in charge
// Optionally wait for master to complete as well. // \param wait - wait for master to complete.
void useMaster(const bool wait=false) const; //
// \return Time::stopAtControls::saUnknown if not waiting, otherwise
// as per the waitForMaster() description.
enum Time::stopAtControls useMaster(const bool wait=false) const;
//- Remove lock file to indicate that the external program is in charge //- Remove lock file to indicate that the external program is in charge
// Optionally wait for slave to complete as well. // \param wait - wait for slave to complete.
void useSlave(const bool wait=false) const; //
// \return Time::stopAtControls::saUnknown if not waiting, otherwise
// as per the waitForSlave() description.
enum Time::stopAtControls useSlave(const bool wait=false) const;
//- Wait for master to complete. //- Wait for master to complete.
// This is when the lock file disappears, or exists but has // This is when the lock file disappears, or exists but has
// "status=done" content. // \c status=done content.
// \return False if lock file contains "status=done" //
bool waitForMaster() const; // \return Time::stopAtControls::saUnknown or if lock file
// contained \c status=done it returns
// Time::stopAtControls::saEndTime
enum Time::stopAtControls waitForMaster() const;
//- Wait for slave to complete. //- Wait for slave to complete.
// This is when the lock file appears. // This is when the lock file appears.
// \return False if lock file contains "status=done" //
bool waitForSlave() const; // When the lock file appears, it is checked for the following
// content which corresponds to particular return values:
// - \c status=done
// \return Foam::Time::saEndTime
// - \c action=writeNow
// \return Foam::Time::saWriteNow
// - \c action=nextWrite
// \return Foam::Time::saNextWrite
// - \c action=noNextWrite
// \return Foam::Time::saNoNextWrite
// - Anything else (empty file, no action= or status=, etc)
// \return Foam::Time::saUnknown
enum Time::stopAtControls waitForSlave() const;
// File creation, removal // File creation, removal
@ -251,13 +278,13 @@ public:
//- Remove data files written by slave (external program) //- Remove data files written by slave (external program)
virtual void removeDataSlave() const; virtual void removeDataSlave() const;
//- Generate status=done in lock (only when run-state = master)
//- Generate \c status=done in lock (only when run-state = master)
void shutdown() const; void shutdown() const;
//- Remove files written by OpenFOAM //- Remove files written by OpenFOAM
void removeDirectory() const; void removeDirectory() const;
}; };

View File

@ -3,7 +3,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-2017 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -24,7 +24,6 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "pimpleControl.H" #include "pimpleControl.H"
#include "Switch.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -42,12 +41,12 @@ void Foam::pimpleControl::read()
const dictionary& pimpleDict = dict(); const dictionary& pimpleDict = dict();
solveFlow_ = pimpleDict.lookupOrDefault<Switch>("solveFlow", true); solveFlow_ = pimpleDict.lookupOrDefault("solveFlow", true);
nCorrPIMPLE_ = pimpleDict.lookupOrDefault<label>("nOuterCorrectors", 1); nCorrPIMPLE_ = pimpleDict.lookupOrDefault<label>("nOuterCorrectors", 1);
nCorrPISO_ = pimpleDict.lookupOrDefault<label>("nCorrectors", 1); nCorrPISO_ = pimpleDict.lookupOrDefault<label>("nCorrectors", 1);
SIMPLErho_ = pimpleDict.lookupOrDefault<Switch>("SIMPLErho", false); SIMPLErho_ = pimpleDict.lookupOrDefault("SIMPLErho", false);
turbOnFinalIterOnly_ = turbOnFinalIterOnly_ =
pimpleDict.lookupOrDefault<Switch>("turbOnFinalIterOnly", true); pimpleDict.lookupOrDefault("turbOnFinalIterOnly", true);
} }
@ -60,41 +59,42 @@ bool Foam::pimpleControl::criteriaSatisfied()
} }
bool storeIni = this->storeInitialResiduals(); const bool storeIni = this->storeInitialResiduals();
bool achieved = true; bool achieved = true;
bool checked = false; // safety that some checks were indeed performed bool checked = false; // safety that some checks were indeed performed
const dictionary& solverDict = mesh_.solverPerformanceDict(); const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter) forAllConstIters(solverDict, iter)
{ {
const word& variableName = iter().keyword(); const entry& solverPerfDictEntry = *iter;
const label fieldi = applyToField(variableName);
const word& fieldName = solverPerfDictEntry.keyword();
const label fieldi = applyToField(fieldName);
if (fieldi != -1) if (fieldi != -1)
{ {
scalar residual = 0; Pair<scalar> residuals = maxResidual(solverPerfDictEntry);
const scalar firstResidual =
maxResidual(variableName, iter().stream(), residual);
checked = true; checked = true;
if (storeIni) scalar relative = 0.0;
{
residualControl_[fieldi].initialResidual = firstResidual;
}
const bool absCheck = residual < residualControl_[fieldi].absTol;
bool relCheck = false; bool relCheck = false;
scalar relative = 0.0; const bool absCheck =
if (!storeIni) (residuals.last() < residualControl_[fieldi].absTol);
if (storeIni)
{
residualControl_[fieldi].initialResidual = residuals.first();
}
else
{ {
const scalar iniRes = const scalar iniRes =
residualControl_[fieldi].initialResidual (residualControl_[fieldi].initialResidual + ROOTVSMALL);
+ ROOTVSMALL;
relative = residual/iniRes; relative = residuals.last() / iniRes;
relCheck = relative < residualControl_[fieldi].relTol; relCheck = (relative < residualControl_[fieldi].relTol);
} }
achieved = achieved && (absCheck || relCheck); achieved = achieved && (absCheck || relCheck);
@ -103,11 +103,11 @@ bool Foam::pimpleControl::criteriaSatisfied()
{ {
Info<< algorithmName_ << " loop:" << endl; Info<< algorithmName_ << " loop:" << endl;
Info<< " " << variableName Info<< " " << fieldName
<< " PIMPLE iter " << corr_ << " PIMPLE iter " << corr_
<< ": ini res = " << ": ini res = "
<< residualControl_[fieldi].initialResidual << residualControl_[fieldi].initialResidual
<< ", abs tol = " << residual << ", abs tol = " << residuals.last()
<< " (" << residualControl_[fieldi].absTol << ")" << " (" << residualControl_[fieldi].absTol << ")"
<< ", rel tol = " << relative << ", rel tol = " << relative
<< " (" << residualControl_[fieldi].relTol << ")" << " (" << residualControl_[fieldi].relTol << ")"
@ -135,50 +135,46 @@ Foam::pimpleControl::pimpleControl(fvMesh& mesh, const word& dictName)
{ {
read(); read();
Info<< nl
<< algorithmName_;
if (nCorrPIMPLE_ > 1) if (nCorrPIMPLE_ > 1)
{ {
Info<< nl;
if (residualControl_.empty()) if (residualControl_.empty())
{ {
Info<< algorithmName_ << ": no residual control data found. " Info<< ": no residual control data found. "
<< "Calculations will employ " << nCorrPIMPLE_ << "Calculations will employ " << nCorrPIMPLE_
<< " corrector loops" << nl << endl; << " corrector loops" << nl;
} }
else else
{ {
Info<< algorithmName_ << ": max iterations = " << nCorrPIMPLE_ Info<< ": max iterations = " << nCorrPIMPLE_ << nl;
<< endl;
forAll(residualControl_, i) for (const fieldData& ctrl : residualControl_)
{ {
Info<< " field " << residualControl_[i].name << token::TAB Info<< " field " << ctrl.name << token::TAB
<< ": relTol " << residualControl_[i].relTol << ": relTol " << ctrl.relTol
<< ", tolerance " << residualControl_[i].absTol << ", tolerance " << ctrl.absTol
<< nl; << nl;
} }
Info<< endl;
} }
} }
else else
{ {
Info<< nl << algorithmName_ << ": Operating solver in PISO mode" << nl Info<< ": Operating solver in PISO mode" << nl;
<< endl;
} }
Info<< endl;
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::pimpleControl::~pimpleControl()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::pimpleControl::loop() bool Foam::pimpleControl::loop()
{ {
read(); read();
corr_++; ++corr_;
if (debug) if (debug)
{ {
@ -187,7 +183,7 @@ bool Foam::pimpleControl::loop()
if (corr_ == nCorrPIMPLE_ + 1) if (corr_ == nCorrPIMPLE_ + 1)
{ {
if ((!residualControl_.empty()) && (nCorrPIMPLE_ != 1)) if (!residualControl_.empty() && (nCorrPIMPLE_ != 1))
{ {
Info<< algorithmName_ << ": not converged within " Info<< algorithmName_ << ": not converged within "
<< nCorrPIMPLE_ << " iterations" << endl; << nCorrPIMPLE_ << " iterations" << endl;

View File

@ -3,7 +3,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-2017 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -57,10 +57,10 @@ class pimpleControl
// Private member functions // Private member functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
pimpleControl(const pimpleControl&); pimpleControl(const pimpleControl&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const pimpleControl&); void operator=(const pimpleControl&) = delete;
protected: protected:
@ -116,7 +116,7 @@ public:
//- Destructor //- Destructor
virtual ~pimpleControl(); virtual ~pimpleControl() = default;
// Member Functions // Member Functions
@ -151,7 +151,7 @@ public:
//- Return true for first PIMPLE (outer) iteration //- Return true for first PIMPLE (outer) iteration
inline bool firstIter() const; inline bool firstIter() const;
//- Return true fore final PIMPLE (outer) iteration //- Return true for final PIMPLE (outer) iteration
inline bool finalIter() const; inline bool finalIter() const;
//- Return true for final inner iteration //- Return true for final inner iteration

View File

@ -51,7 +51,7 @@ inline bool Foam::pimpleControl::SIMPLErho() const
inline bool Foam::pimpleControl::correct() inline bool Foam::pimpleControl::correct()
{ {
corrPISO_++; ++corrPISO_;
if (debug) if (debug)
{ {
@ -62,11 +62,9 @@ inline bool Foam::pimpleControl::correct()
{ {
return true; return true;
} }
else
{
corrPISO_ = 0; corrPISO_ = 0;
return false; return false;
}
} }

View File

@ -3,7 +3,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-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -53,26 +53,29 @@ bool Foam::simpleControl::criteriaSatisfied()
bool checked = false; // safety that some checks were indeed performed bool checked = false; // safety that some checks were indeed performed
const dictionary& solverDict = mesh_.solverPerformanceDict(); const dictionary& solverDict = mesh_.solverPerformanceDict();
forAllConstIter(dictionary, solverDict, iter) forAllConstIters(solverDict, iter)
{ {
const word& variableName = iter().keyword(); const entry& solverPerfDictEntry = *iter;
const label fieldi = applyToField(variableName);
const word& fieldName = solverPerfDictEntry.keyword();
const label fieldi = applyToField(fieldName);
if (fieldi != -1) if (fieldi != -1)
{ {
scalar lastResidual = 0; Pair<scalar> residuals = maxResidual(solverPerfDictEntry);
const scalar residual =
maxResidual(variableName, iter().stream(), lastResidual);
checked = true; checked = true;
bool absCheck = residual < residualControl_[fieldi].absTol; const bool absCheck =
(residuals.first() < residualControl_[fieldi].absTol);
achieved = achieved && absCheck; achieved = achieved && absCheck;
if (debug) if (debug)
{ {
Info<< algorithmName_ << " solution statistics:" << endl; Info<< algorithmName_ << " solution statistics:" << endl;
Info<< " " << variableName << ": tolerance = " << residual Info<< " " << fieldName << ": tolerance = "
<< residuals.first()
<< " (" << residualControl_[fieldi].absTol << ")" << " (" << residualControl_[fieldi].absTol << ")"
<< endl; << endl;
} }
@ -85,64 +88,53 @@ bool Foam::simpleControl::criteriaSatisfied()
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::simpleControl::simpleControl(fvMesh& mesh) Foam::simpleControl::simpleControl(fvMesh& mesh, const word& dictName)
: :
solutionControl(mesh, "SIMPLE"), solutionControl(mesh, dictName),
initialised_(false) initialised_(false)
{ {
read(); read();
Info<< nl; Info<< nl
<< algorithmName_;
if (residualControl_.empty()) if (residualControl_.empty())
{ {
Info<< algorithmName_ << ": no convergence criteria found. " Info<< ": no convergence criteria found. Calculations will run for "
<< "Calculations will run for "
<< mesh_.time().endTime().value() - mesh_.time().startTime().value() << mesh_.time().endTime().value() - mesh_.time().startTime().value()
<< " steps." << nl << endl; << " steps." << nl;
} }
else else
{ {
Info<< algorithmName_ << ": convergence criteria" << nl; Info<< ": convergence criteria" << nl;
forAll(residualControl_, i) for (const fieldData& ctrl : residualControl_)
{ {
Info<< " field " << residualControl_[i].name << token::TAB Info<< " field " << ctrl.name << token::TAB
<< " tolerance " << residualControl_[i].absTol << " tolerance " << ctrl.absTol
<< nl; << nl;
} }
Info<< endl;
} }
Info<< endl;
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::simpleControl::~simpleControl()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::simpleControl::loop() bool Foam::simpleControl::loop()
{ {
read(); read();
Time& time = const_cast<Time&>(mesh_.time()); Time& runTime = const_cast<Time&>(mesh_.time());
if (initialised_) if (initialised_ && criteriaSatisfied())
{ {
if (criteriaSatisfied()) Info<< nl
{ << algorithmName_
Info<< nl << algorithmName_ << " solution converged in " << " solution converged in "
<< time.timeName() << " iterations" << nl << endl; << runTime.timeName() << " iterations" << nl << endl;
// Set to finalise calculation // Set to finalise calculation
time.writeAndEnd(); runTime.writeAndEnd();
}
else
{
storePrevIterFields();
}
} }
else else
{ {
@ -150,8 +142,7 @@ bool Foam::simpleControl::loop()
storePrevIterFields(); storePrevIterFields();
} }
return runTime.loop();
return time.loop();
} }

View File

@ -3,7 +3,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-2016 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -74,10 +74,10 @@ private:
// Private member functions // Private member functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
simpleControl(const simpleControl&); simpleControl(const simpleControl&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const simpleControl&); void operator=(const simpleControl&) = delete;
public: public:
@ -90,19 +90,19 @@ public:
// Constructors // Constructors
//- Construct from mesh //- Construct from mesh and the name of control sub-dictionary
simpleControl(fvMesh& mesh); simpleControl(fvMesh& mesh, const word& dictName="SIMPLE");
//- Destructor //- Destructor
virtual ~simpleControl(); virtual ~simpleControl() = default;
// Member Functions // Member Functions
// Solution control // Solution control
//- Loop loop //- SIMPLE loop
virtual bool loop(); virtual bool loop();
}; };

View File

@ -148,11 +148,7 @@ Foam::label Foam::solutionControl::applyToField
{ {
forAll(residualControl_, i) forAll(residualControl_, i)
{ {
if (useRegEx && residualControl_[i].name.match(fieldName)) if (residualControl_[i].name.match(fieldName, !useRegEx))
{
return i;
}
else if (residualControl_[i].name == fieldName)
{ {
return i; return i;
} }
@ -173,42 +169,68 @@ void Foam::solutionControl::storePrevIterFields() const
} }
template<class Type> Foam::Pair<Foam::scalar> Foam::solutionControl::maxResidual
void Foam::solutionControl::maxTypeResidual
( (
const word& fieldName, const entry& solverPerfDictEntry
ITstream& data,
scalar& firstRes,
scalar& lastRes
) const ) const
{ {
typedef GeometricField<Type, fvPatchField, volMesh> fieldType; return maxResidual(mesh_, solverPerfDictEntry);
if (mesh_.foundObject<fieldType>(fieldName))
{
const List<SolverPerformance<Type>> sp(data);
firstRes = cmptMax(sp.first().initialResidual());
lastRes = cmptMax(sp.last().initialResidual());
}
} }
Foam::scalar Foam::solutionControl::maxResidual // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class Type>
bool Foam::solutionControl::maxTypeResidual
( (
const word& fieldName, const fvMesh& fvmesh,
ITstream& data, const entry& solverPerfDictEntry,
scalar& lastRes Pair<scalar>& residuals
) const )
{ {
scalar firstRes = 0; typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
maxTypeResidual<scalar>(fieldName, data, firstRes, lastRes); const word& fieldName = solverPerfDictEntry.keyword();
maxTypeResidual<vector>(fieldName, data, firstRes, lastRes);
maxTypeResidual<sphericalTensor>(fieldName, data, firstRes, lastRes);
maxTypeResidual<symmTensor>(fieldName, data, firstRes, lastRes);
maxTypeResidual<tensor>(fieldName, data, firstRes, lastRes);
return firstRes; if (fvmesh.foundObject<fieldType>(fieldName))
{
const List<SolverPerformance<Type>> sp(solverPerfDictEntry.stream());
residuals.first() = cmptMax(sp.first().initialResidual());
residuals.last() = cmptMax(sp.last().initialResidual());
return true;
}
return false;
}
Foam::Pair<Foam::scalar> Foam::solutionControl::maxResidual
(
const fvMesh& fvmesh,
const entry& solverPerfDictEntry
)
{
Pair<scalar> residuals(0,0);
// Check with builtin short-circuit
const bool ok =
(
maxTypeResidual<scalar>(fvmesh, solverPerfDictEntry, residuals)
|| maxTypeResidual<vector>(fvmesh, solverPerfDictEntry, residuals)
|| maxTypeResidual<sphericalTensor>(fvmesh, solverPerfDictEntry, residuals)
|| maxTypeResidual<symmTensor>(fvmesh, solverPerfDictEntry, residuals)
|| maxTypeResidual<tensor>(fvmesh, solverPerfDictEntry, residuals)
);
if (!ok && solutionControl::debug)
{
Info<<"no residual for " << solverPerfDictEntry.keyword()
<< " on mesh " << fvmesh.name() << nl;
}
return residuals;
} }
@ -235,10 +257,4 @@ Foam::solutionControl::solutionControl(fvMesh& mesh, const word& algorithmName)
{} {}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::solutionControl::~solutionControl()
{}
// ************************************************************************* // // ************************************************************************* //

View File

@ -3,7 +3,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-2015 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation | \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -33,6 +33,7 @@ Description
#define solutionControl_H #define solutionControl_H
#include "fvMesh.H" #include "fvMesh.H"
#include "Pair.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -49,6 +50,7 @@ class solutionControl
{ {
public: public:
//- Simple convenient storage of field residuals
struct fieldData struct fieldData
{ {
wordRe name; wordRe name;
@ -58,6 +60,20 @@ public:
}; };
// Static Member Functions
//- Extract maximum residual for the solver performance entry,
//- provided the corresponding volume field is available on the mesh.
//
// \return initial residual as first member, the final residual
// as the second (or last) member
static Pair<scalar> maxResidual
(
const fvMesh& fvmesh,
const entry& dataDictEntry
);
protected: protected:
// Protected data // Protected data
@ -126,30 +142,34 @@ protected:
template<class Type> template<class Type>
void storePrevIter() const; void storePrevIter() const;
//- Initial and final residual of the specified field-name,
//- provided that the corresponding volume field is available
//- on the fvMesh.
//
// Populate residuals with initial residual as first member and
// the final residual as second (last) member.
template<class Type> template<class Type>
void maxTypeResidual static bool maxTypeResidual
( (
const word& fieldName, const fvMesh& fvmesh,
ITstream& data, const entry& solverPerfDictEntry,
scalar& firstRes, Pair<scalar>& residuals
scalar& lastRes );
) const;
scalar maxResidual //- Extract the maximum residual for the specified field
( //
const word& fieldName, // \return initial residual as first member, the final residual
ITstream& data, // as second (last) member
scalar& lastRes Pair<scalar> maxResidual(const entry& solverPerfDictEntry) const;
) const;
private: private:
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
solutionControl(const solutionControl&); solutionControl(const solutionControl&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const solutionControl&); void operator=(const solutionControl&) = delete;
public: public:
@ -168,7 +188,7 @@ public:
//- Destructor //- Destructor
virtual ~solutionControl(); virtual ~solutionControl() = default;
// Member Functions // Member Functions

View File

@ -81,7 +81,7 @@ inline bool Foam::solutionControl::frozenFlow() const
inline bool Foam::solutionControl::correctNonOrthogonal() inline bool Foam::solutionControl::correctNonOrthogonal()
{ {
corrNonOrtho_++; ++corrNonOrtho_;
if (debug) if (debug)
{ {
@ -93,11 +93,9 @@ inline bool Foam::solutionControl::correctNonOrthogonal()
{ {
return true; return true;
} }
else
{
corrNonOrtho_ = 0; corrNonOrtho_ = 0;
return false; return false;
}
} }

View File

@ -460,6 +460,42 @@ void Foam::functionObjects::externalCoupled::initCoupling()
} }
void Foam::functionObjects::externalCoupled::performCoupling()
{
// Ensure coupling has been initialised
initCoupling();
// Write data for external source
writeDataMaster();
// Signal external source to execute (by removing lock file)
// - Wait for slave to provide data
useSlave();
// Wait for response - and catch any abort information sent from slave
const auto action = waitForSlave();
// Remove old data files from OpenFOAM
removeDataMaster();
// Read data passed back from external source
readDataMaster();
// Signal external source to wait (by creating the lock file)
useMaster();
// Process any abort information sent from slave
if
(
action != time_.stopAt()
&& action != Time::stopAtControls::saUnknown
)
{
time_.stopAt(action);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::functionObjects::externalCoupled::externalCoupled Foam::functionObjects::externalCoupled::externalCoupled
@ -483,46 +519,16 @@ Foam::functionObjects::externalCoupled::externalCoupled
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::externalCoupled::~externalCoupled()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::externalCoupled::execute() bool Foam::functionObjects::externalCoupled::execute()
{ {
if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0) if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0)
{ {
// Initialise the coupling performCoupling();
initCoupling();
// Write data for external source
writeDataMaster();
// Signal external source to execute (by removing lock file)
// - Wait for slave to provide data
useSlave();
// Wait for response
waitForSlave();
// Remove old data files from OpenFOAM
removeDataMaster();
// Read data passed back from external source
readDataMaster();
// Signal external source to wait (by creating the lock file)
useMaster();
return true;
} }
else
{
return false; return false;
}
} }

View File

@ -282,6 +282,9 @@ private:
static void checkOrder(const wordList& regionNames); static void checkOrder(const wordList& regionNames);
//- Perform the coupling with necessary initialization etc.
void performCoupling();
//- Disallow default bitwise copy constructor //- Disallow default bitwise copy constructor
externalCoupled(const externalCoupled&) = delete; externalCoupled(const externalCoupled&) = delete;
@ -313,7 +316,7 @@ public:
//- Destructor //- Destructor
virtual ~externalCoupled(); virtual ~externalCoupled() = default;
// Member Functions // Member Functions

View File

@ -72,7 +72,7 @@ void Foam::functionObjects::mapFields::createInterpolation
); );
const fvMesh& mapRegion = mapRegionPtr_(); const fvMesh& mapRegion = mapRegionPtr_();
const word mapMethodName(dict.lookup("mapMethod")); const word mapMethodName(dict.lookup("mapMethod"));
if (!meshToMesh::interpolationMethodNames_.hasEnum(mapMethodName)) if (!meshToMesh::interpolationMethodNames_.found(mapMethodName))
{ {
FatalErrorInFunction FatalErrorInFunction
<< type() << " " << name() << ": unknown map method " << type() << " " << name() << ": unknown map method "

View File

@ -49,18 +49,6 @@ namespace functionObjects
} }
const Foam::Enum
<
Foam::Time::stopAtControls
>
Foam::functionObjects::abort::actionNames_
{
{ Time::stopAtControls::saNoWriteNow, "noWriteNow" },
{ Time::stopAtControls::saWriteNow, "writeNow" },
{ Time::stopAtControls::saNextWrite, "nextWrite" },
};
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
// file-scope // file-scope
@ -126,12 +114,6 @@ Foam::functionObjects::abort::abort
} }
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::abort::~abort()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::abort::read(const dictionary& dict) bool Foam::functionObjects::abort::read(const dictionary& dict)
@ -145,7 +127,7 @@ bool Foam::functionObjects::abort::read(const dictionary& dict)
const auto oldAction = action_; const auto oldAction = action_;
action_ = actionNames_.lookupOrDefault action_ = Time::stopAtControlNames.lookupOrDefault
( (
"action", "action",
dict, dict,

View File

@ -30,6 +30,7 @@ Group
Description Description
Watches for presence of the named file in the $FOAM_CASE directory Watches for presence of the named file in the $FOAM_CASE directory
and aborts the calculation if it is present. and aborts the calculation if it is present.
The presence of the abort file is only checked on the master process. The presence of the abort file is only checked on the master process.
Currently the following action types are supported: Currently the following action types are supported:
@ -73,9 +74,6 @@ class abort
{ {
// Private data // Private data
//- A subset of Time stopAtControls
static const Enum<Time::stopAtControls> actionNames_;
//- Reference to the Time //- Reference to the Time
const Time& time_; const Time& time_;
@ -116,7 +114,7 @@ public:
//- Destructor //- Destructor
virtual ~abort(); virtual ~abort() = default;
// Member Functions // Member Functions

View File

@ -187,6 +187,8 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
return; return;
} }
enum Time::stopAtControls action = Time::stopAtControls::saUnknown;
const bool masterPatch = (movement().ownerId() == this->patch().index()); const bool masterPatch = (movement().ownerId() == this->patch().index());
if (masterPatch) if (masterPatch)
{ {
@ -250,13 +252,14 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
{ {
movement().writeData(forces, moments); movement().writeData(forces, moments);
// signal external source to execute // Signal external source to execute
movement().coupler().useSlave(); movement().coupler().useSlave();
} }
} }
// Wait for slave to provide data - includes MPI barrier // Wait for slave to provide data (includes MPI barrier)
movement().coupler().waitForSlave(); // and catch any abort information sent from slave
action = movement().coupler().waitForSlave();
// Read data passed back from external source - includes MPI barrier // Read data passed back from external source - includes MPI barrier
const_cast<lumpedPointMovement&>(movement()).readState(); const_cast<lumpedPointMovement&>(movement()).readState();
@ -271,6 +274,16 @@ void Foam::lumpedPointDisplacementPointPatchVectorField::updateCoeffs()
this->operator==(tdisp); this->operator==(tdisp);
fixedValuePointPatchField<vector>::updateCoeffs(); fixedValuePointPatchField<vector>::updateCoeffs();
// Process any abort information sent from slave
if
(
action != this->db().time().stopAt()
&& action != Time::stopAtControls::saUnknown
)
{
this->db().time().stopAt(action);
}
} }