OPAL (Object Oriented Parallel Accelerator Library) 2022.1
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
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
41SectorField::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
54void 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
61void 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
70void 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
77void 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
162std::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
189std::vector<double> SectorField::getPolarBoundingBoxMin() const {
190 return polarBBMin_m;
191}
192
193std::vector<double> SectorField::getPolarBoundingBoxMax() const {
194 return polarBBMax_m;
195}
196
197void 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
205void 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}
PartBunchBase< T, Dim >::ConstIterator end(PartBunchBase< T, Dim > const &bunch)
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
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
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