Skip to content

Commit 5e8b1cb

Browse files
Merge pull request #511 from JanNiklasB/RenewObserverTimeEvolution
Reworking of the ObserverTimeEvolution
2 parents c5ec112 + 8ce85f1 commit 5e8b1cb

File tree

5 files changed

+307
-87
lines changed

5 files changed

+307
-87
lines changed

CHANGELOG.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
## CRPropa vNext
22

33
### Bug fixes:
4-
* Fixed sign for exponential decay of magn. field strength with Galactic height in LogarithmicSpiralField
5-
* Fixed r term in source distribution for SNR and Pulsar
6-
* Fixed wrong mass inheritance for secondaries other than nuclei or electron/positron
4+
* Fixed sign for exponential decay of magn. field strength with Galactic height in LogarithmicSpiralField
5+
* Fixed r term in source distribution for SNR and Pulsar
6+
* Fixed wrong mass inheritance for secondaries other than nuclei or electron/positron
7+
* Fixed wrong generation of interval ranges in ObserverTimeEvolution
78

89
### New features:
9-
* Added new backwards-compatible function particleMass that returns particle mass also for non-nuclei
10-
* Added the new Galactic magnetic field models from Unger&Farrar arXiv:2311.12120
11-
* Added EBL model from Finke et al. 2022
10+
* Added new backwards-compatible function particleMass that returns particle mass also for non-nuclei
11+
* Added the new Galactic magnetic field models from Unger&Farrar arXiv:2311.12120
12+
* Added EBL model from Finke et al. 2022
13+
* Added overridable getTime function to ObserverTimeEvolution which is called instead of detList.
14+
Old functionalities are preserved by adding old functions and setter/getter functions.
1215

1316
### Interface changes:
1417

doc/pages/example_notebooks/Diffusion/MomentumDiffusion.ipynb

Lines changed: 29 additions & 42 deletions
Large diffs are not rendered by default.

include/crpropa/module/Observer.h

Lines changed: 105 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,24 @@ class ObserverParticleIdVeto: public ObserverFeature {
240240
This observer is very useful if the time evolution of the particle density is needed. It detects all candidates in lin-spaced, log-spaced, or user-defined time intervals and limits the nextStep of candidates to prevent overshooting of detection intervals.
241241
*/
242242
class ObserverTimeEvolution: public ObserverFeature {
243-
private:
243+
protected:
244+
int nIntervals; // number of time invervals
245+
bool isLogarithmicScaling = false; // enables or disables logarithmic scaling for the intervals
246+
bool doDetListConstruction = true; // enables the construction of detList in the relevant functions (addTime, addTimeRange)
247+
double minimum; // the minimum time
248+
double maximum; // the maximum time
249+
/** Vector containing all used times.
250+
It is only constructed by the user manually.
251+
If it is not empty, the vector will be used instead of the getTime function.
252+
(leave empty if you want to rather use functions)
253+
*/
244254
std::vector<double> detList;
255+
/**
256+
A temporary storage for detList, this enables the return of a List in getTimes
257+
without risking to modify detList
258+
*/
259+
mutable std::vector<double> tempDetList;
260+
245261
public:
246262
/** Default constructor
247263
*/
@@ -250,22 +266,105 @@ class ObserverTimeEvolution: public ObserverFeature {
250266
@param min minimum time
251267
@param dist time interval for detection
252268
@param numb number of time intervals
269+
270+
This constructor calculates the maximum from max = min + (numb - 1) * dist
253271
*/
254272
ObserverTimeEvolution(double min, double dist, double numb);
255273
/** Constructor
256274
@param min minimum time
257275
@param max maximum time
258276
@param numb number of time intervals
259277
@param log log (input: true) or lin (input: false) scaling between min and max with numb steps
278+
279+
This constructor sets the maximum directly and gets numb automatically.
280+
You need to set the log parameter, since an overload for the first three doubles exist.
260281
*/
261282
ObserverTimeEvolution(double min, double max, double numb, bool log);
262-
// Add a new time step to the detection time list of the observer
263-
void addTime(const double &position);
264-
// Using log or lin spacing of times in the range between min and
265-
// max for observing particles
283+
/** Constructor
284+
@param detList user defined vector<double> with times to check
285+
286+
This constructor uses a predefined vector containing the times that should be observed.
287+
The so created detList can then be modified via addTime, addTimeRange and setTimes.
288+
*/
289+
ObserverTimeEvolution(const std::vector<double> &detList);
290+
/** Destructor
291+
*/
292+
~ObserverTimeEvolution(){}
293+
294+
/** Function
295+
Generates the detList if it is empty when for example the
296+
ObserverTimeEvolution(const std::vector<double> &detList) constructor
297+
was not used.
298+
Use this function to create a detList with can then be modified.
299+
When detList is not empty its entries are used instead of a runtime calculation of the times.
300+
*/
301+
void constructDetListIfEmpty();
302+
/** Function
303+
@param candidate Candidate usally given by a module list
304+
305+
Checks whether to make a detection at the current step of candidate or not.
306+
This function is called in Observer.process with the simulated Candidate.
307+
*/
308+
DetectionState checkDetection(Candidate *candidate) const;
309+
/** Function
310+
@param enableConstruction if true, constructs detList from range of min, max, numb
311+
when calling addTime
312+
Clears the content of detList
313+
*/
314+
void clear();
315+
/** Function
316+
Checks if detList is empty
317+
*/
318+
bool empty(){return detList.empty();}
319+
320+
// setter functions:
321+
/** Function
322+
@param time Time that should be appended to detList
323+
324+
Makes a push_back on detList with the given time.
325+
*/
326+
void addTime(const double &time);
327+
/** Function
328+
@param min minimum time
329+
@param max maximum time
330+
@param numb number of time intervals
331+
@param log log (input: true) or lin (input: false) scaling between min and max with numb steps
332+
333+
Appends a linear or logarithmic time range to detList via repeatedly calling addTime
334+
*/
266335
void addTimeRange(double min, double max, double numb, bool log = false);
336+
/** Function
337+
@param detList vector<double> containing times when to observe
338+
339+
Sets this->detList to detList, with this it is possible to fully modify detList
340+
*/
341+
void setTimes(const std::vector<double> &detList);
342+
void setMinimum(double min);
343+
void setMaximum(double max){this->maximum = max;}
344+
void setNIntervals(int numb){this->nIntervals = numb;}
345+
void setIsLogarithmicScaling(bool log){this->isLogarithmicScaling = log;}
346+
347+
// getter functions:
348+
/** Function
349+
@param index index of the required time
350+
351+
Replaces the previous preconstructed detList and return the time for a specific index
352+
*/
353+
virtual double getTime(std::size_t index) const;
354+
double getMinimum() const {return minimum;}
355+
double getMaximum() const {return maximum;}
356+
int getNIntervals() const {return nIntervals;}
357+
bool getIsLogarithmicScaling() const {return isLogarithmicScaling;}
358+
/** Function
359+
Returns a vector<double> containing all times between min and max generated by getTime.
360+
This function does not return detList directly, it rather appends a new vector with
361+
getTime numb times.
362+
*/
267363
const std::vector<double>& getTimes() const;
268-
DetectionState checkDetection(Candidate *candidate) const;
364+
/** Function
365+
Returns a string containing a representation of all times.
366+
This function does not create a detList.
367+
*/
269368
std::string getDescription() const;
270369
};
271370

src/module/Observer.cpp

Lines changed: 81 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -246,23 +246,29 @@ std::string ObserverParticleIdVeto::getDescription() const {
246246
ObserverTimeEvolution::ObserverTimeEvolution() {}
247247

248248
ObserverTimeEvolution::ObserverTimeEvolution(double min, double dist, double numb) {
249-
double max = min + numb * dist;
250-
bool log = false;
251-
addTimeRange(min, max, numb, log);
249+
setMaximum(min + (numb - 1) * dist);
250+
setMinimum(min);
251+
setNIntervals(numb);
252+
setIsLogarithmicScaling(false);
252253
}
253254

254255
ObserverTimeEvolution::ObserverTimeEvolution(double min, double max, double numb, bool log) {
255-
addTimeRange(min, max, numb, log);
256+
setMinimum(min);
257+
setMaximum(max);
258+
setNIntervals(numb);
259+
setIsLogarithmicScaling(log);
256260
}
257261

262+
ObserverTimeEvolution::ObserverTimeEvolution(const std::vector<double> &detList){
263+
setTimes(detList);
264+
}
258265

259266
DetectionState ObserverTimeEvolution::checkDetection(Candidate *c) const {
260267

261-
if (detList.size()) {
268+
if (nIntervals) {
262269
double length = c->getTrajectoryLength();
263270
size_t index;
264271
const std::string DI = "DetectionIndex";
265-
std::string value;
266272

267273
// Load the last detection index
268274
if (c->hasProperty(DI)) {
@@ -272,13 +278,13 @@ DetectionState ObserverTimeEvolution::checkDetection(Candidate *c) const {
272278
index = 0;
273279
}
274280

275-
// Break if the particle has been detected once for all detList entries.
276-
if (index > detList.size()) {
281+
// Break if the particle has been detected once for all possible times.
282+
if (index >= nIntervals) {
277283
return NOTHING;
278284
}
279285

280286
// Calculate the distance to next detection
281-
double distance = length - detList[index];
287+
double distance = length - getTime(index);
282288

283289
// Limit next step and detect candidate.
284290
// Increase the index by one in case of detection
@@ -288,8 +294,8 @@ DetectionState ObserverTimeEvolution::checkDetection(Candidate *c) const {
288294
}
289295
else {
290296

291-
if (index < detList.size()-1) {
292-
c->limitNextStep(detList[index+1]-length);
297+
if (index < nIntervals-2) {
298+
c->limitNextStep(getTime(index+1)-length);
293299
}
294300
c->setProperty(DI, Variant::fromUInt64(index+1));
295301

@@ -299,29 +305,86 @@ DetectionState ObserverTimeEvolution::checkDetection(Candidate *c) const {
299305
return NOTHING;
300306
}
301307

302-
void ObserverTimeEvolution::addTime(const double& t) {
303-
detList.push_back(t);
308+
void ObserverTimeEvolution::clear(){
309+
doDetListConstruction = false;
310+
detList.clear();
311+
detList.resize(0);
312+
setNIntervals(0);
313+
}
314+
315+
void ObserverTimeEvolution::constructDetListIfEmpty(){
316+
if (detList.empty() && doDetListConstruction) {
317+
std::vector<double> detListTemp;
318+
size_t counter = 0;
319+
while (getTime(counter)<=maximum) {
320+
detListTemp.push_back(getTime(counter));
321+
counter++;
322+
}
323+
detList.assign(detListTemp.begin(), detListTemp.end());
324+
}
325+
}
326+
327+
void ObserverTimeEvolution::addTime(const double &time){
328+
constructDetListIfEmpty();
329+
detList.push_back(time);
330+
setNIntervals(nIntervals + 1); // increase number of entries by one
304331
}
305332

306333
void ObserverTimeEvolution::addTimeRange(double min, double max, double numb, bool log) {
307334
for (size_t i = 0; i < numb; i++) {
308-
if (log == true) {
335+
if (log) {
336+
if ( min <= 0 ){
337+
std::cout << "min can not be <= 0 if log=true" << std::endl;
338+
throw new std::invalid_argument("min can not be <= 0 if log=true");
339+
}
309340
addTime(min * pow(max / min, i / (numb - 1.0)));
310341
} else {
311-
addTime(min + i * (max - min) / numb);
342+
addTime(min + i * (max - min) / (numb - 1.0));
312343
}
313344
}
345+
// allready corrected by addTime, just here to be safe
346+
setNIntervals(detList.size());
347+
}
348+
349+
void ObserverTimeEvolution::setTimes(const std::vector<double> &detList){
350+
this->detList.assign(detList.begin(), detList.end());
351+
setNIntervals(detList.size());
352+
setMinimum(detList.front());
353+
setMaximum(detList.back());
354+
doDetListConstruction = false;
355+
}
356+
357+
void ObserverTimeEvolution::setMinimum(double min){
358+
if ( min <= 0 ){
359+
std::cout << "minimum can not be <= 0 if isLogarithmicScaling=true" << std::endl;
360+
throw new std::invalid_argument("minimum can not be <= 0 if isLogarithmicScaling=true");
361+
}
362+
this->minimum = min;
363+
}
364+
365+
double ObserverTimeEvolution::getTime(size_t index) const {
366+
if (!detList.empty()) {
367+
return detList.at(index);
368+
} else if (isLogarithmicScaling) {
369+
return minimum * pow(maximum / minimum, index / (nIntervals - 1.0));
370+
} else {
371+
return minimum + index * (maximum - minimum) / (nIntervals - 1.0);
372+
}
314373
}
315374

316375
const std::vector<double>& ObserverTimeEvolution::getTimes() const {
317-
return detList;
376+
tempDetList.resize(nIntervals);
377+
for (size_t i = 0; i < nIntervals; i++){
378+
tempDetList[i] = getTime(i);
379+
}
380+
return tempDetList;
318381
}
319382

320383
std::string ObserverTimeEvolution::getDescription() const {
321384
std::stringstream s;
322385
s << "List of Detection lengths in kpc";
323-
for (size_t i = 0; i < detList.size(); i++)
324-
s << " - " << detList[i] / kpc;
386+
for (size_t i = 0; i < nIntervals; i++)
387+
s << " - " << getTime(i) / kpc;
325388
return s.str();
326389
}
327390

0 commit comments

Comments
 (0)