OPAL (Object Oriented Parallel Accelerator Library) 2024.2
OPAL
Util.cpp
Go to the documentation of this file.
1//
2// Namespace Util
3// This namespace contains useful global methods.
4//
5// Copyright (c) 200x - 2022, Paul Scherrer Institut, Villigen PSI, Switzerland
6// All rights reserved
7//
8// This file is part of OPAL.
9//
10// OPAL is free software: you can redistribute it and/or modify
11// it under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// You should have received a copy of the GNU General Public License
16// along with OPAL. If not, see <https://www.gnu.org/licenses/>.
17//
18#include "Utilities/Util.h"
19
20#include "OPALrevision.h"
22
23#include <algorithm>
24#include <cctype>
25#include <cmath>
26#include <filesystem>
27#include <fstream>
28#include <iostream>
29#include <queue>
30#include <regex>
31#include <sstream>
32#include <string>
33#include <vector>
34
35namespace Util {
36 std::string getGitRevision() {
37 return std::string(GIT_VERSION);
38 }
39
40#define erfinv_a3 -0.140543331
41#define erfinv_a2 0.914624893
42#define erfinv_a1 -1.645349621
43#define erfinv_a0 0.886226899
44
45#define erfinv_b4 0.012229801
46#define erfinv_b3 -0.329097515
47#define erfinv_b2 1.442710462
48#define erfinv_b1 -2.118377725
49#define erfinv_b0 1
50
51#define erfinv_c3 1.641345311
52#define erfinv_c2 3.429567803
53#define erfinv_c1 -1.62490649
54#define erfinv_c0 -1.970840454
55
56#define erfinv_d2 1.637067800
57#define erfinv_d1 3.543889200
58#define erfinv_d0 1
59
60 double erfinv (double x) // inverse error function
61 {
62 double r;
63 int sign_x;
64
65 if (x < -1 || x > 1)
66 return NAN;
67
68 if (x == 0)
69 return 0;
70
71 if (x > 0)
72 sign_x = 1;
73 else {
74 sign_x = -1;
75 x = -x;
76 }
77
78 if (x <= 0.7) {
79 double x2 = x * x;
80 r =
81 x * (((erfinv_a3 * x2 + erfinv_a2) * x2 + erfinv_a1) * x2 + erfinv_a0);
82 r /= (((erfinv_b4 * x2 + erfinv_b3) * x2 + erfinv_b2) * x2 +
83 erfinv_b1) * x2 + erfinv_b0;
84 }
85 else {
86 double y = std::sqrt (-std::log ((1 - x) / 2));
87 r = (((erfinv_c3 * y + erfinv_c2) * y + erfinv_c1) * y + erfinv_c0);
88 r /= ((erfinv_d2 * y + erfinv_d1) * y + erfinv_d0);
89 }
90
91 r = r * sign_x;
92 x = x * sign_x;
93
94 r -= (std::erf (r) - x) / (2 / std::sqrt (Physics::pi) * std::exp (-r * r));
95 r -= (std::erf (r) - x) / (2 / std::sqrt (Physics::pi) * std::exp (-r * r));
96
97 return r;
98 }
99
100#undef erfinv_a3
101#undef erfinv_a2
102#undef erfinv_a1
103#undef erfinv_a0
104
105#undef erfinv_b4
106#undef erfinv_b3
107#undef erfinv_b2
108#undef erfinv_b1
109#undef erfinv_b0
110
111#undef erfinv_c3
112#undef erfinv_c2
113#undef erfinv_c1
114#undef erfinv_c0
115
116#undef erfinv_d2
117#undef erfinv_d1
118#undef erfinv_d0
119
120 Vector_t getTaitBryantAngles(Quaternion rotation, const std::string& /*elementName*/) {
121 Quaternion rotationBAK = rotation;
122
123 // y axis
124 Vector_t tmp = rotation.rotate(Vector_t({0, 0, 1}));
125 tmp(1) = 0.0;
126 // tmp /= euclidean_norm(tmp);
127 double theta = std::fmod(std::atan2(tmp(0), tmp(2)) + Physics::two_pi, Physics::two_pi);
128
129 Quaternion rotTheta(std::cos(0.5 * theta), 0, std::sin(0.5 * theta), 0);
130 rotation = rotTheta.conjugate() * rotation;
131
132 // x axis
133 tmp = rotation.rotate(Vector_t({0, 0, 1}));
134 tmp(0) = 0.0;
135 tmp /= euclidean_norm(tmp);
136 double phi = std::fmod(std::atan2(-tmp(1), tmp(2)) + Physics::two_pi, Physics::two_pi);
137
138 Quaternion rotPhi(std::cos(0.5 * phi), std::sin(0.5 * phi), 0, 0);
139 rotation = rotPhi.conjugate() * rotation;
140
141 // z axis
142 tmp = rotation.rotate(Vector_t({1, 0, 0}));
143 tmp(2) = 0.0;
144 tmp /= euclidean_norm(tmp);
145 double psi = std::fmod(std::atan2(tmp(1), tmp(0)) + Physics::two_pi, Physics::two_pi);
146
147 return Vector_t({theta, phi, psi});
148 }
149
150 std::string toUpper(const std::string& str) {
151 std::string output = str;
152 std::transform(output.begin(), output.end(), output.begin(), [](const char c) { return std::toupper(c);});
153
154 return output;
155 }
156
157 std::string boolToUpperString(const bool& b) {
158 std::ostringstream valueStream;
159 valueStream << std::boolalpha << b;
160 std::string output = Util::toUpper(valueStream.str());
161 return output;
162 }
163
164 std::string boolVectorToUpperString(const std::vector<bool>& b) {
165 std::ostringstream output;
166 if (b.size() > 1) {
167 output << "(";
168 }
169 for (size_t i = 0; i < b.size(); ++i) {
170 output << std::boolalpha << boolToUpperString(b[i]);
171 if (b.size() > 1) {
172 (i < (b.size()-1)) ? (output << ", ") : (output << ")");
173 }
174 }
175
176 return output.str();
177 }
178
179 std::string doubleVectorToString(const std::vector<double>& v) {
180 std::vector<std::string> stringVec;
181 stringVec.reserve(v.size());
182 Util::toString(std::begin(v), std::end(v), std::back_inserter(stringVec));
183
184 std::ostringstream output;
185 if (v.size() > 1) {
186 output << "(";
187 }
188 unsigned int i = 0;
189 for (auto& s: stringVec) {
190 ++i;
191 output << s;
192 if (v.size() > 1) {
193 (i < stringVec.size()) ? (output << ", ") : (output << ")");
194 }
195 }
196
197 return output.str();
198 }
199
200 std::string combineFilePath(std::initializer_list<std::string> ilist) {
201 std::filesystem::path path;
202 for (auto entry : ilist) {
203 path /= entry;
204 }
205 return path.string();
206 }
207
208 void checkInt(double real, std::string name, double tolerance) {
209 real += tolerance; // prevent rounding error
210 if (std::abs(std::floor(real) - real) > 2*tolerance) {
211 throw OpalException("Util::checkInt",
212 "Value for " + name +
213 " should be an integer but a real value was found");
214 }
215 if (std::floor(real) < 0.5) {
216 throw OpalException("Util::checkInt",
217 "Value for " + name + " should be 1 or more");
218 }
219 }
220
221 bool isAllDigits(const std::string& str) {
222 return std::all_of(str.begin(),
223 str.end(),
224 [](char c) { return std::isdigit(c); });
225 }
226
228 sum(0.0),
229 correction(0.0)
230 { }
231
233 long double y = value - this->correction;
234 long double t = this->sum + y;
235 this->correction = (t - this->sum) - y;
236 this->sum = t;
237 return *this;
238 }
239
243 unsigned int rewindLinesSDDS(const std::string& fileName, double maxSPos, bool checkForTime) {
244 if (Ippl::myNode() > 0) return 0;
245
246 std::fstream fs(fileName.c_str(), std::fstream::in);
247 if (!fs.is_open()) return 0;
248
249 std::string line;
250 std::queue<std::string> allLines;
251 unsigned int numParameters = 0;
252 unsigned int numColumns = 0;
253 unsigned int sposColumnNr = 0;
254 unsigned int timeColumnNr = 0;
255 double spos, time = 0.0;
256 double lastTime = -1.0;
257
258 std::regex parameters("&parameter");
259 std::regex column("&column");
260 std::regex data("&data");
261 std::regex end("&end");
262 std::regex name("name=([a-zA-Z0-9\\$_]+)");
263 std::smatch match;
264
265 std::istringstream linestream;
266
267 while (std::getline(fs, line)) {
268 allLines.push(line);
269 }
270 fs.close();
271
272 fs.open (fileName.c_str(), std::fstream::out);
273
274 if (!fs.is_open()) return 0;
275
276 do {
277 line = allLines.front();
278 allLines.pop();
279 fs << line << "\n";
280 if (std::regex_search(line, match, parameters)) {
281 ++numParameters;
282 while (!std::regex_search(line, match, end)) {
283 line = allLines.front();
284 allLines.pop();
285 fs << line << "\n";
286 }
287 } else if (std::regex_search(line, match, column)) {
288 ++numColumns;
289 while (!std::regex_search(line, match, name)) {
290 line = allLines.front();
291 allLines.pop();
292 fs << line << "\n";
293 }
294 if (match[1] == "s") {
295 sposColumnNr = numColumns;
296 }
297 if (match[1] == "t") {
298 timeColumnNr = numColumns;
299 }
300 while (!std::regex_search(line, match, end)) {
301 line = allLines.front();
302 allLines.pop();
303 fs << line << "\n";
304 }
305 }
306 } while (!std::regex_search(line, match, data));
307
308 while (!std::regex_search(line, match, end)) {
309 line = allLines.front();
310 allLines.pop();
311 fs << line << "\n";
312 }
313
314 for (unsigned int i = 0; i < numParameters; ++ i) {
315 fs << allLines.front() << "\n";
316 allLines.pop();
317 }
318
319 while (!allLines.empty()) {
320 line = allLines.front();
321
322 linestream.str(line);
323 if (checkForTime) {
324 for (unsigned int i = 0; i < timeColumnNr; ++ i) {
325 linestream >> time;
326 }
327 }
328
329 linestream.str(line);
330 for (unsigned int i = 0; i < sposColumnNr; ++ i) {
331 linestream >> spos;
332 }
333
334 if ((spos - maxSPos) > 1e-20 * Physics::c) break;
335
336 allLines.pop();
337
338 if (!checkForTime || (time - lastTime) > 1e-20)
339 fs << line << "\n";
340
341 lastTime = time;
342 }
343
344 fs.close();
345
346 if (!allLines.empty())
347 INFOMSG(level2 << "rewind " + fileName + " to " + std::to_string(maxSPos) << " m" << endl);
348
349 return allLines.size();
350 }
351
352 /*
353 base64.cpp and base64.h
354
355 Copyright (C) 2004-2008 René Nyffenegger
356
357 This source code is provided 'as-is', without any express or implied
358 warranty. In no event will the author be held liable for any damages
359 arising from the use of this software.
360
361 Permission is granted to anyone to use this software for any purpose,
362 including commercial applications, and to alter it and redistribute it
363 freely, subject to the following restrictions:
364
365 1. The origin of this source code must not be misrepresented; you must not
366 claim that you wrote the original source code. If you use this source code
367 in a product, an acknowledgment in the product documentation would be
368 appreciated but is not required.
369
370 2. Altered source versions must be plainly marked as such, and must not be
371 misrepresented as being the original source code.
372
373 3. This notice may not be removed or altered from any source distribution.
374
375 René Nyffenegger rene.nyffenegger@adp-gmbh.ch
376
377 */
378
379 static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
380 "abcdefghijklmnopqrstuvwxyz"
381 "0123456789+/";
382
383 static inline bool is_base64(unsigned char c) {
384 return (std::isalnum(c) || (c == '+') || (c == '/'));
385 }
386
387 std::string base64_encode(const std::string& string_to_encode) {
388 const char* bytes_to_encode = string_to_encode.c_str();
389 unsigned int in_len = string_to_encode.size();
390 std::string ret;
391 int i = 0;
392 int j = 0;
393 unsigned char char_array_3[3];
394 unsigned char char_array_4[4];
395
396 while (in_len--) {
397 char_array_3[i++] = *(bytes_to_encode++);
398 if (i == 3) {
399 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
400 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
401 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
402 char_array_4[3] = char_array_3[2] & 0x3f;
403
404 for (i = 0; (i <4) ; i++)
405 ret += base64_chars[char_array_4[i]];
406 i = 0;
407 }
408 }
409
410 if (i)
411 {
412 for (j = i; j < 3; j++)
413 char_array_3[j] = '\0';
414
415 char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
416 char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
417 char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
418 char_array_4[3] = char_array_3[2] & 0x3f;
419
420 for (j = 0; (j < i + 1); j++)
421 ret += base64_chars[char_array_4[j]];
422
423 while((i++ < 3))
424 ret += '=';
425
426 }
427
428 return ret;
429 }
430
431 std::string base64_decode(std::string const& encoded_string) {
432 int in_len = encoded_string.size();
433 int i = 0;
434 int j = 0;
435 int in_ = 0;
436 unsigned char char_array_4[4], char_array_3[3];
437 std::string ret;
438
439 while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
440 char_array_4[i++] = encoded_string[in_]; in_++;
441 if (i ==4) {
442 for (i = 0; i <4; i++)
443 char_array_4[i] = base64_chars.find(char_array_4[i]);
444
445 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
446 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
447 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
448
449 for (i = 0; (i < 3); i++)
450 ret += char_array_3[i];
451 i = 0;
452 }
453 }
454
455 if (i) {
456 for (j = i; j <4; j++)
457 char_array_4[j] = 0;
458
459 for (j = 0; j <4; j++)
460 char_array_4[j] = base64_chars.find(char_array_4[j]);
461
462 char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4);
463 char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
464 char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
465
466 for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
467 }
468
469 return ret;
470 }
471}
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
#define erfinv_c1
Definition Util.cpp:53
#define erfinv_d0
Definition Util.cpp:58
#define erfinv_a0
Definition Util.cpp:43
#define erfinv_b2
Definition Util.cpp:47
#define erfinv_b1
Definition Util.cpp:48
#define erfinv_a2
Definition Util.cpp:41
#define erfinv_c2
Definition Util.cpp:52
#define erfinv_c3
Definition Util.cpp:51
#define erfinv_d1
Definition Util.cpp:57
#define erfinv_a1
Definition Util.cpp:42
#define erfinv_a3
Definition Util.cpp:40
#define erfinv_b4
Definition Util.cpp:45
#define erfinv_d2
Definition Util.cpp:56
#define erfinv_b0
Definition Util.cpp:49
#define erfinv_b3
Definition Util.cpp:46
#define erfinv_c0
Definition Util.cpp:54
T euclidean_norm(const Vector< T > &)
Euclidean norm.
Definition Vector.h:243
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
T::PETE_Expr_t::PETE_Return_t sum(const PETE_Expr< T > &expr)
Definition PETE.h:1111
Inform & level2(Inform &inf)
Definition Inform.cpp:46
Inform & endl(Inform &inf)
Definition Inform.cpp:42
#define INFOMSG(msg)
Definition IpplInfo.h:348
const std::string name
constexpr double two_pi
The value of.
Definition Physics.h:33
constexpr double c
The velocity of light in m/s.
Definition Physics.h:45
constexpr double pi
The value of.
Definition Physics.h:30
Definition Util.cpp:35
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition Util.cpp:200
std::string doubleVectorToString(const std::vector< double > &v)
Definition Util.cpp:179
Vector_t getTaitBryantAngles(Quaternion rotation, const std::string &)
Definition Util.cpp:120
std::string boolVectorToUpperString(const std::vector< bool > &b)
Definition Util.cpp:164
void toString(IteratorIn first, IteratorIn last, IteratorOut out)
Definition Util.h:311
std::string toUpper(const std::string &str)
Definition Util.cpp:150
double erfinv(double x)
Definition Util.cpp:60
std::string base64_decode(std::string const &encoded_string)
Definition Util.cpp:431
unsigned int rewindLinesSDDS(const std::string &fileName, double maxSPos, bool checkForTime)
rewind the SDDS file such that the spos of the last step is less or equal to maxSPos
Definition Util.cpp:243
void checkInt(double real, std::string name, double tolerance)
Definition Util.cpp:208
std::string getGitRevision()
Definition Util.cpp:36
std::string base64_encode(const std::string &string_to_encode)
Definition Util.cpp:387
std::string boolToUpperString(const bool &b)
Definition Util.cpp:157
bool isAllDigits(const std::string &str)
Definition Util.cpp:221
Vector_t rotate(const Vector_t &) const
Quaternion conjugate() const
Definition Quaternion.h:103
long double sum
Definition Util.h:257
long double correction
Definition Util.h:258
KahanAccumulation & operator+=(double value)
Definition Util.cpp:232
The base class for all OPAL exceptions.
static int myNode()
Definition IpplInfo.cpp:691
Vektor< double, 3 > Vector_t
Definition Vektor.h:6