Merge branch 'master' into cvm

This commit is contained in:
graham
2010-11-17 17:25:43 +00:00
87 changed files with 1015 additions and 494 deletions

View File

@ -12,9 +12,9 @@ unset COMP_FLAGS LINK_FLAGS
if [ -f /usr/include/sys/inotify.h -a "${1%USE_STAT}" = "$1" ]
then
echo "Found <sys/inotify.h> -- using inotify for file monitoring."
unset COMP_FLAGS
export COMP_FLAGS="-DFOAM_USE_INOTIFY"
else
export COMP_FLAGS="-DFOAM_USE_STAT"
unset COMP_FLAGS
fi

View File

@ -24,38 +24,25 @@ License
\*---------------------------------------------------------------------------*/
#include "clockTime.H"
#include "scalar.H"
#include <sys/time.h>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void clockTime::getTime(struct timeval& t)
void Foam::clockTime::getTime(timeType& t)
{
gettimeofday(&t, NULL);
gettimeofday(&t, 0);
}
double clockTime::timeDifference
(
const struct timeval& start,
const struct timeval& end
)
double Foam::clockTime::timeDifference(const timeType& beg, const timeType& end)
{
return end.tv_sec - start.tv_sec + 1E-6*(end.tv_usec - start.tv_usec);
return end.tv_sec - beg.tv_sec + 1E-6*(end.tv_usec - beg.tv_usec);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
clockTime::clockTime()
Foam::clockTime::clockTime()
{
getTime(startTime_);
lastTime_ = startTime_;
@ -65,14 +52,14 @@ clockTime::clockTime()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
double clockTime::elapsedTime() const
double Foam::clockTime::elapsedTime() const
{
getTime(newTime_);
return timeDifference(startTime_, newTime_);
}
double clockTime::timeIncrement() const
double Foam::clockTime::timeIncrement() const
{
lastTime_ = newTime_;
getTime(newTime_);
@ -80,8 +67,4 @@ double clockTime::timeIncrement() const
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -44,43 +44,45 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class clockTime Declaration
Class clockTime Declaration
\*---------------------------------------------------------------------------*/
class clockTime
{
// Private data
struct timeval startTime_;
mutable struct timeval lastTime_;
mutable struct timeval newTime_;
//- Time structure used
typedef struct timeval timeType;
static void getTime(struct timeval& t);
timeType startTime_;
static double timeDifference
(
const struct timeval& start,
const struct timeval& end
);
mutable timeType lastTime_;
mutable timeType newTime_;
// Private Member Functions
//- Retrieve the current time values from the system
static void getTime(timeType&);
//- Difference between two times
static double timeDifference(const timeType& beg, const timeType& end);
public:
// Constructors
//- Construct from components
//- Construct with the current clock time
clockTime();
// Member Functions
// Access
//- Return time (in seconds) from the start
double elapsedTime() const;
//- Returns CPU time from start of run
double elapsedTime() const;
//- Returns CPU time from last call of clockTimeIncrement()
double timeIncrement() const;
//- Return time (in seconds) since last call to timeIncrement()
double timeIncrement() const;
};

View File

@ -21,45 +21,32 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
Starts timing CPU usage and return elapsed time from start.
\*---------------------------------------------------------------------------*/
#include "cpuTime.H"
#include <unistd.h>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * Static Members * * * * * * * * * * * * * * //
long cpuTime::Hz_(sysconf(_SC_CLK_TCK));
const long Foam::cpuTime::Hz_(sysconf(_SC_CLK_TCK));
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void cpuTime::getTime(struct tms& t)
void Foam::cpuTime::getTime(timeType& t)
{
times(&t);
}
double cpuTime::timeDifference
(
const struct tms& start,
const struct tms& end
)
double Foam::cpuTime::timeDifference(const timeType& beg, const timeType& end)
{
return
(
double
(
(end.tms_utime + end.tms_stime)
- (start.tms_utime + start.tms_stime)
- (beg.tms_utime + beg.tms_stime)
)/Hz_
);
}
@ -67,7 +54,7 @@ double cpuTime::timeDifference
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
cpuTime::cpuTime()
Foam::cpuTime::cpuTime()
{
getTime(startTime_);
lastTime_ = startTime_;
@ -77,14 +64,14 @@ cpuTime::cpuTime()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
double cpuTime::elapsedCpuTime() const
double Foam::cpuTime::elapsedCpuTime() const
{
getTime(newTime_);
return timeDifference(startTime_, newTime_);
}
double cpuTime::cpuTimeIncrement() const
double Foam::cpuTime::cpuTimeIncrement() const
{
lastTime_ = newTime_;
getTime(newTime_);
@ -92,8 +79,4 @@ double cpuTime::cpuTimeIncrement() const
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -54,38 +54,41 @@ class cpuTime
{
// Private data
static long Hz_;
//- Time structure used
typedef struct tms timeType;
struct tms startTime_;
mutable struct tms lastTime_;
mutable struct tms newTime_;
//- Clock-ticks per second
static const long Hz_;
static void getTime(struct tms& t);
//- The start time
timeType startTime_;
mutable timeType lastTime_;
mutable timeType newTime_;
static double timeDifference
(
const struct tms& start,
const struct tms& end
);
// Private Member Functions
//- Retrieve the current time values from the system
static void getTime(timeType&);
//- Difference between two times
static double timeDifference(const timeType& beg, const timeType& end);
public:
// Constructors
//- Construct from components
//- Construct with the current clock time
cpuTime();
// Member Functions
// Access
//- Return CPU time (in seconds) from the start
double elapsedCpuTime() const;
//- Returns CPU time from start of run
double elapsedCpuTime() const;
//- Returns CPU time from last call of cpuTimeIncrement()
double cpuTimeIncrement() const;
//- Return CPU time (in seconds) since last call to cpuTimeIncrement()
double cpuTimeIncrement() const;
};

View File

@ -32,17 +32,17 @@ Class
#include "PackedList.H"
#include "PstreamReduceOps.H"
#include "OSspecific.H"
#include "regIOobject.H" // for fileModificationSkew symbol
#ifdef FOAM_USE_STAT
# include "OSspecific.H"
# include "regIOobject.H" // for fileModificationSkew symbol
#else
#ifdef FOAM_USE_INOTIFY
# include <sys/inotify.h>
# include <sys/ioctl.h>
# include <errno.h>
# define EVENT_SIZE ( sizeof (struct inotify_event) )
# define EVENT_LEN (EVENT_SIZE + 16)
# define EVENT_BUF_LEN ( 1024 * EVENT_LEN )
#else
# include "OSspecific.H"
#endif
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -111,78 +111,77 @@ namespace Foam
{
public:
#ifdef FOAM_USE_STAT
//- From watch descriptor to modified time
DynamicList<time_t> lastMod_;
const bool useInotify_;
//- initialize HashTable size
inline fileMonitorWatcher(const label sz = 20)
:
lastMod_(sz)
{}
// For inotify
inline bool addWatch(const label watchFd, const fileName& fName)
{
if (watchFd < lastMod_.size() && lastMod_[watchFd] != 0)
{
// Reuse of watchFd : should have lastMod set to 0.
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Problem adding watch " << watchFd
<< " to file " << fName
<< abort(FatalError);
}
//- File descriptor for the inotify instance
int inotifyFd_;
lastMod_(watchFd) = lastModified(fName);
return true;
}
//- Current watchIDs and corresponding directory id
DynamicList<label> dirWatches_;
DynamicList<fileName> dirFiles_;
inline bool removeWatch(const label watchFd)
{
lastMod_[watchFd] = 0;
return true;
}
// For stat
//- From watch descriptor to modified time
DynamicList<time_t> lastMod_;
#else
//- File descriptor for the inotify instance
int inotifyFd_;
//- Current watchIDs and corresponding directory id
DynamicList<label> dirWatches_;
DynamicList<fileName> dirFiles_;
//- initialise inotify
inline fileMonitorWatcher(const label sz = 20)
inline fileMonitorWatcher(const bool useInotify, const label sz = 20)
:
inotifyFd_(inotify_init()),
dirWatches_(sz),
dirFiles_(sz)
useInotify_(useInotify)
{
if (inotifyFd_ < 0)
if (useInotify_)
{
static bool hasWarned = false;
if (!hasWarned)
#ifdef FOAM_USE_INOTIFY
inotifyFd_ = inotify_init();
dirWatches_.setCapacity(sz);
dirFiles_.setCapacity(sz);
if (inotifyFd_ < 0)
{
hasWarned = true;
WarningIn("fileMonitorWatcher(const label)")
<< "Failed allocating an inotify descriptor : "
<< string(strerror(errno)) << endl
<< " Please increase the number of allowable "
<< "inotify instances" << endl
<< " (/proc/sys/fs/inotify/max_user_instances"
<< " on Linux)" << endl
<< " , switch off runTimeModifiable." << endl
<< " or compile this file with FOAM_USE_STAT to use"
<< " time stamps instead of inotify." << endl
<< " Continuing without additional file monitoring."
<< endl;
static bool hasWarned = false;
if (!hasWarned)
{
hasWarned = true;
WarningIn("fileMonitorWatcher(const bool, const label)")
<< "Failed allocating an inotify descriptor : "
<< string(strerror(errno)) << endl
<< " Please increase the number of allowable "
<< "inotify instances" << endl
<< " (/proc/sys/fs/inotify/max_user_instances"
<< " on Linux)" << endl
<< " , switch off runTimeModifiable." << endl
<< " or compile this file without "
<< "FOAM_USE_INOTIFY"
<< " to use time stamps instead of inotify." << endl
<< " Continuing without additional file"
<< " monitoring."
<< endl;
}
}
#else
FatalErrorIn("fileMonitorWatcher(const bool, const label)")
<< "You selected inotify but this file was compiled"
<< " without FOAM_USE_INOTIFY"
<< "Please select another fileModification test method"
<< exit(FatalError);
#endif
}
else
{
lastMod_.setCapacity(sz);
}
}
//- remove all watches
inline ~fileMonitorWatcher()
{
if (inotifyFd_ >= 0)
#ifdef FOAM_USE_INOTIFY
if (useInotify_ && inotifyFd_ >= 0)
{
forAll(dirWatches_, i)
{
@ -197,57 +196,92 @@ namespace Foam
}
}
}
#endif
}
inline bool addWatch(const label watchFd, const fileName& fName)
{
if (inotifyFd_ < 0)
if (useInotify_)
{
return false;
if (inotifyFd_ < 0)
{
return false;
}
#ifdef FOAM_USE_INOTIFY
// Add/retrieve watch on directory containing file.
// Note that fName might be non-existing in special situations
// (master-only reading for IODictionaries)
const fileName dir = fName.path();
label dirWatchID = -1;
if (isDir(dir))
{
dirWatchID = inotify_add_watch
(
inotifyFd_,
dir.c_str(),
IN_CLOSE_WRITE
);
if (dirWatchID < 0)
{
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Failed adding watch " << watchFd
<< " to directory " << fName << " due to "
<< string(strerror(errno))
<< exit(FatalError);
}
}
if (watchFd < dirWatches_.size() && dirWatches_[watchFd] != -1)
{
// Reuse of watchFd : should have dir watchID set to -1.
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Problem adding watch " << watchFd
<< " to file " << fName
<< abort(FatalError);
}
dirWatches_(watchFd) = dirWatchID;
dirFiles_(watchFd) = fName.name();
#endif
}
else
{
if (watchFd < lastMod_.size() && lastMod_[watchFd] != 0)
{
// Reuse of watchFd : should have lastMod set to 0.
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Problem adding watch " << watchFd
<< " to file " << fName
<< abort(FatalError);
}
lastMod_(watchFd) = lastModified(fName);
}
// Add/retrieve watch on directory containing file
label dirWatchID = inotify_add_watch
(
inotifyFd_,
fName.path().c_str(),
IN_CLOSE_WRITE
);
if (dirWatchID < 0)
{
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Failed adding watch " << watchFd
<< " to directory " << fName << " due to "
<< string(strerror(errno))
<< exit(FatalError);
}
if (watchFd < dirWatches_.size() && dirWatches_[watchFd] != -1)
{
// Reuse of watchFd : should have dir watchID set to -1.
FatalErrorIn("addWatch(const label, const fileName&)")
<< "Problem adding watch " << watchFd
<< " to file " << fName
<< abort(FatalError);
}
dirWatches_(watchFd) = dirWatchID;
dirFiles_(watchFd) = fName.name();
return true;
}
inline bool removeWatch(const label watchFd)
{
if (inotifyFd_ < 0)
if (useInotify_)
{
return false;
}
if (inotifyFd_ < 0)
{
return false;
}
dirWatches_[watchFd] = -1;
dirWatches_[watchFd] = -1;
}
else
{
lastMod_[watchFd] = 0;
}
return true;
}
#endif
};
//! @endcond
@ -258,131 +292,146 @@ namespace Foam
void Foam::fileMonitor::checkFiles() const
{
#ifdef FOAM_USE_STAT
forAll(watcher_->lastMod_, watchFd)
if (useInotify_)
{
time_t oldTime = watcher_->lastMod_[watchFd];
#ifdef FOAM_USE_INOTIFY
// Large buffer for lots of events
char buffer[EVENT_BUF_LEN];
if (oldTime != 0)
while (true)
{
const fileName& fName = watchFile_[watchFd];
time_t newTime = lastModified(fName);
struct timeval zeroTimeout = {0, 0};
if (newTime == 0)
//- Pre-allocated structure containing file descriptors
fd_set fdSet;
// Add notify descriptor to select fd_set
FD_ZERO(&fdSet);
FD_SET(watcher_->inotifyFd_, &fdSet);
int ready = select
(
watcher_->inotifyFd_+1, // num filedescriptors in fdSet
&fdSet, // fdSet with only inotifyFd
NULL, // No writefds
NULL, // No errorfds
&zeroTimeout // eNo timeout
);
if (ready < 0)
{
state_[watchFd] = DELETED;
FatalErrorIn("fileMonitor::updateStates()")
<< "Problem in issuing select."
<< abort(FatalError);
}
else if (FD_ISSET(watcher_->inotifyFd_, &fdSet))
{
// Read events
ssize_t nBytes = read
(
watcher_->inotifyFd_,
buffer,
EVENT_BUF_LEN
);
if (nBytes < 0)
{
FatalErrorIn("fileMonitor::updateStates(const fileName&)")
<< "read of " << watcher_->inotifyFd_
<< " failed with " << label(nBytes)
<< abort(FatalError);
}
// Go through buffer, consuming events
int i = 0;
while (i < nBytes)
{
const struct inotify_event* inotifyEvent =
reinterpret_cast<const struct inotify_event*>
(
&buffer[i]
);
//Pout<< "watchFd:" << inotifyEvent->wd << nl
// << "mask:" << inotifyEvent->mask << nl
// << endl;
//Pout<< "file:" << fileName(inotifyEvent->name) << endl;
//Pout<< "len:" << inotifyEvent->len << endl;
if
(
(inotifyEvent->mask & IN_CLOSE_WRITE)
&& inotifyEvent->len
)
{
// Search for file
forAll(watcher_->dirWatches_, i)
{
label id = watcher_->dirWatches_[i];
if
(
id == inotifyEvent->wd
&& inotifyEvent->name == watcher_->dirFiles_[i]
)
{
// Correct directory and name
state_[i] = MODIFIED;
}
}
}
i += EVENT_SIZE + inotifyEvent->len;
}
}
else
{
if (newTime > (oldTime + regIOobject::fileModificationSkew))
// No data
return;
}
}
#endif
}
else
{
forAll(watcher_->lastMod_, watchFd)
{
time_t oldTime = watcher_->lastMod_[watchFd];
if (oldTime != 0)
{
const fileName& fName = watchFile_[watchFd];
time_t newTime = lastModified(fName);
if (newTime == 0)
{
watcher_->lastMod_[watchFd] = newTime;
state_[watchFd] = MODIFIED;
state_[watchFd] = DELETED;
}
else
{
state_[watchFd] = UNMODIFIED;
}
}
}
}
#else
// Large buffer for lots of events
char buffer[EVENT_BUF_LEN];
while (true)
{
struct timeval zeroTimeout = {0, 0};
//- Pre-allocated structure containing file descriptors
fd_set fdSet;
// Add notify descriptor to select fd_set
FD_ZERO(&fdSet);
FD_SET(watcher_->inotifyFd_, &fdSet);
int ready = select
(
watcher_->inotifyFd_+1, // num filedescriptors in fdSet
&fdSet, // fdSet with only inotifyFd
NULL, // No writefds
NULL, // No errorfds
&zeroTimeout // eNo timeout
);
if (ready < 0)
{
FatalErrorIn("fileMonitor::updateStates()")
<< "Problem in issuing select."
<< abort(FatalError);
}
else if (FD_ISSET(watcher_->inotifyFd_, &fdSet))
{
// Read events
ssize_t nBytes = read(watcher_->inotifyFd_, buffer, EVENT_BUF_LEN);
if (nBytes < 0)
{
FatalErrorIn("fileMonitor::updateStates(const fileName&)")
<< "read of " << watcher_->inotifyFd_
<< " failed with " << label(nBytes)
<< abort(FatalError);
}
// Go through buffer, consuming events
int i = 0;
while (i < nBytes)
{
const struct inotify_event* inotifyEvent =
reinterpret_cast<const struct inotify_event*>
(
&buffer[i]
);
//Pout<< "watchFd:" << inotifyEvent->wd << nl
// << "mask:" << inotifyEvent->mask << nl
// << endl;
//Pout<< "file:" << fileName(inotifyEvent->name) << endl;
//Pout<< "len:" << inotifyEvent->len << endl;
if ((inotifyEvent->mask & IN_CLOSE_WRITE) && inotifyEvent->len)
{
// Search for file
forAll(watcher_->dirWatches_, i)
if (newTime > (oldTime + regIOobject::fileModificationSkew))
{
label id = watcher_->dirWatches_[i];
if
(
id == inotifyEvent->wd
&& inotifyEvent->name == watcher_->dirFiles_[i]
)
{
// Correct directory and name
state_[i] = MODIFIED;
}
watcher_->lastMod_[watchFd] = newTime;
state_[watchFd] = MODIFIED;
}
else
{
state_[watchFd] = UNMODIFIED;
}
}
i += EVENT_SIZE + inotifyEvent->len;
}
}
else
{
// No data
return;
}
}
#endif
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::fileMonitor::fileMonitor()
Foam::fileMonitor::fileMonitor(const bool useInotify)
:
useInotify_(useInotify),
state_(20),
watchFile_(20),
freeWatchFds_(2),
watcher_(new fileMonitorWatcher(20))
watcher_(new fileMonitorWatcher(useInotify_, 20))
{}
@ -394,6 +443,8 @@ Foam::fileMonitor::~fileMonitor()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Note: fName might not exist (on slaves if in master-only mode for
// regIOobject)
Foam::label Foam::fileMonitor::addWatch(const fileName& fName)
{
label watchFd;
@ -458,50 +509,97 @@ const
}
void Foam::fileMonitor::updateStates(const bool syncPar) const
void Foam::fileMonitor::updateStates
(
const bool masterOnly,
const bool syncPar
) const
{
checkFiles();
if (Pstream::master() || !masterOnly)
{
checkFiles();
}
if (syncPar)
{
PackedList<2> stats(state_.size());
forAll(state_, watchFd)
// Pack current state (might be on master only)
PackedList<2> stats(state_.size(), MODIFIED);
if (Pstream::master() || !masterOnly)
{
stats[watchFd] = static_cast<unsigned int>(state_[watchFd]);
forAll(state_, watchFd)
{
stats[watchFd] = static_cast<unsigned int>(state_[watchFd]);
}
}
// Save local state for warning message below
PackedList<2> thisProcStats(stats);
if (stats.storage().size() == 1)
// Save local state for warning message below
PackedList<2> thisProcStats;
if (!masterOnly)
{
// Optimisation valid for most cases.
reduce(stats.storage()[0], reduceFileStates());
thisProcStats = stats;
}
// Scatter or reduce to synchronise state
if (masterOnly)
{
// Scatter
if (stats.storage().size() == 1)
{
Pstream::scatter(stats.storage()[0]);
}
else
{
Pstream::listCombineScatter(stats.storage());
}
}
else
{
Pstream::listCombineGather
(
stats.storage(),
combineReduceFileStates()
);
// Reduce
if (stats.storage().size() == 1)
{
// Optimisation valid for most cases.
reduce(stats.storage()[0], reduceFileStates());
}
else
{
Pstream::listCombineGather
(
stats.storage(),
combineReduceFileStates()
);
}
}
// Update local state
forAll(state_, watchFd)
{
if (thisProcStats[watchFd] != UNMODIFIED)
if (masterOnly)
{
if (stats[watchFd] == UNMODIFIED)
// No need to check for inconsistent state. Just assign.
unsigned int stat = stats[watchFd];
state_[watchFd] = fileState(stat);
}
else
{
// Check for inconsistent state before assigning.
if (thisProcStats[watchFd] != UNMODIFIED)
{
WarningIn("fileMonitor::updateStates(const bool) const")
<< "Delaying reading " << watchFile_[watchFd]
<< " due to inconsistent "
"file time-stamps between processors"
<< endl;
}
else
{
unsigned int stat = stats[watchFd];
state_[watchFd] = fileState(stat);
if (stats[watchFd] == UNMODIFIED)
{
WarningIn("fileMonitor::updateStates(const bool) const")
<< "Delaying reading " << watchFile_[watchFd]
<< " due to inconsistent "
"file time-stamps between processors"
<< endl;
}
else
{
unsigned int stat = stats[watchFd];
state_[watchFd] = fileState(stat);
}
}
}
}
@ -511,10 +609,12 @@ void Foam::fileMonitor::updateStates(const bool syncPar) const
void Foam::fileMonitor::setUnmodified(const label watchFd)
{
#ifdef FOAM_USE_STAT
watcher_->lastMod_[watchFd] = lastModified(watchFile_[watchFd]);
#endif
state_[watchFd] = UNMODIFIED;
if (!useInotify_)
{
watcher_->lastMod_[watchFd] = lastModified(watchFile_[watchFd]);
}
}

View File

@ -28,10 +28,11 @@ Description
Checking for changes to files.
Note
The default is to use inotify (Linux specific, since 2.6.13)
The default is to use stat to get the timestamp.
Compiling with FOAM_USE_STAT (or if /usr/include/sys/inotify.h
does not exist) uses the stat function call.
Compile with FOAM_USE_INOTIFY to use the inotify
(Linux specific, since 2.6.13) framework. The problem is that inotify does
not work on nfs3 mounted directories!!
SourceFiles
fileMonitor.C
@ -78,6 +79,9 @@ public:
private:
// Private data
//- Whether to use inotify (requires -DFOAM_USE_INOTIFY, see above)
const bool useInotify_;
//- State for all watchFds
mutable DynamicList<fileState> state_;
@ -111,7 +115,7 @@ public:
// Constructors
//- Construct null
fileMonitor();
fileMonitor(const bool useInotify);
//- Destructor
@ -133,7 +137,11 @@ public:
fileState getState(const label watchFd) const;
//- Check state of all files. Updates state_.
void updateStates(const bool syncPar) const;
void updateStates
(
const bool masterOnly,
const bool syncPar
) const;
//- Reset state (e.g. after having read it) using handle
void setUnmodified(const label watchFd);

View File

@ -24,7 +24,6 @@ License
\*---------------------------------------------------------------------------*/
#include "NamedEnum.H"
#include "stringList.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -85,4 +84,42 @@ void Foam::NamedEnum<Enum, nEnum>::write(const Enum e, Ostream& os) const
}
template<class Enum, int nEnum>
Foam::stringList Foam::NamedEnum<Enum, nEnum>::strings()
{
stringList lst(nEnum);
label nElem = 0;
for (int enumI = 0; enumI < nEnum; ++enumI)
{
if (names[enumI] && names[enumI][0])
{
lst[nElem++] = names[enumI];
}
}
lst.setSize(nElem);
return lst;
}
template<class Enum, int nEnum>
Foam::wordList Foam::NamedEnum<Enum, nEnum>::words()
{
wordList lst(nEnum);
label nElem = 0;
for (int enumI = 0; enumI < nEnum; ++enumI)
{
if (names[enumI] && names[enumI][0])
{
lst[nElem++] = names[enumI];
}
}
lst.setSize(nElem);
return lst;
}
// ************************************************************************* //

View File

@ -37,6 +37,8 @@ SourceFiles
#include "HashTable.H"
#include "StaticAssert.H"
#include "stringList.H"
#include "wordList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -87,6 +89,12 @@ public:
//- Write the name representation of the enumeration to an Ostream
void write(const Enum e, Ostream&) const;
//- The set of names as a list of strings
static stringList strings();
//- The set of names as a list of words
static wordList words();
// Member Operators

View File

@ -31,12 +31,61 @@ Description
#include "IOdictionary.H"
#include "objectRegistry.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(Foam::IOdictionary, 0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Parallel aware reading, using non-virtual type information (typeName instead
// of type()) because of use in constructor.
void Foam::IOdictionary::readFile(const bool masterOnly)
{
if (Pstream::master() || !masterOnly)
{
if (debug)
{
Pout<< "IOdictionary : Reading " << objectPath()
<< " from file " << endl;
}
readStream(typeName) >> *this;
close();
}
if (masterOnly)
{
// Scatter master data
if (Pstream::master())
{
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
slave++
)
{
OPstream toSlave(Pstream::scheduled, slave);
IOdictionary::writeData(toSlave);
}
}
else
{
if (debug)
{
Pout<< "IOdictionary : Reading " << objectPath()
<< " from master processor " << Pstream::masterNo() << endl;
}
IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
IOdictionary::readData(fromMaster);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::IOdictionary::IOdictionary(const IOobject& io)
@ -56,17 +105,41 @@ Foam::IOdictionary::IOdictionary(const IOobject& io)
//<< abort(FatalError);
}
// Everyone check or just master
bool masterOnly =
regIOobject::fileModificationChecking == timeStampMaster
|| regIOobject::fileModificationChecking == inotifyMaster;
// Check if header is ok for READ_IF_PRESENT
bool isHeaderOk = false;
if (io.readOpt() == IOobject::READ_IF_PRESENT)
{
if (masterOnly)
{
if (Pstream::master())
{
isHeaderOk = headerOk();
}
Pstream::scatter(isHeaderOk);
}
else
{
isHeaderOk = headerOk();
}
}
if
(
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
)
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
|| isHeaderOk
)
{
readStream(typeName) >> *this;
close();
readFile(masterOnly);
}
dictionary::name() = IOobject::objectPath();
@ -90,17 +163,41 @@ Foam::IOdictionary::IOdictionary(const IOobject& io, const dictionary& dict)
<< endl;
}
// Everyone check or just master
bool masterOnly =
regIOobject::fileModificationChecking == timeStampMaster
|| regIOobject::fileModificationChecking == inotifyMaster;
// Check if header is ok for READ_IF_PRESENT
bool isHeaderOk = false;
if (io.readOpt() == IOobject::READ_IF_PRESENT)
{
if (masterOnly)
{
if (Pstream::master())
{
isHeaderOk = headerOk();
}
Pstream::scatter(isHeaderOk);
}
else
{
isHeaderOk = headerOk();
}
}
if
(
(
io.readOpt() == IOobject::MUST_READ
|| io.readOpt() == IOobject::MUST_READ_IF_MODIFIED
)
|| (io.readOpt() == IOobject::READ_IF_PRESENT && headerOk())
|| isHeaderOk
)
{
readStream(typeName) >> *this;
close();
readFile(masterOnly);
}
else
{

View File

@ -57,6 +57,11 @@ class IOdictionary
public dictionary
{
// Private Member Functions
//- read dictionary from file
void readFile(const bool);
public:
TypeName("dictionary");

View File

@ -250,8 +250,27 @@ Foam::Time::Time
// Time objects not registered so do like objectRegistry::checkIn ourselves.
if (runTimeModifiable_)
{
monitorPtr_.reset(new fileMonitor());
controlDict_.watchIndex() = addWatch(controlDict_.filePath());
monitorPtr_.reset
(
new fileMonitor
(
regIOobject::fileModificationChecking == inotify
|| regIOobject::fileModificationChecking == inotifyMaster
)
);
// File might not exist yet.
fileName f(controlDict_.filePath());
if (!f.size())
{
// We don't have this file but would like to re-read it.
// Possibly if in master-only reading mode. Use a non-existing
// file to keep fileMonitor synced.
f = controlDict_.objectPath();
}
controlDict_.watchIndex() = addWatch(f);
}
}
@ -308,19 +327,36 @@ Foam::Time::Time
readLibs_(controlDict_, "libs"),
functionObjects_(*this)
{
// Since could not construct regIOobject with setting:
controlDict_.readOpt() = IOobject::MUST_READ_IF_MODIFIED;
setControls();
// Time objects not registered so do like objectRegistry::checkIn ourselves.
if (runTimeModifiable_)
{
monitorPtr_.reset(new fileMonitor());
monitorPtr_.reset
(
new fileMonitor
(
regIOobject::fileModificationChecking == inotify
|| regIOobject::fileModificationChecking == inotifyMaster
)
);
// File might not exist yet.
fileName f(controlDict_.filePath());
if (f != fileName::null)
if (!f.size())
{
controlDict_.watchIndex() = addWatch(f);
// We don't have this file but would like to re-read it.
// Possibly if in master-only reading mode. Use a non-existing
// file to keep fileMonitor synced.
f = controlDict_.objectPath();
}
controlDict_.watchIndex() = addWatch(f);
}
}

View File

@ -211,7 +211,14 @@ void Foam::Time::readModifiedObjects()
// valid filePath).
// Note: requires same ordering in objectRegistries on different
// processors!
monitorPtr_().updateStates(Pstream::parRun());
monitorPtr_().updateStates
(
(
regIOobject::fileModificationChecking == inotifyMaster
|| regIOobject::fileModificationChecking == timeStampMaster
),
Pstream::parRun()
);
// Time handling is special since controlDict_ is the one dictionary
// that is not registered to any database.

View File

@ -198,7 +198,13 @@ bool Foam::functionObjectList::read()
}
// Update existing and add new functionObjects
const entry* entryPtr = parentDict_.lookupEntryPtr("functions",false,false);
const entry* entryPtr = parentDict_.lookupEntryPtr
(
"functions",
false,
false
);
if (entryPtr)
{
PtrList<functionObject> newPtrs;

View File

@ -36,6 +36,35 @@ int Foam::regIOobject::fileModificationSkew
Foam::debug::optimisationSwitch("fileModificationSkew", 30)
);
namespace Foam
{
template<>
const char* Foam::NamedEnum<Foam::regIOobject::fileCheckTypes, 4>::names[] =
{
"timeStamp",
"timeStampMaster",
"inotify",
"inotifyMaster"
};
}
const Foam::NamedEnum<Foam::regIOobject::fileCheckTypes, 4>
Foam::regIOobject::fileCheckTypesNames;
// Default fileCheck type
Foam::regIOobject::fileCheckTypes Foam::regIOobject::fileModificationChecking
(
fileCheckTypesNames.read
(
debug::optimisationSwitches().lookup
(
"fileModificationChecking"
//Foam::regIOobject::timeStamp
)
)
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -149,10 +178,13 @@ bool Foam::regIOobject::checkIn()
}
fileName f = filePath();
if (f != fileName::null)
if (!f.size())
{
watchIndex_ = time().addWatch(f);
// We don't have this file but would like to re-read it.
// Possibly if master-only reading mode.
f = objectPath();
}
watchIndex_ = time().addWatch(f);
}
// check-in on defaultRegion is allowed to fail, since subsetted meshes

View File

@ -41,6 +41,7 @@ SourceFiles
#include "IOobject.H"
#include "typeInfo.H"
#include "OSspecific.H"
#include "NamedEnum.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -57,6 +58,20 @@ class regIOobject
public IOobject
{
public:
//- Types of communications
enum fileCheckTypes
{
timeStamp,
timeStampMaster,
inotify,
inotifyMaster
};
static const NamedEnum<fileCheckTypes, 4> fileCheckTypesNames;
private:
// Private data
@ -95,6 +110,8 @@ public:
static int fileModificationSkew;
static fileCheckTypes fileModificationChecking;
// Constructors

View File

@ -26,7 +26,7 @@ License
#include "regIOobject.H"
#include "IFstream.H"
#include "Time.H"
//#include "PstreamReduceOps.H"
#include "Pstream.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -170,8 +170,50 @@ bool Foam::regIOobject::readData(Istream&)
bool Foam::regIOobject::read()
{
bool ok = readData(readStream(type()));
close();
// Note: cannot do anything in readStream itself since this is used by
// e.g. GeometricField.
bool masterOnly =
regIOobject::fileModificationChecking == timeStampMaster
|| regIOobject::fileModificationChecking == inotifyMaster;
bool ok;
if (Pstream::master() || !masterOnly)
{
ok = readData(readStream(type()));
close();
}
if (masterOnly)
{
// Scatter master data
if (Pstream::master())
{
for
(
int slave=Pstream::firstSlave();
slave<=Pstream::lastSlave();
slave++
)
{
OPstream toSlave(Pstream::scheduled, slave);
writeData(toSlave);
}
}
else
{
if (IFstream::debug)
{
Pout<< "regIOobject::read() : "
<< "reading object " << name()
<< " from master processor " << Pstream::masterNo()
<< endl;
}
IPstream fromMaster(Pstream::scheduled, Pstream::masterNo());
ok = readData(fromMaster);
}
}
return ok;
}

View File

@ -55,6 +55,12 @@ Foam::argList::initValidTables::initValidTables()
);
argList::addBoolOption("parallel", "run in parallel");
validParOptions.set("parallel", "");
argList::addOption
(
"roots", "(dir1 .. dirn)",
"slave root directories for distributed running"
);
validParOptions.set("roots", "(dir1 .. dirn)");
Pstream::addValidParOptions(validParOptions);
}
@ -511,6 +517,10 @@ Foam::argList::argList
// Case is a single processor run unless it is running parallel
int nProcs = 1;
// Roots if running distributed
fileNameList roots;
// If this actually is a parallel run
if (parRunControl_.parRun())
{
@ -520,28 +530,42 @@ Foam::argList::argList
// establish rootPath_/globalCase_/case_ for master
getRootCase();
IFstream decompDictStream
(
rootPath_/globalCase_/"system/decomposeParDict"
);
// See if running distributed (different roots for different procs)
label dictNProcs = -1;
fileName source;
if (!decompDictStream.good())
if (options_.found("roots"))
{
FatalError
<< "Cannot read "
<< decompDictStream.name()
<< exit(FatalError);
IStringStream str(options_["roots"]);
str >> roots;
dictNProcs = roots.size()+1;
source = "roots-command-line";
}
else
{
source = rootPath_/globalCase_/"system/decomposeParDict";
IFstream decompDictStream(source);
dictionary decompDict(decompDictStream);
if (!decompDictStream.good())
{
FatalError
<< "Cannot read "
<< decompDictStream.name()
<< exit(FatalError);
}
label dictNProcs
(
readLabel
dictionary decompDict(decompDictStream);
dictNProcs = readLabel
(
decompDict.lookup("numberOfSubdomains")
)
);
);
if (decompDict.lookupOrDefault("distributed", false))
{
decompDict.lookup("roots") >> roots;
}
}
// Check number of processors.
// nProcs => number of actual procs
@ -555,23 +579,27 @@ Foam::argList::argList
if (dictNProcs > Pstream::nProcs())
{
FatalError
<< decompDictStream.name()
<< source
<< " specifies " << dictNProcs
<< " processors but job was started with "
<< Pstream::nProcs() << " processors."
<< exit(FatalError);
}
// distributed data
if (decompDict.lookupOrDefault("distributed", false))
if (roots.size())
{
fileNameList roots;
decompDict.lookup("roots") >> roots;
forAll(roots, i)
{
roots[i] = roots[i].expand();
}
if (roots.size() != Pstream::nProcs()-1)
{
FatalError
<< "number of entries in decompositionDict::roots"
<< "number of entries in roots "
<< roots.size()
<< " is not equal to the number of slaves "
<< Pstream::nProcs()-1
<< exit(FatalError);
@ -705,8 +733,12 @@ Foam::argList::argList
if (parRunControl_.parRun())
{
Info<< "Slaves : " << slaveProcs << nl
<< "Pstream initialized with:" << nl
Info<< "Slaves : " << slaveProcs << nl;
if (roots.size())
{
Info<< "Roots : " << roots << nl;
}
Info<< "Pstream initialized with:" << nl
<< " floatTransfer : " << Pstream::floatTransfer << nl
<< " nProcsSimpleSum : " << Pstream::nProcsSimpleSum << nl
<< " commsType : "
@ -722,6 +754,10 @@ Foam::argList::argList
{
jobInfo.add("slaves", slaveProcs);
}
if (roots.size())
{
jobInfo.add("roots", roots);
}
jobInfo.write();
// Switch on signal trapping. We have to wait until after Pstream::init

View File

@ -620,24 +620,23 @@ Foam::dynamicRefineFvMesh::cellToPoint(const scalarField& vFld) const
}
// Calculate error. Is < 0 or distance from inbetween levels
Foam::scalarField
Foam::dynamicRefineFvMesh::error
// Calculate error. Is < 0 or distance to minLevel, maxLevel
Foam::scalarField Foam::dynamicRefineFvMesh::error
(
const scalarField& fld,
const scalar minLevel,
const scalar maxLevel
) const
{
const scalar halfLevel = 0.5*(minLevel + maxLevel);
scalarField c(fld.size(), -1);
forAll(fld, i)
{
if (fld[i] >= minLevel && fld[i] < maxLevel)
scalar err = min(fld[i]-minLevel, maxLevel-fld[i]);
if (err >= 0)
{
c[i] = mag(fld[i] - halfLevel);
c[i] = err;
}
}
return c;
@ -877,6 +876,10 @@ Foam::dynamicRefineFvMesh::dynamicRefineFvMesh(const IOobject& io)
nRefinementIterations_(0),
protectedCell_(nCells(), 0)
{
// Read static part of dictionary
readDict();
const labelList& cellLevel = meshCutter_.cellLevel();
const labelList& pointLevel = meshCutter_.pointLevel();

View File

@ -27,7 +27,6 @@ Class
Description
Recycles the velocity and flux at a patch to this patch
mode = NEARESTCELL : sample nearest cell
mode = NEARESTPATCHFACE : sample nearest face on selected patch
mode = NEARESTFACE : sample nearest face on any patch. Note: does not
warn if nearest actually is on internal face!

View File

@ -261,17 +261,16 @@ void timeVaryingMappedFixedValueFvPatchField<Type>::readSamplePoints()
for (label i = 1; i < samplePoints.size(); i++)
{
e1 = samplePoints[i] - p0;
scalar magE1 = mag(e1);
const vector d = samplePoints[i] - p0;
scalar magD = mag(d);
if (magE1 > maxDist)
if (magD > maxDist)
{
e1 /= magE1;
e1 = d/magD;
index1 = i;
maxDist = magE1;
maxDist = magD;
}
}
// Find point that is furthest away from line p0-p1
const point& p1 = samplePoints[index1];

View File

@ -211,7 +211,8 @@ void Foam::singleCellFvMesh::agglomerateMesh
"singleCellFvMesh::agglomerateMesh(..)"
) << "agglomeration does not create a"
<< " single, non-manifold"
<< " face for agglomeration " << coarseI
<< " face for agglomeration " << myAgglom
<< " on patch " << patchI
<< exit(FatalError);
}

View File

@ -21,8 +21,6 @@ License
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -32,7 +30,6 @@ namespace Foam
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Update this with w2 if w2 nearer to pt.
inline bool wallPointYPlus::update
(

View File

@ -333,7 +333,7 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
trackedParticle::trackData td(cloud, maxFeatureLevel);
// Track all particles to their end position (= starting feature point)
cloud.move(td, mesh_.time().deltaTValue());
cloud.move(td, GREAT);
// Reset level
maxFeatureLevel = -1;
@ -406,7 +406,7 @@ Foam::label Foam::meshRefinement::markFeatureRefinement
}
// Track all particles to their end position.
cloud.move(td, mesh_.time().deltaTValue());
cloud.move(td, GREAT);
}

View File

@ -25,8 +25,11 @@ Class
Foam::surfaceInterpolateFields
Description
Reads fields from the time folders and adds them to the mesh database
for further post-processing.
Linear interpolates volFields to surfaceFields
Note: gets executed every time step. Could move it to write() but then
you'd have problems if you have different write frequencies for different
function objects.
SourceFiles
surfaceInterpolateFields.C
@ -38,7 +41,6 @@ SourceFiles
#define surfaceInterpolateFields_H
#include "OFstream.H"
//#include "pointFieldFwd.H"
#include "surfaceFields.H"
#include "Tuple2.H"