Peano 4
Loading...
Searching...
No Matches
TrajectoryDatabase.cpp
Go to the documentation of this file.
2
4#include "tarch/mpi/Rank.h"
5
6#include <fstream>
7
8
9tarch::logging::Log toolbox::particles::TrajectoryDatabase::_log( "toolbox::particles::TrajectoryDatabase" );
10
11
13 x(x_),
14 timestamp(timestamp_),
15 numberOfDataEntries(database._numberOfDataPointsPerParticle) {
16 if (numberOfDataEntries>0) {
17 data = new double[numberOfDataEntries];
18 std::fill_n( data, numberOfDataEntries, 0.0 );
19 }
20 else {
21 data =nullptr;
22 }
23}
24
25
27 x(copy.x),
28 timestamp(copy.timestamp),
29 numberOfDataEntries(copy.numberOfDataEntries) {
30 if (numberOfDataEntries>0) {
31 data = new double[numberOfDataEntries];
32 std::copy_n( copy.data, numberOfDataEntries, data );
33 }
34 else {
35 data =nullptr;
36 }
37}
38
39
43
44
45toolbox::particles::TrajectoryDatabase::TrajectoryDatabase( int growthBetweenTwoDatabaseFlushes, double positionDelta, double dataDelta, double timeDelta, bool clearDatabaseAfterFlush, bool deltasAreRelative ):
46 _fileName(""),
47 _timeDelta(0.0),
48 _dataDelta(dataDelta),
49 _positionDelta(positionDelta),
50 _maxDataDelta(0.0),
53 _deltaBetweenTwoDatabaseFlushes(growthBetweenTwoDatabaseFlushes),
54 _thresholdForNextDatabaseFlush(growthBetweenTwoDatabaseFlushes==0 ? std::numeric_limits<int>::max() : 0),
56 _deltasAreRelative(deltasAreRelative),
57 _rank(-1),
58 _maxTimestamp( -std::numeric_limits<double>::max() ) {
59}
60
61
63 if (_fileName!="") {
64 dumpCSVFile();
65 }
66 clear();
67}
68
69
71 tarch::multicore::Lock lock(_semaphore, false);
72
73 if (lockSemaphore) {
74 lock.lock();
75 }
76
77 _data.clear();
78}
79
80
82 tarch::multicore::Lock lock(_semaphore, false);
83
84 if (lockSemaphore) {
85 lock.lock();
86 }
87
88 for (auto& particle: _data) {
89 if ( particle.second.size()>1 ) {
90 std::list<Entry>::iterator snapshot = particle.second.begin();
91 snapshot++;
92 particle.second.erase(snapshot, particle.second.end());
93 }
94 }
95}
96
97
99 std::ostringstream snapshotFileName;
100 snapshotFileName << _fileName;
101
102 if (tarch::mpi::Rank::getInstance().getNumberOfRanks()>0 ) {
103 if ( _rank<0 ) {
105 }
106 snapshotFileName << "-rank-" << _rank;
107 }
108
109 if (_clearDatabaseAfterFlush) {
110 static int snapshotCounter = -1;
111 snapshotCounter++;
112 snapshotFileName << "-snapshot-" << snapshotCounter;
113 }
114
115 snapshotFileName << ".csv";
116
117 tarch::multicore::Lock lock(_semaphore);
118 if (not _data.empty()) {
119 logInfo( "dumpCSVFile()", "dump particle trajectory database " << snapshotFileName.str() );
120 std::ofstream file( snapshotFileName.str() );
121 file << std::scientific;
122 #if Dimensions==2
123 file << "number(0), number(1), t, x(0), x(1), data " << std::endl;
124 #else
125 file << "number(0), number(1), t, x(0), x(1), x(2), data " << std::endl;
126 #endif
127
128 for (auto& particle: _data) {
129 for (auto& snapshot: particle.second) {
130 file << particle.first.first
131 << ", "
132 << particle.first.second
133 << ", "
134 //<< std::setprecision (6)
135 << snapshot.timestamp;
136 #if Dimensions==2
137 file //<< std::setprecision (_precision)
138 << ", "
139 << snapshot.x(0)
140 << ", "
141 << snapshot.x(1);
142 #else
143 file //<< std::setprecision (_precision)
144 << ", "
145 << snapshot.x(0)
146 << ", "
147 << snapshot.x(1)
148 << ", "
149 << snapshot.x(2);
150 #endif
151
152 if (snapshot.data!=nullptr) {
153 //file.precision(_precision);
154 for (int i=0; i<_numberOfDataPointsPerParticle; i++) {
155 file << ", "
156 << snapshot.data[i];
157 }
158 }
159 file << std::endl;
160 }
161 }
162 }
163 else {
164 #if PeanoDebug>=1
165 logInfo( "dumpCSVFile()", "particle trajectory database is empty. Do not dump " << snapshotFileName.str() );
166 #endif
167 }
168
169 if (_clearDatabaseAfterFlush) {
170 clearHistory(false);
171 }
172}
173
174
176 _fileName = filename;
177}
178
180 _precision = precision;
181}
182
184 _clearDatabaseAfterFlush = value;
185}
186
188 assertion(value>=0.0);
189 _dataDelta = value;
190 _maxDataDelta = 1e-20;
191 _deltasAreRelative = deltasAreRelative;
192}
193
194
196 assertion(value>=0.0);
197 _positionDelta = value;
198 _maxPositionDelta = 1e-20;
199 _deltasAreRelative = deltasAreRelative;
200}
201
203 assertion(value>=0.0);
204 _timeDelta = value;
205}
206
208 const std::pair<int, int>& number,
210 double timestamp
211) {
213
214 if (_data.count(number)==0) {
215 _data.insert( std::pair<std::pair<int,int>, std::list<Entry>>(number,std::list<Entry>()) );
217 }
218 else if (_data.at(number).empty()) {
220 }
221 else {
222 tarch::la::Vector<Dimensions,double> oldX = _data.at(number).front().x;
223 double delta = tarch::la::norm2(oldX-x);
224 _maxPositionDelta = std::max(delta,_maxPositionDelta);
225 if (
226 tarch::la::equals( _data.at(number).front().timestamp, timestamp )
227 and
228 not tarch::la::equals(oldX,x)
229 ) {
230 logWarning( "getAction(...)", "particle " << number.first << "x" << number.second << " has two locations " << x << " and " << oldX << " for same time stamp " << timestamp << ". This is inconsistent");
232 }
233 else if (
234 tarch::la::equals( _data.at(number).front().timestamp, timestamp )
235 ) {
237 }
238 else if ( _deltasAreRelative and _maxPositionDelta>=_deltaCutOffThreshold and delta/_maxPositionDelta>=_positionDelta ) {
240 }
241 else if ( not _deltasAreRelative and delta>=_positionDelta ) {
243 }
244 else if ( (timestamp-_data.at(number).front().timestamp)>=_timeDelta and _timeDelta>0.0 ) {
246 }
247 else {
249 }
250 return result;
251 }
252}
253
254
256 const std::pair<int, int>& number,
258 double timestamp,
259 int numberOfDataEntries,
260 double* data
261) {
262 toolbox::particles::TrajectoryDatabase::AddSnapshotAction result = getAction(number,x,timestamp);
263
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 );
268 if (
269 std::abs( _data.at(number).front().data[i] - data[i] ) > _dataDelta
270 and
271 tarch::la::equals( _data.at(number).front().timestamp, timestamp )
272 ) {
273 //logWarning( "getAction(...)", "particle " << number.first << "x" << number.second << " at " << x << " has different values for same time stamp " << timestamp << ". This is inconsistent");
275 }
276 else if ( _deltasAreRelative and _maxDataDelta>=_deltaCutOffThreshold and delta/_maxDataDelta >= _dataDelta ) {
278 }
279 else if ( not _deltasAreRelative and delta >= _dataDelta ) {
281 }
282 }
283 }
284
285 return result;
286}
287
288
290 tarch::multicore::Lock lock(_semaphore);
291 int totalSize = 0;
292 for (auto p: _data) {
293 totalSize += p.second.size();
294 }
295
296 bool result = tarch::la::greater(_maxTimestamp,0.0) and totalSize >= _thresholdForNextDatabaseFlush;
297
298 if (result and not _clearDatabaseAfterFlush) {
299 _thresholdForNextDatabaseFlush += _deltaBetweenTwoDatabaseFlushes;
300 }
301
302 return result;
303}
304
305
307 const std::pair<int, int>& number,
308 double timestamp,
310) {
311 if ( _rank<0 ) {
313 }
314
315 tarch::multicore::Lock lock(_semaphore);
316 _maxTimestamp = std::max(_maxTimestamp,timestamp);
317 switch ( getAction(number,x,timestamp) ) {
318 case AddSnapshotAction::Ignore:
319 break;
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;
324 }
325 break;
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;
330 }
331 break;
332 }
333 lock.free();
334
335 if (dumpDatabaseSnapshot()) {
336 dumpCSVFile();
337 logInfo( "addSnapshot(...)", "flushed database file (temporary flush - simulation has not terminated yet)" );
338 }
339}
340
341
343 int number0,
344 int number1,
345 double timestamp,
347) {
348 addParticleSnapshot(
349 std::pair<int,int>(number0,number1),
350 timestamp,
351 x
352 );
353}
354
355
357 const std::pair<int, int>& number,
358 double timestamp,
360 int numberOfDataEntries,
361 double* data
362) {
363 assertion( _numberOfDataPointsPerParticle==numberOfDataEntries or _data.empty());
364 _numberOfDataPointsPerParticle = std::max(_numberOfDataPointsPerParticle,numberOfDataEntries);
365
366 if ( _rank<0 ) {
368 }
369
370 tarch::multicore::Lock lock(_semaphore);
371 _maxTimestamp = std::max(_maxTimestamp,timestamp);
372 switch ( getAction(number,x,timestamp,numberOfDataEntries,data) ) {
373 case AddSnapshotAction::Ignore:
374 break;
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];
379 }
380 break;
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];
385 }
386 break;
387 }
388 lock.free();
389
390 if (dumpDatabaseSnapshot()) {
391 dumpCSVFile();
392 logInfo( "addSnapshot(...)", "flush database file " << _fileName << " (temporary flush - simulation has not terminated yet)" );
393 }
394}
395
396
398 int number0,
399 int number1,
400 double timestamp,
402 int numberOfDataEntries,
403 double* data
404) {
405 addParticleSnapshot(
406 std::pair<int,int>(number0,number1),
407 timestamp,
408 x,
409 numberOfDataEntries,
410 data
411 );
412}
#define assertion(expr)
#define logWarning(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:440
#define logInfo(methodName, logMacroMessageStream)
Wrapper macro around tarch::tarch::logging::Log to improve logging.
Definition Log.h:411
Log Device.
Definition Log.h:516
static Rank & getInstance()
This operation returns the singleton instance.
Definition Rank.cpp:538
int getRank() const
Return rank of this node.
Definition Rank.cpp:528
Create a lock around a boolean semaphore region.
Definition Lock.h:19
void setDataDeltaBetweenTwoSnapshots(double value, bool deltasAreRelative=false)
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.
bool _clearDatabaseAfterFlush
Flag that indicates if we erase the database after a flush.
void dumpCSVFile()
Dump data into CSV file.
void addParticleSnapshot(const std::pair< int, int > &number, double timestamp, const tarch::la::Vector< Dimensions, double > &x)
Add particle snapshot.
void setOutputFileName(const std::string &filename)
void clearHistory(bool lockSemaphore=true)
This call does not throw away all particles, but it throws away all the history behind the particles.
void setPositionDeltaBetweenTwoSnapshots(double value, bool deltasAreRelative=false)
STL namespace.
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.
Simple vector class.
Definition Vector.h:134
const int numberOfDataEntries
Have to memorise this guy to be able to write a proper copy constructor.