65 :
SectorField(file_name), interpolator_m(nullptr), symmetry_m(dipole),
66 units_m(6, 1.), filename_m(file_name), phiOffset_m(0.),
67 poly_order_m(polynomial_order), smoothing_order_m(smoothing_order) {
84 "SectorMagneticFieldMap::SectorMagneticFieldMap",
85 "Attempt to construct different SectorFieldMaps with same "+
86 std::string(
"file but different settings")
97 :
SectorField(field), interpolator_m(nullptr), symmetry_m(field.symmetry_m),
98 units_m(field.units_m),
99 filename_m(field.filename_m), phiOffset_m(field.phiOffset_m) {
123 "SectorMagneticFieldMap::setInterpolator",
124 "Attempt to load interpolator with PointDimension != 3")
128 "SectorMagneticFieldMap::setInterpolator",
129 "Attempt to load interpolator with ValueDimension != 3"
134 "SectorMagneticFieldMap::setInterpolator",
135 "Attempt to load interpolator with grid not ThreeDGrid"
169 if (sym ==
"Dipole") {
173 "SectorMagneticFieldMap::StringToSymmetry",
174 "Didn't recognise symmetry type "+sym
187 "SectorMagneticFieldMap::SymmetryToString",
188 "Didn't recognise symmetry type " + std::to_string(sym)
215 double R_temp[3] = {R_c(0)+radius, R_c(1), R_c(2)};
216 double B_temp[3] = {0., 0., 0.};
218 bool mirror = R_temp[1] < midplane;
220 R_temp[1] = midplane + (midplane - R_temp[1]);
244 R_temp[1] = 2*ymin-R_temp[1];
255 _fields = std::map<std::string, SectorMagneticFieldMap*>();
261 (*msg) <<
Filename_m <<
" (3D Sector Magnetostatic);\n"
262 <<
" zini= " << bbmin[1] <<
" mm; zfinal= " << bbmax[1] <<
" mm;\n"
263 <<
" phiini= " << bbmin[2] <<
" rad; phifinal= " << bbmax[2] <<
" rad;\n"
264 <<
" rini= " << bbmin[0] <<
" mm; rfinal= " << bbmax[0] <<
" mm;"
271 out <<
Filename_m <<
" (3D Sector Magnetostatic);\n"
272 <<
" zini= " << bbmin[1] <<
" m; zfinal= " << bbmax[1] <<
" mm;\n"
273 <<
" phiini= " << bbmin[2] <<
" rad; phifinal= " << bbmax[2] <<
" rad;\n"
274 <<
" rini= " << bbmin[0] <<
" m; rfinal= " << bbmax[0] <<
" mm;\n"
280 throw(
LogicalError(
"SectorMagneticFieldMap::getFieldDerivative",
281 "Field map derivatives not implemented"));
296 std::string file_name,
297 std::vector<double>
units,
299 int polynomial_order,
300 int smoothing_order) {
302 *
gmsg <<
"* Opening sector field map " << file_name
303 <<
" fit order " << polynomial_order
304 <<
" smoothing order " << smoothing_order <<
endl;
306 std::vector< std::vector<double> > field_points =
readLines
311 if (polynomial_order == 1 && smoothing_order == 1) {
323 }
catch(std::exception& exc) {
325 "SectorMagneticFieldMap::IO::ReadMap",
326 "Failed to read file "+file_name+
" with "+(&exc)->what()
333 std::vector< std::vector<double> > field_points,
336 int polynomial_order,
337 int smoothing_order) {
341 "SectorMagneticFieldMap::IO::getInterpolatorPolyPatch",
342 "Failed to recognise symmetry type"
345 std::vector< std::vector<double> > data(field_points.size(),
346 std::vector<double>(3));
347 for (
size_t i = 0; i < field_points.size(); ++i) {
348 data[i][0] = field_points[i][3];
349 data[i][1] = field_points[i][4];
350 data[i][2] = field_points[i][5];
354 *
gmsg <<
"Calculating polynomials..." <<
endl;
355 PPSolveFactory solver(grid, data, polynomial_order, smoothing_order);
366 std::string(
"field points during read ")+
367 std::string(
"operation; this could mean that the field ")+
368 std::string(
"map was not complete, or that OPAL could ")+
369 std::string(
"not calculate regular grid spacings properly. ")+
370 std::string(
"Check that the field map is on a cylindrical ")+
371 std::string(
"grid written in Cartesian coordinates and the ")+
372 std::string(
"grid points are written with enough precision (")+
373 std::string(
"check the grid size information above).");
376 (
const std::vector< std::vector<double> > field_points,
380 double *** Bx, *** By, *** Bz;
382 Bx =
new double**[grid->
xSize()];
383 By =
new double**[grid->
xSize()];
384 Bz =
new double**[grid->
xSize()];
385 for (
int i = 0; i < grid->
xSize(); ++i) {
386 Bx[i] =
new double*[grid->
ySize()];
387 By[i] =
new double*[grid->
ySize()];
388 Bz[i] =
new double*[grid->
ySize()];
389 for (
int j = 0; j < grid->
ySize(); ++j) {
390 Bx[i][j] =
new double[grid->
zSize()];
391 By[i][j] =
new double[grid->
zSize()];
392 Bz[i][j] =
new double[grid->
zSize()];
393 for (
int k = 0; k < grid->
zSize(); ++k) {
394 if (index >=
int(field_points.size())) {
397 "SectorMagneticFieldMap::IO::getInterpolator",
398 "Ran out of "+errMsg1)
401 Bx[i][j][k] = field_points[index][3];
402 By[i][j][k] = field_points[index][4];
403 Bz[i][j][k] = field_points[index][5];
408 if (index !=
int(field_points.size())) {
410 "SectorMagneticFieldMap::IO::getInterpolator",
416 return interpolatorMap;
420 std::vector<double> field_item2) {
421 const int* order = sortOrder_m;
422 if (std::abs(field_item1[order[0]] - field_item2[order[0]]) > floatTolerance_m) {
423 return field_item1[order[0]] < field_item2[order[0]];
425 if (std::abs(field_item1[order[1]] - field_item2[order[1]]) > floatTolerance_m) {
426 return field_item1[order[1]] < field_item2[order[1]];
428 return field_item1[order[2]] < field_item2[order[2]];
432 (std::string file_name, std::vector<double>
units) {
433 std::vector< std::vector<double> > field_points;
435 if (
units.size() != 6) {
437 "SectorMagneticFieldMap::IO::ReadLines",
438 "Units should be of length 6"
442 std::ifstream fin(file_name.c_str());
443 if (!fin || !fin.is_open()) {
445 "SectorMagneticFieldMap::IO::ReadLines",
446 "Failed to open file "+file_name
450 *
gmsg <<
"* Opened "+file_name <<
endl;
451 for (
size_t i = 0; i < 8; ++i) {
452 std::getline(fin, line);
457 std::vector<double> field(6);
458 fin >> field[0] >> field[1] >> field[2] >> field[3] >> field[4]
461 for (
size_t i = 0; i < 6; ++i) {
462 field[i] *=
units[i];
464 field_points.push_back(field);
468 *
gmsg <<
"* Read " << line_number <<
" lines" <<
endl;
471 for (
size_t i = 0; i < field_points.size(); ++i) {
476 std::sort(field_points.begin(), field_points.end(),
482 in2 = in2*(1+floatTolerance_m)+floatTolerance_m;
487 (
const std::vector< std::vector<double> > field_points,
489 std::vector<double> r_grid(1, field_points[0][0]);
490 std::vector<double> y_grid(1, field_points[0][1]);
491 std::vector<double> phi_grid(1, field_points[0][2]);
492 for (
size_t i = 0; i < field_points.size(); ++i) {
493 if (floatGreaterEqual(field_points[i][0], r_grid.back())) {
494 r_grid.push_back(field_points[i][0]);
496 if (floatGreaterEqual(field_points[i][1], y_grid.back())) {
497 y_grid.push_back(field_points[i][1]);
499 if (floatGreaterEqual(field_points[i][2], phi_grid.back())) {
500 phi_grid.push_back(field_points[i][2]);
505 *
gmsg <<
"* Grid size (r, y, phi) = ("
506 << r_grid.size() <<
", " << y_grid.size() <<
", " << phi_grid.size()
508 *
gmsg <<
"* Grid min (r [mm], y [mm], phi [rad]) = ("
509 << r_grid[0] <<
", " << y_grid[0] <<
", " << phi_grid[0]
511 *
gmsg <<
"* Grid max (r [mm], y [mm], phi [rad]) = ("
512 << r_grid.back() <<
", " << y_grid.back() <<
", " << phi_grid.back()
Inform & endl(Inform &inf)
constexpr double e
The value of.
std::string::iterator iterator
Interpolator3dGridTo3d interpolates from 3d grid to a 3d vector.
Patches together many SquarePolynomialVectors to make a multidimensional polynomial spline.
PPSolveFactory solves the system of linear equations to interpolate from a grid of points using highe...
PolynomialPatch * solve()
Solve the system of equations to generate a PolynomialPatch object.
ThreeDGrid holds grid information for a rectangular grid used in e.g.
double maxZ() const
Return the largest value of z in the grid.
double maxX() const
Return the largest value of x in the grid.
int zSize() const
Get size of z data.
double maxY() const
Return the largest value of y in the grid.
int xSize() const
Get size of x data.
double minY() const
Return the smallest value of y in the grid.
void setConstantSpacing(bool spacing)
Set to true to use constant spacing.
double minX() const
Return the smallest value of x in the grid.
int ySize() const
Get size of y data.
double minZ() const
Return the smallest value of z in the grid.
VectorMap is an abstract class that defines mapping from one vector to another.
virtual unsigned int getValueDimension() const =0
Return the dimension of the value (output)
virtual Mesh * getMesh() const
Return the mesh used by the vector map or nullptr if no mesh.
virtual unsigned int getPointDimension() const =0
Return the dimension of the point (input)
virtual void function(const double *point, double *value) const =0
Pure virtual function to fill the array value with data evaluated at point.
SectorField is an abstraction type for a sector field map i.e.
virtual std::vector< double > getPolarBoundingBoxMin() const
Get the minimum bounding box in polar coordinates.
bool isInBoundingBox(const double R_p[]) const
Return true if polar vector R_p is within polar bounding box.
std::string Filename_m
Keep the filename.
virtual std::vector< double > getPolarBoundingBoxMax() const
Get the maximum bounding box in polar coordinates.
static void convertToPolar(double *position)
Convert a position from cartesian to polar coordinates.
void setPolarBoundingBox(double bbMinR, double bbMinY, double bbMinPhi, double bbMaxR, double bbMaxY, double bbMaxPhi, double bbTolR, double bbTolY, double bbTolPhi)
Set the bounding boxes from polar coordinates.
handles field map grids with sector geometry
bool applySymmetry(double *R_temp) const
Reflect R_temp about y if below bbmin.
const std::string filename_m
void freeMap()
Delete the field map interpolator and set pointer to nullptr.
interpolation::VectorMap * interpolator_m
static void clearFieldCache()
Delete cached fields.
std::vector< double > units_m
void setInterpolator(interpolation::VectorMap *interpolator)
Set the interpolator.
void readMap()
Read in the field map from the file.
static std::string SymmetryToString(symmetry sym)
double getDeltaPhi() const
Get change in azimuthal angle between entrance and exit.
SectorMagneticFieldMap(std::string file_name, std::string symmetry, double length_units, double field_units, int polynomial_order, int smoothing_order)
Generate the field map by calling SectorMagneticFieldMap::IO.
static symmetry StringToSymmetry(std::string name)
void setSymmetry(std::string name)
Set the field map symmetry.
interpolation::VectorMap * getInterpolator()
Get a pointer to the interpolator or nullptr if it is not set.
static const double fractionalBBPhiTolerance_m
~SectorMagneticFieldMap()
Destructor - delete allocated memory.
bool getFieldDerivative(const Vector_t< double, 3 > &R, Vector_t< double, 3 > &E, Vector_t< double, 3 > &B, const DiffDirection &dir) const
Not implemented - throws a LogicalError.
void getInfo(Inform *msg)
Print summary information about the field map to Inform.
bool getFieldstrength(const Vector_t< double, 3 > &R_c, Vector_t< double, 3 > &E_c, Vector_t< double, 3 > &B_c) const
Return the field value in polar coordinates.
std::string getSymmetry() const
Get a string corresponding to the field map symmetry.
void print(std::ostream &out)
Print summary information about the field map to out.
static std::map< std::string, SectorMagneticFieldMap * > _fields
static const std::string errMsg1
static interpolation::ThreeDGrid * generateGrid(const std::vector< std::vector< double > > field_points, SectorMagneticFieldMap::symmetry sym)
static std::vector< std::vector< double > > readLines(std::string file_name, std::vector< double > units)
static bool comparator(std::vector< double > field_item1, std::vector< double > field_item2)
static const double floatTolerance_m
static interpolation::VectorMap * getInterpolatorPolyPatch(const std::vector< std::vector< double > > field_points, interpolation::ThreeDGrid *grid, SectorMagneticFieldMap::symmetry sym, int poly_order, int smoothing_order)
static interpolation::VectorMap * getInterpolator(const std::vector< std::vector< double > > field_points, interpolation::ThreeDGrid *grid, SectorMagneticFieldMap::symmetry sym)
static const int sortOrder_m[3]
static bool floatGreaterEqual(double in1, double in2)
static interpolation::VectorMap * readMap(std::string file_name, std::vector< double > units, SectorMagneticFieldMap::symmetry sym, int poly_order, int smoothing_order)
Read in the field map.