OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
PeakFinder.cpp
Go to the documentation of this file.
1 //
2 // Class PeakFinder
3 // Find peaks of radial profile.
4 // It computes a histogram based on the radial distribution of the particle
5 // bunch. After that all peaks of the histogram are searched.
6 // The radii are written in ASCII format to a file.
7 // This class is used for the cyclotron probe element.
8 //
9 // Copyright (c) 2017 - 2021, Matthias Frey, Jochem Snuverink, Paul Scherrer Institut, Villigen PSI, Switzerland
10 // All rights reserved
11 //
12 // This file is part of OPAL.
13 //
14 // OPAL is free software: you can redistribute it and/or modify
15 // it under the terms of the GNU General Public License as published by
16 // the Free Software Foundation, either version 3 of the License, or
17 // (at your option) any later version.
18 //
19 // You should have received a copy of the GNU General Public License
20 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
21 //
22 #include "Structure/PeakFinder.h"
23 
25 
26 #include "Message/GlobalComm.h"
27 #include "Utility/IpplInfo.h"
28 
29 #include <algorithm>
30 #include <cmath>
31 #include <iterator>
32 
33 extern Inform* gmsg;
34 
35 PeakFinder::PeakFinder(std::string outfn, double min,
36  double max, double binWidth, bool singlemode)
37  : outputName_m(outfn)
38  , binWidth_m(binWidth)
39  , min_m(min)
40  , max_m(max)
41  , turn_m(0)
42  , peakRadius_m(0.0)
43  , registered_m(0)
44  , singlemode_m(singlemode)
45  , first_m(true)
46  , finished_m(false)
47 {
48  if (min_m > max_m) {
49  std::swap(min_m, max_m);
50  }
51  // calculate bins, round up so that histogram is large enough (add one for safety)
52  nBins_m = static_cast<unsigned int>(std::ceil(( max_m - min_m ) / binWidth_m)) + 1;
53 }
54 
55 
57 
58  double radius = std::hypot(R(0),R(1));
59  radius_m.push_back(radius);
60 
61  peakRadius_m += radius;
62  ++registered_m;
63 }
64 
65 
66 void PeakFinder::evaluate(const int& turn) {
67 
68  if ( first_m ) {
69  turn_m = turn;
70  first_m = false;
71  }
72 
73  if ( turn_m != turn ) {
74  finished_m = true;
75  }
76 
77  bool globFinished = false;
78 
79  if ( !singlemode_m )
80  allreduce(finished_m, globFinished, 1, std::logical_and<bool>());
81  else
82  globFinished = finished_m;
83 
84  if ( globFinished ) {
85 
86  this->computeCentroid_m();
87 
88  turn_m = turn;
89 
90  // reset
91  peakRadius_m = 0.0;
92  registered_m = 0;
93  finished_m = false;
94  }
95 }
96 
97 
99 
101 
102  // last turn is not yet computed
103  this->computeCentroid_m();
104 
105  if ( !peaks_m.empty() ) {
106  // only rank 0 will go in here
107 
108  fn_m = outputName_m + std::string(".peaks");
110 
111  hist_m = outputName_m + std::string(".hist");
113 
114  *gmsg << level2 << "Save " << fn_m << " and " << hist_m << endl;
115 
116  if(OpalData::getInstance()->inRestartRun())
117  this->append_m();
118  else
119  this->open_m();
120 
121  this->saveASCII_m();
122  this->close_m();
123  }
124 
125  radius_m.clear();
126  globHist_m.clear();
127 }
128 
129 
131  double globPeakRadius = 0.0;
132  int globRegister = 0;
133 
134  //FIXME inefficient
135  if ( !singlemode_m ) {
136  reduce(peakRadius_m, globPeakRadius, 1, std::plus<double>());
137  reduce(registered_m, globRegister, 1, std::plus<int>());
138  } else {
139  globPeakRadius = peakRadius_m;
140  globRegister = registered_m;
141  }
142 
143  if ( Ippl::myNode() == 0 ) {
144  if ( globRegister > 0 )
145  peaks_m.push_back(globPeakRadius / double(globRegister));
146  }
147 }
148 
150  /*
151  * create local histograms
152  */
153 
154  globHist_m.resize(nBins_m);
155  container_t locHist(nBins_m,0.0);
156 
157  double invBinWidth = 1.0 / binWidth_m;
158  for(container_t::iterator it = radius_m.begin(); it != radius_m.end(); ++it) {
159  int bin = static_cast<int>(std::abs(*it - min_m ) * invBinWidth);
160  if (bin < 0 || (unsigned int)bin >= nBins_m) continue; // Probe might save particles outside its boundary
161  ++locHist[bin];
162  }
163 
164  /*
165  * create global histograms
166  */
167  if ( !singlemode_m ) {
168  reduce(&(locHist[0]), &(locHist[0]) + locHist.size(),
169  &(globHist_m[0]), OpAddAssign());
170  } else {
171  globHist_m.swap(locHist);
172  }
173 
174 // reduce(locHist.data(), globHist_m.data(), locHist.size(), std::plus<double>());
175 }
176 
177 
179  os_m.open(fn_m.c_str(), std::ios::out);
180  hos_m.open(hist_m.c_str(), std::ios::out);
181 }
182 
183 
185  os_m.open(fn_m.c_str(), std::ios::app);
186  hos_m.open(hist_m.c_str(), std::ios::app);
187 }
188 
189 
191  os_m.close();
192  hos_m.close();
193 }
194 
195 
197  os_m << "# Peak Radii (mm)" << std::endl;
198  for (auto &radius : peaks_m)
199  os_m << radius << std::endl;
200 
201  hos_m << "# Histogram bin counts (min, max, nbins, binsize) "
202  << min_m << " mm "
203  << max_m << " mm "
204  << nBins_m << " "
205  << binWidth_m << " mm" << std::endl;
206  for (auto binCount : globHist_m)
207  hos_m << binCount << std::endl;
208 }
Inform * gmsg
Definition: Main.cpp:62
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
void allreduce(const T *input, T *output, int count, Op op)
Definition: GlobalComm.hpp:510
bool reduce(Communicate &, InputIterator, InputIterator, OutputIterator, const ReduceOp &, bool *IncludeVal=0)
Definition: GlobalComm.hpp:55
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TUTree< FnCeil, typename T::PETE_Expr_t > ceil(const PETE_Expr< T > &l)
Definition: PETE.h:728
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
std::string::iterator iterator
Definition: MSLang.h:16
void checkAndAddOutputFileName(const std::string &outfn)
checks the output file names of all items to avoid duplicates
Definition: OpalData.cpp:664
static OpalData * getInstance()
Definition: OpalData.cpp:195
std::vector< double > container_t
Definition: PeakFinder.h:35
void open_m()
Open output file.
Definition: PeakFinder.cpp:178
std::list< double > peaks_m
Definition: PeakFinder.h:106
std::ofstream hos_m
used to write out the histrogram
Definition: PeakFinder.h:90
PeakFinder()=delete
std::string fn_m
filename with extension (.peaks)
Definition: PeakFinder.h:81
std::ofstream os_m
used to write out the data
Definition: PeakFinder.h:87
double binWidth_m
Bin width in mm.
Definition: PeakFinder.h:99
double peakRadius_m
Definition: PeakFinder.h:104
container_t globHist_m
global histogram values
Definition: PeakFinder.h:78
bool singlemode_m
Definition: PeakFinder.h:107
void save()
Definition: PeakFinder.cpp:98
container_t radius_m
Definition: PeakFinder.h:76
bool finished_m
Definition: PeakFinder.h:109
void createHistogram_m()
Definition: PeakFinder.cpp:149
void computeCentroid_m()
Definition: PeakFinder.cpp:130
double min_m
histogram size
Definition: PeakFinder.h:101
unsigned int nBins_m
Number of bins.
Definition: PeakFinder.h:97
std::string outputName_m
Element/probe name, for name output file.
Definition: PeakFinder.h:93
void append_m()
Open output file in append mode.
Definition: PeakFinder.cpp:184
std::string hist_m
histogram filename with extension (.hist)
Definition: PeakFinder.h:84
bool first_m
Definition: PeakFinder.h:108
int registered_m
Definition: PeakFinder.h:105
void evaluate(const int &turn)
Definition: PeakFinder.cpp:66
void saveASCII_m()
Write to output file.
Definition: PeakFinder.cpp:196
void addParticle(const Vector_t &R)
Definition: PeakFinder.cpp:56
double max_m
Definition: PeakFinder.h:101
void close_m()
Close output file.
Definition: PeakFinder.cpp:190
Definition: Inform.h:42
static int myNode()
Definition: IpplInfo.cpp:691