OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
SectorField.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, Chris Rogers
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  * 1. Redistributions of source code must retain the above copyright notice,
7  * this list of conditions and the following disclaimer.
8  * 2. Redistributions in binary form must reproduce the above copyright notice,
9  * this list of conditions and the following disclaimer in the documentation
10  * and/or other materials provided with the distribution.
11  * 3. Neither the name of STFC nor the names of its contributors may be used to
12  * endorse or promote products derived from this software without specific
13  * prior written permission.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include "Fields/SectorField.h"
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <limits>
33 #include <string>
34 #include <vector>
35 
36 #include "Utilities/LogicalError.h"
37 
38 // note I don't use exactly max() as the bounding box because I don't want to
39 // accidentally wrap around due to some unforeseen floating point precision
40 // issue
41 SectorField::SectorField(const std::string& /*file_name*/)
42  : bbMin_m(3, -std::numeric_limits<double>::max()/10.),
43  bbMax_m(3, std::numeric_limits<double>::max()/10.),
44  polarBBMin_m(3, 0), polarBBMax_m(3, 0) {
45  polarBBMin_m[1] = bbMin_m[1];
46  polarBBMax_m[1] = bbMax_m[1];
47  polarBBMax_m[0] = bbMax_m[0];
48  polarBBMin_m[2] = -2.*M_PI;
49  polarBBMax_m[2] = 2.*M_PI;
50 }
51 
53 
54 void SectorField::convertToPolar(double* position) {
55  double x = std::sqrt(position[0]*position[0]+position[2]*position[2]);
56  double z = std::atan2(position[2], position[0]);
57  position[0] = x;
58  position[2] = z;
59 }
60 
61 void SectorField::convertToPolar(const double* position, double* value) {
62  double x = +value[0]*std::cos(position[2])
63  +value[2]*std::sin(position[2]);
64  double z = +value[2]*std::cos(position[2])
65  -value[0]*std::sin(position[2]);
66  value[0] = x;
67  value[2] = z;
68 }
69 
70 void SectorField::convertToCartesian(double* position) {
71  double x = position[0]*std::cos(position[2]); // r cos(phi)
72  double z = position[0]*std::sin(position[2]); // r sin(phi)
73  position[0] = x;
74  position[2] = z;
75 }
76 
77 void SectorField::convertToCartesian(const double* position, double* value) {
78  double x = +value[0]*std::cos(position[2])
79  -value[2]*std::sin(position[2]);
80  double z = +value[2]*std::cos(position[2])
81  +value[0]*std::sin(position[2]);
82  value[0] = x;
83  value[2] = z;
84 }
85 
87  (double bbMinR, double bbMinY, double bbMinPhi,
88  double bbMaxR, double bbMaxY, double bbMaxPhi,
89  double bbTolR, double bbTolY, double bbTolPhi) {
90  if (bbMinR > bbMaxR) {
91  throw(LogicalError(
92  "SectorField::SetPolarBoundingBox",
93  "Bounding box minimum radius was greater than maximum radius"));
94  }
95  if (bbMinR < 0.) {
96  throw(LogicalError(
97  "SectorField::SetPolarBoundingBox",
98  "Bounding box radius must be positive"
99  ));
100  }
101  if (bbMinY > bbMaxY) {
102  throw(LogicalError(
103  "SectorField::SetPolarBoundingBox",
104  "Bounding box minimum y was greater than maximum y"
105  ));
106  }
107  if (bbMinPhi > bbMaxPhi) {
108  throw(LogicalError(
109  "SectorField::SetPolarBoundingBox",
110  "Bounding box minimum angle was greater than maximum angle"
111  ));
112  }
113  if (bbMinPhi < -2.*M_PI || bbMinPhi > 2.*M_PI ||
114  bbMaxPhi < -2.*M_PI || bbMaxPhi > 2.*M_PI) {
115  throw(LogicalError(
116  "SectorField::SetPolarBoundingBox",
117  "Bounding box angles must be in range -2*M_PI < phi < 2*M_PI"
118  ));
119  }
120 
121  polarBBMin_m[0] = bbMinR-bbTolR;
122  polarBBMin_m[1] = bbMinY-bbTolY;
123  polarBBMin_m[2] = bbMinPhi-bbTolPhi;
124 
125  polarBBMax_m[0] = bbMaxR+bbTolR;
126  polarBBMax_m[1] = bbMaxY+bbTolY;
127  polarBBMax_m[2] = bbMaxPhi+bbTolPhi;
128 
129  // bounding box from corner coordinates
130  std::vector< std::vector<double> > corner_coords(
131  getCorners(bbMinR, bbMinPhi, bbMaxR, bbMaxPhi));
132  bbMin_m[0] =
133  *std::min_element(corner_coords[0].begin(), corner_coords[0].end());
134  bbMax_m[0] =
135  *std::max_element(corner_coords[0].begin(), corner_coords[0].end());
136  bbMin_m[1] = bbMinY;
137  bbMax_m[1] = bbMaxY;
138  bbMin_m[2] =
139  *std::min_element(corner_coords[1].begin(), corner_coords[1].end());
140  bbMax_m[2] =
141  *std::max_element(corner_coords[1].begin(), corner_coords[1].end());
142 
143  // if the magnet crosses an axis, then the corners are no longer at the max
144  // extent
145  if ( (bbMaxPhi > 0.5*M_PI && bbMinPhi < 0.5*M_PI) ||
146  (bbMaxPhi > -1.5*M_PI && bbMinPhi < -1.5*M_PI) ) {
147  bbMax_m[2] = bbMaxR;
148  }
149  if ((bbMaxPhi > M_PI && bbMinPhi < M_PI) ||
150  (bbMaxPhi > -M_PI && bbMinPhi < -M_PI)) {
151  bbMin_m[0] = -bbMaxR;
152  }
153  if ((bbMaxPhi > 1.5*M_PI && bbMinPhi < 1.5*M_PI) ||
154  (bbMaxPhi > -0.5*M_PI && bbMinPhi < -0.5*M_PI)) {
155  bbMin_m[2] = -bbMaxR;
156  }
157  if ((bbMaxPhi > 0.*M_PI && bbMinPhi < 0.*M_PI)) {
158  bbMax_m[0] = bbMaxR;
159  }
160 }
161 
162 std::vector< std::vector<double> > SectorField::getCorners
163  (double bbMinR, double bbMinPhi, double bbMaxR, double bbMaxPhi) {
164  std::vector< std::vector<double> > corner_coords(2);
165  corner_coords[0] = std::vector<double>(4);
166  corner_coords[1] = std::vector<double>(4);
167  // corners in polar coordinates
168  double corner_0[3] = {bbMinR, 0., bbMinPhi};
169  double corner_1[3] = {bbMinR, 0., bbMaxPhi};
170  double corner_2[3] = {bbMaxR, 0., bbMaxPhi};
171  double corner_3[3] = {bbMaxR, 0., bbMinPhi};
172  convertToCartesian(corner_0);
173  convertToCartesian(corner_1);
174  convertToCartesian(corner_2);
175  convertToCartesian(corner_3);
176  // corners in rectangular coordinates (ignore y)
177  corner_coords[0][0] = corner_0[0];
178  corner_coords[0][1] = corner_1[0];
179  corner_coords[0][2] = corner_2[0];
180  corner_coords[0][3] = corner_3[0];
181  corner_coords[1][0] = corner_0[2];
182  corner_coords[1][1] = corner_1[2];
183  corner_coords[1][2] = corner_2[2];
184  corner_coords[1][3] = corner_3[2];
185  return corner_coords;
186 }
187 
188 
189 std::vector<double> SectorField::getPolarBoundingBoxMin() const {
190  return polarBBMin_m;
191 }
192 
193 std::vector<double> SectorField::getPolarBoundingBoxMax() const {
194  return polarBBMax_m;
195 }
196 
197 void SectorField::getFieldDimensions(double &zBegin, double &zEnd,
198  double &rBegin, double &rEnd) const {
199  zBegin = polarBBMin_m[2]*(polarBBMin_m[0]+polarBBMax_m[0])/2.;
200  zEnd = polarBBMax_m[2]*(polarBBMin_m[0]+polarBBMax_m[0])/2.;
201  rBegin = polarBBMin_m[0];
202  rEnd = polarBBMin_m[2];
203 }
204 
205 void SectorField::getFieldDimensions(double &xIni, double &xFinal,
206  double &yIni, double &yFinal,
207  double &zIni, double &zFinal) const {
208  xIni = bbMin_m[0];
209  yIni = bbMin_m[1];
210  zIni = bbMin_m[2];
211  xFinal = bbMax_m[0];
212  yFinal = bbMax_m[1];
213  zFinal = bbMax_m[2];
214 }
Tps< T > cos(const Tps< T > &x)
Cosine.
Definition: TpsMath.h:129
Tps< T > sin(const Tps< T > &x)
Sine.
Definition: TpsMath.h:111
Tps< T > sqrt(const Tps< T > &x)
Square root.
Definition: TpsMath.h:91
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
PETE_TBTree< FnArcTan2, PETE_Scalar< Vektor< T1, Dim > >, typename T2::PETE_Expr_t > atan2(const Vektor< T1, Dim > &l, const PETE_Expr< T2 > &r)
std::vector< double > bbMin_m
Definition: SectorField.h:209
std::vector< std::vector< double > > getCorners(double bbMinR, double bbMinPhi, double bbMaxR, double bbMaxPhi)
std::vector< double > polarBBMin_m
Definition: SectorField.h:213
void getFieldDimensions(double &zBegin, double &zEnd, double &rBegin, double &rEnd) const
virtual std::vector< double > getPolarBoundingBoxMin() const
static void convertToCartesian(double *position)
Definition: SectorField.cpp:70
std::vector< double > polarBBMax_m
Definition: SectorField.h:215
virtual ~SectorField()
Definition: SectorField.cpp:52
std::vector< double > bbMax_m
Definition: SectorField.h:211
SectorField(const std::string &file_name)
Definition: SectorField.cpp:41
virtual std::vector< double > getPolarBoundingBoxMax() const
static void convertToPolar(double *position)
Definition: SectorField.cpp:54
void setPolarBoundingBox(double bbMinR, double bbMinY, double bbMinPhi, double bbMaxR, double bbMaxY, double bbMaxPhi, double bbTolR, double bbTolY, double bbTolPhi)
Definition: SectorField.cpp:87
Logical error exception.
Definition: LogicalError.h:33