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
(
matchName != "perfect"
&& !slidingInterface::typeOfMatchNames.hasEnum(matchName)
&& !slidingInterface::typeOfMatchNames.found(matchName)
)
{
Info<< "Error: unknown match type - " << matchName

View File

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

View File

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

View File

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

View File

@ -112,10 +112,10 @@ class subCycle
// Private Member Functions
//- Disallow default bitwise copy construct
subCycle(const subCycle<GeometricField>&);
subCycle(const subCycle<GeometricField>&) = delete;
//- Disallow default bitwise assignment
void operator=(const subCycle<GeometricField>&);
void operator=(const subCycle<GeometricField>&) = delete;
public:
@ -123,10 +123,10 @@ public:
// Constructors
//- Construct field and number of sub-cycles
subCycle(GeometricField& gf, const label nSubCycles)
subCycle(GeometricField& gf, const label nCycles)
:
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
this->updateTimeIndex();

View File

@ -44,12 +44,14 @@ const Foam::Enum
<
Foam::Time::stopAtControls
>
Foam::Time::stopAtControlNames_
Foam::Time::stopAtControlNames
{
{ stopAtControls::saEndTime, "endTime" },
{ stopAtControls::saNoWriteNow, "noWriteNow" },
{ stopAtControls::saWriteNow, "writeNow" },
{ 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::writeControlNames_
Foam::Time::writeControlNames
{
{ writeControls::wcTimeStep, "timeStep" },
{ writeControls::wcRunTime, "runTime" },
@ -433,8 +435,8 @@ Foam::Time::Time
writeControl_(wcTimeStep),
writeInterval_(GREAT),
purgeWrite_(0),
subCycling_(0),
writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this),
@ -502,8 +504,8 @@ Foam::Time::Time
writeControl_(wcTimeStep),
writeInterval_(GREAT),
purgeWrite_(0),
subCycling_(0),
writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this),
@ -581,8 +583,8 @@ Foam::Time::Time
writeControl_(wcTimeStep),
writeInterval_(GREAT),
purgeWrite_(0),
subCycling_(0),
writeOnce_(false),
subCycling_(false),
sigWriteNow_(true, *this),
sigStopAtWriteNow_(true, *this),
@ -651,9 +653,8 @@ Foam::Time::Time
writeControl_(wcTimeStep),
writeInterval_(GREAT),
purgeWrite_(0),
subCycling_(0),
writeOnce_(false),
subCycling_(false),
writeFormat_(IOstream::ASCII),
writeVersion_(IOstream::currentVersion),
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
{
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);
stopAt_ = sa;
if (stopCtrl == stopAtControls::saUnknown)
{
return false;
}
// adjust endTime
if (sa == saEndTime)
const bool changed = (stopAt_ != stopCtrl);
stopAt_ = stopCtrl;
endTime_ = GREAT;
// Adjust endTime
if (stopCtrl == stopAtControls::saEndTime)
{
controlDict_.lookup("endTime") >> endTime_;
}
else
{
endTime_ = GREAT;
}
return changed;
}
@ -1018,26 +1028,41 @@ void Foam::Time::setDeltaT(const scalar deltaT, const bool adjust)
Foam::TimeState Foam::Time::subCycle(const label nSubCycles)
{
subCycling_ = true;
prevTimeState_.reset(new TimeState(*this));
prevTimeState_.set(new TimeState(*this)); // Fatal if already set
setTime(*this - deltaT(), (timeIndex() - 1)*nSubCycles);
deltaT_ /= nSubCycles;
deltaT0_ /= nSubCycles;
deltaTSave_ = deltaT0_;
subCycling_ = nSubCycles;
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()
{
if (subCycling_)
{
subCycling_ = false;
TimeState::operator=(prevTimeState());
prevTimeState_.clear();
}
subCycling_ = 0;
}
@ -1113,7 +1138,7 @@ Foam::Time& Foam::Time::operator++()
case wcRunTime:
case wcAdjustableRunTime:
{
label writeIndex = label
const label writeIndex = label
(
((value() - startTime_) + 0.5*deltaT_)
/ writeInterval_
@ -1129,7 +1154,7 @@ Foam::Time& Foam::Time::operator++()
case wcCpuTime:
{
label writeIndex = label
const label writeIndex = label
(
returnReduce(elapsedCpuTime(), maxOp<double>())
/ writeInterval_
@ -1144,7 +1169,7 @@ Foam::Time& Foam::Time::operator++()
case wcClockTime:
{
label writeIndex = label
const label writeIndex = label
(
returnReduce(label(elapsedClockTime()), maxOp<label>())
/ writeInterval_
@ -1201,7 +1226,7 @@ Foam::Time& Foam::Time::operator++()
// reinterpretation of the word
if
(
readScalar(dimensionedScalar::name().c_str(), timeNameValue)
readScalar(dimensionedScalar::name(), timeNameValue)
&& (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
)
{
@ -1209,7 +1234,7 @@ Foam::Time& Foam::Time::operator++()
while
(
precision_ < maxPrecision_
&& readScalar(dimensionedScalar::name().c_str(), timeNameValue)
&& readScalar(dimensionedScalar::name(), timeNameValue)
&& (mag(timeNameValue - oldTimeValue - userDeltaT) > timeTol)
)
{
@ -1242,7 +1267,7 @@ Foam::Time& Foam::Time::operator++()
scalar oldTimeNameValue = -VGREAT;
if
(
readScalar(oldTimeName.c_str(), oldTimeNameValue)
readScalar(oldTimeName, oldTimeNameValue)
&& (
sign(timeNameValue - oldTimeNameValue)
!= sign(deltaT_)

View File

@ -75,6 +75,47 @@ class Time
public objectRegistry,
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
//- Profiling trigger for time-loop (for run, loop)
@ -88,36 +129,6 @@ class Time
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 data
@ -126,34 +137,31 @@ protected:
scalar startTime_;
mutable scalar endTime_;
static const Enum<stopAtControls> stopAtControlNames_;
mutable stopAtControls stopAt_;
static const Enum<writeControls> writeControlNames_;
writeControls writeControl_;
scalar writeInterval_;
label purgeWrite_;
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
bool writeOnce_;
//- Is the time currently being sub-cycled?
bool subCycling_;
//- If time is being sub-cycled this is the previous TimeState
autoPtr<TimeState> prevTimeState_;
//- Signal handler for one-shot writing upon signal
sigWriteNow sigWriteNow_;
// Signal handlers for writing
//- Enable one-shot writing upon signal
sigWriteNow sigWriteNow_;
//- Enable write and clean exit upon signal
sigStopAtWriteNow sigStopAtWriteNow_;
//- Signal handler for write and clean exit upon signal
sigStopAtWriteNow sigStopAtWriteNow_;
//- Time directory name format
@ -165,6 +173,7 @@ protected:
//- Maximum time directory name precision
static const int maxPrecision_;
//- Adjust the time step so that writing occurs at the specified time
void adjustDeltaT();
@ -179,7 +188,7 @@ protected:
virtual void readDict();
//- Find IOobject in the objectPath
static bool exists(IOobject&);
static bool exists(IOobject& io);
private:
@ -423,6 +432,9 @@ public:
//- Return end time
virtual dimensionedScalar endTime() const;
//- Return the stop control information
virtual stopAtControls stopAt() const;
//- Return the list of function objects
const functionObjectList& functionObjects() const
{
@ -441,8 +453,12 @@ public:
return libs_;
}
//- Return true if time currently being sub-cycled, otherwise false
bool subCycling() const
//- Zero (tests as false) if time is not being sub-cycled,
//- 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_;
}
@ -498,10 +514,13 @@ public:
// Edit
//- Adjust the current stopAtControl. Note that this value
// only persists until the next time the dictionary is read.
// Return true if the stopAtControl changed.
virtual bool stopAt(const stopAtControls sa) const;
//- Adjust the current stopAtControl.
// \param stopCtrl the new stop control, whereby
// stopAtControls::saUnknown is treated as a no-op.
// \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
virtual void setTime(const Time& t);
@ -542,6 +561,13 @@ public:
//- Set time to sub-cycle for the given number of steps
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
virtual void endSubCycle();

View File

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

View File

@ -27,13 +27,14 @@ License
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::subCycleTime::subCycleTime(Time& t, const label nSubCycles)
Foam::subCycleTime::subCycleTime(Time& runTime, const label nCycles)
:
time_(t),
nSubCycles_(nSubCycles),
subCycleIndex_(0)
time_(runTime),
index_(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 * * * * * * * * * * * * * //
bool Foam::subCycleTime::status() const
{
return (index_ <= total_);
}
bool Foam::subCycleTime::end() const
{
return subCycleIndex_ > nSubCycles_;
return (index_ > total_); // or !(status())
}
void Foam::subCycleTime::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++()
{
time_++;
subCycleIndex_++;
++time_;
++index_;
// Register index change with Time, in case someone wants this information
time_.subCycleIndex(index_);
return *this;
}

View File

@ -50,17 +50,22 @@ class subCycleTime
{
// Private data
//- Reference to the underlying time
Time& time_;
label nSubCycles_;
label subCycleIndex_;
//- Current index in the sub-cycle
label index_;
//- Total number of cycles in the sub-cycle
label total_;
public:
// Constructors
//- Construct from original time and number of sub-cycles
subCycleTime(Time&, const label nSubCycles);
//- Construct referencing the original time and number of sub-cycles
subCycleTime(Time& runTime, const label nCycle);
//- Destructor
@ -69,23 +74,36 @@ public:
// 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
bool end() const;
//- End the sub-cycling and reset the time-state
void endSubCycle();
//- Return the total number of sub-cycles
label nSubCycles() const
{
return nSubCycles_;
}
//- Return the current sub-cycle index
label index() const
{
return subCycleIndex_;
}
//- True if looping is active, increments the index.
// Example usage,
// \code
// while (subcycle.loop())
// {
// solve;
// }
// \endcode
bool loop();
// Member operators
@ -93,7 +111,7 @@ public:
//- Prefix increment
subCycleTime& operator++();
//- Postfix increment
//- Postfix increment, this is identical to the prefix increment
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);
// Behaviour like Enum lookupOrFailsafe()
if (selectableNames.hasEnum(modeName))
if (selectableNames.found(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
forAll(dirEntries, i)
{
//IStringStream timeStream(dirEntries[i]);
//token timeToken(timeStream);
//if (timeToken.isNumber() && timeStream.eof())
scalar timeValue;
if (readScalar(dirEntries[i].c_str(), timeValue))
if (readScalar(dirEntries[i], timeValue))
{
Times[nTimes].value() = timeValue;
Times[nTimes].name() = dirEntries[i];

View File

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

View File

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

View File

@ -87,10 +87,8 @@ const Foam::word& Foam::Enum<EnumType>::getName(const EnumType e) const
{
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 label idx = getIndex(enumName);
if (idx < 0)
{
IOWarningInFunction(dict)
<< "bad " << key <<" specifier " << enumName
<< " using " << getName(deflt) << endl;
}
else
if (idx >= 0)
{
return EnumType(values_[idx]);
}
IOWarningInFunction(dict)
<< "bad " << key <<" specifier " << enumName
<< " using " << getName(deflt) << endl;
}
return deflt;

View File

@ -25,10 +25,11 @@ Class
Foam::Enum
Description
A Enum is a wrapper around a list of names/values that represent
particular enumeration values.
Enum is a wrapper around a list of names/values that represent particular
enumeration values.
SourceFiles
EnumI.H
Enum.C
\*---------------------------------------------------------------------------*/
@ -111,7 +112,7 @@ public:
// Member Functions
// Access
// Access
//- The number of lookup names for the enumeration
inline label size() const;
@ -129,20 +130,28 @@ public:
inline const List<int>& values() const;
// Query
// Query
//- 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;
//- 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;
// Lookup
// Lookup
//- Lookup the key in the dictionary and return the corresponding
//- enumeration element based on its name.
// Fatal if anything is incorrect.
// FatalError if anything is incorrect.
EnumType lookup
(
const word& key,
@ -152,7 +161,7 @@ public:
//- Find the key in the dictionary and return the corresponding
//- enumeration element based on its name.
// 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
(
const word& key,
@ -173,7 +182,7 @@ public:
) const;
// IO
// IO
//- Read a word from Istream and return the corresponding enumeration
EnumType read(Istream& is) const;
@ -193,13 +202,23 @@ public:
// Member Operators
//- Return the enumeration corresponding to the given name
// Fatal if the name cannot be found.
inline const EnumType operator[](const word& name) const;
// FatalError if the name is not found.
// Identical to getEnum()
inline EnumType operator[](const word& enumName) const;
//- Return the first name corresponding to the given enumeration.
// Returns an empty word on failure.
// Identical to getName()
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

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>
inline bool Foam::Enum<EnumType>::hasEnum(const word& enumName) const
{
@ -81,12 +95,12 @@ inline Foam::Ostream& Foam::Enum<EnumType>::writeList
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class EnumType>
inline const EnumType Foam::Enum<EnumType>::operator[]
inline EnumType Foam::Enum<EnumType>::operator[]
(
const word& name
const word& enumName
) 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;
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;
}

View File

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

View File

@ -40,17 +40,51 @@ namespace Foam
Foam::word Foam::externalFileCoupler::lockName = "OpenFOAM";
// file-scope
// check file (must exist) for "status=done" content
static bool checkIsDone(const std::string& lck)
namespace Foam
{
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 * * * * * * * * * * * * * * //
@ -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();
runState_ = MASTER;
@ -163,18 +198,20 @@ void Foam::externalFileCoupler::useMaster(const bool wait) const
std::ofstream os(lck);
os << "status=openfoam\n";
os.flush();
}
}
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();
runState_ = SLAVE;
@ -194,19 +231,23 @@ void Foam::externalFileCoupler::useSlave(const bool wait) const
if (wait)
{
waitForSlave();
return waitForSlave();
}
return Time::stopAtControls::saUnknown;
}
bool Foam::externalFileCoupler::waitForMaster() const
enum Foam::Time::stopAtControls
Foam::externalFileCoupler::waitForMaster() const
{
if (!initialized())
{
useMaster(); // was not initialized
}
bool isDone = false;
auto action = Time::stopAtControls::saUnknown;
if (Pstream::master())
{
const fileName lck(lockFile());
@ -221,9 +262,11 @@ bool Foam::externalFileCoupler::waitForMaster() const
if (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;
}
}
@ -231,21 +274,24 @@ bool Foam::externalFileCoupler::waitForMaster() const
}
}
// MPI barrier
Pstream::scatter(isDone);
label intAction(action);
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())
{
useSlave(); // was not initialized
}
bool isDone = false;
auto action = Time::stopAtControls::saUnknown;
if (Pstream::master())
{
const fileName lck(lockFile());
@ -267,16 +313,16 @@ bool Foam::externalFileCoupler::waitForSlave() const
Log << type() << ": wait time = " << totalTime << endl;
}
// But check for status=done content in the file
isDone = checkIsDone(lck);
action = getStopAction(lck);
Log << type() << ": found lock file " << lck << endl;
}
// MPI barrier
Pstream::scatter(isDone);
label intAction(action);
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_))
{
const fileName lck(lockFile());
Log << type() << ": lock file status=done" << endl;
std::ofstream os(lck);
std::ofstream os(lockFile());
os << "status=done\n";
os.flush();
}
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):
\verbatim
initialize - master takes control
write data for slave
use slave, wait for slave
cleanup old data from master
read data from slave
use master
writeDataMaster() - write data for slave
useSlave()
waitForSlave()
removeDataMaster() - cleanup old data from master [optional?]
readDataMaster() - read data from slave
useMaster()
\endverbatim
On the slave-side:
\verbatim
wait for master
read data from master
write data for master
use master
waitForMaster()
readDataSlave() - read data from master
writeDataSlave() - write data for master
useMaster()
\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
externalFileCoupler.C
externalFileCouplerI.H
@ -86,6 +91,7 @@ SourceFiles
#include "fileName.H"
#include "dictionary.H"
#include "Time.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -177,7 +183,7 @@ public:
// Member Functions
// Initialization
// Initialization
//- True if state has been initialized
inline bool initialized() const;
@ -186,7 +192,7 @@ public:
inline bool slaveFirst() const;
// File locations
// File locations
//- Return the file path to the base communications directory
inline const fileName& commDirectory() const;
@ -198,36 +204,57 @@ public:
inline fileName lockFile() const;
// Settings
// Settings
//- Read communication settings from dictionary
bool readDict(const dictionary& dict);
// Handshaking
// Handshaking
//- Create lock file to indicate that OpenFOAM is in charge
// Optionally wait for master to complete as well.
void useMaster(const bool wait=false) const;
// \param wait - wait for master to complete.
//
// \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
// Optionally wait for slave to complete as well.
void useSlave(const bool wait=false) const;
// \param wait - wait for slave to complete.
//
// \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.
// This is when the lock file disappears, or exists but has
// "status=done" content.
// \return False if lock file contains "status=done"
bool waitForMaster() const;
// \c status=done content.
//
// \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.
// 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
//- Read data files on master (OpenFOAM).
// These data files are normally created by the slave.
@ -251,13 +278,13 @@ public:
//- Remove data files written by slave (external program)
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;
//- Remove files written by OpenFOAM
void removeDirectory() const;
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -148,11 +148,7 @@ Foam::label Foam::solutionControl::applyToField
{
forAll(residualControl_, i)
{
if (useRegEx && residualControl_[i].name.match(fieldName))
{
return i;
}
else if (residualControl_[i].name == fieldName)
if (residualControl_[i].name.match(fieldName, !useRegEx))
{
return i;
}
@ -173,42 +169,68 @@ void Foam::solutionControl::storePrevIterFields() const
}
template<class Type>
void Foam::solutionControl::maxTypeResidual
Foam::Pair<Foam::scalar> Foam::solutionControl::maxResidual
(
const word& fieldName,
ITstream& data,
scalar& firstRes,
scalar& lastRes
const entry& solverPerfDictEntry
) const
{
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
if (mesh_.foundObject<fieldType>(fieldName))
{
const List<SolverPerformance<Type>> sp(data);
firstRes = cmptMax(sp.first().initialResidual());
lastRes = cmptMax(sp.last().initialResidual());
}
return maxResidual(mesh_, solverPerfDictEntry);
}
Foam::scalar Foam::solutionControl::maxResidual
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class Type>
bool Foam::solutionControl::maxTypeResidual
(
const word& fieldName,
ITstream& data,
scalar& lastRes
) const
const fvMesh& fvmesh,
const entry& solverPerfDictEntry,
Pair<scalar>& residuals
)
{
scalar firstRes = 0;
typedef GeometricField<Type, fvPatchField, volMesh> fieldType;
maxTypeResidual<scalar>(fieldName, data, firstRes, lastRes);
maxTypeResidual<vector>(fieldName, data, firstRes, lastRes);
maxTypeResidual<sphericalTensor>(fieldName, data, firstRes, lastRes);
maxTypeResidual<symmTensor>(fieldName, data, firstRes, lastRes);
maxTypeResidual<tensor>(fieldName, data, firstRes, lastRes);
const word& fieldName = solverPerfDictEntry.keyword();
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
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,6 +33,7 @@ Description
#define solutionControl_H
#include "fvMesh.H"
#include "Pair.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -49,6 +50,7 @@ class solutionControl
{
public:
//- Simple convenient storage of field residuals
struct fieldData
{
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 data
@ -126,30 +142,34 @@ protected:
template<class Type>
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>
void maxTypeResidual
static bool maxTypeResidual
(
const word& fieldName,
ITstream& data,
scalar& firstRes,
scalar& lastRes
) const;
const fvMesh& fvmesh,
const entry& solverPerfDictEntry,
Pair<scalar>& residuals
);
scalar maxResidual
(
const word& fieldName,
ITstream& data,
scalar& lastRes
) const;
//- Extract the maximum residual for the specified field
//
// \return initial residual as first member, the final residual
// as second (last) member
Pair<scalar> maxResidual(const entry& solverPerfDictEntry) const;
private:
//- Disallow default bitwise copy construct
solutionControl(const solutionControl&);
solutionControl(const solutionControl&) = delete;
//- Disallow default bitwise assignment
void operator=(const solutionControl&);
void operator=(const solutionControl&) = delete;
public:
@ -168,7 +188,7 @@ public:
//- Destructor
virtual ~solutionControl();
virtual ~solutionControl() = default;
// Member Functions

View File

@ -81,7 +81,7 @@ inline bool Foam::solutionControl::frozenFlow() const
inline bool Foam::solutionControl::correctNonOrthogonal()
{
corrNonOrtho_++;
++corrNonOrtho_;
if (debug)
{
@ -93,11 +93,9 @@ inline bool Foam::solutionControl::correctNonOrthogonal()
{
return true;
}
else
{
corrNonOrtho_ = 0;
return false;
}
corrNonOrtho_ = 0;
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 * * * * * * * * * * * * * * //
Foam::functionObjects::externalCoupled::externalCoupled
@ -483,46 +519,16 @@ Foam::functionObjects::externalCoupled::externalCoupled
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::externalCoupled::~externalCoupled()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::externalCoupled::execute()
{
if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0)
{
// Initialise the coupling
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;
performCoupling();
}
return false;
}

View File

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

View File

@ -72,7 +72,7 @@ void Foam::functionObjects::mapFields::createInterpolation
);
const fvMesh& mapRegion = mapRegionPtr_();
const word mapMethodName(dict.lookup("mapMethod"));
if (!meshToMesh::interpolationMethodNames_.hasEnum(mapMethodName))
if (!meshToMesh::interpolationMethodNames_.found(mapMethodName))
{
FatalErrorInFunction
<< 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 * * * * * * * * * * * * * * //
// file-scope
@ -126,12 +114,6 @@ Foam::functionObjects::abort::abort
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::functionObjects::abort::~abort()
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::functionObjects::abort::read(const dictionary& dict)
@ -145,7 +127,7 @@ bool Foam::functionObjects::abort::read(const dictionary& dict)
const auto oldAction = action_;
action_ = actionNames_.lookupOrDefault
action_ = Time::stopAtControlNames.lookupOrDefault
(
"action",
dict,

View File

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

View File

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