14 timestamp(timestamp_),
15 numberOfDataEntries(database._numberOfDataPointsPerParticle) {
28 timestamp(copy.timestamp),
29 numberOfDataEntries(copy.numberOfDataEntries) {
88 for (
auto& particle: _data) {
89 if ( particle.second.size()>1 ) {
90 std::list<Entry>::iterator snapshot = particle.second.begin();
92 particle.second.erase(snapshot, particle.second.end());
99 std::ostringstream snapshotFileName;
100 snapshotFileName << _fileName;
106 snapshotFileName <<
"-rank-" << _rank;
109 if (_clearDatabaseAfterFlush) {
110 static int snapshotCounter = -1;
112 snapshotFileName <<
"-snapshot-" << snapshotCounter;
115 snapshotFileName <<
".csv";
118 if (not _data.empty()) {
119 logInfo(
"dumpCSVFile()",
"dump particle trajectory database " << snapshotFileName.str() );
120 std::ofstream file( snapshotFileName.str() );
121 file << std::scientific;
123 file <<
"number(0), number(1), t, x(0), x(1), data " << std::endl;
125 file <<
"number(0), number(1), t, x(0), x(1), x(2), data " << std::endl;
128 for (
auto& particle: _data) {
129 for (
auto& snapshot: particle.second) {
130 file << particle.first.first
132 << particle.first.second
135 << snapshot.timestamp;
152 if (snapshot.data!=
nullptr) {
154 for (
int i=0; i<_numberOfDataPointsPerParticle; i++) {
165 logInfo(
"dumpCSVFile()",
"particle trajectory database is empty. Do not dump " << snapshotFileName.str() );
169 if (_clearDatabaseAfterFlush) {
176 _fileName = filename;
180 _precision = precision;
184 _clearDatabaseAfterFlush = value;
190 _maxDataDelta = 1e-20;
191 _deltasAreRelative = deltasAreRelative;
197 _positionDelta = value;
198 _maxPositionDelta = 1e-20;
199 _deltasAreRelative = deltasAreRelative;
208 const std::pair<int, int>& number,
214 if (_data.count(number)==0) {
215 _data.insert( std::pair<std::pair<int,int>, std::list<Entry>>(number,std::list<Entry>()) );
218 else if (_data.at(number).empty()) {
224 _maxPositionDelta = std::max(delta,_maxPositionDelta);
230 logWarning(
"getAction(...)",
"particle " << number.first <<
"x" << number.second <<
" has two locations " << x <<
" and " << oldX <<
" for same time stamp " << timestamp <<
". This is inconsistent");
238 else if ( _deltasAreRelative and _maxPositionDelta>=_deltaCutOffThreshold and delta/_maxPositionDelta>=_positionDelta ) {
241 else if ( not _deltasAreRelative and delta>=_positionDelta ) {
244 else if ( (timestamp-_data.at(number).front().timestamp)>=_timeDelta and _timeDelta>0.0 ) {
256 const std::pair<int, int>& number,
259 int numberOfDataEntries,
265 for (
int i=0; i<numberOfDataEntries; i++) {
266 const double delta =
std::abs( _data.at(number).front().data[i] - data[i] );
267 _maxDataDelta = std::max( _maxDataDelta, delta );
269 std::abs( _data.at(number).front().data[i] - data[i] ) > _dataDelta
276 else if ( _deltasAreRelative and _maxDataDelta>=_deltaCutOffThreshold and delta/_maxDataDelta >= _dataDelta ) {
279 else if ( not _deltasAreRelative and delta >= _dataDelta ) {
292 for (
auto p: _data) {
293 totalSize += p.second.size();
296 bool result =
tarch::la::greater(_maxTimestamp,0.0) and totalSize >= _thresholdForNextDatabaseFlush;
298 if (result and not _clearDatabaseAfterFlush) {
299 _thresholdForNextDatabaseFlush += _deltaBetweenTwoDatabaseFlushes;
307 const std::pair<int, int>& number,
316 _maxTimestamp = std::max(_maxTimestamp,timestamp);
317 switch ( getAction(number,x,timestamp) ) {
318 case AddSnapshotAction::Ignore:
320 case AddSnapshotAction::Append:
321 _data.at(number).push_front(
Entry(*
this,x,timestamp) );
322 for (
int i=0; i<_numberOfDataPointsPerParticle; i++) {
323 _data.at(number).front().data[i] = 0.0;
326 case AddSnapshotAction::Replace:
327 _data.at(number).front().x = x;
328 for (
int i=0; i<_numberOfDataPointsPerParticle; i++) {
329 _data.at(number).front().data[i] = 0.0;
335 if (dumpDatabaseSnapshot()) {
337 logInfo(
"addSnapshot(...)",
"flushed database file (temporary flush - simulation has not terminated yet)" );
349 std::pair<int,int>(number0,number1),
357 const std::pair<int, int>& number,
360 int numberOfDataEntries,
363 assertion( _numberOfDataPointsPerParticle==numberOfDataEntries or _data.empty());
364 _numberOfDataPointsPerParticle = std::max(_numberOfDataPointsPerParticle,numberOfDataEntries);
371 _maxTimestamp = std::max(_maxTimestamp,timestamp);
372 switch ( getAction(number,x,timestamp,numberOfDataEntries,data) ) {
373 case AddSnapshotAction::Ignore:
375 case AddSnapshotAction::Append:
376 _data.at(number).push_front(
Entry(*
this,x,timestamp) );
377 for (
int i=0; i<_numberOfDataPointsPerParticle; i++) {
378 _data.at(number).front().data[i] = data[i];
381 case AddSnapshotAction::Replace:
382 _data.at(number).front().x = x;
383 for (
int i=0; i<_numberOfDataPointsPerParticle; i++) {
384 _data.at(number).front().data[i] = data[i];
390 if (dumpDatabaseSnapshot()) {
392 logInfo(
"addSnapshot(...)",
"flush database file " << _fileName <<
" (temporary flush - simulation has not terminated yet)" );
402 int numberOfDataEntries,
406 std::pair<int,int>(number0,number1),
#define logWarning(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
static Rank & getInstance()
This operation returns the singleton instance.
int getRank() const
Return rank of this node.
Create a lock around a boolean semaphore region.
void free()
Free the lock.
A simple particle database.
void setDataDeltaBetweenTwoSnapshots(double value, bool deltasAreRelative=false)
void clear(bool lockSemaphore=true)
AddSnapshotAction getAction(const std::pair< int, int > &number, const tarch::la::Vector< Dimensions, double > &x, double timestamp)
Determine what to do with new entry.
int _rank
This is a hack: Usually, I'd just ask the rank what its number is.
TrajectoryDatabase(int growthBetweenTwoDatabaseFlushes, double positionDelta=1e-8, double dataDelta=1e-8, double timeDelta=0.0, bool clearDatabaseAfterFlush=true, bool deltasAreRelative=false)
Trajectory database.
void clearDatabaseAfterFlush(bool value)
bool _clearDatabaseAfterFlush
Flag that indicates if we erase the database after a flush.
int _thresholdForNextDatabaseFlush
void dumpCSVFile()
Dump data into CSV file.
void setTimeDeltaBetweenTwoSnapshots(double value)
void addParticleSnapshot(const std::pair< int, int > &number, double timestamp, const tarch::la::Vector< Dimensions, double > &x)
Add particle snapshot.
static tarch::logging::Log _log
const int _deltaBetweenTwoDatabaseFlushes
void setOutputFileName(const std::string &filename)
void setOutputPrecision(int precision)
void clearHistory(bool lockSemaphore=true)
This call does not throw away all particles, but it throws away all the history behind the particles.
int _numberOfDataPointsPerParticle
bool dumpDatabaseSnapshot()
void setPositionDeltaBetweenTwoSnapshots(double value, bool deltasAreRelative=false)
bool greater(double lhs, double rhs, double tolerance=NUMERICAL_ZERO_DIFFERENCE)
bool equals(const Matrix< Rows, Cols, Scalar > &lhs, const Matrix< Rows, Cols, Scalar > &rhs, const Scalar &tolerance=NUMERICAL_ZERO_DIFFERENCE)
Compares to matrices on equality by means of a numerical accuracy.
Scalar norm2(const Vector< Size, Scalar > &vector)
Computes the 2-norm of the vector, i.e.
const int numberOfDataEntries
Have to memorise this guy to be able to write a proper copy constructor.