OPALX (Object Oriented Parallel Accelerator Library for Exascal) MINIorX
OPALX
FM1DDynamic.cpp
Go to the documentation of this file.
2#include "Fields/Fieldmap.hpp"
3#include "Physics/Physics.h"
4#include "Physics/Units.h"
6#include "Utilities/Util.h"
7
8#include "gsl/gsl_fft_real.h"
9
10#include <fstream>
11#include <iostream>
12
13FM1DDynamic::FM1DDynamic(std::string aFilename) : Fieldmap(aFilename) {
15
16 std::ifstream fieldFile(Filename_m.c_str());
17 if (fieldFile.good()) {
18 bool parsingPassed = readFileHeader(fieldFile);
19 parsingPassed = checkFileData(fieldFile, parsingPassed);
20 fieldFile.close();
21
22 if (!parsingPassed) {
24 zEnd_m = zBegin_m - 1.0e-3;
25 } else
27
29
30 } else {
32 zBegin_m = 0.0;
33 zEnd_m = -1e-3;
34 }
35}
36
40
42 if (fourierCoefs_m.empty()) {
43 std::ifstream fieldFile(Filename_m.c_str());
44 stripFileHeader(fieldFile);
45
46 double* fieldData = new double[2 * numberOfGridPoints_m - 1];
47 double maxEz = readFileData(fieldFile, fieldData);
48 fieldFile.close();
49 computeFourierCoefficients(maxEz, fieldData);
50 delete[] fieldData;
51
52 *ippl::Info << typeset_msg("Read in field map '" + Filename_m + "'", "info") << endl;
53 }
54}
55
57 if (!fourierCoefs_m.empty()) {
58 fourierCoefs_m.clear();
59
60 *ippl::Info << typeset_msg("Freed field map '" + Filename_m + "'", "info") << endl;
61 }
62}
63
66 std::vector<double> fieldComponents;
67 computeFieldOnAxis(R(2) - zBegin_m, fieldComponents);
68 computeFieldOffAxis(R, E, B, fieldComponents);
69
70 return false;
71}
72
75 const DiffDirection& /*dir*/) const {
76 double kz = Physics::two_pi * (R(2) - zBegin_m) / length_m + Physics::pi;
77 double eZPrime = 0.0;
78
79 int coefIndex = 1;
80 for (int n = 1; n < accuracy_m; ++n) {
81 eZPrime +=
83 * (-fourierCoefs_m.at(coefIndex) * sin(kz * n)
84 - fourierCoefs_m.at(coefIndex + 1) * cos(kz * n)));
85 coefIndex += 2;
86 }
87
88 E(2) += eZPrime;
89
90 return false;
91}
92
93void FM1DDynamic::getFieldDimensions(double& zBegin, double& zEnd) const {
94 zBegin = zBegin_m;
95 zEnd = zEnd_m;
96}
97
99 double& /*xIni*/, double& /*xFinal*/, double& /*yIni*/, double& /*yFinal*/, double& /*zIni*/,
100 double& /*zFinal*/) const {
101}
102
104}
105
106void FM1DDynamic::getInfo(Inform* msg) {
107 (*msg) << Filename_m << " (1D dynamic); zini= " << zBegin_m << " m; zfinal= " << zEnd_m << " m;"
108 << endl;
109}
110
112 return frequency_m;
113}
114
115void FM1DDynamic::setFrequency(double frequency) {
116 frequency_m = frequency;
117}
118
119void FM1DDynamic::getOnaxisEz(std::vector<std::pair<double, double>>& eZ) {
120 eZ.resize(numberOfGridPoints_m);
121 std::ifstream fieldFile(Filename_m.c_str());
122 stripFileHeader(fieldFile);
123 double maxEz = readFileData(fieldFile, eZ);
124 fieldFile.close();
125 scaleField(maxEz, eZ);
126}
127
128bool FM1DDynamic::checkFileData(std::ifstream& fieldFile, bool parsingPassed) {
129 double tempDouble;
130 for (int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex)
131 parsingPassed = parsingPassed && interpretLine<double>(fieldFile, tempDouble);
132
133 return parsingPassed && interpreteEOF(fieldFile);
134}
135
138 std::vector<double> fieldComponents) const {
139 double radiusSq = pow(R(0), 2.0) + pow(R(1), 2.0);
140 double transverseEFactor =
141 (fieldComponents.at(1) * (0.5 - radiusSq * twoPiOverLambdaSq_m / 16.0)
142 - radiusSq * fieldComponents.at(3) / 16.0);
143 double transverseBFactor =
144 ((fieldComponents.at(0) * (0.5 - radiusSq * twoPiOverLambdaSq_m / 16.0)
145 - radiusSq * fieldComponents.at(2) / 16.0)
147
148 E(0) += -R(0) * transverseEFactor;
149 E(1) += -R(1) * transverseEFactor;
150 E(2) +=
151 (fieldComponents.at(0) * (1.0 - radiusSq * twoPiOverLambdaSq_m / 4.0)
152 - radiusSq * fieldComponents.at(2) / 4.0);
153
154 B(0) += -R(1) * transverseBFactor;
155 B(1) += R(0) * transverseBFactor;
156}
157
158void FM1DDynamic::computeFieldOnAxis(double z, std::vector<double>& fieldComponents) const {
159 double kz = Physics::two_pi * z / length_m + Physics::pi;
160 fieldComponents.push_back(fourierCoefs_m.at(0));
161 fieldComponents.push_back(0.0);
162 fieldComponents.push_back(0.0);
163 fieldComponents.push_back(0.0);
164
165 int coefIndex = 1;
166 for (int n = 1; n < accuracy_m; ++n) {
167 double kn = n * Physics::two_pi / length_m;
168 double coskzn = cos(kz * n);
169 double sinkzn = sin(kz * n);
170
171 fieldComponents.at(0) +=
172 (fourierCoefs_m.at(coefIndex) * coskzn - fourierCoefs_m.at(coefIndex + 1) * sinkzn);
173
174 fieldComponents.at(1) +=
175 kn
176 * (-fourierCoefs_m.at(coefIndex) * sinkzn - fourierCoefs_m.at(coefIndex + 1) * coskzn);
177
178 double derivCoeff = pow(kn, 2.0);
179 fieldComponents.at(2) +=
180 derivCoeff
181 * (-fourierCoefs_m.at(coefIndex) * coskzn + fourierCoefs_m.at(coefIndex + 1) * sinkzn);
182 derivCoeff *= kn;
183 fieldComponents.at(3) +=
184 derivCoeff
185 * (fourierCoefs_m.at(coefIndex) * sinkzn + fourierCoefs_m.at(coefIndex + 1) * coskzn);
186
187 coefIndex += 2;
188 }
189}
190
191void FM1DDynamic::computeFourierCoefficients(double maxEz, double fieldData[]) {
192 const unsigned int totalSize = 2 * numberOfGridPoints_m - 1;
193 gsl_fft_real_wavetable* waveTable = gsl_fft_real_wavetable_alloc(totalSize);
194 gsl_fft_real_workspace* workSpace = gsl_fft_real_workspace_alloc(totalSize);
195 gsl_fft_real_transform(fieldData, 1, totalSize, waveTable, workSpace);
196
197 /*
198 * Normalize the Fourier coefficients such that the max field value
199 * is 1 V/m.
200 */
201 maxEz *= Units::Vpm2MVpm;
202
203 fourierCoefs_m.push_back(fieldData[0] / (totalSize * maxEz));
204 for (int coefIndex = 1; coefIndex < 2 * accuracy_m - 1; ++coefIndex)
205 fourierCoefs_m.push_back(2.0 * fieldData[coefIndex] / (totalSize * maxEz));
206
207 gsl_fft_real_workspace_free(workSpace);
208 gsl_fft_real_wavetable_free(waveTable);
209}
210
212 // Convert to angular frequency in Hz.
214
215 // Convert to m.
220
222}
223
224double FM1DDynamic::readFileData(std::ifstream& fieldFile, double fieldData[]) {
225 double maxEz = 0.0;
226 for (int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex) {
227 interpretLine<double>(fieldFile, fieldData[numberOfGridPoints_m - 1 + dataIndex]);
228 if (std::abs(fieldData[numberOfGridPoints_m + dataIndex]) > maxEz)
229 maxEz = std::abs(fieldData[numberOfGridPoints_m + dataIndex]);
230
231 /*
232 * Mirror the field map about minimum z value to ensure that it
233 * is periodic.
234 */
235 if (dataIndex != 0)
236 fieldData[numberOfGridPoints_m - 1 - dataIndex] =
237 fieldData[numberOfGridPoints_m + dataIndex];
238 }
239
240 if (!normalize_m)
241 maxEz = 1.0;
242
243 return maxEz;
244}
245
247 std::ifstream& fieldFile, std::vector<std::pair<double, double>>& eZ) {
248 double maxEz = 0.0;
249 double deltaZ = (zEnd_m - zBegin_m) / (numberOfGridPoints_m - 1);
250 for (int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex) {
251 eZ.at(dataIndex).first = deltaZ * dataIndex;
252 interpretLine<double>(fieldFile, eZ.at(dataIndex).second);
253 if (std::abs(eZ.at(dataIndex).second) > maxEz)
254 maxEz = std::abs(eZ.at(dataIndex).second);
255 }
256
257 if (!normalize_m)
258 maxEz = 1.0;
259
260 return maxEz;
261}
262
263bool FM1DDynamic::readFileHeader(std::ifstream& fieldFile) {
264 std::string tempString;
265 int tempInt;
266
267 bool parsingPassed = true;
268 try {
269 parsingPassed = interpretLine<std::string, int>(fieldFile, tempString, accuracy_m);
270 } catch (GeneralClassicException& e) {
272 fieldFile, tempString, accuracy_m, tempString);
273
274 tempString = Util::toUpper(tempString);
275 if (tempString != "TRUE" && tempString != "FALSE")
277 "FM1DDynamic::FM1DDynamic",
278 "The third string on the first line of 1D field "
279 "maps has to be either TRUE or FALSE");
280
281 normalize_m = (tempString == "TRUE");
282 }
283
284 parsingPassed =
285 parsingPassed
287 parsingPassed = parsingPassed && interpretLine<double>(fieldFile, frequency_m);
288 parsingPassed =
289 parsingPassed && interpretLine<double, double, int>(fieldFile, rBegin_m, rEnd_m, tempInt);
290
292
295
296 return parsingPassed;
297}
298
299void FM1DDynamic::scaleField(double maxEz, std::vector<std::pair<double, double>>& eZ) {
300 for (int dataIndex = 0; dataIndex < numberOfGridPoints_m; ++dataIndex)
301 eZ.at(dataIndex).second /= maxEz;
302}
303
304void FM1DDynamic::stripFileHeader(std::ifstream& fieldFile) {
305 std::string tempString;
306
307 getLine(fieldFile, tempString);
308 getLine(fieldFile, tempString);
309 getLine(fieldFile, tempString);
310 getLine(fieldFile, tempString);
311}
ippl::Vector< T, Dim > Vector_t
@ T1DDynamic
Definition Fieldmap.h:17
DiffDirection
Definition Fieldmap.h:55
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
constexpr double MHz2Hz
Definition Units.h:113
constexpr double cm2m
Definition Units.h:35
constexpr double Vpm2MVpm
Definition Units.h:125
std::string toUpper(const std::string &str)
Definition Util.cpp:145
MapType Type
Definition Fieldmap.h:118
bool interpreteEOF(std::ifstream &in)
Definition Fieldmap.cpp:516
void disableFieldmapWarning()
Definition Fieldmap.cpp:569
bool normalize_m
Definition Fieldmap.h:123
static std::string typeset_msg(const std::string &msg, const std::string &title)
Definition Fieldmap.cpp:607
std::string Filename_m
Definition Fieldmap.h:120
bool interpretLine(std::ifstream &in, S &value, const bool &file_length_known=true)
void getLine(std::ifstream &in, std::string &buffer)
Definition Fieldmap.h:124
void noFieldmapWarning()
Definition Fieldmap.cpp:576
virtual bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
virtual void getOnaxisEz(std::vector< std::pair< double, double > > &eZ)
double zBegin_m
Maximum radius of field.
Definition FM1DDynamic.h:49
virtual void swap()
void computeFieldOffAxis(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, std::vector< double > fieldComponents) const
void computeFieldOnAxis(double z, std::vector< double > &fieldComponents) const
int numberOfGridPoints_m
Field length.
Definition FM1DDynamic.h:52
void stripFileHeader(std::ifstream &fieldFile)
FM1DDynamic(std::string aFilename)
double twoPiOverLambdaSq_m
Field angular frequency (Hz).
Definition FM1DDynamic.h:45
double readFileData(std::ifstream &fieldFile, double fieldData[])
std::vector< double > fourierCoefs_m
Number of Fourier coefficients to use reconstructing field.
Definition FM1DDynamic.h:55
double rEnd_m
Minimum radius of field.
Definition FM1DDynamic.h:48
friend class Fieldmap
Fourier coefficients derived from field map.
Definition FM1DDynamic.h:57
double length_m
Longitudinal end of field.
Definition FM1DDynamic.h:51
void scaleField(double maxEz, std::vector< std::pair< double, double > > &eZ)
void convertHeaderData()
bool checkFileData(std::ifstream &fieldFile, bool parsingPassed)
virtual double getFrequency() const
double zEnd_m
Longitudinal start of field.
Definition FM1DDynamic.h:50
virtual void freeMap()
virtual void readMap()
virtual void getFieldDimensions(double &zBegin, double &zEnd) const
virtual bool getFieldstrength(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B) const
int accuracy_m
Number of grid points in field input file.
Definition FM1DDynamic.h:54
void computeFourierCoefficients(double maxEz, double fieldData[])
double frequency_m
Definition FM1DDynamic.h:44
double rBegin_m
2 Pi divided by the field RF wavelength squared.
Definition FM1DDynamic.h:47
virtual void getInfo(Inform *)
bool readFileHeader(std::ifstream &fieldFile)
virtual void setFrequency(double freq)