OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
DumpEMFields.cpp
Go to the documentation of this file.
1 //
2 // Class DumpEMFields
3 // DumpEMFields dumps the dynamically changing fields of a Ring in a user-
4 // defined grid.
5 //
6 // Copyright (c) 2017, Chris Rogers
7 // All rights reserved
8 //
9 // This file is part of OPAL.
10 //
11 // OPAL is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
18 //
20 
22 #include "AbsBeamline/Component.h"
23 #include "Attributes/Attributes.h"
25 #include "Physics/Physics.h"
27 #include "Utilities/Util.h"
28 
29 #include <boost/filesystem.hpp>
30 
31 #include <fstream>
32 #include <cmath>
33 
34 extern Inform* gmsg;
35 
36 std::unordered_set<DumpEMFields*> DumpEMFields::dumpsSet_m;
37 
39  Action(SIZE, "DUMPEMFIELDS",
40  "The \"DUMPEMFIELDS\" statement dumps a field map to a user-defined "
41  "field file, for checking that fields are generated correctly. "
42  "The fields are written out on a grid in space and time."),
43  grid_m(NULL),
44  filename_m("") {
45 
46  // would be nice if "steps" could be integer
48  ("FILE_NAME", "Name of the file to which field data is dumped");
49 
51  ("COORDINATE_SYSTEM", "Choose to use CARTESIAN or CYLINDRICAL coordinates", {"CARTESIAN", "CYLINDRICAL"}, "CARTESIAN");
52 
54  ("X_START", "(Cartesian) Start point in the grid in x [m]");
55 
57  ("DX", "(Cartesian) Grid step size in x [m]");
58 
60  ("X_STEPS", "(Cartesian) Number of steps in x");
61 
63  ("Y_START", "(Cartesian) Start point in the grid in y [m]");
64 
66  ("DY", "(Cartesian) Grid step size in y [m]");
67 
69  ("Y_STEPS", "(Cartesian) Number of steps in y");
70 
72  ("Z_START", "Start point in the grid in z [m]");
73 
75  ("DZ", "Grid step size in z [m]");
76 
78  ("Z_STEPS", "Number of steps in z");
79 
81  ("T_START", "Start point in the grid in time [ns]");
82 
84  ("DT", "Grid step size in time [ns]");
85 
87  ("T_STEPS", "Number of steps in time");
88 
90  ("R_START", "(Cylindrical) Start point in the grid in radius [m]");
91 
93  ("DR", "(Cylindrical) Grid step size in radius [m]");
94 
96  ("R_STEPS", "(Cylindrical) Number of steps in radius");
97 
99  ("PHI_START", "(Cylindrical) Start point in the grid in phi [rad]");
100 
102  ("DPHI", "(Cylindrical) Grid step size in phi [rad]");
103 
105  ("PHI_STEPS", "(Cylindrical) Number of steps in phi");
106 
108 }
109 
110 DumpEMFields::DumpEMFields(const std::string& name, DumpEMFields* parent):
111  Action(name, parent), grid_m(NULL)
112 {}
113 
115  delete grid_m;
116  dumpsSet_m.erase(this);
117 }
118 
119 DumpEMFields* DumpEMFields::clone(const std::string& name) {
120  DumpEMFields* dumper = new DumpEMFields(name, this);
121  if (grid_m != NULL) {
122  dumper->grid_m = grid_m->clone();
123  }
124  dumper->filename_m = filename_m;
125  dumper->coordinates_m = coordinates_m;
126  if (dumpsSet_m.find(this) != dumpsSet_m.end()) {
127  dumpsSet_m.insert(dumper);
128  }
129  return dumper;
130 }
131 
133 
134  std::string coordStr = Attributes::getString(itsAttr[COORDINATE_SYSTEM]);
135  if (coordStr == "CYLINDRICAL") {
137  } else if (coordStr == "CARTESIAN") {
139  }
140 }
141 
143  buildGrid();
144  // the routine for action (OpalParser/OpalParser) calls execute and then
145  // deletes 'this'; so we must build a copy that lasts until the field maps
146  // are constructed and we are ready for tracking (which is when the field
147  // maps are written). Hence the clone call below.
148  dumpsSet_m.insert(this->clone(""));
149 }
150 
152  std::vector<double> spacing(4);
153  std::vector<double> origin(4);
154  std::vector<int> gridSize(4);
156 
158  origin[0] = Attributes::getReal(itsAttr[R_START]);
159  spacing[0] = Attributes::getReal(itsAttr[DR]);
161  checkInt(nr, "R_STEPS");
162  gridSize[0] = nr;
163 
164  origin[1] = Attributes::getReal(itsAttr[PHI_START]);
165  spacing[1] = Attributes::getReal(itsAttr[DPHI]);
166  double nphi = Attributes::getReal(itsAttr[PHI_STEPS]);
167  checkInt(nphi, "PHI_STEPS");
168  gridSize[1] = nphi;
169  } else {
170  origin[0] = Attributes::getReal(itsAttr[X_START]);
171  spacing[0] = Attributes::getReal(itsAttr[DX]);
172  double nx = Attributes::getReal(itsAttr[X_STEPS]);
173  checkInt(nx, "X_STEPS");
174  gridSize[0] = nx;
175 
176  origin[1] = Attributes::getReal(itsAttr[Y_START]);
177  spacing[1] = Attributes::getReal(itsAttr[DY]);
178  double ny = Attributes::getReal(itsAttr[Y_STEPS]);
179  checkInt(ny, "Y_STEPS");
180  gridSize[1] = ny;
181  }
182  origin[2] = Attributes::getReal(itsAttr[Z_START]);
183  spacing[2] = Attributes::getReal(itsAttr[DZ]);
184  double nz = Attributes::getReal(itsAttr[Z_STEPS]);
185  checkInt(nz, "Z_STEPS");
186  gridSize[2] = nz;
187 
188  origin[3] = Attributes::getReal(itsAttr[T_START]);
189  spacing[3] = Attributes::getReal(itsAttr[DT]);
190  double nt = Attributes::getReal(itsAttr[T_STEPS]);
191  checkInt(nt, "T_STEPS");
192  gridSize[3] = nt;
193 
194  if (grid_m != NULL) {
195  delete grid_m;
196  }
197 
198  grid_m = new interpolation::NDGrid(4, &gridSize[0], &spacing[0], &origin[0]);
199 
201 }
202 
205  for (dump_iter it = dumpsSet_m.begin(); it != dumpsSet_m.end(); ++it) {
206  (*it)->writeFieldThis(field);
207  }
208 }
209 
210 void DumpEMFields::checkInt(double real, std::string name, double tolerance) {
211  real += tolerance; // prevent rounding error
212  if (std::abs(std::floor(real) - real) > 2*tolerance) {
213  throw OpalException("DumpEMFields::checkInt",
214  "Value for " + name +
215  " should be an integer but a real value was found");
216  }
217  if (std::floor(real) < 0.5) {
218  throw OpalException("DumpEMFields::checkInt",
219  "Value for " + name + " should be 1 or more");
220  }
221 }
222 
223 void DumpEMFields::writeHeader(std::ofstream& fout) const {
224  fout << grid_m->end().toInteger() << "\n";
226  fout << 1 << " r [mm]\n";
227  fout << 2 << " phi [degree]\n";
228  } else {
229  fout << 1 << " x [mm]\n";
230  fout << 2 << " y [mm]\n";
231  }
232  fout << 3 << " z [mm]\n";
233  fout << 4 << " t [ns]\n";
235  fout << 5 << " Br [kGauss]\n";
236  fout << 6 << " Bphi [kGauss]\n";
237  fout << 7 << " Bz [kGauss]\n";
238  fout << 8 << " Er [MV/m]\n";
239  fout << 9 << " Ephi [MV/m]\n";
240  fout << 10 << " Ez [MV/m]\n";
241  } else {
242  fout << 5 << " Bx [kGauss]\n";
243  fout << 6 << " By [kGauss]\n";
244  fout << 7 << " Bz [kGauss]\n";
245  fout << 8 << " Ex [MV/m]\n";
246  fout << 9 << " Ey [MV/m]\n";
247  fout << 10 << " Ez [MV/m]\n";
248  }
249  fout << 0 << std::endl;
250 }
251 
253  const Vector_t& pointIn,
254  const double& time,
255  std::ofstream& fout) const {
256  Vector_t centroid(0., 0., 0.);
257  Vector_t E(0., 0., 0.);
258  Vector_t B(0., 0., 0.);
259  Vector_t point = pointIn;
261  // pointIn is r, phi, z
262  point[0] = std::cos(pointIn[1])*pointIn[0];
263  point[1] = std::sin(pointIn[1])*pointIn[0];
264  }
265 
266  field->apply(point, centroid, time, E, B);
267  Vector_t Bout = B;
268  Vector_t Eout = E;
270  // pointIn is r, phi, z
271  Bout[0] = B[0]*std::cos(pointIn[1])+B[1]*std::sin(pointIn[1]);
272  Bout[1] = -B[0]*std::sin(pointIn[1])+B[1]*std::cos(pointIn[1]);
273  Eout[0] = E[0]*std::cos(pointIn[1])+E[1]*std::sin(pointIn[1]);
274  Eout[1] = -E[0]*std::sin(pointIn[1])+E[1]*std::cos(pointIn[1]);
275  fout << pointIn[0] << " " << pointIn[1]*Physics::rad2deg << " " << pointIn[2] << " " << time << " ";
276  } else {
277  fout << pointIn[0] << " " << pointIn[1] << " " << pointIn[2] << " " << time << " ";
278  }
279 
280  fout << Bout[0] << " " << Bout[1] << " " << Bout[2] << " ";
281  fout << Eout[0] << " " << Eout[1] << " " << Eout[2] << "\n";
282 }
283 
285  if (grid_m == NULL) {
286  throw OpalException("DumpEMFields::writeFieldThis",
287  "The grid was NULL; there was a problem with the DumpEMFields initialisation.");
288  }
289  if (field == NULL) {
290  throw OpalException("DumpEMFields::writeFieldThis",
291  "The field to be written was NULL.");
292  }
293 
294  *gmsg << *this << endl;
295 
296  std::string fname;
297  if (boost::filesystem::path(filename_m).is_absolute() == true) {
298  fname = filename_m;
299  } else {
300  fname = Util::combineFilePath({
302  filename_m
303  });
304  }
305 
306  std::vector<double> point_std(4);
307  Vector_t point(0., 0., 0.);
308  std::ofstream fout;
309  try {
310  fout.open(fname.c_str(), std::ofstream::out);
311  } catch (std::exception& exc) {
312  throw OpalException("DumpEMFields::writeFieldThis",
313  "Failed to open DumpEMFields file " + filename_m);
314  }
315  if (!fout.good()) {
316  throw OpalException("DumpEMFields::writeFieldThis",
317  "Failed to open DumpEMFields file " + filename_m);
318  }
319  // set precision
320  writeHeader(fout);
322  it < grid_m->end();
323  ++it) {
324  it.getPosition(&point_std[0]);
325  for (size_t i = 0; i < 3; ++i) {
326  point[i] = point_std[i];
327  }
328  double time = point_std[3];
329  writeFieldLine(field, point, time, fout);
330  }
331  if (!fout.good()) {
332  throw OpalException("DumpEMFields::writeFieldThis",
333  "Something went wrong during writing " + filename_m);
334  }
335  fout.close();
336 }
337 
338 void DumpEMFields::print(std::ostream& os) const {
339  os << "* ************* D U M P E M F I E L D S ****************************************** " << std::endl;
340  os << "* File name: " << filename_m << '\n';
342  os << "* Coordinate system: " << "Cartesian" << '\n'
343  << "* X_START = " << Attributes::getReal(itsAttr[X_START]) << " [m]\n"
344  << "* DX = " << Attributes::getReal(itsAttr[DX]) << " [m]\n"
345  << "* X_STEPS = " << Attributes::getReal(itsAttr[X_STEPS]) << '\n'
346  << "* Y_START = " << Attributes::getReal(itsAttr[Y_START]) << " [m]\n"
347  << "* DY = " << Attributes::getReal(itsAttr[DY]) << " [m]\n"
348  << "* Y_STEPS = " << Attributes::getReal(itsAttr[Y_STEPS]) << '\n';
350  os << "* Coordinate system: " << "Cylindrical" << '\n'
351  << "* R_START = " << Attributes::getReal(itsAttr[R_START]) << " [m]\n"
352  << "* DR = " << Attributes::getReal(itsAttr[DR]) << " [m]\n"
353  << "* R_STEPS = " << Attributes::getReal(itsAttr[R_STEPS]) << '\n'
354  << "* PHI_START = " << Attributes::getReal(itsAttr[PHI_START]) << " [rad]\n"
355  << "* DPHI = " << Attributes::getReal(itsAttr[DPHI]) << " [rad]\n"
356  << "* PHI_STEPS = " << Attributes::getReal(itsAttr[PHI_STEPS]) << '\n';
357  }
358  os << "* Z_START = " << Attributes::getReal(itsAttr[Z_START]) << " [m]\n"
359  << "* DZ = " << Attributes::getReal(itsAttr[DZ]) << " [m]\n"
360  << "* Z_STEPS = " << Attributes::getReal(itsAttr[Z_STEPS]) << '\n'
361  << "* T_START = " << Attributes::getReal(itsAttr[T_START]) << " [ns]\n"
362  << "* DT = " << Attributes::getReal(itsAttr[DT]) << " [ns]\n"
363  << "* T_STEPS = " << Attributes::getReal(itsAttr[T_STEPS]) << '\n';
364  os << "* ********************************************************************************** " << std::endl;
365 }
@ SIZE
Definition: IndexMap.cpp:174
Inform * gmsg
Definition: Main.cpp:62
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
FLieGenerator< T, N > real(const FLieGenerator< std::complex< T >, N > &)
Take real part of a complex generator.
const int nr
Definition: ClassicRandom.h:24
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
PETE_TUTree< FnFloor, typename T::PETE_Expr_t > floor(const PETE_Expr< T > &l)
Definition: PETE.h:733
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
const std::string name
double getReal(const Attribute &attr)
Return real value.
Definition: Attributes.cpp:252
Attribute makePredefinedString(const std::string &name, const std::string &help, const std::initializer_list< std::string > &predefinedStrings)
Make predefined string attribute.
Definition: Attributes.cpp:409
Attribute makeReal(const std::string &name, const std::string &help)
Make real attribute.
Definition: Attributes.cpp:240
std::string getString(const Attribute &attr)
Get string value.
Definition: Attributes.cpp:343
Attribute makeString(const std::string &name, const std::string &help)
Make string attribute.
Definition: Attributes.cpp:332
constexpr double rad2deg
The conversion factor from radians to degrees.
Definition: Physics.h:45
std::string::iterator iterator
Definition: MSLang.h:16
std::string combineFilePath(std::initializer_list< std::string > ilist)
Definition: Util.cpp:139
The base class for all OPAL actions.
Definition: Action.h:30
void registerOwnership(const AttributeHandler::OwnerType &itsClass) const
Definition: Object.cpp:191
std::vector< Attribute > itsAttr
The object attributes.
Definition: Object.h:216
static OpalData * getInstance()
Definition: OpalData.cpp:195
std::string getAuxiliaryOutputDirectory() const
get the name of the the additional data directory
Definition: OpalData.cpp:650
virtual void writeFieldThis(Component *field)
virtual void buildGrid()
void print(std::ostream &os) const
static std::unordered_set< DumpEMFields * > dumpsSet_m
Definition: DumpEMFields.h:147
void parseCoordinateSystem()
std::string filename_m
Definition: DumpEMFields.h:144
static void writeFields(Component *field)
interpolation::NDGrid * grid_m
Definition: DumpEMFields.h:143
CoordinateSystem coordinates_m
Definition: DumpEMFields.h:145
void writeHeader(std::ofstream &fout) const
virtual void execute()
static void checkInt(double value, std::string name, double tolerance=1e-9)
virtual DumpEMFields * clone(const std::string &name)
void writeFieldLine(Component *field, const Vector_t &point, const double &time, std::ofstream &fout) const
virtual ~DumpEMFields()
Interface for a single beam element.
Definition: Component.h:50
virtual bool apply(const size_t &i, const double &t, Vector_t &E, Vector_t &B)
Definition: Component.cpp:99
Mesh::Iterator begin() const
Definition: NDGrid.h:358
Mesh::Iterator end() const
Definition: NDGrid.h:362
NDGrid * clone()
Definition: NDGrid.h:350
The base class for all OPAL exceptions.
Definition: OpalException.h:28
Definition: Inform.h:42