mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Merge branch 'feature-externalFileCoupler' into 'develop'
Feature external file coupler See merge request !126
This commit is contained in:
@ -50,20 +50,6 @@ namespace functionObjects
|
||||
}
|
||||
}
|
||||
|
||||
const Foam::Enum
|
||||
<
|
||||
Foam::functionObjects::externalCoupled::stateEnd
|
||||
>
|
||||
Foam::functionObjects::externalCoupled::stateEndNames_
|
||||
{
|
||||
{ stateEnd::REMOVE, "remove" },
|
||||
{ stateEnd::DONE, "done" }
|
||||
// 'IGNORE' is internal use only and thus without a name
|
||||
};
|
||||
|
||||
|
||||
Foam::word Foam::functionObjects::externalCoupled::lockName = "OpenFOAM";
|
||||
|
||||
Foam::string Foam::functionObjects::externalCoupled::patchKey = "// Patch:";
|
||||
|
||||
|
||||
@ -99,15 +85,6 @@ static void writeList(Ostream& os, const string& header, const UList<T>& L)
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::fileName Foam::functionObjects::externalCoupled::baseDir() const
|
||||
{
|
||||
fileName result(commsDir_);
|
||||
result.clean();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::functionObjects::externalCoupled::groupDir
|
||||
(
|
||||
const fileName& commsDir,
|
||||
@ -127,171 +104,6 @@ Foam::fileName Foam::functionObjects::externalCoupled::groupDir
|
||||
}
|
||||
|
||||
|
||||
Foam::fileName Foam::functionObjects::externalCoupled::lockFile() const
|
||||
{
|
||||
return fileName(baseDir()/(lockName + ".lock"));
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::useMaster() const
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
const fileName lck(lockFile());
|
||||
|
||||
// Only create lock file if it doesn't already exist
|
||||
if (!Foam::isFile(lck))
|
||||
{
|
||||
Log << type() << ": creating lock file" << endl;
|
||||
|
||||
OFstream os(lck);
|
||||
os << "status=openfoam\n";
|
||||
os.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::useSlave() const
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
Log << type() << ": removing lock file" << endl;
|
||||
|
||||
Foam::rm(lockFile());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::cleanup() const
|
||||
{
|
||||
if (Pstream::master())
|
||||
{
|
||||
const fileName lck(lockFile());
|
||||
switch (stateEnd_)
|
||||
{
|
||||
case REMOVE:
|
||||
{
|
||||
Log << type() << ": removing lock file" << endl;
|
||||
Foam::rm(lck);
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
{
|
||||
Log << type() << ": lock file status=done" << endl;
|
||||
OFstream os(lck);
|
||||
os << "status=done\n";
|
||||
os.flush();
|
||||
break;
|
||||
}
|
||||
case IGNORE:
|
||||
break;
|
||||
}
|
||||
|
||||
stateEnd_ = IGNORE; // Avoid re-triggering in destructor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::removeDataSlave() const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log << type() << ": removing data files written by slave" << nl;
|
||||
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
forAll(groups, i)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
|
||||
forAll(groupReadFields_[groupi], fieldi)
|
||||
{
|
||||
const word& fieldName = groupReadFields_[groupi][fieldi];
|
||||
rm
|
||||
(
|
||||
groupDir(commsDir_, compName, groupName)
|
||||
/ fieldName + ".in"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::removeDataMaster() const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log << type() << ": removing data files written by master" << nl;
|
||||
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
forAll(groups, i)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
|
||||
forAll(groupReadFields_[groupi], fieldi)
|
||||
{
|
||||
const word& fieldName = groupReadFields_[groupi][fieldi];
|
||||
rm
|
||||
(
|
||||
groupDir(commsDir_, compName, groupName)
|
||||
/ fieldName + ".out"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::waitForSlave() const
|
||||
{
|
||||
bool waiting = true;
|
||||
if (Pstream::master())
|
||||
{
|
||||
const fileName lck(lockFile());
|
||||
unsigned totalTime = 0;
|
||||
|
||||
Log << type() << ": beginning wait for lock file " << lck << nl;
|
||||
|
||||
while ((waiting = !Foam::isFile(lck)) == true)
|
||||
{
|
||||
sleep(waitInterval_);
|
||||
totalTime += waitInterval_;
|
||||
|
||||
if (timeOut_ && totalTime > timeOut_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Wait time exceeded timeout of " << timeOut_
|
||||
<< " s" << abort(FatalError);
|
||||
}
|
||||
|
||||
Log << type() << ": wait time = " << totalTime << endl;
|
||||
}
|
||||
|
||||
Log << type() << ": found lock file " << lck << endl;
|
||||
}
|
||||
|
||||
// MPI barrier
|
||||
Pstream::scatter(waiting);
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::readColumns
|
||||
(
|
||||
const label nRows,
|
||||
@ -465,21 +277,19 @@ void Foam::functionObjects::externalCoupled::writeGeometry
|
||||
|
||||
labelList pointToGlobal;
|
||||
labelList uniquePointIDs;
|
||||
forAll(meshes, meshi)
|
||||
for (const fvMesh& mesh : meshes)
|
||||
{
|
||||
const fvMesh& mesh = meshes[meshi];
|
||||
|
||||
const labelList patchIDs
|
||||
(
|
||||
mesh.boundaryMesh().patchSet
|
||||
(
|
||||
List<wordRe>(1, groupName)
|
||||
List<wordRe>{groupName}
|
||||
).sortedToc()
|
||||
);
|
||||
|
||||
forAll(patchIDs, i)
|
||||
for (const label patchi : patchIDs)
|
||||
{
|
||||
const polyPatch& p = mesh.boundaryMesh()[patchIDs[i]];
|
||||
const polyPatch& p = mesh.boundaryMesh()[patchi];
|
||||
|
||||
mesh.globalData().mergePoints
|
||||
(
|
||||
@ -592,207 +402,62 @@ void Foam::functionObjects::externalCoupled::checkOrder
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::readData()
|
||||
void Foam::functionObjects::externalCoupled::initCoupling()
|
||||
{
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
const wordList& regionNames = regionGroupRegions_[regioni];
|
||||
|
||||
// Get the meshes for the region-group
|
||||
UPtrList<const fvMesh> meshes(regionNames.size());
|
||||
forAll(regionNames, j)
|
||||
{
|
||||
const word& regionName = regionNames[j];
|
||||
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
|
||||
}
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
|
||||
forAll(groups, i)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupReadFields_[groupi];
|
||||
|
||||
forAll(fieldNames, fieldi)
|
||||
{
|
||||
const word& fieldName = fieldNames[fieldi];
|
||||
|
||||
const bool ok =
|
||||
(
|
||||
readData<scalar>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| readData<vector>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| readData<sphericalTensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| readData<symmTensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| readData<tensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Field " << fieldName << " in regions " << compName
|
||||
<< " was not found." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::writeData() const
|
||||
{
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
const wordList& regionNames = regionGroupRegions_[regioni];
|
||||
|
||||
// Get the meshes for the region-group
|
||||
UPtrList<const fvMesh> meshes(regionNames.size());
|
||||
forAll(regionNames, j)
|
||||
{
|
||||
const word& regionName = regionNames[j];
|
||||
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
|
||||
}
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
|
||||
forAll(groups, i)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupWriteFields_[groupi];
|
||||
|
||||
forAll(fieldNames, fieldi)
|
||||
{
|
||||
const word& fieldName = fieldNames[fieldi];
|
||||
|
||||
const bool ok =
|
||||
(
|
||||
writeData<scalar>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| writeData<vector>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| writeData<sphericalTensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| writeData<symmTensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
|| writeData<tensor>
|
||||
(
|
||||
meshes,
|
||||
groupName,
|
||||
fieldName
|
||||
)
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Field " << fieldName << " in regions " << compName
|
||||
<< " was not found." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::initialise()
|
||||
{
|
||||
if (initialised_)
|
||||
if (initialisedCoupling_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the geometry if not already there
|
||||
forAll(regionGroupRegions_, i)
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[i];
|
||||
const wordList& regionNames = regionGroupRegions_[i];
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
const wordList& regionNames = regionGroupRegions_[regioni];
|
||||
|
||||
// Get the meshes for the region-group
|
||||
UPtrList<const fvMesh> meshes(regionNames.size());
|
||||
forAll(regionNames, j)
|
||||
forAll(regionNames, regi)
|
||||
{
|
||||
const word& regionName = regionNames[j];
|
||||
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
|
||||
const word& regionName = regionNames[regi];
|
||||
meshes.set(regi, &time_.lookupObject<fvMesh>(regionName));
|
||||
}
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
|
||||
forAll(groups, i)
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
|
||||
bool exists = false;
|
||||
bool geomExists = false;
|
||||
if (Pstream::master())
|
||||
{
|
||||
fileName dir(groupDir(commsDir_, compName, groupName));
|
||||
fileName dir(groupDir(commDirectory(), compName, groupName));
|
||||
|
||||
exists =
|
||||
geomExists =
|
||||
isFile(dir/"patchPoints")
|
||||
|| isFile(dir/"patchFaces");
|
||||
}
|
||||
|
||||
if (!returnReduce(exists, orOp<bool>()))
|
||||
Pstream::scatter(geomExists);
|
||||
|
||||
if (!geomExists)
|
||||
{
|
||||
writeGeometry(meshes, commsDir_, groupName);
|
||||
writeGeometry(meshes, commDirectory(), groupName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (slaveFirst_)
|
||||
if (slaveFirst())
|
||||
{
|
||||
// Wait for initial data to be made available
|
||||
waitForSlave();
|
||||
|
||||
// Read data passed back from external source
|
||||
readData();
|
||||
readDataMaster();
|
||||
}
|
||||
|
||||
initialised_ = true;
|
||||
initialisedCoupling_ = true;
|
||||
}
|
||||
|
||||
|
||||
@ -806,18 +471,13 @@ Foam::functionObjects::externalCoupled::externalCoupled
|
||||
)
|
||||
:
|
||||
functionObject(name),
|
||||
externalFileCoupler(),
|
||||
time_(runTime),
|
||||
stateEnd_(REMOVE),
|
||||
initialised_(false)
|
||||
initialisedCoupling_(false)
|
||||
{
|
||||
read(dict);
|
||||
|
||||
if (Pstream::master())
|
||||
{
|
||||
mkDir(baseDir());
|
||||
}
|
||||
|
||||
if (!slaveFirst_)
|
||||
if (!slaveFirst())
|
||||
{
|
||||
useMaster();
|
||||
}
|
||||
@ -827,22 +487,20 @@ Foam::functionObjects::externalCoupled::externalCoupled
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::functionObjects::externalCoupled::~externalCoupled()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::functionObjects::externalCoupled::execute()
|
||||
{
|
||||
if (!initialised_ || time_.timeIndex() % calcFrequency_ == 0)
|
||||
if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0)
|
||||
{
|
||||
// Initialise the coupling
|
||||
initialise();
|
||||
initCoupling();
|
||||
|
||||
// Write data for external source
|
||||
writeData();
|
||||
writeDataMaster();
|
||||
|
||||
// Signal external source to execute (by removing lock file)
|
||||
// - Wait for slave to provide data
|
||||
@ -855,7 +513,7 @@ bool Foam::functionObjects::externalCoupled::execute()
|
||||
removeDataMaster();
|
||||
|
||||
// Read data passed back from external source
|
||||
readData();
|
||||
readDataMaster();
|
||||
|
||||
// Signal external source to wait (by creating the lock file)
|
||||
useMaster();
|
||||
@ -876,7 +534,7 @@ bool Foam::functionObjects::externalCoupled::end()
|
||||
// Remove old data files
|
||||
removeDataMaster();
|
||||
removeDataSlave();
|
||||
cleanup();
|
||||
shutdown();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -885,33 +543,10 @@ bool Foam::functionObjects::externalCoupled::end()
|
||||
bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||
{
|
||||
functionObject::read(dict);
|
||||
|
||||
// NB: Cannot change directory or initialization
|
||||
// if things have already been initialized
|
||||
if (!initialised_)
|
||||
{
|
||||
dict.lookup("commsDir") >> commsDir_;
|
||||
commsDir_.expand();
|
||||
commsDir_.clean();
|
||||
|
||||
slaveFirst_ = readBool(dict.lookup("initByExternal"));
|
||||
// slaveFirst_ = dict.lookupOrDefault<bool>("initByExternal", false);
|
||||
}
|
||||
externalFileCoupler::readDict(dict);
|
||||
|
||||
calcFrequency_ = dict.lookupOrDefault("calcFrequency", 1);
|
||||
|
||||
waitInterval_ = dict.lookupOrDefault("waitInterval", 1u);
|
||||
if (!waitInterval_)
|
||||
{
|
||||
// Enforce non-zero sleep
|
||||
waitInterval_ = 1u;
|
||||
}
|
||||
|
||||
timeOut_ = dict.lookupOrDefault("timeOut", 100*waitInterval_);
|
||||
stateEnd_ =
|
||||
stateEndNames_.lookupOrDefault("stateEnd", dict, stateEnd::DONE);
|
||||
|
||||
|
||||
// Get names of all fvMeshes (and derived types)
|
||||
wordList allRegionNames(time_.lookupClass<fvMesh>().sortedToc());
|
||||
|
||||
@ -960,7 +595,7 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||
regionToGroups_.insert
|
||||
(
|
||||
regionGroupNames_.last(),
|
||||
labelList(1, nGroups)
|
||||
labelList{nGroups}
|
||||
);
|
||||
}
|
||||
groupNames_.append(groupName);
|
||||
@ -971,16 +606,12 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||
|
||||
|
||||
Info<< type() << ": Communicating with regions:" << endl;
|
||||
forAll(regionGroupNames_, rgi)
|
||||
for (const word& compName : regionGroupNames_)
|
||||
{
|
||||
//const wordList& regionNames = regionGroupRegions_[rgi];
|
||||
const word& compName = regionGroupNames_[rgi];
|
||||
|
||||
Info<< "Region: " << compName << endl << incrIndent;
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
forAll(groups, i)
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
|
||||
Info<< indent << "patchGroup: " << groupName << "\t"
|
||||
@ -1003,17 +634,15 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||
// should already be written - but just make sure
|
||||
if (Pstream::master())
|
||||
{
|
||||
forAll(regionGroupNames_, rgi)
|
||||
for (const word& compName : regionGroupNames_)
|
||||
{
|
||||
const word& compName = regionGroupNames_[rgi];
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
forAll(groups, i)
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
label groupi = groups[i];
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
|
||||
fileName dir(groupDir(commsDir_, compName, groupName));
|
||||
fileName dir(groupDir(commDirectory(), compName, groupName));
|
||||
|
||||
if (!isDir(dir))
|
||||
{
|
||||
Log << type() << ": creating communications directory "
|
||||
@ -1028,6 +657,156 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::readDataMaster()
|
||||
{
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
const wordList& regionNames = regionGroupRegions_[regioni];
|
||||
|
||||
// Get the meshes for the region-group
|
||||
UPtrList<const fvMesh> meshes(regionNames.size());
|
||||
forAll(regionNames, j)
|
||||
{
|
||||
const word& regionName = regionNames[j];
|
||||
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
|
||||
}
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupReadFields_[groupi];
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
const bool ok =
|
||||
(
|
||||
readData<scalar>(meshes, groupName, fieldName)
|
||||
|| readData<vector>(meshes, groupName, fieldName)
|
||||
|| readData<sphericalTensor>(meshes, groupName, fieldName)
|
||||
|| readData<symmTensor>(meshes, groupName, fieldName)
|
||||
|| readData<tensor>(meshes, groupName, fieldName)
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Field " << fieldName << " in regions " << compName
|
||||
<< " was not found." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::writeDataMaster() const
|
||||
{
|
||||
forAll(regionGroupNames_, regioni)
|
||||
{
|
||||
const word& compName = regionGroupNames_[regioni];
|
||||
const wordList& regionNames = regionGroupRegions_[regioni];
|
||||
|
||||
// Get the meshes for the region-group
|
||||
UPtrList<const fvMesh> meshes(regionNames.size());
|
||||
forAll(regionNames, j)
|
||||
{
|
||||
const word& regionName = regionNames[j];
|
||||
meshes.set(j, &time_.lookupObject<fvMesh>(regionName));
|
||||
}
|
||||
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupWriteFields_[groupi];
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
const bool ok =
|
||||
(
|
||||
writeData<scalar>(meshes, groupName, fieldName)
|
||||
|| writeData<vector>(meshes, groupName, fieldName)
|
||||
|| writeData<sphericalTensor>(meshes, groupName, fieldName)
|
||||
|| writeData<symmTensor>(meshes, groupName, fieldName)
|
||||
|| writeData<tensor>(meshes, groupName, fieldName)
|
||||
);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Field " << fieldName << " in regions " << compName
|
||||
<< " was not found." << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::removeDataMaster() const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log << type() << ": removing data files written by master" << nl;
|
||||
|
||||
for (const word& compName : regionGroupNames_)
|
||||
{
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupReadFields_[groupi];
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
Foam::rm
|
||||
(
|
||||
groupDir(commDirectory(), compName, groupName)
|
||||
/ fieldName + ".out"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::functionObjects::externalCoupled::removeDataSlave() const
|
||||
{
|
||||
if (!Pstream::master())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Log << type() << ": removing data files written by slave" << nl;
|
||||
|
||||
for (const word& compName : regionGroupNames_)
|
||||
{
|
||||
const labelList& groups = regionToGroups_[compName];
|
||||
for (const label groupi : groups)
|
||||
{
|
||||
const wordRe& groupName = groupNames_[groupi];
|
||||
const wordList& fieldNames = groupReadFields_[groupi];
|
||||
|
||||
for (const word& fieldName : fieldNames)
|
||||
{
|
||||
Foam::rm
|
||||
(
|
||||
groupDir(commDirectory(), compName, groupName)
|
||||
/ fieldName + ".in"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::externalCoupled::write()
|
||||
{
|
||||
return true;
|
||||
|
||||
@ -42,7 +42,7 @@ Description
|
||||
|
||||
where the actual entries depend on the bc type:
|
||||
- mixed: value, snGrad, refValue, refGrad, valueFraction
|
||||
- externalCoupledMixed: output of writeData
|
||||
- externalCoupledMixed: output of writeDataMaster
|
||||
- other: value, snGrad
|
||||
|
||||
These text files are located in a user specified communications directory
|
||||
@ -146,6 +146,7 @@ SourceFiles
|
||||
#define functionObjects_externalCoupled_H
|
||||
|
||||
#include "functionObject.H"
|
||||
#include "externalFileCoupler.H"
|
||||
#include "DynamicList.H"
|
||||
#include "wordReList.H"
|
||||
#include "scalarField.H"
|
||||
@ -171,7 +172,8 @@ namespace functionObjects
|
||||
|
||||
class externalCoupled
|
||||
:
|
||||
public functionObject
|
||||
public functionObject,
|
||||
public externalFileCoupler
|
||||
{
|
||||
public:
|
||||
|
||||
@ -190,30 +192,14 @@ private:
|
||||
//- State end names (NB, only selectable values itemized)
|
||||
static const Enum<stateEnd> stateEndNames_;
|
||||
|
||||
|
||||
// Private data
|
||||
|
||||
//- Reference to the time database
|
||||
const Time& time_;
|
||||
|
||||
//- Path to communications directory
|
||||
fileName commsDir_;
|
||||
|
||||
//- Interval time between checking for return data [s]
|
||||
unsigned waitInterval_;
|
||||
|
||||
//- Time out time [s]
|
||||
unsigned timeOut_;
|
||||
|
||||
//- Calculation frequency
|
||||
label calcFrequency_;
|
||||
|
||||
//- Flag to indicate values are initialised by external application
|
||||
bool slaveFirst_;
|
||||
|
||||
//- Lockfile state on termination
|
||||
mutable stateEnd stateEnd_;
|
||||
|
||||
//- Names of (composite) regions
|
||||
DynamicList<word> regionGroupNames_;
|
||||
|
||||
@ -232,8 +218,8 @@ private:
|
||||
// Per group the names of the fields to write
|
||||
DynamicList<wordList> groupWriteFields_;
|
||||
|
||||
//- Initialised flag
|
||||
bool initialised_;
|
||||
//- Initialised coupling
|
||||
bool initialisedCoupling_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
@ -246,32 +232,6 @@ private:
|
||||
const wordRe& groupName
|
||||
);
|
||||
|
||||
//- Return the file path to the base communications directory
|
||||
fileName baseDir() const;
|
||||
|
||||
//- Return the file path to the lock file
|
||||
fileName lockFile() const;
|
||||
|
||||
|
||||
//- Create lock file to indicate that OpenFOAM is in charge
|
||||
void useMaster() const;
|
||||
|
||||
//- Remove lock file to indicate that the external program is in charge
|
||||
void useSlave() const;
|
||||
|
||||
//- Remove lock file or status=done in lock.
|
||||
void cleanup() const;
|
||||
|
||||
//- Remove files written by OpenFOAM
|
||||
void removeDataMaster() const;
|
||||
|
||||
//- Remove files written by external code
|
||||
void removeDataSlave() const;
|
||||
|
||||
//- Wait for indication that the external program has supplied input
|
||||
// (ie, for the lock file to reappear).
|
||||
void waitForSlave() const;
|
||||
|
||||
|
||||
//- Read data for a single region, single field
|
||||
template<class Type>
|
||||
@ -281,8 +241,6 @@ private:
|
||||
const wordRe& groupName,
|
||||
const word& fieldName
|
||||
);
|
||||
//- Read data for all regions, all fields
|
||||
void readData();
|
||||
|
||||
//- Write data for a single region, single field
|
||||
template<class Type>
|
||||
@ -293,10 +251,7 @@ private:
|
||||
const word& fieldName
|
||||
) const;
|
||||
|
||||
//- Write data for all regions, all fields
|
||||
void writeData() const;
|
||||
|
||||
void initialise();
|
||||
void initCoupling();
|
||||
|
||||
//- Read (and distribute) scalar columns from stream. Every processor
|
||||
// gets nRows (= patch size) of these. Note: could make its argument
|
||||
@ -339,12 +294,12 @@ public:
|
||||
//- Runtime type information
|
||||
TypeName("externalCoupled");
|
||||
|
||||
//- Name of lock file (normally 'OpenFOAM.lock')
|
||||
static word lockName;
|
||||
|
||||
//- Name of patch key, e.g. '// Patch:' when looking for start of patch data
|
||||
static string patchKey;
|
||||
|
||||
//- Inherited variable for logging
|
||||
using functionObject::log;
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
@ -378,6 +333,21 @@ public:
|
||||
virtual bool write();
|
||||
|
||||
|
||||
// File creation, removal
|
||||
|
||||
//- Write data files (all regions, all fields) from master (OpenFOAM)
|
||||
virtual void writeDataMaster() const;
|
||||
|
||||
//- Read data files (all regions, all fields) on master (OpenFOAM)
|
||||
virtual void readDataMaster();
|
||||
|
||||
//- Remove data files written by master (OpenFOAM)
|
||||
virtual void removeDataMaster() const;
|
||||
|
||||
//- Remove data files written by slave (external code)
|
||||
virtual void removeDataSlave() const;
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Create single name by appending words (in sorted order),
|
||||
|
||||
@ -62,7 +62,7 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
{
|
||||
const fileName transferFile
|
||||
(
|
||||
groupDir(commsDir_, compositeName(regionNames), groupName)
|
||||
groupDir(commDirectory(), compositeName(regionNames), groupName)
|
||||
/ fieldName + ".in"
|
||||
);
|
||||
|
||||
@ -81,46 +81,40 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
|
||||
|
||||
label nFound = 0;
|
||||
forAll(meshes, i)
|
||||
for (const fvMesh& mesh : meshes)
|
||||
{
|
||||
const fvMesh& mesh = meshes[i];
|
||||
const volFieldType* vfptr =
|
||||
mesh.lookupObjectPtr<volFieldType>(fieldName);
|
||||
|
||||
if (!mesh.foundObject<volFieldType>(fieldName))
|
||||
if (!vfptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nFound++;
|
||||
|
||||
const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName);
|
||||
const typename volFieldType::Boundary& bf = cvf.boundaryField();
|
||||
|
||||
typename volFieldType::Boundary& bf =
|
||||
const_cast<volFieldType*>(vfptr)->boundaryFieldRef();
|
||||
|
||||
// Get the patches
|
||||
const labelList patchIDs
|
||||
(
|
||||
mesh.boundaryMesh().patchSet
|
||||
(
|
||||
List<wordRe>(1, groupName)
|
||||
List<wordRe>{groupName}
|
||||
).sortedToc()
|
||||
);
|
||||
|
||||
// Handle column-wise reading of patch data. Supports most easy types
|
||||
forAll(patchIDs, i)
|
||||
for (const label patchi : patchIDs)
|
||||
{
|
||||
label patchi = patchIDs[i];
|
||||
|
||||
if (isA<patchFieldType>(bf[patchi]))
|
||||
{
|
||||
// Explicit handling of externalCoupledMixed bcs - they
|
||||
// have specialised reading routines.
|
||||
|
||||
patchFieldType& pf = const_cast<patchFieldType&>
|
||||
patchFieldType& pf = refCast<patchFieldType>
|
||||
(
|
||||
refCast<const patchFieldType>
|
||||
(
|
||||
bf[patchi]
|
||||
)
|
||||
bf[patchi]
|
||||
);
|
||||
|
||||
// Read from master into local stream
|
||||
@ -141,6 +135,11 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
}
|
||||
else if (isA<mixedFvPatchField<Type>>(bf[patchi]))
|
||||
{
|
||||
mixedFvPatchField<Type>& pf = refCast<mixedFvPatchField<Type>>
|
||||
(
|
||||
bf[patchi]
|
||||
);
|
||||
|
||||
// Read columns from file for
|
||||
// value, snGrad, refValue, refGrad, valueFraction
|
||||
List<scalarField> data;
|
||||
@ -152,15 +151,6 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
data
|
||||
);
|
||||
|
||||
mixedFvPatchField<Type>& pf =
|
||||
const_cast<mixedFvPatchField<Type>&>
|
||||
(
|
||||
refCast<const mixedFvPatchField<Type>>
|
||||
(
|
||||
bf[patchi]
|
||||
)
|
||||
);
|
||||
|
||||
// Transfer read data to bc.
|
||||
// Skip value, snGrad
|
||||
direction columni = 2*pTraits<Type>::nComponents;
|
||||
@ -193,6 +183,9 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
}
|
||||
else if (isA<fixedGradientFvPatchField<Type>>(bf[patchi]))
|
||||
{
|
||||
fixedGradientFvPatchField<Type>& pf =
|
||||
refCast<fixedGradientFvPatchField<Type>>(bf[patchi]);
|
||||
|
||||
// Read columns for value and gradient
|
||||
List<scalarField> data;
|
||||
readColumns
|
||||
@ -203,15 +196,6 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
data
|
||||
);
|
||||
|
||||
fixedGradientFvPatchField<Type>& pf =
|
||||
const_cast<fixedGradientFvPatchField<Type>&>
|
||||
(
|
||||
refCast<const fixedGradientFvPatchField<Type>>
|
||||
(
|
||||
bf[patchi]
|
||||
)
|
||||
);
|
||||
|
||||
// Transfer gradient to bc
|
||||
Field<Type>& gradient = pf.gradient();
|
||||
for
|
||||
@ -234,6 +218,9 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
}
|
||||
else if (isA<fixedValueFvPatchField<Type>>(bf[patchi]))
|
||||
{
|
||||
fixedValueFvPatchField<Type>& pf =
|
||||
refCast<fixedValueFvPatchField<Type>>(bf[patchi]);
|
||||
|
||||
// Read columns for value only
|
||||
List<scalarField> data;
|
||||
readColumns
|
||||
@ -256,15 +243,6 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
value.replace(cmpt, data[cmpt]);
|
||||
}
|
||||
|
||||
fixedValueFvPatchField<Type>& pf =
|
||||
const_cast<fixedValueFvPatchField<Type>&>
|
||||
(
|
||||
refCast<const fixedValueFvPatchField<Type>>
|
||||
(
|
||||
bf[patchi]
|
||||
)
|
||||
);
|
||||
|
||||
pf == value;
|
||||
|
||||
// Update the value from the read coefficicient. Bypass any
|
||||
@ -280,7 +258,7 @@ bool Foam::functionObjects::externalCoupled::readData
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
initialised_ = true;
|
||||
initialisedCoupling_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,7 +335,7 @@ bool Foam::functionObjects::externalCoupled::writeData
|
||||
{
|
||||
const fileName transferFile
|
||||
(
|
||||
groupDir(commsDir_, compositeName(regionNames), groupName)
|
||||
groupDir(commDirectory(), compositeName(regionNames), groupName)
|
||||
/ fieldName + ".out"
|
||||
);
|
||||
|
||||
@ -379,35 +357,32 @@ bool Foam::functionObjects::externalCoupled::writeData
|
||||
|
||||
label nFound = 0;
|
||||
|
||||
forAll(meshes, i)
|
||||
for (const fvMesh& mesh : meshes)
|
||||
{
|
||||
const fvMesh& mesh = meshes[i];
|
||||
const volFieldType* vfptr =
|
||||
mesh.lookupObjectPtr<volFieldType>(fieldName);
|
||||
|
||||
if (!mesh.foundObject<volFieldType>(fieldName))
|
||||
if (!vfptr)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
nFound++;
|
||||
|
||||
const volFieldType& cvf = mesh.lookupObject<volFieldType>(fieldName);
|
||||
const typename volFieldType::Boundary& bf = cvf.boundaryField();
|
||||
|
||||
const typename volFieldType::Boundary& bf =
|
||||
vfptr->boundaryField();
|
||||
|
||||
// Get the patches
|
||||
const labelList patchIDs
|
||||
(
|
||||
mesh.boundaryMesh().patchSet
|
||||
(
|
||||
List<wordRe>(1, groupName)
|
||||
List<wordRe>{groupName}
|
||||
).sortedToc()
|
||||
);
|
||||
|
||||
// Handle column-wise writing of patch data. Supports most easy types
|
||||
forAll(patchIDs, i)
|
||||
for (const label patchi : patchIDs)
|
||||
{
|
||||
label patchi = patchIDs[i];
|
||||
|
||||
const globalIndex globalFaces(bf[patchi].size());
|
||||
|
||||
if (isA<patchFieldType>(bf[patchi]))
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
||||
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -61,19 +61,43 @@ Foam::functionObjects::abort::actionNames_
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::functionObjects::abort::removeFile() const
|
||||
// file-scope
|
||||
// Long description for the action name
|
||||
namespace Foam
|
||||
{
|
||||
bool hasAbort = isFile(abortFile_);
|
||||
reduce(hasAbort, orOp<bool>());
|
||||
|
||||
if (hasAbort && Pstream::master())
|
||||
static std::string longDescription(const Time::stopAtControls ctrl)
|
||||
{
|
||||
switch (ctrl)
|
||||
{
|
||||
// Cleanup ABORT file (on master only)
|
||||
rm(abortFile_);
|
||||
case Foam::Time::saNoWriteNow :
|
||||
{
|
||||
return "stop without writing data";
|
||||
break;
|
||||
}
|
||||
|
||||
case Time::saWriteNow :
|
||||
{
|
||||
return "stop and write data";
|
||||
break;
|
||||
}
|
||||
|
||||
case Time::saNextWrite :
|
||||
{
|
||||
return "stop after next data write";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Invalid choices already filtered out by Enum
|
||||
return "abort";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
@ -88,13 +112,17 @@ Foam::functionObjects::abort::abort
|
||||
functionObject(name),
|
||||
time_(runTime),
|
||||
abortFile_("$FOAM_CASE/" + name),
|
||||
action_(Time::stopAtControls::saNextWrite)
|
||||
action_(Time::stopAtControls::saNextWrite),
|
||||
triggered_(false)
|
||||
{
|
||||
abortFile_.expand();
|
||||
read(dict);
|
||||
|
||||
// Remove any old files from previous runs
|
||||
removeFile();
|
||||
// Cleanup old files from previous runs
|
||||
if (Pstream::master())
|
||||
{
|
||||
Foam::rm(abortFile_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -110,6 +138,13 @@ bool Foam::functionObjects::abort::read(const dictionary& dict)
|
||||
{
|
||||
functionObject::read(dict);
|
||||
|
||||
if (dict.readIfPresent("file", abortFile_))
|
||||
{
|
||||
abortFile_.expand();
|
||||
}
|
||||
|
||||
const auto oldAction = action_;
|
||||
|
||||
action_ = actionNames_.lookupOrDefault
|
||||
(
|
||||
"action",
|
||||
@ -117,64 +152,42 @@ bool Foam::functionObjects::abort::read(const dictionary& dict)
|
||||
Time::stopAtControls::saNextWrite
|
||||
);
|
||||
|
||||
if (dict.readIfPresent("file", abortFile_))
|
||||
// User can change action and re-trigger the abort.
|
||||
// eg, they had nextWrite, but actually wanted writeNow.
|
||||
if (oldAction != action_)
|
||||
{
|
||||
abortFile_.expand();
|
||||
triggered_ = false;
|
||||
}
|
||||
|
||||
Info<< type() << " activated ("
|
||||
<< longDescription(action_).c_str() <<")" << nl
|
||||
<< " File: " << abortFile_ << endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::functionObjects::abort::execute()
|
||||
{
|
||||
bool hasAbort = isFile(abortFile_);
|
||||
reduce(hasAbort, orOp<bool>());
|
||||
|
||||
if (hasAbort)
|
||||
// If it has been triggered (eg, nextWrite) don't need to check it again
|
||||
if (!triggered_)
|
||||
{
|
||||
switch (action_)
|
||||
bool hasAbort = (Pstream::master() && isFile(abortFile_));
|
||||
Pstream::scatter(hasAbort);
|
||||
|
||||
if (hasAbort)
|
||||
{
|
||||
case Time::saNoWriteNow :
|
||||
triggered_ = time_.stopAt(action_);
|
||||
|
||||
if (triggered_)
|
||||
{
|
||||
if (time_.stopAt(action_))
|
||||
{
|
||||
Info<< "USER REQUESTED ABORT (timeIndex="
|
||||
<< time_.timeIndex()
|
||||
<< "): stop without writing data"
|
||||
<< endl;
|
||||
}
|
||||
break;
|
||||
Info<< "USER REQUESTED ABORT (timeIndex="
|
||||
<< time_.timeIndex()
|
||||
<< "): " << longDescription(action_).c_str()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
case Time::saWriteNow :
|
||||
{
|
||||
if (time_.stopAt(action_))
|
||||
{
|
||||
Info<< "USER REQUESTED ABORT (timeIndex="
|
||||
<< time_.timeIndex()
|
||||
<< "): stop+write data"
|
||||
<< endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Time::saNextWrite :
|
||||
{
|
||||
if (time_.stopAt(action_))
|
||||
{
|
||||
Info<< "USER REQUESTED ABORT (timeIndex="
|
||||
<< time_.timeIndex()
|
||||
<< "): stop after next data write"
|
||||
<< endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Invalid choices already filtered out by Enum
|
||||
}
|
||||
Pstream::scatter(triggered_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,7 +203,12 @@ bool Foam::functionObjects::abort::write()
|
||||
|
||||
bool Foam::functionObjects::abort::end()
|
||||
{
|
||||
removeFile();
|
||||
// Cleanup ABORT file
|
||||
if (Pstream::master())
|
||||
{
|
||||
Foam::rm(abortFile_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
@ -30,12 +30,21 @@ 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:
|
||||
- noWriteNow
|
||||
- writeNow
|
||||
- nextWrite
|
||||
|
||||
\heading Function object usage
|
||||
\table
|
||||
Property | Description | Required | Default value
|
||||
type | Type name: abort | yes |
|
||||
file | The abort filename | no | $FOAM_CASE/name
|
||||
action | Abort action | no | nextWrite
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
abort.C
|
||||
|
||||
@ -55,7 +64,7 @@ namespace functionObjects
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class abort Declaration
|
||||
Class abort Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class abort
|
||||
@ -76,12 +85,12 @@ class abort
|
||||
//- The type of action
|
||||
Time::stopAtControls action_;
|
||||
|
||||
//- Only trigger action once
|
||||
bool triggered_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Remove abort file.
|
||||
void removeFile() const;
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
abort(const abort&) = delete;
|
||||
|
||||
@ -102,7 +111,7 @@ public:
|
||||
(
|
||||
const word& name,
|
||||
const Time& runTime,
|
||||
const dictionary&
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
@ -115,13 +124,13 @@ public:
|
||||
//- Read the dictionary settings
|
||||
virtual bool read(const dictionary& dict);
|
||||
|
||||
//- Execute, check existence of abort file and take action
|
||||
//- Check existence of abort file and take action
|
||||
virtual bool execute();
|
||||
|
||||
//- Execute, check existence of abort file and take action
|
||||
//- No-op
|
||||
virtual bool write();
|
||||
|
||||
//- Execute at the final time-loop, used for cleanup
|
||||
//- Remove abort file after the final time-loop.
|
||||
virtual bool end();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user