mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: refactor and combine externalFileCoupler (issue #529)
This commit is contained in:
@ -1,3 +0,0 @@
|
|||||||
Test-externalCoupler.C
|
|
||||||
|
|
||||||
EXE = $(FOAM_USER_APPBIN)/Test-externalCoupler
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
EXE_INC = \
|
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
|
||||||
-I$(LIB_SRC)/lumpedPointMotion/lnInclude
|
|
||||||
|
|
||||||
EXE_LIBS = \
|
|
||||||
-lfiniteVolume \
|
|
||||||
-llumpedPointMotion
|
|
||||||
3
applications/test/externalFileCoupler/Make/files
Normal file
3
applications/test/externalFileCoupler/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-externalFileCoupler.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-externalFileCoupler
|
||||||
5
applications/test/externalFileCoupler/Make/options
Normal file
5
applications/test/externalFileCoupler/Make/options
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
EXE_INC = \
|
||||||
|
-I$(LIB_SRC)/finiteVolume/lnInclude
|
||||||
|
|
||||||
|
EXE_LIBS = \
|
||||||
|
-lfiniteVolume
|
||||||
@ -22,14 +22,14 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Application
|
Application
|
||||||
Test-externalCoupler
|
Test-externalFileCoupler
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Test of master/slave communication etc.
|
Test of master/slave communication etc.
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "argList.H"
|
#include "argList.H"
|
||||||
#include "externalCoupler.H"
|
#include "externalFileCoupler.H"
|
||||||
|
|
||||||
using namespace Foam;
|
using namespace Foam;
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
const label maxCount = args.optionLookupOrDefault<label>("max", 1000);
|
const label maxCount = args.optionLookupOrDefault<label>("max", 1000);
|
||||||
|
|
||||||
externalCoupler coupler;
|
externalFileCoupler coupler;
|
||||||
|
|
||||||
if (args.optionFound("slave"))
|
if (args.optionFound("slave"))
|
||||||
{
|
{
|
||||||
@ -29,7 +29,7 @@ Description
|
|||||||
points/rotations and the corresponding movement of the building surfaces.
|
points/rotations and the corresponding movement of the building surfaces.
|
||||||
Uses the tabulated responses from the specified file.
|
Uses the tabulated responses from the specified file.
|
||||||
Optionally, it can also be used to a dummy responder for the
|
Optionally, it can also be used to a dummy responder for the
|
||||||
externalCoupler logic, which makes it useful as a debugging facility
|
externalFileCoupler logic, which makes it useful as a debugging facility
|
||||||
as well demonstrating how an external application could communicate
|
as well demonstrating how an external application could communicate
|
||||||
with the lumpedPointMovement point-patch boundary condition.
|
with the lumpedPointMovement point-patch boundary condition.
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
Info<< "Running as slave responder" << endl;
|
Info<< "Running as slave responder" << endl;
|
||||||
|
|
||||||
externalCoupler& coupler = movement().coupler();
|
externalFileCoupler& coupler = movement().coupler();
|
||||||
|
|
||||||
label count = 0;
|
label count = 0;
|
||||||
for (label index = 0; index < responseTable.size(); index += span)
|
for (label index = 0; index < responseTable.size(); index += span)
|
||||||
|
|||||||
@ -411,6 +411,9 @@ $(general)/bound/bound.C
|
|||||||
$(general)/CorrectPhi/correctUphiBCs.C
|
$(general)/CorrectPhi/correctUphiBCs.C
|
||||||
$(general)/pressureControl/pressureControl.C
|
$(general)/pressureControl/pressureControl.C
|
||||||
|
|
||||||
|
coupling = $(general)/coupling
|
||||||
|
$(coupling)/externalFileCoupler.C
|
||||||
|
|
||||||
solutionControl = $(general)/solutionControl
|
solutionControl = $(general)/solutionControl
|
||||||
$(solutionControl)/solutionControl/solutionControl.C
|
$(solutionControl)/solutionControl/solutionControl.C
|
||||||
$(solutionControl)/simpleControl/simpleControl.C
|
$(solutionControl)/simpleControl/simpleControl.C
|
||||||
|
|||||||
@ -23,22 +23,21 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "externalCoupler.H"
|
#include "externalFileCoupler.H"
|
||||||
#include "Pstream.H"
|
#include "Pstream.H"
|
||||||
#include "PstreamReduceOps.H"
|
#include "PstreamReduceOps.H"
|
||||||
#include "OSspecific.H"
|
#include "OSspecific.H"
|
||||||
#include "IFstream.H"
|
|
||||||
#include "OFstream.H"
|
|
||||||
#include "Switch.H"
|
#include "Switch.H"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(externalCoupler, 0);
|
defineTypeNameAndDebug(externalFileCoupler, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Foam::word Foam::externalCoupler::lockName = "OpenFOAM";
|
Foam::word Foam::externalFileCoupler::lockName = "OpenFOAM";
|
||||||
|
|
||||||
|
|
||||||
// file-scope
|
// file-scope
|
||||||
@ -46,30 +45,16 @@ Foam::word Foam::externalCoupler::lockName = "OpenFOAM";
|
|||||||
static bool checkIsDone(const std::string& lck)
|
static bool checkIsDone(const std::string& lck)
|
||||||
{
|
{
|
||||||
std::string content;
|
std::string content;
|
||||||
std::ifstream is(lck.c_str());
|
std::ifstream is(lck);
|
||||||
is >> content;
|
is >> content;
|
||||||
|
|
||||||
return (content.find("done") != std::string::npos);
|
return (content.find("done") != std::string::npos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
const Foam::fileName& Foam::externalCoupler::baseDir() const
|
|
||||||
{
|
|
||||||
return commsDir_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::fileName Foam::externalCoupler::lockFile() const
|
|
||||||
{
|
|
||||||
return resolveFile(lockName + ".lock");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::externalCoupler::externalCoupler()
|
Foam::externalFileCoupler::externalFileCoupler()
|
||||||
:
|
:
|
||||||
runState_(NONE),
|
runState_(NONE),
|
||||||
commsDir_("$FOAM_CASE/comms"),
|
commsDir_("$FOAM_CASE/comms"),
|
||||||
@ -83,22 +68,41 @@ Foam::externalCoupler::externalCoupler()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::externalCoupler::externalCoupler(const dictionary& dict)
|
Foam::externalFileCoupler::externalFileCoupler(const fileName& commsDir)
|
||||||
:
|
:
|
||||||
externalCoupler()
|
runState_(NONE),
|
||||||
|
commsDir_(commsDir),
|
||||||
|
waitInterval_(1u),
|
||||||
|
timeOut_(100u),
|
||||||
|
slaveFirst_(false),
|
||||||
|
log(false)
|
||||||
|
{
|
||||||
|
commsDir_.expand();
|
||||||
|
commsDir_.clean();
|
||||||
|
|
||||||
|
if (Pstream::master())
|
||||||
|
{
|
||||||
|
mkDir(commsDir_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::externalFileCoupler::externalFileCoupler(const dictionary& dict)
|
||||||
|
:
|
||||||
|
externalFileCoupler()
|
||||||
{
|
{
|
||||||
readDict(dict);
|
readDict(dict);
|
||||||
|
|
||||||
if (Pstream::master())
|
if (Pstream::master())
|
||||||
{
|
{
|
||||||
mkDir(baseDir());
|
mkDir(commsDir_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::externalCoupler::~externalCoupler()
|
Foam::externalFileCoupler::~externalFileCoupler()
|
||||||
{
|
{
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
@ -106,15 +110,22 @@ Foam::externalCoupler::~externalCoupler()
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::externalCoupler::readDict(const dictionary& dict)
|
bool Foam::externalFileCoupler::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
// Normally cannot change directory or initialization
|
// Normally cannot change directory or initialization
|
||||||
// if things have already been initialized
|
// if things have already been initialized
|
||||||
|
if (!initialized())
|
||||||
|
{
|
||||||
dict.lookup("commsDir") >> commsDir_;
|
dict.lookup("commsDir") >> commsDir_;
|
||||||
commsDir_.expand();
|
commsDir_.expand();
|
||||||
commsDir_.clean();
|
commsDir_.clean();
|
||||||
slaveFirst_ = dict.lookupOrDefault<bool>("initByExternal", false);
|
slaveFirst_ = dict.lookupOrDefault<bool>("initByExternal", false);
|
||||||
|
|
||||||
|
Info<< type() << ": initialize" << nl
|
||||||
|
<< " directory: " << commsDir_ << nl
|
||||||
|
<< " slave-first: " << Switch(slaveFirst_) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
waitInterval_ = dict.lookupOrDefault("waitInterval", 1u);
|
waitInterval_ = dict.lookupOrDefault("waitInterval", 1u);
|
||||||
if (!waitInterval_)
|
if (!waitInterval_)
|
||||||
{
|
{
|
||||||
@ -130,19 +141,7 @@ bool Foam::externalCoupler::readDict(const dictionary& dict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::externalCoupler::initialized() const
|
void Foam::externalFileCoupler::useMaster(const bool wait) const
|
||||||
{
|
|
||||||
return runState_ != NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::externalCoupler::slaveFirst() const
|
|
||||||
{
|
|
||||||
return slaveFirst_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::externalCoupler::useMaster(const bool wait) const
|
|
||||||
{
|
{
|
||||||
const bool wasInit = initialized();
|
const bool wasInit = initialized();
|
||||||
runState_ = MASTER;
|
runState_ = MASTER;
|
||||||
@ -162,7 +161,7 @@ void Foam::externalCoupler::useMaster(const bool wait) const
|
|||||||
{
|
{
|
||||||
Log << type() << ": creating lock file" << endl;
|
Log << type() << ": creating lock file" << endl;
|
||||||
|
|
||||||
OFstream os(lck);
|
std::ofstream os(lck);
|
||||||
os << "status=openfoam\n";
|
os << "status=openfoam\n";
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
@ -175,7 +174,7 @@ void Foam::externalCoupler::useMaster(const bool wait) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::externalCoupler::useSlave(const bool wait) const
|
void Foam::externalFileCoupler::useSlave(const bool wait) const
|
||||||
{
|
{
|
||||||
const bool wasInit = initialized();
|
const bool wasInit = initialized();
|
||||||
runState_ = SLAVE;
|
runState_ = SLAVE;
|
||||||
@ -200,7 +199,7 @@ void Foam::externalCoupler::useSlave(const bool wait) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::externalCoupler::waitForMaster() const
|
bool Foam::externalFileCoupler::waitForMaster() const
|
||||||
{
|
{
|
||||||
if (!initialized())
|
if (!initialized())
|
||||||
{
|
{
|
||||||
@ -212,7 +211,7 @@ bool Foam::externalCoupler::waitForMaster() const
|
|||||||
{
|
{
|
||||||
const fileName lck(lockFile());
|
const fileName lck(lockFile());
|
||||||
|
|
||||||
double prevTime = -1;
|
double prevTime = 0;
|
||||||
double modTime = 0;
|
double modTime = 0;
|
||||||
|
|
||||||
// Wait until file disappears (modTime == 0)
|
// Wait until file disappears (modTime == 0)
|
||||||
@ -239,7 +238,7 @@ bool Foam::externalCoupler::waitForMaster() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::externalCoupler::waitForSlave() const
|
bool Foam::externalFileCoupler::waitForSlave() const
|
||||||
{
|
{
|
||||||
if (!initialized())
|
if (!initialized())
|
||||||
{
|
{
|
||||||
@ -281,23 +280,38 @@ bool Foam::externalCoupler::waitForSlave() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::fileName Foam::externalCoupler::resolveFile
|
void Foam::externalFileCoupler::readDataMaster()
|
||||||
(
|
{}
|
||||||
const word& file
|
|
||||||
) const
|
|
||||||
{
|
|
||||||
return fileName(baseDir()/file);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::externalCoupler::shutdown() const
|
void Foam::externalFileCoupler::readDataSlave()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalFileCoupler::writeDataMaster() const
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalFileCoupler::writeDataSlave() const
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalFileCoupler::removeDataMaster() const
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalFileCoupler::removeDataSlave() const
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::externalFileCoupler::shutdown() const
|
||||||
{
|
{
|
||||||
if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_))
|
if (Pstream::master() && runState_ == MASTER && Foam::isDir(commsDir_))
|
||||||
{
|
{
|
||||||
const fileName lck(lockFile());
|
const fileName lck(lockFile());
|
||||||
|
|
||||||
Log << type() << ": lock file status=done" << endl;
|
Log << type() << ": lock file status=done" << endl;
|
||||||
OFstream os(lck);
|
std::ofstream os(lck);
|
||||||
os << "status=done\n";
|
os << "status=done\n";
|
||||||
os.flush();
|
os.flush();
|
||||||
}
|
}
|
||||||
@ -22,7 +22,7 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::externalCoupler
|
Foam::externalFileCoupler
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Encapsulates the logic for coordinating between OpenFOAM and an
|
Encapsulates the logic for coordinating between OpenFOAM and an
|
||||||
@ -57,13 +57,32 @@ Description
|
|||||||
}
|
}
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
|
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
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
|
On the slave-side:
|
||||||
|
\verbatim
|
||||||
|
wait for master
|
||||||
|
read data from master
|
||||||
|
write data for master
|
||||||
|
use master
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
externalCoupler.C
|
externalFileCoupler.C
|
||||||
|
externalFileCouplerI.H
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef externalCoupler_H
|
#ifndef externalFileCoupler_H
|
||||||
#define externalCoupler_H
|
#define externalFileCoupler_H
|
||||||
|
|
||||||
#include "fileName.H"
|
#include "fileName.H"
|
||||||
#include "dictionary.H"
|
#include "dictionary.H"
|
||||||
@ -74,11 +93,15 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class externalCoupler Declaration
|
Class externalFileCoupler Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class externalCoupler
|
class externalFileCoupler
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Public data types
|
||||||
|
|
||||||
//- The run state (ie, who is currently in charge)
|
//- The run state (ie, who is currently in charge)
|
||||||
enum runState
|
enum runState
|
||||||
{
|
{
|
||||||
@ -89,6 +112,8 @@ class externalCoupler
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
//- The current run (and initialization) state
|
//- The current run (and initialization) state
|
||||||
@ -103,7 +128,7 @@ class externalCoupler
|
|||||||
//- Timeout [s] while waiting for the external application
|
//- Timeout [s] while waiting for the external application
|
||||||
unsigned timeOut_;
|
unsigned timeOut_;
|
||||||
|
|
||||||
//- Flag to indicate values are initialized by external application
|
//- Flag to indicate values are initialized by external program
|
||||||
bool slaveFirst_;
|
bool slaveFirst_;
|
||||||
|
|
||||||
//- Local logging/verbosity flag
|
//- Local logging/verbosity flag
|
||||||
@ -112,22 +137,17 @@ class externalCoupler
|
|||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- Return the file path to the base communications directory
|
//- Disallow default bitwise copy construct
|
||||||
const fileName& baseDir() const;
|
externalFileCoupler(const externalFileCoupler&) = delete;
|
||||||
|
|
||||||
//- Return the file path to the lock file
|
|
||||||
fileName lockFile() const;
|
|
||||||
|
|
||||||
//- Disallow default bitwise copy construc
|
|
||||||
externalCoupler(const externalCoupler&) = delete;
|
|
||||||
|
|
||||||
//- Disallow default bitwise assignmen
|
//- Disallow default bitwise assignmen
|
||||||
void operator=(const externalCoupler&) = delete;
|
void operator=(const externalFileCoupler&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("externalCoupler");
|
TypeName("externalFileCoupler");
|
||||||
|
|
||||||
|
|
||||||
// Static data members
|
// Static data members
|
||||||
@ -138,48 +158,98 @@ public:
|
|||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct null using standard defaults
|
//- Construct using standard defaults.
|
||||||
externalCoupler();
|
// Does not create communications directory.
|
||||||
|
externalFileCoupler();
|
||||||
|
|
||||||
|
//- Construct with specified communications directory.
|
||||||
|
// Creates the communications directory upon construction.
|
||||||
|
externalFileCoupler(const fileName& commsDir);
|
||||||
|
|
||||||
//- Construct from dictionary
|
//- Construct from dictionary
|
||||||
externalCoupler(const dictionary& dict);
|
// Creates the communications directory upon construction.
|
||||||
|
externalFileCoupler(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~externalCoupler();
|
virtual ~externalFileCoupler();
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
// Access
|
// Initialization
|
||||||
|
|
||||||
//- True if state has been initialized
|
//- True if state has been initialized
|
||||||
bool initialized() const;
|
inline bool initialized() const;
|
||||||
|
|
||||||
//- External application provides initial values
|
//- External application provides initial values
|
||||||
bool slaveFirst() const;
|
inline bool slaveFirst() const;
|
||||||
|
|
||||||
|
|
||||||
|
// File locations
|
||||||
|
|
||||||
|
//- Return the file path to the base communications directory
|
||||||
|
inline const fileName& commDirectory() const;
|
||||||
|
|
||||||
|
//- Return the file path in the communications directory
|
||||||
|
inline fileName resolveFile(const word& file) const;
|
||||||
|
|
||||||
|
//- Return the file path to the lock file
|
||||||
|
inline fileName lockFile() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
|
||||||
|
//- Read communication settings from dictionary
|
||||||
|
bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
|
||||||
|
// Handshaking
|
||||||
|
|
||||||
//- Create lock file to indicate that OpenFOAM is in charge
|
//- Create lock file to indicate that OpenFOAM is in charge
|
||||||
// Optionally wait for master as well.
|
// Optionally wait for master to complete as well.
|
||||||
void useMaster(const bool wait=false) const;
|
void useMaster(const bool wait=false) const;
|
||||||
|
|
||||||
//- Wait for indication that OpenFOAM has supplied output.
|
//- Remove lock file to indicate that the external program is in charge
|
||||||
// This is when the lock file disappears, or it exists but with
|
// Optionally wait for slave to complete as well.
|
||||||
|
void 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.
|
// "status=done" content.
|
||||||
// \return False if lock file contains "status=done"
|
// \return False if lock file contains "status=done"
|
||||||
bool waitForMaster() const;
|
bool waitForMaster() const;
|
||||||
|
|
||||||
//- Remove lock file to indicate that the external program is in charge
|
//- Wait for slave to complete.
|
||||||
// Optionally wait for slave as well.
|
|
||||||
void useSlave(const bool wait=false) const;
|
|
||||||
|
|
||||||
//- Wait for indication that the external program has supplied input.
|
|
||||||
// This is when the lock file appears.
|
// This is when the lock file appears.
|
||||||
// \return False if lock file contains "status=done"
|
// \return False if lock file contains "status=done"
|
||||||
bool waitForSlave() const;
|
bool waitForSlave() const;
|
||||||
|
|
||||||
//- Return the file path in the communications directory
|
|
||||||
fileName resolveFile(const word& file) const;
|
// File creation, removal
|
||||||
|
|
||||||
|
//- Read data files on master (OpenFOAM).
|
||||||
|
// These data files are normally created by the slave.
|
||||||
|
virtual void readDataMaster();
|
||||||
|
|
||||||
|
//- Read data files on slave (external program).
|
||||||
|
// These data files are normally created by the master.
|
||||||
|
virtual void readDataSlave();
|
||||||
|
|
||||||
|
|
||||||
|
//- Write data files from master (OpenFOAM)
|
||||||
|
virtual void writeDataMaster() const;
|
||||||
|
|
||||||
|
//- Write data files from slave (external program)
|
||||||
|
virtual void writeDataSlave() const;
|
||||||
|
|
||||||
|
|
||||||
|
//- Remove data files written by master (OpenFOAM)
|
||||||
|
virtual void removeDataMaster() const;
|
||||||
|
|
||||||
|
//- Remove data files written by slave (external program)
|
||||||
|
virtual void removeDataSlave() const;
|
||||||
|
|
||||||
//- Generate status=done in lock (only when run-state = master)
|
//- Generate status=done in lock (only when run-state = master)
|
||||||
void shutdown() const;
|
void shutdown() const;
|
||||||
@ -188,11 +258,6 @@ public:
|
|||||||
void removeDirectory() const;
|
void removeDirectory() const;
|
||||||
|
|
||||||
|
|
||||||
// Edit
|
|
||||||
|
|
||||||
//- Read communication settings from dictionary
|
|
||||||
bool readDict(const dictionary& dict);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -202,6 +267,10 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "externalFileCouplerI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / 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/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline bool Foam::externalFileCoupler::initialized() const
|
||||||
|
{
|
||||||
|
return runState_ != NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::externalFileCoupler::slaveFirst() const
|
||||||
|
{
|
||||||
|
return slaveFirst_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fileName& Foam::externalFileCoupler::commDirectory() const
|
||||||
|
{
|
||||||
|
return commsDir_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::fileName Foam::externalFileCoupler::resolveFile
|
||||||
|
(
|
||||||
|
const word& file
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
return fileName(commDirectory()/file);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::fileName Foam::externalFileCoupler::lockFile() const
|
||||||
|
{
|
||||||
|
return resolveFile(lockName + ".lock");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -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:";
|
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 * * * * * * * * * * * //
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::fileName Foam::functionObjects::externalCoupled::baseDir() const
|
|
||||||
{
|
|
||||||
fileName result(commsDir_);
|
|
||||||
result.clean();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::fileName Foam::functionObjects::externalCoupled::groupDir
|
Foam::fileName Foam::functionObjects::externalCoupled::groupDir
|
||||||
(
|
(
|
||||||
const fileName& commsDir,
|
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
|
void Foam::functionObjects::externalCoupled::readColumns
|
||||||
(
|
(
|
||||||
const label nRows,
|
const label nRows,
|
||||||
@ -592,155 +404,9 @@ void Foam::functionObjects::externalCoupled::checkOrder
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::functionObjects::externalCoupled::readData()
|
void Foam::functionObjects::externalCoupled::initCoupling()
|
||||||
{
|
{
|
||||||
forAll(regionGroupNames_, regioni)
|
if (initialisedCoupling_)
|
||||||
{
|
|
||||||
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_)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -769,7 +435,7 @@ void Foam::functionObjects::externalCoupled::initialise()
|
|||||||
bool exists = false;
|
bool exists = false;
|
||||||
if (Pstream::master())
|
if (Pstream::master())
|
||||||
{
|
{
|
||||||
fileName dir(groupDir(commsDir_, compName, groupName));
|
fileName dir(groupDir(commDirectory(), compName, groupName));
|
||||||
|
|
||||||
exists =
|
exists =
|
||||||
isFile(dir/"patchPoints")
|
isFile(dir/"patchPoints")
|
||||||
@ -778,21 +444,21 @@ void Foam::functionObjects::externalCoupled::initialise()
|
|||||||
|
|
||||||
if (!returnReduce(exists, orOp<bool>()))
|
if (!returnReduce(exists, orOp<bool>()))
|
||||||
{
|
{
|
||||||
writeGeometry(meshes, commsDir_, groupName);
|
writeGeometry(meshes, commDirectory(), groupName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slaveFirst_)
|
if (slaveFirst())
|
||||||
{
|
{
|
||||||
// Wait for initial data to be made available
|
// Wait for initial data to be made available
|
||||||
waitForSlave();
|
waitForSlave();
|
||||||
|
|
||||||
// Read data passed back from external source
|
// Read data passed back from external source
|
||||||
readData();
|
readDataMaster();
|
||||||
}
|
}
|
||||||
|
|
||||||
initialised_ = true;
|
initialisedCoupling_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -806,18 +472,13 @@ Foam::functionObjects::externalCoupled::externalCoupled
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
functionObject(name),
|
functionObject(name),
|
||||||
|
externalFileCoupler(),
|
||||||
time_(runTime),
|
time_(runTime),
|
||||||
stateEnd_(REMOVE),
|
initialisedCoupling_(false)
|
||||||
initialised_(false)
|
|
||||||
{
|
{
|
||||||
read(dict);
|
read(dict);
|
||||||
|
|
||||||
if (Pstream::master())
|
if (!slaveFirst())
|
||||||
{
|
|
||||||
mkDir(baseDir());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!slaveFirst_)
|
|
||||||
{
|
{
|
||||||
useMaster();
|
useMaster();
|
||||||
}
|
}
|
||||||
@ -827,22 +488,20 @@ Foam::functionObjects::externalCoupled::externalCoupled
|
|||||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::functionObjects::externalCoupled::~externalCoupled()
|
Foam::functionObjects::externalCoupled::~externalCoupled()
|
||||||
{
|
{}
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool Foam::functionObjects::externalCoupled::execute()
|
bool Foam::functionObjects::externalCoupled::execute()
|
||||||
{
|
{
|
||||||
if (!initialised_ || time_.timeIndex() % calcFrequency_ == 0)
|
if (!initialisedCoupling_ || time_.timeIndex() % calcFrequency_ == 0)
|
||||||
{
|
{
|
||||||
// Initialise the coupling
|
// Initialise the coupling
|
||||||
initialise();
|
initCoupling();
|
||||||
|
|
||||||
// Write data for external source
|
// Write data for external source
|
||||||
writeData();
|
writeDataMaster();
|
||||||
|
|
||||||
// Signal external source to execute (by removing lock file)
|
// Signal external source to execute (by removing lock file)
|
||||||
// - Wait for slave to provide data
|
// - Wait for slave to provide data
|
||||||
@ -855,7 +514,7 @@ bool Foam::functionObjects::externalCoupled::execute()
|
|||||||
removeDataMaster();
|
removeDataMaster();
|
||||||
|
|
||||||
// Read data passed back from external source
|
// Read data passed back from external source
|
||||||
readData();
|
readDataMaster();
|
||||||
|
|
||||||
// Signal external source to wait (by creating the lock file)
|
// Signal external source to wait (by creating the lock file)
|
||||||
useMaster();
|
useMaster();
|
||||||
@ -876,7 +535,7 @@ bool Foam::functionObjects::externalCoupled::end()
|
|||||||
// Remove old data files
|
// Remove old data files
|
||||||
removeDataMaster();
|
removeDataMaster();
|
||||||
removeDataSlave();
|
removeDataSlave();
|
||||||
cleanup();
|
shutdown();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -885,33 +544,10 @@ bool Foam::functionObjects::externalCoupled::end()
|
|||||||
bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
||||||
{
|
{
|
||||||
functionObject::read(dict);
|
functionObject::read(dict);
|
||||||
|
externalFileCoupler::readDict(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);
|
|
||||||
}
|
|
||||||
|
|
||||||
calcFrequency_ = dict.lookupOrDefault("calcFrequency", 1);
|
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)
|
// Get names of all fvMeshes (and derived types)
|
||||||
wordList allRegionNames(time_.lookupClass<fvMesh>().sortedToc());
|
wordList allRegionNames(time_.lookupClass<fvMesh>().sortedToc());
|
||||||
|
|
||||||
@ -1013,7 +649,8 @@ bool Foam::functionObjects::externalCoupled::read(const dictionary& dict)
|
|||||||
label groupi = groups[i];
|
label groupi = groups[i];
|
||||||
const wordRe& groupName = groupNames_[groupi];
|
const wordRe& groupName = groupNames_[groupi];
|
||||||
|
|
||||||
fileName dir(groupDir(commsDir_, compName, groupName));
|
fileName dir(groupDir(commDirectory(), compName, groupName));
|
||||||
|
|
||||||
if (!isDir(dir))
|
if (!isDir(dir))
|
||||||
{
|
{
|
||||||
Log << type() << ": creating communications directory "
|
Log << type() << ": creating communications directory "
|
||||||
@ -1028,6 +665,218 @@ 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];
|
||||||
|
|
||||||
|
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::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];
|
||||||
|
|
||||||
|
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::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(commDirectory(), compName, groupName)
|
||||||
|
/ fieldName + ".out"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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(commDirectory(), compName, groupName)
|
||||||
|
/ fieldName + ".in"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Foam::functionObjects::externalCoupled::write()
|
bool Foam::functionObjects::externalCoupled::write()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@ -42,7 +42,7 @@ Description
|
|||||||
|
|
||||||
where the actual entries depend on the bc type:
|
where the actual entries depend on the bc type:
|
||||||
- mixed: value, snGrad, refValue, refGrad, valueFraction
|
- mixed: value, snGrad, refValue, refGrad, valueFraction
|
||||||
- externalCoupledMixed: output of writeData
|
- externalCoupledMixed: output of writeDataMaster
|
||||||
- other: value, snGrad
|
- other: value, snGrad
|
||||||
|
|
||||||
These text files are located in a user specified communications directory
|
These text files are located in a user specified communications directory
|
||||||
@ -146,6 +146,7 @@ SourceFiles
|
|||||||
#define functionObjects_externalCoupled_H
|
#define functionObjects_externalCoupled_H
|
||||||
|
|
||||||
#include "functionObject.H"
|
#include "functionObject.H"
|
||||||
|
#include "externalFileCoupler.H"
|
||||||
#include "DynamicList.H"
|
#include "DynamicList.H"
|
||||||
#include "wordReList.H"
|
#include "wordReList.H"
|
||||||
#include "scalarField.H"
|
#include "scalarField.H"
|
||||||
@ -171,7 +172,8 @@ namespace functionObjects
|
|||||||
|
|
||||||
class externalCoupled
|
class externalCoupled
|
||||||
:
|
:
|
||||||
public functionObject
|
public functionObject,
|
||||||
|
public externalFileCoupler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -190,30 +192,14 @@ private:
|
|||||||
//- State end names (NB, only selectable values itemized)
|
//- State end names (NB, only selectable values itemized)
|
||||||
static const Enum<stateEnd> stateEndNames_;
|
static const Enum<stateEnd> stateEndNames_;
|
||||||
|
|
||||||
|
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
//- Reference to the time database
|
//- Reference to the time database
|
||||||
const Time& time_;
|
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
|
//- Calculation frequency
|
||||||
label calcFrequency_;
|
label calcFrequency_;
|
||||||
|
|
||||||
//- Flag to indicate values are initialised by external application
|
|
||||||
bool slaveFirst_;
|
|
||||||
|
|
||||||
//- Lockfile state on termination
|
|
||||||
mutable stateEnd stateEnd_;
|
|
||||||
|
|
||||||
//- Names of (composite) regions
|
//- Names of (composite) regions
|
||||||
DynamicList<word> regionGroupNames_;
|
DynamicList<word> regionGroupNames_;
|
||||||
|
|
||||||
@ -232,8 +218,8 @@ private:
|
|||||||
// Per group the names of the fields to write
|
// Per group the names of the fields to write
|
||||||
DynamicList<wordList> groupWriteFields_;
|
DynamicList<wordList> groupWriteFields_;
|
||||||
|
|
||||||
//- Initialised flag
|
//- Initialised coupling
|
||||||
bool initialised_;
|
bool initialisedCoupling_;
|
||||||
|
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
@ -246,32 +232,6 @@ private:
|
|||||||
const wordRe& groupName
|
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
|
//- Read data for a single region, single field
|
||||||
template<class Type>
|
template<class Type>
|
||||||
@ -281,8 +241,6 @@ private:
|
|||||||
const wordRe& groupName,
|
const wordRe& groupName,
|
||||||
const word& fieldName
|
const word& fieldName
|
||||||
);
|
);
|
||||||
//- Read data for all regions, all fields
|
|
||||||
void readData();
|
|
||||||
|
|
||||||
//- Write data for a single region, single field
|
//- Write data for a single region, single field
|
||||||
template<class Type>
|
template<class Type>
|
||||||
@ -293,10 +251,7 @@ private:
|
|||||||
const word& fieldName
|
const word& fieldName
|
||||||
) const;
|
) const;
|
||||||
|
|
||||||
//- Write data for all regions, all fields
|
void initCoupling();
|
||||||
void writeData() const;
|
|
||||||
|
|
||||||
void initialise();
|
|
||||||
|
|
||||||
//- Read (and distribute) scalar columns from stream. Every processor
|
//- Read (and distribute) scalar columns from stream. Every processor
|
||||||
// gets nRows (= patch size) of these. Note: could make its argument
|
// gets nRows (= patch size) of these. Note: could make its argument
|
||||||
@ -339,12 +294,12 @@ public:
|
|||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("externalCoupled");
|
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
|
//- Name of patch key, e.g. '// Patch:' when looking for start of patch data
|
||||||
static string patchKey;
|
static string patchKey;
|
||||||
|
|
||||||
|
//- Inherited variable for logging
|
||||||
|
using functionObject::log;
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
@ -378,6 +333,21 @@ public:
|
|||||||
virtual bool write();
|
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
|
// Other
|
||||||
|
|
||||||
//- Create single name by appending words (in sorted order),
|
//- Create single name by appending words (in sorted order),
|
||||||
|
|||||||
@ -62,7 +62,7 @@ bool Foam::functionObjects::externalCoupled::readData
|
|||||||
{
|
{
|
||||||
const fileName transferFile
|
const fileName transferFile
|
||||||
(
|
(
|
||||||
groupDir(commsDir_, compositeName(regionNames), groupName)
|
groupDir(commDirectory(), compositeName(regionNames), groupName)
|
||||||
/ fieldName + ".in"
|
/ fieldName + ".in"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ bool Foam::functionObjects::externalCoupled::readData
|
|||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
initialised_ = true;
|
initialisedCoupling_ = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,7 +357,7 @@ bool Foam::functionObjects::externalCoupled::writeData
|
|||||||
{
|
{
|
||||||
const fileName transferFile
|
const fileName transferFile
|
||||||
(
|
(
|
||||||
groupDir(commsDir_, compositeName(regionNames), groupName)
|
groupDir(commDirectory(), compositeName(regionNames), groupName)
|
||||||
/ fieldName + ".out"
|
/ fieldName + ".out"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
externalCoupler.C
|
|
||||||
|
|
||||||
lumpedPointMovement.C
|
lumpedPointMovement.C
|
||||||
lumpedPointMovementWriter.C
|
lumpedPointMovementWriter.C
|
||||||
lumpedPointState.C
|
lumpedPointState.C
|
||||||
|
|||||||
@ -50,7 +50,7 @@ SourceFiles
|
|||||||
#include "IOobject.H"
|
#include "IOobject.H"
|
||||||
#include "tmp.H"
|
#include "tmp.H"
|
||||||
#include "faceZoneMeshFwd.H"
|
#include "faceZoneMeshFwd.H"
|
||||||
#include "externalCoupler.H"
|
#include "externalFileCoupler.H"
|
||||||
#include "lumpedPointState.H"
|
#include "lumpedPointState.H"
|
||||||
#include "boundBox.H"
|
#include "boundBox.H"
|
||||||
#include "Enum.H"
|
#include "Enum.H"
|
||||||
@ -120,7 +120,7 @@ private:
|
|||||||
dictionary forcesDict_;
|
dictionary forcesDict_;
|
||||||
|
|
||||||
//- Communication control
|
//- Communication control
|
||||||
externalCoupler coupler_;
|
externalFileCoupler coupler_;
|
||||||
|
|
||||||
//- File io
|
//- File io
|
||||||
word inputName_;
|
word inputName_;
|
||||||
@ -223,10 +223,10 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
//- Communication control
|
//- Communication control
|
||||||
inline const externalCoupler& coupler() const;
|
inline const externalFileCoupler& coupler() const;
|
||||||
|
|
||||||
//- Communication control
|
//- Communication control
|
||||||
inline externalCoupler& coupler();
|
inline externalFileCoupler& coupler();
|
||||||
|
|
||||||
//- The initial state (positions/rotations)
|
//- The initial state (positions/rotations)
|
||||||
inline const lumpedPointState& state0() const;
|
inline const lumpedPointState& state0() const;
|
||||||
|
|||||||
@ -83,13 +83,14 @@ Foam::lumpedPointMovement::threshold(const point& position) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const Foam::externalCoupler& Foam::lumpedPointMovement::coupler() const
|
inline const Foam::externalFileCoupler&
|
||||||
|
Foam::lumpedPointMovement::coupler() const
|
||||||
{
|
{
|
||||||
return coupler_;
|
return coupler_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline Foam::externalCoupler& Foam::lumpedPointMovement::coupler()
|
inline Foam::externalFileCoupler& Foam::lumpedPointMovement::coupler()
|
||||||
{
|
{
|
||||||
return coupler_;
|
return coupler_;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,9 @@ cd ${0%/*} || exit 1 # Run from this directory
|
|||||||
|
|
||||||
./Allrun.pre
|
./Allrun.pre
|
||||||
|
|
||||||
|
# Remove lock file on interrupt
|
||||||
|
trap '\rm -f comms/OpenFOAM.lock 2>/dev/null' INT
|
||||||
|
|
||||||
#-- Run on single processor
|
#-- Run on single processor
|
||||||
#runApplication $(getApplication) &
|
#runApplication $(getApplication) &
|
||||||
# Simulated external solver
|
# Simulated external solver
|
||||||
|
|||||||
@ -14,12 +14,11 @@ set -u
|
|||||||
echo "Executing dummy external solver"
|
echo "Executing dummy external solver"
|
||||||
|
|
||||||
commsDir="comms"
|
commsDir="comms"
|
||||||
regionGroupName="heater_topAir"
|
patchDir="heater_topAir/coupleGroup"
|
||||||
patchGroupName="coupleGroup"
|
|
||||||
fieldName="T"
|
fieldName="T"
|
||||||
|
|
||||||
lockFile="${commsDir}/OpenFOAM.lock"
|
lockFile="${commsDir}/OpenFOAM.lock"
|
||||||
dataFile="${commsDir}/${regionGroupName}/${patchGroupName}/${fieldName}"
|
dataFile="${commsDir}/${patchDir}/${fieldName}"
|
||||||
waitSec=5
|
waitSec=5
|
||||||
timeOut=100
|
timeOut=100
|
||||||
nSteps=1000 # maximum number of time steps. Note: should be more than
|
nSteps=1000 # maximum number of time steps. Note: should be more than
|
||||||
@ -27,7 +26,6 @@ nSteps=1000 # maximum number of time steps. Note: should be more than
|
|||||||
refGrad=0
|
refGrad=0
|
||||||
valueFraction=1
|
valueFraction=1
|
||||||
|
|
||||||
|
|
||||||
# Remove any old junk
|
# Remove any old junk
|
||||||
\rm -f $lockFile 2>/dev/null
|
\rm -f $lockFile 2>/dev/null
|
||||||
|
|
||||||
@ -36,36 +34,53 @@ log()
|
|||||||
echo "External: $@"
|
echo "External: $@"
|
||||||
}
|
}
|
||||||
|
|
||||||
init()
|
|
||||||
|
# Create lock file to pass control to OpenFOAM
|
||||||
|
useMaster()
|
||||||
{
|
{
|
||||||
log "init - creating ${dataFile}.in"
|
log "creating lock file '${lockFile}'"
|
||||||
|
echo "status=openfoam" >| ${lockFile}
|
||||||
# Hard-coded for patch of size 8 (heater/minY)
|
|
||||||
n1=8
|
|
||||||
refValue1=500
|
|
||||||
touch "${dataFile}.in"
|
|
||||||
log "init - adding $n1 data elements with refValue $refValue1"
|
|
||||||
for i in $(seq 1 $n1); do
|
|
||||||
echo "$refValue1 $refGrad $valueFraction" >> "${dataFile}.in"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Hard-coded for patch of size 40 (topAir/minX)
|
|
||||||
n2=40
|
|
||||||
refValue2=300
|
|
||||||
log "init - adding $n2 data elements with refValue $refValue2"
|
|
||||||
for i in $(seq 1 $n2); do
|
|
||||||
echo "$refValue2 $refGrad $valueFraction" >> "${dataFile}.in"
|
|
||||||
done
|
|
||||||
|
|
||||||
# Create lock file to pass control to OpenFOAM
|
|
||||||
touch ${lockFile}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# create the comms directory
|
init()
|
||||||
mkdir -p ${commsDir}/${regionGroupName}/${patchGroupName}
|
{
|
||||||
|
log "init - creating ${dataFile}.in"
|
||||||
|
cat /dev/null >| "${dataFile}.in"
|
||||||
|
|
||||||
# Tutorial case uses 'initByExternalOption', so we must provide initial values
|
# Hard-coded for patch of size 8 (heater/minY)
|
||||||
|
local n1=8
|
||||||
|
local refValue1=500
|
||||||
|
|
||||||
|
log "init - adding $n1 data elements with refValue $refValue1"
|
||||||
|
for i in $(seq 1 $n1)
|
||||||
|
do
|
||||||
|
echo "$refValue1 $refGrad $valueFraction"
|
||||||
|
done >> "${dataFile}.in"
|
||||||
|
|
||||||
|
# Hard-coded for patch of size 40 (topAir/minX)
|
||||||
|
local n2=40
|
||||||
|
local refValue2=300
|
||||||
|
log "init - adding $n2 data elements with refValue $refValue2"
|
||||||
|
for i in $(seq 1 $n2)
|
||||||
|
do
|
||||||
|
echo "$refValue2 $refGrad $valueFraction"
|
||||||
|
done >> "${dataFile}.in"
|
||||||
|
|
||||||
|
# Verify line count?
|
||||||
|
# log "init ($(wc -l ${dataFile}.in))"
|
||||||
|
|
||||||
|
# Give time for T.in file to flush
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
useMaster
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Create the comms directory
|
||||||
|
mkdir -p ${commsDir}/${patchDir}
|
||||||
|
|
||||||
|
# Tutorial case uses 'initByExternal' option, so we must provide initial values
|
||||||
init
|
init
|
||||||
|
|
||||||
|
|
||||||
@ -108,8 +123,7 @@ do
|
|||||||
awk '{if( $1 != "#" ){print $1+1 " 0 1"}}' \
|
awk '{if( $1 != "#" ){print $1+1 " 0 1"}}' \
|
||||||
${dataFile}.out >| ${dataFile}.in
|
${dataFile}.out >| ${dataFile}.in
|
||||||
|
|
||||||
log "creating lock file '${lockFile}'"
|
useMaster
|
||||||
touch ${lockFile}
|
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|||||||
@ -14,9 +14,6 @@ externalCoupled
|
|||||||
// Does external process start first
|
// Does external process start first
|
||||||
initByExternal true;
|
initByExternal true;
|
||||||
|
|
||||||
// Cleanup behaviour on termination (remove|done)
|
|
||||||
stateEnd done;
|
|
||||||
|
|
||||||
// Additional output
|
// Additional output
|
||||||
log true;
|
log true;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user